diff --git a/src/point_add/arith/adder.rs b/src/point_add/arith/adder.rs index c9b4b6e9..8335c2a0 100644 --- a/src/point_add/arith/adder.rs +++ b/src/point_add/arith/adder.rs @@ -1,1455 +1,1339 @@ -use super::*; - -pub(crate) fn bit(c: U256, i: usize) -> bool { - - c.bit(i) -} - -pub(crate) fn maj(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - b.cx(w, y); - b.cx(w, x); - b.ccx(x, y, w); -} - -pub(crate) fn uma(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - b.ccx(x, y, w); - b.cx(w, x); - b.cx(x, y); -} - -pub(crate) fn cuccaro_add_fast(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(c_in, acc[0]); - b.cx(a[0], acc[0]); - return; - } - - let carries = b.alloc_qubits(n - 1); - - b.cx(a[0], acc[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc[0], carries[0]); - b.cx(carries[0], a[0]); - - for i in 1..n - 1 { - b.cx(a[i], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 2], acc[n - 1]); - b.cx(a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc[i]); - } - - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_add_fast_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(c_in, acc[0]); - b.cx(a[0], acc[0]); - return; - } - assert!(carries.len() >= n - 1); - - b.cx(a[0], acc[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n - 1 { - b.cx(a[i], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 2], acc[n - 1]); - b.cx(a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc[0]); -} - -/// UMA specialized for a `w` operand bit that is provably |0> at entry (M023). -/// -/// The plain `uma(x, y, w) = ccx(x,y,w); cx(w,x); cx(x,y)` uncomputes a target that, -/// for a zero-entry operand, holds exactly `AND(x, y)` (the carry the matching `maj` -/// ANDed into a fresh |0>). Its Toffoli can therefore be replaced with the shipped -/// measurement-based AND-uncompute idiom (`hmr` + `cz_if`, identical to the one used in -/// `cuccaro_add_fast` above), removing one CCX per site, bit-exactly. `cx(w,x)` is a -/// no-op because `w` is |0> after the measured clear, so only the trailing `cx(x,y)` -/// survives. -pub(crate) fn uma_from_zero(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - let m = b.alloc_bit(); - b.hmr(w, m); - b.cz_if(x, y, m); - b.cx(x, y); -} - -/// inv-MAJ specialized for a `w` operand bit that is provably |0> at entry (M023). -/// -/// Mirror of `uma_from_zero` for the subtract chain: the plain -/// `inv_maj(x, y, w) = ccx(x,y,w); cx(w,x); cx(w,y)` uncomputes `w = AND(x, y)`; both -/// trailing CXs are no-ops once `w` is cleared, so the whole gate reduces to the measured -/// AND-uncompute. -pub(crate) fn inv_maj_from_zero(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - let m = b.alloc_bit(); - b.hmr(w, m); - b.cz_if(x, y, m); -} - -/// `cuccaro_add` variant that routes the UMA uncompute of every provably-|0> operand bit -/// (`zero[i] == true`) through `uma_from_zero`. With an all-false mask this is byte-identical -/// to `cuccaro_add`. -pub(crate) fn cuccaro_add_from_zero( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - zero: &[bool], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - assert_eq!(n, zero.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(c_in, acc[0]); - b.cx(a[0], acc[0]); - return; - } - - maj(b, c_in, acc[0], a[0]); - for i in 1..n - 1 { - maj(b, a[i - 1], acc[i], a[i]); - } - - b.cx(a[n - 2], acc[n - 1]); - b.cx(a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - if zero[i] { - uma_from_zero(b, a[i - 1], acc[i], a[i]); - } else { - uma(b, a[i - 1], acc[i], a[i]); - } - } - if zero[0] { - uma_from_zero(b, c_in, acc[0], a[0]); - } else { - uma(b, c_in, acc[0], a[0]); - } -} - -/// `cuccaro_sub` variant that routes the inv-MAJ uncompute of every provably-|0> operand bit -/// (`zero[i] == true`) through `inv_maj_from_zero`. With an all-false mask this is -/// byte-identical to `cuccaro_sub`. -pub(crate) fn cuccaro_sub_from_zero( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - zero: &[bool], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - assert_eq!(n, zero.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(a[0], acc[0]); - b.cx(c_in, acc[0]); - return; - } - - inv_uma(b, c_in, acc[0], a[0]); - for i in 1..n - 1 { - inv_uma(b, a[i - 1], acc[i], a[i]); - } - - b.cx(a[n - 1], acc[n - 1]); - b.cx(a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - if zero[i] { - inv_maj_from_zero(b, a[i - 1], acc[i], a[i]); - } else { - inv_maj(b, a[i - 1], acc[i], a[i]); - } - } - if zero[0] { - inv_maj_from_zero(b, c_in, acc[0], a[0]); - } else { - inv_maj(b, c_in, acc[0], a[0]); - } -} - -pub(crate) fn cuccaro_add(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - - b.cx(c_in, acc[0]); - b.cx(a[0], acc[0]); - return; - } - - maj(b, c_in, acc[0], a[0]); - for i in 1..n - 1 { - maj(b, a[i - 1], acc[i], a[i]); - } - - b.cx(a[n - 2], acc[n - 1]); - b.cx(a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - uma(b, a[i - 1], acc[i], a[i]); - } - uma(b, c_in, acc[0], a[0]); -} - -pub(crate) fn cuccaro_sub(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - - b.cx(a[0], acc[0]); - b.cx(c_in, acc[0]); - return; - } - - inv_uma(b, c_in, acc[0], a[0]); - for i in 1..n - 1 { - inv_uma(b, a[i - 1], acc[i], a[i]); - } - - b.cx(a[n - 1], acc[n - 1]); - b.cx(a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - inv_maj(b, a[i - 1], acc[i], a[i]); - } - inv_maj(b, c_in, acc[0], a[0]); -} - -pub(crate) fn cuccaro_add_low_to_ext_clean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - - b.cx(c_in, acc_ext[0]); - return; - } - - maj(b, c_in, acc_ext[0], a[0]); - for i in 1..n { - maj(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - uma(b, a[i - 1], acc_ext[i], a[i]); - } - uma(b, c_in, acc_ext[0], a[0]); -} - -pub(crate) fn cuccaro_sub_low_to_ext_clean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - - inv_uma(b, c_in, acc_ext[0], a[0]); - for i in 1..n { - inv_uma(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - inv_maj(b, a[i - 1], acc_ext[i], a[i]); - } - inv_maj(b, c_in, acc_ext[0], a[0]); -} - -pub(crate) fn load_const(b: &mut B, n: usize, c: U256) -> Vec { - let qs = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.x(qs[i]); - } - } - qs -} - -pub(crate) fn unload_const(b: &mut B, qs: &[QubitId], c: U256) { - for i in 0..qs.len() { - if bit(c, i) { - b.x(qs[i]); - } - } - b.free_vec(qs); -} - -pub(crate) fn load_bits(b: &mut B, bits: &[BitId]) -> Vec { - let n = bits.len(); - let qs = b.alloc_qubits(n); - for i in 0..n { - - b.x_if(qs[i], bits[i]); - } - qs -} - -pub(crate) fn unload_bits(b: &mut B, qs: &[QubitId], bits: &[BitId]) { - for i in 0..qs.len() { - b.x_if(qs[i], bits[i]); - } - b.free_vec(qs); -} - -pub(crate) fn ext_reg(b: &mut B, reg: &[QubitId]) -> (Vec, QubitId) { - let ovf = b.alloc_qubit(); - let mut r = reg.to_vec(); - r.push(ovf); - (r, ovf) -} - -pub(crate) fn unext_reg(b: &mut B, ovf: QubitId) { - b.free(ovf); -} - -pub(crate) fn cuccaro_sub_fast(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(a[0], acc[0]); - b.cx(c_in, acc[0]); - return; - } - - let carries = b.alloc_qubits(n - 1); - - b.cx(c_in, acc[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc[0], carries[0]); - b.cx(carries[0], a[0]); - - for i in 1..n - 1 { - b.cx(a[i - 1], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc[n - 1]); - b.cx(a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_add_fast_low_to_ext(b: &mut B, a: &[QubitId], acc_ext: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - - let carries = b.alloc_qubits(n); - - b.cx(a[0], acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n { - b.cx(a[i], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc_ext[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_sub_fast_low_to_ext(b: &mut B, a: &[QubitId], acc_ext: &[QubitId], c_in: QubitId) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - - let carries = b.alloc_qubits(n); - - b.cx(c_in, acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n { - b.cx(a[i - 1], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc_ext[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_add_fast_low_to_ext_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - clean_top: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - let clean_top = clean_top.min(n.saturating_sub(1)); - if clean_top == 0 { - return cuccaro_add_fast_low_to_ext(b, a, acc_ext, c_in); - } - let borrowed = n - clean_top; - let carries = b.alloc_qubits(borrowed); - - b.cx(a[0], acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - maj(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - uma(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc_ext[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_sub_fast_low_to_ext_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - clean_top: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - let clean_top = clean_top.min(n.saturating_sub(1)); - if clean_top == 0 { - return cuccaro_sub_fast_low_to_ext(b, a, acc_ext, c_in); - } - let borrowed = n - clean_top; - let carries = b.alloc_qubits(borrowed); - - b.cx(c_in, acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i - 1], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - inv_uma(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - inv_maj(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc_ext[0]); - - b.free_vec(&carries); -} - -pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - carries: &[QubitId], - clean_top: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - let clean_top = clean_top.min(n.saturating_sub(1)); - if clean_top == 0 { - return cuccaro_add_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, carries); - } - let borrowed = n - clean_top; - assert!(carries.len() >= borrowed); - - b.cx(a[0], acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - maj(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - uma(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc_ext[0]); -} - -pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - carries: &[QubitId], - clean_top: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - let clean_top = clean_top.min(n.saturating_sub(1)); - if clean_top == 0 { - return cuccaro_sub_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, carries); - } - let borrowed = n - clean_top; - assert!(carries.len() >= borrowed); - - b.cx(c_in, acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i - 1], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - inv_uma(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - inv_maj(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc_ext[0]); -} - -pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - assert!(carries.len() >= n); - - b.cx(a[0], acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n { - b.cx(a[i], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(c_in, acc_ext[0]); -} - -pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - b.cx(c_in, acc_ext[0]); - return; - } - assert!(carries.len() >= n); - - b.cx(c_in, acc_ext[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n { - b.cx(a[i - 1], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (1..n).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc_ext[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc_ext[0]); -} - -pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - return; - } - let gate_suffix = square_selfhost_gate_suffix_carries(n); - let borrowed = n - gate_suffix; - assert!(carries.len() >= borrowed); - - b.cx(a[0], acc_ext[0]); - b.ccx(a[0], acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - maj(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - uma(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(a[0], acc_ext[0], m0); -} - -pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - if n == 0 { - return; - } - let gate_suffix = square_selfhost_gate_suffix_carries(n); - let borrowed = n - gate_suffix; - assert!(carries.len() >= borrowed); - - b.ccx(a[0], acc_ext[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..borrowed { - b.cx(a[i - 1], acc_ext[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc_ext[i], carries[i]); - b.cx(carries[i], a[i]); - } - for i in borrowed..n { - inv_uma(b, a[i - 1], acc_ext[i], a[i]); - } - - b.cx(a[n - 1], acc_ext[n]); - - for i in (borrowed..n).rev() { - inv_maj(b, a[i - 1], acc_ext[i], a[i]); - } - for i in (1..borrowed).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc_ext[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc_ext[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(a[0], acc_ext[0], m0); - b.cx(a[0], acc_ext[0]); -} - -pub(crate) fn cuccaro_add_fast_prefix_ctrl_suffix_no_cin( - b: &mut B, - prefix: &[QubitId], - suffix: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - carries: &[QubitId], - scratch: QubitId, -) { - let n = prefix.len(); - assert!(n > 0); - assert!(!suffix.is_empty()); - assert_eq!(acc.len(), n + suffix.len()); - assert!(carries.len() >= n); - - b.cx(prefix[0], acc[0]); - b.ccx(prefix[0], acc[0], carries[0]); - b.cx(carries[0], prefix[0]); - for i in 1..n { - b.cx(prefix[i], acc[i]); - b.cx(prefix[i], prefix[i - 1]); - b.ccx(prefix[i - 1], acc[i], carries[i]); - b.cx(carries[i], prefix[i]); - } - - cuccaro_add_ctrl_lowq(b, suffix, &acc[n..], ctrl, prefix[n - 1], scratch); - - for i in (1..n).rev() { - b.cx(carries[i], prefix[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(prefix[i - 1], acc[i], m); - b.cx(prefix[i], prefix[i - 1]); - b.cx(prefix[i - 1], acc[i]); - } - b.cx(carries[0], prefix[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(prefix[0], acc[0], m0); -} - -pub(crate) fn cuccaro_sub_fast_prefix_ctrl_suffix_no_cin( - b: &mut B, - prefix: &[QubitId], - suffix: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - carries: &[QubitId], - scratch: QubitId, -) { - let n = prefix.len(); - assert!(n > 0); - assert!(!suffix.is_empty()); - assert_eq!(acc.len(), n + suffix.len()); - assert!(carries.len() >= n); - - b.ccx(prefix[0], acc[0], carries[0]); - b.cx(carries[0], prefix[0]); - for i in 1..n { - b.cx(prefix[i - 1], acc[i]); - b.cx(prefix[i], prefix[i - 1]); - b.ccx(prefix[i - 1], acc[i], carries[i]); - b.cx(carries[i], prefix[i]); - } - - cuccaro_sub_ctrl_lowq(b, suffix, &acc[n..], ctrl, prefix[n - 1], scratch); - - for i in (1..n).rev() { - b.cx(carries[i], prefix[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(prefix[i - 1], acc[i], m); - b.cx(prefix[i], prefix[i - 1]); - b.cx(prefix[i], acc[i]); - } - b.cx(carries[0], prefix[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(prefix[0], acc[0], m0); - b.cx(prefix[0], acc[0]); -} - -pub(crate) fn cuccaro_add_fast_windowed_low_to_ext( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - blocks: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - let ext_n = acc_ext.len(); - if ext_n == 0 { - return; - } - let blocks = blocks.max(1).min(ext_n); - if blocks == 1 { - cuccaro_add_fast_low_to_ext(b, a, acc_ext, c_in); - return; - } - - let mut carry = c_in; - let mut lo = 0usize; - let mut couts: Vec<(QubitId, usize, QubitId)> = Vec::new(); - for blk in 0..blocks { - let hi = ((blk + 1) * ext_n) / blocks; - if hi <= lo { - continue; - } - if blk == blocks - 1 || hi == ext_n { - cuccaro_add_fast_low_to_ext(b, &a[lo..n], &acc_ext[lo..hi], carry); - break; - } - let cout = b.alloc_qubit(); - let zero = b.alloc_qubit(); - let mut a_block: Vec = a[lo..hi].to_vec(); - a_block.push(zero); - let mut acc_block: Vec = acc_ext[lo..hi].to_vec(); - acc_block.push(cout); - let c_in = carry; - cuccaro_add_fast(b, &a_block, &acc_block, carry); - b.free(zero); - couts.push((cout, hi, c_in)); - carry = cout; - lo = hi; - } - - for &(cout, p, c_in) in couts.iter().rev() { - cmp_lt_into_fast_with_cin(b, &acc_ext[..p], &a[..p], c_in, cout); - b.free(cout); - } -} - -pub(crate) fn cuccaro_sub_fast_windowed_low_to_ext( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - blocks: usize, -) { - let n = a.len(); - assert_eq!(acc_ext.len(), n + 1); - let ext_n = acc_ext.len(); - if ext_n == 0 { - return; - } - let blocks = blocks.max(1).min(ext_n); - if blocks == 1 { - cuccaro_sub_fast_low_to_ext(b, a, acc_ext, c_in); - return; - } - - let mut borrow = c_in; - let mut lo = 0usize; - let mut bouts: Vec<(QubitId, usize, QubitId)> = Vec::new(); - for blk in 0..blocks { - let hi = ((blk + 1) * ext_n) / blocks; - if hi <= lo { - continue; - } - if blk == blocks - 1 || hi == ext_n { - cuccaro_sub_fast_low_to_ext(b, &a[lo..n], &acc_ext[lo..hi], borrow); - break; - } - let bout = b.alloc_qubit(); - let zero = b.alloc_qubit(); - let mut a_block: Vec = a[lo..hi].to_vec(); - a_block.push(zero); - let mut acc_block: Vec = acc_ext[lo..hi].to_vec(); - acc_block.push(bout); - let b_in = borrow; - cuccaro_sub_fast(b, &a_block, &acc_block, borrow); - b.free(zero); - bouts.push((bout, hi, b_in)); - borrow = bout; - lo = hi; - } - - for &(bout, p, b_in) in bouts.iter().rev() { - for i in 0..p { - b.x(a[i]); - } - cmp_lt_into_fast_with_cin(b, &a[..p], &acc_ext[..p], b_in, bout); - for i in 0..p { - b.x(a[i]); - } - b.free(bout); - } -} - -pub(crate) fn cuccaro_sub_fast_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.cx(a[0], acc[0]); - b.cx(c_in, acc[0]); - return; - } - assert!(carries.len() >= n - 1); - - b.cx(c_in, acc[0]); - b.cx(a[0], c_in); - b.ccx(c_in, acc[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n - 1 { - b.cx(a[i - 1], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc[n - 1]); - b.cx(a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, acc[0], m0); - b.cx(a[0], c_in); - b.cx(a[0], acc[0]); -} - -pub(crate) fn cuccaro_add_fast_borrowed_carries_no_cin( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - - b.cx(a[0], acc[0]); - return; - } - assert!(carries.len() >= n - 1); - - b.cx(a[0], acc[0]); - b.ccx(a[0], acc[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n - 1 { - b.cx(a[i], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 2], acc[n - 1]); - b.cx(a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i - 1], acc[i]); - } - - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(a[0], acc[0], m0); -} - -pub(crate) fn cuccaro_sub_fast_borrowed_carries_no_cin( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - carries: &[QubitId], -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - - b.cx(a[0], acc[0]); - return; - } - assert!(carries.len() >= n - 1); - - b.ccx(a[0], acc[0], carries[0]); - b.cx(carries[0], a[0]); - for i in 1..n - 1 { - b.cx(a[i - 1], acc[i]); - b.cx(a[i], a[i - 1]); - b.ccx(a[i - 1], acc[i], carries[i]); - b.cx(carries[i], a[i]); - } - - b.cx(a[n - 1], acc[n - 1]); - b.cx(a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - b.cx(carries[i], a[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(a[i - 1], acc[i], m); - b.cx(a[i], a[i - 1]); - b.cx(a[i], acc[i]); - } - b.cx(carries[0], a[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(a[0], acc[0], m0); - b.cx(a[0], acc[0]); -} - -pub(crate) fn inv_maj(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - - b.ccx(x, y, w); - b.cx(w, x); - b.cx(w, y); -} - -pub(crate) fn inv_uma(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { - - b.cx(x, y); - b.cx(w, x); - b.ccx(x, y, w); -} - -pub(crate) fn cswap(b: &mut B, ctrl: QubitId, a: QubitId, t: QubitId) { - if a == t { - return; - } - assert!( - ctrl != a && ctrl != t, - "invalid CSWAP with control aliased to swapped wire" - ); - b.cx(t, a); - b.ccx(ctrl, a, t); - b.cx(t, a); -} - -pub(crate) fn mcx3_polar( - b: &mut B, - c1: QubitId, - p1: bool, - c2: QubitId, - p2: bool, - c3: QubitId, - p3: bool, - target: QubitId, - scratch: QubitId, -) { - if !p1 { - b.x(c1); - } - if !p2 { - b.x(c2); - } - if !p3 { - b.x(c3); - } - b.ccx(c1, c2, scratch); - b.ccx(scratch, c3, target); - b.ccx(c1, c2, scratch); - if !p3 { - b.x(c3); - } - if !p2 { - b.x(c2); - } - if !p1 { - b.x(c1); - } -} - -pub(crate) fn ctrl_maj(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { - b.ccx(ctrl, w, y); - b.ccx(ctrl, w, x); - mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); -} - -pub(crate) fn ctrl_uma(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { - mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); - b.ccx(ctrl, w, x); - b.ccx(ctrl, x, y); -} - -pub(crate) fn ctrl_inv_maj(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { - mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); - b.ccx(ctrl, w, x); - b.ccx(ctrl, w, y); -} - -pub(crate) fn ctrl_inv_uma(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { - b.ccx(ctrl, x, y); - b.ccx(ctrl, w, x); - mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); -} - -pub(crate) fn cuccaro_add_ctrl_lowq( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - scratch: QubitId, -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.ccx(ctrl, c_in, acc[0]); - b.ccx(ctrl, a[0], acc[0]); - return; - } - - ctrl_maj(b, ctrl, c_in, acc[0], a[0], scratch); - for i in 1..n - 1 { - ctrl_maj(b, ctrl, a[i - 1], acc[i], a[i], scratch); - } - - b.ccx(ctrl, a[n - 2], acc[n - 1]); - b.ccx(ctrl, a[n - 1], acc[n - 1]); - - for i in (1..n - 1).rev() { - ctrl_uma(b, ctrl, a[i - 1], acc[i], a[i], scratch); - } - ctrl_uma(b, ctrl, c_in, acc[0], a[0], scratch); -} - -pub(crate) fn cuccaro_sub_ctrl_lowq( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - scratch: QubitId, -) { - let n = a.len(); - assert_eq!(n, acc.len()); - if n == 0 { - return; - } - if n == 1 { - b.ccx(ctrl, a[0], acc[0]); - b.ccx(ctrl, c_in, acc[0]); - return; - } - - ctrl_inv_uma(b, ctrl, c_in, acc[0], a[0], scratch); - for i in 1..n - 1 { - ctrl_inv_uma(b, ctrl, a[i - 1], acc[i], a[i], scratch); - } - - b.ccx(ctrl, a[n - 1], acc[n - 1]); - b.ccx(ctrl, a[n - 2], acc[n - 1]); - - for i in (1..n - 1).rev() { - ctrl_inv_maj(b, ctrl, a[i - 1], acc[i], a[i], scratch); - } - ctrl_inv_maj(b, ctrl, c_in, acc[0], a[0], scratch); -} - -pub(crate) fn cuccaro_add_ctrl_vented( - b: &mut B, addend: &[QubitId], acc: &[QubitId], ctrl: QubitId, vent_pool: &[QubitId], -) { - let n = addend.len(); - assert_eq!(n, acc.len()); - if n == 0 { return; } - if n == 1 { b.ccx(ctrl, addend[0], acc[0]); return; } - assert!(vent_pool.len() >= n - 1, "vented body needs n-1 borrowed vent lanes"); - for i in 1..n { b.cx(addend[i], acc[i]); } - for i in (1..n-1).rev() { b.cx(addend[i], addend[i+1]); } - for i in 0..n-1 { - let anc = vent_pool[i]; - b.ccx(acc[i], addend[i], anc); - b.cx(anc, addend[i+1]); - } - for i in (0..n-1).rev() { - b.ccx(ctrl, addend[i+1], acc[i+1]); - let anc = vent_pool[i]; - b.cx(anc, addend[i+1]); - let m = b.alloc_bit(); - b.hmr(anc, m); - b.cz_if(acc[i], addend[i], m); - } - for i in 1..n-1 { b.cx(addend[i], addend[i+1]); } - b.ccx(ctrl, addend[0], acc[0]); - for i in 1..n { b.cx(addend[i], acc[i]); } -} - -pub(crate) fn cuccaro_sub_ctrl_vented( - b: &mut B, subtrahend: &[QubitId], acc: &[QubitId], ctrl: QubitId, vent_pool: &[QubitId], -) { - for &q in acc { b.x(q); } - cuccaro_add_ctrl_vented(b, subtrahend, acc, ctrl, vent_pool); - for &q in acc { b.x(q); } -} - -pub(crate) fn cucc_add_ctrl_lowq(b: &mut B, a: &[QubitId], acc: &[QubitId], ctrl: QubitId) { - let c_in = b.alloc_qubit(); - let scratch = b.alloc_qubit(); - cuccaro_add_ctrl_lowq(b, a, acc, ctrl, c_in, scratch); - b.free(scratch); - b.free(c_in); -} - -pub(crate) fn cucc_sub_ctrl_lowq(b: &mut B, a: &[QubitId], acc: &[QubitId], ctrl: QubitId) { - let c_in = b.alloc_qubit(); - let scratch = b.alloc_qubit(); - cuccaro_sub_ctrl_lowq(b, a, acc, ctrl, c_in, scratch); - b.free(scratch); - b.free(c_in); -} +use super::*; + +pub(crate) fn bit(c: U256, i: usize) -> bool { + + c.bit(i) +} + +pub(crate) fn maj(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { + b.cx(w, y); + b.cx(w, x); + b.ccx(x, y, w); +} + +pub(crate) fn uma(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { + b.ccx(x, y, w); + b.cx(w, x); + b.cx(x, y); +} + +pub(crate) fn cuccaro_add_fast(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.cx(c_in, acc[0]); + b.cx(a[0], acc[0]); + return; + } + + let carries = b.alloc_qubits(n - 1); + + b.cx(a[0], acc[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc[0], carries[0]); + b.cx(carries[0], a[0]); + + for i in 1..n - 1 { + b.cx(a[i], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 2], acc[n - 1]); + b.cx(a[n - 1], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc[i]); + } + + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_add_fast_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + c_in: QubitId, + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.cx(c_in, acc[0]); + b.cx(a[0], acc[0]); + return; + } + assert!(carries.len() >= n - 1); + + b.cx(a[0], acc[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n - 1 { + b.cx(a[i], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 2], acc[n - 1]); + b.cx(a[n - 1], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc[0]); +} + +pub(crate) fn cuccaro_add(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + + b.cx(c_in, acc[0]); + b.cx(a[0], acc[0]); + return; + } + + maj(b, c_in, acc[0], a[0]); + for i in 1..n - 1 { + maj(b, a[i - 1], acc[i], a[i]); + } + + b.cx(a[n - 2], acc[n - 1]); + b.cx(a[n - 1], acc[n - 1]); + + for i in (1..n - 1).rev() { + uma(b, a[i - 1], acc[i], a[i]); + } + uma(b, c_in, acc[0], a[0]); +} + +pub(crate) fn cuccaro_sub(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + + b.cx(a[0], acc[0]); + b.cx(c_in, acc[0]); + return; + } + + inv_uma(b, c_in, acc[0], a[0]); + for i in 1..n - 1 { + inv_uma(b, a[i - 1], acc[i], a[i]); + } + + b.cx(a[n - 1], acc[n - 1]); + b.cx(a[n - 2], acc[n - 1]); + + for i in (1..n - 1).rev() { + inv_maj(b, a[i - 1], acc[i], a[i]); + } + inv_maj(b, c_in, acc[0], a[0]); +} + +pub(crate) fn cuccaro_add_low_to_ext_clean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + + b.cx(c_in, acc_ext[0]); + return; + } + + maj(b, c_in, acc_ext[0], a[0]); + for i in 1..n { + maj(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + uma(b, a[i - 1], acc_ext[i], a[i]); + } + uma(b, c_in, acc_ext[0], a[0]); +} + +pub(crate) fn cuccaro_sub_low_to_ext_clean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + + inv_uma(b, c_in, acc_ext[0], a[0]); + for i in 1..n { + inv_uma(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + inv_maj(b, a[i - 1], acc_ext[i], a[i]); + } + inv_maj(b, c_in, acc_ext[0], a[0]); +} + +pub(crate) fn load_const(b: &mut B, n: usize, c: U256) -> Vec { + let qs = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.x(qs[i]); + } + } + qs +} + +pub(crate) fn unload_const(b: &mut B, qs: &[QubitId], c: U256) { + for i in 0..qs.len() { + if bit(c, i) { + b.x(qs[i]); + } + } + b.free_vec(qs); +} + +pub(crate) fn load_bits(b: &mut B, bits: &[BitId]) -> Vec { + let n = bits.len(); + let qs = b.alloc_qubits(n); + for i in 0..n { + + b.x_if(qs[i], bits[i]); + } + qs +} + +pub(crate) fn unload_bits(b: &mut B, qs: &[QubitId], bits: &[BitId]) { + for i in 0..qs.len() { + b.x_if(qs[i], bits[i]); + } + b.free_vec(qs); +} + +pub(crate) fn ext_reg(b: &mut B, reg: &[QubitId]) -> (Vec, QubitId) { + let ovf = b.alloc_qubit(); + let mut r = reg.to_vec(); + r.push(ovf); + (r, ovf) +} + +pub(crate) fn unext_reg(b: &mut B, ovf: QubitId) { + b.free(ovf); +} + +pub(crate) fn cuccaro_sub_fast(b: &mut B, a: &[QubitId], acc: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.cx(a[0], acc[0]); + b.cx(c_in, acc[0]); + return; + } + + let carries = b.alloc_qubits(n - 1); + + b.cx(c_in, acc[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc[0], carries[0]); + b.cx(carries[0], a[0]); + + for i in 1..n - 1 { + b.cx(a[i - 1], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc[n - 1]); + b.cx(a[n - 2], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_add_fast_low_to_ext(b: &mut B, a: &[QubitId], acc_ext: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + + let carries = b.alloc_qubits(n); + + b.cx(a[0], acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n { + b.cx(a[i], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc_ext[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_sub_fast_low_to_ext(b: &mut B, a: &[QubitId], acc_ext: &[QubitId], c_in: QubitId) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + + let carries = b.alloc_qubits(n); + + b.cx(c_in, acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n { + b.cx(a[i - 1], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc_ext[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_add_fast_low_to_ext_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + clean_top: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + let clean_top = clean_top.min(n.saturating_sub(1)); + if clean_top == 0 { + return cuccaro_add_fast_low_to_ext(b, a, acc_ext, c_in); + } + let borrowed = n - clean_top; + let carries = b.alloc_qubits(borrowed); + + b.cx(a[0], acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + maj(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + uma(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc_ext[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_sub_fast_low_to_ext_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + clean_top: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + let clean_top = clean_top.min(n.saturating_sub(1)); + if clean_top == 0 { + return cuccaro_sub_fast_low_to_ext(b, a, acc_ext, c_in); + } + let borrowed = n - clean_top; + let carries = b.alloc_qubits(borrowed); + + b.cx(c_in, acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i - 1], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + inv_uma(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + inv_maj(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc_ext[0]); + + b.free_vec(&carries); +} + +pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + carries: &[QubitId], + clean_top: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + let clean_top = clean_top.min(n.saturating_sub(1)); + if clean_top == 0 { + return cuccaro_add_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, carries); + } + let borrowed = n - clean_top; + assert!(carries.len() >= borrowed); + + b.cx(a[0], acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + maj(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + uma(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc_ext[0]); +} + +pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + carries: &[QubitId], + clean_top: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + let clean_top = clean_top.min(n.saturating_sub(1)); + if clean_top == 0 { + return cuccaro_sub_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, carries); + } + let borrowed = n - clean_top; + assert!(carries.len() >= borrowed); + + b.cx(c_in, acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i - 1], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + inv_uma(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + inv_maj(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc_ext[0]); +} + +pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + assert!(carries.len() >= n); + + b.cx(a[0], acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n { + b.cx(a[i], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(c_in, acc_ext[0]); +} + +pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + b.cx(c_in, acc_ext[0]); + return; + } + assert!(carries.len() >= n); + + b.cx(c_in, acc_ext[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n { + b.cx(a[i - 1], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (1..n).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc_ext[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc_ext[0]); +} + +pub(crate) fn cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + return; + } + let gate_suffix = square_selfhost_gate_suffix_carries(n); + let borrowed = n - gate_suffix; + assert!(carries.len() >= borrowed); + + b.cx(a[0], acc_ext[0]); + b.ccx(a[0], acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + maj(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + uma(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(a[0], acc_ext[0], m0); +} + +pub(crate) fn cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + if n == 0 { + return; + } + let gate_suffix = square_selfhost_gate_suffix_carries(n); + let borrowed = n - gate_suffix; + assert!(carries.len() >= borrowed); + + b.ccx(a[0], acc_ext[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..borrowed { + b.cx(a[i - 1], acc_ext[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc_ext[i], carries[i]); + b.cx(carries[i], a[i]); + } + for i in borrowed..n { + inv_uma(b, a[i - 1], acc_ext[i], a[i]); + } + + b.cx(a[n - 1], acc_ext[n]); + + for i in (borrowed..n).rev() { + inv_maj(b, a[i - 1], acc_ext[i], a[i]); + } + for i in (1..borrowed).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc_ext[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc_ext[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(a[0], acc_ext[0], m0); + b.cx(a[0], acc_ext[0]); +} + +pub(crate) fn cuccaro_add_fast_prefix_ctrl_suffix_no_cin( + b: &mut B, + prefix: &[QubitId], + suffix: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + carries: &[QubitId], + scratch: QubitId, +) { + let n = prefix.len(); + assert!(n > 0); + assert!(!suffix.is_empty()); + assert_eq!(acc.len(), n + suffix.len()); + assert!(carries.len() >= n); + + b.cx(prefix[0], acc[0]); + b.ccx(prefix[0], acc[0], carries[0]); + b.cx(carries[0], prefix[0]); + for i in 1..n { + b.cx(prefix[i], acc[i]); + b.cx(prefix[i], prefix[i - 1]); + b.ccx(prefix[i - 1], acc[i], carries[i]); + b.cx(carries[i], prefix[i]); + } + + cuccaro_add_ctrl_lowq(b, suffix, &acc[n..], ctrl, prefix[n - 1], scratch); + + for i in (1..n).rev() { + b.cx(carries[i], prefix[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(prefix[i - 1], acc[i], m); + b.cx(prefix[i], prefix[i - 1]); + b.cx(prefix[i - 1], acc[i]); + } + b.cx(carries[0], prefix[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(prefix[0], acc[0], m0); +} + +pub(crate) fn cuccaro_sub_fast_prefix_ctrl_suffix_no_cin( + b: &mut B, + prefix: &[QubitId], + suffix: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + carries: &[QubitId], + scratch: QubitId, +) { + let n = prefix.len(); + assert!(n > 0); + assert!(!suffix.is_empty()); + assert_eq!(acc.len(), n + suffix.len()); + assert!(carries.len() >= n); + + b.ccx(prefix[0], acc[0], carries[0]); + b.cx(carries[0], prefix[0]); + for i in 1..n { + b.cx(prefix[i - 1], acc[i]); + b.cx(prefix[i], prefix[i - 1]); + b.ccx(prefix[i - 1], acc[i], carries[i]); + b.cx(carries[i], prefix[i]); + } + + cuccaro_sub_ctrl_lowq(b, suffix, &acc[n..], ctrl, prefix[n - 1], scratch); + + for i in (1..n).rev() { + b.cx(carries[i], prefix[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(prefix[i - 1], acc[i], m); + b.cx(prefix[i], prefix[i - 1]); + b.cx(prefix[i], acc[i]); + } + b.cx(carries[0], prefix[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(prefix[0], acc[0], m0); + b.cx(prefix[0], acc[0]); +} + +pub(crate) fn cuccaro_add_fast_windowed_low_to_ext( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + blocks: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + let ext_n = acc_ext.len(); + if ext_n == 0 { + return; + } + let blocks = blocks.max(1).min(ext_n); + if blocks == 1 { + cuccaro_add_fast_low_to_ext(b, a, acc_ext, c_in); + return; + } + + let mut carry = c_in; + let mut lo = 0usize; + let mut couts: Vec<(QubitId, usize, QubitId)> = Vec::new(); + for blk in 0..blocks { + let hi = ((blk + 1) * ext_n) / blocks; + if hi <= lo { + continue; + } + if blk == blocks - 1 || hi == ext_n { + cuccaro_add_fast_low_to_ext(b, &a[lo..n], &acc_ext[lo..hi], carry); + break; + } + let cout = b.alloc_qubit(); + let zero = b.alloc_qubit(); + let mut a_block: Vec = a[lo..hi].to_vec(); + a_block.push(zero); + let mut acc_block: Vec = acc_ext[lo..hi].to_vec(); + acc_block.push(cout); + let c_in = carry; + cuccaro_add_fast(b, &a_block, &acc_block, carry); + b.free(zero); + couts.push((cout, hi, c_in)); + carry = cout; + lo = hi; + } + + for &(cout, p, c_in) in couts.iter().rev() { + cmp_lt_into_fast_with_cin(b, &acc_ext[..p], &a[..p], c_in, cout); + b.free(cout); + } +} + +pub(crate) fn cuccaro_sub_fast_windowed_low_to_ext( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + blocks: usize, +) { + let n = a.len(); + assert_eq!(acc_ext.len(), n + 1); + let ext_n = acc_ext.len(); + if ext_n == 0 { + return; + } + let blocks = blocks.max(1).min(ext_n); + if blocks == 1 { + cuccaro_sub_fast_low_to_ext(b, a, acc_ext, c_in); + return; + } + + let mut borrow = c_in; + let mut lo = 0usize; + let mut bouts: Vec<(QubitId, usize, QubitId)> = Vec::new(); + for blk in 0..blocks { + let hi = ((blk + 1) * ext_n) / blocks; + if hi <= lo { + continue; + } + if blk == blocks - 1 || hi == ext_n { + cuccaro_sub_fast_low_to_ext(b, &a[lo..n], &acc_ext[lo..hi], borrow); + break; + } + let bout = b.alloc_qubit(); + let zero = b.alloc_qubit(); + let mut a_block: Vec = a[lo..hi].to_vec(); + a_block.push(zero); + let mut acc_block: Vec = acc_ext[lo..hi].to_vec(); + acc_block.push(bout); + let b_in = borrow; + cuccaro_sub_fast(b, &a_block, &acc_block, borrow); + b.free(zero); + bouts.push((bout, hi, b_in)); + borrow = bout; + lo = hi; + } + + for &(bout, p, b_in) in bouts.iter().rev() { + for i in 0..p { + b.x(a[i]); + } + cmp_lt_into_fast_with_cin(b, &a[..p], &acc_ext[..p], b_in, bout); + for i in 0..p { + b.x(a[i]); + } + b.free(bout); + } +} + +pub(crate) fn cuccaro_sub_fast_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + c_in: QubitId, + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.cx(a[0], acc[0]); + b.cx(c_in, acc[0]); + return; + } + assert!(carries.len() >= n - 1); + + b.cx(c_in, acc[0]); + b.cx(a[0], c_in); + b.ccx(c_in, acc[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n - 1 { + b.cx(a[i - 1], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc[n - 1]); + b.cx(a[n - 2], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, acc[0], m0); + b.cx(a[0], c_in); + b.cx(a[0], acc[0]); +} + +pub(crate) fn cuccaro_add_fast_borrowed_carries_no_cin( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + + b.cx(a[0], acc[0]); + return; + } + assert!(carries.len() >= n - 1); + + b.cx(a[0], acc[0]); + b.ccx(a[0], acc[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n - 1 { + b.cx(a[i], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 2], acc[n - 1]); + b.cx(a[n - 1], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i - 1], acc[i]); + } + + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(a[0], acc[0], m0); +} + +pub(crate) fn cuccaro_sub_fast_borrowed_carries_no_cin( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + carries: &[QubitId], +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + + b.cx(a[0], acc[0]); + return; + } + assert!(carries.len() >= n - 1); + + b.ccx(a[0], acc[0], carries[0]); + b.cx(carries[0], a[0]); + for i in 1..n - 1 { + b.cx(a[i - 1], acc[i]); + b.cx(a[i], a[i - 1]); + b.ccx(a[i - 1], acc[i], carries[i]); + b.cx(carries[i], a[i]); + } + + b.cx(a[n - 1], acc[n - 1]); + b.cx(a[n - 2], acc[n - 1]); + + for i in (1..n - 1).rev() { + b.cx(carries[i], a[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(a[i - 1], acc[i], m); + b.cx(a[i], a[i - 1]); + b.cx(a[i], acc[i]); + } + b.cx(carries[0], a[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(a[0], acc[0], m0); + b.cx(a[0], acc[0]); +} + +pub(crate) fn inv_maj(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { + + b.ccx(x, y, w); + b.cx(w, x); + b.cx(w, y); +} + +pub(crate) fn inv_uma(b: &mut B, x: QubitId, y: QubitId, w: QubitId) { + + b.cx(x, y); + b.cx(w, x); + b.ccx(x, y, w); +} + +pub(crate) fn cswap(b: &mut B, ctrl: QubitId, a: QubitId, t: QubitId) { + if a == t { + return; + } + assert!( + ctrl != a && ctrl != t, + "invalid CSWAP with control aliased to swapped wire" + ); + b.cx(t, a); + b.ccx(ctrl, a, t); + b.cx(t, a); +} + +pub(crate) fn mcx3_polar( + b: &mut B, + c1: QubitId, + p1: bool, + c2: QubitId, + p2: bool, + c3: QubitId, + p3: bool, + target: QubitId, + scratch: QubitId, +) { + if !p1 { + b.x(c1); + } + if !p2 { + b.x(c2); + } + if !p3 { + b.x(c3); + } + b.ccx(c1, c2, scratch); + b.ccx(scratch, c3, target); + b.ccx(c1, c2, scratch); + if !p3 { + b.x(c3); + } + if !p2 { + b.x(c2); + } + if !p1 { + b.x(c1); + } +} + +pub(crate) fn ctrl_maj(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { + b.ccx(ctrl, w, y); + b.ccx(ctrl, w, x); + mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); +} + +pub(crate) fn ctrl_uma(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { + mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); + b.ccx(ctrl, w, x); + b.ccx(ctrl, x, y); +} + +pub(crate) fn ctrl_inv_maj(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { + mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); + b.ccx(ctrl, w, x); + b.ccx(ctrl, w, y); +} + +pub(crate) fn ctrl_inv_uma(b: &mut B, ctrl: QubitId, x: QubitId, y: QubitId, w: QubitId, scratch: QubitId) { + b.ccx(ctrl, x, y); + b.ccx(ctrl, w, x); + mcx3_polar(b, ctrl, true, x, true, y, true, w, scratch); +} + +pub(crate) fn cuccaro_add_ctrl_lowq( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + scratch: QubitId, +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.ccx(ctrl, c_in, acc[0]); + b.ccx(ctrl, a[0], acc[0]); + return; + } + + ctrl_maj(b, ctrl, c_in, acc[0], a[0], scratch); + for i in 1..n - 1 { + ctrl_maj(b, ctrl, a[i - 1], acc[i], a[i], scratch); + } + + b.ccx(ctrl, a[n - 2], acc[n - 1]); + b.ccx(ctrl, a[n - 1], acc[n - 1]); + + for i in (1..n - 1).rev() { + ctrl_uma(b, ctrl, a[i - 1], acc[i], a[i], scratch); + } + ctrl_uma(b, ctrl, c_in, acc[0], a[0], scratch); +} + +pub(crate) fn cuccaro_sub_ctrl_lowq( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + scratch: QubitId, +) { + let n = a.len(); + assert_eq!(n, acc.len()); + if n == 0 { + return; + } + if n == 1 { + b.ccx(ctrl, a[0], acc[0]); + b.ccx(ctrl, c_in, acc[0]); + return; + } + + ctrl_inv_uma(b, ctrl, c_in, acc[0], a[0], scratch); + for i in 1..n - 1 { + ctrl_inv_uma(b, ctrl, a[i - 1], acc[i], a[i], scratch); + } + + b.ccx(ctrl, a[n - 1], acc[n - 1]); + b.ccx(ctrl, a[n - 2], acc[n - 1]); + + for i in (1..n - 1).rev() { + ctrl_inv_maj(b, ctrl, a[i - 1], acc[i], a[i], scratch); + } + ctrl_inv_maj(b, ctrl, c_in, acc[0], a[0], scratch); +} + +pub(crate) fn cuccaro_add_ctrl_vented( + b: &mut B, addend: &[QubitId], acc: &[QubitId], ctrl: QubitId, vent_pool: &[QubitId], +) { + let n = addend.len(); + assert_eq!(n, acc.len()); + if n == 0 { return; } + if n == 1 { b.ccx(ctrl, addend[0], acc[0]); return; } + assert!(vent_pool.len() >= n - 1, "vented body needs n-1 borrowed vent lanes"); + for i in 1..n { b.cx(addend[i], acc[i]); } + for i in (1..n-1).rev() { b.cx(addend[i], addend[i+1]); } + for i in 0..n-1 { + let anc = vent_pool[i]; + b.ccx(acc[i], addend[i], anc); + b.cx(anc, addend[i+1]); + } + for i in (0..n-1).rev() { + b.ccx(ctrl, addend[i+1], acc[i+1]); + let anc = vent_pool[i]; + b.cx(anc, addend[i+1]); + let m = b.alloc_bit(); + b.hmr(anc, m); + b.cz_if(acc[i], addend[i], m); + } + for i in 1..n-1 { b.cx(addend[i], addend[i+1]); } + b.ccx(ctrl, addend[0], acc[0]); + for i in 1..n { b.cx(addend[i], acc[i]); } +} + +pub(crate) fn cuccaro_sub_ctrl_vented( + b: &mut B, subtrahend: &[QubitId], acc: &[QubitId], ctrl: QubitId, vent_pool: &[QubitId], +) { + for &q in acc { b.x(q); } + cuccaro_add_ctrl_vented(b, subtrahend, acc, ctrl, vent_pool); + for &q in acc { b.x(q); } +} + +pub(crate) fn cucc_add_ctrl_lowq(b: &mut B, a: &[QubitId], acc: &[QubitId], ctrl: QubitId) { + let c_in = b.alloc_qubit(); + let scratch = b.alloc_qubit(); + cuccaro_add_ctrl_lowq(b, a, acc, ctrl, c_in, scratch); + b.free(scratch); + b.free(c_in); +} + +pub(crate) fn cucc_sub_ctrl_lowq(b: &mut B, a: &[QubitId], acc: &[QubitId], ctrl: QubitId) { + let c_in = b.alloc_qubit(); + let scratch = b.alloc_qubit(); + cuccaro_sub_ctrl_lowq(b, a, acc, ctrl, c_in, scratch); + b.free(scratch); + b.free(c_in); +} diff --git a/src/point_add/arith/compare.rs b/src/point_add/arith/compare.rs index 74924a38..c523053e 100644 --- a/src/point_add/arith/compare.rs +++ b/src/point_add/arith/compare.rs @@ -1,686 +1,686 @@ -use super::*; - -pub(crate) fn cmp_lt_into_fast(b: &mut B, u: &[QubitId], v: &[QubitId], flag: QubitId) { - - if kal_vent_modadd_enabled() { - cmp_lt_into(b, u, v, flag); - return; - } - let n = u.len(); - assert_eq!(n, v.len()); - let c_in = b.alloc_qubit(); - let carries = b.alloc_qubits(n); - for i in 0..n { - b.x(u[i]); - } - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - } - - b.cx(u[n - 1], flag); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - - for i in 0..n { - b.x(u[i]); - } - b.free_vec(&carries); - b.free(c_in); -} - -pub(crate) fn cmp_lt_into_fast_with_cin( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - flag: QubitId, -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(!u.contains(&c_in)); - assert!(!v.contains(&c_in)); - assert_ne!(c_in, flag); - assert!(!u.contains(&flag)); - assert!(!v.contains(&flag)); - let carries = b.alloc_qubits(n); - for i in 0..n { - b.x(u[i]); - } - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - } - - b.cx(u[n - 1], flag); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - - for i in 0..n { - b.x(u[i]); - } - b.free_vec(&carries); -} - -pub(crate) fn cmp_lt_into_fast_with_cin_borrowed_carries( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - flag: QubitId, - carries: &[QubitId], -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(carries.len() >= n); - for i in 0..n { - b.x(u[i]); - } - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - } - b.cx(u[n - 1], flag); - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - for i in 0..n { - b.x(u[i]); - } -} - -pub(crate) fn ccx_cmp_lt_into_fast(b: &mut B, u: &[QubitId], v: &[QubitId], ctrl: QubitId, target: QubitId) { - if kal_vent_modadd_enabled() { - let flag = b.alloc_qubit(); - cmp_lt_into(b, u, v, flag); - b.ccx(ctrl, flag, target); - cmp_lt_into(b, u, v, flag); - b.free(flag); - return; - } - - let n = u.len(); - assert_eq!(n, v.len()); - let c_in = b.alloc_qubit(); - let carries = b.alloc_qubits(n); - for i in 0..n { - b.x(u[i]); - } - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - } - - b.ccx(ctrl, u[n - 1], target); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - - for i in 0..n { - b.x(u[i]); - } - b.free_vec(&carries); - b.free(c_in); -} - -pub(crate) fn ccx_cmp_lt_into_fast_prefix_targets( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - targets: &[(QubitId, usize)], -) { - if targets.is_empty() { - return; - } - if kal_vent_modadd_enabled() { - for &(target, n) in targets { - ccx_cmp_lt_into_fast(b, &u[..n], &v[..n], ctrl, target); - } - return; - } - - let n = targets.last().expect("non-empty targets").1; - assert_eq!(u.len(), n); - assert_eq!(v.len(), n); - assert!(n > 0); - assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); - assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); - - let c_in = b.alloc_qubit(); - let carries = b.alloc_qubits(n); - for &q in u { - b.x(q); - } - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - let mut next_target = 0; - while next_target < targets.len() && targets[next_target].1 == 1 { - b.ccx(ctrl, u[0], targets[next_target].0); - next_target += 1; - } - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - while next_target < targets.len() && targets[next_target].1 == i + 1 { - b.ccx(ctrl, u[i], targets[next_target].0); - next_target += 1; - } - } - assert_eq!(next_target, targets.len()); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - - for &q in u { - b.x(q); - } - b.free_vec(&carries); - b.free(c_in); -} - -pub(crate) fn cmp_lt_fast_prefix_window_forward( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - carries: &[QubitId], - ctrl: QubitId, - targets: &[(QubitId, usize)], -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(n > 0); - assert!(carries.len() >= n); - assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); - assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - let mut next_target = 0usize; - while next_target < targets.len() && targets[next_target].1 == 1 { - b.ccx(ctrl, u[0], targets[next_target].0); - next_target += 1; - } - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - while next_target < targets.len() && targets[next_target].1 == i + 1 { - b.ccx(ctrl, u[i], targets[next_target].0); - next_target += 1; - } - } - assert_eq!(next_target, targets.len()); -} - -pub(crate) fn cmp_lt_fast_prefix_window_inverse( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - carries: &[QubitId], -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(n > 0); - assert!(carries.len() >= n); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); -} - -pub(crate) fn cmp_lt_phase_conditioned_with_cin( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - ctrl: QubitId, - phase: BitId, -) { - let n = u.len(); - assert_eq!(v.len(), n); - assert!(n > 0); - - b.push_condition(phase); - for &q in u { - b.x(q); - } - let carries = b.alloc_qubits(n); - cmp_lt_fast_prefix_window_forward(b, u, v, c_in, &carries, ctrl, &[]); - b.cz(ctrl, u[n - 1]); - cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, &carries); - b.free_vec(&carries); - for &q in u { - b.x(q); - } - b.pop_condition(); -} - -pub(crate) fn cmp_lt_phase_conditioned_borrowed_carries( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - carries: &[QubitId], - ctrl: QubitId, - phase: BitId, -) { - let n = u.len(); - assert_eq!(v.len(), n); - assert!(n > 0); - assert!(carries.len() >= n); - - b.push_condition(phase); - for &q in u { - b.x(q); - } - cmp_lt_fast_prefix_window_forward(b, u, v, c_in, carries, ctrl, &[]); - b.cz(ctrl, u[n - 1]); - cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, carries); - for &q in u { - b.x(q); - } - b.pop_condition(); -} - -pub(crate) fn cmp_lt_phase_conditioned_with_cin_borrowed_carries( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - carries: &[QubitId], - phase: BitId, -) { - let n = u.len(); - assert_eq!(v.len(), n); - assert!(n > 0); - assert!(carries.len() >= n); - - b.push_condition(phase); - for &q in u { - b.x(q); - } - cmp_lt_fast_prefix_window_forward(b, u, v, c_in, carries, c_in, &[]); - b.cz(u[n - 1], u[n - 1]); - cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, carries); - for &q in u { - b.x(q); - } - b.pop_condition(); -} - -pub(crate) fn cmp_lt_phase_conditioned( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - phase: BitId, -) { - let n = u.len(); - assert_eq!(v.len(), n); - assert!(n > 0); - - let c_in = b.alloc_qubit(); - b.push_condition(phase); - for &q in u { - b.x(q); - } - let carries = b.alloc_qubits(n); - cmp_lt_fast_prefix_window_forward(b, u, v, c_in, &carries, c_in, &[]); - b.cz(u[n - 1], u[n - 1]); - cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, &carries); - b.free_vec(&carries); - for &q in u { - b.x(q); - } - b.pop_condition(); - b.free(c_in); -} - -pub(crate) fn ccx_cmp_lt_into_fast_prefix_targets_split( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - targets: &[(QubitId, usize)], - split: usize, -) { - if targets.is_empty() { - return; - } - let n = targets.last().expect("non-empty targets").1; - assert_eq!(u.len(), n); - assert_eq!(v.len(), n); - assert!(n > 0); - assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); - assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); - if split == 0 || split >= n { - ccx_cmp_lt_into_fast_prefix_targets(b, u, v, ctrl, targets); - return; - } - - if let Some(boundary_idx) = targets.iter().position(|&(_, p)| p == split) { - let boundary = targets[boundary_idx].0; - let targets_lo = targets[..=boundary_idx].to_vec(); - let targets_hi_rel = targets[boundary_idx + 1..] - .iter() - .map(|&(target, p)| (target, p - split)) - .collect::>(); - - for &q in u { - b.x(q); - } - - let hi_len = n - split; - let carries_hi = b.alloc_qubits(hi_len); - cmp_lt_fast_prefix_window_forward( - b, - &u[split..n], - &v[split..n], - boundary, - &carries_hi, - ctrl, - &targets_hi_rel, - ); - cmp_lt_fast_prefix_window_inverse(b, &u[split..n], &v[split..n], boundary, &carries_hi); - b.free_vec(&carries_hi); - - let c_in_lo = b.alloc_qubit(); - let carries_lo = b.alloc_qubits(split); - cmp_lt_fast_prefix_window_forward( - b, - &u[..split], - &v[..split], - c_in_lo, - &carries_lo, - ctrl, - &targets_lo, - ); - cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_lo, &carries_lo); - b.free_vec(&carries_lo); - b.free(c_in_lo); - - for &q in u { - b.x(q); - } - return; - } - - let (targets_lo, targets_hi): (Vec<_>, Vec<_>) = - targets.iter().copied().partition(|&(_, p)| p <= split); - let targets_hi_rel = targets_hi - .iter() - .map(|&(target, p)| (target, p - split)) - .collect::>(); - - for &q in u { - b.x(q); - } - - let boundary = b.alloc_qubit(); - let c_in_lo = b.alloc_qubit(); - let carries_lo = b.alloc_qubits(split); - cmp_lt_fast_prefix_window_forward( - b, - &u[..split], - &v[..split], - c_in_lo, - &carries_lo, - ctrl, - &targets_lo, - ); - b.cx(u[split - 1], boundary); - cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_lo, &carries_lo); - b.free_vec(&carries_lo); - b.free(c_in_lo); - - let hi_len = n - split; - let carries_hi = b.alloc_qubits(hi_len); - cmp_lt_fast_prefix_window_forward( - b, - &u[split..n], - &v[split..n], - boundary, - &carries_hi, - ctrl, - &targets_hi_rel, - ); - cmp_lt_fast_prefix_window_inverse(b, &u[split..n], &v[split..n], boundary, &carries_hi); - b.free_vec(&carries_hi); - - let c_in_clear = b.alloc_qubit(); - let carries_clear = b.alloc_qubits(split); - cmp_lt_fast_prefix_window_forward( - b, - &u[..split], - &v[..split], - c_in_clear, - &carries_clear, - ctrl, - &[], - ); - b.cx(u[split - 1], boundary); - cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_clear, &carries_clear); - b.free_vec(&carries_clear); - b.free(c_in_clear); - b.free(boundary); - - for &q in u { - b.x(q); - } -} - -pub(crate) fn cmp_lt_into_with_cin_slow( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - c_in: QubitId, - flag: QubitId, -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(n > 0); - for i in 0..n { - b.x(u[i]); - } - maj(b, c_in, v[0], u[0]); - for i in 1..n { - maj(b, u[i - 1], v[i], u[i]); - } - b.cx(u[n - 1], flag); - for i in (1..n).rev() { - inv_maj(b, u[i - 1], v[i], u[i]); - } - inv_maj(b, c_in, v[0], u[0]); - for i in 0..n { - b.x(u[i]); - } -} - -pub(crate) fn cmp_lt_into(b: &mut B, u: &[QubitId], v: &[QubitId], flag: QubitId) { - let n = u.len(); - assert_eq!(n, v.len()); - - let c_in = b.alloc_qubit(); - - for i in 0..n { - b.x(u[i]); - } - - maj(b, c_in, v[0], u[0]); - for i in 1..n { - maj(b, u[i - 1], v[i], u[i]); - } - - b.cx(u[n - 1], flag); - - for i in (1..n).rev() { - inv_maj(b, u[i - 1], v[i], u[i]); - } - inv_maj(b, c_in, v[0], u[0]); - - for i in 0..n { - b.x(u[i]); - } - - b.free(c_in); -} - -pub(crate) fn ccx_cmp_lt_into_fast_borrowed_carries( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - target: QubitId, - c_in: QubitId, - carries: &[QubitId], -) { - let n = u.len(); - assert_eq!(n, v.len()); - assert!(n > 0); - assert!(carries.len() >= n); - - for i in 0..n { - b.x(u[i]); - } - - b.cx(u[0], v[0]); - b.cx(u[0], c_in); - b.ccx(c_in, v[0], carries[0]); - b.cx(carries[0], u[0]); - for i in 1..n { - b.cx(u[i], v[i]); - b.cx(u[i], u[i - 1]); - b.ccx(u[i - 1], v[i], carries[i]); - b.cx(carries[i], u[i]); - } - - b.ccx(ctrl, u[n - 1], target); - - for i in (1..n).rev() { - b.cx(carries[i], u[i]); - let m = b.alloc_bit(); - b.hmr(carries[i], m); - b.cz_if(u[i - 1], v[i], m); - b.cx(u[i], u[i - 1]); - b.cx(u[i], v[i]); - } - b.cx(carries[0], u[0]); - let m0 = b.alloc_bit(); - b.hmr(carries[0], m0); - b.cz_if(c_in, v[0], m0); - b.cx(u[0], c_in); - b.cx(u[0], v[0]); - - for i in 0..n { - b.x(u[i]); - } -} +use super::*; + +pub(crate) fn cmp_lt_into_fast(b: &mut B, u: &[QubitId], v: &[QubitId], flag: QubitId) { + + if kal_vent_modadd_enabled() { + cmp_lt_into(b, u, v, flag); + return; + } + let n = u.len(); + assert_eq!(n, v.len()); + let c_in = b.alloc_qubit(); + let carries = b.alloc_qubits(n); + for i in 0..n { + b.x(u[i]); + } + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + } + + b.cx(u[n - 1], flag); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + + for i in 0..n { + b.x(u[i]); + } + b.free_vec(&carries); + b.free(c_in); +} + +pub(crate) fn cmp_lt_into_fast_with_cin( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + flag: QubitId, +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(!u.contains(&c_in)); + assert!(!v.contains(&c_in)); + assert_ne!(c_in, flag); + assert!(!u.contains(&flag)); + assert!(!v.contains(&flag)); + let carries = b.alloc_qubits(n); + for i in 0..n { + b.x(u[i]); + } + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + } + + b.cx(u[n - 1], flag); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + + for i in 0..n { + b.x(u[i]); + } + b.free_vec(&carries); +} + +pub(crate) fn cmp_lt_into_fast_with_cin_borrowed_carries( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + flag: QubitId, + carries: &[QubitId], +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(carries.len() >= n); + for i in 0..n { + b.x(u[i]); + } + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + } + b.cx(u[n - 1], flag); + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + for i in 0..n { + b.x(u[i]); + } +} + +pub(crate) fn ccx_cmp_lt_into_fast(b: &mut B, u: &[QubitId], v: &[QubitId], ctrl: QubitId, target: QubitId) { + if kal_vent_modadd_enabled() { + let flag = b.alloc_qubit(); + cmp_lt_into(b, u, v, flag); + b.ccx(ctrl, flag, target); + cmp_lt_into(b, u, v, flag); + b.free(flag); + return; + } + + let n = u.len(); + assert_eq!(n, v.len()); + let c_in = b.alloc_qubit(); + let carries = b.alloc_qubits(n); + for i in 0..n { + b.x(u[i]); + } + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + } + + b.ccx(ctrl, u[n - 1], target); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + + for i in 0..n { + b.x(u[i]); + } + b.free_vec(&carries); + b.free(c_in); +} + +pub(crate) fn ccx_cmp_lt_into_fast_prefix_targets( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + targets: &[(QubitId, usize)], +) { + if targets.is_empty() { + return; + } + if kal_vent_modadd_enabled() { + for &(target, n) in targets { + ccx_cmp_lt_into_fast(b, &u[..n], &v[..n], ctrl, target); + } + return; + } + + let n = targets.last().expect("non-empty targets").1; + assert_eq!(u.len(), n); + assert_eq!(v.len(), n); + assert!(n > 0); + assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); + assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); + + let c_in = b.alloc_qubit(); + let carries = b.alloc_qubits(n); + for &q in u { + b.x(q); + } + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + let mut next_target = 0; + while next_target < targets.len() && targets[next_target].1 == 1 { + b.ccx(ctrl, u[0], targets[next_target].0); + next_target += 1; + } + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + while next_target < targets.len() && targets[next_target].1 == i + 1 { + b.ccx(ctrl, u[i], targets[next_target].0); + next_target += 1; + } + } + assert_eq!(next_target, targets.len()); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + + for &q in u { + b.x(q); + } + b.free_vec(&carries); + b.free(c_in); +} + +pub(crate) fn cmp_lt_fast_prefix_window_forward( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + carries: &[QubitId], + ctrl: QubitId, + targets: &[(QubitId, usize)], +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(n > 0); + assert!(carries.len() >= n); + assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); + assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + let mut next_target = 0usize; + while next_target < targets.len() && targets[next_target].1 == 1 { + b.ccx(ctrl, u[0], targets[next_target].0); + next_target += 1; + } + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + while next_target < targets.len() && targets[next_target].1 == i + 1 { + b.ccx(ctrl, u[i], targets[next_target].0); + next_target += 1; + } + } + assert_eq!(next_target, targets.len()); +} + +pub(crate) fn cmp_lt_fast_prefix_window_inverse( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + carries: &[QubitId], +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(n > 0); + assert!(carries.len() >= n); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); +} + +pub(crate) fn cmp_lt_phase_conditioned_with_cin( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + ctrl: QubitId, + phase: BitId, +) { + let n = u.len(); + assert_eq!(v.len(), n); + assert!(n > 0); + + b.push_condition(phase); + for &q in u { + b.x(q); + } + let carries = b.alloc_qubits(n); + cmp_lt_fast_prefix_window_forward(b, u, v, c_in, &carries, ctrl, &[]); + b.cz(ctrl, u[n - 1]); + cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, &carries); + b.free_vec(&carries); + for &q in u { + b.x(q); + } + b.pop_condition(); +} + +pub(crate) fn cmp_lt_phase_conditioned_borrowed_carries( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + carries: &[QubitId], + ctrl: QubitId, + phase: BitId, +) { + let n = u.len(); + assert_eq!(v.len(), n); + assert!(n > 0); + assert!(carries.len() >= n); + + b.push_condition(phase); + for &q in u { + b.x(q); + } + cmp_lt_fast_prefix_window_forward(b, u, v, c_in, carries, ctrl, &[]); + b.cz(ctrl, u[n - 1]); + cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, carries); + for &q in u { + b.x(q); + } + b.pop_condition(); +} + +pub(crate) fn cmp_lt_phase_conditioned_with_cin_borrowed_carries( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + carries: &[QubitId], + phase: BitId, +) { + let n = u.len(); + assert_eq!(v.len(), n); + assert!(n > 0); + assert!(carries.len() >= n); + + b.push_condition(phase); + for &q in u { + b.x(q); + } + cmp_lt_fast_prefix_window_forward(b, u, v, c_in, carries, c_in, &[]); + b.cz(u[n - 1], u[n - 1]); + cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, carries); + for &q in u { + b.x(q); + } + b.pop_condition(); +} + +pub(crate) fn cmp_lt_phase_conditioned( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + phase: BitId, +) { + let n = u.len(); + assert_eq!(v.len(), n); + assert!(n > 0); + + let c_in = b.alloc_qubit(); + b.push_condition(phase); + for &q in u { + b.x(q); + } + let carries = b.alloc_qubits(n); + cmp_lt_fast_prefix_window_forward(b, u, v, c_in, &carries, c_in, &[]); + b.cz(u[n - 1], u[n - 1]); + cmp_lt_fast_prefix_window_inverse(b, u, v, c_in, &carries); + b.free_vec(&carries); + for &q in u { + b.x(q); + } + b.pop_condition(); + b.free(c_in); +} + +pub(crate) fn ccx_cmp_lt_into_fast_prefix_targets_split( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + targets: &[(QubitId, usize)], + split: usize, +) { + if targets.is_empty() { + return; + } + let n = targets.last().expect("non-empty targets").1; + assert_eq!(u.len(), n); + assert_eq!(v.len(), n); + assert!(n > 0); + assert!(targets.iter().all(|&(_, p)| (1..=n).contains(&p))); + assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); + if split == 0 || split >= n { + ccx_cmp_lt_into_fast_prefix_targets(b, u, v, ctrl, targets); + return; + } + + if let Some(boundary_idx) = targets.iter().position(|&(_, p)| p == split) { + let boundary = targets[boundary_idx].0; + let targets_lo = targets[..=boundary_idx].to_vec(); + let targets_hi_rel = targets[boundary_idx + 1..] + .iter() + .map(|&(target, p)| (target, p - split)) + .collect::>(); + + for &q in u { + b.x(q); + } + + let hi_len = n - split; + let carries_hi = b.alloc_qubits(hi_len); + cmp_lt_fast_prefix_window_forward( + b, + &u[split..n], + &v[split..n], + boundary, + &carries_hi, + ctrl, + &targets_hi_rel, + ); + cmp_lt_fast_prefix_window_inverse(b, &u[split..n], &v[split..n], boundary, &carries_hi); + b.free_vec(&carries_hi); + + let c_in_lo = b.alloc_qubit(); + let carries_lo = b.alloc_qubits(split); + cmp_lt_fast_prefix_window_forward( + b, + &u[..split], + &v[..split], + c_in_lo, + &carries_lo, + ctrl, + &targets_lo, + ); + cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_lo, &carries_lo); + b.free_vec(&carries_lo); + b.free(c_in_lo); + + for &q in u { + b.x(q); + } + return; + } + + let (targets_lo, targets_hi): (Vec<_>, Vec<_>) = + targets.iter().copied().partition(|&(_, p)| p <= split); + let targets_hi_rel = targets_hi + .iter() + .map(|&(target, p)| (target, p - split)) + .collect::>(); + + for &q in u { + b.x(q); + } + + let boundary = b.alloc_qubit(); + let c_in_lo = b.alloc_qubit(); + let carries_lo = b.alloc_qubits(split); + cmp_lt_fast_prefix_window_forward( + b, + &u[..split], + &v[..split], + c_in_lo, + &carries_lo, + ctrl, + &targets_lo, + ); + b.cx(u[split - 1], boundary); + cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_lo, &carries_lo); + b.free_vec(&carries_lo); + b.free(c_in_lo); + + let hi_len = n - split; + let carries_hi = b.alloc_qubits(hi_len); + cmp_lt_fast_prefix_window_forward( + b, + &u[split..n], + &v[split..n], + boundary, + &carries_hi, + ctrl, + &targets_hi_rel, + ); + cmp_lt_fast_prefix_window_inverse(b, &u[split..n], &v[split..n], boundary, &carries_hi); + b.free_vec(&carries_hi); + + let c_in_clear = b.alloc_qubit(); + let carries_clear = b.alloc_qubits(split); + cmp_lt_fast_prefix_window_forward( + b, + &u[..split], + &v[..split], + c_in_clear, + &carries_clear, + ctrl, + &[], + ); + b.cx(u[split - 1], boundary); + cmp_lt_fast_prefix_window_inverse(b, &u[..split], &v[..split], c_in_clear, &carries_clear); + b.free_vec(&carries_clear); + b.free(c_in_clear); + b.free(boundary); + + for &q in u { + b.x(q); + } +} + +pub(crate) fn cmp_lt_into_with_cin_slow( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + c_in: QubitId, + flag: QubitId, +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(n > 0); + for i in 0..n { + b.x(u[i]); + } + maj(b, c_in, v[0], u[0]); + for i in 1..n { + maj(b, u[i - 1], v[i], u[i]); + } + b.cx(u[n - 1], flag); + for i in (1..n).rev() { + inv_maj(b, u[i - 1], v[i], u[i]); + } + inv_maj(b, c_in, v[0], u[0]); + for i in 0..n { + b.x(u[i]); + } +} + +pub(crate) fn cmp_lt_into(b: &mut B, u: &[QubitId], v: &[QubitId], flag: QubitId) { + let n = u.len(); + assert_eq!(n, v.len()); + + let c_in = b.alloc_qubit(); + + for i in 0..n { + b.x(u[i]); + } + + maj(b, c_in, v[0], u[0]); + for i in 1..n { + maj(b, u[i - 1], v[i], u[i]); + } + + b.cx(u[n - 1], flag); + + for i in (1..n).rev() { + inv_maj(b, u[i - 1], v[i], u[i]); + } + inv_maj(b, c_in, v[0], u[0]); + + for i in 0..n { + b.x(u[i]); + } + + b.free(c_in); +} + +pub(crate) fn ccx_cmp_lt_into_fast_borrowed_carries( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + target: QubitId, + c_in: QubitId, + carries: &[QubitId], +) { + let n = u.len(); + assert_eq!(n, v.len()); + assert!(n > 0); + assert!(carries.len() >= n); + + for i in 0..n { + b.x(u[i]); + } + + b.cx(u[0], v[0]); + b.cx(u[0], c_in); + b.ccx(c_in, v[0], carries[0]); + b.cx(carries[0], u[0]); + for i in 1..n { + b.cx(u[i], v[i]); + b.cx(u[i], u[i - 1]); + b.ccx(u[i - 1], v[i], carries[i]); + b.cx(carries[i], u[i]); + } + + b.ccx(ctrl, u[n - 1], target); + + for i in (1..n).rev() { + b.cx(carries[i], u[i]); + let m = b.alloc_bit(); + b.hmr(carries[i], m); + b.cz_if(u[i - 1], v[i], m); + b.cx(u[i], u[i - 1]); + b.cx(u[i], v[i]); + } + b.cx(carries[0], u[0]); + let m0 = b.alloc_bit(); + b.hmr(carries[0], m0); + b.cz_if(c_in, v[0], m0); + b.cx(u[0], c_in); + b.cx(u[0], v[0]); + + for i in 0..n { + b.x(u[i]); + } +} diff --git a/src/point_add/arith/const_arith.rs b/src/point_add/arith/const_arith.rs index edff778a..0c04a59f 100644 --- a/src/point_add/arith/const_arith.rs +++ b/src/point_add/arith/const_arith.rs @@ -1,3471 +1,3471 @@ -use super::*; - -#[inline] -fn maj1_inputs_distinct(a: QubitId, k: QubitId, carry: QubitId, target: QubitId) -> bool { - a != k && a != carry && a != target && k != carry && k != target && carry != target -} - -#[inline] -fn fold_maj1_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_MAJ1").ok().as_deref() == Some("1") -} - -fn emit_fold_maj1(b: &mut B, a: QubitId, k: QubitId, carry: QubitId, target: QubitId) { - debug_assert!(maj1_inputs_distinct(a, k, carry, target)); - b.cx(carry, target); - b.cx(carry, a); - b.cx(carry, k); - b.ccx(a, k, target); - b.cx(carry, k); - b.cx(carry, a); -} - -fn emit_fold_majority( - b: &mut B, - a: QubitId, - k: QubitId, - carry: QubitId, - target: QubitId, - maj2: bool, -) { - if fold_maj1_enabled() && maj1_inputs_distinct(a, k, carry, target) { - emit_fold_maj1(b, a, k, carry, target); - } else if maj2 { - b.ccx(a, carry, target); - b.cx(a, carry); - b.ccx(k, carry, target); - b.cx(a, carry); - } else { - b.ccx(a, carry, target); - b.ccx(k, a, target); - b.ccx(k, carry, target); - } -} - -pub(crate) fn csub_nbit_const(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - - let n = acc.len(); - let a = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - sub_nbit_qq(b, &a, acc); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - b.free_vec(&a); -} - -pub(crate) fn cadd_nbit_const(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - - let n = acc.len(); - let a = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - add_nbit_qq(b, &a, acc); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - b.free_vec(&a); -} - -pub(crate) fn csub_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - let n = acc.len(); - let a = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - sub_nbit_qq_fast(b, &a, acc); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - b.free_vec(&a); -} - -pub(crate) fn csub_nbit_const_direct_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - let n = acc.len(); - if n == 0 { - return; - } - if n == 1 { - if bit(c, 0) { - b.cx(ctrl, acc[0]); - } - return; - } - - let borrows = b.alloc_qubits(n - 1); - - for i in 0..n - 1 { - let target = borrows[i]; - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if bit(c, i) { - b.x(acc[i]); - if let Some(bi) = borrow_in { - emit_fold_majority(b, acc[i], ctrl, bi, target, false); - } else { - b.ccx(acc[i], ctrl, target); - } - b.x(acc[i]); - } else if let Some(bi) = borrow_in { - b.x(acc[i]); - b.ccx(acc[i], bi, target); - b.x(acc[i]); - } - } - - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, acc[i]); - } - if i > 0 { - b.cx(borrows[i - 1], acc[i]); - } - } - - for i in (0..n - 1).rev() { - let m = b.alloc_bit(); - b.hmr(borrows[i], m); - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if bit(c, i) { - if let Some(bi) = borrow_in { - b.cz_if(acc[i], ctrl, m); - b.cz_if(acc[i], bi, m); - b.cz_if(ctrl, bi, m); - } else { - b.cz_if(acc[i], ctrl, m); - } - } else if let Some(bi) = borrow_in { - b.cz_if(acc[i], bi, m); - } - } - - b.free_vec(&borrows); -} - -pub(crate) fn cadd_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - let n = acc.len(); - let a = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - add_nbit_qq_fast(b, &a, acc); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, a[i]); - } - } - b.free_vec(&a); -} - -pub(crate) fn cadd_nbit_const_direct_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { - let n = acc.len(); - if n == 0 { - return; - } - if n == 1 { - if bit(c, 0) { - b.cx(ctrl, acc[0]); - } - return; - } - - let carries = b.alloc_qubits(n - 1); - - for i in 0..n - 1 { - let target = carries[i]; - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if bit(c, i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], ctrl, ci, target, false); - } else { - b.ccx(acc[i], ctrl, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } - - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, acc[i]); - } - if i > 0 { - b.cx(carries[i - 1], acc[i]); - } - } - - for i in (0..n - 1).rev() { - let m = b.alloc_bit(); - b.hmr(carries[i], m); - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if bit(c, i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - b.cz_if(acc[i], ctrl, m); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - b.cz_if(ctrl, ci, m); - } else { - b.cz_if(acc[i], ctrl, m); - b.x(acc[i]); - } - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - } - } - - b.free_vec(&carries); -} - -pub(crate) fn add_nbit_const_extcarry_clean(b: &mut B, acc_ext: &[QubitId], c: U256) { - add_nbit_const_extcarry_clean_with_cin(b, acc_ext, c, None); -} - -pub(crate) fn add_nbit_const_extcarry_clean_with_cin( - b: &mut B, - acc_ext: &[QubitId], - c: U256, - borrow_cin: Option, -) { - let ext = acc_ext.len(); - debug_assert!(ext >= 1); - let n = ext - 1; - let ca = load_const(b, n, c); - let (c_in, fresh) = match borrow_cin { - Some(q) => (q, false), - None => (b.alloc_qubit(), true), - }; - cuccaro_add_low_to_ext_clean(b, &ca, acc_ext, c_in); - if fresh { - b.free(c_in); - } - unload_const(b, &ca, c); -} - -pub(crate) fn sub_nbit_const_extcarry_clean(b: &mut B, acc_ext: &[QubitId], c: U256) { - let ext = acc_ext.len(); - debug_assert!(ext >= 1); - let n = ext - 1; - let ca = load_const(b, n, c); - let c_in = b.alloc_qubit(); - cuccaro_sub_low_to_ext_clean(b, &ca, acc_ext, c_in); - b.free(c_in); - unload_const(b, &ca, c); -} - -pub(crate) fn cadd_nbit_const_extcarry_clean( - b: &mut B, - acc_ext: &[QubitId], - c: U256, - ctrl: QubitId, -) { - let ext = acc_ext.len(); - debug_assert!(ext >= 1); - let n = ext - 1; - let ca = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, ca[i]); - } - } - let c_in = b.alloc_qubit(); - cuccaro_add_low_to_ext_clean(b, &ca, acc_ext, c_in); - b.free(c_in); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, ca[i]); - } - } - b.free_vec(&ca); -} - -pub(crate) fn csub_nbit_const_extcarry_clean( - b: &mut B, - acc_ext: &[QubitId], - c: U256, - ctrl: QubitId, -) { - csub_nbit_const_extcarry_clean_with_cin(b, acc_ext, c, ctrl, None); -} - -pub(crate) fn csub_nbit_const_extcarry_clean_with_cin( - b: &mut B, - acc_ext: &[QubitId], - c: U256, - ctrl: QubitId, - borrow_cin: Option, -) { - let ext = acc_ext.len(); - debug_assert!(ext >= 1); - let n = ext - 1; - let ca = b.alloc_qubits(n); - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, ca[i]); - } - } - let (c_in, fresh) = match borrow_cin { - Some(q) => (q, false), - None => (b.alloc_qubit(), true), - }; - cuccaro_sub_low_to_ext_clean(b, &ca, acc_ext, c_in); - if fresh { - b.free(c_in); - } - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, ca[i]); - } - } - b.free_vec(&ca); -} - -pub(crate) fn add_nbit_const_direct_uncontrolled_fast(b: &mut B, acc: &[QubitId], c: U256) { - let ctrl = b.alloc_qubit(); - b.x(ctrl); - cadd_nbit_const_direct_fast(b, acc, c, ctrl); - b.x(ctrl); - b.free(ctrl); -} - -pub(crate) fn sub_nbit_const_direct_uncontrolled_fast(b: &mut B, acc: &[QubitId], c: U256) { - let ctrl = b.alloc_qubit(); - b.x(ctrl); - csub_nbit_const_direct_fast(b, acc, c, ctrl); - b.x(ctrl); - b.free(ctrl); -} - -pub(crate) fn add_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256) { - if secp_direct_const_arith_enabled() { - add_nbit_const_direct_uncontrolled_fast(b, acc, c); - return; - } - let n = acc.len(); - let a = load_const(b, n, c); - add_nbit_qq_fast(b, &a, acc); - unload_const(b, &a, c); -} - -pub(crate) fn sub_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256) { - if secp_direct_const_arith_enabled() { - sub_nbit_const_direct_uncontrolled_fast(b, acc, c); - return; - } - let n = acc.len(); - let a = load_const(b, n, c); - sub_nbit_qq_fast(b, &a, acc); - unload_const(b, &a, c); -} - -pub(crate) fn highest_set_bit(c: U256) -> usize { - let mut hi = 0usize; - for i in 0..256 { - if bit(c, i) { - hi = i; - } - } - hi -} - -pub(crate) fn double_carry_trunc_window() -> Option { - std::env::var("KAL_DOUBLE_CARRY_TRUNC_W") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&w| w > 0) -} - -pub(crate) fn fold_carry_trunc_window() -> Option { - std::env::var("KAL_FOLD_CARRY_TRUNC_W") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&w| w > 0) -} - -pub(crate) fn perpos_maj2_enabled() -> bool { - std::env::var("DIALOG_GCD_PERPOS_MAJ2").ok().as_deref() == Some("1") -} - -pub(crate) fn fold_maj2_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_MAJ2").ok().as_deref() == Some("1") -} - -fn borrowed_const_fold_carries( - b: &mut B, - need: usize, - borrowed: &[QubitId], -) -> (Vec, Vec) { - let borrowed_len = borrowed.len().min(need); - let owned = b.alloc_qubits(need - borrowed_len); - let mut carries = Vec::with_capacity(need); - carries.extend_from_slice(&borrowed[..borrowed_len]); - carries.extend_from_slice(&owned); - (carries, owned) -} - -pub(crate) fn cadd_nbit_const_direct_trunc_fast( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, -) { - cadd_nbit_const_direct_trunc_fast_borrowed_carries(b, acc, c, ctrl, window, &[]); -} - -pub(crate) fn cadd_nbit_const_direct_trunc_fast_borrowed_carries( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - borrowed_carries: &[QubitId], -) { - let n = acc.len(); - if n == 0 { - return; - } - if n == 1 { - if bit(c, 0) { - b.cx(ctrl, acc[0]); - } - return; - } - - let hi = highest_set_bit(c); - let last = core::cmp::min(n - 2, hi.saturating_add(window)); - let maj2 = fold_maj2_enabled(); - let (carries, owned_carries) = borrowed_const_fold_carries(b, last + 1, borrowed_carries); - - for i in 0..=last { - let target = carries[i]; - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if bit(c, i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], ctrl, ci, target, maj2); - } else { - b.ccx(acc[i], ctrl, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } - - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, acc[i]); - } - if i > 0 && i - 1 <= last { - b.cx(carries[i - 1], acc[i]); - } - } - - for i in (0..=last).rev() { - let m = b.alloc_bit(); - b.hmr(carries[i], m); - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if bit(c, i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - b.cz_if(acc[i], ctrl, m); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - b.cz_if(ctrl, ci, m); - } else { - b.cz_if(acc[i], ctrl, m); - b.x(acc[i]); - } - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - } - } - - b.free_vec(&owned_carries); -} - -pub(crate) fn csub_nbit_const_direct_trunc_fast( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, -) { - csub_nbit_const_direct_trunc_fast_borrowed_carries(b, acc, c, ctrl, window, &[]); -} - -pub(crate) fn csub_nbit_const_direct_trunc_fast_borrowed_carries( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - borrowed_carries: &[QubitId], -) { - let n = acc.len(); - if n == 0 { - return; - } - if n == 1 { - if bit(c, 0) { - b.cx(ctrl, acc[0]); - } - return; - } - - let hi = highest_set_bit(c); - let last = core::cmp::min(n - 2, hi.saturating_add(window)); - let maj2 = fold_maj2_enabled(); - let (borrows, owned_borrows) = borrowed_const_fold_carries(b, last + 1, borrowed_carries); - - for i in 0..=last { - let target = borrows[i]; - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if bit(c, i) { - b.x(acc[i]); - if let Some(bi) = borrow_in { - emit_fold_majority(b, acc[i], ctrl, bi, target, maj2); - } else { - b.ccx(acc[i], ctrl, target); - } - b.x(acc[i]); - } else if let Some(bi) = borrow_in { - b.x(acc[i]); - b.ccx(acc[i], bi, target); - b.x(acc[i]); - } - } - - for i in 0..n { - if bit(c, i) { - b.cx(ctrl, acc[i]); - } - if i > 0 && i - 1 <= last { - b.cx(borrows[i - 1], acc[i]); - } - } - - for i in (0..=last).rev() { - let m = b.alloc_bit(); - b.hmr(borrows[i], m); - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if bit(c, i) { - if let Some(bi) = borrow_in { - b.cz_if(acc[i], ctrl, m); - b.cz_if(acc[i], bi, m); - b.cz_if(ctrl, bi, m); - } else { - b.cz_if(acc[i], ctrl, m); - } - } else if let Some(bi) = borrow_in { - b.cz_if(acc[i], bi, m); - } - } - - b.free_vec(&owned_borrows); -} - -fn special_fold_park_low_carries() -> usize { - std::env::var("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -fn special_fold_park_low_carries_at_step(step: Option) -> usize { - let mapped = step.and_then(|step| { - let map = - std::env::var("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES_STEP_MAP").ok()?; - map.split(',').rev().find_map(|entry| { - let (raw_step, raw_value) = entry.trim().split_once(':')?; - if raw_step.trim().parse::().ok()? != step { - return None; - } - raw_value.trim().parse::().ok() - }) - }); - mapped.unwrap_or_else(special_fold_park_low_carries) -} - -fn cconst_nbit_direct_trunc_fast_parked( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - park_low: usize, - is_add: bool, -) { - let n = acc.len(); - if n <= 1 { - if n == 1 && bit(c, 0) { - b.cx(ctrl, acc[0]); - } - return; - } - - let hi = highest_set_bit(c); - let last = core::cmp::min(n - 2, hi.saturating_add(window)); - let park_low = core::cmp::min(park_low, last.saturating_sub(hi)); - if park_low == 0 { - if is_add { - cadd_nbit_const_direct_trunc_fast(b, acc, c, ctrl, window); - } else { - csub_nbit_const_direct_trunc_fast(b, acc, c, ctrl, window); - } - return; - } - - let split = last - park_low; - let maj2 = fold_maj2_enabled(); - let prefix = b.alloc_qubits(split + 1); - let kctrl = |i: usize| bit(c, i).then_some(ctrl); - - for i in 0..=split { - let target = prefix[i]; - let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; - if is_add { - if let Some(kc) = kctrl(i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = kctrl(i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - } - - for i in 0..=split { - if let Some(kc) = kctrl(i) { - b.cx(kc, acc[i]); - } - if i > 0 { - b.cx(prefix[i - 1], acc[i]); - } - } - - for i in (0..park_low).rev() { - let measured = b.alloc_bit(); - b.hmr(prefix[i], measured); - let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - measured, - i, - is_add, - ); - b.free(prefix[i]); - } - - let tail = b.alloc_qubits(park_low); - let carry = |i: usize| { - if i <= split { - prefix[i] - } else { - tail[i - split - 1] - } - }; - for i in split + 1..=last { - let target = carry(i); - let carry_in = carry(i - 1); - if is_add { - if let Some(kc) = kctrl(i) { - emit_fold_majority(b, acc[i], kc, carry_in, target, maj2); - } else { - b.ccx(acc[i], carry_in, target); - } - } else if let Some(kc) = kctrl(i) { - b.x(acc[i]); - emit_fold_majority(b, acc[i], kc, carry_in, target, maj2); - b.x(acc[i]); - } else { - b.x(acc[i]); - b.ccx(acc[i], carry_in, target); - b.x(acc[i]); - } - } - - for i in split + 1..n { - if let Some(kc) = kctrl(i) { - b.cx(kc, acc[i]); - } - if i - 1 <= last { - b.cx(carry(i - 1), acc[i]); - } - } - - for i in (split + 1..=last).rev() { - let measured = b.alloc_bit(); - b.hmr(carry(i), measured); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(carry(i - 1)), - measured, - i, - is_add, - ); - b.free(carry(i)); - } - drop(tail); - - for i in 0..park_low { - b.reacquire(prefix[i]); - let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - carry_in, - prefix[i], - i, - is_add, - ); - } - - for i in (0..=split).rev() { - let measured = b.alloc_bit(); - b.hmr(prefix[i], measured); - let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - measured, - i, - is_add, - ); - b.free(prefix[i]); - } -} - -pub(crate) fn cadd_nbit_const_direct_trunc_fast_releasing_scratch( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - releasable_scratch: &[QubitId], -) { - cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b, - acc, - c, - ctrl, - window, - releasable_scratch, - None, - ); -} - -pub(crate) fn cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - releasable_scratch: &[QubitId], - step: Option, -) { - let park_low = special_fold_park_low_carries_at_step(step); - if park_low == 0 || releasable_scratch.is_empty() { - cadd_nbit_const_direct_trunc_fast_borrowed_carries( - b, - acc, - c, - ctrl, - window, - releasable_scratch, - ); - return; - } - b.free_vec(releasable_scratch); - cconst_nbit_direct_trunc_fast_parked(b, acc, c, ctrl, window, park_low, true); - b.reacquire_vec(releasable_scratch); -} - -pub(crate) fn csub_nbit_const_direct_trunc_fast_releasing_scratch( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - releasable_scratch: &[QubitId], -) { - csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b, - acc, - c, - ctrl, - window, - releasable_scratch, - None, - ); -} - -pub(crate) fn csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b: &mut B, - acc: &[QubitId], - c: U256, - ctrl: QubitId, - window: usize, - releasable_scratch: &[QubitId], - step: Option, -) { - let park_low = special_fold_park_low_carries_at_step(step); - if park_low == 0 || releasable_scratch.is_empty() { - csub_nbit_const_direct_trunc_fast_borrowed_carries( - b, - acc, - c, - ctrl, - window, - releasable_scratch, - ); - return; - } - b.free_vec(releasable_scratch); - cconst_nbit_direct_trunc_fast_parked(b, acc, c, ctrl, window, park_low, false); - b.reacquire_vec(releasable_scratch); -} - -pub(crate) fn cadd_per_position_controls_trunc( - b: &mut B, - acc: &[QubitId], - controls: &[Option], - last: usize, -) { - let n = acc.len(); - debug_assert!(last < n); - debug_assert!(controls.len() <= n); - let kctrl = |i: usize| -> Option { - if i < controls.len() { - controls[i] - } else { - None - } - }; - let maj2 = perpos_maj2_enabled(); - let carries = b.alloc_qubits(last + 1); - - for i in 0..=last { - let target = carries[i]; - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if let Some(kc) = kctrl(i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } - - for i in 0..n { - if let Some(kc) = kctrl(i) { - b.cx(kc, acc[i]); - } - if i > 0 && i - 1 <= last { - b.cx(carries[i - 1], acc[i]); - } - } - - for i in (0..=last).rev() { - let m = b.alloc_bit(); - b.hmr(carries[i], m); - let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; - if let Some(kc) = kctrl(i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - b.cz_if(acc[i], kc, m); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - b.cz_if(kc, ci, m); - } else { - b.cz_if(acc[i], kc, m); - b.x(acc[i]); - } - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.cz_if(acc[i], ci, m); - b.x(acc[i]); - } - } - - b.free_vec(&carries); -} - -pub(crate) fn csub_per_position_controls_trunc( - b: &mut B, - acc: &[QubitId], - controls: &[Option], - last: usize, -) { - let n = acc.len(); - debug_assert!(last < n); - debug_assert!(controls.len() <= n); - let kctrl = |i: usize| -> Option { - if i < controls.len() { - controls[i] - } else { - None - } - }; - let maj2 = perpos_maj2_enabled(); - let borrows = b.alloc_qubits(last + 1); - - for i in 0..=last { - let target = borrows[i]; - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if let Some(kc) = kctrl(i) { - b.x(acc[i]); - if let Some(bi) = borrow_in { - emit_fold_majority(b, acc[i], kc, bi, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(bi) = borrow_in { - b.x(acc[i]); - b.ccx(acc[i], bi, target); - b.x(acc[i]); - } - } - - for i in 0..n { - if let Some(kc) = kctrl(i) { - b.cx(kc, acc[i]); - } - if i > 0 && i - 1 <= last { - b.cx(borrows[i - 1], acc[i]); - } - } - - for i in (0..=last).rev() { - let m = b.alloc_bit(); - b.hmr(borrows[i], m); - let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; - if let Some(kc) = kctrl(i) { - if let Some(bi) = borrow_in { - b.cz_if(acc[i], kc, m); - b.cz_if(acc[i], bi, m); - b.cz_if(kc, bi, m); - } else { - b.cz_if(acc[i], kc, m); - } - } else if let Some(bi) = borrow_in { - b.cz_if(acc[i], bi, m); - } - } - - b.free_vec(&borrows); -} - -pub(crate) fn fold_freed_tail_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_FREED_TAIL").ok().as_deref() == Some("1") -} - -pub(crate) fn fold_freed_tail_ed_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_FREED_TAIL_ED") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn fold_host_derived_controls_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_DERIVED_CONTROLS") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_n10_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_N10") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_h_n10_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_H_N10") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_h_xed_n10_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_H_XED_N10") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_e_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_E") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_d_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_D") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn fold_only_carry_trunc_window() -> Option { - std::env::var("DIALOG_GCD_FOLD_CARRY_TRUNC_W") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&w| w > 0) -} - -fn fold_park_low_carries() -> usize { - std::env::var("DIALOG_GCD_FOLD_PARK_LOW_CARRIES") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -pub(crate) fn fold_park_low_carries_at_step(step: Option) -> usize { - let mapped = step.and_then(|step| { - let map = std::env::var("DIALOG_GCD_FOLD_PARK_LOW_CARRIES_STEP_MAP").ok()?; - map.split(',').rev().find_map(|entry| { - let (raw_step, raw_value) = entry.trim().split_once(':')?; - if raw_step.trim().parse::().ok()? != step { - return None; - } - raw_value.trim().parse::().ok() - }) - }); - mapped.unwrap_or_else(fold_park_low_carries) -} - -pub(crate) fn fold_stream_controls_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_STREAM_CONTROLS") - .ok() - .as_deref() - == Some("1") - && fold_park_low_carries() >= 12 -} - -fn fold_host_streamed_control_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_STREAMED_CONTROL") - .ok() - .as_deref() - == Some("1") - && fold_park_low_carries() >= 13 -} - -fn fold_host_e_top_carry_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_E_TOP_CARRY") - .ok() - .as_deref() - == Some("1") -} - -fn fold_host_d_carry12_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_D_CARRY12") - .ok() - .as_deref() - == Some("1") - && fold_park_low_carries() >= 14 -} - -fn fold_host_ovf2_carry13_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_HOST_OVF2_CARRY13") - .ok() - .as_deref() - == Some("1") - && fold_park_low_carries() >= 15 -} - -fn fold_free_first_high_carry_enabled() -> bool { - std::env::var("DIALOG_GCD_FOLD_FREE_FIRST_HIGH_CARRY") - .ok() - .as_deref() - == Some("1") -} - -fn fold_stream_profile_phase(b: &mut B, add_phase: &'static str, sub_phase: &'static str, is_add: bool) { - if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { - b.set_phase(if is_add { add_phase } else { sub_phase }); - } -} - -fn fold_postsum_carry_phase_uncompute( - b: &mut B, - acc: &[QubitId], - kctrl: Option, - carry_in: Option, - measured: BitId, - i: usize, - is_add: bool, -) { - if is_add { - if let Some(kc) = kctrl { - b.x(acc[i]); - if let Some(ci) = carry_in { - b.cz_if(acc[i], kc, measured); - b.cz_if(acc[i], ci, measured); - b.x(acc[i]); - b.cz_if(kc, ci, measured); - } else { - b.cz_if(acc[i], kc, measured); - b.x(acc[i]); - } - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.cz_if(acc[i], ci, measured); - b.x(acc[i]); - } - } else if let Some(kc) = kctrl { - if let Some(ci) = carry_in { - b.cz_if(acc[i], kc, measured); - b.cz_if(acc[i], ci, measured); - b.cz_if(kc, ci, measured); - } else { - b.cz_if(acc[i], kc, measured); - } - } else if let Some(ci) = carry_in { - b.cz_if(acc[i], ci, measured); - } -} - -fn fold_postsum_carry_compute( - b: &mut B, - acc: &[QubitId], - kctrl: Option, - carry_in: Option, - target: QubitId, - i: usize, - is_add: bool, -) { - if is_add { - if let Some(kc) = kctrl { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority( - b, - acc[i], - kc, - ci, - target, - perpos_maj2_enabled(), - ); - b.x(acc[i]); - } else { - b.ccx(acc[i], kc, target); - b.x(acc[i]); - } - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - } else if let Some(kc) = kctrl { - if let Some(ci) = carry_in { - emit_fold_majority( - b, - acc[i], - kc, - ci, - target, - perpos_maj2_enabled(), - ); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } -} - -fn fold_presum_carry_compute_and_sum( - b: &mut B, - acc: &[QubitId], - kctrl: Option, - carry_in: Option, - target: QubitId, - i: usize, - is_add: bool, - maj2: bool, -) { - if is_add { - if let Some(kc) = kctrl { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = kctrl { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - if let Some(kc) = kctrl { - b.cx(kc, acc[i]); - } - if let Some(ci) = carry_in { - b.cx(ci, acc[i]); - } -} - -pub(crate) fn secp_fold_controls( - e: QubitId, - d: QubitId, - h: QubitId, - xed: QubitId, - eord: QubitId, - n10: QubitId, - hi_delta: usize, - hi_c: usize, -) -> Vec> { - let mut controls: Vec> = vec![None; hi_delta + 1]; - controls[0] = Some(e); - controls[1] = Some(d); - controls[4] = Some(e); - controls[5] = Some(d); - controls[6] = Some(e); - controls[7] = Some(xed); - controls[8] = Some(eord); - controls[9] = Some(eord); - controls[10] = Some(n10); - controls[11] = Some(h); - controls[hi_c] = Some(e); - controls[hi_delta] = Some(d); - controls -} - -pub(crate) fn fold_ripple_freed_tail( - b: &mut B, - acc: &[QubitId], - e: QubitId, - d: QubitId, - h: QubitId, - xed: QubitId, - eord: QubitId, - n10: QubitId, - last: usize, - is_add: bool, -) { - - fold_ripple_freed_tail_ed( - b, acc, e, d, h, xed, eord, n10, None, None, last, is_add, - ); -} - -pub(crate) fn fold_ripple_freed_tail_ed_streamed( - b: &mut B, - acc: &[QubitId], - e: QubitId, - d: QubitId, - ed: Option<(QubitId, QubitId, QubitId)>, - park_low: usize, - last: usize, - is_add: bool, -) { - let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); - let n = acc.len(); - let hi_delta = 33usize; - debug_assert!(last < n); - debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); - let park_low = core::cmp::min(park_low, hi_delta); - assert!( - park_low >= 12, - "streamed fold controls require at least 12 parked carries" - ); - let host_streamed = fold_host_streamed_control_enabled(); - let host_e_top = free_ed && fold_host_e_top_carry_enabled(); - let host_d_carry12 = - host_e_top && fold_host_d_carry12_enabled(); - let host_ovf2_carry13 = - host_d_carry12 && fold_host_ovf2_carry13_enabled(); - let maj2 = perpos_maj2_enabled(); - let kctrl = |i: usize| match i { - 0 | 4 | 6 | 32 => Some(e), - 1 | 5 | 33 => Some(d), - _ => None, - }; - fold_stream_profile_phase( - b, - "dialog_gcd_streamed_double_active", - "dialog_gcd_streamed_halve_active", - is_add, - ); - let low_chain_last = if host_e_top { - hi_delta - 1 - } else { - hi_delta - }; - let mut low = b.alloc_qubits( - low_chain_last + 1 - - usize::from(host_d_carry12) - - usize::from(host_ovf2_carry13), - ); - if host_d_carry12 { - low.insert(12, d); - } - if host_ovf2_carry13 { - let (_, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); - low.insert(13, ovf2); - let (ovf1, _, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); - b.cx(ovf1, ovf2); - b.cx(d, ovf2); - b.cx(e, ovf2); - } - let streamed_slot = low[park_low - 1]; - - for i in 0..7 { - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_presum_carry_compute_and_sum( - b, - acc, - kctrl(i), - carry_in, - low[i], - i, - is_add, - maj2, - ); - } - let streamed = if host_streamed { - streamed_slot - } else { - b.alloc_qubit() - }; - b.cx(e, streamed); - b.cx(d, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[6]), - low[7], - 7, - is_add, - maj2, - ); - b.ccx(e, d, streamed); - for i in 8..10 { - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[i - 1]), - low[i], - i, - is_add, - maj2, - ); - } - b.cx(e, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[9]), - low[10], - 10, - is_add, - maj2, - ); - b.cx(d, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[10]), - low[11], - 11, - is_add, - maj2, - ); - if host_streamed { - b.ccx(e, d, streamed); - } - if host_d_carry12 { - let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); - b.ccx(ovf1, s2, d); - } - for i in 12..=low_chain_last { - fold_presum_carry_compute_and_sum( - b, - acc, - kctrl(i), - Some(low[i - 1]), - low[i], - i, - is_add, - maj2, - ); - } - - let free_first_high_carry = fold_free_first_high_carry_enabled() - && park_low < low_chain_last - && !(host_d_carry12 && park_low == 12) - && !(host_ovf2_carry13 && park_low == 13); - if free_first_high_carry { - let m = b.alloc_bit(); - b.hmr(low[park_low], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(park_low), - Some(low[park_low - 1]), - m, - park_low, - is_add, - ); - b.free(low[park_low]); - } - - for i in (12..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - if host_d_carry12 { - let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); - b.reacquire(d); - b.ccx(ovf1, s2, d); - } - if host_streamed { - b.reacquire(streamed); - b.ccx(e, d, streamed); - } - let m11 = b.alloc_bit(); - b.hmr(low[11], m11); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[10]), - m11, - 11, - is_add, - ); - b.free(low[11]); - b.cx(d, streamed); - let m10 = b.alloc_bit(); - b.hmr(low[10], m10); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[9]), - m10, - 10, - is_add, - ); - b.free(low[10]); - b.cx(e, streamed); - for i in (8..10).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - b.ccx(e, d, streamed); - let m7 = b.alloc_bit(); - b.hmr(low[7], m7); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[6]), - m7, - 7, - is_add, - ); - b.free(low[7]); - b.cx(d, streamed); - b.cx(e, streamed); - b.free(streamed); - for i in (0..7).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - - if host_ovf2_carry13 { - let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); - b.reacquire(ovf2); - b.cx(ovf1, ovf2); - b.cx(d, ovf2); - b.cx(e, ovf2); - } - - if host_e_top { - let (ovf1, ovf2, _) = ed.expect("host_e_top implies ed is Some"); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(d), - Some(low[hi_delta - 1]), - e, - hi_delta, - is_add, - maj2, - ); - } - - if free_ed { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - if !host_e_top { - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.free(e); - } - let md = b.alloc_bit(); - b.hmr(d, md); - b.cz_if(ovf1, s2, md); - b.free(d); - } - - fold_stream_profile_phase( - b, - "dialog_gcd_streamed_double_tail", - "dialog_gcd_streamed_halve_tail", - is_add, - ); - let tail_len = last - hi_delta; - let tail = b.alloc_qubits(tail_len); - let cw = |i: usize| -> QubitId { - if i < hi_delta { - low[i] - } else if i == hi_delta { - if host_e_top { - e - } else { - low[i] - } - } else { - tail[i - hi_delta - 1] - } - }; - for i in hi_delta + 1..=last { - if is_add { - b.ccx(acc[i], cw(i - 1), cw(i)); - } else { - b.x(acc[i]); - b.ccx(acc[i], cw(i - 1), cw(i)); - b.x(acc[i]); - } - } - for i in hi_delta + 1..n { - if i - 1 <= last { - b.cx(cw(i - 1), acc[i]); - } - } - for i in (hi_delta + 1..=last).rev() { - let m = b.alloc_bit(); - b.hmr(cw(i), m); - let carry_in = cw(i - 1); - if is_add { - b.x(acc[i]); - b.cz_if(acc[i], carry_in, m); - b.x(acc[i]); - } else { - b.cz_if(acc[i], carry_in, m); - } - b.free(cw(i)); - } - drop(tail); - - fold_stream_profile_phase( - b, - "dialog_gcd_streamed_double_reverse", - "dialog_gcd_streamed_halve_reverse", - is_add, - ); - if free_ed { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - b.reacquire(d); - b.ccx(ovf1, s2, d); - if host_e_top { - let m_top = b.alloc_bit(); - b.hmr(e, m_top); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(d), - Some(low[hi_delta - 1]), - m_top, - hi_delta, - is_add, - ); - b.free(e); - } - b.reacquire(e); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - } - if host_ovf2_carry13 { - let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); - b.cx(ovf1, ovf2); - b.cx(d, ovf2); - b.cx(e, ovf2); - } - - for i in 0..park_low { - if !(host_d_carry12 && i == 12) - && !(host_ovf2_carry13 && i == 13) - { - b.reacquire(low[i]); - } - } - for i in 0..7 { - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - carry_in, - low[i], - i, - is_add, - ); - } - let streamed = if host_streamed { - streamed_slot - } else { - b.alloc_qubit() - }; - b.cx(e, streamed); - b.cx(d, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[6]), - low[7], - 7, - is_add, - ); - b.ccx(e, d, streamed); - for i in 8..10 { - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - low[i], - i, - is_add, - ); - } - b.cx(e, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[9]), - low[10], - 10, - is_add, - ); - b.cx(d, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[10]), - low[11], - 11, - is_add, - ); - if host_streamed { - b.ccx(e, d, streamed); - } - if host_d_carry12 { - let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); - b.ccx(ovf1, s2, d); - } - for i in 12..park_low { - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - low[i], - i, - is_add, - ); - } - if free_first_high_carry { - b.reacquire(low[park_low]); - fold_postsum_carry_compute( - b, - acc, - kctrl(park_low), - Some(low[park_low - 1]), - low[park_low], - park_low, - is_add, - ); - } - - for i in (12..=low_chain_last).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - if host_d_carry12 { - let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); - b.reacquire(d); - b.ccx(ovf1, s2, d); - } - if host_ovf2_carry13 { - let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); - b.reacquire(ovf2); - b.cx(ovf1, ovf2); - b.cx(d, ovf2); - b.cx(e, ovf2); - } - if host_streamed { - b.reacquire(streamed); - b.ccx(e, d, streamed); - } - let m11 = b.alloc_bit(); - b.hmr(low[11], m11); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[10]), - m11, - 11, - is_add, - ); - b.free(low[11]); - b.cx(d, streamed); - let m10 = b.alloc_bit(); - b.hmr(low[10], m10); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[9]), - m10, - 10, - is_add, - ); - b.free(low[10]); - b.cx(e, streamed); - for i in (8..10).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - b.ccx(e, d, streamed); - let m7 = b.alloc_bit(); - b.hmr(low[7], m7); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[6]), - m7, - 7, - is_add, - ); - b.free(low[7]); - b.cx(d, streamed); - b.cx(e, streamed); - b.free(streamed); - for i in (0..7).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - drop(low); -} - -pub(crate) fn fold_ripple_freed_tail_ed( - b: &mut B, - acc: &[QubitId], - e: QubitId, - d: QubitId, - h: QubitId, - xed: QubitId, - eord: QubitId, - n10: QubitId, - ed: Option<(QubitId, QubitId, QubitId)>, - step: Option, - last: usize, - is_add: bool, -) { - let configured_park_low = fold_park_low_carries_at_step(step); - if fold_host_derived_controls_enabled() && configured_park_low <= 7 { - fold_ripple_freed_tail_ed_hosted( - b, - acc, - e, - d, - h, - xed, - eord, - n10, - ed, - configured_park_low, - last, - is_add, - ); - return; - } - if fold_stream_controls_enabled() && configured_park_low >= 12 { - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(n10); - b.free(eord); - b.free(xed); - let mh = b.alloc_bit(); - b.hmr(h, mh); - b.cz_if(e, d, mh); - b.free(h); - fold_ripple_freed_tail_ed_streamed( - b, - acc, - e, - d, - ed, - configured_park_low, - last, - is_add, - ); - b.reacquire(h); - b.ccx(e, d, h); - b.reacquire(xed); - b.cx(e, xed); - b.cx(d, xed); - b.reacquire(eord); - b.cx(xed, eord); - b.cx(h, eord); - b.reacquire(n10); - b.cx(d, n10); - b.cx(h, n10); - return; - } - - let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); - let n = acc.len(); - let hi_delta = 33usize; - let hi_c = 32usize; - debug_assert!(last < n); - debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); - let controls = secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); - let kctrl = |i: usize| controls.get(i).copied().flatten(); - let maj2 = perpos_maj2_enabled(); - let park_low = core::cmp::min(configured_park_low, hi_delta); - let host_all_derived = fold_host_derived_controls_enabled() && park_low >= 15; - let host_h_xed_n10 = - (fold_host_h_xed_n10_enabled() || host_all_derived) && park_low >= 14; - let host_h_n10 = - (fold_host_h_n10_enabled() || host_h_xed_n10) && park_low >= 13; - let host_xed = host_h_xed_n10; - let host_eord = host_all_derived; - let host_e = fold_host_e_enabled() && host_all_derived && free_ed && park_low >= 17; - let host_d = fold_host_d_enabled() && host_e && park_low >= 18; - let host_n10 = (fold_host_n10_enabled() || host_h_n10) && park_low >= 12; - let stream_controls = - fold_stream_controls_enabled() && park_low >= 12 && !host_n10; - - if stream_controls { - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(n10); - b.free(eord); - b.free(xed); - let mh = b.alloc_bit(); - b.hmr(h, mh); - b.cz_if(e, d, mh); - b.free(h); - } - - let low = if host_h_n10 { - b.cx(h, n10); - b.cx(d, n10); - b.free(n10); - if host_eord { - b.cx(h, eord); - b.cx(xed, eord); - b.free(eord); - } - if host_xed { - b.cx(d, xed); - b.cx(e, xed); - b.free(xed); - } - b.ccx(e, d, h); - b.free(h); - if host_e { - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.free(e); - } - - let d_slot = host_d.then_some(d); - let e_slot = if host_e { - let slot = b.alloc_qubit(); - debug_assert_eq!(slot, e); - Some(slot) - } else { - None - }; - let h_slot = b.alloc_qubit(); - debug_assert_eq!(h_slot, h); - let xed_slot = if host_xed { - let slot = b.alloc_qubit(); - debug_assert_eq!(slot, xed); - Some(slot) - } else { - None - }; - let eord_slot = if host_eord { - let slot = b.alloc_qubit(); - debug_assert_eq!(slot, eord); - Some(slot) - } else { - None - }; - let n10_slot = b.alloc_qubit(); - debug_assert_eq!(n10_slot, n10); - let regular = b.alloc_qubits( - hi_delta - - 1 - - usize::from(host_xed) - - usize::from(host_eord) - - usize::from(host_e) - - usize::from(host_d), - ); - let mut low = Vec::with_capacity(hi_delta + 1); - let mut next_regular = 0usize; - for i in 0..=hi_delta { - if i == 28 && host_d { - low.push(n10_slot); - } else if i == 29 && host_d { - low.push(d_slot.expect("hosted d slot")); - } else if i == 29 && host_e { - low.push(n10_slot); - } else if i == 30 { - low.push(h_slot); - } else if i == 31 && host_xed { - low.push(xed_slot.expect("hosted xed slot")); - } else if i == 32 && host_eord { - low.push(eord_slot.expect("hosted eord slot")); - } else if i == hi_delta { - low.push(e_slot.unwrap_or(n10_slot)); - } else { - low.push(regular[next_regular]); - next_regular += 1; - } - } - debug_assert_eq!(next_regular, regular.len()); - low - } else if host_n10 { - b.cx(h, n10); - b.cx(d, n10); - b.free(n10); - let n10_slot = b.alloc_qubit(); - debug_assert_eq!(n10_slot, n10); - let mut low = b.alloc_qubits(hi_delta); - low.push(n10_slot); - low - } else { - b.alloc_qubits(hi_delta + 1) - }; - - let mut tail_d = None; - let mut streamed_forward = None; - if host_h_n10 { - - let e_host = host_e.then_some(low[hi_delta]); - let h_host = low[30]; - let xed_host = host_xed.then_some(low[31]); - let eord_host = host_eord.then_some(low[32]); - let d_host = host_d.then_some(low[29]); - let n10_host = if host_d { - low[28] - } else if host_e { - low[29] - } else { - low[hi_delta] - }; - let e_ctrl = e_host.unwrap_or(e); - let d_ctrl = d_host.unwrap_or(d); - if let Some(e_host) = e_host { - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - b.cx(ovf1, e_host); - b.cx(d_ctrl, e_host); - b.cx(ovf2, e_host); - } - b.ccx(e_ctrl, d_ctrl, h_host); - if let Some(xed_host) = xed_host { - b.cx(e_ctrl, xed_host); - b.cx(d_ctrl, xed_host); - } - if let Some(eord_host) = eord_host { - b.cx(xed_host.expect("hosted xed for eord"), eord_host); - b.cx(h_host, eord_host); - } - b.cx(d_ctrl, n10_host); - b.cx(h_host, n10_host); - for i in 0..=hi_delta { - if (host_d && i == 28) - || (!host_d && host_e && i == 29) - || (!host_e && i == 30) - { - b.cx(h_host, n10_host); - b.cx(d_ctrl, n10_host); - if let Some(eord_host) = eord_host { - b.cx(h_host, eord_host); - b.cx(xed_host.expect("hosted xed for eord"), eord_host); - } - if let Some(xed_host) = xed_host { - b.cx(d_ctrl, xed_host); - b.cx(e_ctrl, xed_host); - } - b.ccx(e_ctrl, d_ctrl, h_host); - } - if host_d && i == 29 { - let (ovf1, _, s2) = ed.expect("host_d requires overflow controls"); - b.ccx(ovf1, s2, d_ctrl); - } - if host_e && i == hi_delta { - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - b.cx(ovf2, e_ctrl); - if host_d { - b.cx(tail_d.expect("tail d is live at bit 33"), e_ctrl); - } else { - b.cx(d_ctrl, e_ctrl); - } - b.cx(ovf1, e_ctrl); - } - let target = low[i]; - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - let kc = match i { - 0 | 4 | 6 | 32 if host_e => Some(e_ctrl), - 1 | 5 if host_d => d_host, - 7 if host_xed => xed_host, - 8 | 9 if host_eord => eord_host, - 10 => Some(n10_host), - 11 => Some(h_host), - 33 if host_d => tail_d, - _ => kctrl(i), - }; - if is_add { - if let Some(kc) = kc { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = kc { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - if let Some(kc) = kc { - b.cx(kc, acc[i]); - } - if i > 0 { - b.cx(low[i - 1], acc[i]); - } - if host_d && i == hi_delta - 1 { - - let measured = b.alloc_bit(); - b.hmr(low[31], measured); - fold_postsum_carry_phase_uncompute( - b, - acc, - None, - Some(low[30]), - measured, - 31, - is_add, - ); - b.free(low[31]); - let slot = b.alloc_qubit(); - debug_assert_eq!(slot, low[31]); - let (ovf1, _, s2) = ed.expect("host_d requires overflow controls"); - b.ccx(ovf1, s2, slot); - tail_d = Some(slot); - } - } - } else if host_n10 { - - let n10_host = low[hi_delta]; - b.cx(d, n10_host); - b.cx(h, n10_host); - for i in 0..=hi_delta { - if i == hi_delta { - b.cx(h, n10_host); - b.cx(d, n10_host); - } - let target = low[i]; - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - let kc = if i == 10 { Some(n10_host) } else { kctrl(i) }; - if is_add { - if let Some(kc) = kc { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = kc { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - if let Some(kc) = kc { - b.cx(kc, acc[i]); - } - if i > 0 { - b.cx(low[i - 1], acc[i]); - } - } - } else if stream_controls { - for i in 0..7 { - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_presum_carry_compute_and_sum( - b, - acc, - kctrl(i), - carry_in, - low[i], - i, - is_add, - maj2, - ); - } - let streamed = b.alloc_qubit(); - b.cx(e, streamed); - b.cx(d, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[6]), - low[7], - 7, - is_add, - maj2, - ); - b.ccx(e, d, streamed); - for i in 8..10 { - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[i - 1]), - low[i], - i, - is_add, - maj2, - ); - } - b.cx(e, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[9]), - low[10], - 10, - is_add, - maj2, - ); - b.cx(d, streamed); - fold_presum_carry_compute_and_sum( - b, - acc, - Some(streamed), - Some(low[10]), - low[11], - 11, - is_add, - maj2, - ); - for i in 12..=hi_delta { - fold_presum_carry_compute_and_sum( - b, - acc, - kctrl(i), - Some(low[i - 1]), - low[i], - i, - is_add, - maj2, - ); - } - streamed_forward = Some(streamed); - } else { - for i in 0..=hi_delta { - let target = low[i]; - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - if is_add { - if let Some(kc) = kctrl(i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = kctrl(i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - } - - for i in 0..=hi_delta { - if let Some(kc) = kctrl(i) { - b.cx(kc, acc[i]); - } - if i > 0 { - b.cx(low[i - 1], acc[i]); - } - } - } - - if park_low > 0 { - if host_h_n10 { - for i in (12..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - - let d_ctrl = if host_d { - tail_d.expect("tail d is live during parked-carry cleanup") - } else { - d - }; - let rev_e = if host_e { - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - let rev_e = b.alloc_qubit(); - b.cx(ovf1, rev_e); - b.cx(d_ctrl, rev_e); - b.cx(ovf2, rev_e); - Some(rev_e) - } else { - None - }; - let e_ctrl = rev_e.unwrap_or(e); - let rev_h = b.alloc_qubit(); - b.ccx(e_ctrl, d_ctrl, rev_h); - let measured_h = b.alloc_bit(); - b.hmr(low[11], measured_h); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(rev_h), - Some(low[10]), - measured_h, - 11, - is_add, - ); - b.free(low[11]); - - let rev_n10 = b.alloc_qubit(); - debug_assert_eq!(rev_n10, low[11]); - b.cx(d_ctrl, rev_n10); - b.cx(rev_h, rev_n10); - let measured_n10 = b.alloc_bit(); - b.hmr(low[10], measured_n10); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(rev_n10), - Some(low[9]), - measured_n10, - 10, - is_add, - ); - b.free(low[10]); - b.cx(rev_h, rev_n10); - b.cx(d_ctrl, rev_n10); - b.free(rev_n10); - - let rev_xed = if host_xed { - let rev_xed = b.alloc_qubit(); - b.cx(e_ctrl, rev_xed); - b.cx(d_ctrl, rev_xed); - Some(rev_xed) - } else { - None - }; - let rev_eord = if host_eord { - let rev_eord = b.alloc_qubit(); - b.cx(rev_xed.expect("hosted xed for eord"), rev_eord); - b.cx(rev_h, rev_eord); - Some(rev_eord) - } else { - None - }; - if !host_xed { - b.ccx(e, d, rev_h); - b.free(rev_h); - } - for i in (0..10).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - let kc = match i { - 0 | 4 | 6 if host_e => rev_e, - 1 | 5 if host_d => Some(d_ctrl), - 7 if host_xed => rev_xed, - 8 | 9 if host_eord => rev_eord, - _ => kctrl(i), - }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kc, - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - if let Some(rev_eord) = rev_eord { - b.cx(rev_h, rev_eord); - b.cx(rev_xed.expect("hosted xed for eord"), rev_eord); - b.free(rev_eord); - } - if let Some(rev_xed) = rev_xed { - b.cx(d_ctrl, rev_xed); - b.cx(e_ctrl, rev_xed); - b.free(rev_xed); - } - if host_xed { - b.ccx(e_ctrl, d_ctrl, rev_h); - b.free(rev_h); - } - if let Some(rev_e) = rev_e { - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - b.cx(ovf2, rev_e); - b.cx(d_ctrl, rev_e); - b.cx(ovf1, rev_e); - b.free(rev_e); - } - } else if host_n10 { - for i in (11..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - let rev_n10 = b.alloc_qubit(); - b.cx(d, rev_n10); - b.cx(h, rev_n10); - for i in (0..11).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - let kc = if i == 10 { Some(rev_n10) } else { kctrl(i) }; - fold_postsum_carry_phase_uncompute( - b, acc, kc, carry_in, m, i, is_add, - ); - b.free(low[i]); - } - b.cx(h, rev_n10); - b.cx(d, rev_n10); - b.free(rev_n10); - } else if stream_controls { - let streamed = streamed_forward - .take() - .expect("streamed forward control is live"); - for i in (12..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - let m11 = b.alloc_bit(); - b.hmr(low[11], m11); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[10]), - m11, - 11, - is_add, - ); - b.free(low[11]); - b.cx(d, streamed); - let m10 = b.alloc_bit(); - b.hmr(low[10], m10); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[9]), - m10, - 10, - is_add, - ); - b.free(low[10]); - b.cx(e, streamed); - for i in (8..10).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - b.ccx(e, d, streamed); - let m7 = b.alloc_bit(); - b.hmr(low[7], m7); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[6]), - m7, - 7, - is_add, - ); - b.free(low[7]); - b.cx(d, streamed); - b.cx(e, streamed); - b.free(streamed); - for i in (0..7).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - } else { - for i in (0..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - } - } - debug_assert!(streamed_forward.is_none()); - - if !stream_controls { - if !host_n10 { - b.cx(h, n10); - b.cx(d, n10); - b.free(n10); - } - if !host_eord { - if host_h_n10 { - let rev_h = b.alloc_qubit(); - b.ccx(e, d, rev_h); - b.cx(rev_h, eord); - b.ccx(e, d, rev_h); - b.free(rev_h); - } else { - b.cx(h, eord); - } - if host_xed { - let rev_xed = b.alloc_qubit(); - b.cx(e, rev_xed); - b.cx(d, rev_xed); - b.cx(rev_xed, eord); - b.cx(d, rev_xed); - b.cx(e, rev_xed); - b.free(rev_xed); - } else { - b.cx(xed, eord); - } - b.free(eord); - } - if !host_xed { - b.cx(d, xed); - b.cx(e, xed); - b.free(xed); - } - if !host_h_n10 { - let mh = b.alloc_bit(); - b.hmr(h, mh); - b.cz_if(e, d, mh); - b.free(h); - } - } - - if free_ed { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - if !host_e { - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.free(e); - } - if !host_d { - let md = b.alloc_bit(); - b.hmr(d, md); - b.cz_if(ovf1, s2, md); - b.free(d); - } - } - - let tail_len = last - hi_delta; - let tail = b.alloc_qubits(tail_len); - let cw = |i: usize| -> QubitId { - if i <= hi_delta { - low[i] - } else { - tail[i - hi_delta - 1] - } - }; - - for i in (hi_delta + 1)..=last { - if is_add { - b.ccx(acc[i], cw(i - 1), cw(i)); - } else { - b.x(acc[i]); - b.ccx(acc[i], cw(i - 1), cw(i)); - b.x(acc[i]); - } - } - - for i in (hi_delta + 1)..n { - if i - 1 <= last { - b.cx(cw(i - 1), acc[i]); - } - } - - for i in (hi_delta + 1..=last).rev() { - let m = b.alloc_bit(); - b.hmr(cw(i), m); - let carry_in = cw(i - 1); - if is_add { - b.x(acc[i]); - b.cz_if(acc[i], carry_in, m); - b.x(acc[i]); - } else { - b.cz_if(acc[i], carry_in, m); - } - b.free(cw(i)); - } - drop(tail); - - if free_ed && !host_d { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - b.reacquire(d); - b.ccx(ovf1, s2, d); - if !host_e { - b.reacquire(e); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - } - } - if host_h_n10 { - if host_e { - let measured = b.alloc_bit(); - b.hmr(low[hi_delta], measured); - if host_d { - fold_postsum_carry_phase_uncompute( - b, - acc, - tail_d, - Some(low[hi_delta - 1]), - measured, - hi_delta, - is_add, - ); - } else { - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(d), - Some(low[hi_delta - 1]), - measured, - hi_delta, - is_add, - ); - } - b.free(low[hi_delta]); - let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); - b.reacquire(e); - b.cx(ovf1, e); - if host_d { - b.cx(tail_d.expect("tail d is live while restoring e"), e); - } else { - b.cx(d, e); - } - b.cx(ovf2, e); - } - if host_d { - - let carry31 = b.alloc_qubit(); - fold_postsum_carry_compute( - b, - acc, - None, - Some(low[30]), - carry31, - 31, - is_add, - ); - let measured32 = b.alloc_bit(); - b.hmr(low[32], measured32); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(e), - Some(carry31), - measured32, - 32, - is_add, - ); - b.free(low[32]); - let measured31 = b.alloc_bit(); - b.hmr(carry31, measured31); - fold_postsum_carry_phase_uncompute( - b, - acc, - None, - Some(low[30]), - measured31, - 31, - is_add, - ); - b.free(carry31); - - for i in (28..=30).rev() { - let measured = b.alloc_bit(); - b.hmr(low[i], measured); - fold_postsum_carry_phase_uncompute( - b, - acc, - None, - Some(low[i - 1]), - measured, - i, - is_add, - ); - b.free(low[i]); - } - - let d_tail = tail_d.expect("tail d is live during d restoration"); - b.reacquire(d); - b.cx(d_tail, d); - b.cx(d, d_tail); - b.free(d_tail); - } else { - let high_start = if host_e { 29 } else { 30 }; - let high_end = if host_e { hi_delta - 1 } else { hi_delta }; - for i in (high_start..=high_end).rev() { - let measured = b.alloc_bit(); - b.hmr(low[i], measured); - let kc = match i { - 32 => Some(e), - 33 => Some(d), - _ => None, - }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kc, - Some(low[i - 1]), - measured, - i, - is_add, - ); - b.free(low[i]); - } - } - } else if host_n10 { - let measured = b.alloc_bit(); - b.hmr(low[hi_delta], measured); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(d), - Some(low[hi_delta - 1]), - measured, - hi_delta, - is_add, - ); - b.free(low[hi_delta]); - } - if stream_controls { - for i in 0..park_low { - b.reacquire(low[i]); - } - - for i in 0..7 { - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - carry_in, - low[i], - i, - is_add, - ); - } - - let streamed = b.alloc_qubit(); - b.cx(e, streamed); - b.cx(d, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[6]), - low[7], - 7, - is_add, - ); - b.ccx(e, d, streamed); - for i in 8..10 { - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - low[i], - i, - is_add, - ); - } - b.cx(e, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[9]), - low[10], - 10, - is_add, - ); - b.cx(d, streamed); - fold_postsum_carry_compute( - b, - acc, - Some(streamed), - Some(low[10]), - low[11], - 11, - is_add, - ); - for i in 12..park_low { - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - low[i], - i, - is_add, - ); - } - - for i in (12..=hi_delta).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - - let m11 = b.alloc_bit(); - b.hmr(low[11], m11); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[10]), - m11, - 11, - is_add, - ); - b.free(low[11]); - b.cx(d, streamed); - - let m10 = b.alloc_bit(); - b.hmr(low[10], m10); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[9]), - m10, - 10, - is_add, - ); - b.free(low[10]); - b.cx(e, streamed); - - for i in (8..10).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - b.ccx(e, d, streamed); - - let m7 = b.alloc_bit(); - b.hmr(low[7], m7); - fold_postsum_carry_phase_uncompute( - b, - acc, - Some(streamed), - Some(low[6]), - m7, - 7, - is_add, - ); - b.free(low[7]); - b.cx(d, streamed); - b.cx(e, streamed); - b.free(streamed); - - for i in (0..7).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - drop(low); - - b.reacquire(h); - b.ccx(e, d, h); - b.reacquire(xed); - b.cx(e, xed); - b.cx(d, xed); - b.reacquire(eord); - b.cx(xed, eord); - b.cx(h, eord); - b.reacquire(n10); - b.cx(d, n10); - b.cx(h, n10); - } else { - b.reacquire(h); - b.ccx(e, d, h); - b.reacquire(xed); - b.cx(e, xed); - b.cx(d, xed); - b.reacquire(eord); - b.cx(xed, eord); - b.cx(h, eord); - b.reacquire(n10); - b.cx(d, n10); - b.cx(h, n10); - - if park_low > 0 { - for i in 0..park_low { - b.reacquire(low[i]); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_compute( - b, - acc, - kctrl(i), - carry_in, - low[i], - i, - is_add, - ); - } - } - - let low_top = if host_d { - 27 - } else if host_e { - 28 - } else if host_h_n10 { - 29 - } else if host_n10 { - hi_delta - 1 - } else { - hi_delta - }; - for i in (0..=low_top).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl(i), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - drop(low); - } - -} - -fn fold_ripple_freed_tail_ed_hosted( - b: &mut B, - acc: &[QubitId], - e: QubitId, - d: QubitId, - h: QubitId, - xed: QubitId, - eord: QubitId, - n10: QubitId, - ed: Option<(QubitId, QubitId, QubitId)>, - park_low: usize, - last: usize, - is_add: bool, -) { - let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); - let n = acc.len(); - let hi_delta = 33usize; - let split = 11usize; - debug_assert!(last < n); - debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); - let maj2 = perpos_maj2_enabled(); - let park_low = core::cmp::min(park_low, split + 1); - - b.cx(h, n10); - b.cx(d, n10); - b.free(n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(eord); - b.free(xed); - let mh = b.alloc_bit(); - b.hmr(h, mh); - b.cz_if(e, d, mh); - b.free(h); - - let low = b.alloc_qubits(hi_delta + 1); - - let h_host = low[30]; - let xed_host = low[31]; - let eord_host = low[32]; - let n10_host = low[33]; - b.ccx(e, d, h_host); - b.cx(e, xed_host); - b.cx(d, xed_host); - b.cx(xed_host, eord_host); - b.cx(h_host, eord_host); - b.cx(d, n10_host); - b.cx(h_host, n10_host); - - let hosted_kctrl = |i: usize| -> Option { - match i { - 0 | 4 | 6 | 32 => Some(e), - 1 | 5 | 33 => Some(d), - 7 => Some(xed_host), - 8 | 9 => Some(eord_host), - 10 => Some(n10_host), - 11 => Some(h_host), - _ => None, - } - }; - - for i in 0..=split { - let target = low[i]; - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - if is_add { - if let Some(kc) = hosted_kctrl(i) { - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - } else if let Some(ci) = carry_in { - b.ccx(acc[i], ci, target); - } - } else if let Some(kc) = hosted_kctrl(i) { - b.x(acc[i]); - if let Some(ci) = carry_in { - emit_fold_majority(b, acc[i], kc, ci, target, maj2); - } else { - b.ccx(acc[i], kc, target); - } - b.x(acc[i]); - } else if let Some(ci) = carry_in { - b.x(acc[i]); - b.ccx(acc[i], ci, target); - b.x(acc[i]); - } - } - for i in 0..=split { - if let Some(kc) = hosted_kctrl(i) { - b.cx(kc, acc[i]); - } - if i > 0 { - b.cx(low[i - 1], acc[i]); - } - } - - b.cx(h_host, n10_host); - b.cx(d, n10_host); - b.cx(h_host, eord_host); - b.cx(xed_host, eord_host); - b.cx(d, xed_host); - b.cx(e, xed_host); - let mh_host = b.alloc_bit(); - b.hmr(h_host, mh_host); - b.cz_if(e, d, mh_host); - - for i in split + 1..=hi_delta { - let target = low[i]; - let carry_in = Some(low[i - 1]); - let kctrl = match i { - 32 => Some(e), - 33 => Some(d), - _ => None, - }; - if is_add { - if let Some(kc) = kctrl { - emit_fold_majority( - b, - acc[i], - kc, - carry_in.expect("high carry-in"), - target, - maj2, - ); - } else { - b.ccx( - acc[i], - carry_in.expect("high carry-in"), - target, - ); - } - } else if let Some(kc) = kctrl { - b.x(acc[i]); - emit_fold_majority( - b, - acc[i], - kc, - carry_in.expect("high carry-in"), - target, - maj2, - ); - b.x(acc[i]); - } else { - b.x(acc[i]); - b.ccx( - acc[i], - carry_in.expect("high carry-in"), - target, - ); - b.x(acc[i]); - } - } - for i in split + 1..=hi_delta { - let kctrl = match i { - 32 => Some(e), - 33 => Some(d), - _ => None, - }; - if let Some(kc) = kctrl { - b.cx(kc, acc[i]); - } - b.cx(low[i - 1], acc[i]); - } - - if park_low > 0 { - let controls = secp_fold_controls( - e, d, h_host, xed_host, eord_host, n10_host, hi_delta, 32, - ); - for i in (0..park_low).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - controls.get(i).copied().flatten(), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - } - - if free_ed { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.free(e); - let md = b.alloc_bit(); - b.hmr(d, md); - b.cz_if(ovf1, s2, md); - b.free(d); - } - - let tail_len = last - hi_delta; - let tail = b.alloc_qubits(tail_len); - let cw = |i: usize| -> QubitId { - if i <= hi_delta { - low[i] - } else { - tail[i - hi_delta - 1] - } - }; - - for i in (hi_delta + 1)..=last { - if is_add { - b.ccx(acc[i], cw(i - 1), cw(i)); - } else { - b.x(acc[i]); - b.ccx(acc[i], cw(i - 1), cw(i)); - b.x(acc[i]); - } - } - for i in (hi_delta + 1)..n { - if i - 1 <= last { - b.cx(cw(i - 1), acc[i]); - } - } - for i in (hi_delta + 1..=last).rev() { - let m = b.alloc_bit(); - b.hmr(cw(i), m); - let carry_in = cw(i - 1); - if is_add { - b.x(acc[i]); - b.cz_if(acc[i], carry_in, m); - b.x(acc[i]); - } else { - b.cz_if(acc[i], carry_in, m); - } - b.free(cw(i)); - } - drop(tail); - - if free_ed { - let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); - b.reacquire(d); - b.ccx(ovf1, s2, d); - b.reacquire(e); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - } - - for i in (split + 1..=hi_delta).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let kctrl = match i { - 32 => Some(e), - 33 => Some(d), - _ => None, - }; - fold_postsum_carry_phase_uncompute( - b, - acc, - kctrl, - Some(low[i - 1]), - m, - i, - is_add, - ); - b.free(low[i]); - } - - let rev_h = b.alloc_qubit(); - let rev_xed = b.alloc_qubit(); - let rev_eord = b.alloc_qubit(); - let rev_n10 = b.alloc_qubit(); - b.ccx(e, d, rev_h); - b.cx(e, rev_xed); - b.cx(d, rev_xed); - b.cx(rev_xed, rev_eord); - b.cx(rev_h, rev_eord); - b.cx(d, rev_n10); - b.cx(rev_h, rev_n10); - let controls = - secp_fold_controls(e, d, rev_h, rev_xed, rev_eord, rev_n10, hi_delta, 32); - - if park_low > 0 { - for i in 0..park_low { - b.reacquire(low[i]); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_compute( - b, - acc, - controls.get(i).copied().flatten(), - carry_in, - low[i], - i, - is_add, - ); - } - } - - for i in (0..=split).rev() { - let m = b.alloc_bit(); - b.hmr(low[i], m); - let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; - fold_postsum_carry_phase_uncompute( - b, - acc, - controls.get(i).copied().flatten(), - carry_in, - m, - i, - is_add, - ); - b.free(low[i]); - } - drop(low); - - b.reacquire(h); - b.cx(rev_h, h); - b.reacquire(xed); - b.cx(rev_xed, xed); - b.reacquire(eord); - b.cx(rev_eord, eord); - b.reacquire(n10); - b.cx(rev_n10, n10); - - b.cx(rev_h, rev_n10); - b.cx(d, rev_n10); - b.cx(rev_h, rev_eord); - b.cx(rev_xed, rev_eord); - b.cx(d, rev_xed); - b.cx(e, rev_xed); - b.free(rev_n10); - b.free(rev_eord); - b.free(rev_xed); - let mh_rev = b.alloc_bit(); - b.hmr(rev_h, mh_rev); - b.cz_if(e, d, mh_rev); - b.free(rev_h); -} +use super::*; + +#[inline] +fn maj1_inputs_distinct(a: QubitId, k: QubitId, carry: QubitId, target: QubitId) -> bool { + a != k && a != carry && a != target && k != carry && k != target && carry != target +} + +#[inline] +fn fold_maj1_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_MAJ1").ok().as_deref() == Some("1") +} + +fn emit_fold_maj1(b: &mut B, a: QubitId, k: QubitId, carry: QubitId, target: QubitId) { + debug_assert!(maj1_inputs_distinct(a, k, carry, target)); + b.cx(carry, target); + b.cx(carry, a); + b.cx(carry, k); + b.ccx(a, k, target); + b.cx(carry, k); + b.cx(carry, a); +} + +fn emit_fold_majority( + b: &mut B, + a: QubitId, + k: QubitId, + carry: QubitId, + target: QubitId, + maj2: bool, +) { + if fold_maj1_enabled() && maj1_inputs_distinct(a, k, carry, target) { + emit_fold_maj1(b, a, k, carry, target); + } else if maj2 { + b.ccx(a, carry, target); + b.cx(a, carry); + b.ccx(k, carry, target); + b.cx(a, carry); + } else { + b.ccx(a, carry, target); + b.ccx(k, a, target); + b.ccx(k, carry, target); + } +} + +pub(crate) fn csub_nbit_const(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + + let n = acc.len(); + let a = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + sub_nbit_qq(b, &a, acc); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + b.free_vec(&a); +} + +pub(crate) fn cadd_nbit_const(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + + let n = acc.len(); + let a = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + add_nbit_qq(b, &a, acc); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + b.free_vec(&a); +} + +pub(crate) fn csub_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + let n = acc.len(); + let a = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + sub_nbit_qq_fast(b, &a, acc); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + b.free_vec(&a); +} + +pub(crate) fn csub_nbit_const_direct_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + let n = acc.len(); + if n == 0 { + return; + } + if n == 1 { + if bit(c, 0) { + b.cx(ctrl, acc[0]); + } + return; + } + + let borrows = b.alloc_qubits(n - 1); + + for i in 0..n - 1 { + let target = borrows[i]; + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if bit(c, i) { + b.x(acc[i]); + if let Some(bi) = borrow_in { + emit_fold_majority(b, acc[i], ctrl, bi, target, false); + } else { + b.ccx(acc[i], ctrl, target); + } + b.x(acc[i]); + } else if let Some(bi) = borrow_in { + b.x(acc[i]); + b.ccx(acc[i], bi, target); + b.x(acc[i]); + } + } + + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, acc[i]); + } + if i > 0 { + b.cx(borrows[i - 1], acc[i]); + } + } + + for i in (0..n - 1).rev() { + let m = b.alloc_bit(); + b.hmr(borrows[i], m); + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if bit(c, i) { + if let Some(bi) = borrow_in { + b.cz_if(acc[i], ctrl, m); + b.cz_if(acc[i], bi, m); + b.cz_if(ctrl, bi, m); + } else { + b.cz_if(acc[i], ctrl, m); + } + } else if let Some(bi) = borrow_in { + b.cz_if(acc[i], bi, m); + } + } + + b.free_vec(&borrows); +} + +pub(crate) fn cadd_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + let n = acc.len(); + let a = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + add_nbit_qq_fast(b, &a, acc); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, a[i]); + } + } + b.free_vec(&a); +} + +pub(crate) fn cadd_nbit_const_direct_fast(b: &mut B, acc: &[QubitId], c: U256, ctrl: QubitId) { + let n = acc.len(); + if n == 0 { + return; + } + if n == 1 { + if bit(c, 0) { + b.cx(ctrl, acc[0]); + } + return; + } + + let carries = b.alloc_qubits(n - 1); + + for i in 0..n - 1 { + let target = carries[i]; + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if bit(c, i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], ctrl, ci, target, false); + } else { + b.ccx(acc[i], ctrl, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } + + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, acc[i]); + } + if i > 0 { + b.cx(carries[i - 1], acc[i]); + } + } + + for i in (0..n - 1).rev() { + let m = b.alloc_bit(); + b.hmr(carries[i], m); + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if bit(c, i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + b.cz_if(acc[i], ctrl, m); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + b.cz_if(ctrl, ci, m); + } else { + b.cz_if(acc[i], ctrl, m); + b.x(acc[i]); + } + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + } + } + + b.free_vec(&carries); +} + +pub(crate) fn add_nbit_const_extcarry_clean(b: &mut B, acc_ext: &[QubitId], c: U256) { + add_nbit_const_extcarry_clean_with_cin(b, acc_ext, c, None); +} + +pub(crate) fn add_nbit_const_extcarry_clean_with_cin( + b: &mut B, + acc_ext: &[QubitId], + c: U256, + borrow_cin: Option, +) { + let ext = acc_ext.len(); + debug_assert!(ext >= 1); + let n = ext - 1; + let ca = load_const(b, n, c); + let (c_in, fresh) = match borrow_cin { + Some(q) => (q, false), + None => (b.alloc_qubit(), true), + }; + cuccaro_add_low_to_ext_clean(b, &ca, acc_ext, c_in); + if fresh { + b.free(c_in); + } + unload_const(b, &ca, c); +} + +pub(crate) fn sub_nbit_const_extcarry_clean(b: &mut B, acc_ext: &[QubitId], c: U256) { + let ext = acc_ext.len(); + debug_assert!(ext >= 1); + let n = ext - 1; + let ca = load_const(b, n, c); + let c_in = b.alloc_qubit(); + cuccaro_sub_low_to_ext_clean(b, &ca, acc_ext, c_in); + b.free(c_in); + unload_const(b, &ca, c); +} + +pub(crate) fn cadd_nbit_const_extcarry_clean( + b: &mut B, + acc_ext: &[QubitId], + c: U256, + ctrl: QubitId, +) { + let ext = acc_ext.len(); + debug_assert!(ext >= 1); + let n = ext - 1; + let ca = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, ca[i]); + } + } + let c_in = b.alloc_qubit(); + cuccaro_add_low_to_ext_clean(b, &ca, acc_ext, c_in); + b.free(c_in); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, ca[i]); + } + } + b.free_vec(&ca); +} + +pub(crate) fn csub_nbit_const_extcarry_clean( + b: &mut B, + acc_ext: &[QubitId], + c: U256, + ctrl: QubitId, +) { + csub_nbit_const_extcarry_clean_with_cin(b, acc_ext, c, ctrl, None); +} + +pub(crate) fn csub_nbit_const_extcarry_clean_with_cin( + b: &mut B, + acc_ext: &[QubitId], + c: U256, + ctrl: QubitId, + borrow_cin: Option, +) { + let ext = acc_ext.len(); + debug_assert!(ext >= 1); + let n = ext - 1; + let ca = b.alloc_qubits(n); + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, ca[i]); + } + } + let (c_in, fresh) = match borrow_cin { + Some(q) => (q, false), + None => (b.alloc_qubit(), true), + }; + cuccaro_sub_low_to_ext_clean(b, &ca, acc_ext, c_in); + if fresh { + b.free(c_in); + } + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, ca[i]); + } + } + b.free_vec(&ca); +} + +pub(crate) fn add_nbit_const_direct_uncontrolled_fast(b: &mut B, acc: &[QubitId], c: U256) { + let ctrl = b.alloc_qubit(); + b.x(ctrl); + cadd_nbit_const_direct_fast(b, acc, c, ctrl); + b.x(ctrl); + b.free(ctrl); +} + +pub(crate) fn sub_nbit_const_direct_uncontrolled_fast(b: &mut B, acc: &[QubitId], c: U256) { + let ctrl = b.alloc_qubit(); + b.x(ctrl); + csub_nbit_const_direct_fast(b, acc, c, ctrl); + b.x(ctrl); + b.free(ctrl); +} + +pub(crate) fn add_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256) { + if secp_direct_const_arith_enabled() { + add_nbit_const_direct_uncontrolled_fast(b, acc, c); + return; + } + let n = acc.len(); + let a = load_const(b, n, c); + add_nbit_qq_fast(b, &a, acc); + unload_const(b, &a, c); +} + +pub(crate) fn sub_nbit_const_fast(b: &mut B, acc: &[QubitId], c: U256) { + if secp_direct_const_arith_enabled() { + sub_nbit_const_direct_uncontrolled_fast(b, acc, c); + return; + } + let n = acc.len(); + let a = load_const(b, n, c); + sub_nbit_qq_fast(b, &a, acc); + unload_const(b, &a, c); +} + +pub(crate) fn highest_set_bit(c: U256) -> usize { + let mut hi = 0usize; + for i in 0..256 { + if bit(c, i) { + hi = i; + } + } + hi +} + +pub(crate) fn double_carry_trunc_window() -> Option { + std::env::var("KAL_DOUBLE_CARRY_TRUNC_W") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&w| w > 0) +} + +pub(crate) fn fold_carry_trunc_window() -> Option { + std::env::var("KAL_FOLD_CARRY_TRUNC_W") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&w| w > 0) +} + +pub(crate) fn perpos_maj2_enabled() -> bool { + std::env::var("DIALOG_GCD_PERPOS_MAJ2").ok().as_deref() == Some("1") +} + +pub(crate) fn fold_maj2_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_MAJ2").ok().as_deref() == Some("1") +} + +fn borrowed_const_fold_carries( + b: &mut B, + need: usize, + borrowed: &[QubitId], +) -> (Vec, Vec) { + let borrowed_len = borrowed.len().min(need); + let owned = b.alloc_qubits(need - borrowed_len); + let mut carries = Vec::with_capacity(need); + carries.extend_from_slice(&borrowed[..borrowed_len]); + carries.extend_from_slice(&owned); + (carries, owned) +} + +pub(crate) fn cadd_nbit_const_direct_trunc_fast( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, +) { + cadd_nbit_const_direct_trunc_fast_borrowed_carries(b, acc, c, ctrl, window, &[]); +} + +pub(crate) fn cadd_nbit_const_direct_trunc_fast_borrowed_carries( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + borrowed_carries: &[QubitId], +) { + let n = acc.len(); + if n == 0 { + return; + } + if n == 1 { + if bit(c, 0) { + b.cx(ctrl, acc[0]); + } + return; + } + + let hi = highest_set_bit(c); + let last = core::cmp::min(n - 2, hi.saturating_add(window)); + let maj2 = fold_maj2_enabled(); + let (carries, owned_carries) = borrowed_const_fold_carries(b, last + 1, borrowed_carries); + + for i in 0..=last { + let target = carries[i]; + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if bit(c, i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], ctrl, ci, target, maj2); + } else { + b.ccx(acc[i], ctrl, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } + + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, acc[i]); + } + if i > 0 && i - 1 <= last { + b.cx(carries[i - 1], acc[i]); + } + } + + for i in (0..=last).rev() { + let m = b.alloc_bit(); + b.hmr(carries[i], m); + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if bit(c, i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + b.cz_if(acc[i], ctrl, m); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + b.cz_if(ctrl, ci, m); + } else { + b.cz_if(acc[i], ctrl, m); + b.x(acc[i]); + } + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + } + } + + b.free_vec(&owned_carries); +} + +pub(crate) fn csub_nbit_const_direct_trunc_fast( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, +) { + csub_nbit_const_direct_trunc_fast_borrowed_carries(b, acc, c, ctrl, window, &[]); +} + +pub(crate) fn csub_nbit_const_direct_trunc_fast_borrowed_carries( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + borrowed_carries: &[QubitId], +) { + let n = acc.len(); + if n == 0 { + return; + } + if n == 1 { + if bit(c, 0) { + b.cx(ctrl, acc[0]); + } + return; + } + + let hi = highest_set_bit(c); + let last = core::cmp::min(n - 2, hi.saturating_add(window)); + let maj2 = fold_maj2_enabled(); + let (borrows, owned_borrows) = borrowed_const_fold_carries(b, last + 1, borrowed_carries); + + for i in 0..=last { + let target = borrows[i]; + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if bit(c, i) { + b.x(acc[i]); + if let Some(bi) = borrow_in { + emit_fold_majority(b, acc[i], ctrl, bi, target, maj2); + } else { + b.ccx(acc[i], ctrl, target); + } + b.x(acc[i]); + } else if let Some(bi) = borrow_in { + b.x(acc[i]); + b.ccx(acc[i], bi, target); + b.x(acc[i]); + } + } + + for i in 0..n { + if bit(c, i) { + b.cx(ctrl, acc[i]); + } + if i > 0 && i - 1 <= last { + b.cx(borrows[i - 1], acc[i]); + } + } + + for i in (0..=last).rev() { + let m = b.alloc_bit(); + b.hmr(borrows[i], m); + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if bit(c, i) { + if let Some(bi) = borrow_in { + b.cz_if(acc[i], ctrl, m); + b.cz_if(acc[i], bi, m); + b.cz_if(ctrl, bi, m); + } else { + b.cz_if(acc[i], ctrl, m); + } + } else if let Some(bi) = borrow_in { + b.cz_if(acc[i], bi, m); + } + } + + b.free_vec(&owned_borrows); +} + +fn special_fold_park_low_carries() -> usize { + std::env::var("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +fn special_fold_park_low_carries_at_step(step: Option) -> usize { + let mapped = step.and_then(|step| { + let map = + std::env::var("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES_STEP_MAP").ok()?; + map.split(',').rev().find_map(|entry| { + let (raw_step, raw_value) = entry.trim().split_once(':')?; + if raw_step.trim().parse::().ok()? != step { + return None; + } + raw_value.trim().parse::().ok() + }) + }); + mapped.unwrap_or_else(special_fold_park_low_carries) +} + +fn cconst_nbit_direct_trunc_fast_parked( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + park_low: usize, + is_add: bool, +) { + let n = acc.len(); + if n <= 1 { + if n == 1 && bit(c, 0) { + b.cx(ctrl, acc[0]); + } + return; + } + + let hi = highest_set_bit(c); + let last = core::cmp::min(n - 2, hi.saturating_add(window)); + let park_low = core::cmp::min(park_low, last.saturating_sub(hi)); + if park_low == 0 { + if is_add { + cadd_nbit_const_direct_trunc_fast(b, acc, c, ctrl, window); + } else { + csub_nbit_const_direct_trunc_fast(b, acc, c, ctrl, window); + } + return; + } + + let split = last - park_low; + let maj2 = fold_maj2_enabled(); + let prefix = b.alloc_qubits(split + 1); + let kctrl = |i: usize| bit(c, i).then_some(ctrl); + + for i in 0..=split { + let target = prefix[i]; + let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; + if is_add { + if let Some(kc) = kctrl(i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = kctrl(i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + } + + for i in 0..=split { + if let Some(kc) = kctrl(i) { + b.cx(kc, acc[i]); + } + if i > 0 { + b.cx(prefix[i - 1], acc[i]); + } + } + + for i in (0..park_low).rev() { + let measured = b.alloc_bit(); + b.hmr(prefix[i], measured); + let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + measured, + i, + is_add, + ); + b.free(prefix[i]); + } + + let tail = b.alloc_qubits(park_low); + let carry = |i: usize| { + if i <= split { + prefix[i] + } else { + tail[i - split - 1] + } + }; + for i in split + 1..=last { + let target = carry(i); + let carry_in = carry(i - 1); + if is_add { + if let Some(kc) = kctrl(i) { + emit_fold_majority(b, acc[i], kc, carry_in, target, maj2); + } else { + b.ccx(acc[i], carry_in, target); + } + } else if let Some(kc) = kctrl(i) { + b.x(acc[i]); + emit_fold_majority(b, acc[i], kc, carry_in, target, maj2); + b.x(acc[i]); + } else { + b.x(acc[i]); + b.ccx(acc[i], carry_in, target); + b.x(acc[i]); + } + } + + for i in split + 1..n { + if let Some(kc) = kctrl(i) { + b.cx(kc, acc[i]); + } + if i - 1 <= last { + b.cx(carry(i - 1), acc[i]); + } + } + + for i in (split + 1..=last).rev() { + let measured = b.alloc_bit(); + b.hmr(carry(i), measured); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(carry(i - 1)), + measured, + i, + is_add, + ); + b.free(carry(i)); + } + drop(tail); + + for i in 0..park_low { + b.reacquire(prefix[i]); + let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + carry_in, + prefix[i], + i, + is_add, + ); + } + + for i in (0..=split).rev() { + let measured = b.alloc_bit(); + b.hmr(prefix[i], measured); + let carry_in = if i == 0 { None } else { Some(prefix[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + measured, + i, + is_add, + ); + b.free(prefix[i]); + } +} + +pub(crate) fn cadd_nbit_const_direct_trunc_fast_releasing_scratch( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + releasable_scratch: &[QubitId], +) { + cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b, + acc, + c, + ctrl, + window, + releasable_scratch, + None, + ); +} + +pub(crate) fn cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + releasable_scratch: &[QubitId], + step: Option, +) { + let park_low = special_fold_park_low_carries_at_step(step); + if park_low == 0 || releasable_scratch.is_empty() { + cadd_nbit_const_direct_trunc_fast_borrowed_carries( + b, + acc, + c, + ctrl, + window, + releasable_scratch, + ); + return; + } + b.free_vec(releasable_scratch); + cconst_nbit_direct_trunc_fast_parked(b, acc, c, ctrl, window, park_low, true); + b.reacquire_vec(releasable_scratch); +} + +pub(crate) fn csub_nbit_const_direct_trunc_fast_releasing_scratch( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + releasable_scratch: &[QubitId], +) { + csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b, + acc, + c, + ctrl, + window, + releasable_scratch, + None, + ); +} + +pub(crate) fn csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b: &mut B, + acc: &[QubitId], + c: U256, + ctrl: QubitId, + window: usize, + releasable_scratch: &[QubitId], + step: Option, +) { + let park_low = special_fold_park_low_carries_at_step(step); + if park_low == 0 || releasable_scratch.is_empty() { + csub_nbit_const_direct_trunc_fast_borrowed_carries( + b, + acc, + c, + ctrl, + window, + releasable_scratch, + ); + return; + } + b.free_vec(releasable_scratch); + cconst_nbit_direct_trunc_fast_parked(b, acc, c, ctrl, window, park_low, false); + b.reacquire_vec(releasable_scratch); +} + +pub(crate) fn cadd_per_position_controls_trunc( + b: &mut B, + acc: &[QubitId], + controls: &[Option], + last: usize, +) { + let n = acc.len(); + debug_assert!(last < n); + debug_assert!(controls.len() <= n); + let kctrl = |i: usize| -> Option { + if i < controls.len() { + controls[i] + } else { + None + } + }; + let maj2 = perpos_maj2_enabled(); + let carries = b.alloc_qubits(last + 1); + + for i in 0..=last { + let target = carries[i]; + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if let Some(kc) = kctrl(i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } + + for i in 0..n { + if let Some(kc) = kctrl(i) { + b.cx(kc, acc[i]); + } + if i > 0 && i - 1 <= last { + b.cx(carries[i - 1], acc[i]); + } + } + + for i in (0..=last).rev() { + let m = b.alloc_bit(); + b.hmr(carries[i], m); + let carry_in = if i == 0 { None } else { Some(carries[i - 1]) }; + if let Some(kc) = kctrl(i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + b.cz_if(acc[i], kc, m); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + b.cz_if(kc, ci, m); + } else { + b.cz_if(acc[i], kc, m); + b.x(acc[i]); + } + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.cz_if(acc[i], ci, m); + b.x(acc[i]); + } + } + + b.free_vec(&carries); +} + +pub(crate) fn csub_per_position_controls_trunc( + b: &mut B, + acc: &[QubitId], + controls: &[Option], + last: usize, +) { + let n = acc.len(); + debug_assert!(last < n); + debug_assert!(controls.len() <= n); + let kctrl = |i: usize| -> Option { + if i < controls.len() { + controls[i] + } else { + None + } + }; + let maj2 = perpos_maj2_enabled(); + let borrows = b.alloc_qubits(last + 1); + + for i in 0..=last { + let target = borrows[i]; + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if let Some(kc) = kctrl(i) { + b.x(acc[i]); + if let Some(bi) = borrow_in { + emit_fold_majority(b, acc[i], kc, bi, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(bi) = borrow_in { + b.x(acc[i]); + b.ccx(acc[i], bi, target); + b.x(acc[i]); + } + } + + for i in 0..n { + if let Some(kc) = kctrl(i) { + b.cx(kc, acc[i]); + } + if i > 0 && i - 1 <= last { + b.cx(borrows[i - 1], acc[i]); + } + } + + for i in (0..=last).rev() { + let m = b.alloc_bit(); + b.hmr(borrows[i], m); + let borrow_in = if i == 0 { None } else { Some(borrows[i - 1]) }; + if let Some(kc) = kctrl(i) { + if let Some(bi) = borrow_in { + b.cz_if(acc[i], kc, m); + b.cz_if(acc[i], bi, m); + b.cz_if(kc, bi, m); + } else { + b.cz_if(acc[i], kc, m); + } + } else if let Some(bi) = borrow_in { + b.cz_if(acc[i], bi, m); + } + } + + b.free_vec(&borrows); +} + +pub(crate) fn fold_freed_tail_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_FREED_TAIL").ok().as_deref() == Some("1") +} + +pub(crate) fn fold_freed_tail_ed_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_FREED_TAIL_ED") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn fold_host_derived_controls_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_DERIVED_CONTROLS") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_n10_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_N10") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_h_n10_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_H_N10") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_h_xed_n10_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_H_XED_N10") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_e_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_E") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_d_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_D") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn fold_only_carry_trunc_window() -> Option { + std::env::var("DIALOG_GCD_FOLD_CARRY_TRUNC_W") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&w| w > 0) +} + +fn fold_park_low_carries() -> usize { + std::env::var("DIALOG_GCD_FOLD_PARK_LOW_CARRIES") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +pub(crate) fn fold_park_low_carries_at_step(step: Option) -> usize { + let mapped = step.and_then(|step| { + let map = std::env::var("DIALOG_GCD_FOLD_PARK_LOW_CARRIES_STEP_MAP").ok()?; + map.split(',').rev().find_map(|entry| { + let (raw_step, raw_value) = entry.trim().split_once(':')?; + if raw_step.trim().parse::().ok()? != step { + return None; + } + raw_value.trim().parse::().ok() + }) + }); + mapped.unwrap_or_else(fold_park_low_carries) +} + +pub(crate) fn fold_stream_controls_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_STREAM_CONTROLS") + .ok() + .as_deref() + == Some("1") + && fold_park_low_carries() >= 12 +} + +fn fold_host_streamed_control_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_STREAMED_CONTROL") + .ok() + .as_deref() + == Some("1") + && fold_park_low_carries() >= 13 +} + +fn fold_host_e_top_carry_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_E_TOP_CARRY") + .ok() + .as_deref() + == Some("1") +} + +fn fold_host_d_carry12_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_D_CARRY12") + .ok() + .as_deref() + == Some("1") + && fold_park_low_carries() >= 14 +} + +fn fold_host_ovf2_carry13_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_HOST_OVF2_CARRY13") + .ok() + .as_deref() + == Some("1") + && fold_park_low_carries() >= 15 +} + +fn fold_free_first_high_carry_enabled() -> bool { + std::env::var("DIALOG_GCD_FOLD_FREE_FIRST_HIGH_CARRY") + .ok() + .as_deref() + == Some("1") +} + +fn fold_stream_profile_phase(b: &mut B, add_phase: &'static str, sub_phase: &'static str, is_add: bool) { + if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { + b.set_phase(if is_add { add_phase } else { sub_phase }); + } +} + +fn fold_postsum_carry_phase_uncompute( + b: &mut B, + acc: &[QubitId], + kctrl: Option, + carry_in: Option, + measured: BitId, + i: usize, + is_add: bool, +) { + if is_add { + if let Some(kc) = kctrl { + b.x(acc[i]); + if let Some(ci) = carry_in { + b.cz_if(acc[i], kc, measured); + b.cz_if(acc[i], ci, measured); + b.x(acc[i]); + b.cz_if(kc, ci, measured); + } else { + b.cz_if(acc[i], kc, measured); + b.x(acc[i]); + } + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.cz_if(acc[i], ci, measured); + b.x(acc[i]); + } + } else if let Some(kc) = kctrl { + if let Some(ci) = carry_in { + b.cz_if(acc[i], kc, measured); + b.cz_if(acc[i], ci, measured); + b.cz_if(kc, ci, measured); + } else { + b.cz_if(acc[i], kc, measured); + } + } else if let Some(ci) = carry_in { + b.cz_if(acc[i], ci, measured); + } +} + +fn fold_postsum_carry_compute( + b: &mut B, + acc: &[QubitId], + kctrl: Option, + carry_in: Option, + target: QubitId, + i: usize, + is_add: bool, +) { + if is_add { + if let Some(kc) = kctrl { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority( + b, + acc[i], + kc, + ci, + target, + perpos_maj2_enabled(), + ); + b.x(acc[i]); + } else { + b.ccx(acc[i], kc, target); + b.x(acc[i]); + } + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + } else if let Some(kc) = kctrl { + if let Some(ci) = carry_in { + emit_fold_majority( + b, + acc[i], + kc, + ci, + target, + perpos_maj2_enabled(), + ); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } +} + +fn fold_presum_carry_compute_and_sum( + b: &mut B, + acc: &[QubitId], + kctrl: Option, + carry_in: Option, + target: QubitId, + i: usize, + is_add: bool, + maj2: bool, +) { + if is_add { + if let Some(kc) = kctrl { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = kctrl { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + if let Some(kc) = kctrl { + b.cx(kc, acc[i]); + } + if let Some(ci) = carry_in { + b.cx(ci, acc[i]); + } +} + +pub(crate) fn secp_fold_controls( + e: QubitId, + d: QubitId, + h: QubitId, + xed: QubitId, + eord: QubitId, + n10: QubitId, + hi_delta: usize, + hi_c: usize, +) -> Vec> { + let mut controls: Vec> = vec![None; hi_delta + 1]; + controls[0] = Some(e); + controls[1] = Some(d); + controls[4] = Some(e); + controls[5] = Some(d); + controls[6] = Some(e); + controls[7] = Some(xed); + controls[8] = Some(eord); + controls[9] = Some(eord); + controls[10] = Some(n10); + controls[11] = Some(h); + controls[hi_c] = Some(e); + controls[hi_delta] = Some(d); + controls +} + +pub(crate) fn fold_ripple_freed_tail( + b: &mut B, + acc: &[QubitId], + e: QubitId, + d: QubitId, + h: QubitId, + xed: QubitId, + eord: QubitId, + n10: QubitId, + last: usize, + is_add: bool, +) { + + fold_ripple_freed_tail_ed( + b, acc, e, d, h, xed, eord, n10, None, None, last, is_add, + ); +} + +pub(crate) fn fold_ripple_freed_tail_ed_streamed( + b: &mut B, + acc: &[QubitId], + e: QubitId, + d: QubitId, + ed: Option<(QubitId, QubitId, QubitId)>, + park_low: usize, + last: usize, + is_add: bool, +) { + let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); + let n = acc.len(); + let hi_delta = 33usize; + debug_assert!(last < n); + debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); + let park_low = core::cmp::min(park_low, hi_delta); + assert!( + park_low >= 12, + "streamed fold controls require at least 12 parked carries" + ); + let host_streamed = fold_host_streamed_control_enabled(); + let host_e_top = free_ed && fold_host_e_top_carry_enabled(); + let host_d_carry12 = + host_e_top && fold_host_d_carry12_enabled(); + let host_ovf2_carry13 = + host_d_carry12 && fold_host_ovf2_carry13_enabled(); + let maj2 = perpos_maj2_enabled(); + let kctrl = |i: usize| match i { + 0 | 4 | 6 | 32 => Some(e), + 1 | 5 | 33 => Some(d), + _ => None, + }; + fold_stream_profile_phase( + b, + "dialog_gcd_streamed_double_active", + "dialog_gcd_streamed_halve_active", + is_add, + ); + let low_chain_last = if host_e_top { + hi_delta - 1 + } else { + hi_delta + }; + let mut low = b.alloc_qubits( + low_chain_last + 1 + - usize::from(host_d_carry12) + - usize::from(host_ovf2_carry13), + ); + if host_d_carry12 { + low.insert(12, d); + } + if host_ovf2_carry13 { + let (_, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); + low.insert(13, ovf2); + let (ovf1, _, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); + b.cx(ovf1, ovf2); + b.cx(d, ovf2); + b.cx(e, ovf2); + } + let streamed_slot = low[park_low - 1]; + + for i in 0..7 { + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_presum_carry_compute_and_sum( + b, + acc, + kctrl(i), + carry_in, + low[i], + i, + is_add, + maj2, + ); + } + let streamed = if host_streamed { + streamed_slot + } else { + b.alloc_qubit() + }; + b.cx(e, streamed); + b.cx(d, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[6]), + low[7], + 7, + is_add, + maj2, + ); + b.ccx(e, d, streamed); + for i in 8..10 { + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[i - 1]), + low[i], + i, + is_add, + maj2, + ); + } + b.cx(e, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[9]), + low[10], + 10, + is_add, + maj2, + ); + b.cx(d, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[10]), + low[11], + 11, + is_add, + maj2, + ); + if host_streamed { + b.ccx(e, d, streamed); + } + if host_d_carry12 { + let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); + b.ccx(ovf1, s2, d); + } + for i in 12..=low_chain_last { + fold_presum_carry_compute_and_sum( + b, + acc, + kctrl(i), + Some(low[i - 1]), + low[i], + i, + is_add, + maj2, + ); + } + + let free_first_high_carry = fold_free_first_high_carry_enabled() + && park_low < low_chain_last + && !(host_d_carry12 && park_low == 12) + && !(host_ovf2_carry13 && park_low == 13); + if free_first_high_carry { + let m = b.alloc_bit(); + b.hmr(low[park_low], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(park_low), + Some(low[park_low - 1]), + m, + park_low, + is_add, + ); + b.free(low[park_low]); + } + + for i in (12..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + if host_d_carry12 { + let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); + b.reacquire(d); + b.ccx(ovf1, s2, d); + } + if host_streamed { + b.reacquire(streamed); + b.ccx(e, d, streamed); + } + let m11 = b.alloc_bit(); + b.hmr(low[11], m11); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[10]), + m11, + 11, + is_add, + ); + b.free(low[11]); + b.cx(d, streamed); + let m10 = b.alloc_bit(); + b.hmr(low[10], m10); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[9]), + m10, + 10, + is_add, + ); + b.free(low[10]); + b.cx(e, streamed); + for i in (8..10).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + b.ccx(e, d, streamed); + let m7 = b.alloc_bit(); + b.hmr(low[7], m7); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[6]), + m7, + 7, + is_add, + ); + b.free(low[7]); + b.cx(d, streamed); + b.cx(e, streamed); + b.free(streamed); + for i in (0..7).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + + if host_ovf2_carry13 { + let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); + b.reacquire(ovf2); + b.cx(ovf1, ovf2); + b.cx(d, ovf2); + b.cx(e, ovf2); + } + + if host_e_top { + let (ovf1, ovf2, _) = ed.expect("host_e_top implies ed is Some"); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(d), + Some(low[hi_delta - 1]), + e, + hi_delta, + is_add, + maj2, + ); + } + + if free_ed { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + if !host_e_top { + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.free(e); + } + let md = b.alloc_bit(); + b.hmr(d, md); + b.cz_if(ovf1, s2, md); + b.free(d); + } + + fold_stream_profile_phase( + b, + "dialog_gcd_streamed_double_tail", + "dialog_gcd_streamed_halve_tail", + is_add, + ); + let tail_len = last - hi_delta; + let tail = b.alloc_qubits(tail_len); + let cw = |i: usize| -> QubitId { + if i < hi_delta { + low[i] + } else if i == hi_delta { + if host_e_top { + e + } else { + low[i] + } + } else { + tail[i - hi_delta - 1] + } + }; + for i in hi_delta + 1..=last { + if is_add { + b.ccx(acc[i], cw(i - 1), cw(i)); + } else { + b.x(acc[i]); + b.ccx(acc[i], cw(i - 1), cw(i)); + b.x(acc[i]); + } + } + for i in hi_delta + 1..n { + if i - 1 <= last { + b.cx(cw(i - 1), acc[i]); + } + } + for i in (hi_delta + 1..=last).rev() { + let m = b.alloc_bit(); + b.hmr(cw(i), m); + let carry_in = cw(i - 1); + if is_add { + b.x(acc[i]); + b.cz_if(acc[i], carry_in, m); + b.x(acc[i]); + } else { + b.cz_if(acc[i], carry_in, m); + } + b.free(cw(i)); + } + drop(tail); + + fold_stream_profile_phase( + b, + "dialog_gcd_streamed_double_reverse", + "dialog_gcd_streamed_halve_reverse", + is_add, + ); + if free_ed { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + b.reacquire(d); + b.ccx(ovf1, s2, d); + if host_e_top { + let m_top = b.alloc_bit(); + b.hmr(e, m_top); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(d), + Some(low[hi_delta - 1]), + m_top, + hi_delta, + is_add, + ); + b.free(e); + } + b.reacquire(e); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + } + if host_ovf2_carry13 { + let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); + b.cx(ovf1, ovf2); + b.cx(d, ovf2); + b.cx(e, ovf2); + } + + for i in 0..park_low { + if !(host_d_carry12 && i == 12) + && !(host_ovf2_carry13 && i == 13) + { + b.reacquire(low[i]); + } + } + for i in 0..7 { + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + carry_in, + low[i], + i, + is_add, + ); + } + let streamed = if host_streamed { + streamed_slot + } else { + b.alloc_qubit() + }; + b.cx(e, streamed); + b.cx(d, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[6]), + low[7], + 7, + is_add, + ); + b.ccx(e, d, streamed); + for i in 8..10 { + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + low[i], + i, + is_add, + ); + } + b.cx(e, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[9]), + low[10], + 10, + is_add, + ); + b.cx(d, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[10]), + low[11], + 11, + is_add, + ); + if host_streamed { + b.ccx(e, d, streamed); + } + if host_d_carry12 { + let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); + b.ccx(ovf1, s2, d); + } + for i in 12..park_low { + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + low[i], + i, + is_add, + ); + } + if free_first_high_carry { + b.reacquire(low[park_low]); + fold_postsum_carry_compute( + b, + acc, + kctrl(park_low), + Some(low[park_low - 1]), + low[park_low], + park_low, + is_add, + ); + } + + for i in (12..=low_chain_last).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + if host_d_carry12 { + let (ovf1, _, s2) = ed.expect("host_d_carry12 implies ed is Some"); + b.reacquire(d); + b.ccx(ovf1, s2, d); + } + if host_ovf2_carry13 { + let (ovf1, ovf2, _) = ed.expect("host_ovf2_carry13 implies ed is Some"); + b.reacquire(ovf2); + b.cx(ovf1, ovf2); + b.cx(d, ovf2); + b.cx(e, ovf2); + } + if host_streamed { + b.reacquire(streamed); + b.ccx(e, d, streamed); + } + let m11 = b.alloc_bit(); + b.hmr(low[11], m11); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[10]), + m11, + 11, + is_add, + ); + b.free(low[11]); + b.cx(d, streamed); + let m10 = b.alloc_bit(); + b.hmr(low[10], m10); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[9]), + m10, + 10, + is_add, + ); + b.free(low[10]); + b.cx(e, streamed); + for i in (8..10).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + b.ccx(e, d, streamed); + let m7 = b.alloc_bit(); + b.hmr(low[7], m7); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[6]), + m7, + 7, + is_add, + ); + b.free(low[7]); + b.cx(d, streamed); + b.cx(e, streamed); + b.free(streamed); + for i in (0..7).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + drop(low); +} + +pub(crate) fn fold_ripple_freed_tail_ed( + b: &mut B, + acc: &[QubitId], + e: QubitId, + d: QubitId, + h: QubitId, + xed: QubitId, + eord: QubitId, + n10: QubitId, + ed: Option<(QubitId, QubitId, QubitId)>, + step: Option, + last: usize, + is_add: bool, +) { + let configured_park_low = fold_park_low_carries_at_step(step); + if fold_host_derived_controls_enabled() && configured_park_low <= 7 { + fold_ripple_freed_tail_ed_hosted( + b, + acc, + e, + d, + h, + xed, + eord, + n10, + ed, + configured_park_low, + last, + is_add, + ); + return; + } + if fold_stream_controls_enabled() && configured_park_low >= 12 { + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(n10); + b.free(eord); + b.free(xed); + let mh = b.alloc_bit(); + b.hmr(h, mh); + b.cz_if(e, d, mh); + b.free(h); + fold_ripple_freed_tail_ed_streamed( + b, + acc, + e, + d, + ed, + configured_park_low, + last, + is_add, + ); + b.reacquire(h); + b.ccx(e, d, h); + b.reacquire(xed); + b.cx(e, xed); + b.cx(d, xed); + b.reacquire(eord); + b.cx(xed, eord); + b.cx(h, eord); + b.reacquire(n10); + b.cx(d, n10); + b.cx(h, n10); + return; + } + + let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); + let n = acc.len(); + let hi_delta = 33usize; + let hi_c = 32usize; + debug_assert!(last < n); + debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); + let controls = secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); + let kctrl = |i: usize| controls.get(i).copied().flatten(); + let maj2 = perpos_maj2_enabled(); + let park_low = core::cmp::min(configured_park_low, hi_delta); + let host_all_derived = fold_host_derived_controls_enabled() && park_low >= 15; + let host_h_xed_n10 = + (fold_host_h_xed_n10_enabled() || host_all_derived) && park_low >= 14; + let host_h_n10 = + (fold_host_h_n10_enabled() || host_h_xed_n10) && park_low >= 13; + let host_xed = host_h_xed_n10; + let host_eord = host_all_derived; + let host_e = fold_host_e_enabled() && host_all_derived && free_ed && park_low >= 17; + let host_d = fold_host_d_enabled() && host_e && park_low >= 18; + let host_n10 = (fold_host_n10_enabled() || host_h_n10) && park_low >= 12; + let stream_controls = + fold_stream_controls_enabled() && park_low >= 12 && !host_n10; + + if stream_controls { + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(n10); + b.free(eord); + b.free(xed); + let mh = b.alloc_bit(); + b.hmr(h, mh); + b.cz_if(e, d, mh); + b.free(h); + } + + let low = if host_h_n10 { + b.cx(h, n10); + b.cx(d, n10); + b.free(n10); + if host_eord { + b.cx(h, eord); + b.cx(xed, eord); + b.free(eord); + } + if host_xed { + b.cx(d, xed); + b.cx(e, xed); + b.free(xed); + } + b.ccx(e, d, h); + b.free(h); + if host_e { + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.free(e); + } + + let d_slot = host_d.then_some(d); + let e_slot = if host_e { + let slot = b.alloc_qubit(); + debug_assert_eq!(slot, e); + Some(slot) + } else { + None + }; + let h_slot = b.alloc_qubit(); + debug_assert_eq!(h_slot, h); + let xed_slot = if host_xed { + let slot = b.alloc_qubit(); + debug_assert_eq!(slot, xed); + Some(slot) + } else { + None + }; + let eord_slot = if host_eord { + let slot = b.alloc_qubit(); + debug_assert_eq!(slot, eord); + Some(slot) + } else { + None + }; + let n10_slot = b.alloc_qubit(); + debug_assert_eq!(n10_slot, n10); + let regular = b.alloc_qubits( + hi_delta + - 1 + - usize::from(host_xed) + - usize::from(host_eord) + - usize::from(host_e) + - usize::from(host_d), + ); + let mut low = Vec::with_capacity(hi_delta + 1); + let mut next_regular = 0usize; + for i in 0..=hi_delta { + if i == 28 && host_d { + low.push(n10_slot); + } else if i == 29 && host_d { + low.push(d_slot.expect("hosted d slot")); + } else if i == 29 && host_e { + low.push(n10_slot); + } else if i == 30 { + low.push(h_slot); + } else if i == 31 && host_xed { + low.push(xed_slot.expect("hosted xed slot")); + } else if i == 32 && host_eord { + low.push(eord_slot.expect("hosted eord slot")); + } else if i == hi_delta { + low.push(e_slot.unwrap_or(n10_slot)); + } else { + low.push(regular[next_regular]); + next_regular += 1; + } + } + debug_assert_eq!(next_regular, regular.len()); + low + } else if host_n10 { + b.cx(h, n10); + b.cx(d, n10); + b.free(n10); + let n10_slot = b.alloc_qubit(); + debug_assert_eq!(n10_slot, n10); + let mut low = b.alloc_qubits(hi_delta); + low.push(n10_slot); + low + } else { + b.alloc_qubits(hi_delta + 1) + }; + + let mut tail_d = None; + let mut streamed_forward = None; + if host_h_n10 { + + let e_host = host_e.then_some(low[hi_delta]); + let h_host = low[30]; + let xed_host = host_xed.then_some(low[31]); + let eord_host = host_eord.then_some(low[32]); + let d_host = host_d.then_some(low[29]); + let n10_host = if host_d { + low[28] + } else if host_e { + low[29] + } else { + low[hi_delta] + }; + let e_ctrl = e_host.unwrap_or(e); + let d_ctrl = d_host.unwrap_or(d); + if let Some(e_host) = e_host { + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + b.cx(ovf1, e_host); + b.cx(d_ctrl, e_host); + b.cx(ovf2, e_host); + } + b.ccx(e_ctrl, d_ctrl, h_host); + if let Some(xed_host) = xed_host { + b.cx(e_ctrl, xed_host); + b.cx(d_ctrl, xed_host); + } + if let Some(eord_host) = eord_host { + b.cx(xed_host.expect("hosted xed for eord"), eord_host); + b.cx(h_host, eord_host); + } + b.cx(d_ctrl, n10_host); + b.cx(h_host, n10_host); + for i in 0..=hi_delta { + if (host_d && i == 28) + || (!host_d && host_e && i == 29) + || (!host_e && i == 30) + { + b.cx(h_host, n10_host); + b.cx(d_ctrl, n10_host); + if let Some(eord_host) = eord_host { + b.cx(h_host, eord_host); + b.cx(xed_host.expect("hosted xed for eord"), eord_host); + } + if let Some(xed_host) = xed_host { + b.cx(d_ctrl, xed_host); + b.cx(e_ctrl, xed_host); + } + b.ccx(e_ctrl, d_ctrl, h_host); + } + if host_d && i == 29 { + let (ovf1, _, s2) = ed.expect("host_d requires overflow controls"); + b.ccx(ovf1, s2, d_ctrl); + } + if host_e && i == hi_delta { + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + b.cx(ovf2, e_ctrl); + if host_d { + b.cx(tail_d.expect("tail d is live at bit 33"), e_ctrl); + } else { + b.cx(d_ctrl, e_ctrl); + } + b.cx(ovf1, e_ctrl); + } + let target = low[i]; + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + let kc = match i { + 0 | 4 | 6 | 32 if host_e => Some(e_ctrl), + 1 | 5 if host_d => d_host, + 7 if host_xed => xed_host, + 8 | 9 if host_eord => eord_host, + 10 => Some(n10_host), + 11 => Some(h_host), + 33 if host_d => tail_d, + _ => kctrl(i), + }; + if is_add { + if let Some(kc) = kc { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = kc { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + if let Some(kc) = kc { + b.cx(kc, acc[i]); + } + if i > 0 { + b.cx(low[i - 1], acc[i]); + } + if host_d && i == hi_delta - 1 { + + let measured = b.alloc_bit(); + b.hmr(low[31], measured); + fold_postsum_carry_phase_uncompute( + b, + acc, + None, + Some(low[30]), + measured, + 31, + is_add, + ); + b.free(low[31]); + let slot = b.alloc_qubit(); + debug_assert_eq!(slot, low[31]); + let (ovf1, _, s2) = ed.expect("host_d requires overflow controls"); + b.ccx(ovf1, s2, slot); + tail_d = Some(slot); + } + } + } else if host_n10 { + + let n10_host = low[hi_delta]; + b.cx(d, n10_host); + b.cx(h, n10_host); + for i in 0..=hi_delta { + if i == hi_delta { + b.cx(h, n10_host); + b.cx(d, n10_host); + } + let target = low[i]; + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + let kc = if i == 10 { Some(n10_host) } else { kctrl(i) }; + if is_add { + if let Some(kc) = kc { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = kc { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + if let Some(kc) = kc { + b.cx(kc, acc[i]); + } + if i > 0 { + b.cx(low[i - 1], acc[i]); + } + } + } else if stream_controls { + for i in 0..7 { + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_presum_carry_compute_and_sum( + b, + acc, + kctrl(i), + carry_in, + low[i], + i, + is_add, + maj2, + ); + } + let streamed = b.alloc_qubit(); + b.cx(e, streamed); + b.cx(d, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[6]), + low[7], + 7, + is_add, + maj2, + ); + b.ccx(e, d, streamed); + for i in 8..10 { + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[i - 1]), + low[i], + i, + is_add, + maj2, + ); + } + b.cx(e, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[9]), + low[10], + 10, + is_add, + maj2, + ); + b.cx(d, streamed); + fold_presum_carry_compute_and_sum( + b, + acc, + Some(streamed), + Some(low[10]), + low[11], + 11, + is_add, + maj2, + ); + for i in 12..=hi_delta { + fold_presum_carry_compute_and_sum( + b, + acc, + kctrl(i), + Some(low[i - 1]), + low[i], + i, + is_add, + maj2, + ); + } + streamed_forward = Some(streamed); + } else { + for i in 0..=hi_delta { + let target = low[i]; + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + if is_add { + if let Some(kc) = kctrl(i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = kctrl(i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + } + + for i in 0..=hi_delta { + if let Some(kc) = kctrl(i) { + b.cx(kc, acc[i]); + } + if i > 0 { + b.cx(low[i - 1], acc[i]); + } + } + } + + if park_low > 0 { + if host_h_n10 { + for i in (12..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + + let d_ctrl = if host_d { + tail_d.expect("tail d is live during parked-carry cleanup") + } else { + d + }; + let rev_e = if host_e { + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + let rev_e = b.alloc_qubit(); + b.cx(ovf1, rev_e); + b.cx(d_ctrl, rev_e); + b.cx(ovf2, rev_e); + Some(rev_e) + } else { + None + }; + let e_ctrl = rev_e.unwrap_or(e); + let rev_h = b.alloc_qubit(); + b.ccx(e_ctrl, d_ctrl, rev_h); + let measured_h = b.alloc_bit(); + b.hmr(low[11], measured_h); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(rev_h), + Some(low[10]), + measured_h, + 11, + is_add, + ); + b.free(low[11]); + + let rev_n10 = b.alloc_qubit(); + debug_assert_eq!(rev_n10, low[11]); + b.cx(d_ctrl, rev_n10); + b.cx(rev_h, rev_n10); + let measured_n10 = b.alloc_bit(); + b.hmr(low[10], measured_n10); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(rev_n10), + Some(low[9]), + measured_n10, + 10, + is_add, + ); + b.free(low[10]); + b.cx(rev_h, rev_n10); + b.cx(d_ctrl, rev_n10); + b.free(rev_n10); + + let rev_xed = if host_xed { + let rev_xed = b.alloc_qubit(); + b.cx(e_ctrl, rev_xed); + b.cx(d_ctrl, rev_xed); + Some(rev_xed) + } else { + None + }; + let rev_eord = if host_eord { + let rev_eord = b.alloc_qubit(); + b.cx(rev_xed.expect("hosted xed for eord"), rev_eord); + b.cx(rev_h, rev_eord); + Some(rev_eord) + } else { + None + }; + if !host_xed { + b.ccx(e, d, rev_h); + b.free(rev_h); + } + for i in (0..10).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + let kc = match i { + 0 | 4 | 6 if host_e => rev_e, + 1 | 5 if host_d => Some(d_ctrl), + 7 if host_xed => rev_xed, + 8 | 9 if host_eord => rev_eord, + _ => kctrl(i), + }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kc, + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + if let Some(rev_eord) = rev_eord { + b.cx(rev_h, rev_eord); + b.cx(rev_xed.expect("hosted xed for eord"), rev_eord); + b.free(rev_eord); + } + if let Some(rev_xed) = rev_xed { + b.cx(d_ctrl, rev_xed); + b.cx(e_ctrl, rev_xed); + b.free(rev_xed); + } + if host_xed { + b.ccx(e_ctrl, d_ctrl, rev_h); + b.free(rev_h); + } + if let Some(rev_e) = rev_e { + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + b.cx(ovf2, rev_e); + b.cx(d_ctrl, rev_e); + b.cx(ovf1, rev_e); + b.free(rev_e); + } + } else if host_n10 { + for i in (11..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + let rev_n10 = b.alloc_qubit(); + b.cx(d, rev_n10); + b.cx(h, rev_n10); + for i in (0..11).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + let kc = if i == 10 { Some(rev_n10) } else { kctrl(i) }; + fold_postsum_carry_phase_uncompute( + b, acc, kc, carry_in, m, i, is_add, + ); + b.free(low[i]); + } + b.cx(h, rev_n10); + b.cx(d, rev_n10); + b.free(rev_n10); + } else if stream_controls { + let streamed = streamed_forward + .take() + .expect("streamed forward control is live"); + for i in (12..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + let m11 = b.alloc_bit(); + b.hmr(low[11], m11); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[10]), + m11, + 11, + is_add, + ); + b.free(low[11]); + b.cx(d, streamed); + let m10 = b.alloc_bit(); + b.hmr(low[10], m10); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[9]), + m10, + 10, + is_add, + ); + b.free(low[10]); + b.cx(e, streamed); + for i in (8..10).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + b.ccx(e, d, streamed); + let m7 = b.alloc_bit(); + b.hmr(low[7], m7); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[6]), + m7, + 7, + is_add, + ); + b.free(low[7]); + b.cx(d, streamed); + b.cx(e, streamed); + b.free(streamed); + for i in (0..7).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + } else { + for i in (0..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + } + } + debug_assert!(streamed_forward.is_none()); + + if !stream_controls { + if !host_n10 { + b.cx(h, n10); + b.cx(d, n10); + b.free(n10); + } + if !host_eord { + if host_h_n10 { + let rev_h = b.alloc_qubit(); + b.ccx(e, d, rev_h); + b.cx(rev_h, eord); + b.ccx(e, d, rev_h); + b.free(rev_h); + } else { + b.cx(h, eord); + } + if host_xed { + let rev_xed = b.alloc_qubit(); + b.cx(e, rev_xed); + b.cx(d, rev_xed); + b.cx(rev_xed, eord); + b.cx(d, rev_xed); + b.cx(e, rev_xed); + b.free(rev_xed); + } else { + b.cx(xed, eord); + } + b.free(eord); + } + if !host_xed { + b.cx(d, xed); + b.cx(e, xed); + b.free(xed); + } + if !host_h_n10 { + let mh = b.alloc_bit(); + b.hmr(h, mh); + b.cz_if(e, d, mh); + b.free(h); + } + } + + if free_ed { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + if !host_e { + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.free(e); + } + if !host_d { + let md = b.alloc_bit(); + b.hmr(d, md); + b.cz_if(ovf1, s2, md); + b.free(d); + } + } + + let tail_len = last - hi_delta; + let tail = b.alloc_qubits(tail_len); + let cw = |i: usize| -> QubitId { + if i <= hi_delta { + low[i] + } else { + tail[i - hi_delta - 1] + } + }; + + for i in (hi_delta + 1)..=last { + if is_add { + b.ccx(acc[i], cw(i - 1), cw(i)); + } else { + b.x(acc[i]); + b.ccx(acc[i], cw(i - 1), cw(i)); + b.x(acc[i]); + } + } + + for i in (hi_delta + 1)..n { + if i - 1 <= last { + b.cx(cw(i - 1), acc[i]); + } + } + + for i in (hi_delta + 1..=last).rev() { + let m = b.alloc_bit(); + b.hmr(cw(i), m); + let carry_in = cw(i - 1); + if is_add { + b.x(acc[i]); + b.cz_if(acc[i], carry_in, m); + b.x(acc[i]); + } else { + b.cz_if(acc[i], carry_in, m); + } + b.free(cw(i)); + } + drop(tail); + + if free_ed && !host_d { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + b.reacquire(d); + b.ccx(ovf1, s2, d); + if !host_e { + b.reacquire(e); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + } + } + if host_h_n10 { + if host_e { + let measured = b.alloc_bit(); + b.hmr(low[hi_delta], measured); + if host_d { + fold_postsum_carry_phase_uncompute( + b, + acc, + tail_d, + Some(low[hi_delta - 1]), + measured, + hi_delta, + is_add, + ); + } else { + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(d), + Some(low[hi_delta - 1]), + measured, + hi_delta, + is_add, + ); + } + b.free(low[hi_delta]); + let (ovf1, ovf2, _) = ed.expect("host_e requires overflow controls"); + b.reacquire(e); + b.cx(ovf1, e); + if host_d { + b.cx(tail_d.expect("tail d is live while restoring e"), e); + } else { + b.cx(d, e); + } + b.cx(ovf2, e); + } + if host_d { + + let carry31 = b.alloc_qubit(); + fold_postsum_carry_compute( + b, + acc, + None, + Some(low[30]), + carry31, + 31, + is_add, + ); + let measured32 = b.alloc_bit(); + b.hmr(low[32], measured32); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(e), + Some(carry31), + measured32, + 32, + is_add, + ); + b.free(low[32]); + let measured31 = b.alloc_bit(); + b.hmr(carry31, measured31); + fold_postsum_carry_phase_uncompute( + b, + acc, + None, + Some(low[30]), + measured31, + 31, + is_add, + ); + b.free(carry31); + + for i in (28..=30).rev() { + let measured = b.alloc_bit(); + b.hmr(low[i], measured); + fold_postsum_carry_phase_uncompute( + b, + acc, + None, + Some(low[i - 1]), + measured, + i, + is_add, + ); + b.free(low[i]); + } + + let d_tail = tail_d.expect("tail d is live during d restoration"); + b.reacquire(d); + b.cx(d_tail, d); + b.cx(d, d_tail); + b.free(d_tail); + } else { + let high_start = if host_e { 29 } else { 30 }; + let high_end = if host_e { hi_delta - 1 } else { hi_delta }; + for i in (high_start..=high_end).rev() { + let measured = b.alloc_bit(); + b.hmr(low[i], measured); + let kc = match i { + 32 => Some(e), + 33 => Some(d), + _ => None, + }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kc, + Some(low[i - 1]), + measured, + i, + is_add, + ); + b.free(low[i]); + } + } + } else if host_n10 { + let measured = b.alloc_bit(); + b.hmr(low[hi_delta], measured); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(d), + Some(low[hi_delta - 1]), + measured, + hi_delta, + is_add, + ); + b.free(low[hi_delta]); + } + if stream_controls { + for i in 0..park_low { + b.reacquire(low[i]); + } + + for i in 0..7 { + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + carry_in, + low[i], + i, + is_add, + ); + } + + let streamed = b.alloc_qubit(); + b.cx(e, streamed); + b.cx(d, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[6]), + low[7], + 7, + is_add, + ); + b.ccx(e, d, streamed); + for i in 8..10 { + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + low[i], + i, + is_add, + ); + } + b.cx(e, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[9]), + low[10], + 10, + is_add, + ); + b.cx(d, streamed); + fold_postsum_carry_compute( + b, + acc, + Some(streamed), + Some(low[10]), + low[11], + 11, + is_add, + ); + for i in 12..park_low { + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + low[i], + i, + is_add, + ); + } + + for i in (12..=hi_delta).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + + let m11 = b.alloc_bit(); + b.hmr(low[11], m11); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[10]), + m11, + 11, + is_add, + ); + b.free(low[11]); + b.cx(d, streamed); + + let m10 = b.alloc_bit(); + b.hmr(low[10], m10); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[9]), + m10, + 10, + is_add, + ); + b.free(low[10]); + b.cx(e, streamed); + + for i in (8..10).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + b.ccx(e, d, streamed); + + let m7 = b.alloc_bit(); + b.hmr(low[7], m7); + fold_postsum_carry_phase_uncompute( + b, + acc, + Some(streamed), + Some(low[6]), + m7, + 7, + is_add, + ); + b.free(low[7]); + b.cx(d, streamed); + b.cx(e, streamed); + b.free(streamed); + + for i in (0..7).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + drop(low); + + b.reacquire(h); + b.ccx(e, d, h); + b.reacquire(xed); + b.cx(e, xed); + b.cx(d, xed); + b.reacquire(eord); + b.cx(xed, eord); + b.cx(h, eord); + b.reacquire(n10); + b.cx(d, n10); + b.cx(h, n10); + } else { + b.reacquire(h); + b.ccx(e, d, h); + b.reacquire(xed); + b.cx(e, xed); + b.cx(d, xed); + b.reacquire(eord); + b.cx(xed, eord); + b.cx(h, eord); + b.reacquire(n10); + b.cx(d, n10); + b.cx(h, n10); + + if park_low > 0 { + for i in 0..park_low { + b.reacquire(low[i]); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_compute( + b, + acc, + kctrl(i), + carry_in, + low[i], + i, + is_add, + ); + } + } + + let low_top = if host_d { + 27 + } else if host_e { + 28 + } else if host_h_n10 { + 29 + } else if host_n10 { + hi_delta - 1 + } else { + hi_delta + }; + for i in (0..=low_top).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl(i), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + drop(low); + } + +} + +fn fold_ripple_freed_tail_ed_hosted( + b: &mut B, + acc: &[QubitId], + e: QubitId, + d: QubitId, + h: QubitId, + xed: QubitId, + eord: QubitId, + n10: QubitId, + ed: Option<(QubitId, QubitId, QubitId)>, + park_low: usize, + last: usize, + is_add: bool, +) { + let free_ed = ed.is_some() && fold_freed_tail_ed_enabled(); + let n = acc.len(); + let hi_delta = 33usize; + let split = 11usize; + debug_assert!(last < n); + debug_assert!(last > hi_delta, "freed-tail requires a nonempty high tail"); + let maj2 = perpos_maj2_enabled(); + let park_low = core::cmp::min(park_low, split + 1); + + b.cx(h, n10); + b.cx(d, n10); + b.free(n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(eord); + b.free(xed); + let mh = b.alloc_bit(); + b.hmr(h, mh); + b.cz_if(e, d, mh); + b.free(h); + + let low = b.alloc_qubits(hi_delta + 1); + + let h_host = low[30]; + let xed_host = low[31]; + let eord_host = low[32]; + let n10_host = low[33]; + b.ccx(e, d, h_host); + b.cx(e, xed_host); + b.cx(d, xed_host); + b.cx(xed_host, eord_host); + b.cx(h_host, eord_host); + b.cx(d, n10_host); + b.cx(h_host, n10_host); + + let hosted_kctrl = |i: usize| -> Option { + match i { + 0 | 4 | 6 | 32 => Some(e), + 1 | 5 | 33 => Some(d), + 7 => Some(xed_host), + 8 | 9 => Some(eord_host), + 10 => Some(n10_host), + 11 => Some(h_host), + _ => None, + } + }; + + for i in 0..=split { + let target = low[i]; + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + if is_add { + if let Some(kc) = hosted_kctrl(i) { + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + } else if let Some(ci) = carry_in { + b.ccx(acc[i], ci, target); + } + } else if let Some(kc) = hosted_kctrl(i) { + b.x(acc[i]); + if let Some(ci) = carry_in { + emit_fold_majority(b, acc[i], kc, ci, target, maj2); + } else { + b.ccx(acc[i], kc, target); + } + b.x(acc[i]); + } else if let Some(ci) = carry_in { + b.x(acc[i]); + b.ccx(acc[i], ci, target); + b.x(acc[i]); + } + } + for i in 0..=split { + if let Some(kc) = hosted_kctrl(i) { + b.cx(kc, acc[i]); + } + if i > 0 { + b.cx(low[i - 1], acc[i]); + } + } + + b.cx(h_host, n10_host); + b.cx(d, n10_host); + b.cx(h_host, eord_host); + b.cx(xed_host, eord_host); + b.cx(d, xed_host); + b.cx(e, xed_host); + let mh_host = b.alloc_bit(); + b.hmr(h_host, mh_host); + b.cz_if(e, d, mh_host); + + for i in split + 1..=hi_delta { + let target = low[i]; + let carry_in = Some(low[i - 1]); + let kctrl = match i { + 32 => Some(e), + 33 => Some(d), + _ => None, + }; + if is_add { + if let Some(kc) = kctrl { + emit_fold_majority( + b, + acc[i], + kc, + carry_in.expect("high carry-in"), + target, + maj2, + ); + } else { + b.ccx( + acc[i], + carry_in.expect("high carry-in"), + target, + ); + } + } else if let Some(kc) = kctrl { + b.x(acc[i]); + emit_fold_majority( + b, + acc[i], + kc, + carry_in.expect("high carry-in"), + target, + maj2, + ); + b.x(acc[i]); + } else { + b.x(acc[i]); + b.ccx( + acc[i], + carry_in.expect("high carry-in"), + target, + ); + b.x(acc[i]); + } + } + for i in split + 1..=hi_delta { + let kctrl = match i { + 32 => Some(e), + 33 => Some(d), + _ => None, + }; + if let Some(kc) = kctrl { + b.cx(kc, acc[i]); + } + b.cx(low[i - 1], acc[i]); + } + + if park_low > 0 { + let controls = secp_fold_controls( + e, d, h_host, xed_host, eord_host, n10_host, hi_delta, 32, + ); + for i in (0..park_low).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + controls.get(i).copied().flatten(), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + } + + if free_ed { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.free(e); + let md = b.alloc_bit(); + b.hmr(d, md); + b.cz_if(ovf1, s2, md); + b.free(d); + } + + let tail_len = last - hi_delta; + let tail = b.alloc_qubits(tail_len); + let cw = |i: usize| -> QubitId { + if i <= hi_delta { + low[i] + } else { + tail[i - hi_delta - 1] + } + }; + + for i in (hi_delta + 1)..=last { + if is_add { + b.ccx(acc[i], cw(i - 1), cw(i)); + } else { + b.x(acc[i]); + b.ccx(acc[i], cw(i - 1), cw(i)); + b.x(acc[i]); + } + } + for i in (hi_delta + 1)..n { + if i - 1 <= last { + b.cx(cw(i - 1), acc[i]); + } + } + for i in (hi_delta + 1..=last).rev() { + let m = b.alloc_bit(); + b.hmr(cw(i), m); + let carry_in = cw(i - 1); + if is_add { + b.x(acc[i]); + b.cz_if(acc[i], carry_in, m); + b.x(acc[i]); + } else { + b.cz_if(acc[i], carry_in, m); + } + b.free(cw(i)); + } + drop(tail); + + if free_ed { + let (ovf1, ovf2, s2) = ed.expect("free_ed implies ed is Some"); + b.reacquire(d); + b.ccx(ovf1, s2, d); + b.reacquire(e); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + } + + for i in (split + 1..=hi_delta).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let kctrl = match i { + 32 => Some(e), + 33 => Some(d), + _ => None, + }; + fold_postsum_carry_phase_uncompute( + b, + acc, + kctrl, + Some(low[i - 1]), + m, + i, + is_add, + ); + b.free(low[i]); + } + + let rev_h = b.alloc_qubit(); + let rev_xed = b.alloc_qubit(); + let rev_eord = b.alloc_qubit(); + let rev_n10 = b.alloc_qubit(); + b.ccx(e, d, rev_h); + b.cx(e, rev_xed); + b.cx(d, rev_xed); + b.cx(rev_xed, rev_eord); + b.cx(rev_h, rev_eord); + b.cx(d, rev_n10); + b.cx(rev_h, rev_n10); + let controls = + secp_fold_controls(e, d, rev_h, rev_xed, rev_eord, rev_n10, hi_delta, 32); + + if park_low > 0 { + for i in 0..park_low { + b.reacquire(low[i]); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_compute( + b, + acc, + controls.get(i).copied().flatten(), + carry_in, + low[i], + i, + is_add, + ); + } + } + + for i in (0..=split).rev() { + let m = b.alloc_bit(); + b.hmr(low[i], m); + let carry_in = if i == 0 { None } else { Some(low[i - 1]) }; + fold_postsum_carry_phase_uncompute( + b, + acc, + controls.get(i).copied().flatten(), + carry_in, + m, + i, + is_add, + ); + b.free(low[i]); + } + drop(low); + + b.reacquire(h); + b.cx(rev_h, h); + b.reacquire(xed); + b.cx(rev_xed, xed); + b.reacquire(eord); + b.cx(rev_eord, eord); + b.reacquire(n10); + b.cx(rev_n10, n10); + + b.cx(rev_h, rev_n10); + b.cx(d, rev_n10); + b.cx(rev_h, rev_eord); + b.cx(rev_xed, rev_eord); + b.cx(d, rev_xed); + b.cx(e, rev_xed); + b.free(rev_n10); + b.free(rev_eord); + b.free(rev_xed); + let mh_rev = b.alloc_bit(); + b.hmr(rev_h, mh_rev); + b.cz_if(e, d, mh_rev); + b.free(rev_h); +} diff --git a/src/point_add/arith/mod.rs b/src/point_add/arith/mod.rs index 05b53ca0..b1a588f6 100644 --- a/src/point_add/arith/mod.rs +++ b/src/point_add/arith/mod.rs @@ -1,16 +1,16 @@ - -use super::*; - -mod adder; -mod compare; -mod const_arith; -mod modular; -mod multiply; -mod nbit; - -pub(crate) use adder::*; -pub(crate) use compare::*; -pub(crate) use const_arith::*; -pub(crate) use modular::*; -pub(crate) use multiply::*; -pub(crate) use nbit::*; + +use super::*; + +mod adder; +mod compare; +mod const_arith; +mod modular; +mod multiply; +mod nbit; +// hey +pub(crate) use adder::*; +pub(crate) use compare::*; +pub(crate) use const_arith::*; +pub(crate) use modular::*; +pub(crate) use multiply::*; +pub(crate) use nbit::*; diff --git a/src/point_add/arith/modular.rs b/src/point_add/arith/modular.rs index 70afd4a1..1151ac1e 100644 --- a/src/point_add/arith/modular.rs +++ b/src/point_add/arith/modular.rs @@ -1,1133 +1,1133 @@ - -use super::*; - -pub(crate) fn mod_add_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - add_nbit_qq(b, &a_ext, &acc_ext); - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - add_nbit_const(b, &acc_ext, c); - - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - - b.x(flag); - csub_nbit_const(b, &acc_ext, c, flag); - b.x(flag); - - b.cx(flag, acc_ovf); - - cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_sub_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - - let a_copy: Vec = a.to_vec(); - emit_inverse(b, move |b| mod_add_qq(b, acc, &a_copy, p)); -} - -pub(crate) fn mod_add_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - add_nbit_qq(b, &a_ext, &acc_ext); - - let borrow = if r84_lowq_cin_borrow_enabled() { - Some(a_ovf) - } else { - None - }; - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - add_nbit_const_extcarry_clean_with_cin(b, &acc_ext, c, borrow); - - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - - b.x(flag); - csub_nbit_const_extcarry_clean_with_cin(b, &acc_ext, c, flag, borrow); - b.x(flag); - - b.cx(flag, acc_ovf); - - cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_sub_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let a_copy: Vec = a.to_vec(); - emit_inverse(b, move |b| mod_add_qq_lowq(b, acc, &a_copy, p)); -} - -pub(crate) fn mod_sub_qq_fast(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - sub_nbit_qq_fast(b, &a_ext, &acc_ext); - - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - - b.cx(flag, acc_ovf); - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - if kal_vent_modadd_enabled() { - - let c_low = c.as_limbs()[0]; - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical( - b, - &acc_ext[..n], - &a_ext[..n - 2], - &q_clean2, - c_low, - flag, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else if secp_direct_const_arith_enabled() { - csub_nbit_const_direct_fast(b, &acc_ext[..n], c, flag); - } else { - csub_nbit_const_fast(b, &acc_ext[..n], c, flag); - } - - b.x(flag); - mod_neg_inplace_fast(b, &a_ext[..n], p); - if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { - let phase = b.alloc_bit(); - b.hmr(flag, phase); - cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); - } else { - cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); - } - mod_neg_inplace_fast(b, &a_ext[..n], p); - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_add_qq_vent(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - add_nbit_qq(b, &a_ext, &acc_ext); - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let c_low = c.as_limbs()[0]; - let n1 = acc_ext.len(); - { - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::iadd_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - false, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } - - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - - b.x(flag); - { - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - flag, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } - b.x(flag); - - b.cx(flag, acc_ovf); - - cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_sub_qq_vent(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let c_low = c.as_limbs()[0]; - let n1 = acc_ext.len(); - - let flag = b.alloc_qubit(); - cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); - - b.cx(flag, acc_ovf); - - b.x(flag); - { - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::ciadd_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - flag, - false, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } - b.x(flag); - - b.cx(acc_ovf, flag); - b.free(flag); - - { - let one = b.alloc_qubit(); - b.x(one); - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical(b, &acc_ext, &a_ext[..n1 - 2], &q_clean2, c_low, one); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - b.x(one); - b.free(one); - } - - sub_nbit_qq(b, &a_ext, &acc_ext); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_neg_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { - for &q in v { - b.x(q); - } - let n = v.len(); - let ca = load_const(b, n, p.wrapping_add(U256::from(1))); - add_nbit_qq_fast(b, &ca, v); - unload_const(b, &ca, p.wrapping_add(U256::from(1))); -} - -pub(crate) fn mod_add_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { - - let a = load_bits(b, bits); - if std::env::var("MOD_ADD_QB_VENT").ok().as_deref() != Some("0") { - - mod_add_qq_vent(b, acc, &a, p); - } else { - mod_add_qq_fast(b, acc, &a, p); - } - unload_bits(b, &a, bits); -} - -pub(crate) fn mod_add_double_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { - - let a = load_bits(b, bits); - mod_double_inplace_fast(b, &a, p); - if std::env::var("MOD_ADD_DOUBLE_QB_VENT").ok().as_deref() != Some("0") { - - mod_add_qq_vent(b, acc, &a, p); - } else { - mod_add_qq_fast(b, acc, &a, p); - } - mod_halve_inplace_fast(b, &a, p); - unload_bits(b, &a, bits); -} - -pub(crate) fn mod_sub_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { - - let a = load_bits(b, bits); - if std::env::var("MOD_SUB_QB_VENT").ok().as_deref() != Some("0") { - - mod_sub_qq_vent(b, acc, &a, p); - } else { - mod_sub_qq_fast(b, acc, &a, p); - } - unload_bits(b, &a, bits); -} - -pub(crate) fn mod_add_triple_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { - let n = bits.len(); - let a = load_bits(b, bits); - let d = b.alloc_qubits(n); - for i in 0..n { - b.cx(a[i], d[i]); - } - mod_double_inplace_fast(b, &d, p); - mod_add_qq_vent(b, acc, &d, p); - mod_add_qq_vent(b, acc, &a, p); - mod_halve_inplace_fast(b, &d, p); - for i in 0..n { - b.cx(a[i], d[i]); - } - b.free_vec(&d); - unload_bits(b, &a, bits); -} - -pub(crate) fn mod_const_minus_reg_qb(b: &mut B, tx: &[QubitId], bits: &[BitId], p: U256) { - let n = tx.len(); - assert_eq!(n, bits.len()); - let a = load_bits(b, bits); - let (a_ext, a_ovf) = ext_reg(b, &a); - let (tx_ext, tx_ovf) = ext_reg(b, tx); - for i in 0..n { - b.x(tx_ext[i]); - } - let cin = b.alloc_qubit(); - b.x(cin); - cuccaro_add_low_to_ext_clean(b, &a, &tx_ext, cin); - b.x(cin); - b.free(cin); - let flag = b.alloc_qubit(); - b.cx(tx_ovf, flag); - b.cx(flag, tx_ovf); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let c_low = c.as_limbs()[0]; - let n1 = tx_ext.len(); - b.x(flag); - { - let q2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical(b, &tx_ext, &a_ext[..n1 - 2], &q2, c_low, flag); - b.free(q2[0]); - b.free(q2[1]); - } - b.x(flag); - b.x(flag); - cmp_lt_into(b, &a, &tx_ext[..n], flag); - b.free(flag); - unext_reg(b, tx_ovf); - unext_reg(b, a_ovf); - let _ = (tx_ext, a_ext); - unload_bits(b, &a, bits); -} - -pub(crate) fn dialog_fuse_primitive_selftest() -> Result<(), String> { - use crate::sim::Simulator; - use sha3::digest::{ExtendableOutput, Update, XofReader}; - let p = crate::point_add::SECP256K1_P; - let nbits = 256usize; - let red = |v: U256| v % p; - let sub_modp = |x: U256, y: U256| -> U256 { - if x >= y { - x - y - } else { - p - (y - x) - } - }; - for fuse_x_restore in [false, true] { - let name = if fuse_x_restore { - "mod_const_minus_reg_qb (FUSE_X_RESTORE)" - } else { - "mod_add_triple_qb (FUSE_C_FORM)" - }; - let mut bld = B::new(); - let tx = bld.alloc_qubits(nbits); - let qx = bld.alloc_bits(nbits); - if fuse_x_restore { - mod_const_minus_reg_qb(&mut bld, &tx, &qx, p); - } else { - mod_add_triple_qb(&mut bld, &tx, &qx, p); - } - let (ops, nq, nb) = (bld.ops, bld.next_qubit as usize, bld.next_bit as usize); - let mut seed = sha3::Shake256::default(); - seed.update(b"dialog-fuse-primitive-selftest"); - seed.update(&[u8::from(fuse_x_restore)]); - let mut xof = seed.finalize_xof(); - - let mut txv = [U256::ZERO; 64]; - let mut qxv = [U256::ZERO; 64]; - let mut buf = [0u8; 32]; - for shot in 0..64 { - xof.read(&mut buf); - txv[shot] = red(U256::from_le_bytes(buf)); - xof.read(&mut buf); - qxv[shot] = red(U256::from_le_bytes(buf)); - } - let mut sim = Simulator::new(nq, nb, &mut xof); - sim.clear_for_shot(); - for shot in 0..64 { - for i in 0..nbits { - if txv[shot].bit(i) { - *sim.qubit_mut(tx[i]) |= 1u64 << shot; - } - if qxv[shot].bit(i) { - *sim.bit_mut(qx[i]) |= 1u64 << shot; - } - } - } - sim.apply_iter(ops.iter()); - if sim.phase != 0 { - return Err(format!("{name}: phase garbage 0x{:x}", sim.phase)); - } - for shot in 0..64 { - let mut out = U256::ZERO; - for i in 0..nbits { - if (sim.qubit(tx[i]) >> shot) & 1 == 1 { - out |= U256::from(1u64) << i; - } - } - let expect = if fuse_x_restore { - sub_modp(qxv[shot], txv[shot]) - } else { - txv[shot].add_mod(qxv[shot].mul_mod(U256::from(3u64), p), p) - }; - if out != expect { - return Err(format!( - "{name}: shot {shot} got {out:#x} expect {expect:#x} (tx={:#x} qx={:#x})", - txv[shot], qxv[shot] - )); - } - } - for q in 0..nq as u64 { - if tx.iter().any(|t| t.0 == q) { - continue; - } - let v = sim.qubit(QubitId(q)); - if v != 0 { - return Err(format!("{name}: ancilla qubit {q} not clean = 0x{v:x}")); - } - } - } - Ok(()) -} - -pub(crate) fn mod_double_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { - mod_double_inplace_fast_with_dirty(b, v, p, None) -} - -pub(crate) fn mod_double_inplace_fast_with_dirty( - b: &mut B, - v: &[QubitId], - p: U256, - dirty_src: Option<&[QubitId]>, -) { - let n = v.len(); - let ovf = b.alloc_qubit(); - b.swap(v[n - 1], ovf); - for i in (0..n - 1).rev() { - b.swap(v[i], v[i + 1]); - } - debug_assert_eq!(n, 256); - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let use_venting = std::env::var("KAL_VENT_DOUBLE").ok().as_deref() == Some("1") - && dirty_src.map_or(false, |d| d.len() >= n - 2); - if let Some(w) = double_carry_trunc_window() { - - cadd_nbit_const_direct_trunc_fast(b, v, c, ovf, w); - } else if use_venting { - let dirty = dirty_src.unwrap(); - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::ciadd_dirty_2clean_classical( - b, - v, - &dirty[..n - 2], - &q_clean2, - c.as_limbs()[0], - ovf, - false, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else if direct_const_walks_enabled() - || std::env::var("KAL_DIRECT_CONST_DOUBLE").ok().as_deref() == Some("1") - { - cadd_nbit_const_direct_fast(b, v, c, ovf); - } else { - cadd_nbit_const_fast(b, v, c, ovf); - } - - b.cx(v[0], ovf); - b.free(ovf); -} - -pub(crate) fn mod_double_inplace_direct_const_fast(b: &mut B, v: &[QubitId], p: U256) { - let n = v.len(); - let ovf = b.alloc_qubit(); - b.swap(v[n - 1], ovf); - for i in (0..n - 1).rev() { - b.swap(v[i], v[i + 1]); - } - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - cadd_nbit_const_direct_fast(b, v, c, ovf); - b.cx(v[0], ovf); - b.free(ovf); -} - -pub(crate) fn lowq_shift22() -> bool { - if d1_phase_corrected_product_core_active() { - return true; - } - - match std::env::var("LOWQ_SHIFT22") { - Ok(v) => v != "0", - Err(_) => false, - } -} - -pub(crate) fn mod_shift_left_by_k( - b: &mut B, - v: &[QubitId], - p: U256, - k: usize, -) -> (Vec, QubitId, QubitId) { - let n = v.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let spill = b.alloc_qubits(k); - let ovf = b.alloc_qubit(); - let flag_inv = b.alloc_qubit(); - - for shift_i in 0..k { - b.swap(v[n - 1], spill[k - 1 - shift_i]); - for i in (0..n - 1).rev() { - b.swap(v[i], v[i + 1]); - } - } - - let mut v_ext = v.to_vec(); - v_ext.push(ovf); - let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { - let pad_width = n + 1 - pos; - let padded = b.alloc_qubits(pad_width); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - let v_slice: Vec = v_ext[pos..n + 1].to_vec(); - let c_in = b.alloc_qubit(); - if lowq_shift22() { - if is_sub { - cuccaro_sub(b, &padded, &v_slice, c_in); - } else { - cuccaro_add(b, &padded, &v_slice, c_in); - } - } else if is_sub { - - cuccaro_sub_fast(b, &padded, &v_slice, c_in); - } else { - cuccaro_add_fast(b, &padded, &v_slice, c_in); - } - b.free(c_in); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - b.free_vec(&padded); - }; - b.set_phase("shift22_cuccaro_op_0"); - cuccaro_op(b, 0, false); - b.set_phase("shift22_cuccaro_op_4"); - cuccaro_op(b, 4, false); - b.set_phase("shift22_cuccaro_op_6"); - cuccaro_op(b, 6, true); - b.set_phase("shift22_cuccaro_op_10"); - cuccaro_op(b, 10, false); - b.set_phase("shift22_cuccaro_op_32"); - cuccaro_op(b, 32, false); - - b.set_phase("shift22_step3"); - if lowq_shift22() { - add_nbit_const(b, &v_ext, c); - } else { - add_nbit_const_fast(b, &v_ext, c); - } - b.x(ovf); - b.cx(ovf, flag_inv); - b.x(ovf); - - b.set_phase("shift22_step4"); - if lowq_shift22() { - csub_nbit_const(b, &v_ext, c, flag_inv); - } else { - csub_nbit_const_fast(b, &v_ext, c, flag_inv); - } - b.x(flag_inv); - b.cx(flag_inv, ovf); - b.x(flag_inv); - - (spill, flag_inv, ovf) -} - -pub(crate) fn mod_shift_right_by_k( - b: &mut B, - v: &[QubitId], - p: U256, - k: usize, - spill: Vec, - flag_inv: QubitId, - ovf: QubitId, -) { - let n = v.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let mut v_ext = v.to_vec(); - v_ext.push(ovf); - - b.x(flag_inv); - b.cx(flag_inv, ovf); - b.x(flag_inv); - b.set_phase("rshift22_rev_step4"); - if lowq_shift22() { - cadd_nbit_const(b, &v_ext, c, flag_inv); - } else { - cadd_nbit_const_fast(b, &v_ext, c, flag_inv); - } - - b.x(ovf); - b.cx(ovf, flag_inv); - b.x(ovf); - b.set_phase("rshift22_rev_step3"); - if lowq_shift22() { - sub_nbit_const(b, &v_ext, c); - } else { - sub_nbit_const_fast(b, &v_ext, c); - } - b.free(flag_inv); - b.set_phase("rshift22_rev_step2"); - - let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { - let pad_width = n + 1 - pos; - let padded = b.alloc_qubits(pad_width); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - let v_slice: Vec = v_ext[pos..n + 1].to_vec(); - let c_in = b.alloc_qubit(); - if lowq_shift22() { - if is_sub { - cuccaro_sub(b, &padded, &v_slice, c_in); - } else { - cuccaro_add(b, &padded, &v_slice, c_in); - } - } else if is_sub { - cuccaro_sub_fast(b, &padded, &v_slice, c_in); - } else { - cuccaro_add_fast(b, &padded, &v_slice, c_in); - } - b.free(c_in); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - b.free_vec(&padded); - }; - - cuccaro_op(b, 32, true); - cuccaro_op(b, 10, true); - cuccaro_op(b, 6, false); - cuccaro_op(b, 4, true); - cuccaro_op(b, 0, true); - - for shift_i in (0..k).rev() { - for i in 0..n - 1 { - b.swap(v[i], v[i + 1]); - } - b.swap(v[n - 1], spill[k - 1 - shift_i]); - } - - b.free(ovf); - b.free_vec(&spill); -} - -pub(crate) fn mod_shift_left_by_k_lowq( - b: &mut B, - v: &[QubitId], - p: U256, - k: usize, -) -> (Vec, QubitId, QubitId) { - let n = v.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let spill = b.alloc_qubits(k); - let ovf = b.alloc_qubit(); - let flag_inv = b.alloc_qubit(); - - for shift_i in 0..k { - b.swap(v[n - 1], spill[k - 1 - shift_i]); - for i in (0..n - 1).rev() { - b.swap(v[i], v[i + 1]); - } - } - - let mut v_ext = v.to_vec(); - v_ext.push(ovf); - let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { - let pad_width = n + 1 - pos; - let padded = b.alloc_qubits(pad_width); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - let v_slice: Vec = v_ext[pos..n + 1].to_vec(); - let c_in = b.alloc_qubit(); - if is_sub { - cuccaro_sub(b, &padded, &v_slice, c_in); - } else { - cuccaro_add(b, &padded, &v_slice, c_in); - } - b.free(c_in); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - b.free_vec(&padded); - }; - cuccaro_op(b, 0, false); - cuccaro_op(b, 4, false); - cuccaro_op(b, 6, true); - cuccaro_op(b, 10, false); - cuccaro_op(b, 32, false); - - add_nbit_const(b, &v_ext, c); - b.x(ovf); - b.cx(ovf, flag_inv); - b.x(ovf); - csub_nbit_const(b, &v_ext, c, flag_inv); - b.x(flag_inv); - b.cx(flag_inv, ovf); - b.x(flag_inv); - - (spill, flag_inv, ovf) -} - -pub(crate) fn mod_shift_right_by_k_lowq( - b: &mut B, - v: &[QubitId], - p: U256, - k: usize, - spill: Vec, - flag_inv: QubitId, - ovf: QubitId, -) { - let n = v.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let mut v_ext = v.to_vec(); - v_ext.push(ovf); - - b.x(flag_inv); - b.cx(flag_inv, ovf); - b.x(flag_inv); - cadd_nbit_const(b, &v_ext, c, flag_inv); - - b.x(ovf); - b.cx(ovf, flag_inv); - b.x(ovf); - sub_nbit_const(b, &v_ext, c); - b.free(flag_inv); - - let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { - let pad_width = n + 1 - pos; - let padded = b.alloc_qubits(pad_width); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - let v_slice: Vec = v_ext[pos..n + 1].to_vec(); - let c_in = b.alloc_qubit(); - if is_sub { - cuccaro_sub(b, &padded, &v_slice, c_in); - } else { - cuccaro_add(b, &padded, &v_slice, c_in); - } - b.free(c_in); - for i in 0..k.min(pad_width) { - b.cx(spill[i], padded[i]); - } - b.free_vec(&padded); - }; - cuccaro_op(b, 32, true); - cuccaro_op(b, 10, true); - cuccaro_op(b, 6, false); - cuccaro_op(b, 4, true); - cuccaro_op(b, 0, true); - - for shift_i in (0..k).rev() { - for i in 0..n - 1 { - b.swap(v[i], v[i + 1]); - } - b.swap(v[n - 1], spill[k - 1 - shift_i]); - } - - b.free(ovf); - b.free_vec(&spill); -} - -pub(crate) fn mod_halve_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { - mod_halve_inplace_fast_with_dirty(b, v, p, None) -} - -pub(crate) fn mod_halve_inplace_direct_const_fast(b: &mut B, v: &[QubitId], p: U256) { - let n = v.len(); - let ovf = b.alloc_qubit(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - b.cx(v[0], ovf); - csub_nbit_const_direct_fast(b, v, c, ovf); - for i in 0..n - 1 { - b.swap(v[i], v[i + 1]); - } - b.swap(v[n - 1], ovf); - b.free(ovf); -} - -pub(crate) fn mod_halve_inplace_fast_with_dirty( - b: &mut B, - v: &[QubitId], - p: U256, - dirty_src: Option<&[QubitId]>, -) { - let n = v.len(); - let ovf = b.alloc_qubit(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - b.cx(v[0], ovf); - - let use_venting = kal_vent_halve_enabled() && dirty_src.map_or(false, |d| d.len() >= n - 2); - if let Some(w) = double_carry_trunc_window() { - - csub_nbit_const_direct_trunc_fast(b, v, c, ovf, w); - } else if use_venting { - - let c_u64: u64 = c.as_limbs()[0] | (c.as_limbs()[1] << 32); - - let c_low = c.as_limbs()[0]; - let dirty = dirty_src.unwrap(); - let dirty_slice = &dirty[..n - 2]; - - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical(b, v, dirty_slice, &q_clean2, c_low, ovf); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - let _ = c_u64; - } else if direct_const_walks_enabled() - || std::env::var("KAL_DIRECT_CONST_HALVE").ok().as_deref() == Some("1") - { - csub_nbit_const_direct_fast(b, v, c, ovf); - } else { - csub_nbit_const_fast(b, v, c, ovf); - } - for i in 0..n - 1 { - b.swap(v[i], v[i + 1]); - } - b.swap(v[n - 1], ovf); - b.free(ovf); -} - -pub(crate) fn cmod_double_inplace_lazy(b: &mut B, v: &[QubitId], p: U256, ctrl: QubitId) { - let n = v.len(); - let ovf = b.alloc_qubit(); - cswap(b, ctrl, v[n - 1], ovf); - for i in (0..n - 1).rev() { - cswap(b, ctrl, v[i], v[i + 1]); - } - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - if let Some(w) = double_carry_trunc_window() { - cadd_nbit_const_direct_trunc_fast(b, v, c, ovf, w); - } else if direct_const_walks_enabled() - || std::env::var("KAL_DIRECT_CONST_DOUBLE").ok().as_deref() == Some("1") - { - cadd_nbit_const_direct_fast(b, v, c, ovf); - } else { - cadd_nbit_const_fast(b, v, c, ovf); - } - - b.ccx(ctrl, v[0], ovf); - b.free(ovf); -} - -pub(crate) fn cmod_halve_inplace_lazy(b: &mut B, v: &[QubitId], p: U256, ctrl: QubitId) { - let n = v.len(); - let ovf = b.alloc_qubit(); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - b.ccx(ctrl, v[0], ovf); - if let Some(w) = double_carry_trunc_window() { - csub_nbit_const_direct_trunc_fast(b, v, c, ovf, w); - } else if direct_const_walks_enabled() - || std::env::var("KAL_DIRECT_CONST_HALVE").ok().as_deref() == Some("1") - { - csub_nbit_const_direct_fast(b, v, c, ovf); - } else { - csub_nbit_const_fast(b, v, c, ovf); - } - for i in 0..n - 1 { - cswap(b, ctrl, v[i], v[i + 1]); - } - cswap(b, ctrl, v[n - 1], ovf); - b.free(ovf); -} - -pub(crate) fn mod_add_qq_fast(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - add_nbit_qq_fast(b, &a_ext, &acc_ext); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let use_vent = kal_vent_modadd_enabled(); - if use_vent { - let n1 = acc_ext.len(); - - let c_low = c.as_limbs()[0]; - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::iadd_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - false, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else if secp_direct_const_arith_enabled() { - add_nbit_const_direct_uncontrolled_fast(b, &acc_ext, c); - } else { - let n1 = acc_ext.len(); - let ca = load_const(b, n1, c); - add_nbit_qq_fast(b, &ca, &acc_ext); - unload_const(b, &ca, c); - } - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - b.x(flag); - - if use_vent { - let c_low = c.as_limbs()[0]; - let n1 = acc_ext.len(); - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - flag, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else if secp_direct_const_arith_enabled() { - csub_nbit_const_direct_fast(b, &acc_ext, c, flag); - } else { - let n1 = acc_ext.len(); - let ca = b.alloc_qubits(n1); - for i in 0..n1 { - if bit(c, i) { - b.cx(flag, ca[i]); - } - } - sub_nbit_qq_fast(b, &ca, &acc_ext); - for i in 0..n1 { - if bit(c, i) { - b.cx(flag, ca[i]); - } - } - b.free_vec(&ca); - } - b.x(flag); - b.cx(flag, acc_ovf); - if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { - let phase = b.alloc_bit(); - b.hmr(flag, phase); - cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); - } else { - cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); - } - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn mod_add_qq_fast_from_zero(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { - let n = acc.len(); - assert_eq!(n, a.len()); - debug_assert_eq!(n, 256); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let (a_ext, a_ovf) = ext_reg(b, a); - - for i in 0..n { - b.cx(a[i], acc[i]); - } - - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let use_vent = kal_vent_modadd_enabled(); - if use_vent { - let n1 = acc_ext.len(); - let c_low = c.as_limbs()[0]; - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::iadd_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - false, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else { - let n1 = acc_ext.len(); - let ca = load_const(b, n1, c); - add_nbit_qq_fast(b, &ca, &acc_ext); - unload_const(b, &ca, c); - } - let flag = b.alloc_qubit(); - b.cx(acc_ovf, flag); - b.x(flag); - if use_vent { - let c_low = c.as_limbs()[0]; - let n1 = acc_ext.len(); - let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical( - b, - &acc_ext, - &a_ext[..n1 - 2], - &q_clean2, - c_low, - flag, - ); - b.free(q_clean2[0]); - b.free(q_clean2[1]); - } else { - let n1 = acc_ext.len(); - let ca = b.alloc_qubits(n1); - for i in 0..n1 { - if bit(c, i) { - b.cx(flag, ca[i]); - } - } - sub_nbit_qq_fast(b, &ca, &acc_ext); - for i in 0..n1 { - if bit(c, i) { - b.cx(flag, ca[i]); - } - } - b.free_vec(&ca); - } - b.x(flag); - b.cx(flag, acc_ovf); - if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { - let phase = b.alloc_bit(); - b.hmr(flag, phase); - cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); - } else { - cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); - } - b.free(flag); - - unext_reg(b, a_ovf); - unext_reg(b, acc_ovf); - let _ = (acc_ext, a_ext); -} - -pub(crate) fn cmod_add_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { - let n = acc.len(); - let f = b.alloc_qubits(n); - for i in 0..n { - b.ccx(ctrl, a[i], f[i]); - } - mod_add_qq_fast(b, acc, &f, p); - - for i in 0..n { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} - -pub(crate) fn cmod_sub_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { - let n = acc.len(); - let f = b.alloc_qubits(n); - for i in 0..n { - b.ccx(ctrl, a[i], f[i]); - } - mod_sub_qq_fast(b, acc, &f, p); - for i in 0..n { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} - -pub(crate) fn cmod_add_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { - let n = acc.len(); - let f = b.alloc_qubits(n); - for i in 0..n { - b.ccx(ctrl, a[i], f[i]); - } - mod_add_qq(b, acc, &f, p); - for i in 0..n { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} - -pub(crate) fn cmod_sub_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { - let n = acc.len(); - let f = b.alloc_qubits(n); - for i in 0..n { - b.ccx(ctrl, a[i], f[i]); - } - mod_sub_qq(b, acc, &f, p); - for i in 0..n { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} + +use super::*; + +pub(crate) fn mod_add_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + add_nbit_qq(b, &a_ext, &acc_ext); + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + add_nbit_const(b, &acc_ext, c); + + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + + b.x(flag); + csub_nbit_const(b, &acc_ext, c, flag); + b.x(flag); + + b.cx(flag, acc_ovf); + + cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_sub_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + + let a_copy: Vec = a.to_vec(); + emit_inverse(b, move |b| mod_add_qq(b, acc, &a_copy, p)); +} + +pub(crate) fn mod_add_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + add_nbit_qq(b, &a_ext, &acc_ext); + + let borrow = if r84_lowq_cin_borrow_enabled() { + Some(a_ovf) + } else { + None + }; + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + add_nbit_const_extcarry_clean_with_cin(b, &acc_ext, c, borrow); + + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + + b.x(flag); + csub_nbit_const_extcarry_clean_with_cin(b, &acc_ext, c, flag, borrow); + b.x(flag); + + b.cx(flag, acc_ovf); + + cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_sub_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let a_copy: Vec = a.to_vec(); + emit_inverse(b, move |b| mod_add_qq_lowq(b, acc, &a_copy, p)); +} + +pub(crate) fn mod_sub_qq_fast(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + sub_nbit_qq_fast(b, &a_ext, &acc_ext); + + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + + b.cx(flag, acc_ovf); + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + if kal_vent_modadd_enabled() { + + let c_low = c.as_limbs()[0]; + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical( + b, + &acc_ext[..n], + &a_ext[..n - 2], + &q_clean2, + c_low, + flag, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else if secp_direct_const_arith_enabled() { + csub_nbit_const_direct_fast(b, &acc_ext[..n], c, flag); + } else { + csub_nbit_const_fast(b, &acc_ext[..n], c, flag); + } + + b.x(flag); + mod_neg_inplace_fast(b, &a_ext[..n], p); + if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { + let phase = b.alloc_bit(); + b.hmr(flag, phase); + cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); + } else { + cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); + } + mod_neg_inplace_fast(b, &a_ext[..n], p); + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_add_qq_vent(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + add_nbit_qq(b, &a_ext, &acc_ext); + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let c_low = c.as_limbs()[0]; + let n1 = acc_ext.len(); + { + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::iadd_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + false, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } + + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + + b.x(flag); + { + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + flag, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } + b.x(flag); + + b.cx(flag, acc_ovf); + + cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_sub_qq_vent(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let c_low = c.as_limbs()[0]; + let n1 = acc_ext.len(); + + let flag = b.alloc_qubit(); + cmp_lt_into(b, &acc_ext[..n], &a_ext[..n], flag); + + b.cx(flag, acc_ovf); + + b.x(flag); + { + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::ciadd_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + flag, + false, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } + b.x(flag); + + b.cx(acc_ovf, flag); + b.free(flag); + + { + let one = b.alloc_qubit(); + b.x(one); + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical(b, &acc_ext, &a_ext[..n1 - 2], &q_clean2, c_low, one); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + b.x(one); + b.free(one); + } + + sub_nbit_qq(b, &a_ext, &acc_ext); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_neg_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { + for &q in v { + b.x(q); + } + let n = v.len(); + let ca = load_const(b, n, p.wrapping_add(U256::from(1))); + add_nbit_qq_fast(b, &ca, v); + unload_const(b, &ca, p.wrapping_add(U256::from(1))); +} + +pub(crate) fn mod_add_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { + + let a = load_bits(b, bits); + if std::env::var("MOD_ADD_QB_VENT").ok().as_deref() != Some("0") { + + mod_add_qq_vent(b, acc, &a, p); + } else { + mod_add_qq_fast(b, acc, &a, p); + } + unload_bits(b, &a, bits); +} + +pub(crate) fn mod_add_double_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { + + let a = load_bits(b, bits); + mod_double_inplace_fast(b, &a, p); + if std::env::var("MOD_ADD_DOUBLE_QB_VENT").ok().as_deref() != Some("0") { + + mod_add_qq_vent(b, acc, &a, p); + } else { + mod_add_qq_fast(b, acc, &a, p); + } + mod_halve_inplace_fast(b, &a, p); + unload_bits(b, &a, bits); +} + +pub(crate) fn mod_sub_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { + + let a = load_bits(b, bits); + if std::env::var("MOD_SUB_QB_VENT").ok().as_deref() != Some("0") { + + mod_sub_qq_vent(b, acc, &a, p); + } else { + mod_sub_qq_fast(b, acc, &a, p); + } + unload_bits(b, &a, bits); +} + +pub(crate) fn mod_add_triple_qb(b: &mut B, acc: &[QubitId], bits: &[BitId], p: U256) { + let n = bits.len(); + let a = load_bits(b, bits); + let d = b.alloc_qubits(n); + for i in 0..n { + b.cx(a[i], d[i]); + } + mod_double_inplace_fast(b, &d, p); + mod_add_qq_vent(b, acc, &d, p); + mod_add_qq_vent(b, acc, &a, p); + mod_halve_inplace_fast(b, &d, p); + for i in 0..n { + b.cx(a[i], d[i]); + } + b.free_vec(&d); + unload_bits(b, &a, bits); +} + +pub(crate) fn mod_const_minus_reg_qb(b: &mut B, tx: &[QubitId], bits: &[BitId], p: U256) { + let n = tx.len(); + assert_eq!(n, bits.len()); + let a = load_bits(b, bits); + let (a_ext, a_ovf) = ext_reg(b, &a); + let (tx_ext, tx_ovf) = ext_reg(b, tx); + for i in 0..n { + b.x(tx_ext[i]); + } + let cin = b.alloc_qubit(); + b.x(cin); + cuccaro_add_low_to_ext_clean(b, &a, &tx_ext, cin); + b.x(cin); + b.free(cin); + let flag = b.alloc_qubit(); + b.cx(tx_ovf, flag); + b.cx(flag, tx_ovf); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let c_low = c.as_limbs()[0]; + let n1 = tx_ext.len(); + b.x(flag); + { + let q2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical(b, &tx_ext, &a_ext[..n1 - 2], &q2, c_low, flag); + b.free(q2[0]); + b.free(q2[1]); + } + b.x(flag); + b.x(flag); + cmp_lt_into(b, &a, &tx_ext[..n], flag); + b.free(flag); + unext_reg(b, tx_ovf); + unext_reg(b, a_ovf); + let _ = (tx_ext, a_ext); + unload_bits(b, &a, bits); +} + +pub(crate) fn dialog_fuse_primitive_selftest() -> Result<(), String> { + use crate::sim::Simulator; + use sha3::digest::{ExtendableOutput, Update, XofReader}; + let p = crate::point_add::SECP256K1_P; + let nbits = 256usize; + let red = |v: U256| v % p; + let sub_modp = |x: U256, y: U256| -> U256 { + if x >= y { + x - y + } else { + p - (y - x) + } + }; + for fuse_x_restore in [false, true] { + let name = if fuse_x_restore { + "mod_const_minus_reg_qb (FUSE_X_RESTORE)" + } else { + "mod_add_triple_qb (FUSE_C_FORM)" + }; + let mut bld = B::new(); + let tx = bld.alloc_qubits(nbits); + let qx = bld.alloc_bits(nbits); + if fuse_x_restore { + mod_const_minus_reg_qb(&mut bld, &tx, &qx, p); + } else { + mod_add_triple_qb(&mut bld, &tx, &qx, p); + } + let (ops, nq, nb) = (bld.ops, bld.next_qubit as usize, bld.next_bit as usize); + let mut seed = sha3::Shake256::default(); + seed.update(b"dialog-fuse-primitive-selftest"); + seed.update(&[u8::from(fuse_x_restore)]); + let mut xof = seed.finalize_xof(); + + let mut txv = [U256::ZERO; 64]; + let mut qxv = [U256::ZERO; 64]; + let mut buf = [0u8; 32]; + for shot in 0..64 { + xof.read(&mut buf); + txv[shot] = red(U256::from_le_bytes(buf)); + xof.read(&mut buf); + qxv[shot] = red(U256::from_le_bytes(buf)); + } + let mut sim = Simulator::new(nq, nb, &mut xof); + sim.clear_for_shot(); + for shot in 0..64 { + for i in 0..nbits { + if txv[shot].bit(i) { + *sim.qubit_mut(tx[i]) |= 1u64 << shot; + } + if qxv[shot].bit(i) { + *sim.bit_mut(qx[i]) |= 1u64 << shot; + } + } + } + sim.apply_iter(ops.iter()); + if sim.phase != 0 { + return Err(format!("{name}: phase garbage 0x{:x}", sim.phase)); + } + for shot in 0..64 { + let mut out = U256::ZERO; + for i in 0..nbits { + if (sim.qubit(tx[i]) >> shot) & 1 == 1 { + out |= U256::from(1u64) << i; + } + } + let expect = if fuse_x_restore { + sub_modp(qxv[shot], txv[shot]) + } else { + txv[shot].add_mod(qxv[shot].mul_mod(U256::from(3u64), p), p) + }; + if out != expect { + return Err(format!( + "{name}: shot {shot} got {out:#x} expect {expect:#x} (tx={:#x} qx={:#x})", + txv[shot], qxv[shot] + )); + } + } + for q in 0..nq as u64 { + if tx.iter().any(|t| t.0 == q) { + continue; + } + let v = sim.qubit(QubitId(q)); + if v != 0 { + return Err(format!("{name}: ancilla qubit {q} not clean = 0x{v:x}")); + } + } + } + Ok(()) +} + +pub(crate) fn mod_double_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { + mod_double_inplace_fast_with_dirty(b, v, p, None) +} + +pub(crate) fn mod_double_inplace_fast_with_dirty( + b: &mut B, + v: &[QubitId], + p: U256, + dirty_src: Option<&[QubitId]>, +) { + let n = v.len(); + let ovf = b.alloc_qubit(); + b.swap(v[n - 1], ovf); + for i in (0..n - 1).rev() { + b.swap(v[i], v[i + 1]); + } + debug_assert_eq!(n, 256); + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let use_venting = std::env::var("KAL_VENT_DOUBLE").ok().as_deref() == Some("1") + && dirty_src.map_or(false, |d| d.len() >= n - 2); + if let Some(w) = double_carry_trunc_window() { + + cadd_nbit_const_direct_trunc_fast(b, v, c, ovf, w); + } else if use_venting { + let dirty = dirty_src.unwrap(); + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::ciadd_dirty_2clean_classical( + b, + v, + &dirty[..n - 2], + &q_clean2, + c.as_limbs()[0], + ovf, + false, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else if direct_const_walks_enabled() + || std::env::var("KAL_DIRECT_CONST_DOUBLE").ok().as_deref() == Some("1") + { + cadd_nbit_const_direct_fast(b, v, c, ovf); + } else { + cadd_nbit_const_fast(b, v, c, ovf); + } + + b.cx(v[0], ovf); + b.free(ovf); +} + +pub(crate) fn mod_double_inplace_direct_const_fast(b: &mut B, v: &[QubitId], p: U256) { + let n = v.len(); + let ovf = b.alloc_qubit(); + b.swap(v[n - 1], ovf); + for i in (0..n - 1).rev() { + b.swap(v[i], v[i + 1]); + } + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + cadd_nbit_const_direct_fast(b, v, c, ovf); + b.cx(v[0], ovf); + b.free(ovf); +} + +pub(crate) fn lowq_shift22() -> bool { + if d1_phase_corrected_product_core_active() { + return true; + } + + match std::env::var("LOWQ_SHIFT22") { + Ok(v) => v != "0", + Err(_) => false, + } +} + +pub(crate) fn mod_shift_left_by_k( + b: &mut B, + v: &[QubitId], + p: U256, + k: usize, +) -> (Vec, QubitId, QubitId) { + let n = v.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let spill = b.alloc_qubits(k); + let ovf = b.alloc_qubit(); + let flag_inv = b.alloc_qubit(); + + for shift_i in 0..k { + b.swap(v[n - 1], spill[k - 1 - shift_i]); + for i in (0..n - 1).rev() { + b.swap(v[i], v[i + 1]); + } + } + + let mut v_ext = v.to_vec(); + v_ext.push(ovf); + let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { + let pad_width = n + 1 - pos; + let padded = b.alloc_qubits(pad_width); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + let v_slice: Vec = v_ext[pos..n + 1].to_vec(); + let c_in = b.alloc_qubit(); + if lowq_shift22() { + if is_sub { + cuccaro_sub(b, &padded, &v_slice, c_in); + } else { + cuccaro_add(b, &padded, &v_slice, c_in); + } + } else if is_sub { + + cuccaro_sub_fast(b, &padded, &v_slice, c_in); + } else { + cuccaro_add_fast(b, &padded, &v_slice, c_in); + } + b.free(c_in); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + b.free_vec(&padded); + }; + b.set_phase("shift22_cuccaro_op_0"); + cuccaro_op(b, 0, false); + b.set_phase("shift22_cuccaro_op_4"); + cuccaro_op(b, 4, false); + b.set_phase("shift22_cuccaro_op_6"); + cuccaro_op(b, 6, true); + b.set_phase("shift22_cuccaro_op_10"); + cuccaro_op(b, 10, false); + b.set_phase("shift22_cuccaro_op_32"); + cuccaro_op(b, 32, false); + + b.set_phase("shift22_step3"); + if lowq_shift22() { + add_nbit_const(b, &v_ext, c); + } else { + add_nbit_const_fast(b, &v_ext, c); + } + b.x(ovf); + b.cx(ovf, flag_inv); + b.x(ovf); + + b.set_phase("shift22_step4"); + if lowq_shift22() { + csub_nbit_const(b, &v_ext, c, flag_inv); + } else { + csub_nbit_const_fast(b, &v_ext, c, flag_inv); + } + b.x(flag_inv); + b.cx(flag_inv, ovf); + b.x(flag_inv); + + (spill, flag_inv, ovf) +} + +pub(crate) fn mod_shift_right_by_k( + b: &mut B, + v: &[QubitId], + p: U256, + k: usize, + spill: Vec, + flag_inv: QubitId, + ovf: QubitId, +) { + let n = v.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let mut v_ext = v.to_vec(); + v_ext.push(ovf); + + b.x(flag_inv); + b.cx(flag_inv, ovf); + b.x(flag_inv); + b.set_phase("rshift22_rev_step4"); + if lowq_shift22() { + cadd_nbit_const(b, &v_ext, c, flag_inv); + } else { + cadd_nbit_const_fast(b, &v_ext, c, flag_inv); + } + + b.x(ovf); + b.cx(ovf, flag_inv); + b.x(ovf); + b.set_phase("rshift22_rev_step3"); + if lowq_shift22() { + sub_nbit_const(b, &v_ext, c); + } else { + sub_nbit_const_fast(b, &v_ext, c); + } + b.free(flag_inv); + b.set_phase("rshift22_rev_step2"); + + let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { + let pad_width = n + 1 - pos; + let padded = b.alloc_qubits(pad_width); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + let v_slice: Vec = v_ext[pos..n + 1].to_vec(); + let c_in = b.alloc_qubit(); + if lowq_shift22() { + if is_sub { + cuccaro_sub(b, &padded, &v_slice, c_in); + } else { + cuccaro_add(b, &padded, &v_slice, c_in); + } + } else if is_sub { + cuccaro_sub_fast(b, &padded, &v_slice, c_in); + } else { + cuccaro_add_fast(b, &padded, &v_slice, c_in); + } + b.free(c_in); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + b.free_vec(&padded); + }; + + cuccaro_op(b, 32, true); + cuccaro_op(b, 10, true); + cuccaro_op(b, 6, false); + cuccaro_op(b, 4, true); + cuccaro_op(b, 0, true); + + for shift_i in (0..k).rev() { + for i in 0..n - 1 { + b.swap(v[i], v[i + 1]); + } + b.swap(v[n - 1], spill[k - 1 - shift_i]); + } + + b.free(ovf); + b.free_vec(&spill); +} + +pub(crate) fn mod_shift_left_by_k_lowq( + b: &mut B, + v: &[QubitId], + p: U256, + k: usize, +) -> (Vec, QubitId, QubitId) { + let n = v.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let spill = b.alloc_qubits(k); + let ovf = b.alloc_qubit(); + let flag_inv = b.alloc_qubit(); + + for shift_i in 0..k { + b.swap(v[n - 1], spill[k - 1 - shift_i]); + for i in (0..n - 1).rev() { + b.swap(v[i], v[i + 1]); + } + } + + let mut v_ext = v.to_vec(); + v_ext.push(ovf); + let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { + let pad_width = n + 1 - pos; + let padded = b.alloc_qubits(pad_width); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + let v_slice: Vec = v_ext[pos..n + 1].to_vec(); + let c_in = b.alloc_qubit(); + if is_sub { + cuccaro_sub(b, &padded, &v_slice, c_in); + } else { + cuccaro_add(b, &padded, &v_slice, c_in); + } + b.free(c_in); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + b.free_vec(&padded); + }; + cuccaro_op(b, 0, false); + cuccaro_op(b, 4, false); + cuccaro_op(b, 6, true); + cuccaro_op(b, 10, false); + cuccaro_op(b, 32, false); + + add_nbit_const(b, &v_ext, c); + b.x(ovf); + b.cx(ovf, flag_inv); + b.x(ovf); + csub_nbit_const(b, &v_ext, c, flag_inv); + b.x(flag_inv); + b.cx(flag_inv, ovf); + b.x(flag_inv); + + (spill, flag_inv, ovf) +} + +pub(crate) fn mod_shift_right_by_k_lowq( + b: &mut B, + v: &[QubitId], + p: U256, + k: usize, + spill: Vec, + flag_inv: QubitId, + ovf: QubitId, +) { + let n = v.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let mut v_ext = v.to_vec(); + v_ext.push(ovf); + + b.x(flag_inv); + b.cx(flag_inv, ovf); + b.x(flag_inv); + cadd_nbit_const(b, &v_ext, c, flag_inv); + + b.x(ovf); + b.cx(ovf, flag_inv); + b.x(ovf); + sub_nbit_const(b, &v_ext, c); + b.free(flag_inv); + + let cuccaro_op = |b: &mut B, pos: usize, is_sub: bool| { + let pad_width = n + 1 - pos; + let padded = b.alloc_qubits(pad_width); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + let v_slice: Vec = v_ext[pos..n + 1].to_vec(); + let c_in = b.alloc_qubit(); + if is_sub { + cuccaro_sub(b, &padded, &v_slice, c_in); + } else { + cuccaro_add(b, &padded, &v_slice, c_in); + } + b.free(c_in); + for i in 0..k.min(pad_width) { + b.cx(spill[i], padded[i]); + } + b.free_vec(&padded); + }; + cuccaro_op(b, 32, true); + cuccaro_op(b, 10, true); + cuccaro_op(b, 6, false); + cuccaro_op(b, 4, true); + cuccaro_op(b, 0, true); + + for shift_i in (0..k).rev() { + for i in 0..n - 1 { + b.swap(v[i], v[i + 1]); + } + b.swap(v[n - 1], spill[k - 1 - shift_i]); + } + + b.free(ovf); + b.free_vec(&spill); +} + +pub(crate) fn mod_halve_inplace_fast(b: &mut B, v: &[QubitId], p: U256) { + mod_halve_inplace_fast_with_dirty(b, v, p, None) +} + +pub(crate) fn mod_halve_inplace_direct_const_fast(b: &mut B, v: &[QubitId], p: U256) { + let n = v.len(); + let ovf = b.alloc_qubit(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + b.cx(v[0], ovf); + csub_nbit_const_direct_fast(b, v, c, ovf); + for i in 0..n - 1 { + b.swap(v[i], v[i + 1]); + } + b.swap(v[n - 1], ovf); + b.free(ovf); +} + +pub(crate) fn mod_halve_inplace_fast_with_dirty( + b: &mut B, + v: &[QubitId], + p: U256, + dirty_src: Option<&[QubitId]>, +) { + let n = v.len(); + let ovf = b.alloc_qubit(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + b.cx(v[0], ovf); + + let use_venting = kal_vent_halve_enabled() && dirty_src.map_or(false, |d| d.len() >= n - 2); + if let Some(w) = double_carry_trunc_window() { + + csub_nbit_const_direct_trunc_fast(b, v, c, ovf, w); + } else if use_venting { + + let c_u64: u64 = c.as_limbs()[0] | (c.as_limbs()[1] << 32); + + let c_low = c.as_limbs()[0]; + let dirty = dirty_src.unwrap(); + let dirty_slice = &dirty[..n - 2]; + + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical(b, v, dirty_slice, &q_clean2, c_low, ovf); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + let _ = c_u64; + } else if direct_const_walks_enabled() + || std::env::var("KAL_DIRECT_CONST_HALVE").ok().as_deref() == Some("1") + { + csub_nbit_const_direct_fast(b, v, c, ovf); + } else { + csub_nbit_const_fast(b, v, c, ovf); + } + for i in 0..n - 1 { + b.swap(v[i], v[i + 1]); + } + b.swap(v[n - 1], ovf); + b.free(ovf); +} + +pub(crate) fn cmod_double_inplace_lazy(b: &mut B, v: &[QubitId], p: U256, ctrl: QubitId) { + let n = v.len(); + let ovf = b.alloc_qubit(); + cswap(b, ctrl, v[n - 1], ovf); + for i in (0..n - 1).rev() { + cswap(b, ctrl, v[i], v[i + 1]); + } + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + if let Some(w) = double_carry_trunc_window() { + cadd_nbit_const_direct_trunc_fast(b, v, c, ovf, w); + } else if direct_const_walks_enabled() + || std::env::var("KAL_DIRECT_CONST_DOUBLE").ok().as_deref() == Some("1") + { + cadd_nbit_const_direct_fast(b, v, c, ovf); + } else { + cadd_nbit_const_fast(b, v, c, ovf); + } + + b.ccx(ctrl, v[0], ovf); + b.free(ovf); +} + +pub(crate) fn cmod_halve_inplace_lazy(b: &mut B, v: &[QubitId], p: U256, ctrl: QubitId) { + let n = v.len(); + let ovf = b.alloc_qubit(); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + b.ccx(ctrl, v[0], ovf); + if let Some(w) = double_carry_trunc_window() { + csub_nbit_const_direct_trunc_fast(b, v, c, ovf, w); + } else if direct_const_walks_enabled() + || std::env::var("KAL_DIRECT_CONST_HALVE").ok().as_deref() == Some("1") + { + csub_nbit_const_direct_fast(b, v, c, ovf); + } else { + csub_nbit_const_fast(b, v, c, ovf); + } + for i in 0..n - 1 { + cswap(b, ctrl, v[i], v[i + 1]); + } + cswap(b, ctrl, v[n - 1], ovf); + b.free(ovf); +} + +pub(crate) fn mod_add_qq_fast(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + add_nbit_qq_fast(b, &a_ext, &acc_ext); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let use_vent = kal_vent_modadd_enabled(); + if use_vent { + let n1 = acc_ext.len(); + + let c_low = c.as_limbs()[0]; + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::iadd_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + false, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else if secp_direct_const_arith_enabled() { + add_nbit_const_direct_uncontrolled_fast(b, &acc_ext, c); + } else { + let n1 = acc_ext.len(); + let ca = load_const(b, n1, c); + add_nbit_qq_fast(b, &ca, &acc_ext); + unload_const(b, &ca, c); + } + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + b.x(flag); + + if use_vent { + let c_low = c.as_limbs()[0]; + let n1 = acc_ext.len(); + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + flag, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else if secp_direct_const_arith_enabled() { + csub_nbit_const_direct_fast(b, &acc_ext, c, flag); + } else { + let n1 = acc_ext.len(); + let ca = b.alloc_qubits(n1); + for i in 0..n1 { + if bit(c, i) { + b.cx(flag, ca[i]); + } + } + sub_nbit_qq_fast(b, &ca, &acc_ext); + for i in 0..n1 { + if bit(c, i) { + b.cx(flag, ca[i]); + } + } + b.free_vec(&ca); + } + b.x(flag); + b.cx(flag, acc_ovf); + if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { + let phase = b.alloc_bit(); + b.hmr(flag, phase); + cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); + } else { + cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); + } + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn mod_add_qq_fast_from_zero(b: &mut B, acc: &[QubitId], a: &[QubitId], p: U256) { + let n = acc.len(); + assert_eq!(n, a.len()); + debug_assert_eq!(n, 256); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let (a_ext, a_ovf) = ext_reg(b, a); + + for i in 0..n { + b.cx(a[i], acc[i]); + } + + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let use_vent = kal_vent_modadd_enabled(); + if use_vent { + let n1 = acc_ext.len(); + let c_low = c.as_limbs()[0]; + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::iadd_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + false, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else { + let n1 = acc_ext.len(); + let ca = load_const(b, n1, c); + add_nbit_qq_fast(b, &ca, &acc_ext); + unload_const(b, &ca, c); + } + let flag = b.alloc_qubit(); + b.cx(acc_ovf, flag); + b.x(flag); + if use_vent { + let c_low = c.as_limbs()[0]; + let n1 = acc_ext.len(); + let q_clean2: [QubitId; 2] = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical( + b, + &acc_ext, + &a_ext[..n1 - 2], + &q_clean2, + c_low, + flag, + ); + b.free(q_clean2[0]); + b.free(q_clean2[1]); + } else { + let n1 = acc_ext.len(); + let ca = b.alloc_qubits(n1); + for i in 0..n1 { + if bit(c, i) { + b.cx(flag, ca[i]); + } + } + sub_nbit_qq_fast(b, &ca, &acc_ext); + for i in 0..n1 { + if bit(c, i) { + b.cx(flag, ca[i]); + } + } + b.free_vec(&ca); + } + b.x(flag); + b.cx(flag, acc_ovf); + if std::env::var("MOD_FAST_FLAG_CONDITIONAL_REPLAY").ok().as_deref() == Some("1") { + let phase = b.alloc_bit(); + b.hmr(flag, phase); + cmp_lt_phase_conditioned(b, &acc_ext[..n], &a_ext[..n], phase); + } else { + cmp_lt_into_fast(b, &acc_ext[..n], &a_ext[..n], flag); + } + b.free(flag); + + unext_reg(b, a_ovf); + unext_reg(b, acc_ovf); + let _ = (acc_ext, a_ext); +} + +pub(crate) fn cmod_add_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { + let n = acc.len(); + let f = b.alloc_qubits(n); + for i in 0..n { + b.ccx(ctrl, a[i], f[i]); + } + mod_add_qq_fast(b, acc, &f, p); + + for i in 0..n { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} + +pub(crate) fn cmod_sub_qq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { + let n = acc.len(); + let f = b.alloc_qubits(n); + for i in 0..n { + b.ccx(ctrl, a[i], f[i]); + } + mod_sub_qq_fast(b, acc, &f, p); + for i in 0..n { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} + +pub(crate) fn cmod_add_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { + let n = acc.len(); + let f = b.alloc_qubits(n); + for i in 0..n { + b.ccx(ctrl, a[i], f[i]); + } + mod_add_qq(b, acc, &f, p); + for i in 0..n { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} + +pub(crate) fn cmod_sub_qq_lowq(b: &mut B, acc: &[QubitId], a: &[QubitId], ctrl: QubitId, p: U256) { + let n = acc.len(); + let f = b.alloc_qubits(n); + for i in 0..n { + b.ccx(ctrl, a[i], f[i]); + } + mod_sub_qq(b, acc, &f, p); + for i in 0..n { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} diff --git a/src/point_add/arith/multiply.rs b/src/point_add/arith/multiply.rs index f39852f4..9dc80644 100644 --- a/src/point_add/arith/multiply.rs +++ b/src/point_add/arith/multiply.rs @@ -1,2462 +1,2416 @@ - -use super::*; - -#[allow(dead_code)] -pub(crate) fn mod_mul_write_into_zero_acc_schoolbook_lowq( - b: &mut B, - acc: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, -) { - let n = acc.len(); - debug_assert_eq!(n, 256); - - let tmp_ext = b.alloc_qubits(2 * n); - schoolbook_mul_into_addsub_lowq(b, x, y, &tmp_ext); - - let lo: Vec = tmp_ext[0..n].to_vec(); - let hi: Vec = tmp_ext[n..2 * n].to_vec(); - mod_add_qq_fast_from_zero(b, acc, &lo, p); - mod_add_qq_fast(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_fast(b, &hi, p); - } - mod_add_qq_fast(b, acc, &hi, p); - for _ in 0..2 { - mod_double_inplace_fast(b, &hi, p); - } - mod_sub_qq_fast(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_fast(b, &hi, p); - } - mod_add_qq_fast(b, acc, &hi, p); - let (spill, flag_inv, ovf) = mod_shift_left_by_k(b, &hi, p, 22); - mod_add_qq(b, acc, &hi, p); - mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); - for _ in 0..10 { - mod_halve_inplace_fast(b, &hi, p); - } - - schoolbook_mul_into_addsub_lowq_inverse(b, x, y, &tmp_ext); - b.free_vec(&tmp_ext); -} - -pub(crate) fn controlled_add_subtract_lowq(b: &mut B, x: &[QubitId], acc: &[QubitId], ctrl: QubitId) { - let n = x.len(); - debug_assert_eq!(acc.len(), n + 1); - - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - - let c_in = b.alloc_qubit(); - - b.x(ctrl); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.cx(ctrl, c_in); - - cuccaro_add(b, &x_ext, acc, c_in); - - b.cx(ctrl, c_in); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.x(ctrl); - - b.free(c_in); - b.free(pad); -} - -pub(crate) fn controlled_add_subtract_lowq_inverse(b: &mut B, x: &[QubitId], acc: &[QubitId], ctrl: QubitId) { - let n = x.len(); - debug_assert_eq!(acc.len(), n + 1); - - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - - let c_in = b.alloc_qubit(); - - b.x(ctrl); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.cx(ctrl, c_in); - - cuccaro_sub(b, &x_ext, acc, c_in); - - b.cx(ctrl, c_in); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.x(ctrl); - - b.free(c_in); - b.free(pad); -} - -pub(crate) fn schoolbook_mul_into_addsub_lowq(b: &mut B, x: &[QubitId], y: &[QubitId], tmp_ext: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(y.len(), n); - debug_assert_eq!(tmp_ext.len(), 2 * n); - - let low = b.alloc_qubit(); - let mut wide: Vec = Vec::with_capacity(2 * n + 1); - wide.push(low); - wide.extend_from_slice(tmp_ext); - - for k in 0..n { - let slice: Vec = wide[k..k + n + 1].to_vec(); - controlled_add_subtract_lowq(b, x, &slice, y[k]); - } - - { - let pad = b.alloc_qubit(); - let mut y_ext = y.to_vec(); - y_ext.push(pad); - let slice: Vec = wide[n..2 * n + 1].to_vec(); - let c_in = b.alloc_qubit(); - b.x(c_in); - cuccaro_add(b, &y_ext, &slice, c_in); - b.x(c_in); - b.free(c_in); - b.free(pad); - } - - b.x(wide[2 * n]); - - { - let mut x_ext: Vec = x.to_vec(); - while x_ext.len() < 2 * n + 1 { - x_ext.push(b.alloc_qubit()); - } - let c_in = b.alloc_qubit(); - cuccaro_sub(b, &x_ext, &wide, c_in); - b.free(c_in); - for _ in n..2 * n + 1 { - let q = x_ext.pop().unwrap(); - b.free(q); - } - } - - { - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - let slice: Vec = wide[n..2 * n + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_add(b, &x_ext, &slice, c_in); - b.free(c_in); - b.free(pad); - } - - b.free(low); -} - -pub(crate) fn schoolbook_mul_into_addsub_lowq_inverse( - b: &mut B, - x: &[QubitId], - y: &[QubitId], - tmp_ext: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(y.len(), n); - debug_assert_eq!(tmp_ext.len(), 2 * n); - - let low = b.alloc_qubit(); - let mut wide: Vec = Vec::with_capacity(2 * n + 1); - wide.push(low); - wide.extend_from_slice(tmp_ext); - - { - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - let slice: Vec = wide[n..2 * n + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_sub(b, &x_ext, &slice, c_in); - b.free(c_in); - b.free(pad); - } - - { - let mut x_ext: Vec = x.to_vec(); - while x_ext.len() < 2 * n + 1 { - x_ext.push(b.alloc_qubit()); - } - let c_in = b.alloc_qubit(); - cuccaro_add(b, &x_ext, &wide, c_in); - b.free(c_in); - for _ in n..2 * n + 1 { - let q = x_ext.pop().unwrap(); - b.free(q); - } - } - - b.x(wide[2 * n]); - - { - let pad = b.alloc_qubit(); - let mut y_ext = y.to_vec(); - y_ext.push(pad); - let slice: Vec = wide[n..2 * n + 1].to_vec(); - let c_in = b.alloc_qubit(); - b.x(c_in); - cuccaro_sub(b, &y_ext, &slice, c_in); - b.x(c_in); - b.free(c_in); - b.free(pad); - } - for k in (0..n).rev() { - let slice: Vec = wide[k..k + n + 1].to_vec(); - controlled_add_subtract_lowq_inverse(b, x, &slice, y[k]); - } - - b.free(low); -} - -pub(crate) fn karatsuba_half_sum_compute(b: &mut B, lo: &[QubitId], hi: &[QubitId], acc: &[QubitId]) { - let h = lo.len(); - debug_assert_eq!(h, hi.len()); - debug_assert_eq!(acc.len(), h + 1); - for i in 0..h { - b.cx(lo[i], acc[i]); - } - let hi_pad = b.alloc_qubit(); - let mut hi_ext = hi.to_vec(); - hi_ext.push(hi_pad); - add_nbit_qq_fast(b, &hi_ext, acc); - b.free(hi_pad); -} - -pub(crate) fn karatsuba_half_sum_uncompute(b: &mut B, lo: &[QubitId], hi: &[QubitId], acc: &[QubitId]) { - let h = lo.len(); - let hi_pad = b.alloc_qubit(); - let mut hi_ext = hi.to_vec(); - hi_ext.push(hi_pad); - sub_nbit_qq_fast(b, &hi_ext, acc); - b.free(hi_pad); - for i in 0..h { - b.cx(lo[i], acc[i]); - } -} - -pub(crate) fn schoolbook_square_symmetric(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(tmp_ext.len(), 2 * n); - for i in 0..n { - - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_add_fast(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_inverse(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { - let n = x.len(); - for i in (0..n).rev() { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_sub_fast(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_lowq(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(tmp_ext.len(), 2 * n); - for i in 0..n { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_add(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_lowq_inverse(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { - let n = x.len(); - for i in (0..n).rev() { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - let c_in = b.alloc_qubit(); - cuccaro_sub(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_hosted( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], - host: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(tmp_ext.len(), 2 * n); - if square_selfhost_safe_lane_reuse_enabled() { - assert_qubit_slices_disjoint(&[x, tmp_ext, host]); - } - for i in 0..n { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - if square_selfhost_safe_lane_reuse_enabled() { - - assert!(host.len() > width); - cuccaro_add_fast_low_to_ext_borrowed_carries( - b, - &row, - &slice, - host[width], - &host[..width], - ); - } else { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - cuccaro_add_fast_borrowed_carries( - b, - &row_padded, - &slice, - c_in, - &host[..row_padded.len() - 1], - ); - b.free(c_in); - b.free(pad); - } - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_hosted_inverse( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], - host: &[QubitId], -) { - let n = x.len(); - if square_selfhost_safe_lane_reuse_enabled() { - assert_qubit_slices_disjoint(&[x, tmp_ext, host]); - } - for i in (0..n).rev() { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); - if square_selfhost_safe_lane_reuse_enabled() { - assert!(host.len() > width); - cuccaro_sub_fast_low_to_ext_borrowed_carries( - b, - &row, - &slice, - host[width], - &host[..width], - ); - } else { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - cuccaro_sub_fast_borrowed_carries( - b, - &row_padded, - &slice, - c_in, - &host[..row_padded.len() - 1], - ); - b.free(c_in); - b.free(pad); - } - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn square_selfhost_safe_lane_reuse_enabled() -> bool { - std::env::var("SQUARE_SELFHOST_SAFE_LANE_REUSE") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn assert_qubit_slices_disjoint(slices: &[&[QubitId]]) { - let mut seen = std::collections::BTreeSet::new(); - for slice in slices { - for &q in *slice { - assert!(seen.insert(q), "scratch lane q{} aliases an operand", q.0); - } - } -} - -pub(crate) fn square_selfhost_gate_suffix_carries(n: usize) -> usize { - std::env::var("SQUARE_SELFHOST_GATE_SUFFIX_CARRIES") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) - .min(n.saturating_sub(1)) -} - -pub(crate) fn square_row_windows() -> usize { - std::env::var("SQUARE_ROW_WINDOWS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -fn square_row_window_min_width() -> usize { - std::env::var("SQUARE_ROW_WINDOW_MIN_WIDTH") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(96) -} - -fn square_row_max_seg() -> usize { - std::env::var("SQUARE_ROW_MAX_SEG") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -fn square_cleanup_direction(raw: &str) -> Option { - match raw.trim().to_ascii_lowercase().as_str() { - "f" | "forward" | "false" | "0" => Some(false), - "r" | "reverse" | "true" | "1" => Some(true), - _ => None, - } -} - -fn square_row_window_clean_compare_bits( - row: usize, - window: usize, - reverse: bool, -) -> usize { - let default_bits = std::env::var("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0); - let row_bits = std::env::var("SQUARE_ROW_WINDOW_CLEAN_ROW_BITS") - .ok() - .and_then(|spec| { - spec.split(',').rev().find_map(|item| { - let (raw_row, raw_bits) = item.trim().split_once(':')?; - if raw_row.trim().parse::().ok()? != row { - return None; - } - raw_bits - .trim() - .parse::() - .ok() - .filter(|bits| (1..=N).contains(bits)) - }) - }) - .unwrap_or(default_bits); - let Ok(spec) = std::env::var("SQUARE_ROW_WINDOW_CLEAN_SITE_BITS") else { - return row_bits; - }; - for item in spec.split(',').rev() { - let fields: Vec<_> = item.trim().split(':').map(str::trim).collect(); - if fields.len() != 4 { - continue; - } - if fields[0].parse::().ok() != Some(row) - || fields[1].parse::().ok() != Some(window) - || square_cleanup_direction(fields[2]) != Some(reverse) - { - continue; - } - if let Ok(bits) = fields[3].parse::() { - if (1..=N).contains(&bits) { - return bits; - } - } - } - row_bits -} - -fn square_row_window_measured_carry_clear_enabled() -> bool { - std::env::var("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR") - .ok() - .as_deref() - == Some("1") -} - -fn square_row_bit_set(b: &mut B, x: &[QubitId], i: usize, j: usize, t: QubitId) { - if j == 0 { - b.cx(x[i], t); - } else if j == 1 { - - } else { - b.ccx(x[i], x[i + 1 + (j - 2)], t); - } -} - -fn square_row_bit_clear_hmr(b: &mut B, x: &[QubitId], i: usize, j: usize, t: QubitId) { - if j == 0 { - b.cx(x[i], t); - } else if j == 1 { - - } else { - let m = b.alloc_bit(); - b.hmr(t, m); - b.cz_if(x[i], x[i + 1 + (j - 2)], m); - } -} - -fn square_row_windowed_apply( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], - i: usize, - width: usize, - windows: usize, - forward: bool, -) { - let base = 2 * i; - let windows = windows.max(1).min(width); - - let bounds: Vec<(usize, usize)> = (0..windows) - .map(|w| { - let lo = (w * width) / windows; - let hi = ((w + 1) * width) / windows; - (lo, hi) - }) - .filter(|&(lo, hi)| hi > lo) - .collect(); - let nwin = bounds.len(); - - let build_seg = |b: &mut B, lo: usize, hi: usize| -> Vec { - let seg = b.alloc_qubits(hi - lo); - for (k, &q) in seg.iter().enumerate() { - square_row_bit_set(b, x, i, lo + k, q); - } - seg - }; - let clear_seg = |b: &mut B, lo: usize, seg: &[QubitId]| { - for (k, &q) in seg.iter().enumerate() { - square_row_bit_clear_hmr(b, x, i, lo + k, q); - } - b.free_vec(seg); - }; - - let row_top = base + width + 1; - let borrow_lane = |b: &mut B, _need: usize| -> Vec { - - tmp_ext[row_top..row_top + _need].to_vec() - }; - - let mut carry_in = b.alloc_qubit(); - let first_carry = carry_in; - let mut couts: Vec<(QubitId, usize, usize, QubitId, usize)> = Vec::new(); - for (wi, &(lo, hi)) in bounds.iter().enumerate() { - let last = wi == nwin - 1; - let seg = build_seg(b, lo, hi); - let seg_w = hi - lo; - - let pad = b.alloc_qubit(); - let mut a_block = seg.clone(); - a_block.push(pad); - let high = if last { - - tmp_ext[base + hi] - } else { - b.alloc_qubit() - }; - let mut acc_block: Vec = tmp_ext[base + lo..base + hi].to_vec(); - acc_block.push(high); - let nblk = a_block.len(); - let carries = borrow_lane(b, nblk - 1); - if forward { - cuccaro_add_fast_borrowed_carries(b, &a_block, &acc_block, carry_in, &carries); - } else { - cuccaro_sub_fast_borrowed_carries(b, &a_block, &acc_block, carry_in, &carries); - } - b.free(pad); - if last { - - } else { - couts.push((high, lo, hi, carry_in, wi)); - carry_in = high; - } - clear_seg(b, lo, &seg); - } - - let slow_cmp = std::env::var("SQUARE_ROW_WINDOW_SLOW_CMP").ok().as_deref() == Some("1"); - let measured_clear = square_row_window_measured_carry_clear_enabled(); - for &(cout, lo, hi, cin, window) in couts.iter().rev() { - let clean_cmp_bits = - square_row_window_clean_compare_bits(i, window, !forward); - let seg_w = hi - lo; - let trunc_w = if clean_cmp_bits == 0 { - seg_w - } else { - clean_cmp_bits.min(seg_w) - }; - if trunc_w < seg_w { - let suffix_lo = hi - trunc_w; - let seg = build_seg(b, suffix_lo, hi); - let carries = tmp_ext[row_top..row_top + trunc_w].to_vec(); - let cmp_cin = b.alloc_qubit(); - if forward { - if measured_clear { - let phase = b.alloc_bit(); - b.hmr(cout, phase); - cmp_lt_phase_conditioned_with_cin_borrowed_carries( - b, - &tmp_ext[base + suffix_lo..base + hi], - &seg, - cmp_cin, - &carries, - phase, - ); - } else { - cmp_lt_into_fast_with_cin_borrowed_carries( - b, - &tmp_ext[base + suffix_lo..base + hi], - &seg, - cmp_cin, - cout, - &carries, - ); - } - } else { - for &q in &seg { - b.x(q); - } - if measured_clear { - let phase = b.alloc_bit(); - b.hmr(cout, phase); - cmp_lt_phase_conditioned_with_cin_borrowed_carries( - b, - &seg, - &tmp_ext[base + suffix_lo..base + hi], - cmp_cin, - &carries, - phase, - ); - } else { - cmp_lt_into_fast_with_cin_borrowed_carries( - b, - &seg, - &tmp_ext[base + suffix_lo..base + hi], - cmp_cin, - cout, - &carries, - ); - } - for &q in &seg { - b.x(q); - } - } - b.free(cmp_cin); - clear_seg(b, suffix_lo, &seg); - } else { - let seg = build_seg(b, lo, hi); - let carries = tmp_ext[row_top..row_top + seg_w].to_vec(); - if forward { - - if measured_clear { - let phase = b.alloc_bit(); - b.hmr(cout, phase); - cmp_lt_phase_conditioned_with_cin_borrowed_carries( - b, - &tmp_ext[base + lo..base + hi], - &seg, - cin, - &carries, - phase, - ); - } else if slow_cmp { - cmp_lt_into_with_cin_slow(b, &tmp_ext[base + lo..base + hi], &seg, cin, cout); - } else { - cmp_lt_into_fast_with_cin_borrowed_carries( - b, &tmp_ext[base + lo..base + hi], &seg, cin, cout, &carries, - ); - } - } else { - - for k in 0..seg_w { - b.x(seg[k]); - } - if measured_clear { - let phase = b.alloc_bit(); - b.hmr(cout, phase); - cmp_lt_phase_conditioned_with_cin_borrowed_carries( - b, - &seg, - &tmp_ext[base + lo..base + hi], - cin, - &carries, - phase, - ); - } else if slow_cmp { - cmp_lt_into_with_cin_slow(b, &seg, &tmp_ext[base + lo..base + hi], cin, cout); - } else { - cmp_lt_into_fast_with_cin_borrowed_carries( - b, &seg, &tmp_ext[base + lo..base + hi], cin, cout, &carries, - ); - } - for k in 0..seg_w { - b.x(seg[k]); - } - } - clear_seg(b, lo, &seg); - } - b.free(cout); - } - b.free(first_carry); -} - -pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { - schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement(b, x, tmp_ext, &[]); -} - -pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], - clean_supplement: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(tmp_ext.len(), 2 * n); - let safe_reuse = square_selfhost_safe_lane_reuse_enabled(); - if safe_reuse { - assert_qubit_slices_disjoint(&[x, tmp_ext, clean_supplement]); - } - let gate_prefix_rows = std::env::var("SQUARE_SELFHOST_GATE_PREFIX_ROWS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0); - let row_windows = square_row_windows(); - let row_window_min = square_row_window_min_width(); - let max_seg = square_row_max_seg(); - for i in 0..n { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - if max_seg > 0 && i >= gate_prefix_rows && width > max_seg { - let w = width.div_ceil(max_seg); - square_row_windowed_apply(b, x, tmp_ext, i, width, w, true); - continue; - } - if max_seg == 0 && row_windows >= 1 && i >= gate_prefix_rows && width >= row_window_min { - square_row_windowed_apply(b, x, tmp_ext, i, width, row_windows, true); - continue; - } - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let hi = 2 * i + width + 1; - let slice: Vec = tmp_ext[2 * i..hi].to_vec(); - if i < gate_prefix_rows { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - cuccaro_add(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - } else if safe_reuse { - let need = row.len() - square_selfhost_gate_suffix_carries(row.len()); - let avail = tmp_ext.len() - hi; - let from_tmp = need.min(avail); - let from_supplement = (need - from_tmp).min(clean_supplement.len()); - let from_global = need - from_tmp - from_supplement; - let gpool = b.alloc_qubits(from_global); - let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); - carries.extend_from_slice(&clean_supplement[..from_supplement]); - carries.extend_from_slice(&gpool); - cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin(b, &row, &slice, &carries); - b.free_vec(&gpool); - } else { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - let need = row_padded.len() - 1; - let avail = tmp_ext.len() - hi; - let from_tmp = need.min(avail); - let from_global = need - from_tmp; - let gpool = b.alloc_qubits(from_global); - let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); - carries.extend_from_slice(&gpool); - cuccaro_add_fast_borrowed_carries(b, &row_padded, &slice, c_in, &carries); - b.free(c_in); - b.free_vec(&gpool); - b.free(pad); - } - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_inverse( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], -) { - schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement(b, x, tmp_ext, &[]); -} - -pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement( - b: &mut B, - x: &[QubitId], - tmp_ext: &[QubitId], - clean_supplement: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(tmp_ext.len(), 2 * n); - let safe_reuse = square_selfhost_safe_lane_reuse_enabled(); - if safe_reuse { - assert_qubit_slices_disjoint(&[x, tmp_ext, clean_supplement]); - } - let gate_prefix_rows = std::env::var("SQUARE_SELFHOST_GATE_PREFIX_ROWS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0); - let row_windows = square_row_windows(); - let row_window_min = square_row_window_min_width(); - let max_seg = square_row_max_seg(); - for i in (0..n).rev() { - let width = if i == n - 1 { 1 } else { n - i + 1 }; - let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; - if max_seg > 0 && i >= gate_prefix_rows && width > max_seg { - let w = width.div_ceil(max_seg); - square_row_windowed_apply(b, x, tmp_ext, i, width, w, false); - continue; - } - if max_seg == 0 && row_windows >= 1 && i >= gate_prefix_rows && width >= row_window_min { - square_row_windowed_apply(b, x, tmp_ext, i, width, row_windows, false); - continue; - } - let row = b.alloc_qubits(width); - b.cx(x[i], row[0]); - for k in 0..num_cross { - b.ccx(x[i], x[i + 1 + k], row[k + 2]); - } - let hi = 2 * i + width + 1; - let slice: Vec = tmp_ext[2 * i..hi].to_vec(); - if i < gate_prefix_rows { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - cuccaro_sub(b, &row_padded, &slice, c_in); - b.free(c_in); - b.free(pad); - } else if safe_reuse { - let need = row.len() - square_selfhost_gate_suffix_carries(row.len()); - let avail = tmp_ext.len() - hi; - let from_tmp = need.min(avail); - let from_supplement = (need - from_tmp).min(clean_supplement.len()); - let from_global = need - from_tmp - from_supplement; - let gpool = b.alloc_qubits(from_global); - let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); - carries.extend_from_slice(&clean_supplement[..from_supplement]); - carries.extend_from_slice(&gpool); - cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin(b, &row, &slice, &carries); - b.free_vec(&gpool); - } else { - let pad = b.alloc_qubit(); - let mut row_padded = row.clone(); - row_padded.push(pad); - let c_in = b.alloc_qubit(); - let need = row_padded.len() - 1; - let avail = tmp_ext.len() - hi; - let from_tmp = need.min(avail); - let from_global = need - from_tmp; - let gpool = b.alloc_qubits(from_global); - let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); - carries.extend_from_slice(&gpool); - cuccaro_sub_fast_borrowed_carries(b, &row_padded, &slice, c_in, &carries); - b.free(c_in); - b.free_vec(&gpool); - b.free(pad); - } - b.cx(x[i], row[0]); - for k in 0..num_cross { - let m = b.alloc_bit(); - b.hmr(row[k + 2], m); - b.cz_if(x[i], x[i + 1 + k], m); - } - b.free_vec(&row); - } -} - -pub(crate) fn kara_z2_selfhost_enabled() -> bool { - std::env::var("KARA_Z2_SELFHOST").ok().as_deref() != Some("0") -} - -pub(crate) fn xtail_sq_selfhost_enabled() -> bool { - std::env::var("XTAIL_SQ_SELFHOST").ok().as_deref() != Some("0") -} - -fn round84_inplace_solinas_fold_enabled() -> bool { - std::env::var("ROUND84_INPLACE_SOLINAS_FOLD") - .ok() - .as_deref() - == Some("1") -} - -fn round84_fold_fast_add_enabled() -> bool { - std::env::var("ROUND84_FOLD_FAST_ADD").ok().as_deref() == Some("1") -} -#[inline] -fn round84_add_small(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - if round84_fold_fast_add_enabled() { - add_nbit_qq_fast(b, a, acc); - } else { - add_nbit_qq(b, a, acc); - } -} -#[inline] -fn round84_sub_small(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - if round84_fold_fast_add_enabled() { - sub_nbit_qq_fast(b, a, acc); - } else { - sub_nbit_qq(b, a, acc); - } -} - -fn round84_inplace_quotient_carry_trunc_window() -> usize { - std::env::var("ROUND84_INPLACE_QUOTIENT_CARRY_TRUNC_W") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(21) - .max(1) -} - -fn round84_inplace_vent_carry_enabled() -> bool { - std::env::var("ROUND84_INPLACE_VENT_CARRY") - .ok() - .as_deref() - == Some("1") -} - -fn round84_correction_wrap_borrow_quotient_top_enabled() -> bool { - std::env::var("ROUND84_CORRECTION_WRAP_BORROW_QUOTIENT_TOP") - .ok() - .as_deref() - == Some("1") -} - -fn round84_keep_quotient_product_enabled() -> bool { - std::env::var("ROUND84_KEEP_QUOTIENT_PRODUCT") - .ok() - .as_deref() - == Some("1") -} - -fn round84_qprod_naf_enabled() -> bool { - std::env::var("R84_QPROD_NAF").ok().as_deref() == Some("1") -} - -fn round84_qprod_short_enabled() -> bool { - std::env::var("ROUND84_QPROD_SHORT").ok().as_deref() == Some("1") -} - -struct Round84FoldStep { - shift: usize, - add: bool, - wrap: QubitId, -} - -struct Round84AggregateFold { - steps: Vec, - quotient: Vec, - correction_wrap: QubitId, - correction_wrap_owned: bool, - product: Option>, -} - -fn round84_update_fold_quotient( - b: &mut B, - quotient: &[QubitId], - hi: &[QubitId], - step: &Round84FoldStep, - inverse: bool, -) { - let add = step.add != inverse; - let update_wrap = |b: &mut B| { - if add { - cadd_nbit_const_direct_fast(b, quotient, U256::from(1), step.wrap); - } else { - csub_nbit_const_direct_fast(b, quotient, U256::from(1), step.wrap); - } - }; - let update_spill = |b: &mut B| { - if step.shift == 0 { - return; - } - let pad = b.alloc_qubits(quotient.len() - step.shift); - let mut spill = hi[hi.len() - step.shift..].to_vec(); - spill.extend_from_slice(&pad); - if add { - add_nbit_qq(b, &spill, quotient); - } else { - sub_nbit_qq(b, &spill, quotient); - } - b.free_vec(&pad); - }; - - if inverse { - update_wrap(b); - update_spill(b); - } else { - update_spill(b); - update_wrap(b); - } -} - -fn round84_compute_quotient_c_product(b: &mut B, quotient: &[QubitId], dirty: &[QubitId]) -> Vec { - - let q = "ient[..33]; - let product = b.alloc_qubits(66); - for i in 0..q.len() { - b.cx(q[i], product[i]); - } - if round84_qprod_naf_enabled() { - for (shift, add) in [(10usize, true), (32, true), (5, false), (4, false)] { - if round84_qprod_vent_pad_enabled() - && (product.len() - shift - q.len()) >= round84_qprod_vent_pad_min_width() - { - round84_qprod_shifted_addsub_vented(b, q, &product, shift, add, dirty); - continue; - } - let target = &product[shift..]; - if round84_qprod_short_enabled() { - if add { - add_short_to_long_qq_fast_no_cin(b, q, target); - } else { - sub_short_to_long_qq_fast_no_cin(b, q, target); - } - } else { - let pad = b.alloc_qubits(target.len() - q.len()); - let mut source = q.to_vec(); - source.extend_from_slice(&pad); - if add { - round84_add_small(b, &source, target); - } else { - round84_sub_small(b, &source, target); - } - b.free_vec(&pad); - } - } - } else { - for shift in [4usize, 6, 7, 8, 9, 32] { - let target = &product[shift..]; - if round84_qprod_short_enabled() { - add_short_to_long_qq_fast_no_cin(b, q, target); - } else { - let pad = b.alloc_qubits(target.len() - q.len()); - let mut source = q.to_vec(); - source.extend_from_slice(&pad); - round84_add_small(b, &source, target); - b.free_vec(&pad); - } - } - } - product -} - -fn round84_uncompute_quotient_c_product(b: &mut B, quotient: &[QubitId], product: &[QubitId], dirty: &[QubitId]) { - let q = "ient[..33]; - if round84_qprod_naf_enabled() { - for (shift, add) in [(10usize, true), (32, true), (5, false), (4, false)] - .into_iter() - .rev() - { - if round84_qprod_vent_pad_enabled() - && (product.len() - shift - q.len()) >= round84_qprod_vent_pad_min_width() - { - - round84_qprod_shifted_addsub_vented(b, q, product, shift, !add, dirty); - continue; - } - let target = &product[shift..]; - if round84_qprod_short_enabled() { - if add { - sub_short_to_long_qq_fast_no_cin(b, q, target); - } else { - add_short_to_long_qq_fast_no_cin(b, q, target); - } - } else { - let pad = b.alloc_qubits(target.len() - q.len()); - let mut source = q.to_vec(); - source.extend_from_slice(&pad); - if add { - round84_sub_small(b, &source, target); - } else { - round84_add_small(b, &source, target); - } - b.free_vec(&pad); - } - } - } else { - for shift in [4usize, 6, 7, 8, 9, 32].into_iter().rev() { - let target = &product[shift..]; - if round84_qprod_short_enabled() { - sub_short_to_long_qq_fast_no_cin(b, q, target); - } else { - let pad = b.alloc_qubits(target.len() - q.len()); - let mut source = q.to_vec(); - source.extend_from_slice(&pad); - round84_sub_small(b, &source, target); - b.free_vec(&pad); - } - } - } - for i in 0..q.len() { - b.cx(q[i], product[i]); - } - b.free_vec(product); -} - -fn round84_add_narrow_correction( - b: &mut B, - lo: &[QubitId], - product: &[QubitId], - dirty: &[QubitId], - borrowed_wrap: Option, -) -> (QubitId, bool) { - let (wrap, owned_wrap) = borrowed_wrap.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); - let source_top = b.alloc_qubit(); - let mut target_ext = lo[..product.len()].to_vec(); - target_ext.push(wrap); - let mut source_ext = product.to_vec(); - source_ext.push(source_top); - round84_add_small(b, &source_ext, &target_ext); - b.free(source_top); - let high = &lo[product.len()..]; - if round84_inplace_vent_carry_enabled() { - let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; - venting::ciadd_dirty_2clean_classical( - b, - high, - &dirty[..high.len() - 2], - &clean2, - 1, - wrap, - false, - ); - b.free(clean2[0]); - b.free(clean2[1]); - } else { - cadd_nbit_const_direct_trunc_fast( - b, - high, - U256::from(1), - wrap, - round84_inplace_quotient_carry_trunc_window(), - ); - } - (wrap, owned_wrap) -} - -fn round84_sub_narrow_correction( - b: &mut B, - lo: &[QubitId], - product: &[QubitId], - wrap: QubitId, - dirty: &[QubitId], - owned_wrap: bool, -) { - let high = &lo[product.len()..]; - if round84_inplace_vent_carry_enabled() { - let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical(b, high, &dirty[..high.len() - 2], &clean2, 1, wrap); - b.free(clean2[0]); - b.free(clean2[1]); - } else { - csub_nbit_const_direct_trunc_fast( - b, - high, - U256::from(1), - wrap, - round84_inplace_quotient_carry_trunc_window(), - ); - } - let source_top = b.alloc_qubit(); - let mut target_ext = lo[..product.len()].to_vec(); - target_ext.push(wrap); - let mut source_ext = product.to_vec(); - source_ext.push(source_top); - round84_sub_small(b, &source_ext, &target_ext); - b.free(source_top); - if owned_wrap { - b.free(wrap); - } -} - -fn round84_fold_hi_into_lo_aggregate( - b: &mut B, - lo: &[QubitId], - hi: &[QubitId], - dirty: &[QubitId], -) -> Round84AggregateFold { - let n = lo.len(); - let quotient = b.alloc_qubits(34); - - let terms = [ - (0usize, true), - (4, false), - (5, false), - (10, true), - (32, true), - ]; - let mut steps = Vec::with_capacity(terms.len()); - - for (shift, add) in terms { - let width = n - shift; - let wrap = b.alloc_qubit(); - let source_top = b.alloc_qubit(); - let mut target_ext = lo[shift..].to_vec(); - target_ext.push(wrap); - let mut source_ext = hi[..width].to_vec(); - source_ext.push(source_top); - if add { - add_nbit_qq(b, &source_ext, &target_ext); - } else { - sub_nbit_qq(b, &source_ext, &target_ext); - } - b.free(source_top); - - let step = Round84FoldStep { shift, add, wrap }; - round84_update_fold_quotient(b, "ient, hi, &step, false); - steps.push(step); - } - - let product = round84_compute_quotient_c_product(b, "ient, dirty); - let borrowed_correction_wrap = round84_correction_wrap_borrow_quotient_top_enabled() - .then_some(quotient[33]); - let (correction_wrap, correction_wrap_owned) = - round84_add_narrow_correction(b, lo, &product, dirty, borrowed_correction_wrap); - let product = if round84_keep_quotient_product_enabled() { - Some(product) - } else { - round84_uncompute_quotient_c_product(b, "ient, &product, dirty); - None - }; - Round84AggregateFold { - steps, - quotient, - correction_wrap, - correction_wrap_owned, - product, - } -} - -fn round84_unfold_hi_from_lo_aggregate( - b: &mut B, - lo: &[QubitId], - hi: &[QubitId], - dirty: &[QubitId], - state: Round84AggregateFold, -) { - let product = state - .product - .unwrap_or_else(|| round84_compute_quotient_c_product(b, &state.quotient, dirty)); - round84_sub_narrow_correction( - b, - lo, - &product, - state.correction_wrap, - dirty, - state.correction_wrap_owned, - ); - round84_uncompute_quotient_c_product(b, &state.quotient, &product, dirty); - - for step in state.steps.into_iter().rev() { - round84_update_fold_quotient(b, &state.quotient, hi, &step, true); - let width = lo.len() - step.shift; - let source_top = b.alloc_qubit(); - let mut target_ext = lo[step.shift..].to_vec(); - target_ext.push(step.wrap); - let mut source_ext = hi[..width].to_vec(); - source_ext.push(source_top); - if step.add { - sub_nbit_qq(b, &source_ext, &target_ext); - } else { - add_nbit_qq(b, &source_ext, &target_ext); - } - b.free(source_top); - b.free(step.wrap); - } - b.free_vec(&state.quotient); -} - -pub(crate) fn squaring_sub_from_acc_schoolbook(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { - let n = acc.len(); - debug_assert_eq!(n, 256); - debug_assert_eq!(x.len(), n); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let tmp_ext = b.alloc_qubits(2 * n); - - schoolbook_square_symmetric(b, x, &tmp_ext); - - let lo: Vec = tmp_ext[0..n].to_vec(); - let hi: Vec = tmp_ext[n..2 * n].to_vec(); - mod_sub_qq_fast(b, acc, &lo, p); - let _ = c; - - mod_sub_qq_fast(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_fast(b, &hi, p); - } - mod_sub_qq_fast(b, acc, &hi, p); - for _ in 0..2 { - mod_double_inplace_fast(b, &hi, p); - } - mod_add_qq_fast(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_fast(b, &hi, p); - } - mod_sub_qq_fast(b, acc, &hi, p); - let (spill, flag_inv, ovf) = mod_shift_left_by_k(b, &hi, p, 22); - mod_sub_qq(b, acc, &hi, p); - mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); - for _ in 0..10 { - mod_halve_inplace_fast(b, &hi, p); - } - - schoolbook_square_symmetric_inverse(b, x, &tmp_ext); - - b.free_vec(&tmp_ext); -} - -pub(crate) fn squaring_sub_from_acc_karatsuba(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { - let n = acc.len(); - debug_assert_eq!(n, 256); - debug_assert_eq!(x.len(), n); - let h = n / 2; - let x_lo: Vec = x[0..h].to_vec(); - let x_hi: Vec = x[h..n].to_vec(); - - let mut z1_reg = b.alloc_qubits(2 * (h + 1)); - - let free_z1_top = std::env::var("KARA_FREE_Z1_TOPBIT").ok().as_deref() == Some("1"); - - let z02_lowq = std::env::var("KARA_Z02_LOWQ").ok().as_deref() == Some("1"); - - { - let x_sum = b.alloc_qubits(h + 1); - karatsuba_half_sum_compute(b, &x_lo, &x_hi, &x_sum); - schoolbook_square_symmetric(b, &x_sum, &z1_reg); - karatsuba_half_sum_uncompute(b, &x_lo, &x_hi, &x_sum); - b.free_vec(&x_sum); - } - - let tmp_ext = b.alloc_qubits(2 * n); - - { - let slice: Vec = tmp_ext[0..2 * h].to_vec(); - if z02_lowq { - - let host: Vec = tmp_ext[2 * h..4 * h].to_vec(); - schoolbook_square_symmetric_hosted(b, &x_lo, &slice, &host); - } else { - schoolbook_square_symmetric(b, &x_lo, &slice); - } - } - { - let slice: Vec = tmp_ext[2 * h..4 * h].to_vec(); - if z02_lowq { - if kara_z2_selfhost_enabled() { - if square_selfhost_safe_lane_reuse_enabled() { - - let clean_square_bits = [z1_reg[1], tmp_ext[1]]; - schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement( - b, - &x_hi, - &slice, - &clean_square_bits, - ); - } else { - schoolbook_square_symmetric_lowq_selfhosted(b, &x_hi, &slice); - } - } else { - schoolbook_square_symmetric_lowq(b, &x_hi, &slice); - } - } else { - schoolbook_square_symmetric(b, &x_hi, &slice); - } - } - - { - let pad = b.alloc_qubits(2); - let mut z0_ext: Vec = tmp_ext[0..2 * h].to_vec(); - z0_ext.extend_from_slice(&pad); - sub_nbit_qq(b, &z0_ext, &z1_reg); - b.free_vec(&pad); - } - { - let pad = b.alloc_qubits(2); - let mut z2_ext: Vec = tmp_ext[2 * h..4 * h].to_vec(); - z2_ext.extend_from_slice(&pad); - sub_nbit_qq(b, &z2_ext, &z1_reg); - b.free_vec(&pad); - } - - if free_z1_top { - let top = z1_reg.pop().expect("z1_reg width 2*(h+1) >= 2"); - b.free(top); - } - { - let pad = b.alloc_qubits(3 * h - z1_reg.len()); - let mut z1_ext: Vec = z1_reg.to_vec(); - z1_ext.extend_from_slice(&pad); - let acc_slice: Vec = tmp_ext[h..4 * h].to_vec(); - add_nbit_qq(b, &z1_ext, &acc_slice); - b.free_vec(&pad); - } - - let mod_fast = std::env::var("KARA_SOL_MOD_FAST").ok().as_deref() == Some("1"); - let dbl_fast = std::env::var("KARA_SOL_DBL_FAST").ok().as_deref() == Some("1"); - let shift_fast = std::env::var("KARA_SOL_SHIFT_FAST").ok().as_deref() == Some("1"); - let lo: Vec = tmp_ext[0..n].to_vec(); - let hi: Vec = tmp_ext[n..2 * n].to_vec(); - - let mod_vent = std::env::var("KARA_SOL_MOD_VENT").ok().as_deref() == Some("1"); - let mod_sub = |b: &mut B, acc: &[QubitId], a: &[QubitId]| { - if mod_vent { - mod_sub_qq_vent(b, acc, a, p); - } else if mod_fast { - mod_sub_qq_fast(b, acc, a, p); - } else { - mod_sub_qq(b, acc, a, p); - } - }; - let mod_add = |b: &mut B, acc: &[QubitId], a: &[QubitId]| { - if mod_vent { - mod_add_qq_vent(b, acc, a, p); - } else if mod_fast { - mod_add_qq_fast(b, acc, a, p); - } else { - mod_add_qq(b, acc, a, p); - } - }; - let mod_dbl = |b: &mut B, v: &[QubitId]| { - if dbl_fast { - mod_double_inplace_fast(b, v, p); - } else { - mod_double_inplace_direct_const_fast(b, v, p); - } - }; - let mod_hlv = |b: &mut B, v: &[QubitId]| { - if dbl_fast { - mod_halve_inplace_fast(b, v, p); - } else { - mod_halve_inplace_direct_const_fast(b, v, p); - } - }; - b.set_phase("r84k_sol_subadd"); - mod_sub(b, acc, &lo); - mod_sub(b, acc, &hi); - for _ in 0..4 { - mod_dbl(b, &hi); - } - mod_sub(b, acc, &hi); - for _ in 0..2 { - mod_dbl(b, &hi); - } - mod_add(b, acc, &hi); - for _ in 0..4 { - mod_dbl(b, &hi); - } - mod_sub(b, acc, &hi); - b.set_phase("r84k_sol_shift"); - - let shift_dirty = std::env::var("ROUND84_XTAIL_BORROW_CARRIES") - .ok() - .as_deref() - == Some("1"); - if shift_dirty { - - b.set_phase("r84k_sol_dbl22"); - for _ in 0..22 { - mod_dbl(b, &hi); - } - b.set_phase("r84k_sol_midsub"); - mod_sub(b, acc, &hi); - b.set_phase("r84k_sol_hlv22"); - for _ in 0..22 { - mod_hlv(b, &hi); - } - } else { - b.set_phase("r84k_sol_shiftL"); - let (spill, flag_inv, ovf) = if shift_fast { - mod_shift_left_by_k(b, &hi, p, 22) - } else { - mod_shift_left_by_k_lowq(b, &hi, p, 22) - }; - b.set_phase("r84k_sol_midsub"); - mod_sub(b, acc, &hi); - b.set_phase("r84k_sol_shiftR"); - if shift_fast { - mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); - } else { - mod_shift_right_by_k_lowq(b, &hi, p, 22, spill, flag_inv, ovf); - } - } - b.set_phase("r84k_sol_halve"); - for _ in 0..10 { - mod_hlv(b, &hi); - } - - b.set_phase("r84k_inv_combine"); - { - let pad = b.alloc_qubits(3 * h - z1_reg.len()); - let mut z1_ext: Vec = z1_reg.to_vec(); - z1_ext.extend_from_slice(&pad); - let acc_slice: Vec = tmp_ext[h..4 * h].to_vec(); - sub_nbit_qq(b, &z1_ext, &acc_slice); - b.free_vec(&pad); - } - - if free_z1_top { - let top = b.alloc_qubit(); - z1_reg.push(top); - } - { - let pad = b.alloc_qubits(2); - let mut z2_ext: Vec = tmp_ext[2 * h..4 * h].to_vec(); - z2_ext.extend_from_slice(&pad); - add_nbit_qq(b, &z2_ext, &z1_reg); - b.free_vec(&pad); - } - { - let pad = b.alloc_qubits(2); - let mut z0_ext: Vec = tmp_ext[0..2 * h].to_vec(); - z0_ext.extend_from_slice(&pad); - add_nbit_qq(b, &z0_ext, &z1_reg); - b.free_vec(&pad); - } - - b.set_phase("r84k_z_inv_squares"); - { - let slice: Vec = tmp_ext[2 * h..4 * h].to_vec(); - if z02_lowq { - if kara_z2_selfhost_enabled() { - if square_selfhost_safe_lane_reuse_enabled() { - - let clean_square_bits = [z1_reg[1], tmp_ext[1]]; - schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement( - b, - &x_hi, - &slice, - &clean_square_bits, - ); - } else { - schoolbook_square_symmetric_lowq_selfhosted_inverse(b, &x_hi, &slice); - } - } else { - schoolbook_square_symmetric_lowq_inverse(b, &x_hi, &slice); - } - } else { - schoolbook_square_symmetric_inverse(b, &x_hi, &slice); - } - } - { - let slice: Vec = tmp_ext[0..2 * h].to_vec(); - if z02_lowq { - - let host: Vec = tmp_ext[2 * h..4 * h].to_vec(); - schoolbook_square_symmetric_hosted_inverse(b, &x_lo, &slice, &host); - } else { - schoolbook_square_symmetric_inverse(b, &x_lo, &slice); - } - } - b.free_vec(&tmp_ext); - - { - let x_sum = b.alloc_qubits(h + 1); - karatsuba_half_sum_compute(b, &x_lo, &x_hi, &x_sum); - schoolbook_square_symmetric_inverse(b, &x_sum, &z1_reg); - karatsuba_half_sum_uncompute(b, &x_lo, &x_hi, &x_sum); - b.free_vec(&x_sum); - } - - b.free_vec(&z1_reg); -} - -pub(crate) fn squaring_sub_from_acc_schoolbook_lowq_shift22( - b: &mut B, - acc: &[QubitId], - x: &[QubitId], - p: U256, -) { - let n = acc.len(); - debug_assert_eq!(n, 256); - debug_assert_eq!(x.len(), n); - - let tmp_ext = b.alloc_qubits(2 * n); - b.set_phase("round84_inplace_solinas_square_forward"); - if xtail_sq_selfhost_enabled() { - schoolbook_square_symmetric_lowq_selfhosted(b, x, &tmp_ext); - } else { - schoolbook_square_symmetric_lowq(b, x, &tmp_ext); - } - - let lo: Vec = tmp_ext[0..n].to_vec(); - let hi: Vec = tmp_ext[n..2 * n].to_vec(); - if round84_inplace_solinas_fold_enabled() { - b.set_phase("round84_inplace_solinas_fold"); - let state = round84_fold_hi_into_lo_aggregate(b, &lo, &hi, acc); - b.set_phase("round84_inplace_solinas_sub"); - mod_sub_qq_vent(b, acc, &lo, p); - b.set_phase("round84_inplace_solinas_unfold"); - round84_unfold_hi_from_lo_aggregate(b, &lo, &hi, acc, state); - } else { - mod_sub_qq(b, acc, &lo, p); - mod_sub_qq(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_direct_const_fast(b, &hi, p); - } - mod_sub_qq(b, acc, &hi, p); - for _ in 0..2 { - mod_double_inplace_direct_const_fast(b, &hi, p); - } - mod_add_qq(b, acc, &hi, p); - for _ in 0..4 { - mod_double_inplace_direct_const_fast(b, &hi, p); - } - mod_sub_qq(b, acc, &hi, p); - let (spill, flag_inv, ovf) = mod_shift_left_by_k_lowq(b, &hi, p, 22); - if r84_lowq_enabled() { - mod_sub_qq_lowq(b, acc, &hi, p); - } else { - mod_sub_qq(b, acc, &hi, p); - } - mod_shift_right_by_k_lowq(b, &hi, p, 22, spill, flag_inv, ovf); - for _ in 0..10 { - mod_halve_inplace_direct_const_fast(b, &hi, p); - } - } - - b.set_phase("round84_inplace_solinas_square_inverse"); - if xtail_sq_selfhost_enabled() { - schoolbook_square_symmetric_lowq_selfhosted_inverse(b, x, &tmp_ext); - } else { - schoolbook_square_symmetric_lowq_inverse(b, x, &tmp_ext); - } - b.free_vec(&tmp_ext); -} - -pub(crate) fn squaring_sub_from_acc_walk_controls_lowq(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { - let n = acc.len(); - debug_assert_eq!(n, 256); - debug_assert_eq!(x.len(), n); - - let ctrl_copy = b.alloc_qubits(n); - for i in 0..n { - b.cx(x[i], ctrl_copy[i]); - } - - mod_neg_inplace_fast(b, x, p); - for i in 0..n { - cmod_add_qq(b, acc, x, ctrl_copy[i], p); - if i < n - 1 { - mod_double_inplace_fast(b, x, p); - } - } - for _ in 0..(n - 1) { - mod_halve_inplace_fast(b, x, p); - } - mod_neg_inplace_fast(b, x, p); - - for i in 0..n { - b.cx(x[i], ctrl_copy[i]); - } - b.free_vec(&ctrl_copy); -} - -fn round84_qprod_vent_pad_enabled() -> bool { - std::env::var("ROUND84_QPROD_VENT_PAD").ok().as_deref() == Some("1") -} - -fn round84_qprod_vent_pad_min_width() -> usize { - std::env::var("ROUND84_QPROD_VENT_PAD_MINW") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(29) -} - -fn round84_qprod_shifted_addsub_vented( - b: &mut B, - q: &[QubitId], - product: &[QubitId], - shift: usize, - add: bool, - dirty: &[QubitId], -) { - let m = q.len(); - let total = product.len() - shift; - debug_assert!(total >= m); - let high_w = total - m; - - if high_w < 5 || dirty.len() < high_w.saturating_sub(2) { - let target = &product[shift..]; - let pad = b.alloc_qubits(high_w); - let mut source = q.to_vec(); - source.extend_from_slice(&pad); - if add { - round84_add_small(b, &source, target); - } else { - round84_sub_small(b, &source, target); - } - b.free_vec(&pad); - return; - } - - let wrap = b.alloc_qubit(); - let mut low_ext = product[shift..shift + m].to_vec(); - low_ext.push(wrap); - let high = &product[shift + m..]; - - if add { - - let c_in = b.alloc_qubit(); - cuccaro_add_low_to_ext_clean(b, q, &low_ext, c_in); - b.free(c_in); - - let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; - venting::ciadd_dirty_2clean_classical( - b, - high, - &dirty[..high_w - 2], - &clean2, - 1, - wrap, - false, - ); - b.free(clean2[1]); - b.free(clean2[0]); - - cmp_lt_into(b, &product[shift..shift + m], q, wrap); - } else { - - let c_in = b.alloc_qubit(); - cuccaro_sub_low_to_ext_clean(b, q, &low_ext, c_in); - b.free(c_in); - - let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; - venting::cisub_dirty_2clean_classical(b, high, &dirty[..high_w - 2], &clean2, 1, wrap); - b.free(clean2[1]); - b.free(clean2[0]); - - for &qb in q { - b.x(qb); - } - cmp_lt_into(b, q, &product[shift..shift + m], wrap); - for &qb in q { - b.x(qb); - } - } - b.free(wrap); -} - -pub(crate) fn cross_addsub_stage1( - b: &mut B, - prod: &[QubitId], - off: usize, - addend: &[QubitId], - ctrl: QubitId, -) { - let w = prod.len(); - let m = addend.len(); - if m == 0 { - return; - } - debug_assert!(off + m <= w); - let t = b.alloc_qubits(w); - for k in 0..m { - b.cx(addend[k], t[off + k]); - } - b.x(ctrl); - for k in 0..w { - b.cx(ctrl, t[k]); - } - let cin = b.alloc_qubit(); - b.cx(ctrl, cin); - cuccaro_add(b, &t, prod, cin); - b.cx(ctrl, cin); - for k in 0..w { - b.cx(ctrl, t[k]); - } - b.x(ctrl); - for k in 0..m { - b.cx(addend[k], t[off + k]); - } - b.free(cin); - b.free_vec(&t); -} - -pub(crate) fn square_addsub_stage1(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(prod.len(), 2 * n); - - for i in 0..n { - let m = n - 1 - i; - if m == 0 { - continue; - } - let off = 2 * i + 1; - cross_addsub_stage1(b, prod, off, &x[i + 1..n], x[i]); - } - - let t = b.alloc_qubits(2 * n); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - let cin = b.alloc_qubit(); - cuccaro_add(b, &t, prod, cin); - b.free(cin); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - b.free_vec(&t); - - let zero_ctrl = b.alloc_qubit(); - cross_addsub_stage1(b, prod, 0, x, zero_ctrl); - b.free(zero_ctrl); -} - -/// M023: when `TLM_SQUARE_FROM_ZERO=1`, specialize the provably-|0> operand bits of the -/// `square_corr_forward`/`inverse` correction adders to the measured (`hmr`+`cz_if`) -/// AND-uncompute, removing one CCX per zero operand bit, bit-exactly. Read once and cached. -fn square_from_zero_enabled() -> bool { - static ENABLED: std::sync::OnceLock = std::sync::OnceLock::new(); - *ENABLED.get_or_init(|| std::env::var("TLM_SQUARE_FROM_ZERO").ok().as_deref() == Some("1")) -} - -fn square_corr_forward(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - let fz = square_from_zero_enabled(); - - let zeros = b.alloc_qubits(n); - let mut a2d: Vec = Vec::with_capacity(2 * n); - for i in 0..n { - a2d.push(zeros[i]); - a2d.push(x[i]); - } - let cin = b.alloc_qubit(); - if fz { - // a2d = [zeros[0], x[0], zeros[1], x[1], ...] -> even indices are |0>. - let mask: Vec = (0..2 * n).map(|j| j % 2 == 0).collect(); - cuccaro_add_from_zero(b, &a2d, prod, cin, &mask); - } else { - cuccaro_add(b, &a2d, prod, cin); - } - b.free(cin); - b.free_vec(&zeros); - - let pad = b.alloc_qubits(n); - let mut xext = x.to_vec(); - xext.extend_from_slice(&pad); - let cinx = b.alloc_qubit(); - if fz { - // xext = x || pad[n] -> the high half (indices >= n) is |0>. - let mask: Vec = (0..2 * n).map(|j| j >= n).collect(); - cuccaro_sub_from_zero(b, &xext, prod, cinx, &mask); - } else { - cuccaro_sub(b, &xext, prod, cinx); - } - b.free(cinx); - b.free_vec(&pad); - - let p1 = b.alloc_qubit(); - let mut a = x[0..n - 1].to_vec(); - a.push(p1); - let high: Vec = prod[n..2 * n].to_vec(); - let cinl = b.alloc_qubit(); - b.x(cinl); - if fz { - // a = x[0..n-1] || p1 -> only the top bit is |0> (no UMA there; 0 savings, harmless). - let mask: Vec = (0..n).map(|j| j == n - 1).collect(); - cuccaro_add_from_zero(b, &a, &high, cinl, &mask); - } else { - cuccaro_add(b, &a, &high, cinl); - } - b.x(cinl); - b.free(cinl); - b.free(p1); - - b.x(prod[2 * n - 1]); -} - -fn square_corr_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - let fz = square_from_zero_enabled(); - - b.x(prod[2 * n - 1]); - - let p1 = b.alloc_qubit(); - let mut a = x[0..n - 1].to_vec(); - a.push(p1); - let high: Vec = prod[n..2 * n].to_vec(); - let cinl = b.alloc_qubit(); - b.x(cinl); - if fz { - // a = x[0..n-1] || p1 -> only the top bit is |0> (no inv-MAJ there; 0 savings). - let mask: Vec = (0..n).map(|j| j == n - 1).collect(); - cuccaro_sub_from_zero(b, &a, &high, cinl, &mask); - } else { - cuccaro_sub(b, &a, &high, cinl); - } - b.x(cinl); - b.free(cinl); - b.free(p1); - - let pad = b.alloc_qubits(n); - let mut xext = x.to_vec(); - xext.extend_from_slice(&pad); - let cinx = b.alloc_qubit(); - if fz { - // xext = x || pad[n] -> the high half (indices >= n) is |0>. - let mask: Vec = (0..2 * n).map(|j| j >= n).collect(); - cuccaro_add_from_zero(b, &xext, prod, cinx, &mask); - } else { - cuccaro_add(b, &xext, prod, cinx); - } - b.free(cinx); - b.free_vec(&pad); - - let zeros = b.alloc_qubits(n); - let mut a2d: Vec = Vec::with_capacity(2 * n); - for i in 0..n { - a2d.push(zeros[i]); - a2d.push(x[i]); - } - let cin = b.alloc_qubit(); - if fz { - // a2d = [zeros[0], x[0], zeros[1], x[1], ...] -> even indices are |0>. - let mask: Vec = (0..2 * n).map(|j| j % 2 == 0).collect(); - cuccaro_sub_from_zero(b, &a2d, prod, cin, &mask); - } else { - cuccaro_sub(b, &a2d, prod, cin); - } - b.free(cin); - b.free_vec(&zeros); -} - -pub(crate) fn square_addsub_local(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(prod.len(), 2 * n); - - for i in 0..n { - let m = n - 1 - i; - if m == 0 { - continue; - } - let off = 2 * i + 1; - let slice: Vec = prod[off..off + m + 1].to_vec(); - controlled_add_subtract_lowq(b, &x[i + 1..n], &slice, x[i]); - } - - let t = b.alloc_qubits(2 * n); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - let cin = b.alloc_qubit(); - cuccaro_add(b, &t, prod, cin); - b.free(cin); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - b.free_vec(&t); - - let zc = b.alloc_qubit(); - cross_addsub_stage1(b, prod, 0, x, zc); - b.free(zc); - - if n >= 2 { - let oc = b.alloc_qubit(); - b.x(oc); - cross_addsub_stage1(b, prod, n, &x[0..n - 1], oc); - b.x(oc); - b.free(oc); - } - - let t2 = b.alloc_qubits(2 * n); - b.x(t2[2 * n - 1]); - b.x(t2[n]); - let cin2 = b.alloc_qubit(); - cuccaro_add(b, &t2, prod, cin2); - b.free(cin2); - b.x(t2[2 * n - 1]); - b.x(t2[n]); - b.free_vec(&t2); -} - -pub(crate) fn controlled_add_subtract_vented_borrowed( - b: &mut B, - x: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - carries: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(acc.len(), n + 1); - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - let c_in = b.alloc_qubit(); - b.x(ctrl); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.cx(ctrl, c_in); - cuccaro_add_fast_borrowed_carries(b, &x_ext, acc, c_in, carries); - b.cx(ctrl, c_in); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.x(ctrl); - b.free(c_in); - b.free(pad); -} - -pub(crate) fn square_addsub_vented(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(prod.len(), 2 * n); - for i in 0..n { - let m = n - 1 - i; - if m == 0 { - continue; - } - let off = 2 * i + 1; - let slice: Vec = prod[off..off + m + 1].to_vec(); - - let hi = off + m + 1; - let need = m; - let carries: Vec = prod[hi..hi + need].to_vec(); - controlled_add_subtract_vented_borrowed(b, &x[i + 1..n], &slice, x[i], &carries); - } - - square_corr_forward(b, x, prod); -} - -pub(crate) fn square_addsub_local_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(prod.len(), 2 * n); - let t2 = b.alloc_qubits(2 * n); - b.x(t2[2 * n - 1]); - b.x(t2[n]); - let cin2 = b.alloc_qubit(); - cuccaro_sub(b, &t2, prod, cin2); - b.free(cin2); - b.x(t2[2 * n - 1]); - b.x(t2[n]); - b.free_vec(&t2); - if n >= 2 { - let zc = b.alloc_qubit(); - cross_addsub_stage1(b, prod, n, &x[0..n - 1], zc); - b.free(zc); - } - let oc = b.alloc_qubit(); - b.x(oc); - cross_addsub_stage1(b, prod, 0, x, oc); - b.x(oc); - b.free(oc); - let t = b.alloc_qubits(2 * n); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - let cin = b.alloc_qubit(); - cuccaro_sub(b, &t, prod, cin); - b.free(cin); - for i in 0..n { - let p = 2 * i + 1; - if p < 2 * n { - b.cx(x[i], t[p]); - } - } - b.free_vec(&t); - for i in (0..n).rev() { - let m = n - 1 - i; - if m == 0 { - continue; - } - let off = 2 * i + 1; - let slice: Vec = prod[off..off + m + 1].to_vec(); - controlled_add_subtract_lowq_inverse(b, &x[i + 1..n], &slice, x[i]); - } -} - -pub(crate) fn controlled_add_subtract_vented_borrowed_inverse( - b: &mut B, - x: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - carries: &[QubitId], -) { - let n = x.len(); - debug_assert_eq!(acc.len(), n + 1); - let pad = b.alloc_qubit(); - let mut x_ext = x.to_vec(); - x_ext.push(pad); - let c_in = b.alloc_qubit(); - b.x(ctrl); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.cx(ctrl, c_in); - cuccaro_sub_fast_borrowed_carries(b, &x_ext, acc, c_in, carries); - b.cx(ctrl, c_in); - for i in 0..n { - b.cx(ctrl, x_ext[i]); - } - b.x(ctrl); - b.free(c_in); - b.free(pad); -} - -pub(crate) fn square_addsub_vented_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { - let n = x.len(); - debug_assert_eq!(prod.len(), 2 * n); - - square_corr_inverse(b, x, prod); - - for i in (0..n).rev() { - let m = n - 1 - i; - if m == 0 { - continue; - } - let off = 2 * i + 1; - let slice: Vec = prod[off..off + m + 1].to_vec(); - let hi = off + m + 1; - let carries: Vec = prod[hi..hi + m].to_vec(); - controlled_add_subtract_vented_borrowed_inverse(b, &x[i + 1..n], &slice, x[i], &carries); - } -} - -pub(crate) mod square_addsub_selftest { - use super::*; - use crate::sim::Simulator; - use crate::circuit::OperationType; - use sha3::digest::{ExtendableOutput, Update, XofReader}; - - fn count_tof(ops: &[crate::circuit::Op]) -> usize { - ops.iter() - .filter(|o| matches!(o.kind, OperationType::CCX | OperationType::CCZ)) - .count() - } - - pub(crate) fn toffoli_compare() { - for &n in &[128usize, 129] { - let mut b1 = B::new(); - let x1 = b1.alloc_qubits(n); - let p1 = b1.alloc_qubits(2 * n); - schoolbook_square_symmetric(&mut b1, &x1, &p1); - let cur = count_tof(&b1.ops); - let peak_cur = b1.peak_qubits; - - let mut b2 = B::new(); - let x2 = b2.alloc_qubits(n); - let p2 = b2.alloc_qubits(2 * n); - square_addsub_vented(&mut b2, &x2, &p2); - let new = count_tof(&b2.ops); - let peak_new = b2.peak_qubits; - - println!( - " SQ_TOF n={n}: current(AND) CCX={cur} peakQ={peak_cur} | addsub_vented CCX={new} peakQ={peak_new} | delta={}", - cur as i64 - new as i64 - ); - } - } - - pub(crate) fn run() { - let big = std::env::var("TLM_SQ_SELFTEST_BIG").ok().as_deref() == Some("1"); - exhaustive_small_n(); - random_large_n(if big { 4096 } else { 64 }); - println!(" SQ_SELFTEST (vented): bit-exact vs classical x^2 — 0 divergence"); - inverse_drains_to_zero(if big { 4096 } else { 256 }); - println!(" SQ_SELFTEST (inverse): forward+inverse drains prod to 0, clean"); - toffoli_compare(); - } - - fn inverse_drains_to_zero(count: usize) { - for &n in &[1usize, 2, 3, 8, 32, 127, 128, 129] { - let mut seed = sha3::Shake256::default(); - seed.update(b"missed3-inv"); - seed.update(&[n as u8]); - let mut xof = seed.finalize_xof(); - let mut buf = [0u8; 32]; - let batches = (count / 64).max(1); - for batch in 0..batches { - let mut xs = Vec::with_capacity(64); - for _ in 0..64 { - xof.read(&mut buf); - let mut v = U256::from_le_bytes(buf); - if n < 256 { - v &= (U256::from(1u64) << n) - U256::from(1u64); - } - xs.push(v); - } - let mut b = B::new(); - let x = b.alloc_qubits(n); - let prod = b.alloc_qubits(2 * n); - square_addsub_vented(&mut b, &x, &prod); - square_addsub_vented_inverse(&mut b, &x, &prod); - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut s2 = sha3::Shake256::default(); - s2.update(b"missed3-inv-sim"); - s2.update(&[n as u8, batch as u8]); - let mut xof2 = s2.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof2); - sim.clear_for_shot(); - for (shot, xv) in xs.iter().enumerate() { - for i in 0..n { - if xv.bit(i) { - *sim.qubit_mut(x[i]) |= 1u64 << shot; - } - } - } - sim.apply_iter(b.ops.iter()); - assert_eq!(sim.phase, 0, "inv n={n} b{batch}: phase garbage"); - - let mut is_x = vec![false; nq]; - for &q in x.iter() { - is_x[q.0 as usize] = true; - } - for q in 0..nq { - if !is_x[q] { - assert_eq!( - sim.qubit(QubitId(q as u64)), - 0, - "inv n={n} b{batch}: nonzero q{q} (prod/ancilla not drained)" - ); - } - } - for (shot, xv) in xs.iter().enumerate() { - for i in 0..n { - let got = (sim.qubit(x[i]) >> shot) & 1 == 1; - assert_eq!(got, xv.bit(i), "inv n={n} b{batch}: x[{i}] corrupted"); - } - } - } - } - } - - fn check_square(n: usize, xs: &[U256], label: &str) { - assert!(xs.len() <= 64); - let mut b = B::new(); - let x = b.alloc_qubits(n); - let prod = b.alloc_qubits(2 * n); - square_addsub_vented(&mut b, &x, &prod); - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - - let mut seed = sha3::Shake256::default(); - seed.update(b"missed3-square-addsub-stage1"); - seed.update(label.as_bytes()); - let mut xof = seed.finalize_xof(); - - let mut sim = Simulator::new(nq, nb, &mut xof); - sim.clear_for_shot(); - for (shot, xv) in xs.iter().enumerate() { - for i in 0..n { - if xv.bit(i) { - *sim.qubit_mut(x[i]) |= 1u64 << shot; - } - } - } - sim.apply_iter(b.ops.iter()); - - let cond_mask: u64 = if xs.len() == 64 { - u64::MAX - } else { - (1u64 << xs.len()) - 1 - }; - if sim.phase & cond_mask != 0 { - let mut is_reg = vec![false; nq]; - for &q in x.iter().chain(prod.iter()) { - is_reg[q.0 as usize] = true; - } - for q in 0..nq { - let v = sim.qubit(QubitId(q as u64)) & cond_mask; - if !is_reg[q] && v != 0 { - eprintln!(" DIRTY q{q} = {v:#018x}"); - } - } - panic!("{label}: phase garbage {:#018x}", sim.phase & cond_mask); - } - - for (shot, xv) in xs.iter().enumerate() { - let mut out = U256::ZERO; - for i in 0..(2 * n) { - if (sim.qubit(prod[i]) >> shot) & 1 == 1 { - out |= U256::from(1u64) << i; - } - } - let expect = xv.wrapping_mul(*xv); - assert_eq!(out, expect, "{label}: shot {shot} x={xv:#x} got {out:#x}"); - } - - let mut is_reg = vec![false; nq]; - for &q in x.iter().chain(prod.iter()) { - is_reg[q.0 as usize] = true; - } - for q in 0..nq { - if !is_reg[q] { - assert_eq!( - sim.qubit(QubitId(q as u64)) & cond_mask, - 0, - "{label}: dirty ancilla q{q}" - ); - } - } - } - - fn exhaustive_small_n() { - for n in 1..=6usize { - let limit = 1usize << n; - let xs: Vec = (0..limit).map(|v| U256::from(v as u64)).collect(); - - for chunk in xs.chunks(64) { - check_square(n, chunk, &format!("exhaustive-n{n}")); - } - } - } - - fn random_large_n(batches: usize) { - for &n in &[8usize, 16, 32, 64, 127, 128, 129] { - let mut seed = sha3::Shake256::default(); - seed.update(b"missed3-rand"); - seed.update(&[n as u8]); - let mut xof = seed.finalize_xof(); - let mut buf = [0u8; 32]; - for batch in 0..batches { - let mut xs = Vec::with_capacity(64); - for _ in 0..64 { - xof.read(&mut buf); - let mut v = U256::from_le_bytes(buf); - - if n < 256 { - v &= (U256::from(1u64) << n) - U256::from(1u64); - } - xs.push(v); - } - check_square(n, &xs, &format!("rand-n{n}-b{batch}")); - } - } - } -} + +use super::*; + +#[allow(dead_code)] +pub(crate) fn mod_mul_write_into_zero_acc_schoolbook_lowq( + b: &mut B, + acc: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, +) { + let n = acc.len(); + debug_assert_eq!(n, 256); + + let tmp_ext = b.alloc_qubits(2 * n); + schoolbook_mul_into_addsub_lowq(b, x, y, &tmp_ext); + + let lo: Vec = tmp_ext[0..n].to_vec(); + let hi: Vec = tmp_ext[n..2 * n].to_vec(); + mod_add_qq_fast_from_zero(b, acc, &lo, p); + mod_add_qq_fast(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_fast(b, &hi, p); + } + mod_add_qq_fast(b, acc, &hi, p); + for _ in 0..2 { + mod_double_inplace_fast(b, &hi, p); + } + mod_sub_qq_fast(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_fast(b, &hi, p); + } + mod_add_qq_fast(b, acc, &hi, p); + let (spill, flag_inv, ovf) = mod_shift_left_by_k(b, &hi, p, 22); + mod_add_qq(b, acc, &hi, p); + mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); + for _ in 0..10 { + mod_halve_inplace_fast(b, &hi, p); + } + + schoolbook_mul_into_addsub_lowq_inverse(b, x, y, &tmp_ext); + b.free_vec(&tmp_ext); +} + +pub(crate) fn controlled_add_subtract_lowq(b: &mut B, x: &[QubitId], acc: &[QubitId], ctrl: QubitId) { + let n = x.len(); + debug_assert_eq!(acc.len(), n + 1); + + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + + let c_in = b.alloc_qubit(); + + b.x(ctrl); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.cx(ctrl, c_in); + + cuccaro_add(b, &x_ext, acc, c_in); + + b.cx(ctrl, c_in); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.x(ctrl); + + b.free(c_in); + b.free(pad); +} + +pub(crate) fn controlled_add_subtract_lowq_inverse(b: &mut B, x: &[QubitId], acc: &[QubitId], ctrl: QubitId) { + let n = x.len(); + debug_assert_eq!(acc.len(), n + 1); + + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + + let c_in = b.alloc_qubit(); + + b.x(ctrl); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.cx(ctrl, c_in); + + cuccaro_sub(b, &x_ext, acc, c_in); + + b.cx(ctrl, c_in); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.x(ctrl); + + b.free(c_in); + b.free(pad); +} + +pub(crate) fn schoolbook_mul_into_addsub_lowq(b: &mut B, x: &[QubitId], y: &[QubitId], tmp_ext: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(y.len(), n); + debug_assert_eq!(tmp_ext.len(), 2 * n); + + let low = b.alloc_qubit(); + let mut wide: Vec = Vec::with_capacity(2 * n + 1); + wide.push(low); + wide.extend_from_slice(tmp_ext); + + for k in 0..n { + let slice: Vec = wide[k..k + n + 1].to_vec(); + controlled_add_subtract_lowq(b, x, &slice, y[k]); + } + + { + let pad = b.alloc_qubit(); + let mut y_ext = y.to_vec(); + y_ext.push(pad); + let slice: Vec = wide[n..2 * n + 1].to_vec(); + let c_in = b.alloc_qubit(); + b.x(c_in); + cuccaro_add(b, &y_ext, &slice, c_in); + b.x(c_in); + b.free(c_in); + b.free(pad); + } + + b.x(wide[2 * n]); + + { + let mut x_ext: Vec = x.to_vec(); + while x_ext.len() < 2 * n + 1 { + x_ext.push(b.alloc_qubit()); + } + let c_in = b.alloc_qubit(); + cuccaro_sub(b, &x_ext, &wide, c_in); + b.free(c_in); + for _ in n..2 * n + 1 { + let q = x_ext.pop().unwrap(); + b.free(q); + } + } + + { + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + let slice: Vec = wide[n..2 * n + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_add(b, &x_ext, &slice, c_in); + b.free(c_in); + b.free(pad); + } + + b.free(low); +} + +pub(crate) fn schoolbook_mul_into_addsub_lowq_inverse( + b: &mut B, + x: &[QubitId], + y: &[QubitId], + tmp_ext: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(y.len(), n); + debug_assert_eq!(tmp_ext.len(), 2 * n); + + let low = b.alloc_qubit(); + let mut wide: Vec = Vec::with_capacity(2 * n + 1); + wide.push(low); + wide.extend_from_slice(tmp_ext); + + { + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + let slice: Vec = wide[n..2 * n + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_sub(b, &x_ext, &slice, c_in); + b.free(c_in); + b.free(pad); + } + + { + let mut x_ext: Vec = x.to_vec(); + while x_ext.len() < 2 * n + 1 { + x_ext.push(b.alloc_qubit()); + } + let c_in = b.alloc_qubit(); + cuccaro_add(b, &x_ext, &wide, c_in); + b.free(c_in); + for _ in n..2 * n + 1 { + let q = x_ext.pop().unwrap(); + b.free(q); + } + } + + b.x(wide[2 * n]); + + { + let pad = b.alloc_qubit(); + let mut y_ext = y.to_vec(); + y_ext.push(pad); + let slice: Vec = wide[n..2 * n + 1].to_vec(); + let c_in = b.alloc_qubit(); + b.x(c_in); + cuccaro_sub(b, &y_ext, &slice, c_in); + b.x(c_in); + b.free(c_in); + b.free(pad); + } + for k in (0..n).rev() { + let slice: Vec = wide[k..k + n + 1].to_vec(); + controlled_add_subtract_lowq_inverse(b, x, &slice, y[k]); + } + + b.free(low); +} + +pub(crate) fn karatsuba_half_sum_compute(b: &mut B, lo: &[QubitId], hi: &[QubitId], acc: &[QubitId]) { + let h = lo.len(); + debug_assert_eq!(h, hi.len()); + debug_assert_eq!(acc.len(), h + 1); + for i in 0..h { + b.cx(lo[i], acc[i]); + } + let hi_pad = b.alloc_qubit(); + let mut hi_ext = hi.to_vec(); + hi_ext.push(hi_pad); + add_nbit_qq_fast(b, &hi_ext, acc); + b.free(hi_pad); +} + +pub(crate) fn karatsuba_half_sum_uncompute(b: &mut B, lo: &[QubitId], hi: &[QubitId], acc: &[QubitId]) { + let h = lo.len(); + let hi_pad = b.alloc_qubit(); + let mut hi_ext = hi.to_vec(); + hi_ext.push(hi_pad); + sub_nbit_qq_fast(b, &hi_ext, acc); + b.free(hi_pad); + for i in 0..h { + b.cx(lo[i], acc[i]); + } +} + +pub(crate) fn schoolbook_square_symmetric(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(tmp_ext.len(), 2 * n); + for i in 0..n { + + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_add_fast(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_inverse(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { + let n = x.len(); + for i in (0..n).rev() { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_sub_fast(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_lowq(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(tmp_ext.len(), 2 * n); + for i in 0..n { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_add(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_lowq_inverse(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { + let n = x.len(); + for i in (0..n).rev() { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + let c_in = b.alloc_qubit(); + cuccaro_sub(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_hosted( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], + host: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(tmp_ext.len(), 2 * n); + if square_selfhost_safe_lane_reuse_enabled() { + assert_qubit_slices_disjoint(&[x, tmp_ext, host]); + } + for i in 0..n { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + if square_selfhost_safe_lane_reuse_enabled() { + + assert!(host.len() > width); + cuccaro_add_fast_low_to_ext_borrowed_carries( + b, + &row, + &slice, + host[width], + &host[..width], + ); + } else { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + cuccaro_add_fast_borrowed_carries( + b, + &row_padded, + &slice, + c_in, + &host[..row_padded.len() - 1], + ); + b.free(c_in); + b.free(pad); + } + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_hosted_inverse( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], + host: &[QubitId], +) { + let n = x.len(); + if square_selfhost_safe_lane_reuse_enabled() { + assert_qubit_slices_disjoint(&[x, tmp_ext, host]); + } + for i in (0..n).rev() { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let slice: Vec = tmp_ext[2 * i..2 * i + width + 1].to_vec(); + if square_selfhost_safe_lane_reuse_enabled() { + assert!(host.len() > width); + cuccaro_sub_fast_low_to_ext_borrowed_carries( + b, + &row, + &slice, + host[width], + &host[..width], + ); + } else { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + cuccaro_sub_fast_borrowed_carries( + b, + &row_padded, + &slice, + c_in, + &host[..row_padded.len() - 1], + ); + b.free(c_in); + b.free(pad); + } + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn square_selfhost_safe_lane_reuse_enabled() -> bool { + std::env::var("SQUARE_SELFHOST_SAFE_LANE_REUSE") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn assert_qubit_slices_disjoint(slices: &[&[QubitId]]) { + let mut seen = std::collections::BTreeSet::new(); + for slice in slices { + for &q in *slice { + assert!(seen.insert(q), "scratch lane q{} aliases an operand", q.0); + } + } +} + +pub(crate) fn square_selfhost_gate_suffix_carries(n: usize) -> usize { + std::env::var("SQUARE_SELFHOST_GATE_SUFFIX_CARRIES") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) + .min(n.saturating_sub(1)) +} + +pub(crate) fn square_row_windows() -> usize { + std::env::var("SQUARE_ROW_WINDOWS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +fn square_row_window_min_width() -> usize { + std::env::var("SQUARE_ROW_WINDOW_MIN_WIDTH") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(96) +} + +fn square_row_max_seg() -> usize { + std::env::var("SQUARE_ROW_MAX_SEG") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +fn square_cleanup_direction(raw: &str) -> Option { + match raw.trim().to_ascii_lowercase().as_str() { + "f" | "forward" | "false" | "0" => Some(false), + "r" | "reverse" | "true" | "1" => Some(true), + _ => None, + } +} + +fn square_row_window_clean_compare_bits( + row: usize, + window: usize, + reverse: bool, +) -> usize { + let default_bits = std::env::var("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + let row_bits = std::env::var("SQUARE_ROW_WINDOW_CLEAN_ROW_BITS") + .ok() + .and_then(|spec| { + spec.split(',').rev().find_map(|item| { + let (raw_row, raw_bits) = item.trim().split_once(':')?; + if raw_row.trim().parse::().ok()? != row { + return None; + } + raw_bits + .trim() + .parse::() + .ok() + .filter(|bits| (1..=N).contains(bits)) + }) + }) + .unwrap_or(default_bits); + let Ok(spec) = std::env::var("SQUARE_ROW_WINDOW_CLEAN_SITE_BITS") else { + return row_bits; + }; + for item in spec.split(',').rev() { + let fields: Vec<_> = item.trim().split(':').map(str::trim).collect(); + if fields.len() != 4 { + continue; + } + if fields[0].parse::().ok() != Some(row) + || fields[1].parse::().ok() != Some(window) + || square_cleanup_direction(fields[2]) != Some(reverse) + { + continue; + } + if let Ok(bits) = fields[3].parse::() { + if (1..=N).contains(&bits) { + return bits; + } + } + } + row_bits +} + +fn square_row_window_measured_carry_clear_enabled() -> bool { + std::env::var("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR") + .ok() + .as_deref() + == Some("1") +} + +fn square_row_bit_set(b: &mut B, x: &[QubitId], i: usize, j: usize, t: QubitId) { + if j == 0 { + b.cx(x[i], t); + } else if j == 1 { + + } else { + b.ccx(x[i], x[i + 1 + (j - 2)], t); + } +} + +fn square_row_bit_clear_hmr(b: &mut B, x: &[QubitId], i: usize, j: usize, t: QubitId) { + if j == 0 { + b.cx(x[i], t); + } else if j == 1 { + + } else { + let m = b.alloc_bit(); + b.hmr(t, m); + b.cz_if(x[i], x[i + 1 + (j - 2)], m); + } +} + +fn square_row_windowed_apply( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], + i: usize, + width: usize, + windows: usize, + forward: bool, +) { + let base = 2 * i; + let windows = windows.max(1).min(width); + + let bounds: Vec<(usize, usize)> = (0..windows) + .map(|w| { + let lo = (w * width) / windows; + let hi = ((w + 1) * width) / windows; + (lo, hi) + }) + .filter(|&(lo, hi)| hi > lo) + .collect(); + let nwin = bounds.len(); + + let build_seg = |b: &mut B, lo: usize, hi: usize| -> Vec { + let seg = b.alloc_qubits(hi - lo); + for (k, &q) in seg.iter().enumerate() { + square_row_bit_set(b, x, i, lo + k, q); + } + seg + }; + let clear_seg = |b: &mut B, lo: usize, seg: &[QubitId]| { + for (k, &q) in seg.iter().enumerate() { + square_row_bit_clear_hmr(b, x, i, lo + k, q); + } + b.free_vec(seg); + }; + + let row_top = base + width + 1; + let borrow_lane = |b: &mut B, _need: usize| -> Vec { + + tmp_ext[row_top..row_top + _need].to_vec() + }; + + let mut carry_in = b.alloc_qubit(); + let first_carry = carry_in; + let mut couts: Vec<(QubitId, usize, usize, QubitId, usize)> = Vec::new(); + for (wi, &(lo, hi)) in bounds.iter().enumerate() { + let last = wi == nwin - 1; + let seg = build_seg(b, lo, hi); + let seg_w = hi - lo; + + let pad = b.alloc_qubit(); + let mut a_block = seg.clone(); + a_block.push(pad); + let high = if last { + + tmp_ext[base + hi] + } else { + b.alloc_qubit() + }; + let mut acc_block: Vec = tmp_ext[base + lo..base + hi].to_vec(); + acc_block.push(high); + let nblk = a_block.len(); + let carries = borrow_lane(b, nblk - 1); + if forward { + cuccaro_add_fast_borrowed_carries(b, &a_block, &acc_block, carry_in, &carries); + } else { + cuccaro_sub_fast_borrowed_carries(b, &a_block, &acc_block, carry_in, &carries); + } + b.free(pad); + if last { + + } else { + couts.push((high, lo, hi, carry_in, wi)); + carry_in = high; + } + clear_seg(b, lo, &seg); + } + + let slow_cmp = std::env::var("SQUARE_ROW_WINDOW_SLOW_CMP").ok().as_deref() == Some("1"); + let measured_clear = square_row_window_measured_carry_clear_enabled(); + for &(cout, lo, hi, cin, window) in couts.iter().rev() { + let clean_cmp_bits = + square_row_window_clean_compare_bits(i, window, !forward); + let seg_w = hi - lo; + let trunc_w = if clean_cmp_bits == 0 { + seg_w + } else { + clean_cmp_bits.min(seg_w) + }; + if trunc_w < seg_w { + let suffix_lo = hi - trunc_w; + let seg = build_seg(b, suffix_lo, hi); + let carries = tmp_ext[row_top..row_top + trunc_w].to_vec(); + let cmp_cin = b.alloc_qubit(); + if forward { + if measured_clear { + let phase = b.alloc_bit(); + b.hmr(cout, phase); + cmp_lt_phase_conditioned_with_cin_borrowed_carries( + b, + &tmp_ext[base + suffix_lo..base + hi], + &seg, + cmp_cin, + &carries, + phase, + ); + } else { + cmp_lt_into_fast_with_cin_borrowed_carries( + b, + &tmp_ext[base + suffix_lo..base + hi], + &seg, + cmp_cin, + cout, + &carries, + ); + } + } else { + for &q in &seg { + b.x(q); + } + if measured_clear { + let phase = b.alloc_bit(); + b.hmr(cout, phase); + cmp_lt_phase_conditioned_with_cin_borrowed_carries( + b, + &seg, + &tmp_ext[base + suffix_lo..base + hi], + cmp_cin, + &carries, + phase, + ); + } else { + cmp_lt_into_fast_with_cin_borrowed_carries( + b, + &seg, + &tmp_ext[base + suffix_lo..base + hi], + cmp_cin, + cout, + &carries, + ); + } + for &q in &seg { + b.x(q); + } + } + b.free(cmp_cin); + clear_seg(b, suffix_lo, &seg); + } else { + let seg = build_seg(b, lo, hi); + let carries = tmp_ext[row_top..row_top + seg_w].to_vec(); + if forward { + + if measured_clear { + let phase = b.alloc_bit(); + b.hmr(cout, phase); + cmp_lt_phase_conditioned_with_cin_borrowed_carries( + b, + &tmp_ext[base + lo..base + hi], + &seg, + cin, + &carries, + phase, + ); + } else if slow_cmp { + cmp_lt_into_with_cin_slow(b, &tmp_ext[base + lo..base + hi], &seg, cin, cout); + } else { + cmp_lt_into_fast_with_cin_borrowed_carries( + b, &tmp_ext[base + lo..base + hi], &seg, cin, cout, &carries, + ); + } + } else { + + for k in 0..seg_w { + b.x(seg[k]); + } + if measured_clear { + let phase = b.alloc_bit(); + b.hmr(cout, phase); + cmp_lt_phase_conditioned_with_cin_borrowed_carries( + b, + &seg, + &tmp_ext[base + lo..base + hi], + cin, + &carries, + phase, + ); + } else if slow_cmp { + cmp_lt_into_with_cin_slow(b, &seg, &tmp_ext[base + lo..base + hi], cin, cout); + } else { + cmp_lt_into_fast_with_cin_borrowed_carries( + b, &seg, &tmp_ext[base + lo..base + hi], cin, cout, &carries, + ); + } + for k in 0..seg_w { + b.x(seg[k]); + } + } + clear_seg(b, lo, &seg); + } + b.free(cout); + } + b.free(first_carry); +} + +pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted(b: &mut B, x: &[QubitId], tmp_ext: &[QubitId]) { + schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement(b, x, tmp_ext, &[]); +} + +pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], + clean_supplement: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(tmp_ext.len(), 2 * n); + let safe_reuse = square_selfhost_safe_lane_reuse_enabled(); + if safe_reuse { + assert_qubit_slices_disjoint(&[x, tmp_ext, clean_supplement]); + } + let gate_prefix_rows = std::env::var("SQUARE_SELFHOST_GATE_PREFIX_ROWS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + let row_windows = square_row_windows(); + let row_window_min = square_row_window_min_width(); + let max_seg = square_row_max_seg(); + for i in 0..n { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + if max_seg > 0 && i >= gate_prefix_rows && width > max_seg { + let w = width.div_ceil(max_seg); + square_row_windowed_apply(b, x, tmp_ext, i, width, w, true); + continue; + } + if max_seg == 0 && row_windows >= 1 && i >= gate_prefix_rows && width >= row_window_min { + square_row_windowed_apply(b, x, tmp_ext, i, width, row_windows, true); + continue; + } + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let hi = 2 * i + width + 1; + let slice: Vec = tmp_ext[2 * i..hi].to_vec(); + if i < gate_prefix_rows { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + cuccaro_add(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + } else if safe_reuse { + let need = row.len() - square_selfhost_gate_suffix_carries(row.len()); + let avail = tmp_ext.len() - hi; + let from_tmp = need.min(avail); + let from_supplement = (need - from_tmp).min(clean_supplement.len()); + let from_global = need - from_tmp - from_supplement; + let gpool = b.alloc_qubits(from_global); + let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); + carries.extend_from_slice(&clean_supplement[..from_supplement]); + carries.extend_from_slice(&gpool); + cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin(b, &row, &slice, &carries); + b.free_vec(&gpool); + } else { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + let need = row_padded.len() - 1; + let avail = tmp_ext.len() - hi; + let from_tmp = need.min(avail); + let from_global = need - from_tmp; + let gpool = b.alloc_qubits(from_global); + let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); + carries.extend_from_slice(&gpool); + cuccaro_add_fast_borrowed_carries(b, &row_padded, &slice, c_in, &carries); + b.free(c_in); + b.free_vec(&gpool); + b.free(pad); + } + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_inverse( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], +) { + schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement(b, x, tmp_ext, &[]); +} + +pub(crate) fn schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement( + b: &mut B, + x: &[QubitId], + tmp_ext: &[QubitId], + clean_supplement: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(tmp_ext.len(), 2 * n); + let safe_reuse = square_selfhost_safe_lane_reuse_enabled(); + if safe_reuse { + assert_qubit_slices_disjoint(&[x, tmp_ext, clean_supplement]); + } + let gate_prefix_rows = std::env::var("SQUARE_SELFHOST_GATE_PREFIX_ROWS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + let row_windows = square_row_windows(); + let row_window_min = square_row_window_min_width(); + let max_seg = square_row_max_seg(); + for i in (0..n).rev() { + let width = if i == n - 1 { 1 } else { n - i + 1 }; + let num_cross = if i + 1 < n { n - i - 1 } else { 0 }; + if max_seg > 0 && i >= gate_prefix_rows && width > max_seg { + let w = width.div_ceil(max_seg); + square_row_windowed_apply(b, x, tmp_ext, i, width, w, false); + continue; + } + if max_seg == 0 && row_windows >= 1 && i >= gate_prefix_rows && width >= row_window_min { + square_row_windowed_apply(b, x, tmp_ext, i, width, row_windows, false); + continue; + } + let row = b.alloc_qubits(width); + b.cx(x[i], row[0]); + for k in 0..num_cross { + b.ccx(x[i], x[i + 1 + k], row[k + 2]); + } + let hi = 2 * i + width + 1; + let slice: Vec = tmp_ext[2 * i..hi].to_vec(); + if i < gate_prefix_rows { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + cuccaro_sub(b, &row_padded, &slice, c_in); + b.free(c_in); + b.free(pad); + } else if safe_reuse { + let need = row.len() - square_selfhost_gate_suffix_carries(row.len()); + let avail = tmp_ext.len() - hi; + let from_tmp = need.min(avail); + let from_supplement = (need - from_tmp).min(clean_supplement.len()); + let from_global = need - from_tmp - from_supplement; + let gpool = b.alloc_qubits(from_global); + let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); + carries.extend_from_slice(&clean_supplement[..from_supplement]); + carries.extend_from_slice(&gpool); + cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin(b, &row, &slice, &carries); + b.free_vec(&gpool); + } else { + let pad = b.alloc_qubit(); + let mut row_padded = row.clone(); + row_padded.push(pad); + let c_in = b.alloc_qubit(); + let need = row_padded.len() - 1; + let avail = tmp_ext.len() - hi; + let from_tmp = need.min(avail); + let from_global = need - from_tmp; + let gpool = b.alloc_qubits(from_global); + let mut carries: Vec = tmp_ext[hi..hi + from_tmp].to_vec(); + carries.extend_from_slice(&gpool); + cuccaro_sub_fast_borrowed_carries(b, &row_padded, &slice, c_in, &carries); + b.free(c_in); + b.free_vec(&gpool); + b.free(pad); + } + b.cx(x[i], row[0]); + for k in 0..num_cross { + let m = b.alloc_bit(); + b.hmr(row[k + 2], m); + b.cz_if(x[i], x[i + 1 + k], m); + } + b.free_vec(&row); + } +} + +pub(crate) fn kara_z2_selfhost_enabled() -> bool { + std::env::var("KARA_Z2_SELFHOST").ok().as_deref() != Some("0") +} + +pub(crate) fn xtail_sq_selfhost_enabled() -> bool { + std::env::var("XTAIL_SQ_SELFHOST").ok().as_deref() != Some("0") +} + +fn round84_inplace_solinas_fold_enabled() -> bool { + std::env::var("ROUND84_INPLACE_SOLINAS_FOLD") + .ok() + .as_deref() + == Some("1") +} + +fn round84_fold_fast_add_enabled() -> bool { + std::env::var("ROUND84_FOLD_FAST_ADD").ok().as_deref() == Some("1") +} +#[inline] +fn round84_add_small(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + if round84_fold_fast_add_enabled() { + add_nbit_qq_fast(b, a, acc); + } else { + add_nbit_qq(b, a, acc); + } +} +#[inline] +fn round84_sub_small(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + if round84_fold_fast_add_enabled() { + sub_nbit_qq_fast(b, a, acc); + } else { + sub_nbit_qq(b, a, acc); + } +} + +fn round84_inplace_quotient_carry_trunc_window() -> usize { + std::env::var("ROUND84_INPLACE_QUOTIENT_CARRY_TRUNC_W") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(21) + .max(1) +} + +fn round84_inplace_vent_carry_enabled() -> bool { + std::env::var("ROUND84_INPLACE_VENT_CARRY") + .ok() + .as_deref() + == Some("1") +} + +fn round84_correction_wrap_borrow_quotient_top_enabled() -> bool { + std::env::var("ROUND84_CORRECTION_WRAP_BORROW_QUOTIENT_TOP") + .ok() + .as_deref() + == Some("1") +} + +fn round84_keep_quotient_product_enabled() -> bool { + std::env::var("ROUND84_KEEP_QUOTIENT_PRODUCT") + .ok() + .as_deref() + == Some("1") +} + +fn round84_qprod_naf_enabled() -> bool { + std::env::var("R84_QPROD_NAF").ok().as_deref() == Some("1") +} + +fn round84_qprod_short_enabled() -> bool { + std::env::var("ROUND84_QPROD_SHORT").ok().as_deref() == Some("1") +} + +struct Round84FoldStep { + shift: usize, + add: bool, + wrap: QubitId, +} + +struct Round84AggregateFold { + steps: Vec, + quotient: Vec, + correction_wrap: QubitId, + correction_wrap_owned: bool, + product: Option>, +} + +fn round84_update_fold_quotient( + b: &mut B, + quotient: &[QubitId], + hi: &[QubitId], + step: &Round84FoldStep, + inverse: bool, +) { + let add = step.add != inverse; + let update_wrap = |b: &mut B| { + if add { + cadd_nbit_const_direct_fast(b, quotient, U256::from(1), step.wrap); + } else { + csub_nbit_const_direct_fast(b, quotient, U256::from(1), step.wrap); + } + }; + let update_spill = |b: &mut B| { + if step.shift == 0 { + return; + } + let pad = b.alloc_qubits(quotient.len() - step.shift); + let mut spill = hi[hi.len() - step.shift..].to_vec(); + spill.extend_from_slice(&pad); + if add { + add_nbit_qq(b, &spill, quotient); + } else { + sub_nbit_qq(b, &spill, quotient); + } + b.free_vec(&pad); + }; + + if inverse { + update_wrap(b); + update_spill(b); + } else { + update_spill(b); + update_wrap(b); + } +} + +fn round84_compute_quotient_c_product(b: &mut B, quotient: &[QubitId], dirty: &[QubitId]) -> Vec { + + let q = "ient[..33]; + let product = b.alloc_qubits(66); + for i in 0..q.len() { + b.cx(q[i], product[i]); + } + if round84_qprod_naf_enabled() { + for (shift, add) in [(10usize, true), (32, true), (5, false), (4, false)] { + if round84_qprod_vent_pad_enabled() + && (product.len() - shift - q.len()) >= round84_qprod_vent_pad_min_width() + { + round84_qprod_shifted_addsub_vented(b, q, &product, shift, add, dirty); + continue; + } + let target = &product[shift..]; + if round84_qprod_short_enabled() { + if add { + add_short_to_long_qq_fast_no_cin(b, q, target); + } else { + sub_short_to_long_qq_fast_no_cin(b, q, target); + } + } else { + let pad = b.alloc_qubits(target.len() - q.len()); + let mut source = q.to_vec(); + source.extend_from_slice(&pad); + if add { + round84_add_small(b, &source, target); + } else { + round84_sub_small(b, &source, target); + } + b.free_vec(&pad); + } + } + } else { + for shift in [4usize, 6, 7, 8, 9, 32] { + let target = &product[shift..]; + if round84_qprod_short_enabled() { + add_short_to_long_qq_fast_no_cin(b, q, target); + } else { + let pad = b.alloc_qubits(target.len() - q.len()); + let mut source = q.to_vec(); + source.extend_from_slice(&pad); + round84_add_small(b, &source, target); + b.free_vec(&pad); + } + } + } + product +} + +fn round84_uncompute_quotient_c_product(b: &mut B, quotient: &[QubitId], product: &[QubitId], dirty: &[QubitId]) { + let q = "ient[..33]; + if round84_qprod_naf_enabled() { + for (shift, add) in [(10usize, true), (32, true), (5, false), (4, false)] + .into_iter() + .rev() + { + if round84_qprod_vent_pad_enabled() + && (product.len() - shift - q.len()) >= round84_qprod_vent_pad_min_width() + { + + round84_qprod_shifted_addsub_vented(b, q, product, shift, !add, dirty); + continue; + } + let target = &product[shift..]; + if round84_qprod_short_enabled() { + if add { + sub_short_to_long_qq_fast_no_cin(b, q, target); + } else { + add_short_to_long_qq_fast_no_cin(b, q, target); + } + } else { + let pad = b.alloc_qubits(target.len() - q.len()); + let mut source = q.to_vec(); + source.extend_from_slice(&pad); + if add { + round84_sub_small(b, &source, target); + } else { + round84_add_small(b, &source, target); + } + b.free_vec(&pad); + } + } + } else { + for shift in [4usize, 6, 7, 8, 9, 32].into_iter().rev() { + let target = &product[shift..]; + if round84_qprod_short_enabled() { + sub_short_to_long_qq_fast_no_cin(b, q, target); + } else { + let pad = b.alloc_qubits(target.len() - q.len()); + let mut source = q.to_vec(); + source.extend_from_slice(&pad); + round84_sub_small(b, &source, target); + b.free_vec(&pad); + } + } + } + for i in 0..q.len() { + b.cx(q[i], product[i]); + } + b.free_vec(product); +} + +fn round84_add_narrow_correction( + b: &mut B, + lo: &[QubitId], + product: &[QubitId], + dirty: &[QubitId], + borrowed_wrap: Option, +) -> (QubitId, bool) { + let (wrap, owned_wrap) = borrowed_wrap.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); + let source_top = b.alloc_qubit(); + let mut target_ext = lo[..product.len()].to_vec(); + target_ext.push(wrap); + let mut source_ext = product.to_vec(); + source_ext.push(source_top); + round84_add_small(b, &source_ext, &target_ext); + b.free(source_top); + let high = &lo[product.len()..]; + if round84_inplace_vent_carry_enabled() { + let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; + venting::ciadd_dirty_2clean_classical( + b, + high, + &dirty[..high.len() - 2], + &clean2, + 1, + wrap, + false, + ); + b.free(clean2[0]); + b.free(clean2[1]); + } else { + cadd_nbit_const_direct_trunc_fast( + b, + high, + U256::from(1), + wrap, + round84_inplace_quotient_carry_trunc_window(), + ); + } + (wrap, owned_wrap) +} + +fn round84_sub_narrow_correction( + b: &mut B, + lo: &[QubitId], + product: &[QubitId], + wrap: QubitId, + dirty: &[QubitId], + owned_wrap: bool, +) { + let high = &lo[product.len()..]; + if round84_inplace_vent_carry_enabled() { + let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical(b, high, &dirty[..high.len() - 2], &clean2, 1, wrap); + b.free(clean2[0]); + b.free(clean2[1]); + } else { + csub_nbit_const_direct_trunc_fast( + b, + high, + U256::from(1), + wrap, + round84_inplace_quotient_carry_trunc_window(), + ); + } + let source_top = b.alloc_qubit(); + let mut target_ext = lo[..product.len()].to_vec(); + target_ext.push(wrap); + let mut source_ext = product.to_vec(); + source_ext.push(source_top); + round84_sub_small(b, &source_ext, &target_ext); + b.free(source_top); + if owned_wrap { + b.free(wrap); + } +} + +fn round84_fold_hi_into_lo_aggregate( + b: &mut B, + lo: &[QubitId], + hi: &[QubitId], + dirty: &[QubitId], +) -> Round84AggregateFold { + let n = lo.len(); + let quotient = b.alloc_qubits(34); + + let terms = [ + (0usize, true), + (4, false), + (5, false), + (10, true), + (32, true), + ]; + let mut steps = Vec::with_capacity(terms.len()); + + for (shift, add) in terms { + let width = n - shift; + let wrap = b.alloc_qubit(); + let source_top = b.alloc_qubit(); + let mut target_ext = lo[shift..].to_vec(); + target_ext.push(wrap); + let mut source_ext = hi[..width].to_vec(); + source_ext.push(source_top); + if add { + add_nbit_qq(b, &source_ext, &target_ext); + } else { + sub_nbit_qq(b, &source_ext, &target_ext); + } + b.free(source_top); + + let step = Round84FoldStep { shift, add, wrap }; + round84_update_fold_quotient(b, "ient, hi, &step, false); + steps.push(step); + } + + let product = round84_compute_quotient_c_product(b, "ient, dirty); + let borrowed_correction_wrap = round84_correction_wrap_borrow_quotient_top_enabled() + .then_some(quotient[33]); + let (correction_wrap, correction_wrap_owned) = + round84_add_narrow_correction(b, lo, &product, dirty, borrowed_correction_wrap); + let product = if round84_keep_quotient_product_enabled() { + Some(product) + } else { + round84_uncompute_quotient_c_product(b, "ient, &product, dirty); + None + }; + Round84AggregateFold { + steps, + quotient, + correction_wrap, + correction_wrap_owned, + product, + } +} + +fn round84_unfold_hi_from_lo_aggregate( + b: &mut B, + lo: &[QubitId], + hi: &[QubitId], + dirty: &[QubitId], + state: Round84AggregateFold, +) { + let product = state + .product + .unwrap_or_else(|| round84_compute_quotient_c_product(b, &state.quotient, dirty)); + round84_sub_narrow_correction( + b, + lo, + &product, + state.correction_wrap, + dirty, + state.correction_wrap_owned, + ); + round84_uncompute_quotient_c_product(b, &state.quotient, &product, dirty); + + for step in state.steps.into_iter().rev() { + round84_update_fold_quotient(b, &state.quotient, hi, &step, true); + let width = lo.len() - step.shift; + let source_top = b.alloc_qubit(); + let mut target_ext = lo[step.shift..].to_vec(); + target_ext.push(step.wrap); + let mut source_ext = hi[..width].to_vec(); + source_ext.push(source_top); + if step.add { + sub_nbit_qq(b, &source_ext, &target_ext); + } else { + add_nbit_qq(b, &source_ext, &target_ext); + } + b.free(source_top); + b.free(step.wrap); + } + b.free_vec(&state.quotient); +} + +pub(crate) fn squaring_sub_from_acc_schoolbook(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { + let n = acc.len(); + debug_assert_eq!(n, 256); + debug_assert_eq!(x.len(), n); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let tmp_ext = b.alloc_qubits(2 * n); + + schoolbook_square_symmetric(b, x, &tmp_ext); + + let lo: Vec = tmp_ext[0..n].to_vec(); + let hi: Vec = tmp_ext[n..2 * n].to_vec(); + mod_sub_qq_fast(b, acc, &lo, p); + let _ = c; + + mod_sub_qq_fast(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_fast(b, &hi, p); + } + mod_sub_qq_fast(b, acc, &hi, p); + for _ in 0..2 { + mod_double_inplace_fast(b, &hi, p); + } + mod_add_qq_fast(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_fast(b, &hi, p); + } + mod_sub_qq_fast(b, acc, &hi, p); + let (spill, flag_inv, ovf) = mod_shift_left_by_k(b, &hi, p, 22); + mod_sub_qq(b, acc, &hi, p); + mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); + for _ in 0..10 { + mod_halve_inplace_fast(b, &hi, p); + } + + schoolbook_square_symmetric_inverse(b, x, &tmp_ext); + + b.free_vec(&tmp_ext); +} + +pub(crate) fn squaring_sub_from_acc_karatsuba(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { + let n = acc.len(); + debug_assert_eq!(n, 256); + debug_assert_eq!(x.len(), n); + let h = n / 2; + let x_lo: Vec = x[0..h].to_vec(); + let x_hi: Vec = x[h..n].to_vec(); + + let mut z1_reg = b.alloc_qubits(2 * (h + 1)); + + let free_z1_top = std::env::var("KARA_FREE_Z1_TOPBIT").ok().as_deref() == Some("1"); + + let z02_lowq = std::env::var("KARA_Z02_LOWQ").ok().as_deref() == Some("1"); + + { + let x_sum = b.alloc_qubits(h + 1); + karatsuba_half_sum_compute(b, &x_lo, &x_hi, &x_sum); + schoolbook_square_symmetric(b, &x_sum, &z1_reg); + karatsuba_half_sum_uncompute(b, &x_lo, &x_hi, &x_sum); + b.free_vec(&x_sum); + } + + let tmp_ext = b.alloc_qubits(2 * n); + + { + let slice: Vec = tmp_ext[0..2 * h].to_vec(); + if z02_lowq { + + let host: Vec = tmp_ext[2 * h..4 * h].to_vec(); + schoolbook_square_symmetric_hosted(b, &x_lo, &slice, &host); + } else { + schoolbook_square_symmetric(b, &x_lo, &slice); + } + } + { + let slice: Vec = tmp_ext[2 * h..4 * h].to_vec(); + if z02_lowq { + if kara_z2_selfhost_enabled() { + if square_selfhost_safe_lane_reuse_enabled() { + + let clean_square_bits = [z1_reg[1], tmp_ext[1]]; + schoolbook_square_symmetric_lowq_selfhosted_with_clean_supplement( + b, + &x_hi, + &slice, + &clean_square_bits, + ); + } else { + schoolbook_square_symmetric_lowq_selfhosted(b, &x_hi, &slice); + } + } else { + schoolbook_square_symmetric_lowq(b, &x_hi, &slice); + } + } else { + schoolbook_square_symmetric(b, &x_hi, &slice); + } + } + + { + let pad = b.alloc_qubits(2); + let mut z0_ext: Vec = tmp_ext[0..2 * h].to_vec(); + z0_ext.extend_from_slice(&pad); + sub_nbit_qq(b, &z0_ext, &z1_reg); + b.free_vec(&pad); + } + { + let pad = b.alloc_qubits(2); + let mut z2_ext: Vec = tmp_ext[2 * h..4 * h].to_vec(); + z2_ext.extend_from_slice(&pad); + sub_nbit_qq(b, &z2_ext, &z1_reg); + b.free_vec(&pad); + } + + if free_z1_top { + let top = z1_reg.pop().expect("z1_reg width 2*(h+1) >= 2"); + b.free(top); + } + { + let pad = b.alloc_qubits(3 * h - z1_reg.len()); + let mut z1_ext: Vec = z1_reg.to_vec(); + z1_ext.extend_from_slice(&pad); + let acc_slice: Vec = tmp_ext[h..4 * h].to_vec(); + add_nbit_qq(b, &z1_ext, &acc_slice); + b.free_vec(&pad); + } + + let mod_fast = std::env::var("KARA_SOL_MOD_FAST").ok().as_deref() == Some("1"); + let dbl_fast = std::env::var("KARA_SOL_DBL_FAST").ok().as_deref() == Some("1"); + let shift_fast = std::env::var("KARA_SOL_SHIFT_FAST").ok().as_deref() == Some("1"); + let lo: Vec = tmp_ext[0..n].to_vec(); + let hi: Vec = tmp_ext[n..2 * n].to_vec(); + + let mod_vent = std::env::var("KARA_SOL_MOD_VENT").ok().as_deref() == Some("1"); + let mod_sub = |b: &mut B, acc: &[QubitId], a: &[QubitId]| { + if mod_vent { + mod_sub_qq_vent(b, acc, a, p); + } else if mod_fast { + mod_sub_qq_fast(b, acc, a, p); + } else { + mod_sub_qq(b, acc, a, p); + } + }; + let mod_add = |b: &mut B, acc: &[QubitId], a: &[QubitId]| { + if mod_vent { + mod_add_qq_vent(b, acc, a, p); + } else if mod_fast { + mod_add_qq_fast(b, acc, a, p); + } else { + mod_add_qq(b, acc, a, p); + } + }; + let mod_dbl = |b: &mut B, v: &[QubitId]| { + if dbl_fast { + mod_double_inplace_fast(b, v, p); + } else { + mod_double_inplace_direct_const_fast(b, v, p); + } + }; + let mod_hlv = |b: &mut B, v: &[QubitId]| { + if dbl_fast { + mod_halve_inplace_fast(b, v, p); + } else { + mod_halve_inplace_direct_const_fast(b, v, p); + } + }; + b.set_phase("r84k_sol_subadd"); + mod_sub(b, acc, &lo); + mod_sub(b, acc, &hi); + for _ in 0..4 { + mod_dbl(b, &hi); + } + mod_sub(b, acc, &hi); + for _ in 0..2 { + mod_dbl(b, &hi); + } + mod_add(b, acc, &hi); + for _ in 0..4 { + mod_dbl(b, &hi); + } + mod_sub(b, acc, &hi); + b.set_phase("r84k_sol_shift"); + + let shift_dirty = std::env::var("ROUND84_XTAIL_BORROW_CARRIES") + .ok() + .as_deref() + == Some("1"); + if shift_dirty { + + b.set_phase("r84k_sol_dbl22"); + for _ in 0..22 { + mod_dbl(b, &hi); + } + b.set_phase("r84k_sol_midsub"); + mod_sub(b, acc, &hi); + b.set_phase("r84k_sol_hlv22"); + for _ in 0..22 { + mod_hlv(b, &hi); + } + } else { + b.set_phase("r84k_sol_shiftL"); + let (spill, flag_inv, ovf) = if shift_fast { + mod_shift_left_by_k(b, &hi, p, 22) + } else { + mod_shift_left_by_k_lowq(b, &hi, p, 22) + }; + b.set_phase("r84k_sol_midsub"); + mod_sub(b, acc, &hi); + b.set_phase("r84k_sol_shiftR"); + if shift_fast { + mod_shift_right_by_k(b, &hi, p, 22, spill, flag_inv, ovf); + } else { + mod_shift_right_by_k_lowq(b, &hi, p, 22, spill, flag_inv, ovf); + } + } + b.set_phase("r84k_sol_halve"); + for _ in 0..10 { + mod_hlv(b, &hi); + } + + b.set_phase("r84k_inv_combine"); + { + let pad = b.alloc_qubits(3 * h - z1_reg.len()); + let mut z1_ext: Vec = z1_reg.to_vec(); + z1_ext.extend_from_slice(&pad); + let acc_slice: Vec = tmp_ext[h..4 * h].to_vec(); + sub_nbit_qq(b, &z1_ext, &acc_slice); + b.free_vec(&pad); + } + + if free_z1_top { + let top = b.alloc_qubit(); + z1_reg.push(top); + } + { + let pad = b.alloc_qubits(2); + let mut z2_ext: Vec = tmp_ext[2 * h..4 * h].to_vec(); + z2_ext.extend_from_slice(&pad); + add_nbit_qq(b, &z2_ext, &z1_reg); + b.free_vec(&pad); + } + { + let pad = b.alloc_qubits(2); + let mut z0_ext: Vec = tmp_ext[0..2 * h].to_vec(); + z0_ext.extend_from_slice(&pad); + add_nbit_qq(b, &z0_ext, &z1_reg); + b.free_vec(&pad); + } + + b.set_phase("r84k_z_inv_squares"); + { + let slice: Vec = tmp_ext[2 * h..4 * h].to_vec(); + if z02_lowq { + if kara_z2_selfhost_enabled() { + if square_selfhost_safe_lane_reuse_enabled() { + + let clean_square_bits = [z1_reg[1], tmp_ext[1]]; + schoolbook_square_symmetric_lowq_selfhosted_inverse_with_clean_supplement( + b, + &x_hi, + &slice, + &clean_square_bits, + ); + } else { + schoolbook_square_symmetric_lowq_selfhosted_inverse(b, &x_hi, &slice); + } + } else { + schoolbook_square_symmetric_lowq_inverse(b, &x_hi, &slice); + } + } else { + schoolbook_square_symmetric_inverse(b, &x_hi, &slice); + } + } + { + let slice: Vec = tmp_ext[0..2 * h].to_vec(); + if z02_lowq { + + let host: Vec = tmp_ext[2 * h..4 * h].to_vec(); + schoolbook_square_symmetric_hosted_inverse(b, &x_lo, &slice, &host); + } else { + schoolbook_square_symmetric_inverse(b, &x_lo, &slice); + } + } + b.free_vec(&tmp_ext); + + { + let x_sum = b.alloc_qubits(h + 1); + karatsuba_half_sum_compute(b, &x_lo, &x_hi, &x_sum); + schoolbook_square_symmetric_inverse(b, &x_sum, &z1_reg); + karatsuba_half_sum_uncompute(b, &x_lo, &x_hi, &x_sum); + b.free_vec(&x_sum); + } + + b.free_vec(&z1_reg); +} + +pub(crate) fn squaring_sub_from_acc_schoolbook_lowq_shift22( + b: &mut B, + acc: &[QubitId], + x: &[QubitId], + p: U256, +) { + let n = acc.len(); + debug_assert_eq!(n, 256); + debug_assert_eq!(x.len(), n); + + let tmp_ext = b.alloc_qubits(2 * n); + b.set_phase("round84_inplace_solinas_square_forward"); + if xtail_sq_selfhost_enabled() { + schoolbook_square_symmetric_lowq_selfhosted(b, x, &tmp_ext); + } else { + schoolbook_square_symmetric_lowq(b, x, &tmp_ext); + } + + let lo: Vec = tmp_ext[0..n].to_vec(); + let hi: Vec = tmp_ext[n..2 * n].to_vec(); + if round84_inplace_solinas_fold_enabled() { + b.set_phase("round84_inplace_solinas_fold"); + let state = round84_fold_hi_into_lo_aggregate(b, &lo, &hi, acc); + b.set_phase("round84_inplace_solinas_sub"); + mod_sub_qq_vent(b, acc, &lo, p); + b.set_phase("round84_inplace_solinas_unfold"); + round84_unfold_hi_from_lo_aggregate(b, &lo, &hi, acc, state); + } else { + mod_sub_qq(b, acc, &lo, p); + mod_sub_qq(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_direct_const_fast(b, &hi, p); + } + mod_sub_qq(b, acc, &hi, p); + for _ in 0..2 { + mod_double_inplace_direct_const_fast(b, &hi, p); + } + mod_add_qq(b, acc, &hi, p); + for _ in 0..4 { + mod_double_inplace_direct_const_fast(b, &hi, p); + } + mod_sub_qq(b, acc, &hi, p); + let (spill, flag_inv, ovf) = mod_shift_left_by_k_lowq(b, &hi, p, 22); + if r84_lowq_enabled() { + mod_sub_qq_lowq(b, acc, &hi, p); + } else { + mod_sub_qq(b, acc, &hi, p); + } + mod_shift_right_by_k_lowq(b, &hi, p, 22, spill, flag_inv, ovf); + for _ in 0..10 { + mod_halve_inplace_direct_const_fast(b, &hi, p); + } + } + + b.set_phase("round84_inplace_solinas_square_inverse"); + if xtail_sq_selfhost_enabled() { + schoolbook_square_symmetric_lowq_selfhosted_inverse(b, x, &tmp_ext); + } else { + schoolbook_square_symmetric_lowq_inverse(b, x, &tmp_ext); + } + b.free_vec(&tmp_ext); +} + +pub(crate) fn squaring_sub_from_acc_walk_controls_lowq(b: &mut B, acc: &[QubitId], x: &[QubitId], p: U256) { + let n = acc.len(); + debug_assert_eq!(n, 256); + debug_assert_eq!(x.len(), n); + + let ctrl_copy = b.alloc_qubits(n); + for i in 0..n { + b.cx(x[i], ctrl_copy[i]); + } + + mod_neg_inplace_fast(b, x, p); + for i in 0..n { + cmod_add_qq(b, acc, x, ctrl_copy[i], p); + if i < n - 1 { + mod_double_inplace_fast(b, x, p); + } + } + for _ in 0..(n - 1) { + mod_halve_inplace_fast(b, x, p); + } + mod_neg_inplace_fast(b, x, p); + + for i in 0..n { + b.cx(x[i], ctrl_copy[i]); + } + b.free_vec(&ctrl_copy); +} + +fn round84_qprod_vent_pad_enabled() -> bool { + std::env::var("ROUND84_QPROD_VENT_PAD").ok().as_deref() == Some("1") +} + +fn round84_qprod_vent_pad_min_width() -> usize { + std::env::var("ROUND84_QPROD_VENT_PAD_MINW") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(29) +} + +fn round84_qprod_shifted_addsub_vented( + b: &mut B, + q: &[QubitId], + product: &[QubitId], + shift: usize, + add: bool, + dirty: &[QubitId], +) { + let m = q.len(); + let total = product.len() - shift; + debug_assert!(total >= m); + let high_w = total - m; + + if high_w < 5 || dirty.len() < high_w.saturating_sub(2) { + let target = &product[shift..]; + let pad = b.alloc_qubits(high_w); + let mut source = q.to_vec(); + source.extend_from_slice(&pad); + if add { + round84_add_small(b, &source, target); + } else { + round84_sub_small(b, &source, target); + } + b.free_vec(&pad); + return; + } + + let wrap = b.alloc_qubit(); + let mut low_ext = product[shift..shift + m].to_vec(); + low_ext.push(wrap); + let high = &product[shift + m..]; + + if add { + + let c_in = b.alloc_qubit(); + cuccaro_add_low_to_ext_clean(b, q, &low_ext, c_in); + b.free(c_in); + + let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; + venting::ciadd_dirty_2clean_classical( + b, + high, + &dirty[..high_w - 2], + &clean2, + 1, + wrap, + false, + ); + b.free(clean2[1]); + b.free(clean2[0]); + + cmp_lt_into(b, &product[shift..shift + m], q, wrap); + } else { + + let c_in = b.alloc_qubit(); + cuccaro_sub_low_to_ext_clean(b, q, &low_ext, c_in); + b.free(c_in); + + let clean2 = [b.alloc_qubit(), b.alloc_qubit()]; + venting::cisub_dirty_2clean_classical(b, high, &dirty[..high_w - 2], &clean2, 1, wrap); + b.free(clean2[1]); + b.free(clean2[0]); + + for &qb in q { + b.x(qb); + } + cmp_lt_into(b, q, &product[shift..shift + m], wrap); + for &qb in q { + b.x(qb); + } + } + b.free(wrap); +} + +pub(crate) fn cross_addsub_stage1( + b: &mut B, + prod: &[QubitId], + off: usize, + addend: &[QubitId], + ctrl: QubitId, +) { + let w = prod.len(); + let m = addend.len(); + if m == 0 { + return; + } + debug_assert!(off + m <= w); + let t = b.alloc_qubits(w); + for k in 0..m { + b.cx(addend[k], t[off + k]); + } + b.x(ctrl); + for k in 0..w { + b.cx(ctrl, t[k]); + } + let cin = b.alloc_qubit(); + b.cx(ctrl, cin); + cuccaro_add(b, &t, prod, cin); + b.cx(ctrl, cin); + for k in 0..w { + b.cx(ctrl, t[k]); + } + b.x(ctrl); + for k in 0..m { + b.cx(addend[k], t[off + k]); + } + b.free(cin); + b.free_vec(&t); +} + +pub(crate) fn square_addsub_stage1(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(prod.len(), 2 * n); + + for i in 0..n { + let m = n - 1 - i; + if m == 0 { + continue; + } + let off = 2 * i + 1; + cross_addsub_stage1(b, prod, off, &x[i + 1..n], x[i]); + } + + let t = b.alloc_qubits(2 * n); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + let cin = b.alloc_qubit(); + cuccaro_add(b, &t, prod, cin); + b.free(cin); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + b.free_vec(&t); + + let zero_ctrl = b.alloc_qubit(); + cross_addsub_stage1(b, prod, 0, x, zero_ctrl); + b.free(zero_ctrl); +} + +fn square_corr_forward(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + + let zeros = b.alloc_qubits(n); + let mut a2d: Vec = Vec::with_capacity(2 * n); + for i in 0..n { + a2d.push(zeros[i]); + a2d.push(x[i]); + } + let cin = b.alloc_qubit(); + cuccaro_add(b, &a2d, prod, cin); + b.free(cin); + b.free_vec(&zeros); + + let pad = b.alloc_qubits(n); + let mut xext = x.to_vec(); + xext.extend_from_slice(&pad); + let cinx = b.alloc_qubit(); + cuccaro_sub(b, &xext, prod, cinx); + b.free(cinx); + b.free_vec(&pad); + + let p1 = b.alloc_qubit(); + let mut a = x[0..n - 1].to_vec(); + a.push(p1); + let high: Vec = prod[n..2 * n].to_vec(); + let cinl = b.alloc_qubit(); + b.x(cinl); + cuccaro_add(b, &a, &high, cinl); + b.x(cinl); + b.free(cinl); + b.free(p1); + + b.x(prod[2 * n - 1]); +} + +fn square_corr_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + + b.x(prod[2 * n - 1]); + + let p1 = b.alloc_qubit(); + let mut a = x[0..n - 1].to_vec(); + a.push(p1); + let high: Vec = prod[n..2 * n].to_vec(); + let cinl = b.alloc_qubit(); + b.x(cinl); + cuccaro_sub(b, &a, &high, cinl); + b.x(cinl); + b.free(cinl); + b.free(p1); + + let pad = b.alloc_qubits(n); + let mut xext = x.to_vec(); + xext.extend_from_slice(&pad); + let cinx = b.alloc_qubit(); + cuccaro_add(b, &xext, prod, cinx); + b.free(cinx); + b.free_vec(&pad); + + let zeros = b.alloc_qubits(n); + let mut a2d: Vec = Vec::with_capacity(2 * n); + for i in 0..n { + a2d.push(zeros[i]); + a2d.push(x[i]); + } + let cin = b.alloc_qubit(); + cuccaro_sub(b, &a2d, prod, cin); + b.free(cin); + b.free_vec(&zeros); +} + +pub(crate) fn square_addsub_local(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(prod.len(), 2 * n); + + for i in 0..n { + let m = n - 1 - i; + if m == 0 { + continue; + } + let off = 2 * i + 1; + let slice: Vec = prod[off..off + m + 1].to_vec(); + controlled_add_subtract_lowq(b, &x[i + 1..n], &slice, x[i]); + } + + let t = b.alloc_qubits(2 * n); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + let cin = b.alloc_qubit(); + cuccaro_add(b, &t, prod, cin); + b.free(cin); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + b.free_vec(&t); + + let zc = b.alloc_qubit(); + cross_addsub_stage1(b, prod, 0, x, zc); + b.free(zc); + + if n >= 2 { + let oc = b.alloc_qubit(); + b.x(oc); + cross_addsub_stage1(b, prod, n, &x[0..n - 1], oc); + b.x(oc); + b.free(oc); + } + + let t2 = b.alloc_qubits(2 * n); + b.x(t2[2 * n - 1]); + b.x(t2[n]); + let cin2 = b.alloc_qubit(); + cuccaro_add(b, &t2, prod, cin2); + b.free(cin2); + b.x(t2[2 * n - 1]); + b.x(t2[n]); + b.free_vec(&t2); +} + +pub(crate) fn controlled_add_subtract_vented_borrowed( + b: &mut B, + x: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + carries: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(acc.len(), n + 1); + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + let c_in = b.alloc_qubit(); + b.x(ctrl); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.cx(ctrl, c_in); + cuccaro_add_fast_borrowed_carries(b, &x_ext, acc, c_in, carries); + b.cx(ctrl, c_in); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.x(ctrl); + b.free(c_in); + b.free(pad); +} + +pub(crate) fn square_addsub_vented(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(prod.len(), 2 * n); + for i in 0..n { + let m = n - 1 - i; + if m == 0 { + continue; + } + let off = 2 * i + 1; + let slice: Vec = prod[off..off + m + 1].to_vec(); + + let hi = off + m + 1; + let need = m; + let carries: Vec = prod[hi..hi + need].to_vec(); + controlled_add_subtract_vented_borrowed(b, &x[i + 1..n], &slice, x[i], &carries); + } + + square_corr_forward(b, x, prod); +} + +pub(crate) fn square_addsub_local_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(prod.len(), 2 * n); + let t2 = b.alloc_qubits(2 * n); + b.x(t2[2 * n - 1]); + b.x(t2[n]); + let cin2 = b.alloc_qubit(); + cuccaro_sub(b, &t2, prod, cin2); + b.free(cin2); + b.x(t2[2 * n - 1]); + b.x(t2[n]); + b.free_vec(&t2); + if n >= 2 { + let zc = b.alloc_qubit(); + cross_addsub_stage1(b, prod, n, &x[0..n - 1], zc); + b.free(zc); + } + let oc = b.alloc_qubit(); + b.x(oc); + cross_addsub_stage1(b, prod, 0, x, oc); + b.x(oc); + b.free(oc); + let t = b.alloc_qubits(2 * n); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + let cin = b.alloc_qubit(); + cuccaro_sub(b, &t, prod, cin); + b.free(cin); + for i in 0..n { + let p = 2 * i + 1; + if p < 2 * n { + b.cx(x[i], t[p]); + } + } + b.free_vec(&t); + for i in (0..n).rev() { + let m = n - 1 - i; + if m == 0 { + continue; + } + let off = 2 * i + 1; + let slice: Vec = prod[off..off + m + 1].to_vec(); + controlled_add_subtract_lowq_inverse(b, &x[i + 1..n], &slice, x[i]); + } +} + +pub(crate) fn controlled_add_subtract_vented_borrowed_inverse( + b: &mut B, + x: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + carries: &[QubitId], +) { + let n = x.len(); + debug_assert_eq!(acc.len(), n + 1); + let pad = b.alloc_qubit(); + let mut x_ext = x.to_vec(); + x_ext.push(pad); + let c_in = b.alloc_qubit(); + b.x(ctrl); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.cx(ctrl, c_in); + cuccaro_sub_fast_borrowed_carries(b, &x_ext, acc, c_in, carries); + b.cx(ctrl, c_in); + for i in 0..n { + b.cx(ctrl, x_ext[i]); + } + b.x(ctrl); + b.free(c_in); + b.free(pad); +} + +pub(crate) fn square_addsub_vented_inverse(b: &mut B, x: &[QubitId], prod: &[QubitId]) { + let n = x.len(); + debug_assert_eq!(prod.len(), 2 * n); + + square_corr_inverse(b, x, prod); + + for i in (0..n).rev() { + let m = n - 1 - i; + if m == 0 { + continue; + } + let off = 2 * i + 1; + let slice: Vec = prod[off..off + m + 1].to_vec(); + let hi = off + m + 1; + let carries: Vec = prod[hi..hi + m].to_vec(); + controlled_add_subtract_vented_borrowed_inverse(b, &x[i + 1..n], &slice, x[i], &carries); + } +} + +pub(crate) mod square_addsub_selftest { + use super::*; + use crate::sim::Simulator; + use crate::circuit::OperationType; + use sha3::digest::{ExtendableOutput, Update, XofReader}; + + fn count_tof(ops: &[crate::circuit::Op]) -> usize { + ops.iter() + .filter(|o| matches!(o.kind, OperationType::CCX | OperationType::CCZ)) + .count() + } + + pub(crate) fn toffoli_compare() { + for &n in &[128usize, 129] { + let mut b1 = B::new(); + let x1 = b1.alloc_qubits(n); + let p1 = b1.alloc_qubits(2 * n); + schoolbook_square_symmetric(&mut b1, &x1, &p1); + let cur = count_tof(&b1.ops); + let peak_cur = b1.peak_qubits; + + let mut b2 = B::new(); + let x2 = b2.alloc_qubits(n); + let p2 = b2.alloc_qubits(2 * n); + square_addsub_vented(&mut b2, &x2, &p2); + let new = count_tof(&b2.ops); + let peak_new = b2.peak_qubits; + + println!( + " SQ_TOF n={n}: current(AND) CCX={cur} peakQ={peak_cur} | addsub_vented CCX={new} peakQ={peak_new} | delta={}", + cur as i64 - new as i64 + ); + } + } + + pub(crate) fn run() { + let big = std::env::var("TLM_SQ_SELFTEST_BIG").ok().as_deref() == Some("1"); + exhaustive_small_n(); + random_large_n(if big { 4096 } else { 64 }); + println!(" SQ_SELFTEST (vented): bit-exact vs classical x^2 — 0 divergence"); + inverse_drains_to_zero(if big { 4096 } else { 256 }); + println!(" SQ_SELFTEST (inverse): forward+inverse drains prod to 0, clean"); + toffoli_compare(); + } + + fn inverse_drains_to_zero(count: usize) { + for &n in &[1usize, 2, 3, 8, 32, 127, 128, 129] { + let mut seed = sha3::Shake256::default(); + seed.update(b"missed3-inv"); + seed.update(&[n as u8]); + let mut xof = seed.finalize_xof(); + let mut buf = [0u8; 32]; + let batches = (count / 64).max(1); + for batch in 0..batches { + let mut xs = Vec::with_capacity(64); + for _ in 0..64 { + xof.read(&mut buf); + let mut v = U256::from_le_bytes(buf); + if n < 256 { + v &= (U256::from(1u64) << n) - U256::from(1u64); + } + xs.push(v); + } + let mut b = B::new(); + let x = b.alloc_qubits(n); + let prod = b.alloc_qubits(2 * n); + square_addsub_vented(&mut b, &x, &prod); + square_addsub_vented_inverse(&mut b, &x, &prod); + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut s2 = sha3::Shake256::default(); + s2.update(b"missed3-inv-sim"); + s2.update(&[n as u8, batch as u8]); + let mut xof2 = s2.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof2); + sim.clear_for_shot(); + for (shot, xv) in xs.iter().enumerate() { + for i in 0..n { + if xv.bit(i) { + *sim.qubit_mut(x[i]) |= 1u64 << shot; + } + } + } + sim.apply_iter(b.ops.iter()); + assert_eq!(sim.phase, 0, "inv n={n} b{batch}: phase garbage"); + + let mut is_x = vec![false; nq]; + for &q in x.iter() { + is_x[q.0 as usize] = true; + } + for q in 0..nq { + if !is_x[q] { + assert_eq!( + sim.qubit(QubitId(q as u64)), + 0, + "inv n={n} b{batch}: nonzero q{q} (prod/ancilla not drained)" + ); + } + } + for (shot, xv) in xs.iter().enumerate() { + for i in 0..n { + let got = (sim.qubit(x[i]) >> shot) & 1 == 1; + assert_eq!(got, xv.bit(i), "inv n={n} b{batch}: x[{i}] corrupted"); + } + } + } + } + } + + fn check_square(n: usize, xs: &[U256], label: &str) { + assert!(xs.len() <= 64); + let mut b = B::new(); + let x = b.alloc_qubits(n); + let prod = b.alloc_qubits(2 * n); + square_addsub_vented(&mut b, &x, &prod); + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + + let mut seed = sha3::Shake256::default(); + seed.update(b"missed3-square-addsub-stage1"); + seed.update(label.as_bytes()); + let mut xof = seed.finalize_xof(); + + let mut sim = Simulator::new(nq, nb, &mut xof); + sim.clear_for_shot(); + for (shot, xv) in xs.iter().enumerate() { + for i in 0..n { + if xv.bit(i) { + *sim.qubit_mut(x[i]) |= 1u64 << shot; + } + } + } + sim.apply_iter(b.ops.iter()); + + let cond_mask: u64 = if xs.len() == 64 { + u64::MAX + } else { + (1u64 << xs.len()) - 1 + }; + if sim.phase & cond_mask != 0 { + let mut is_reg = vec![false; nq]; + for &q in x.iter().chain(prod.iter()) { + is_reg[q.0 as usize] = true; + } + for q in 0..nq { + let v = sim.qubit(QubitId(q as u64)) & cond_mask; + if !is_reg[q] && v != 0 { + eprintln!(" DIRTY q{q} = {v:#018x}"); + } + } + panic!("{label}: phase garbage {:#018x}", sim.phase & cond_mask); + } + + for (shot, xv) in xs.iter().enumerate() { + let mut out = U256::ZERO; + for i in 0..(2 * n) { + if (sim.qubit(prod[i]) >> shot) & 1 == 1 { + out |= U256::from(1u64) << i; + } + } + let expect = xv.wrapping_mul(*xv); + assert_eq!(out, expect, "{label}: shot {shot} x={xv:#x} got {out:#x}"); + } + + let mut is_reg = vec![false; nq]; + for &q in x.iter().chain(prod.iter()) { + is_reg[q.0 as usize] = true; + } + for q in 0..nq { + if !is_reg[q] { + assert_eq!( + sim.qubit(QubitId(q as u64)) & cond_mask, + 0, + "{label}: dirty ancilla q{q}" + ); + } + } + } + + fn exhaustive_small_n() { + for n in 1..=6usize { + let limit = 1usize << n; + let xs: Vec = (0..limit).map(|v| U256::from(v as u64)).collect(); + + for chunk in xs.chunks(64) { + check_square(n, chunk, &format!("exhaustive-n{n}")); + } + } + } + + fn random_large_n(batches: usize) { + for &n in &[8usize, 16, 32, 64, 127, 128, 129] { + let mut seed = sha3::Shake256::default(); + seed.update(b"missed3-rand"); + seed.update(&[n as u8]); + let mut xof = seed.finalize_xof(); + let mut buf = [0u8; 32]; + for batch in 0..batches { + let mut xs = Vec::with_capacity(64); + for _ in 0..64 { + xof.read(&mut buf); + let mut v = U256::from_le_bytes(buf); + + if n < 256 { + v &= (U256::from(1u64) << n) - U256::from(1u64); + } + xs.push(v); + } + check_square(n, &xs, &format!("rand-n{n}-b{batch}")); + } + } + } +} diff --git a/src/point_add/arith/nbit.rs b/src/point_add/arith/nbit.rs index 6216a2ff..36fd5634 100644 --- a/src/point_add/arith/nbit.rs +++ b/src/point_add/arith/nbit.rs @@ -1,182 +1,182 @@ -use super::*; - -pub(crate) fn add_nbit_qq_fast(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_add_fast(b, a, acc, c_in); - b.free(c_in); -} - -pub(crate) fn sub_nbit_qq_fast(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_sub_fast(b, a, acc, c_in); - b.free(c_in); -} - -pub(crate) fn add_nbit_qq_fast_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - carries: &[QubitId], -) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_add_fast_borrowed_carries(b, a, acc, c_in, carries); - b.free(c_in); -} - -pub(crate) fn sub_nbit_qq_fast_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - carries: &[QubitId], -) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_sub_fast_borrowed_carries(b, a, acc, c_in, carries); - b.free(c_in); -} - -#[inline] -fn maj3_into_clean_2ccx(b: &mut B, x: QubitId, y: QubitId, z: QubitId, target: QubitId) { - debug_assert!(x != y && x != z && x != target && y != z && y != target && z != target); - b.ccx(x, z, target); - b.cx(x, z); - b.ccx(y, z, target); - b.cx(x, z); -} - -pub(crate) fn add_short_to_long_qq_fast_no_cin(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - let m = a.len(); - let n = acc.len(); - assert!(m > 0); - assert!(m <= n); - if n == 1 { - b.cx(a[0], acc[0]); - return; - } - - let carries = b.alloc_qubits(n - 1); - for i in 0..n - 1 { - if i < m { - if i == 0 { - b.ccx(acc[i], a[i], carries[i]); - } else { - maj3_into_clean_2ccx(b, acc[i], a[i], carries[i - 1], carries[i]); - } - } else { - b.ccx(acc[i], carries[i - 1], carries[i]); - } - } - - for i in 0..n { - if i < m { - b.cx(a[i], acc[i]); - } - if i > 0 { - b.cx(carries[i - 1], acc[i]); - } - } - - for i in (0..n - 1).rev() { - let bit = b.alloc_bit(); - b.hmr(carries[i], bit); - if i < m { - b.x(acc[i]); - b.cz_if(acc[i], a[i], bit); - if i > 0 { - b.cz_if(acc[i], carries[i - 1], bit); - b.x(acc[i]); - b.cz_if(a[i], carries[i - 1], bit); - } else { - b.x(acc[i]); - } - } else { - b.x(acc[i]); - b.cz_if(acc[i], carries[i - 1], bit); - b.x(acc[i]); - } - } - b.free_vec(&carries); -} - -pub(crate) fn sub_short_to_long_qq_fast_no_cin(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - let m = a.len(); - let n = acc.len(); - assert!(m > 0); - assert!(m <= n); - if n == 1 { - b.cx(a[0], acc[0]); - return; - } - - let borrows = b.alloc_qubits(n - 1); - for i in 0..n - 1 { - if i < m { - b.x(acc[i]); - if i == 0 { - b.ccx(acc[i], a[i], borrows[i]); - } else { - maj3_into_clean_2ccx(b, acc[i], a[i], borrows[i - 1], borrows[i]); - } - b.x(acc[i]); - } else { - b.x(acc[i]); - b.ccx(acc[i], borrows[i - 1], borrows[i]); - b.x(acc[i]); - } - } - - for i in 0..n { - if i < m { - b.cx(a[i], acc[i]); - } - if i > 0 { - b.cx(borrows[i - 1], acc[i]); - } - } - - for i in (0..n - 1).rev() { - let bit = b.alloc_bit(); - b.hmr(borrows[i], bit); - if i < m { - b.cz_if(acc[i], a[i], bit); - if i > 0 { - b.cz_if(acc[i], borrows[i - 1], bit); - b.cz_if(a[i], borrows[i - 1], bit); - } - } else { - b.cz_if(acc[i], borrows[i - 1], bit); - } - } - b.free_vec(&borrows); -} - -pub(crate) fn add_nbit_qq(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_add(b, a, acc, c_in); - b.free(c_in); -} - -pub(crate) fn sub_nbit_qq(b: &mut B, a: &[QubitId], acc: &[QubitId]) { - assert_eq!(a.len(), acc.len()); - let c_in = b.alloc_qubit(); - cuccaro_sub(b, a, acc, c_in); - b.free(c_in); -} - -pub(crate) fn add_nbit_const(b: &mut B, acc: &[QubitId], c: U256) { - let n = acc.len(); - let a = load_const(b, n, c); - add_nbit_qq(b, &a, acc); - unload_const(b, &a, c); -} - -pub(crate) fn sub_nbit_const(b: &mut B, acc: &[QubitId], c: U256) { - let n = acc.len(); - let a = load_const(b, n, c); - sub_nbit_qq(b, &a, acc); - unload_const(b, &a, c); -} +use super::*; + +pub(crate) fn add_nbit_qq_fast(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_add_fast(b, a, acc, c_in); + b.free(c_in); +} + +pub(crate) fn sub_nbit_qq_fast(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_sub_fast(b, a, acc, c_in); + b.free(c_in); +} + +pub(crate) fn add_nbit_qq_fast_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + carries: &[QubitId], +) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_add_fast_borrowed_carries(b, a, acc, c_in, carries); + b.free(c_in); +} + +pub(crate) fn sub_nbit_qq_fast_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + carries: &[QubitId], +) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_sub_fast_borrowed_carries(b, a, acc, c_in, carries); + b.free(c_in); +} + +#[inline] +fn maj3_into_clean_2ccx(b: &mut B, x: QubitId, y: QubitId, z: QubitId, target: QubitId) { + debug_assert!(x != y && x != z && x != target && y != z && y != target && z != target); + b.ccx(x, z, target); + b.cx(x, z); + b.ccx(y, z, target); + b.cx(x, z); +} + +pub(crate) fn add_short_to_long_qq_fast_no_cin(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + let m = a.len(); + let n = acc.len(); + assert!(m > 0); + assert!(m <= n); + if n == 1 { + b.cx(a[0], acc[0]); + return; + } + + let carries = b.alloc_qubits(n - 1); + for i in 0..n - 1 { + if i < m { + if i == 0 { + b.ccx(acc[i], a[i], carries[i]); + } else { + maj3_into_clean_2ccx(b, acc[i], a[i], carries[i - 1], carries[i]); + } + } else { + b.ccx(acc[i], carries[i - 1], carries[i]); + } + } + + for i in 0..n { + if i < m { + b.cx(a[i], acc[i]); + } + if i > 0 { + b.cx(carries[i - 1], acc[i]); + } + } + + for i in (0..n - 1).rev() { + let bit = b.alloc_bit(); + b.hmr(carries[i], bit); + if i < m { + b.x(acc[i]); + b.cz_if(acc[i], a[i], bit); + if i > 0 { + b.cz_if(acc[i], carries[i - 1], bit); + b.x(acc[i]); + b.cz_if(a[i], carries[i - 1], bit); + } else { + b.x(acc[i]); + } + } else { + b.x(acc[i]); + b.cz_if(acc[i], carries[i - 1], bit); + b.x(acc[i]); + } + } + b.free_vec(&carries); +} + +pub(crate) fn sub_short_to_long_qq_fast_no_cin(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + let m = a.len(); + let n = acc.len(); + assert!(m > 0); + assert!(m <= n); + if n == 1 { + b.cx(a[0], acc[0]); + return; + } + + let borrows = b.alloc_qubits(n - 1); + for i in 0..n - 1 { + if i < m { + b.x(acc[i]); + if i == 0 { + b.ccx(acc[i], a[i], borrows[i]); + } else { + maj3_into_clean_2ccx(b, acc[i], a[i], borrows[i - 1], borrows[i]); + } + b.x(acc[i]); + } else { + b.x(acc[i]); + b.ccx(acc[i], borrows[i - 1], borrows[i]); + b.x(acc[i]); + } + } + + for i in 0..n { + if i < m { + b.cx(a[i], acc[i]); + } + if i > 0 { + b.cx(borrows[i - 1], acc[i]); + } + } + + for i in (0..n - 1).rev() { + let bit = b.alloc_bit(); + b.hmr(borrows[i], bit); + if i < m { + b.cz_if(acc[i], a[i], bit); + if i > 0 { + b.cz_if(acc[i], borrows[i - 1], bit); + b.cz_if(a[i], borrows[i - 1], bit); + } + } else { + b.cz_if(acc[i], borrows[i - 1], bit); + } + } + b.free_vec(&borrows); +} + +pub(crate) fn add_nbit_qq(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_add(b, a, acc, c_in); + b.free(c_in); +} + +pub(crate) fn sub_nbit_qq(b: &mut B, a: &[QubitId], acc: &[QubitId]) { + assert_eq!(a.len(), acc.len()); + let c_in = b.alloc_qubit(); + cuccaro_sub(b, a, acc, c_in); + b.free(c_in); +} + +pub(crate) fn add_nbit_const(b: &mut B, acc: &[QubitId], c: U256) { + let n = acc.len(); + let a = load_const(b, n, c); + add_nbit_qq(b, &a, acc); + unload_const(b, &a, c); +} + +pub(crate) fn sub_nbit_const(b: &mut B, acc: &[QubitId], c: U256) { + let n = acc.len(); + let a = load_const(b, n, c); + sub_nbit_qq(b, &a, acc); + unload_const(b, &a, c); +} diff --git a/src/point_add/d2_deep_strip.rs b/src/point_add/d2_deep_strip.rs deleted file mode 100644 index 2a5c644f..00000000 --- a/src/point_add/d2_deep_strip.rs +++ /dev/null @@ -1,172 +0,0 @@ -// AUTO-GENERATED - deep-strip dead-CCX set for the GAP delta=2 circuit. -// Indices into the FINAL emitted op stream (post fanout / ccz-cancel / ccx-final-cancel). -// Census-verified never-firing over 1e8 faithful-RNG inputs (hx firecensus, seeds 909/1111/2222/3333). -pub(crate) const D2_DEEP_STRIP: [usize; 1999] = [ - 20425, 21846, 128213, 144451, 160739, 160744, 177253, 242828, 259138, 275615, 291898, 324598, - 340831, 389614, 405801, 422143, 438272, 470687, 486763, 486768, 535129, 567357, 583343, 599330, - 615480, 663471, 679366, 774803, 806554, 869674, 979693, 1011063, 1057908, 1243927, 1381962, 1518764, - 1609246, 1654379, 1699364, 1744206, 1759088, 1818863, 1922277, 1936986, 1951845, 1981084, 1995893, 2010497, - 2025092, 2039851, 2054414, 2068969, 2198940, 2213510, 2227829, 2256309, 2823022, 2929947, 2957366, 3723823, - 3773358, 3819143, 3821366, 3823448, 3827795, 3832078, 3834402, 3836586, 3838790, 3841174, 3845685, 3850438, - 3852749, 3855239, 3857589, 3859959, 3862509, 3872404, 3874889, 3877545, 3882612, 3887905, 3893259, 3898538, - 3901360, 3906745, 3909627, 3912374, 3915140, 3918073, 3923693, 3926678, 3929526, 3935443, 3950319, 3953482, - 3956496, 3959542, 3959547, 3965857, 3965862, 3972275, 3994929, 3998207, 4001678, 4008359, 4011885, 4015259, - 4018656, 4022233, 4029111, 4032744, 4036247, 4057856, 4061490, 4065307, 4068984, 4072681, 4076551, 4080280, - 4087925, 4091708, 4099464, 4103303, 4107157, 4115068, 4126942, 4138965, 4138970, 4142987, 4155257, 4163566, - 4167670, 4176099, 4184589, 4197428, 4201687, 4205957, 4210402, 4219039, 4223558, 4227928, 4232310, 4241283, - 4245719, 4254812, 4273032, 4277754, 4286939, 4296364, 4301026, 4310571, 4315288, 4320176, 4329692, 4334640, - 4339448, 4344271, 4354131, 4359010, 4394169, 4399203, 4404252, 4409477, 4424948, 4440581, 4461640, 4466906, - 4488506, 4543477, 4686959, 4688040, 4691217, 4692254, 4693280, 4694295, 4695299, 4696292, 4697274, 4698245, - 4699205, 4700154, 4701092, 4702019, 4702935, 4703840, 4704734, 4705617, 4706489, 4707350, 4708200, 4709039, - 4709867, 4710684, 4711490, 4712285, 4713069, 4713842, 4714604, 4715355, 4716095, 4716824, 4717542, 4718249, - 4718945, 4719630, 4720304, 4720967, 4721619, 4722260, 4722890, 4723509, 4724117, 4724714, 4725300, 4725875, - 4726439, 4726992, 4727534, 4728065, 4728585, 4729094, 4729592, 4730079, 4730555, 4731020, 4731474, 4731917, - 4732349, 4732770, 4733180, 4733579, 4733967, 4734344, 4734710, 4735065, 4741384, 4742287, 4742752, 4742755, - 4742758, 4742761, 4742764, 4742767, 4742770, 4742773, 4742776, 4742779, 4742782, 4742785, 4742788, 4742791, - 4742794, 4742797, 4742800, 4742803, 4742806, 4742809, 4742812, 4742815, 4742818, 4742821, 4742824, 4742827, - 4742830, 4742833, 4742836, 4742839, 4742842, 4742845, 4742848, 4742851, 4742854, 4742857, 4742860, 4742863, - 4742866, 4742869, 4742872, 4742875, 4742878, 4742881, 4742884, 4742887, 4742890, 4742893, 4742896, 4742899, - 4742902, 4742905, 4742908, 4742911, 4742914, 4742917, 4742920, 4742923, 4742926, 4742929, 4742932, 4742935, - 4742938, 4742941, 4742944, 4742947, 4742950, 4742953, 4742956, 4742959, 4742962, 4742965, 4742968, 4742971, - 4742974, 4742977, 4742980, 4742983, 4742986, 4742989, 4742992, 4742995, 4742998, 4743001, 4743004, 4743007, - 4743010, 4743013, 4743016, 4743019, 4743022, 4743025, 4743028, 4743031, 4743034, 4743037, 4743040, 4743043, - 4743046, 4743049, 4743052, 4743057, 4743060, 4743063, 4743066, 4743069, 4743072, 4743075, 4743078, 4743081, - 4743084, 4743087, 4743090, 4743093, 4743096, 4743099, 4743102, 4743105, 4743108, 4743111, 4743114, 4743117, - 4743120, 4743123, 4743126, 4743129, 4743132, 4743135, 4743138, 4743141, 4743144, 4743147, 4743150, 4743153, - 4743156, 4743159, 4743162, 4743165, 4743168, 4743171, 4743174, 4743177, 4743180, 4743183, 4743186, 4743189, - 4743192, 4743195, 4743198, 4743201, 4743204, 4743207, 4743210, 4743213, 4743216, 4743219, 4743222, 4743225, - 4743228, 4743231, 4743234, 4743237, 4743240, 4743243, 4743246, 4743249, 4743252, 4743255, 4743258, 4743261, - 4743264, 4743267, 4743270, 4743273, 4743276, 4743279, 4743282, 4743285, 4743288, 4743291, 4743294, 4743297, - 4743300, 4743303, 4743306, 4743309, 4743312, 4743315, 4743318, 4743321, 4743324, 4743327, 4743330, 4743333, - 4743336, 4743339, 4743342, 4743345, 4743348, 4743351, 4743354, 4743357, 4743360, 4743825, 4751514, 4751663, - 4751688, 4755383, 4755532, 4755557, 4758695, 4758844, 4758869, 4762463, 4762612, 4762637, 4766259, 4766408, - 4766433, 4767982, 4768447, 4768450, 4768453, 4768456, 4768459, 4768462, 4768465, 4768468, 4768471, 4768474, - 4768477, 4768480, 4768483, 4768486, 4768489, 4768492, 4768495, 4768498, 4768501, 4768504, 4768507, 4768510, - 4768513, 4768516, 4768519, 4768522, 4768525, 4768528, 4768531, 4768534, 4768537, 4768540, 4768543, 4768546, - 4768549, 4768552, 4768555, 4768558, 4768561, 4768564, 4768567, 4768570, 4768573, 4768576, 4768579, 4768582, - 4768585, 4768588, 4768591, 4768594, 4768597, 4768600, 4768603, 4768606, 4768609, 4768612, 4768615, 4768618, - 4768621, 4768624, 4768627, 4768630, 4768633, 4768636, 4768639, 4768642, 4768645, 4768648, 4768651, 4768654, - 4768657, 4768660, 4768663, 4768666, 4768669, 4768672, 4768675, 4768678, 4768681, 4768684, 4768687, 4768690, - 4768693, 4768696, 4768699, 4768702, 4768705, 4768708, 4768711, 4768714, 4768717, 4768720, 4768723, 4768726, - 4768729, 4768732, 4768735, 4768738, 4768741, 4768744, 4768747, 4768751, 4768755, 4768758, 4768761, 4768764, - 4768767, 4768770, 4768773, 4768776, 4768779, 4768782, 4768785, 4768788, 4768791, 4768794, 4768797, 4768800, - 4768803, 4768806, 4768809, 4768812, 4768815, 4768818, 4768821, 4768824, 4768827, 4768830, 4768833, 4768836, - 4768839, 4768842, 4768845, 4768848, 4768851, 4768854, 4768857, 4768860, 4768863, 4768866, 4768869, 4768872, - 4768875, 4768878, 4768881, 4768884, 4768887, 4768890, 4768893, 4768896, 4768899, 4768902, 4768905, 4768908, - 4768911, 4768914, 4768917, 4768920, 4768923, 4768926, 4768929, 4768932, 4768935, 4768938, 4768941, 4768944, - 4768947, 4768950, 4768953, 4768956, 4768959, 4768962, 4768965, 4768968, 4768971, 4768974, 4768977, 4768980, - 4768983, 4768986, 4768989, 4768992, 4768995, 4768998, 4769001, 4769004, 4769007, 4769010, 4769013, 4769016, - 4769019, 4769022, 4769025, 4769028, 4769031, 4769034, 4769037, 4769040, 4769043, 4769046, 4769049, 4769052, - 4769055, 4769520, 4770424, 4776834, 4777188, 4777553, 4777929, 4778316, 4778714, 4779123, 4779543, 4779974, - 4780416, 4780869, 4781333, 4781808, 4782294, 4782791, 4783299, 4783818, 4784348, 4784889, 4785441, 4786004, - 4786578, 4787163, 4787759, 4788366, 4788984, 4789613, 4790253, 4790904, 4791566, 4792239, 4792923, 4793618, - 4794324, 4795041, 4795769, 4796508, 4797258, 4798019, 4798791, 4799574, 4800368, 4801173, 4801989, 4802816, - 4803654, 4804503, 4805363, 4806234, 4807116, 4808009, 4808913, 4809828, 4810754, 4811691, 4812639, 4813598, - 4814568, 4815549, 4816541, 4817544, 4818558, 4819583, 4820619, 4823793, 4824873, 4903401, 4904449, 4905486, - 4906512, 4907527, 4908531, 4909524, 4910506, 4911477, 4912437, 4913386, 4914324, 4915251, 4916167, 4917072, - 4917966, 4918849, 4919721, 4920582, 4921432, 4922271, 4923099, 4923916, 4924722, 4925517, 4926301, 4927074, - 4927836, 4928587, 4929327, 4930056, 4930774, 4931481, 4932177, 4932862, 4933536, 4934199, 4934851, 4935492, - 4936122, 4936741, 4937349, 4937946, 4938532, 4939107, 4939671, 4940224, 4940766, 4941297, 4941817, 4942326, - 4942824, 4943311, 4943787, 4944252, 4944706, 4945149, 4945581, 4946002, 4946412, 4946811, 4947199, 4947576, - 4947942, 4948297, 4954610, 4955506, 4955974, 4955977, 4955980, 4955983, 4955986, 4955989, 4955992, 4955995, - 4955998, 4956001, 4956004, 4956007, 4956010, 4956013, 4956016, 4956019, 4956022, 4956025, 4956028, 4956031, - 4956034, 4956037, 4956040, 4956043, 4956046, 4956049, 4956052, 4956055, 4956058, 4956061, 4956064, 4956067, - 4956070, 4956073, 4956076, 4956079, 4956082, 4956085, 4956088, 4956091, 4956094, 4956097, 4956100, 4956103, - 4956106, 4956109, 4956112, 4956115, 4956118, 4956121, 4956124, 4956127, 4956130, 4956133, 4956136, 4956139, - 4956142, 4956145, 4956148, 4956151, 4956154, 4956157, 4956160, 4956163, 4956166, 4956169, 4956172, 4956175, - 4956178, 4956181, 4956184, 4956187, 4956190, 4956193, 4956196, 4956199, 4956202, 4956205, 4956208, 4956211, - 4956214, 4956217, 4956220, 4956223, 4956226, 4956229, 4956232, 4956235, 4956238, 4956241, 4956244, 4956247, - 4956250, 4956253, 4956256, 4956259, 4956262, 4956265, 4956270, 4956273, 4956276, 4956279, 4956282, 4956285, - 4956288, 4956291, 4956294, 4956297, 4956300, 4956303, 4956306, 4956309, 4956312, 4956315, 4956318, 4956321, - 4956324, 4956327, 4956330, 4956333, 4956336, 4956339, 4956342, 4956345, 4956348, 4956351, 4956354, 4956357, - 4956360, 4956363, 4956366, 4956369, 4956372, 4956375, 4956378, 4956381, 4956384, 4956387, 4956390, 4956393, - 4956396, 4956399, 4956402, 4956405, 4956408, 4956411, 4956414, 4956417, 4956420, 4956423, 4956426, 4956429, - 4956432, 4956435, 4956438, 4956441, 4956444, 4956447, 4956450, 4956453, 4956456, 4956459, 4956462, 4956465, - 4956468, 4956471, 4956474, 4956477, 4956480, 4956483, 4956486, 4956489, 4956492, 4956495, 4956498, 4956501, - 4956504, 4956507, 4956510, 4956513, 4956516, 4956519, 4956522, 4956525, 4956528, 4956531, 4956534, 4956537, - 4956540, 4956543, 4956546, 4956549, 4956552, 4956555, 4956558, 4956561, 4956564, 4957032, 4968295, 4968444, - 4968469, 4971512, 4971661, 4971686, 4975278, 4975427, 4975452, 4978588, 4978737, 4978762, 4981788, 4981937, - 4981962, 4983416, 4983884, 4983887, 4983890, 4983893, 4983896, 4983899, 4983902, 4983905, 4983908, 4983911, - 4983914, 4983917, 4983920, 4983923, 4983926, 4983929, 4983932, 4983935, 4983938, 4983941, 4983944, 4983947, - 4983950, 4983953, 4983956, 4983959, 4983962, 4983965, 4983968, 4983971, 4983974, 4983977, 4983980, 4983983, - 4983986, 4983989, 4983992, 4983995, 4983998, 4984001, 4984004, 4984007, 4984010, 4984013, 4984016, 4984019, - 4984022, 4984025, 4984028, 4984031, 4984034, 4984037, 4984040, 4984043, 4984046, 4984049, 4984052, 4984055, - 4984058, 4984061, 4984064, 4984067, 4984070, 4984073, 4984076, 4984079, 4984082, 4984085, 4984088, 4984091, - 4984094, 4984097, 4984100, 4984103, 4984106, 4984109, 4984112, 4984115, 4984118, 4984121, 4984124, 4984127, - 4984130, 4984133, 4984136, 4984139, 4984142, 4984145, 4984148, 4984151, 4984154, 4984157, 4984160, 4984163, - 4984166, 4984169, 4984172, 4984175, 4984179, 4984183, 4984186, 4984189, 4984192, 4984195, 4984198, 4984201, - 4984204, 4984207, 4984210, 4984213, 4984216, 4984219, 4984222, 4984225, 4984228, 4984231, 4984234, 4984237, - 4984240, 4984243, 4984246, 4984249, 4984252, 4984255, 4984258, 4984261, 4984264, 4984267, 4984270, 4984273, - 4984276, 4984279, 4984282, 4984285, 4984288, 4984291, 4984294, 4984297, 4984300, 4984303, 4984306, 4984309, - 4984312, 4984315, 4984318, 4984321, 4984324, 4984327, 4984330, 4984333, 4984336, 4984339, 4984342, 4984345, - 4984348, 4984351, 4984354, 4984357, 4984360, 4984363, 4984366, 4984369, 4984372, 4984375, 4984378, 4984381, - 4984384, 4984387, 4984390, 4984393, 4984396, 4984399, 4984402, 4984405, 4984408, 4984411, 4984414, 4984417, - 4984420, 4984423, 4984426, 4984429, 4984432, 4984435, 4984438, 4984441, 4984444, 4984447, 4984450, 4984453, - 4984456, 4984459, 4984462, 4984465, 4984468, 4984471, 4984474, 4984942, 4985839, 4992242, 4992596, 4992961, - 4993337, 4993724, 4994122, 4994531, 4994951, 4995382, 4995824, 4996277, 4996741, 4997216, 4997702, 4998199, - 4998707, 4999226, 4999756, 5000297, 5000849, 5001412, 5001986, 5002571, 5003167, 5003774, 5004392, 5005021, - 5005661, 5006312, 5006974, 5007647, 5008331, 5009026, 5009732, 5010449, 5011177, 5011916, 5012666, 5013427, - 5014199, 5014982, 5015776, 5016581, 5017397, 5018224, 5019062, 5019911, 5020771, 5021642, 5022524, 5023417, - 5024321, 5025236, 5026162, 5027099, 5028047, 5029006, 5029976, 5030957, 5031949, 5032952, 5033966, 5034991, - 5036027, 5037074, 5115262, 5116332, 5117391, 5118439, 5119476, 5120502, 5121517, 5122521, 5123514, 5124496, - 5125467, 5126427, 5127376, 5128314, 5129241, 5130157, 5131062, 5131956, 5132839, 5133711, 5134572, 5135422, - 5136261, 5137089, 5137906, 5138712, 5139507, 5140291, 5141064, 5141826, 5142577, 5143317, 5144046, 5144764, - 5145471, 5146167, 5146852, 5147526, 5148189, 5148841, 5149482, 5150112, 5150731, 5151339, 5151936, 5152522, - 5153097, 5153661, 5154214, 5154756, 5155287, 5155807, 5156316, 5156814, 5157301, 5157777, 5158242, 5158696, - 5159139, 5159571, 5159992, 5160402, 5160801, 5161189, 5161566, 5161932, 5162287, 5162631, 5168600, 5169496, - 5169952, 5169955, 5169958, 5169961, 5169964, 5169967, 5169970, 5169973, 5169976, 5169979, 5169982, 5169985, - 5169988, 5169991, 5169994, 5169997, 5170000, 5170003, 5170006, 5170009, 5170012, 5170015, 5170018, 5170021, - 5170024, 5170027, 5170030, 5170033, 5170036, 5170039, 5170042, 5170045, 5170048, 5170051, 5170054, 5170057, - 5170060, 5170063, 5170066, 5170069, 5170072, 5170075, 5170078, 5170081, 5170084, 5170087, 5170090, 5170093, - 5170096, 5170099, 5170102, 5170105, 5170108, 5170111, 5170114, 5170117, 5170120, 5170123, 5170126, 5170129, - 5170132, 5170135, 5170138, 5170141, 5170144, 5170147, 5170150, 5170153, 5170156, 5170159, 5170162, 5170165, - 5170168, 5170171, 5170174, 5170177, 5170180, 5170183, 5170186, 5170189, 5170192, 5170195, 5170198, 5170201, - 5170204, 5170207, 5170210, 5170213, 5170216, 5170219, 5170222, 5170225, 5170228, 5170231, 5170234, 5170237, - 5170240, 5170243, 5170246, 5170249, 5170252, 5170255, 5170260, 5170263, 5170266, 5170269, 5170272, 5170275, - 5170278, 5170281, 5170284, 5170287, 5170290, 5170293, 5170296, 5170299, 5170302, 5170305, 5170308, 5170311, - 5170314, 5170317, 5170320, 5170323, 5170326, 5170329, 5170332, 5170335, 5170338, 5170341, 5170344, 5170347, - 5170350, 5170353, 5170356, 5170359, 5170362, 5170365, 5170368, 5170371, 5170374, 5170377, 5170380, 5170383, - 5170386, 5170389, 5170392, 5170395, 5170398, 5170401, 5170404, 5170407, 5170410, 5170413, 5170416, 5170419, - 5170422, 5170425, 5170428, 5170431, 5170434, 5170437, 5170440, 5170443, 5170446, 5170449, 5170452, 5170455, - 5170458, 5170461, 5170464, 5170467, 5170470, 5170473, 5170476, 5170479, 5170482, 5170485, 5170488, 5170491, - 5170494, 5170497, 5170500, 5170503, 5170506, 5170509, 5170512, 5170515, 5170518, 5170521, 5170524, 5170527, - 5170530, 5170533, 5170536, 5170539, 5170542, 5170545, 5170548, 5170551, 5170554, 5170557, 5170560, 5170563, - 5170566, 5171022, 5177491, 5177640, 5177665, 5180710, 5180859, 5180884, 5184478, 5184627, 5184652, 5187786, - 5187935, 5187960, 5190978, 5191127, 5191152, 5248743, 5249199, 5249202, 5249205, 5249208, 5249211, 5249214, - 5249217, 5249220, 5249223, 5249226, 5249229, 5249232, 5249235, 5249238, 5249241, 5249244, 5249247, 5249250, - 5249253, 5249256, 5249259, 5249262, 5249265, 5249268, 5249271, 5249274, 5249277, 5249280, 5249283, 5249286, - 5249289, 5249292, 5249295, 5249298, 5249301, 5249304, 5249307, 5249310, 5249313, 5249316, 5249319, 5249322, - 5249325, 5249328, 5249331, 5249334, 5249337, 5249340, 5249343, 5249346, 5249349, 5249352, 5249355, 5249358, - 5249361, 5249364, 5249367, 5249370, 5249373, 5249376, 5249379, 5249382, 5249385, 5249388, 5249391, 5249394, - 5249397, 5249400, 5249403, 5249406, 5249409, 5249412, 5249415, 5249418, 5249421, 5249424, 5249427, 5249430, - 5249433, 5249436, 5249439, 5249442, 5249445, 5249448, 5249451, 5249454, 5249457, 5249460, 5249463, 5249466, - 5249469, 5249472, 5249475, 5249478, 5249481, 5249484, 5249487, 5249490, 5249493, 5249496, 5249499, 5249502, - 5249506, 5249510, 5249513, 5249516, 5249519, 5249522, 5249525, 5249528, 5249531, 5249534, 5249537, 5249540, - 5249543, 5249546, 5249549, 5249552, 5249555, 5249558, 5249561, 5249564, 5249567, 5249570, 5249573, 5249576, - 5249579, 5249582, 5249585, 5249588, 5249591, 5249594, 5249597, 5249600, 5249603, 5249606, 5249609, 5249612, - 5249615, 5249618, 5249621, 5249624, 5249627, 5249630, 5249633, 5249636, 5249639, 5249642, 5249645, 5249648, - 5249651, 5249654, 5249657, 5249660, 5249663, 5249666, 5249669, 5249672, 5249675, 5249678, 5249681, 5249684, - 5249687, 5249690, 5249693, 5249696, 5249699, 5249702, 5249705, 5249708, 5249711, 5249714, 5249717, 5249720, - 5249723, 5249726, 5249729, 5249732, 5249735, 5249738, 5249741, 5249744, 5249747, 5249750, 5249753, 5249756, - 5249759, 5249762, 5249765, 5249768, 5249771, 5249774, 5249777, 5249780, 5249783, 5249786, 5249789, 5249792, - 5249795, 5249798, 5249801, 5249804, 5249807, 5249810, 5249813, 5250269, 5251166, 5257226, 5257569, 5257923, - 5258288, 5258664, 5259051, 5259449, 5259858, 5260278, 5260709, 5261151, 5261604, 5262068, 5262543, 5263029, - 5263526, 5264034, 5264553, 5265083, 5265624, 5266176, 5266739, 5267313, 5267898, 5268494, 5269101, 5269719, - 5270348, 5270988, 5271639, 5272301, 5272974, 5273658, 5274353, 5275059, 5275776, 5276504, 5277243, 5277993, - 5278754, 5279526, 5280309, 5281103, 5281908, 5282724, 5283551, 5284389, 5285238, 5286098, 5286969, 5287851, - 5288744, 5289648, 5290563, 5291489, 5292426, 5293374, 5294333, 5295303, 5296284, 5297276, 5298279, 5299293, - 5300318, 5301354, 5302401, 5303459, 5304528, 5387616, 5399658, 5405862, 5417945, 5424124, 5436078, 5448133, - 5454040, 5454045, 5460099, 5460104, 5465975, 5483618, 5489417, 5495357, 5501101, 5512699, 5524038, 5529860, - 5541079, 5546829, 5563616, 5591078, 5596644, 5602020, 5628936, 5820958, 5847738, 5852104, 5878029, 5886597, - 5890779, 5894935, 5903341, 5907440, 5915717, 5919759, 5927949, 5931935, 5936065, 5940005, 5963379, 5967175, - 5978543, 5982409, 6032508, 6036064, 6039427, 6150531, 6278105, 6278155, 6278212, 6278278, 6278355, 6278433, - 6282659, 6283030, 6283056, 6283111, 6283176, 6283251, 6283334, 6283421, 6986362, 6999465, 7025091, 7037458, - 7049829, 7062401, 7112279, 7124716, 7175026, 7187550, 7212854, 7224359, 7224368, 7225452, 7238032, 7275029, - 7275038, 7276132, 7327313, 7365757, 7378545, 7430036, 7468920, 7482047, 7495003, 7507950, 7560340, 7586403, - 7612771, 7639177, 7652322, 7665574, 7692267, 7692272, 7705589, 7719139, 7799324, 7812795, 7812800, 7826283, - 7839967, 7853498, 7867037, 7880765, 7894328, 7907899, 7921666, 7948832, 7962638, 7976302, 8058603, 8072352, - 8086298, 8100091, 8113871, 8141675, 8169450, 8183304, 8211161, 8225053, 8238951, 8266932, 8350864, 8364881, - 8534359, 8548695, 8562871, 8577043, 8763526, 8777896, 8806844, 8821260, 8952115, 8981367, 9010503, 9025262, - 9054482, 9069291, 9098590, 9113435, 9128122, 9216893, 9231669, 9246636, 9276270, 9291281, 9336054, 9410865, - 9425994, 9471152, 9501214, 9516437, 9531501, 9735354, 9736673, -]; diff --git a/src/point_add/deep_strip_keys.rs b/src/point_add/deep_strip_keys.rs deleted file mode 100644 index 03ed03f3..00000000 --- a/src/point_add/deep_strip_keys.rs +++ /dev/null @@ -1,17284 +0,0 @@ -// AUTO-GENERATED by union max-coverage admission (census6/maxcov). -// Key = (kind, q_control2, q_control1, q_target, c_condition, ordinal, tuple_occupancy). -pub(crate) const DEAD_KEYS: &[(u8, u64, u64, u64, u64, u32, u32)] = &[ - (13, 54, 822, 1079, 18446744073709551615, 0, 1), - (13, 55, 823, 1080, 18446744073709551615, 0, 1), - (13, 56, 824, 1081, 18446744073709551615, 0, 1), - (13, 57, 825, 1082, 18446744073709551615, 0, 1), - (13, 58, 826, 1083, 18446744073709551615, 0, 2), - (13, 59, 827, 1084, 18446744073709551615, 0, 2), - (13, 60, 828, 1085, 18446744073709551615, 0, 3), - (13, 61, 829, 1086, 18446744073709551615, 0, 5), - (13, 62, 830, 1087, 18446744073709551615, 0, 6), - (13, 63, 831, 1088, 18446744073709551615, 0, 6), - (13, 64, 832, 1089, 18446744073709551615, 0, 6), - (13, 65, 833, 1090, 18446744073709551615, 0, 6), - (13, 66, 834, 1091, 18446744073709551615, 0, 7), - (13, 67, 835, 1092, 18446744073709551615, 0, 6), - (13, 68, 836, 1093, 18446744073709551615, 0, 7), - (13, 69, 837, 1094, 18446744073709551615, 0, 8), - (13, 70, 838, 1095, 18446744073709551615, 0, 12), - (13, 71, 839, 1096, 18446744073709551615, 0, 12), - (13, 72, 840, 1097, 18446744073709551615, 0, 12), - (13, 73, 841, 1098, 18446744073709551615, 0, 8), - (13, 74, 842, 1099, 18446744073709551615, 0, 9), - (13, 75, 843, 1100, 18446744073709551615, 0, 9), - (13, 76, 844, 1101, 18446744073709551615, 0, 9), - (13, 77, 845, 1102, 18446744073709551615, 0, 9), - (13, 78, 846, 1103, 18446744073709551615, 0, 9), - (13, 79, 847, 1104, 18446744073709551615, 0, 10), - (13, 80, 848, 1105, 18446744073709551615, 0, 11), - (13, 81, 849, 1106, 18446744073709551615, 0, 11), - (13, 82, 850, 1107, 18446744073709551615, 0, 11), - (13, 83, 851, 1108, 18446744073709551615, 0, 11), - (13, 84, 852, 1109, 18446744073709551615, 0, 11), - (13, 85, 853, 1110, 18446744073709551615, 0, 11), - (13, 86, 854, 1111, 18446744073709551615, 0, 11), - (13, 87, 855, 1112, 18446744073709551615, 0, 11), - (13, 88, 856, 1113, 18446744073709551615, 0, 11), - (13, 89, 857, 1114, 18446744073709551615, 0, 11), - (13, 90, 858, 1115, 18446744073709551615, 0, 11), - (13, 91, 859, 1116, 18446744073709551615, 0, 11), - (13, 92, 860, 1117, 18446744073709551615, 0, 11), - (13, 93, 861, 1118, 18446744073709551615, 0, 11), - (13, 94, 862, 1119, 18446744073709551615, 0, 10), - (13, 95, 863, 1120, 18446744073709551615, 0, 9), - (13, 96, 864, 1121, 18446744073709551615, 0, 9), - (13, 97, 865, 1122, 18446744073709551615, 0, 9), - (13, 98, 866, 1123, 18446744073709551615, 0, 9), - (13, 99, 867, 1124, 18446744073709551615, 0, 9), - (13, 100, 868, 1125, 18446744073709551615, 0, 9), - (13, 101, 869, 1126, 18446744073709551615, 0, 9), - (13, 102, 870, 1127, 18446744073709551615, 0, 9), - (13, 103, 871, 1128, 18446744073709551615, 0, 9), - (13, 104, 872, 1129, 18446744073709551615, 0, 9), - (13, 105, 873, 1130, 18446744073709551615, 0, 9), - (13, 106, 874, 1131, 18446744073709551615, 0, 9), - (13, 107, 875, 1132, 18446744073709551615, 0, 9), - (13, 108, 876, 1133, 18446744073709551615, 0, 9), - (13, 109, 877, 1134, 18446744073709551615, 0, 9), - (13, 110, 878, 1135, 18446744073709551615, 0, 9), - (13, 111, 879, 1136, 18446744073709551615, 0, 9), - (13, 112, 880, 1137, 18446744073709551615, 0, 9), - (13, 113, 881, 1138, 18446744073709551615, 0, 8), - (13, 114, 882, 1139, 18446744073709551615, 0, 7), - (13, 115, 883, 1140, 18446744073709551615, 0, 7), - (13, 116, 884, 1141, 18446744073709551615, 0, 7), - (13, 117, 885, 1142, 18446744073709551615, 0, 7), - (13, 118, 886, 1143, 18446744073709551615, 0, 7), - (13, 119, 887, 1144, 18446744073709551615, 0, 7), - (13, 120, 888, 1145, 18446744073709551615, 0, 7), - (13, 121, 889, 1146, 18446744073709551615, 0, 7), - (13, 122, 890, 1147, 18446744073709551615, 0, 7), - (13, 123, 891, 1148, 18446744073709551615, 0, 7), - (13, 124, 892, 1149, 18446744073709551615, 0, 7), - (13, 125, 893, 1150, 18446744073709551615, 0, 6), - (13, 1024, 1150, 0, 18446744073709551615, 0, 195), - (13, 145, 913, 1046, 18446744073709551615, 0, 1), - (13, 146, 914, 1047, 18446744073709551615, 0, 1), - (13, 147, 915, 1048, 18446744073709551615, 0, 1), - (13, 148, 916, 1049, 18446744073709551615, 0, 1), - (13, 149, 917, 1050, 18446744073709551615, 0, 1), - (13, 150, 918, 1051, 18446744073709551615, 0, 1), - (13, 151, 919, 1052, 18446744073709551615, 0, 1), - (13, 152, 920, 1053, 18446744073709551615, 0, 1), - (13, 153, 921, 1054, 18446744073709551615, 0, 1), - (13, 154, 922, 1055, 18446744073709551615, 0, 1), - (13, 155, 923, 1056, 18446744073709551615, 0, 1), - (13, 156, 924, 1057, 18446744073709551615, 0, 1), - (13, 157, 925, 1058, 18446744073709551615, 0, 1), - (13, 158, 926, 1059, 18446744073709551615, 0, 1), - (13, 159, 927, 1060, 18446744073709551615, 0, 1), - (13, 160, 928, 1061, 18446744073709551615, 0, 1), - (13, 161, 929, 1062, 18446744073709551615, 0, 1), - (13, 162, 930, 1063, 18446744073709551615, 0, 1), - (13, 163, 931, 1064, 18446744073709551615, 0, 1), - (13, 164, 932, 1065, 18446744073709551615, 0, 3), - (13, 165, 933, 1066, 18446744073709551615, 0, 2), - (13, 166, 934, 1067, 18446744073709551615, 0, 1), - (13, 167, 935, 1068, 18446744073709551615, 0, 1), - (13, 168, 936, 1069, 18446744073709551615, 0, 1), - (13, 169, 937, 1070, 18446744073709551615, 0, 1), - (13, 170, 938, 1071, 18446744073709551615, 0, 2), - (13, 171, 939, 1072, 18446744073709551615, 0, 3), - (13, 172, 940, 1073, 18446744073709551615, 0, 3), - (13, 173, 941, 1074, 18446744073709551615, 0, 4), - (13, 174, 942, 1075, 18446744073709551615, 0, 5), - (13, 175, 943, 1076, 18446744073709551615, 0, 5), - (13, 176, 944, 1077, 18446744073709551615, 0, 4), - (13, 177, 945, 1078, 18446744073709551615, 0, 4), - (13, 178, 946, 1079, 18446744073709551615, 0, 4), - (13, 179, 947, 1080, 18446744073709551615, 0, 4), - (13, 180, 948, 1081, 18446744073709551615, 0, 4), - (13, 181, 949, 1082, 18446744073709551615, 0, 4), - (13, 182, 950, 1083, 18446744073709551615, 0, 4), - (13, 183, 951, 1084, 18446744073709551615, 0, 4), - (13, 184, 952, 1085, 18446744073709551615, 0, 4), - (13, 185, 953, 1086, 18446744073709551615, 0, 4), - (13, 186, 954, 1087, 18446744073709551615, 0, 4), - (13, 187, 955, 1088, 18446744073709551615, 0, 4), - (13, 188, 956, 1089, 18446744073709551615, 0, 4), - (13, 189, 957, 1090, 18446744073709551615, 0, 4), - (13, 190, 958, 1091, 18446744073709551615, 0, 4), - (13, 191, 959, 1092, 18446744073709551615, 0, 4), - (13, 192, 960, 1093, 18446744073709551615, 0, 4), - (13, 193, 961, 1094, 18446744073709551615, 0, 4), - (13, 194, 962, 1095, 18446744073709551615, 0, 4), - (13, 195, 963, 1096, 18446744073709551615, 0, 4), - (13, 196, 964, 1097, 18446744073709551615, 0, 4), - (13, 197, 965, 1098, 18446744073709551615, 0, 4), - (13, 198, 966, 1099, 18446744073709551615, 0, 4), - (13, 199, 967, 1100, 18446744073709551615, 0, 4), - (13, 200, 968, 1101, 18446744073709551615, 0, 4), - (13, 201, 969, 1102, 18446744073709551615, 0, 4), - (13, 202, 970, 1103, 18446744073709551615, 0, 3), - (13, 203, 971, 1104, 18446744073709551615, 0, 3), - (13, 204, 972, 1105, 18446744073709551615, 0, 2), - (13, 205, 973, 1106, 18446744073709551615, 0, 2), - (13, 206, 974, 1107, 18446744073709551615, 0, 1), - (13, 207, 975, 1108, 18446744073709551615, 0, 1), - (13, 208, 976, 1109, 18446744073709551615, 0, 1), - (13, 209, 977, 1110, 18446744073709551615, 0, 1), - (13, 210, 978, 1111, 18446744073709551615, 0, 1), - (13, 211, 979, 1112, 18446744073709551615, 0, 1), - (13, 212, 980, 1113, 18446744073709551615, 0, 1), - (13, 213, 981, 1114, 18446744073709551615, 0, 1), - (13, 214, 982, 1115, 18446744073709551615, 0, 1), - (13, 215, 983, 1116, 18446744073709551615, 0, 1), - (13, 216, 984, 1117, 18446744073709551615, 0, 1), - (13, 217, 985, 1118, 18446744073709551615, 0, 1), - (13, 218, 986, 1119, 18446744073709551615, 0, 1), - (13, 219, 987, 1120, 18446744073709551615, 0, 1), - (13, 220, 988, 1121, 18446744073709551615, 0, 1), - (13, 221, 989, 1122, 18446744073709551615, 0, 1), - (13, 222, 990, 1123, 18446744073709551615, 0, 1), - (13, 223, 991, 1124, 18446744073709551615, 0, 1), - (13, 224, 992, 1125, 18446744073709551615, 0, 1), - (13, 225, 993, 1126, 18446744073709551615, 0, 1), - (13, 226, 994, 1127, 18446744073709551615, 0, 1), - (13, 227, 995, 1128, 18446744073709551615, 0, 1), - (13, 228, 996, 1129, 18446744073709551615, 0, 1), - (13, 229, 997, 1130, 18446744073709551615, 0, 1), - (13, 230, 998, 1131, 18446744073709551615, 0, 1), - (13, 231, 999, 1132, 18446744073709551615, 0, 1), - (13, 232, 1000, 1133, 18446744073709551615, 0, 1), - (13, 233, 1001, 1134, 18446744073709551615, 0, 1), - (13, 234, 1002, 1135, 18446744073709551615, 0, 1), - (13, 235, 1003, 1136, 18446744073709551615, 0, 1), - (13, 236, 1004, 1137, 18446744073709551615, 0, 1), - (13, 237, 1005, 1138, 18446744073709551615, 0, 1), - (13, 238, 1006, 1139, 18446744073709551615, 0, 1), - (13, 239, 1007, 1140, 18446744073709551615, 0, 1), - (13, 240, 1008, 1141, 18446744073709551615, 0, 1), - (13, 241, 1009, 1142, 18446744073709551615, 0, 1), - (13, 242, 1010, 1143, 18446744073709551615, 0, 1), - (13, 243, 1011, 1144, 18446744073709551615, 0, 1), - (13, 244, 1012, 1145, 18446744073709551615, 0, 1), - (13, 245, 1013, 1146, 18446744073709551615, 0, 1), - (13, 246, 1014, 1147, 18446744073709551615, 0, 1), - (13, 247, 1015, 1148, 18446744073709551615, 0, 1), - (13, 248, 1016, 1149, 18446744073709551615, 0, 1), - (13, 249, 1017, 1150, 18446744073709551615, 0, 1), - (13, 1024, 1150, 768, 18446744073709551615, 0, 145), - (13, 255, 1023, 1033, 18446744073709551615, 0, 1), - (13, 1024, 1033, 1027, 18446744073709551615, 0, 1), - (13, 254, 1022, 1032, 18446744073709551615, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 0, 11), - (13, 248, 1016, 1046, 18446744073709551615, 0, 1), - (14, 1024, 249, 1017, 18446744073709551615, 0, 2), - (13, 124, 892, 1045, 18446744073709551615, 0, 1), - (14, 1024, 125, 893, 18446744073709551615, 0, 7), - (13, 0, 512, 768, 18446744073709551615, 0, 3), - (13, 513, 768, 1027, 18446744073709551615, 0, 3), - (13, 514, 1027, 1028, 18446744073709551615, 0, 3), - (13, 515, 1028, 1029, 18446744073709551615, 0, 3), - (13, 542, 1055, 1056, 18446744073709551615, 0, 3), - (13, 543, 1056, 1057, 18446744073709551615, 0, 3), - (13, 0, 512, 768, 18446744073709551615, 1, 3), - (13, 513, 768, 1027, 18446744073709551615, 1, 3), - (13, 514, 1027, 1028, 18446744073709551615, 1, 3), - (13, 515, 1028, 1029, 18446744073709551615, 1, 3), - (13, 542, 1055, 1056, 18446744073709551615, 1, 3), - (13, 543, 1056, 1057, 18446744073709551615, 1, 3), - (13, 534, 278, 1049, 18446744073709551615, 0, 1), - (13, 535, 279, 1050, 18446744073709551615, 0, 1), - (13, 536, 280, 1051, 18446744073709551615, 0, 1), - (13, 537, 281, 1052, 18446744073709551615, 0, 1), - (13, 538, 282, 1053, 18446744073709551615, 0, 1), - (13, 539, 283, 1054, 18446744073709551615, 0, 1), - (13, 540, 284, 1055, 18446744073709551615, 0, 1), - (13, 541, 285, 1056, 18446744073709551615, 0, 1), - (13, 542, 286, 1057, 18446744073709551615, 0, 1), - (13, 543, 287, 1058, 18446744073709551615, 0, 1), - (13, 544, 288, 1059, 18446744073709551615, 0, 1), - (13, 545, 289, 1060, 18446744073709551615, 0, 1), - (13, 546, 290, 1061, 18446744073709551615, 0, 1), - (13, 547, 291, 1062, 18446744073709551615, 0, 1), - (13, 548, 292, 1063, 18446744073709551615, 0, 1), - (13, 549, 293, 1064, 18446744073709551615, 0, 1), - (13, 550, 294, 1065, 18446744073709551615, 0, 1), - (13, 551, 295, 1066, 18446744073709551615, 0, 1), - (13, 552, 296, 1067, 18446744073709551615, 0, 1), - (13, 553, 297, 1068, 18446744073709551615, 0, 1), - (13, 554, 298, 1069, 18446744073709551615, 0, 1), - (13, 555, 299, 1070, 18446744073709551615, 0, 1), - (13, 556, 300, 1071, 18446744073709551615, 0, 1), - (13, 557, 301, 1072, 18446744073709551615, 0, 1), - (13, 558, 302, 1073, 18446744073709551615, 0, 1), - (13, 559, 303, 1074, 18446744073709551615, 0, 1), - (13, 560, 304, 1075, 18446744073709551615, 0, 1), - (13, 561, 305, 1076, 18446744073709551615, 0, 1), - (13, 562, 306, 1077, 18446744073709551615, 0, 1), - (13, 563, 307, 1078, 18446744073709551615, 0, 1), - (13, 564, 308, 1079, 18446744073709551615, 0, 1), - (13, 565, 309, 1080, 18446744073709551615, 0, 1), - (13, 566, 310, 1081, 18446744073709551615, 0, 1), - (13, 567, 311, 1082, 18446744073709551615, 0, 1), - (13, 568, 312, 1083, 18446744073709551615, 0, 1), - (13, 569, 313, 1084, 18446744073709551615, 0, 1), - (13, 570, 314, 1085, 18446744073709551615, 0, 1), - (13, 571, 315, 1086, 18446744073709551615, 0, 1), - (13, 572, 316, 1087, 18446744073709551615, 0, 1), - (13, 573, 317, 1088, 18446744073709551615, 0, 1), - (13, 574, 318, 1089, 18446744073709551615, 0, 1), - (13, 575, 319, 1090, 18446744073709551615, 0, 1), - (13, 576, 320, 1091, 18446744073709551615, 0, 2), - (13, 577, 321, 1028, 18446744073709551615, 0, 2), - (13, 578, 322, 1029, 18446744073709551615, 0, 2), - (13, 579, 323, 1030, 18446744073709551615, 0, 2), - (13, 580, 324, 1031, 18446744073709551615, 0, 2), - (13, 581, 325, 1032, 18446744073709551615, 0, 2), - (13, 582, 326, 1033, 18446744073709551615, 0, 4), - (13, 583, 327, 1034, 18446744073709551615, 0, 2), - (13, 584, 328, 1035, 18446744073709551615, 0, 4), - (13, 585, 329, 1036, 18446744073709551615, 0, 2), - (13, 586, 330, 1037, 18446744073709551615, 0, 2), - (13, 587, 331, 1038, 18446744073709551615, 0, 2), - (13, 588, 332, 1039, 18446744073709551615, 0, 2), - (13, 589, 333, 1040, 18446744073709551615, 0, 2), - (13, 590, 334, 1041, 18446744073709551615, 0, 2), - (13, 591, 335, 1042, 18446744073709551615, 0, 2), - (13, 592, 336, 1043, 18446744073709551615, 0, 2), - (13, 593, 337, 1044, 18446744073709551615, 0, 2), - (13, 594, 338, 1045, 18446744073709551615, 0, 2), - (13, 595, 339, 1046, 18446744073709551615, 0, 2), - (13, 596, 340, 1047, 18446744073709551615, 0, 2), - (13, 597, 341, 1048, 18446744073709551615, 0, 2), - (13, 598, 342, 1049, 18446744073709551615, 0, 2), - (13, 599, 343, 1050, 18446744073709551615, 0, 2), - (13, 600, 344, 1051, 18446744073709551615, 0, 2), - (13, 601, 345, 1052, 18446744073709551615, 0, 2), - (13, 602, 346, 1053, 18446744073709551615, 0, 2), - (13, 603, 347, 1054, 18446744073709551615, 0, 2), - (13, 604, 348, 1055, 18446744073709551615, 0, 2), - (13, 605, 349, 1056, 18446744073709551615, 0, 2), - (13, 606, 350, 1057, 18446744073709551615, 0, 2), - (13, 607, 351, 1058, 18446744073709551615, 0, 2), - (13, 608, 352, 1059, 18446744073709551615, 0, 2), - (13, 609, 353, 1060, 18446744073709551615, 0, 2), - (13, 610, 354, 1061, 18446744073709551615, 0, 2), - (13, 611, 355, 1062, 18446744073709551615, 0, 2), - (13, 612, 356, 1063, 18446744073709551615, 0, 2), - (13, 613, 357, 1064, 18446744073709551615, 0, 2), - (13, 614, 358, 1065, 18446744073709551615, 0, 2), - (13, 615, 359, 1066, 18446744073709551615, 0, 2), - (13, 616, 360, 1067, 18446744073709551615, 0, 2), - (13, 617, 361, 1068, 18446744073709551615, 0, 2), - (13, 618, 362, 1069, 18446744073709551615, 0, 2), - (13, 619, 363, 1070, 18446744073709551615, 0, 2), - (13, 620, 364, 1071, 18446744073709551615, 0, 2), - (13, 621, 365, 1072, 18446744073709551615, 0, 2), - (13, 622, 366, 1073, 18446744073709551615, 0, 2), - (13, 623, 367, 1074, 18446744073709551615, 0, 2), - (13, 624, 368, 1075, 18446744073709551615, 0, 2), - (13, 625, 369, 1076, 18446744073709551615, 0, 2), - (13, 626, 370, 1077, 18446744073709551615, 0, 2), - (13, 627, 371, 1078, 18446744073709551615, 0, 2), - (13, 628, 372, 1079, 18446744073709551615, 0, 2), - (13, 629, 373, 1080, 18446744073709551615, 0, 2), - (13, 630, 374, 1081, 18446744073709551615, 0, 2), - (13, 631, 375, 1082, 18446744073709551615, 0, 2), - (13, 632, 376, 1083, 18446744073709551615, 0, 2), - (13, 633, 377, 1084, 18446744073709551615, 0, 2), - (13, 634, 378, 1085, 18446744073709551615, 0, 2), - (13, 635, 379, 1086, 18446744073709551615, 0, 2), - (13, 636, 380, 1087, 18446744073709551615, 0, 2), - (13, 637, 381, 1088, 18446744073709551615, 0, 2), - (13, 638, 382, 1089, 18446744073709551615, 0, 2), - (13, 639, 383, 1090, 18446744073709551615, 0, 2), - (13, 640, 384, 1091, 18446744073709551615, 0, 2), - (13, 641, 385, 1092, 18446744073709551615, 0, 1), - (13, 642, 386, 1028, 18446744073709551615, 0, 1), - (13, 643, 387, 1029, 18446744073709551615, 0, 1), - (13, 644, 388, 1030, 18446744073709551615, 0, 1), - (13, 645, 389, 1031, 18446744073709551615, 0, 1), - (13, 646, 390, 1032, 18446744073709551615, 0, 1), - (13, 647, 391, 1033, 18446744073709551615, 0, 2), - (13, 648, 392, 1034, 18446744073709551615, 0, 2), - (13, 649, 393, 1035, 18446744073709551615, 0, 2), - (13, 650, 394, 1036, 18446744073709551615, 0, 3), - (13, 651, 395, 1037, 18446744073709551615, 0, 3), - (13, 652, 396, 1038, 18446744073709551615, 0, 3), - (13, 653, 397, 1039, 18446744073709551615, 0, 4), - (13, 654, 398, 1040, 18446744073709551615, 0, 5), - (13, 655, 399, 1041, 18446744073709551615, 0, 5), - (13, 656, 400, 1042, 18446744073709551615, 0, 5), - (13, 657, 401, 1043, 18446744073709551615, 0, 6), - (13, 658, 402, 1044, 18446744073709551615, 0, 6), - (13, 659, 403, 1045, 18446744073709551615, 0, 6), - (13, 660, 404, 1046, 18446744073709551615, 0, 7), - (13, 661, 405, 1047, 18446744073709551615, 0, 8), - (13, 662, 406, 1048, 18446744073709551615, 0, 8), - (13, 663, 407, 1049, 18446744073709551615, 0, 8), - (13, 664, 408, 1050, 18446744073709551615, 0, 9), - (13, 665, 409, 1051, 18446744073709551615, 0, 9), - (13, 666, 410, 1052, 18446744073709551615, 0, 9), - (13, 667, 411, 1053, 18446744073709551615, 0, 10), - (13, 668, 412, 1054, 18446744073709551615, 0, 11), - (13, 669, 413, 1055, 18446744073709551615, 0, 12), - (13, 670, 414, 1056, 18446744073709551615, 0, 13), - (13, 671, 415, 1057, 18446744073709551615, 0, 16), - (13, 672, 416, 1058, 18446744073709551615, 0, 19), - (13, 673, 417, 1059, 18446744073709551615, 0, 22), - (13, 674, 418, 1060, 18446744073709551615, 0, 25), - (13, 675, 419, 1061, 18446744073709551615, 0, 28), - (13, 676, 420, 1062, 18446744073709551615, 0, 31), - (13, 677, 421, 1063, 18446744073709551615, 0, 34), - (13, 678, 422, 1064, 18446744073709551615, 0, 37), - (13, 679, 423, 1065, 18446744073709551615, 0, 40), - (13, 680, 424, 1066, 18446744073709551615, 0, 43), - (13, 681, 425, 1067, 18446744073709551615, 0, 46), - (13, 682, 426, 1068, 18446744073709551615, 0, 49), - (13, 683, 427, 1069, 18446744073709551615, 0, 52), - (13, 684, 428, 1070, 18446744073709551615, 0, 55), - (13, 685, 429, 1071, 18446744073709551615, 0, 58), - (13, 686, 430, 1072, 18446744073709551615, 0, 61), - (13, 687, 431, 1073, 18446744073709551615, 0, 64), - (13, 688, 432, 1074, 18446744073709551615, 0, 67), - (13, 689, 433, 1075, 18446744073709551615, 0, 70), - (13, 690, 434, 1076, 18446744073709551615, 0, 73), - (13, 691, 435, 1077, 18446744073709551615, 0, 76), - (13, 692, 436, 1078, 18446744073709551615, 0, 79), - (13, 693, 437, 1079, 18446744073709551615, 0, 82), - (13, 694, 438, 1080, 18446744073709551615, 0, 85), - (13, 695, 439, 1081, 18446744073709551615, 0, 88), - (13, 696, 440, 1082, 18446744073709551615, 0, 91), - (13, 697, 441, 1083, 18446744073709551615, 0, 94), - (13, 698, 442, 1084, 18446744073709551615, 0, 95), - (13, 699, 443, 1085, 18446744073709551615, 0, 100), - (13, 700, 444, 1086, 18446744073709551615, 0, 109), - (13, 701, 445, 1087, 18446744073709551615, 0, 112), - (13, 702, 446, 1088, 18446744073709551615, 0, 115), - (13, 703, 447, 1089, 18446744073709551615, 0, 122), - (13, 704, 448, 1090, 18446744073709551615, 0, 123), - (13, 705, 449, 1091, 18446744073709551615, 0, 124), - (13, 706, 450, 1092, 18446744073709551615, 0, 127), - (13, 707, 451, 1093, 18446744073709551615, 0, 130), - (13, 708, 452, 1094, 18446744073709551615, 0, 133), - (13, 709, 453, 1095, 18446744073709551615, 0, 141), - (13, 710, 454, 1096, 18446744073709551615, 0, 141), - (13, 711, 455, 1097, 18446744073709551615, 0, 142), - (13, 712, 456, 1098, 18446744073709551615, 0, 151), - (13, 713, 457, 1099, 18446744073709551615, 0, 154), - (13, 714, 458, 1100, 18446744073709551615, 0, 157), - (13, 715, 459, 1101, 18446744073709551615, 0, 160), - (13, 716, 460, 1102, 18446744073709551615, 0, 163), - (13, 717, 461, 1103, 18446744073709551615, 0, 166), - (13, 718, 462, 1104, 18446744073709551615, 0, 169), - (13, 719, 463, 1105, 18446744073709551615, 0, 172), - (13, 720, 464, 1106, 18446744073709551615, 0, 175), - (13, 721, 465, 1107, 18446744073709551615, 0, 178), - (13, 722, 466, 1108, 18446744073709551615, 0, 181), - (13, 723, 467, 1109, 18446744073709551615, 0, 184), - (13, 724, 468, 1110, 18446744073709551615, 0, 187), - (13, 725, 469, 1111, 18446744073709551615, 0, 190), - (13, 726, 470, 1112, 18446744073709551615, 0, 192), - (13, 727, 471, 1113, 18446744073709551615, 0, 195), - (13, 728, 472, 1114, 18446744073709551615, 0, 195), - (13, 729, 473, 1115, 18446744073709551615, 0, 195), - (13, 730, 474, 1116, 18446744073709551615, 0, 199), - (13, 731, 475, 1117, 18446744073709551615, 0, 195), - (13, 732, 476, 1118, 18446744073709551615, 0, 196), - (13, 733, 477, 1119, 18446744073709551615, 0, 195), - (13, 734, 478, 1120, 18446744073709551615, 0, 196), - (13, 735, 479, 1121, 18446744073709551615, 0, 197), - (13, 736, 480, 1122, 18446744073709551615, 0, 200), - (13, 737, 481, 1123, 18446744073709551615, 0, 203), - (13, 738, 482, 1124, 18446744073709551615, 0, 206), - (13, 739, 483, 1125, 18446744073709551615, 0, 209), - (13, 740, 484, 1126, 18446744073709551615, 0, 212), - (13, 741, 485, 1127, 18446744073709551615, 0, 215), - (13, 742, 486, 1128, 18446744073709551615, 0, 218), - (13, 743, 487, 1129, 18446744073709551615, 0, 221), - (13, 744, 488, 1130, 18446744073709551615, 0, 224), - (13, 745, 489, 1131, 18446744073709551615, 0, 226), - (13, 746, 490, 1132, 18446744073709551615, 0, 232), - (13, 747, 491, 1133, 18446744073709551615, 0, 232), - (13, 748, 492, 1134, 18446744073709551615, 0, 241), - (13, 749, 493, 1135, 18446744073709551615, 0, 237), - (13, 750, 494, 1136, 18446744073709551615, 0, 247), - (13, 751, 495, 1137, 18446744073709551615, 0, 246), - (13, 752, 496, 1138, 18446744073709551615, 0, 246), - (13, 753, 497, 1139, 18446744073709551615, 0, 246), - (13, 754, 498, 1140, 18446744073709551615, 0, 247), - (13, 755, 499, 1141, 18446744073709551615, 0, 246), - (13, 756, 500, 1142, 18446744073709551615, 0, 247), - (13, 757, 501, 1143, 18446744073709551615, 0, 246), - (13, 758, 502, 1144, 18446744073709551615, 0, 246), - (13, 759, 503, 1145, 18446744073709551615, 0, 247), - (13, 760, 504, 1146, 18446744073709551615, 0, 247), - (13, 761, 505, 1147, 18446744073709551615, 0, 249), - (13, 762, 506, 1148, 18446744073709551615, 0, 249), - (13, 763, 507, 1149, 18446744073709551615, 0, 249), - (13, 764, 508, 1150, 18446744073709551615, 0, 247), - (13, 765, 509, 1151, 18446744073709551615, 0, 189), - (13, 766, 510, 1152, 18446744073709551615, 0, 189), - (13, 767, 511, 1153, 18446744073709551615, 0, 249), - (13, 577, 321, 1028, 18446744073709551615, 1, 2), - (13, 578, 322, 1029, 18446744073709551615, 1, 2), - (13, 579, 323, 1030, 18446744073709551615, 1, 2), - (13, 580, 324, 1031, 18446744073709551615, 1, 2), - (13, 581, 325, 1032, 18446744073709551615, 1, 2), - (13, 582, 326, 1033, 18446744073709551615, 1, 4), - (13, 583, 327, 1034, 18446744073709551615, 1, 2), - (13, 584, 328, 1035, 18446744073709551615, 1, 4), - (13, 585, 329, 1036, 18446744073709551615, 1, 2), - (13, 586, 330, 1037, 18446744073709551615, 1, 2), - (13, 587, 331, 1038, 18446744073709551615, 1, 2), - (13, 588, 332, 1039, 18446744073709551615, 1, 2), - (13, 589, 333, 1040, 18446744073709551615, 1, 2), - (13, 590, 334, 1041, 18446744073709551615, 1, 2), - (13, 591, 335, 1042, 18446744073709551615, 1, 2), - (13, 592, 336, 1043, 18446744073709551615, 1, 2), - (13, 593, 337, 1044, 18446744073709551615, 1, 2), - (13, 594, 338, 1045, 18446744073709551615, 1, 2), - (13, 595, 339, 1046, 18446744073709551615, 1, 2), - (13, 596, 340, 1047, 18446744073709551615, 1, 2), - (13, 597, 341, 1048, 18446744073709551615, 1, 2), - (13, 598, 342, 1049, 18446744073709551615, 1, 2), - (13, 599, 343, 1050, 18446744073709551615, 1, 2), - (13, 600, 344, 1051, 18446744073709551615, 1, 2), - (13, 601, 345, 1052, 18446744073709551615, 1, 2), - (13, 602, 346, 1053, 18446744073709551615, 1, 2), - (13, 603, 347, 1054, 18446744073709551615, 1, 2), - (13, 604, 348, 1055, 18446744073709551615, 1, 2), - (13, 605, 349, 1056, 18446744073709551615, 1, 2), - (13, 606, 350, 1057, 18446744073709551615, 1, 2), - (13, 607, 351, 1058, 18446744073709551615, 1, 2), - (13, 608, 352, 1059, 18446744073709551615, 1, 2), - (13, 609, 353, 1060, 18446744073709551615, 1, 2), - (13, 610, 354, 1061, 18446744073709551615, 1, 2), - (13, 611, 355, 1062, 18446744073709551615, 1, 2), - (13, 612, 356, 1063, 18446744073709551615, 1, 2), - (13, 613, 357, 1064, 18446744073709551615, 1, 2), - (13, 614, 358, 1065, 18446744073709551615, 1, 2), - (13, 615, 359, 1066, 18446744073709551615, 1, 2), - (13, 616, 360, 1067, 18446744073709551615, 1, 2), - (13, 617, 361, 1068, 18446744073709551615, 1, 2), - (13, 618, 362, 1069, 18446744073709551615, 1, 2), - (13, 619, 363, 1070, 18446744073709551615, 1, 2), - (13, 620, 364, 1071, 18446744073709551615, 1, 2), - (13, 621, 365, 1072, 18446744073709551615, 1, 2), - (13, 622, 366, 1073, 18446744073709551615, 1, 2), - (13, 623, 367, 1074, 18446744073709551615, 1, 2), - (13, 624, 368, 1075, 18446744073709551615, 1, 2), - (13, 625, 369, 1076, 18446744073709551615, 1, 2), - (13, 626, 370, 1077, 18446744073709551615, 1, 2), - (13, 627, 371, 1078, 18446744073709551615, 1, 2), - (13, 628, 372, 1079, 18446744073709551615, 1, 2), - (13, 629, 373, 1080, 18446744073709551615, 1, 2), - (13, 630, 374, 1081, 18446744073709551615, 1, 2), - (13, 631, 375, 1082, 18446744073709551615, 1, 2), - (13, 632, 376, 1083, 18446744073709551615, 1, 2), - (13, 633, 377, 1084, 18446744073709551615, 1, 2), - (13, 634, 378, 1085, 18446744073709551615, 1, 2), - (13, 635, 379, 1086, 18446744073709551615, 1, 2), - (13, 636, 380, 1087, 18446744073709551615, 1, 2), - (13, 637, 381, 1088, 18446744073709551615, 1, 2), - (13, 638, 382, 1089, 18446744073709551615, 1, 2), - (13, 639, 383, 1090, 18446744073709551615, 1, 2), - (13, 640, 384, 1091, 18446744073709551615, 1, 2), - (14, 1024, 641, 385, 18446744073709551615, 0, 13), - (13, 533, 277, 1049, 18446744073709551615, 0, 1), - (13, 534, 278, 1050, 18446744073709551615, 0, 1), - (13, 535, 279, 1051, 18446744073709551615, 0, 1), - (13, 536, 280, 1052, 18446744073709551615, 0, 1), - (13, 537, 281, 1053, 18446744073709551615, 0, 1), - (13, 538, 282, 1054, 18446744073709551615, 0, 1), - (13, 539, 283, 1055, 18446744073709551615, 0, 1), - (13, 540, 284, 1056, 18446744073709551615, 0, 1), - (13, 541, 285, 1057, 18446744073709551615, 0, 1), - (13, 542, 286, 1058, 18446744073709551615, 0, 1), - (13, 543, 287, 1059, 18446744073709551615, 0, 1), - (13, 544, 288, 1060, 18446744073709551615, 0, 1), - (13, 545, 289, 1061, 18446744073709551615, 0, 1), - (13, 546, 290, 1062, 18446744073709551615, 0, 1), - (13, 547, 291, 1063, 18446744073709551615, 0, 1), - (13, 548, 292, 1064, 18446744073709551615, 0, 1), - (13, 549, 293, 1065, 18446744073709551615, 0, 1), - (13, 550, 294, 1066, 18446744073709551615, 0, 1), - (13, 551, 295, 1067, 18446744073709551615, 0, 1), - (13, 552, 296, 1068, 18446744073709551615, 0, 1), - (13, 553, 297, 1069, 18446744073709551615, 0, 1), - (13, 554, 298, 1070, 18446744073709551615, 0, 1), - (13, 555, 299, 1071, 18446744073709551615, 0, 1), - (13, 556, 300, 1072, 18446744073709551615, 0, 1), - (13, 557, 301, 1073, 18446744073709551615, 0, 1), - (13, 558, 302, 1074, 18446744073709551615, 0, 1), - (13, 559, 303, 1075, 18446744073709551615, 0, 1), - (13, 560, 304, 1076, 18446744073709551615, 0, 1), - (13, 561, 305, 1077, 18446744073709551615, 0, 1), - (13, 562, 306, 1078, 18446744073709551615, 0, 1), - (13, 563, 307, 1079, 18446744073709551615, 0, 1), - (13, 564, 308, 1080, 18446744073709551615, 0, 1), - (13, 565, 309, 1081, 18446744073709551615, 0, 1), - (13, 566, 310, 1082, 18446744073709551615, 0, 1), - (13, 567, 311, 1083, 18446744073709551615, 0, 1), - (13, 568, 312, 1084, 18446744073709551615, 0, 1), - (13, 569, 313, 1085, 18446744073709551615, 0, 1), - (13, 570, 314, 1086, 18446744073709551615, 0, 1), - (13, 571, 315, 1087, 18446744073709551615, 0, 1), - (13, 572, 316, 1088, 18446744073709551615, 0, 1), - (13, 573, 317, 1089, 18446744073709551615, 0, 1), - (13, 574, 318, 1090, 18446744073709551615, 0, 1), - (13, 575, 319, 1091, 18446744073709551615, 0, 1), - (14, 1024, 576, 320, 18446744073709551615, 0, 1), - (13, 543, 1056, 1057, 18446744073709551615, 2, 3), - (13, 767, 511, 1045, 18446744073709551615, 0, 1), - (13, 1024, 1039, 1027, 18446744073709551615, 0, 1), - (13, 513, 1033, 1034, 18446744073709551615, 0, 1), - (13, 514, 1034, 1035, 18446744073709551615, 0, 1), - (13, 515, 1035, 1036, 18446744073709551615, 0, 1), - (13, 542, 1057, 1058, 18446744073709551615, 0, 1), - (13, 1024, 1048, 1030, 18446744073709551615, 0, 1), - (13, 513, 1036, 1037, 18446744073709551615, 0, 1), - (13, 514, 1037, 1038, 18446744073709551615, 0, 1), - (13, 515, 1038, 1039, 18446744073709551615, 0, 1), - (13, 1024, 1057, 1033, 18446744073709551615, 0, 1), - (13, 513, 1039, 1040, 18446744073709551615, 0, 1), - (13, 514, 1040, 1041, 18446744073709551615, 0, 1), - (13, 515, 1041, 1042, 18446744073709551615, 0, 2), - (13, 542, 1063, 1064, 18446744073709551615, 0, 1), - (13, 543, 1064, 1065, 18446744073709551615, 0, 1), - (13, 1024, 1060, 1033, 18446744073709551615, 0, 1), - (13, 513, 1040, 1041, 18446744073709551615, 0, 1), - (13, 514, 1041, 1042, 18446744073709551615, 0, 1), - (13, 515, 1042, 1043, 18446744073709551615, 0, 1), - (13, 1024, 1069, 1035, 18446744073709551615, 0, 1), - (13, 513, 1043, 1044, 18446744073709551615, 0, 1), - (13, 514, 1044, 1045, 18446744073709551615, 0, 1), - (13, 515, 1045, 1046, 18446744073709551615, 0, 1), - (13, 255, 1023, 1069, 18446744073709551615, 1, 2), - (13, 255, 1023, 1078, 18446744073709551615, 0, 1), - (13, 1024, 1078, 1040, 18446744073709551615, 0, 1), - (13, 1024, 1023, 255, 18446744073709551615, 7, 12), - (13, 513, 1046, 1047, 18446744073709551615, 0, 1), - (13, 514, 1047, 1048, 18446744073709551615, 0, 1), - (13, 515, 1048, 1049, 18446744073709551615, 0, 2), - (13, 542, 1070, 1071, 18446744073709551615, 0, 1), - (13, 255, 1023, 1071, 18446744073709551615, 0, 1), - (13, 255, 1023, 1081, 18446744073709551615, 0, 1), - (13, 1024, 1081, 1040, 18446744073709551615, 0, 1), - (13, 1024, 1023, 255, 18446744073709551615, 8, 12), - (14, 1024, 255, 1023, 18446744073709551615, 7, 11), - (13, 513, 1047, 1048, 18446744073709551615, 0, 1), - (13, 514, 1048, 1049, 18446744073709551615, 0, 1), - (13, 515, 1049, 1050, 18446744073709551615, 0, 1), - (13, 542, 1071, 1072, 18446744073709551615, 1, 2), - (13, 543, 1072, 1073, 18446744073709551615, 1, 2), - (13, 254, 1022, 1075, 18446744073709551615, 0, 1), - (13, 255, 1023, 1076, 18446744073709551615, 0, 1), - (13, 254, 1022, 1089, 18446744073709551615, 0, 1), - (13, 255, 1023, 1090, 18446744073709551615, 0, 1), - (13, 1024, 1090, 1042, 18446744073709551615, 0, 1), - (13, 1024, 1023, 255, 18446744073709551615, 9, 12), - (13, 1024, 1022, 254, 18446744073709551615, 9, 13), - (14, 1024, 255, 1023, 18446744073709551615, 8, 11), - (13, 513, 1050, 1051, 18446744073709551615, 0, 1), - (13, 514, 1051, 1052, 18446744073709551615, 0, 1), - (13, 515, 1052, 1053, 18446744073709551615, 0, 1), - (13, 543, 1075, 1076, 18446744073709551615, 0, 1), - (13, 253, 1021, 1077, 18446744073709551615, 0, 1), - (13, 254, 1022, 1078, 18446744073709551615, 0, 1), - (13, 255, 1023, 1079, 18446744073709551615, 0, 1), - (13, 253, 1021, 1097, 18446744073709551615, 0, 1), - (13, 254, 1022, 1098, 18446744073709551615, 0, 1), - (13, 255, 1023, 1099, 18446744073709551615, 0, 1), - (13, 1024, 1099, 1047, 18446744073709551615, 0, 1), - (13, 1024, 1023, 255, 18446744073709551615, 10, 12), - (13, 1024, 1022, 254, 18446744073709551615, 10, 13), - (13, 1024, 1021, 253, 18446744073709551615, 10, 14), - (14, 1024, 255, 1023, 18446744073709551615, 9, 11), - (13, 513, 1053, 1054, 18446744073709551615, 0, 1), - (13, 514, 1054, 1055, 18446744073709551615, 0, 1), - (13, 515, 1055, 1056, 18446744073709551615, 0, 1), - (13, 542, 1077, 1078, 18446744073709551615, 0, 1), - (13, 543, 1078, 1079, 18446744073709551615, 0, 1), - (13, 252, 1020, 1079, 18446744073709551615, 0, 1), - (13, 253, 1021, 1080, 18446744073709551615, 0, 1), - (13, 254, 1022, 1081, 18446744073709551615, 0, 1), - (13, 255, 1023, 1082, 18446744073709551615, 0, 1), - (13, 252, 1020, 1099, 18446744073709551615, 0, 1), - (13, 253, 1021, 1100, 18446744073709551615, 0, 1), - (13, 254, 1022, 1101, 18446744073709551615, 0, 1), - (13, 255, 1023, 1102, 18446744073709551615, 0, 1), - (13, 1024, 1102, 1047, 18446744073709551615, 0, 1), - (13, 1024, 1023, 255, 18446744073709551615, 11, 12), - (13, 1024, 1022, 254, 18446744073709551615, 11, 13), - (13, 1024, 1021, 253, 18446744073709551615, 11, 14), - (13, 1024, 1020, 252, 18446744073709551615, 11, 15), - (13, 254, 1022, 1070, 18446744073709551615, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 10, 11), - (13, 513, 1054, 1055, 18446744073709551615, 0, 1), - (13, 514, 1055, 1056, 18446744073709551615, 0, 1), - (13, 515, 1056, 1057, 18446744073709551615, 0, 1), - (13, 542, 1078, 1079, 18446744073709551615, 1, 2), - (13, 543, 1079, 1080, 18446744073709551615, 1, 2), - (13, 251, 1019, 1080, 18446744073709551615, 0, 1), - (13, 252, 1020, 1081, 18446744073709551615, 0, 1), - (13, 253, 1021, 1082, 18446744073709551615, 0, 1), - (13, 254, 1022, 1083, 18446744073709551615, 0, 1), - (13, 251, 1019, 1101, 18446744073709551615, 0, 2), - (13, 252, 1020, 1102, 18446744073709551615, 0, 2), - (13, 253, 1021, 1103, 18446744073709551615, 0, 1), - (13, 254, 1022, 1104, 18446744073709551615, 0, 1), - (13, 1024, 1104, 255, 18446744073709551615, 0, 1), - (13, 1024, 1022, 254, 18446744073709551615, 12, 13), - (13, 1024, 1021, 253, 18446744073709551615, 12, 14), - (13, 1024, 1020, 252, 18446744073709551615, 12, 15), - (13, 1024, 1019, 251, 18446744073709551615, 12, 16), - (13, 253, 1021, 1071, 18446744073709551615, 0, 1), - (14, 1024, 254, 1022, 18446744073709551615, 0, 1), - (13, 513, 1055, 1056, 18446744073709551615, 0, 1), - (13, 514, 1056, 1057, 18446744073709551615, 0, 1), - (13, 515, 1057, 1058, 18446744073709551615, 0, 2), - (13, 543, 1080, 1081, 18446744073709551615, 1, 3), - (13, 250, 1018, 1081, 18446744073709551615, 0, 2), - (13, 251, 1019, 1082, 18446744073709551615, 0, 2), - (13, 252, 1020, 1083, 18446744073709551615, 0, 2), - (13, 253, 1021, 1084, 18446744073709551615, 0, 1), - (13, 250, 1018, 1103, 18446744073709551615, 0, 2), - (13, 251, 1019, 1104, 18446744073709551615, 0, 2), - (13, 252, 1020, 1105, 18446744073709551615, 0, 1), - (13, 253, 1021, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 254, 18446744073709551615, 0, 1), - (13, 1024, 1021, 253, 18446744073709551615, 13, 14), - (13, 1024, 1020, 252, 18446744073709551615, 13, 15), - (13, 1024, 1019, 251, 18446744073709551615, 13, 16), - (13, 1024, 1018, 250, 18446744073709551615, 13, 17), - (13, 251, 1019, 1071, 18446744073709551615, 0, 2), - (13, 252, 1020, 1072, 18446744073709551615, 0, 1), - (14, 1024, 253, 1021, 18446744073709551615, 0, 1), - (13, 513, 1056, 1057, 18446744073709551615, 0, 1), - (13, 514, 1057, 1058, 18446744073709551615, 0, 2), - (13, 515, 1058, 1059, 18446744073709551615, 0, 3), - (13, 249, 1017, 1080, 18446744073709551615, 1, 2), - (13, 250, 1018, 1081, 18446744073709551615, 1, 2), - (13, 251, 1019, 1082, 18446744073709551615, 1, 2), - (13, 252, 1020, 1083, 18446744073709551615, 1, 2), - (13, 249, 1017, 1099, 18446744073709551615, 1, 2), - (13, 250, 1018, 1100, 18446744073709551615, 1, 2), - (13, 251, 1019, 1101, 18446744073709551615, 1, 2), - (13, 252, 1020, 1102, 18446744073709551615, 1, 2), - (13, 1024, 1102, 253, 18446744073709551615, 0, 1), - (13, 1024, 1020, 252, 18446744073709551615, 14, 15), - (13, 1024, 1019, 251, 18446744073709551615, 14, 16), - (13, 1024, 1018, 250, 18446744073709551615, 14, 17), - (13, 1024, 1017, 249, 18446744073709551615, 14, 18), - (13, 250, 1018, 1070, 18446744073709551615, 1, 2), - (13, 251, 1019, 1071, 18446744073709551615, 1, 2), - (14, 1024, 252, 1020, 18446744073709551615, 0, 1), - (13, 513, 1056, 1022, 18446744073709551615, 0, 1), - (13, 514, 1022, 1057, 18446744073709551615, 0, 1), - (13, 515, 1057, 1058, 18446744073709551615, 1, 2), - (13, 248, 1016, 1081, 18446744073709551615, 0, 1), - (13, 249, 1017, 1082, 18446744073709551615, 0, 1), - (13, 250, 1018, 1083, 18446744073709551615, 0, 1), - (13, 251, 1019, 1084, 18446744073709551615, 0, 1), - (13, 248, 1016, 1101, 18446744073709551615, 1, 3), - (13, 249, 1017, 1102, 18446744073709551615, 1, 3), - (13, 250, 1018, 1103, 18446744073709551615, 1, 2), - (13, 251, 1019, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 252, 18446744073709551615, 0, 1), - (13, 1024, 1019, 251, 18446744073709551615, 15, 16), - (13, 1024, 1018, 250, 18446744073709551615, 15, 17), - (13, 1024, 1017, 249, 18446744073709551615, 15, 18), - (13, 1024, 1016, 248, 18446744073709551615, 15, 19), - (13, 249, 1017, 1071, 18446744073709551615, 0, 1), - (13, 250, 1018, 1072, 18446744073709551615, 0, 1), - (14, 1024, 251, 1019, 18446744073709551615, 0, 1), - (13, 513, 1022, 1057, 18446744073709551615, 0, 1), - (13, 514, 1057, 1058, 18446744073709551615, 1, 2), - (13, 515, 1058, 1059, 18446744073709551615, 1, 3), - (13, 542, 1080, 1081, 18446744073709551615, 3, 5), - (13, 543, 1081, 1082, 18446744073709551615, 3, 5), - (13, 247, 1015, 1082, 18446744073709551615, 1, 2), - (13, 248, 1016, 1083, 18446744073709551615, 1, 2), - (13, 249, 1017, 1084, 18446744073709551615, 1, 2), - (13, 250, 1018, 1085, 18446744073709551615, 1, 2), - (13, 247, 1015, 1103, 18446744073709551615, 0, 2), - (13, 248, 1016, 1104, 18446744073709551615, 0, 2), - (13, 249, 1017, 1105, 18446744073709551615, 0, 1), - (13, 250, 1018, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 251, 18446744073709551615, 0, 1), - (13, 1024, 1018, 250, 18446744073709551615, 16, 17), - (13, 1024, 1017, 249, 18446744073709551615, 16, 18), - (13, 1024, 1016, 248, 18446744073709551615, 16, 19), - (13, 1024, 1015, 247, 18446744073709551615, 16, 20), - (13, 248, 1016, 1072, 18446744073709551615, 1, 3), - (13, 249, 1017, 1073, 18446744073709551615, 1, 2), - (14, 1024, 250, 1018, 18446744073709551615, 0, 1), - (13, 513, 1057, 1058, 18446744073709551615, 0, 1), - (13, 514, 1058, 1059, 18446744073709551615, 0, 2), - (13, 515, 1059, 1060, 18446744073709551615, 0, 3), - (13, 543, 1082, 1083, 18446744073709551615, 2, 6), - (13, 246, 1014, 1082, 18446744073709551615, 0, 1), - (13, 247, 1015, 1083, 18446744073709551615, 0, 1), - (13, 248, 1016, 1084, 18446744073709551615, 0, 1), - (13, 249, 1017, 1085, 18446744073709551615, 0, 1), - (13, 246, 1014, 1099, 18446744073709551615, 2, 3), - (13, 247, 1015, 1100, 18446744073709551615, 2, 3), - (13, 248, 1016, 1101, 18446744073709551615, 2, 3), - (13, 249, 1017, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 250, 18446744073709551615, 0, 1), - (13, 1024, 1017, 249, 18446744073709551615, 17, 18), - (13, 1024, 1016, 248, 18446744073709551615, 17, 19), - (13, 1024, 1015, 247, 18446744073709551615, 17, 20), - (13, 1024, 1014, 246, 18446744073709551615, 17, 21), - (13, 246, 1014, 1070, 18446744073709551615, 2, 3), - (13, 247, 1015, 1071, 18446744073709551615, 2, 3), - (13, 248, 1016, 1072, 18446744073709551615, 2, 3), - (14, 1024, 249, 1017, 18446744073709551615, 1, 2), - (13, 513, 1057, 1019, 18446744073709551615, 0, 1), - (13, 514, 1019, 1058, 18446744073709551615, 0, 1), - (13, 515, 1058, 1059, 18446744073709551615, 2, 3), - (13, 542, 1080, 1081, 18446744073709551615, 4, 5), - (13, 543, 1081, 1082, 18446744073709551615, 4, 5), - (13, 246, 1014, 1084, 18446744073709551615, 0, 1), - (13, 247, 1015, 1085, 18446744073709551615, 0, 1), - (13, 248, 1016, 1086, 18446744073709551615, 0, 1), - (13, 246, 1014, 1102, 18446744073709551615, 1, 3), - (13, 247, 1015, 1103, 18446744073709551615, 1, 2), - (13, 248, 1016, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 249, 18446744073709551615, 0, 1), - (13, 1024, 1016, 248, 18446744073709551615, 18, 19), - (13, 1024, 1015, 247, 18446744073709551615, 18, 20), - (13, 1024, 1014, 246, 18446744073709551615, 18, 21), - (13, 246, 1014, 1072, 18446744073709551615, 1, 2), - (13, 247, 1015, 1073, 18446744073709551615, 1, 2), - (14, 1024, 248, 1016, 18446744073709551615, 0, 1), - (13, 513, 1019, 1058, 18446744073709551615, 0, 1), - (13, 514, 1058, 1059, 18446744073709551615, 1, 2), - (13, 515, 1059, 1060, 18446744073709551615, 1, 3), - (13, 543, 1083, 1084, 18446744073709551615, 1, 6), - (13, 245, 1013, 1084, 18446744073709551615, 0, 1), - (13, 246, 1014, 1085, 18446744073709551615, 0, 1), - (13, 247, 1015, 1086, 18446744073709551615, 0, 1), - (13, 245, 1013, 1104, 18446744073709551615, 0, 2), - (13, 246, 1014, 1105, 18446744073709551615, 0, 1), - (13, 247, 1015, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 248, 18446744073709551615, 0, 1), - (13, 1024, 1015, 247, 18446744073709551615, 19, 20), - (13, 1024, 1014, 246, 18446744073709551615, 19, 21), - (13, 1024, 1013, 245, 18446744073709551615, 19, 22), - (13, 244, 1012, 1072, 18446744073709551615, 0, 2), - (13, 245, 1013, 1073, 18446744073709551615, 0, 2), - (13, 246, 1014, 1074, 18446744073709551615, 0, 1), - (14, 1024, 247, 1015, 18446744073709551615, 0, 1), - (13, 513, 1058, 1059, 18446744073709551615, 0, 1), - (13, 514, 1059, 1060, 18446744073709551615, 0, 2), - (13, 515, 1060, 1061, 18446744073709551615, 0, 3), - (13, 543, 1084, 1085, 18446744073709551615, 0, 6), - (13, 542, 1082, 1083, 18446744073709551615, 2, 6), - (13, 543, 1083, 1084, 18446744073709551615, 2, 6), - (13, 244, 1012, 1084, 18446744073709551615, 0, 1), - (13, 245, 1013, 1085, 18446744073709551615, 0, 1), - (13, 246, 1014, 1086, 18446744073709551615, 0, 1), - (13, 244, 1012, 1100, 18446744073709551615, 2, 3), - (13, 245, 1013, 1101, 18446744073709551615, 2, 3), - (13, 246, 1014, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 247, 18446744073709551615, 0, 1), - (13, 1024, 1014, 246, 18446744073709551615, 20, 21), - (13, 1024, 1013, 245, 18446744073709551615, 20, 22), - (13, 1024, 1012, 244, 18446744073709551615, 20, 23), - (13, 243, 1011, 1071, 18446744073709551615, 1, 2), - (13, 244, 1012, 1072, 18446744073709551615, 1, 2), - (13, 245, 1013, 1073, 18446744073709551615, 1, 2), - (14, 1024, 246, 1014, 18446744073709551615, 0, 1), - (13, 513, 1058, 1016, 18446744073709551615, 0, 1), - (13, 514, 1016, 1059, 18446744073709551615, 0, 1), - (13, 515, 1059, 1060, 18446744073709551615, 2, 3), - (13, 542, 1081, 1082, 18446744073709551615, 5, 6), - (13, 543, 1082, 1083, 18446744073709551615, 5, 6), - (13, 243, 1011, 1085, 18446744073709551615, 0, 1), - (13, 244, 1012, 1086, 18446744073709551615, 0, 1), - (13, 245, 1013, 1087, 18446744073709551615, 0, 1), - (13, 243, 1011, 1102, 18446744073709551615, 1, 3), - (13, 244, 1012, 1103, 18446744073709551615, 1, 2), - (13, 245, 1013, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 246, 18446744073709551615, 0, 1), - (13, 1024, 1013, 245, 18446744073709551615, 21, 22), - (13, 1024, 1012, 244, 18446744073709551615, 21, 23), - (13, 1024, 1011, 243, 18446744073709551615, 21, 24), - (13, 243, 1011, 1073, 18446744073709551615, 0, 1), - (13, 244, 1012, 1074, 18446744073709551615, 0, 1), - (14, 1024, 245, 1013, 18446744073709551615, 1, 2), - (13, 513, 1016, 1059, 18446744073709551615, 0, 1), - (13, 514, 1059, 1060, 18446744073709551615, 1, 2), - (13, 515, 1060, 1061, 18446744073709551615, 1, 3), - (13, 542, 1082, 1083, 18446744073709551615, 4, 6), - (13, 242, 1010, 1086, 18446744073709551615, 1, 2), - (13, 243, 1011, 1087, 18446744073709551615, 1, 2), - (13, 244, 1012, 1088, 18446744073709551615, 1, 2), - (13, 242, 1010, 1104, 18446744073709551615, 0, 2), - (13, 243, 1011, 1105, 18446744073709551615, 0, 1), - (13, 244, 1012, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 245, 18446744073709551615, 0, 1), - (13, 1024, 1012, 244, 18446744073709551615, 22, 23), - (13, 1024, 1011, 243, 18446744073709551615, 22, 24), - (13, 1024, 1010, 242, 18446744073709551615, 22, 25), - (13, 242, 1010, 1074, 18446744073709551615, 0, 2), - (13, 243, 1011, 1075, 18446744073709551615, 0, 1), - (14, 1024, 244, 1012, 18446744073709551615, 0, 1), - (13, 513, 1059, 1060, 18446744073709551615, 0, 1), - (13, 514, 1060, 1061, 18446744073709551615, 0, 2), - (13, 515, 1061, 1062, 18446744073709551615, 0, 3), - (13, 542, 1083, 1084, 18446744073709551615, 2, 6), - (13, 543, 1084, 1085, 18446744073709551615, 2, 6), - (13, 241, 1009, 1084, 18446744073709551615, 0, 1), - (13, 242, 1010, 1085, 18446744073709551615, 0, 1), - (13, 243, 1011, 1086, 18446744073709551615, 0, 1), - (13, 241, 1009, 1100, 18446744073709551615, 2, 3), - (13, 242, 1010, 1101, 18446744073709551615, 2, 3), - (13, 243, 1011, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 244, 18446744073709551615, 0, 1), - (13, 1024, 1011, 243, 18446744073709551615, 23, 24), - (13, 1024, 1010, 242, 18446744073709551615, 23, 25), - (13, 1024, 1009, 241, 18446744073709551615, 23, 26), - (13, 241, 1009, 1073, 18446744073709551615, 1, 2), - (13, 242, 1010, 1074, 18446744073709551615, 1, 2), - (14, 1024, 243, 1011, 18446744073709551615, 0, 1), - (13, 513, 1059, 1013, 18446744073709551615, 0, 1), - (13, 514, 1013, 1060, 18446744073709551615, 0, 1), - (13, 515, 1060, 1061, 18446744073709551615, 2, 3), - (13, 542, 1082, 1083, 18446744073709551615, 5, 6), - (13, 240, 1008, 1087, 18446744073709551615, 1, 2), - (13, 241, 1009, 1088, 18446744073709551615, 1, 2), - (13, 242, 1010, 1089, 18446744073709551615, 1, 2), - (13, 240, 1008, 1102, 18446744073709551615, 1, 3), - (13, 241, 1009, 1103, 18446744073709551615, 1, 2), - (13, 242, 1010, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 243, 18446744073709551615, 0, 1), - (13, 1024, 1010, 242, 18446744073709551615, 24, 25), - (13, 1024, 1009, 241, 18446744073709551615, 24, 26), - (13, 1024, 1008, 240, 18446744073709551615, 24, 27), - (13, 240, 1008, 1074, 18446744073709551615, 0, 1), - (13, 241, 1009, 1075, 18446744073709551615, 0, 1), - (14, 1024, 242, 1010, 18446744073709551615, 0, 1), - (13, 513, 1013, 1060, 18446744073709551615, 0, 1), - (13, 514, 1060, 1061, 18446744073709551615, 1, 2), - (13, 515, 1061, 1062, 18446744073709551615, 1, 3), - (13, 542, 1083, 1084, 18446744073709551615, 4, 6), - (13, 239, 1007, 1088, 18446744073709551615, 0, 1), - (13, 240, 1008, 1089, 18446744073709551615, 0, 1), - (13, 241, 1009, 1090, 18446744073709551615, 0, 1), - (13, 239, 1007, 1104, 18446744073709551615, 0, 2), - (13, 240, 1008, 1105, 18446744073709551615, 0, 1), - (13, 241, 1009, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 242, 18446744073709551615, 0, 1), - (13, 1024, 1009, 241, 18446744073709551615, 25, 26), - (13, 1024, 1008, 240, 18446744073709551615, 25, 27), - (13, 1024, 1007, 239, 18446744073709551615, 25, 28), - (13, 239, 1007, 1075, 18446744073709551615, 1, 3), - (13, 240, 1008, 1076, 18446744073709551615, 1, 2), - (14, 1024, 241, 1009, 18446744073709551615, 0, 1), - (13, 513, 1060, 1061, 18446744073709551615, 0, 1), - (13, 514, 1061, 1062, 18446744073709551615, 0, 2), - (13, 515, 1062, 1063, 18446744073709551615, 0, 3), - (13, 542, 1084, 1085, 18446744073709551615, 2, 6), - (13, 543, 1085, 1086, 18446744073709551615, 2, 6), - (13, 238, 1006, 1086, 18446744073709551615, 0, 1), - (13, 239, 1007, 1087, 18446744073709551615, 0, 1), - (13, 240, 1008, 1088, 18446744073709551615, 0, 1), - (13, 238, 1006, 1100, 18446744073709551615, 2, 3), - (13, 239, 1007, 1101, 18446744073709551615, 2, 3), - (13, 240, 1008, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 241, 18446744073709551615, 0, 1), - (13, 1024, 1008, 240, 18446744073709551615, 26, 27), - (13, 1024, 1007, 239, 18446744073709551615, 26, 28), - (13, 1024, 1006, 238, 18446744073709551615, 26, 29), - (13, 238, 1006, 1074, 18446744073709551615, 2, 3), - (13, 239, 1007, 1075, 18446744073709551615, 2, 3), - (14, 1024, 240, 1008, 18446744073709551615, 0, 1), - (13, 513, 1060, 1010, 18446744073709551615, 0, 1), - (13, 514, 1010, 1061, 18446744073709551615, 0, 1), - (13, 515, 1061, 1062, 18446744073709551615, 2, 3), - (13, 237, 1005, 1087, 18446744073709551615, 2, 3), - (13, 238, 1006, 1088, 18446744073709551615, 2, 3), - (13, 239, 1007, 1089, 18446744073709551615, 2, 3), - (13, 237, 1005, 1102, 18446744073709551615, 1, 3), - (13, 238, 1006, 1103, 18446744073709551615, 1, 2), - (13, 239, 1007, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 240, 18446744073709551615, 0, 1), - (13, 1024, 1007, 239, 18446744073709551615, 27, 28), - (13, 1024, 1006, 238, 18446744073709551615, 27, 29), - (13, 1024, 1005, 237, 18446744073709551615, 27, 30), - (13, 237, 1005, 1075, 18446744073709551615, 1, 2), - (13, 238, 1006, 1076, 18446744073709551615, 1, 2), - (14, 1024, 239, 1007, 18446744073709551615, 1, 2), - (13, 513, 1010, 1061, 18446744073709551615, 0, 1), - (13, 514, 1061, 1062, 18446744073709551615, 1, 2), - (13, 515, 1062, 1063, 18446744073709551615, 1, 3), - (13, 542, 1084, 1085, 18446744073709551615, 4, 6), - (13, 543, 1085, 1086, 18446744073709551615, 4, 6), - (13, 236, 1004, 1089, 18446744073709551615, 3, 4), - (13, 237, 1005, 1090, 18446744073709551615, 3, 4), - (13, 238, 1006, 1091, 18446744073709551615, 3, 4), - (13, 236, 1004, 1104, 18446744073709551615, 0, 2), - (13, 237, 1005, 1105, 18446744073709551615, 0, 1), - (13, 238, 1006, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 239, 18446744073709551615, 0, 1), - (13, 1024, 1006, 238, 18446744073709551615, 28, 29), - (13, 1024, 1005, 237, 18446744073709551615, 28, 30), - (13, 1024, 1004, 236, 18446744073709551615, 28, 31), - (13, 236, 1004, 1076, 18446744073709551615, 1, 3), - (13, 237, 1005, 1077, 18446744073709551615, 1, 2), - (13, 513, 1061, 1062, 18446744073709551615, 0, 1), - (13, 514, 1062, 1063, 18446744073709551615, 0, 2), - (13, 515, 1063, 1064, 18446744073709551615, 0, 3), - (13, 543, 1086, 1087, 18446744073709551615, 2, 6), - (13, 235, 1003, 1087, 18446744073709551615, 0, 1), - (13, 236, 1004, 1088, 18446744073709551615, 0, 1), - (13, 237, 1005, 1089, 18446744073709551615, 0, 1), - (13, 235, 1003, 1100, 18446744073709551615, 2, 3), - (13, 236, 1004, 1101, 18446744073709551615, 2, 3), - (13, 237, 1005, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 238, 18446744073709551615, 0, 1), - (13, 1024, 1005, 237, 18446744073709551615, 29, 30), - (13, 1024, 1004, 236, 18446744073709551615, 29, 31), - (13, 1024, 1003, 235, 18446744073709551615, 29, 32), - (13, 235, 1003, 1075, 18446744073709551615, 2, 3), - (13, 236, 1004, 1076, 18446744073709551615, 2, 3), - (14, 1024, 237, 1005, 18446744073709551615, 0, 1), - (13, 513, 1061, 1007, 18446744073709551615, 0, 1), - (13, 514, 1007, 1062, 18446744073709551615, 0, 1), - (13, 515, 1062, 1063, 18446744073709551615, 2, 3), - (13, 542, 1084, 1085, 18446744073709551615, 5, 6), - (13, 543, 1085, 1086, 18446744073709551615, 5, 6), - (13, 234, 1002, 1088, 18446744073709551615, 0, 1), - (13, 235, 1003, 1089, 18446744073709551615, 0, 1), - (13, 236, 1004, 1090, 18446744073709551615, 0, 1), - (13, 234, 1002, 1102, 18446744073709551615, 1, 3), - (13, 235, 1003, 1103, 18446744073709551615, 1, 2), - (13, 236, 1004, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 237, 18446744073709551615, 0, 1), - (13, 1024, 1004, 236, 18446744073709551615, 30, 31), - (13, 1024, 1003, 235, 18446744073709551615, 30, 32), - (13, 234, 1002, 1076, 18446744073709551615, 1, 2), - (13, 235, 1003, 1077, 18446744073709551615, 1, 2), - (14, 1024, 236, 1004, 18446744073709551615, 0, 1), - (13, 513, 1007, 1062, 18446744073709551615, 0, 1), - (13, 514, 1062, 1063, 18446744073709551615, 1, 2), - (13, 515, 1063, 1064, 18446744073709551615, 1, 3), - (13, 542, 1085, 1086, 18446744073709551615, 4, 6), - (13, 543, 1086, 1087, 18446744073709551615, 4, 6), - (13, 233, 1001, 1091, 18446744073709551615, 0, 1), - (13, 234, 1002, 1092, 18446744073709551615, 0, 1), - (13, 235, 1003, 1093, 18446744073709551615, 0, 1), - (13, 233, 1001, 1104, 18446744073709551615, 0, 2), - (13, 234, 1002, 1105, 18446744073709551615, 0, 1), - (13, 235, 1003, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 236, 18446744073709551615, 0, 1), - (13, 1024, 1003, 235, 18446744073709551615, 31, 32), - (13, 1024, 1002, 234, 18446744073709551615, 31, 33), - (13, 1024, 1001, 233, 18446744073709551615, 31, 34), - (13, 233, 1001, 1077, 18446744073709551615, 2, 4), - (13, 234, 1002, 1078, 18446744073709551615, 2, 3), - (14, 1024, 235, 1003, 18446744073709551615, 0, 1), - (13, 513, 1062, 1063, 18446744073709551615, 0, 1), - (13, 514, 1063, 1064, 18446744073709551615, 0, 2), - (13, 515, 1064, 1065, 18446744073709551615, 0, 3), - (13, 233, 1001, 1089, 18446744073709551615, 3, 4), - (13, 234, 1002, 1090, 18446744073709551615, 3, 4), - (13, 233, 1001, 1101, 18446744073709551615, 2, 3), - (13, 234, 1002, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 235, 18446744073709551615, 0, 1), - (13, 1024, 1002, 234, 18446744073709551615, 32, 33), - (13, 1024, 1001, 233, 18446744073709551615, 32, 34), - (13, 232, 1000, 1076, 18446744073709551615, 3, 4), - (13, 233, 1001, 1077, 18446744073709551615, 3, 4), - (14, 1024, 234, 1002, 18446744073709551615, 0, 1), - (13, 513, 1062, 1004, 18446744073709551615, 0, 1), - (13, 514, 1004, 1063, 18446744073709551615, 0, 1), - (13, 515, 1063, 1064, 18446744073709551615, 2, 3), - (13, 542, 1085, 1086, 18446744073709551615, 5, 6), - (13, 543, 1086, 1087, 18446744073709551615, 5, 6), - (13, 231, 999, 1090, 18446744073709551615, 3, 4), - (13, 232, 1000, 1091, 18446744073709551615, 3, 4), - (13, 233, 1001, 1092, 18446744073709551615, 3, 4), - (13, 231, 999, 1102, 18446744073709551615, 1, 3), - (13, 232, 1000, 1103, 18446744073709551615, 1, 2), - (13, 233, 1001, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 234, 18446744073709551615, 0, 1), - (13, 1024, 1001, 233, 18446744073709551615, 33, 34), - (13, 1024, 1000, 232, 18446744073709551615, 33, 35), - (13, 231, 999, 1077, 18446744073709551615, 0, 1), - (13, 232, 1000, 1078, 18446744073709551615, 0, 1), - (14, 1024, 233, 1001, 18446744073709551615, 1, 2), - (13, 513, 1004, 1063, 18446744073709551615, 0, 1), - (13, 514, 1063, 1064, 18446744073709551615, 1, 2), - (13, 515, 1064, 1065, 18446744073709551615, 1, 3), - (13, 542, 1086, 1087, 18446744073709551615, 4, 6), - (13, 231, 999, 1092, 18446744073709551615, 0, 2), - (13, 232, 1000, 1093, 18446744073709551615, 0, 1), - (13, 231, 999, 1105, 18446744073709551615, 0, 1), - (13, 232, 1000, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 233, 18446744073709551615, 0, 1), - (13, 1024, 1000, 232, 18446744073709551615, 34, 35), - (13, 1024, 999, 231, 18446744073709551615, 34, 36), - (13, 1024, 998, 230, 18446744073709551615, 34, 37), - (13, 230, 998, 1078, 18446744073709551615, 1, 3), - (13, 231, 999, 1079, 18446744073709551615, 1, 2), - (14, 1024, 232, 1000, 18446744073709551615, 0, 1), - (13, 513, 1063, 1064, 18446744073709551615, 0, 1), - (13, 514, 1064, 1065, 18446744073709551615, 0, 2), - (13, 515, 1065, 1066, 18446744073709551615, 0, 3), - (13, 542, 1087, 1088, 18446744073709551615, 2, 6), - (13, 543, 1088, 1089, 18446744073709551615, 2, 6), - (13, 230, 998, 1091, 18446744073709551615, 1, 2), - (13, 231, 999, 1092, 18446744073709551615, 1, 2), - (13, 230, 998, 1101, 18446744073709551615, 2, 3), - (13, 231, 999, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 232, 18446744073709551615, 0, 1), - (13, 1024, 999, 231, 18446744073709551615, 35, 36), - (13, 1024, 998, 230, 18446744073709551615, 35, 37), - (13, 230, 998, 1078, 18446744073709551615, 2, 3), - (14, 1024, 231, 999, 18446744073709551615, 1, 2), - (13, 513, 1063, 1001, 18446744073709551615, 0, 1), - (13, 514, 1001, 1064, 18446744073709551615, 0, 1), - (13, 515, 1064, 1065, 18446744073709551615, 2, 3), - (13, 229, 997, 1092, 18446744073709551615, 0, 1), - (13, 230, 998, 1093, 18446744073709551615, 0, 1), - (13, 229, 997, 1103, 18446744073709551615, 1, 2), - (13, 230, 998, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 231, 18446744073709551615, 0, 1), - (13, 1024, 998, 230, 18446744073709551615, 36, 37), - (13, 1024, 997, 229, 18446744073709551615, 36, 38), - (13, 229, 997, 1079, 18446744073709551615, 3, 4), - (14, 1024, 230, 998, 18446744073709551615, 0, 1), - (13, 513, 1001, 1064, 18446744073709551615, 0, 1), - (13, 514, 1064, 1065, 18446744073709551615, 1, 2), - (13, 515, 1065, 1066, 18446744073709551615, 1, 3), - (13, 542, 1087, 1088, 18446744073709551615, 4, 6), - (13, 228, 996, 1094, 18446744073709551615, 0, 1), - (13, 229, 997, 1095, 18446744073709551615, 0, 1), - (13, 228, 996, 1105, 18446744073709551615, 0, 1), - (13, 229, 997, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 230, 18446744073709551615, 0, 1), - (13, 1024, 997, 229, 18446744073709551615, 37, 38), - (13, 1024, 996, 228, 18446744073709551615, 37, 39), - (13, 228, 996, 1080, 18446744073709551615, 1, 2), - (13, 513, 1064, 1065, 18446744073709551615, 0, 1), - (13, 514, 1065, 1066, 18446744073709551615, 0, 2), - (13, 515, 1066, 1067, 18446744073709551615, 0, 3), - (13, 227, 995, 1092, 18446744073709551615, 3, 4), - (13, 228, 996, 1093, 18446744073709551615, 3, 4), - (13, 227, 995, 1101, 18446744073709551615, 2, 3), - (13, 228, 996, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 229, 18446744073709551615, 0, 1), - (13, 1024, 996, 228, 18446744073709551615, 38, 39), - (13, 1024, 995, 227, 18446744073709551615, 38, 40), - (13, 227, 995, 1079, 18446744073709551615, 2, 3), - (14, 1024, 228, 996, 18446744073709551615, 0, 1), - (13, 513, 1064, 998, 18446744073709551615, 0, 1), - (13, 514, 998, 1065, 18446744073709551615, 0, 1), - (13, 515, 1065, 1066, 18446744073709551615, 2, 3), - (13, 226, 994, 1094, 18446744073709551615, 3, 4), - (13, 227, 995, 1095, 18446744073709551615, 3, 4), - (13, 226, 994, 1103, 18446744073709551615, 1, 2), - (13, 227, 995, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 228, 18446744073709551615, 0, 1), - (13, 1024, 995, 227, 18446744073709551615, 39, 40), - (13, 1024, 994, 226, 18446744073709551615, 39, 41), - (13, 226, 994, 1080, 18446744073709551615, 1, 2), - (14, 1024, 227, 995, 18446744073709551615, 0, 1), - (13, 513, 998, 1065, 18446744073709551615, 0, 1), - (13, 514, 1065, 1066, 18446744073709551615, 1, 2), - (13, 515, 1066, 1067, 18446744073709551615, 1, 3), - (13, 542, 1088, 1089, 18446744073709551615, 4, 6), - (13, 225, 993, 1095, 18446744073709551615, 0, 2), - (13, 226, 994, 1096, 18446744073709551615, 0, 1), - (13, 225, 993, 1105, 18446744073709551615, 0, 1), - (13, 226, 994, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 227, 18446744073709551615, 0, 1), - (13, 1024, 994, 226, 18446744073709551615, 40, 41), - (13, 1024, 993, 225, 18446744073709551615, 40, 42), - (13, 225, 993, 1081, 18446744073709551615, 4, 5), - (14, 1024, 226, 994, 18446744073709551615, 0, 1), - (13, 513, 1065, 1066, 18446744073709551615, 0, 1), - (13, 514, 1066, 1067, 18446744073709551615, 0, 2), - (13, 515, 1067, 1068, 18446744073709551615, 0, 3), - (13, 542, 1089, 1090, 18446744073709551615, 2, 6), - (13, 224, 992, 1094, 18446744073709551615, 1, 2), - (13, 225, 993, 1095, 18446744073709551615, 1, 2), - (13, 224, 992, 1101, 18446744073709551615, 2, 3), - (13, 225, 993, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 226, 18446744073709551615, 0, 1), - (13, 1024, 993, 225, 18446744073709551615, 41, 42), - (13, 1024, 992, 224, 18446744073709551615, 41, 43), - (13, 224, 992, 1080, 18446744073709551615, 5, 6), - (14, 1024, 225, 993, 18446744073709551615, 1, 2), - (13, 513, 1065, 995, 18446744073709551615, 0, 1), - (13, 514, 995, 1066, 18446744073709551615, 0, 1), - (13, 515, 1066, 1067, 18446744073709551615, 2, 3), - (13, 542, 1088, 1089, 18446744073709551615, 5, 6), - (13, 543, 1089, 1090, 18446744073709551615, 5, 6), - (13, 223, 991, 1094, 18446744073709551615, 3, 4), - (13, 224, 992, 1095, 18446744073709551615, 3, 4), - (13, 223, 991, 1103, 18446744073709551615, 1, 2), - (13, 224, 992, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 225, 18446744073709551615, 0, 1), - (13, 1024, 992, 224, 18446744073709551615, 42, 43), - (13, 1024, 991, 223, 18446744073709551615, 42, 44), - (13, 223, 991, 1081, 18446744073709551615, 1, 2), - (14, 1024, 224, 992, 18446744073709551615, 0, 1), - (13, 513, 995, 1066, 18446744073709551615, 0, 1), - (13, 514, 1066, 1067, 18446744073709551615, 1, 2), - (13, 515, 1067, 1068, 18446744073709551615, 1, 3), - (13, 542, 1089, 1090, 18446744073709551615, 4, 6), - (13, 543, 1090, 1091, 18446744073709551615, 4, 6), - (13, 222, 990, 1096, 18446744073709551615, 3, 5), - (13, 223, 991, 1097, 18446744073709551615, 3, 4), - (13, 222, 990, 1105, 18446744073709551615, 0, 1), - (13, 223, 991, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 224, 18446744073709551615, 0, 1), - (13, 1024, 991, 223, 18446744073709551615, 43, 44), - (13, 1024, 990, 222, 18446744073709551615, 43, 45), - (13, 222, 990, 1082, 18446744073709551615, 0, 1), - (14, 1024, 223, 991, 18446744073709551615, 0, 1), - (13, 513, 1066, 1067, 18446744073709551615, 0, 1), - (13, 514, 1067, 1068, 18446744073709551615, 0, 2), - (13, 515, 1068, 1069, 18446744073709551615, 0, 3), - (13, 542, 1090, 1091, 18446744073709551615, 2, 6), - (13, 543, 1091, 1092, 18446744073709551615, 2, 6), - (13, 221, 989, 1095, 18446744073709551615, 4, 5), - (13, 222, 990, 1096, 18446744073709551615, 4, 5), - (13, 221, 989, 1101, 18446744073709551615, 2, 3), - (13, 222, 990, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 223, 18446744073709551615, 0, 1), - (13, 1024, 990, 222, 18446744073709551615, 44, 45), - (13, 1024, 989, 221, 18446744073709551615, 44, 46), - (13, 221, 989, 1081, 18446744073709551615, 1, 2), - (14, 1024, 222, 990, 18446744073709551615, 0, 1), - (13, 513, 1066, 992, 18446744073709551615, 0, 1), - (13, 514, 992, 1067, 18446744073709551615, 0, 1), - (13, 515, 1067, 1068, 18446744073709551615, 2, 3), - (13, 542, 1089, 1090, 18446744073709551615, 5, 6), - (13, 543, 1090, 1091, 18446744073709551615, 5, 6), - (13, 220, 988, 1096, 18446744073709551615, 0, 1), - (13, 221, 989, 1097, 18446744073709551615, 0, 1), - (13, 220, 988, 1103, 18446744073709551615, 1, 2), - (13, 221, 989, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 222, 18446744073709551615, 0, 1), - (13, 1024, 989, 221, 18446744073709551615, 45, 46), - (13, 1024, 988, 220, 18446744073709551615, 45, 47), - (13, 220, 988, 1082, 18446744073709551615, 3, 4), - (14, 1024, 221, 989, 18446744073709551615, 0, 1), - (13, 513, 992, 1067, 18446744073709551615, 0, 1), - (13, 514, 1067, 1068, 18446744073709551615, 1, 2), - (13, 515, 1068, 1069, 18446744073709551615, 1, 3), - (13, 543, 1091, 1092, 18446744073709551615, 4, 6), - (13, 219, 987, 1097, 18446744073709551615, 0, 1), - (13, 220, 988, 1098, 18446744073709551615, 0, 1), - (13, 219, 987, 1105, 18446744073709551615, 0, 1), - (13, 220, 988, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 221, 18446744073709551615, 0, 1), - (13, 1024, 988, 220, 18446744073709551615, 46, 47), - (13, 1024, 987, 219, 18446744073709551615, 46, 48), - (13, 219, 987, 1083, 18446744073709551615, 0, 1), - (14, 1024, 220, 988, 18446744073709551615, 0, 1), - (13, 513, 1067, 1068, 18446744073709551615, 0, 1), - (13, 514, 1068, 1069, 18446744073709551615, 0, 2), - (13, 515, 1069, 1070, 18446744073709551615, 0, 3), - (13, 543, 1092, 1093, 18446744073709551615, 2, 6), - (13, 218, 986, 1097, 18446744073709551615, 0, 1), - (13, 219, 987, 1098, 18446744073709551615, 0, 1), - (13, 218, 986, 1101, 18446744073709551615, 2, 3), - (13, 219, 987, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 220, 18446744073709551615, 0, 1), - (13, 1024, 987, 219, 18446744073709551615, 47, 48), - (13, 1024, 986, 218, 18446744073709551615, 47, 49), - (13, 218, 986, 1082, 18446744073709551615, 1, 2), - (14, 1024, 219, 987, 18446744073709551615, 1, 2), - (13, 513, 1067, 989, 18446744073709551615, 0, 1), - (13, 514, 989, 1068, 18446744073709551615, 0, 1), - (13, 515, 1068, 1069, 18446744073709551615, 2, 3), - (13, 542, 1090, 1091, 18446744073709551615, 5, 6), - (13, 543, 1091, 1092, 18446744073709551615, 5, 6), - (13, 217, 985, 1097, 18446744073709551615, 3, 4), - (13, 218, 986, 1098, 18446744073709551615, 3, 4), - (13, 217, 985, 1103, 18446744073709551615, 1, 2), - (13, 218, 986, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 219, 18446744073709551615, 0, 1), - (13, 1024, 986, 218, 18446744073709551615, 48, 49), - (13, 1024, 985, 217, 18446744073709551615, 48, 50), - (13, 217, 985, 1083, 18446744073709551615, 1, 2), - (13, 513, 989, 1068, 18446744073709551615, 0, 1), - (13, 514, 1068, 1069, 18446744073709551615, 1, 2), - (13, 515, 1069, 1070, 18446744073709551615, 1, 3), - (13, 542, 1091, 1092, 18446744073709551615, 4, 6), - (13, 543, 1092, 1093, 18446744073709551615, 4, 6), - (13, 216, 984, 1099, 18446744073709551615, 3, 4), - (13, 217, 985, 1100, 18446744073709551615, 3, 4), - (13, 216, 984, 1105, 18446744073709551615, 0, 1), - (13, 217, 985, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 218, 18446744073709551615, 0, 1), - (13, 1024, 985, 217, 18446744073709551615, 49, 50), - (13, 1024, 984, 216, 18446744073709551615, 49, 51), - (13, 216, 984, 1084, 18446744073709551615, 4, 5), - (14, 1024, 217, 985, 18446744073709551615, 1, 2), - (13, 513, 1068, 1069, 18446744073709551615, 0, 1), - (13, 514, 1069, 1070, 18446744073709551615, 0, 2), - (13, 515, 1070, 1071, 18446744073709551615, 0, 3), - (13, 543, 1094, 1095, 18446744073709551615, 0, 6), - (13, 215, 983, 1097, 18446744073709551615, 0, 1), - (13, 216, 984, 1098, 18446744073709551615, 0, 1), - (13, 215, 983, 1101, 18446744073709551615, 2, 3), - (13, 216, 984, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 217, 18446744073709551615, 0, 1), - (13, 1024, 984, 216, 18446744073709551615, 50, 51), - (13, 1024, 983, 215, 18446744073709551615, 50, 52), - (13, 215, 983, 1083, 18446744073709551615, 5, 6), - (14, 1024, 216, 984, 18446744073709551615, 0, 1), - (13, 513, 1068, 986, 18446744073709551615, 0, 1), - (13, 514, 986, 1069, 18446744073709551615, 0, 1), - (13, 515, 1069, 1070, 18446744073709551615, 2, 3), - (13, 542, 1091, 1092, 18446744073709551615, 5, 6), - (13, 214, 982, 1099, 18446744073709551615, 0, 1), - (13, 215, 983, 1100, 18446744073709551615, 0, 1), - (13, 214, 982, 1103, 18446744073709551615, 1, 2), - (13, 215, 983, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 216, 18446744073709551615, 0, 1), - (13, 1024, 983, 215, 18446744073709551615, 51, 52), - (13, 1024, 982, 214, 18446744073709551615, 51, 53), - (13, 214, 982, 1084, 18446744073709551615, 2, 3), - (14, 1024, 215, 983, 18446744073709551615, 0, 1), - (13, 513, 986, 1069, 18446744073709551615, 0, 1), - (13, 514, 1069, 1070, 18446744073709551615, 1, 2), - (13, 515, 1070, 1071, 18446744073709551615, 1, 3), - (13, 543, 1094, 1095, 18446744073709551615, 1, 6), - (13, 542, 1092, 1093, 18446744073709551615, 4, 6), - (13, 543, 1093, 1094, 18446744073709551615, 4, 6), - (13, 214, 982, 1101, 18446744073709551615, 0, 1), - (13, 214, 982, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 215, 18446744073709551615, 0, 1), - (13, 1024, 982, 214, 18446744073709551615, 52, 53), - (13, 213, 981, 1085, 18446744073709551615, 0, 1), - (13, 513, 1069, 1070, 18446744073709551615, 0, 1), - (13, 514, 1070, 1071, 18446744073709551615, 0, 2), - (13, 515, 1071, 1072, 18446744073709551615, 0, 3), - (13, 542, 1093, 1094, 18446744073709551615, 2, 6), - (13, 543, 1094, 1095, 18446744073709551615, 2, 6), - (13, 212, 980, 1099, 18446744073709551615, 1, 2), - (13, 213, 981, 1100, 18446744073709551615, 1, 2), - (13, 212, 980, 1101, 18446744073709551615, 2, 4), - (13, 213, 981, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 214, 18446744073709551615, 0, 1), - (13, 1024, 981, 213, 18446744073709551615, 53, 54), - (13, 1024, 980, 212, 18446744073709551615, 53, 55), - (13, 212, 980, 1084, 18446744073709551615, 1, 2), - (13, 513, 1069, 983, 18446744073709551615, 0, 1), - (13, 514, 983, 1070, 18446744073709551615, 0, 1), - (13, 515, 1070, 1071, 18446744073709551615, 2, 3), - (13, 543, 1093, 1094, 18446744073709551615, 5, 6), - (13, 211, 979, 1100, 18446744073709551615, 3, 4), - (13, 212, 980, 1101, 18446744073709551615, 3, 4), - (13, 211, 979, 1103, 18446744073709551615, 1, 2), - (13, 212, 980, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 213, 18446744073709551615, 0, 1), - (13, 1024, 980, 212, 18446744073709551615, 54, 55), - (13, 1024, 979, 211, 18446744073709551615, 54, 56), - (13, 211, 979, 1085, 18446744073709551615, 5, 6), - (14, 1024, 212, 980, 18446744073709551615, 0, 1), - (13, 513, 983, 1070, 18446744073709551615, 0, 1), - (13, 514, 1070, 1071, 18446744073709551615, 1, 2), - (13, 515, 1071, 1072, 18446744073709551615, 1, 3), - (13, 210, 978, 1101, 18446744073709551615, 0, 2), - (13, 211, 979, 1102, 18446744073709551615, 0, 1), - (13, 210, 978, 1105, 18446744073709551615, 0, 1), - (13, 211, 979, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 212, 18446744073709551615, 0, 1), - (13, 1024, 979, 211, 18446744073709551615, 55, 56), - (13, 1024, 978, 210, 18446744073709551615, 55, 57), - (13, 210, 978, 1086, 18446744073709551615, 1, 2), - (14, 1024, 211, 979, 18446744073709551615, 1, 2), - (13, 513, 1070, 1071, 18446744073709551615, 0, 1), - (13, 514, 1071, 1072, 18446744073709551615, 0, 2), - (13, 515, 1072, 1073, 18446744073709551615, 0, 3), - (13, 542, 1094, 1095, 18446744073709551615, 2, 6), - (13, 209, 977, 1100, 18446744073709551615, 1, 2), - (13, 210, 978, 1101, 18446744073709551615, 1, 2), - (13, 209, 977, 1101, 18446744073709551615, 2, 3), - (13, 210, 978, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 211, 18446744073709551615, 0, 1), - (13, 1024, 978, 210, 18446744073709551615, 56, 57), - (13, 209, 977, 1085, 18446744073709551615, 2, 3), - (13, 513, 1070, 980, 18446744073709551615, 0, 1), - (13, 514, 980, 1071, 18446744073709551615, 0, 1), - (13, 515, 1071, 1072, 18446744073709551615, 2, 3), - (13, 542, 1093, 1094, 18446744073709551615, 5, 6), - (13, 208, 976, 1102, 18446744073709551615, 0, 1), - (13, 209, 977, 1103, 18446744073709551615, 0, 1), - (13, 208, 976, 1103, 18446744073709551615, 1, 2), - (13, 209, 977, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 210, 18446744073709551615, 0, 1), - (13, 1024, 977, 209, 18446744073709551615, 57, 58), - (13, 1024, 976, 208, 18446744073709551615, 57, 59), - (13, 208, 976, 1086, 18446744073709551615, 1, 2), - (13, 513, 980, 1071, 18446744073709551615, 0, 1), - (13, 514, 1071, 1072, 18446744073709551615, 1, 2), - (13, 515, 1072, 1073, 18446744073709551615, 1, 3), - (13, 542, 1094, 1095, 18446744073709551615, 4, 6), - (13, 543, 1095, 1096, 18446744073709551615, 4, 6), - (13, 208, 976, 1104, 18446744073709551615, 0, 1), - (13, 208, 976, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 209, 18446744073709551615, 0, 1), - (13, 1024, 976, 208, 18446744073709551615, 58, 59), - (13, 207, 975, 1087, 18446744073709551615, 4, 5), - (13, 513, 1071, 1072, 18446744073709551615, 0, 1), - (13, 514, 1072, 1073, 18446744073709551615, 0, 2), - (13, 515, 1073, 1074, 18446744073709551615, 0, 3), - (13, 543, 1096, 1097, 18446744073709551615, 2, 6), - (13, 207, 975, 1103, 18446744073709551615, 1, 2), - (13, 207, 975, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 208, 18446744073709551615, 0, 1), - (13, 1024, 975, 207, 18446744073709551615, 59, 60), - (13, 206, 974, 1086, 18446744073709551615, 5, 6), - (13, 513, 1071, 977, 18446744073709551615, 0, 1), - (13, 514, 977, 1072, 18446744073709551615, 0, 1), - (13, 515, 1072, 1073, 18446744073709551615, 2, 3), - (13, 542, 1094, 1095, 18446744073709551615, 5, 6), - (13, 206, 974, 1104, 18446744073709551615, 1, 3), - (13, 206, 974, 1104, 18446744073709551615, 2, 3), - (13, 1024, 1104, 207, 18446744073709551615, 0, 1), - (13, 1024, 974, 206, 18446744073709551615, 60, 61), - (13, 205, 973, 1087, 18446744073709551615, 1, 2), - (13, 513, 977, 1072, 18446744073709551615, 0, 1), - (13, 514, 1072, 1073, 18446744073709551615, 1, 2), - (13, 515, 1073, 1074, 18446744073709551615, 1, 3), - (13, 542, 1095, 1096, 18446744073709551615, 4, 6), - (13, 543, 1096, 1097, 18446744073709551615, 4, 6), - (13, 204, 972, 1104, 18446744073709551615, 0, 2), - (13, 205, 973, 1105, 18446744073709551615, 0, 1), - (13, 204, 972, 1105, 18446744073709551615, 1, 2), - (13, 205, 973, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 206, 18446744073709551615, 0, 1), - (13, 1024, 973, 205, 18446744073709551615, 61, 62), - (13, 204, 972, 1088, 18446744073709551615, 0, 1), - (14, 1024, 205, 973, 18446744073709551615, 1, 2), - (13, 513, 1072, 1073, 18446744073709551615, 0, 1), - (13, 514, 1073, 1074, 18446744073709551615, 0, 2), - (13, 515, 1074, 1075, 18446744073709551615, 0, 3), - (13, 542, 1096, 1097, 18446744073709551615, 2, 6), - (13, 543, 1097, 1098, 18446744073709551615, 2, 6), - (13, 204, 972, 1104, 18446744073709551615, 1, 2), - (13, 204, 972, 1102, 18446744073709551615, 3, 4), - (13, 1024, 1102, 205, 18446744073709551615, 0, 1), - (13, 1024, 972, 204, 18446744073709551615, 62, 63), - (13, 513, 1072, 974, 18446744073709551615, 0, 1), - (13, 514, 974, 1073, 18446744073709551615, 0, 1), - (13, 515, 1073, 1074, 18446744073709551615, 2, 3), - (13, 542, 1095, 1096, 18446744073709551615, 5, 6), - (13, 543, 1096, 1097, 18446744073709551615, 5, 6), - (13, 203, 971, 1105, 18446744073709551615, 0, 1), - (13, 203, 971, 1104, 18446744073709551615, 2, 3), - (13, 1024, 1104, 204, 18446744073709551615, 0, 1), - (13, 1024, 971, 203, 18446744073709551615, 63, 64), - (13, 513, 974, 1073, 18446744073709551615, 0, 1), - (13, 514, 1073, 1074, 18446744073709551615, 1, 2), - (13, 515, 1074, 1075, 18446744073709551615, 1, 3), - (13, 202, 970, 1106, 18446744073709551615, 0, 2), - (13, 202, 970, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 203, 18446744073709551615, 0, 1), - (13, 1024, 970, 202, 18446744073709551615, 64, 65), - (13, 513, 1073, 1074, 18446744073709551615, 0, 1), - (13, 514, 1074, 1075, 18446744073709551615, 0, 2), - (13, 515, 1075, 1076, 18446744073709551615, 0, 3), - (13, 542, 1097, 1098, 18446744073709551615, 2, 6), - (13, 543, 1098, 1099, 18446744073709551615, 2, 6), - (13, 201, 969, 1105, 18446744073709551615, 2, 3), - (13, 201, 969, 1102, 18446744073709551615, 3, 4), - (13, 1024, 1102, 202, 18446744073709551615, 0, 1), - (13, 1024, 969, 201, 18446744073709551615, 65, 66), - (13, 513, 1073, 971, 18446744073709551615, 0, 1), - (13, 514, 971, 1074, 18446744073709551615, 0, 1), - (13, 515, 1074, 1075, 18446744073709551615, 2, 3), - (13, 542, 1096, 1097, 18446744073709551615, 5, 6), - (13, 543, 1097, 1098, 18446744073709551615, 5, 6), - (13, 200, 968, 1106, 18446744073709551615, 0, 1), - (13, 200, 968, 1104, 18446744073709551615, 3, 4), - (13, 1024, 1104, 201, 18446744073709551615, 0, 1), - (13, 1024, 968, 200, 18446744073709551615, 66, 67), - (14, 1024, 200, 968, 18446744073709551615, 0, 1), - (13, 513, 971, 1074, 18446744073709551615, 0, 1), - (13, 514, 1074, 1075, 18446744073709551615, 1, 2), - (13, 515, 1075, 1076, 18446744073709551615, 1, 3), - (13, 199, 967, 1107, 18446744073709551615, 0, 1), - (13, 199, 967, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 200, 18446744073709551615, 0, 1), - (13, 1024, 967, 199, 18446744073709551615, 67, 68), - (13, 513, 1074, 1075, 18446744073709551615, 0, 1), - (13, 514, 1075, 1076, 18446744073709551615, 0, 2), - (13, 515, 1076, 1077, 18446744073709551615, 0, 3), - (13, 198, 966, 1106, 18446744073709551615, 1, 2), - (13, 198, 966, 1102, 18446744073709551615, 4, 5), - (13, 1024, 1102, 199, 18446744073709551615, 0, 1), - (13, 1024, 966, 198, 18446744073709551615, 68, 69), - (13, 513, 1074, 968, 18446744073709551615, 0, 1), - (13, 514, 968, 1075, 18446744073709551615, 0, 1), - (13, 515, 1075, 1076, 18446744073709551615, 2, 3), - (13, 543, 1098, 1099, 18446744073709551615, 5, 6), - (13, 197, 965, 1108, 18446744073709551615, 1, 2), - (13, 197, 965, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 198, 18446744073709551615, 0, 1), - (13, 1024, 965, 197, 18446744073709551615, 69, 70), - (13, 513, 968, 1075, 18446744073709551615, 0, 1), - (13, 514, 1075, 1076, 18446744073709551615, 1, 2), - (13, 515, 1076, 1077, 18446744073709551615, 1, 3), - (13, 542, 1098, 1099, 18446744073709551615, 4, 6), - (13, 196, 964, 1109, 18446744073709551615, 0, 1), - (13, 196, 964, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 197, 18446744073709551615, 0, 1), - (13, 1024, 964, 196, 18446744073709551615, 70, 71), - (14, 1024, 196, 964, 18446744073709551615, 0, 1), - (13, 513, 1075, 1076, 18446744073709551615, 0, 1), - (13, 514, 1076, 1077, 18446744073709551615, 0, 2), - (13, 515, 1077, 1078, 18446744073709551615, 0, 3), - (13, 542, 1099, 1100, 18446744073709551615, 2, 6), - (13, 543, 1100, 1101, 18446744073709551615, 2, 6), - (13, 195, 963, 1108, 18446744073709551615, 1, 2), - (13, 195, 963, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 196, 18446744073709551615, 0, 1), - (13, 1024, 963, 195, 18446744073709551615, 71, 72), - (14, 1024, 195, 963, 18446744073709551615, 3, 4), - (13, 513, 1075, 965, 18446744073709551615, 0, 1), - (13, 514, 965, 1076, 18446744073709551615, 0, 1), - (13, 515, 1076, 1077, 18446744073709551615, 2, 3), - (13, 543, 1099, 1100, 18446744073709551615, 5, 6), - (13, 194, 962, 1109, 18446744073709551615, 0, 1), - (13, 194, 962, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 195, 18446744073709551615, 0, 1), - (13, 1024, 962, 194, 18446744073709551615, 72, 73), - (13, 193, 961, 1091, 18446744073709551615, 4, 5), - (14, 1024, 194, 962, 18446744073709551615, 0, 1), - (13, 513, 965, 1076, 18446744073709551615, 0, 1), - (13, 514, 1076, 1077, 18446744073709551615, 1, 2), - (13, 515, 1077, 1078, 18446744073709551615, 1, 3), - (13, 542, 1099, 1100, 18446744073709551615, 4, 6), - (13, 193, 961, 1110, 18446744073709551615, 1, 2), - (13, 193, 961, 1106, 18446744073709551615, 2, 3), - (13, 1024, 1106, 194, 18446744073709551615, 0, 1), - (13, 1024, 961, 193, 18446744073709551615, 73, 74), - (13, 513, 1076, 1077, 18446744073709551615, 0, 1), - (13, 514, 1077, 1078, 18446744073709551615, 0, 2), - (13, 515, 1078, 1079, 18446744073709551615, 0, 3), - (13, 543, 1101, 1102, 18446744073709551615, 2, 6), - (13, 192, 960, 1109, 18446744073709551615, 2, 3), - (13, 192, 960, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 193, 18446744073709551615, 0, 1), - (13, 1024, 960, 192, 18446744073709551615, 74, 75), - (14, 1024, 192, 960, 18446744073709551615, 0, 1), - (13, 513, 1076, 962, 18446744073709551615, 0, 1), - (13, 514, 962, 1077, 18446744073709551615, 0, 1), - (13, 515, 1077, 1078, 18446744073709551615, 2, 3), - (13, 542, 1099, 1100, 18446744073709551615, 5, 6), - (13, 191, 959, 1111, 18446744073709551615, 0, 1), - (13, 191, 959, 1104, 18446744073709551615, 3, 4), - (13, 1024, 1104, 192, 18446744073709551615, 0, 1), - (13, 1024, 959, 191, 18446744073709551615, 75, 76), - (13, 513, 962, 1077, 18446744073709551615, 0, 1), - (13, 514, 1077, 1078, 18446744073709551615, 1, 2), - (13, 515, 1078, 1079, 18446744073709551615, 1, 3), - (13, 542, 1100, 1101, 18446744073709551615, 4, 6), - (13, 543, 1101, 1102, 18446744073709551615, 4, 6), - (13, 190, 958, 1112, 18446744073709551615, 0, 1), - (13, 190, 958, 1106, 18446744073709551615, 0, 1), - (13, 1024, 1106, 191, 18446744073709551615, 0, 1), - (13, 1024, 958, 190, 18446744073709551615, 76, 77), - (13, 513, 1077, 1078, 18446744073709551615, 0, 1), - (13, 514, 1078, 1079, 18446744073709551615, 0, 2), - (13, 515, 1079, 1080, 18446744073709551615, 0, 3), - (13, 189, 957, 1112, 18446744073709551615, 0, 1), - (13, 189, 957, 1102, 18446744073709551615, 4, 5), - (13, 1024, 1102, 190, 18446744073709551615, 0, 1), - (13, 1024, 957, 189, 18446744073709551615, 77, 78), - (13, 513, 1077, 959, 18446744073709551615, 0, 1), - (13, 514, 959, 1078, 18446744073709551615, 0, 1), - (13, 515, 1078, 1079, 18446744073709551615, 2, 3), - (13, 542, 1100, 1101, 18446744073709551615, 5, 6), - (13, 543, 1101, 1102, 18446744073709551615, 5, 6), - (13, 188, 956, 1112, 18446744073709551615, 0, 1), - (13, 188, 956, 1104, 18446744073709551615, 1, 2), - (13, 1024, 1104, 189, 18446744073709551615, 0, 1), - (13, 1024, 956, 188, 18446744073709551615, 78, 79), - (13, 513, 959, 1078, 18446744073709551615, 0, 1), - (13, 514, 1078, 1079, 18446744073709551615, 1, 2), - (13, 515, 1079, 1080, 18446744073709551615, 1, 3), - (13, 542, 1101, 1102, 18446744073709551615, 4, 6), - (13, 543, 1102, 1103, 18446744073709551615, 4, 6), - (13, 187, 955, 1112, 18446744073709551615, 1, 2), - (13, 187, 955, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 188, 18446744073709551615, 0, 1), - (13, 1024, 955, 187, 18446744073709551615, 79, 80), - (13, 513, 1078, 1079, 18446744073709551615, 0, 1), - (13, 514, 1079, 1080, 18446744073709551615, 0, 2), - (13, 515, 1080, 1081, 18446744073709551615, 0, 3), - (13, 186, 954, 1112, 18446744073709551615, 0, 1), - (13, 186, 954, 1102, 18446744073709551615, 2, 3), - (13, 1024, 1102, 187, 18446744073709551615, 0, 1), - (13, 1024, 954, 186, 18446744073709551615, 80, 81), - (13, 513, 1078, 956, 18446744073709551615, 0, 1), - (13, 514, 956, 1079, 18446744073709551615, 0, 1), - (13, 515, 1079, 1080, 18446744073709551615, 2, 3), - (13, 542, 1101, 1102, 18446744073709551615, 5, 6), - (13, 543, 1102, 1103, 18446744073709551615, 5, 6), - (13, 185, 953, 1113, 18446744073709551615, 0, 1), - (13, 185, 953, 1104, 18446744073709551615, 2, 3), - (13, 1024, 1104, 186, 18446744073709551615, 0, 1), - (13, 1024, 953, 185, 18446744073709551615, 81, 82), - (13, 513, 956, 1079, 18446744073709551615, 0, 1), - (13, 514, 1079, 1080, 18446744073709551615, 1, 2), - (13, 515, 1080, 1081, 18446744073709551615, 1, 3), - (13, 542, 1102, 1103, 18446744073709551615, 4, 6), - (13, 543, 1103, 1104, 18446744073709551615, 4, 6), - (13, 184, 952, 1115, 18446744073709551615, 1, 2), - (13, 184, 952, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 185, 18446744073709551615, 0, 1), - (13, 1024, 952, 184, 18446744073709551615, 82, 83), - (13, 513, 1079, 1080, 18446744073709551615, 0, 1), - (13, 514, 1080, 1081, 18446744073709551615, 0, 2), - (13, 515, 1081, 1082, 18446744073709551615, 0, 3), - (13, 543, 1104, 1105, 18446744073709551615, 2, 6), - (13, 183, 951, 1114, 18446744073709551615, 2, 3), - (13, 183, 951, 1102, 18446744073709551615, 3, 4), - (13, 1024, 1102, 184, 18446744073709551615, 0, 1), - (13, 1024, 951, 183, 18446744073709551615, 83, 84), - (13, 513, 1079, 953, 18446744073709551615, 0, 1), - (13, 514, 953, 1080, 18446744073709551615, 0, 1), - (13, 515, 1080, 1081, 18446744073709551615, 2, 3), - (13, 543, 1103, 1104, 18446744073709551615, 5, 6), - (13, 182, 950, 1116, 18446744073709551615, 0, 1), - (13, 182, 950, 1104, 18446744073709551615, 2, 3), - (13, 1024, 1104, 183, 18446744073709551615, 0, 1), - (13, 1024, 950, 182, 18446744073709551615, 84, 85), - (13, 513, 953, 1080, 18446744073709551615, 0, 1), - (13, 514, 1080, 1081, 18446744073709551615, 1, 2), - (13, 515, 1081, 1082, 18446744073709551615, 1, 3), - (13, 542, 1103, 1104, 18446744073709551615, 4, 6), - (13, 181, 949, 1115, 18446744073709551615, 1, 2), - (13, 181, 949, 1106, 18446744073709551615, 2, 3), - (13, 1024, 1106, 182, 18446744073709551615, 0, 1), - (13, 1024, 949, 181, 18446744073709551615, 85, 86), - (14, 1024, 181, 949, 18446744073709551615, 3, 4), - (13, 513, 1080, 1081, 18446744073709551615, 0, 1), - (13, 514, 1081, 1082, 18446744073709551615, 0, 2), - (13, 515, 1082, 1083, 18446744073709551615, 0, 3), - (13, 542, 1104, 1105, 18446744073709551615, 2, 6), - (13, 180, 948, 1114, 18446744073709551615, 2, 3), - (13, 180, 948, 1102, 18446744073709551615, 3, 4), - (13, 1024, 1102, 181, 18446744073709551615, 0, 1), - (13, 1024, 948, 180, 18446744073709551615, 86, 87), - (14, 1024, 180, 948, 18446744073709551615, 0, 1), - (13, 513, 1080, 950, 18446744073709551615, 0, 1), - (13, 514, 950, 1081, 18446744073709551615, 0, 1), - (13, 515, 1081, 1082, 18446744073709551615, 2, 3), - (13, 543, 1104, 1105, 18446744073709551615, 5, 6), - (13, 179, 947, 1116, 18446744073709551615, 0, 1), - (13, 179, 947, 1104, 18446744073709551615, 3, 4), - (13, 1024, 1104, 180, 18446744073709551615, 0, 1), - (13, 1024, 947, 179, 18446744073709551615, 87, 88), - (13, 513, 950, 1081, 18446744073709551615, 0, 1), - (13, 514, 1081, 1082, 18446744073709551615, 1, 2), - (13, 515, 1082, 1083, 18446744073709551615, 1, 3), - (13, 542, 1104, 1105, 18446744073709551615, 4, 6), - (13, 178, 946, 1117, 18446744073709551615, 1, 2), - (13, 178, 946, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 179, 18446744073709551615, 0, 1), - (13, 1024, 946, 178, 18446744073709551615, 88, 89), - (13, 513, 1081, 1082, 18446744073709551615, 0, 1), - (13, 514, 1082, 1083, 18446744073709551615, 0, 2), - (13, 515, 1083, 1084, 18446744073709551615, 0, 3), - (13, 542, 1105, 1106, 18446744073709551615, 2, 6), - (13, 543, 1106, 1107, 18446744073709551615, 2, 6), - (13, 177, 945, 1116, 18446744073709551615, 2, 3), - (13, 177, 945, 1102, 18446744073709551615, 4, 5), - (13, 1024, 1102, 178, 18446744073709551615, 0, 1), - (13, 1024, 945, 177, 18446744073709551615, 89, 90), - (14, 1024, 177, 945, 18446744073709551615, 3, 4), - (13, 513, 1081, 947, 18446744073709551615, 0, 1), - (13, 514, 947, 1082, 18446744073709551615, 0, 1), - (13, 515, 1082, 1083, 18446744073709551615, 2, 3), - (13, 543, 1106, 1107, 18446744073709551615, 3, 6), - (13, 543, 1105, 1106, 18446744073709551615, 5, 6), - (13, 176, 944, 1117, 18446744073709551615, 0, 1), - (13, 176, 944, 1104, 18446744073709551615, 2, 3), - (13, 1024, 1104, 177, 18446744073709551615, 0, 1), - (13, 1024, 944, 176, 18446744073709551615, 90, 91), - (13, 513, 947, 1082, 18446744073709551615, 0, 1), - (13, 514, 1082, 1083, 18446744073709551615, 1, 2), - (13, 515, 1083, 1084, 18446744073709551615, 1, 3), - (13, 542, 1105, 1106, 18446744073709551615, 4, 6), - (13, 543, 1106, 1107, 18446744073709551615, 4, 6), - (13, 175, 943, 1118, 18446744073709551615, 0, 1), - (13, 175, 943, 1106, 18446744073709551615, 3, 4), - (13, 1024, 1106, 176, 18446744073709551615, 0, 1), - (13, 1024, 943, 175, 18446744073709551615, 91, 92), - (13, 513, 1082, 1083, 18446744073709551615, 0, 1), - (13, 514, 1083, 1084, 18446744073709551615, 0, 2), - (13, 515, 1084, 1085, 18446744073709551615, 0, 2), - (13, 174, 942, 1117, 18446744073709551615, 1, 2), - (13, 174, 942, 1102, 18446744073709551615, 3, 4), - (13, 1024, 1102, 175, 18446744073709551615, 0, 1), - (13, 1024, 942, 174, 18446744073709551615, 92, 93), - (13, 513, 1082, 944, 18446744073709551615, 0, 1), - (13, 514, 944, 1083, 18446744073709551615, 0, 1), - (13, 515, 1083, 1084, 18446744073709551615, 2, 3), - (13, 542, 1105, 1106, 18446744073709551615, 5, 6), - (13, 543, 1106, 1107, 18446744073709551615, 5, 6), - (13, 173, 941, 1119, 18446744073709551615, 0, 1), - (13, 173, 941, 1104, 18446744073709551615, 4, 5), - (13, 1024, 1104, 174, 18446744073709551615, 0, 1), - (13, 1024, 941, 173, 18446744073709551615, 93, 94), - (13, 513, 944, 1083, 18446744073709551615, 0, 1), - (13, 514, 1083, 1084, 18446744073709551615, 1, 2), - (13, 515, 1084, 1085, 18446744073709551615, 1, 2), - (13, 543, 1107, 1108, 18446744073709551615, 4, 7), - (13, 172, 940, 1119, 18446744073709551615, 1, 2), - (13, 172, 940, 1106, 18446744073709551615, 3, 4), - (13, 1024, 1106, 173, 18446744073709551615, 0, 1), - (13, 1024, 940, 172, 18446744073709551615, 94, 96), - (13, 513, 1083, 1084, 18446744073709551615, 0, 1), - (13, 514, 1084, 1085, 18446744073709551615, 0, 1), - (13, 515, 1085, 1086, 18446744073709551615, 0, 2), - (13, 543, 1108, 1109, 18446744073709551615, 2, 9), - (13, 171, 939, 1121, 18446744073709551615, 0, 1), - (13, 172, 940, 1122, 18446744073709551615, 0, 1), - (13, 171, 939, 1108, 18446744073709551615, 1, 2), - (13, 172, 940, 1109, 18446744073709551615, 1, 2), - (13, 1024, 1109, 173, 18446744073709551615, 0, 1), - (13, 1024, 940, 172, 18446744073709551615, 95, 96), - (13, 1024, 939, 171, 18446744073709551615, 95, 97), - (13, 171, 939, 1100, 18446744073709551615, 0, 1), - (14, 1024, 172, 940, 18446744073709551615, 1, 2), - (13, 513, 1084, 1085, 18446744073709551615, 0, 1), - (13, 514, 1085, 1086, 18446744073709551615, 0, 3), - (13, 515, 1086, 1087, 18446744073709551615, 0, 5), - (13, 542, 1108, 1109, 18446744073709551615, 1, 10), - (13, 543, 1109, 1110, 18446744073709551615, 1, 10), - (13, 170, 938, 1121, 18446744073709551615, 3, 4), - (13, 171, 939, 1122, 18446744073709551615, 3, 4), - (13, 170, 938, 1110, 18446744073709551615, 0, 1), - (13, 171, 939, 1111, 18446744073709551615, 0, 1), - (13, 1024, 1111, 172, 18446744073709551615, 0, 1), - (13, 1024, 939, 171, 18446744073709551615, 96, 97), - (13, 1024, 938, 170, 18446744073709551615, 96, 97), - (13, 170, 938, 1101, 18446744073709551615, 5, 6), - (14, 1024, 171, 939, 18446744073709551615, 3, 4), - (13, 513, 1085, 1086, 18446744073709551615, 0, 2), - (13, 514, 1086, 1087, 18446744073709551615, 0, 4), - (13, 515, 1087, 1088, 18446744073709551615, 0, 4), - (13, 542, 1109, 1110, 18446744073709551615, 1, 9), - (13, 543, 1110, 1111, 18446744073709551615, 1, 9), - (13, 169, 937, 1120, 18446744073709551615, 4, 5), - (13, 169, 937, 1106, 18446744073709551615, 2, 3), - (13, 1024, 1106, 170, 18446744073709551615, 0, 1), - (13, 1024, 937, 169, 18446744073709551615, 97, 98), - (13, 513, 940, 1085, 18446744073709551615, 0, 1), - (13, 514, 1085, 1086, 18446744073709551615, 1, 3), - (13, 515, 1086, 1087, 18446744073709551615, 1, 5), - (13, 543, 1109, 1110, 18446744073709551615, 2, 10), - (13, 168, 936, 1119, 18446744073709551615, 5, 6), - (13, 168, 936, 1102, 18446744073709551615, 4, 5), - (13, 1024, 1102, 169, 18446744073709551615, 0, 1), - (13, 1024, 936, 168, 18446744073709551615, 98, 99), - (13, 513, 940, 171, 18446744073709551615, 0, 1), - (13, 514, 171, 1085, 18446744073709551615, 0, 1), - (13, 515, 1085, 1086, 18446744073709551615, 1, 2), - (13, 543, 1109, 1110, 18446744073709551615, 3, 10), - (13, 542, 1107, 1108, 18446744073709551615, 3, 9), - (13, 167, 935, 1122, 18446744073709551615, 3, 4), - (13, 167, 935, 1104, 18446744073709551615, 3, 4), - (13, 1024, 1104, 168, 18446744073709551615, 0, 1), - (13, 1024, 935, 167, 18446744073709551615, 99, 100), - (13, 513, 171, 1085, 18446744073709551615, 0, 1), - (13, 514, 1085, 1086, 18446744073709551615, 2, 3), - (13, 515, 1086, 1087, 18446744073709551615, 2, 5), - (13, 542, 1108, 1109, 18446744073709551615, 4, 10), - (13, 543, 1109, 1110, 18446744073709551615, 4, 10), - (13, 166, 934, 1122, 18446744073709551615, 0, 1), - (13, 166, 934, 1106, 18446744073709551615, 1, 2), - (13, 1024, 1106, 167, 18446744073709551615, 0, 1), - (13, 1024, 934, 166, 18446744073709551615, 100, 101), - (13, 513, 1085, 1086, 18446744073709551615, 1, 2), - (13, 514, 1086, 1087, 18446744073709551615, 1, 4), - (13, 515, 1087, 1088, 18446744073709551615, 1, 4), - (13, 543, 1110, 1111, 18446744073709551615, 4, 9), - (13, 165, 933, 1121, 18446744073709551615, 1, 2), - (13, 165, 933, 1102, 18446744073709551615, 4, 5), - (13, 1024, 1102, 166, 18446744073709551615, 0, 1), - (13, 1024, 933, 165, 18446744073709551615, 101, 102), - (13, 513, 1085, 935, 18446744073709551615, 0, 2), - (13, 514, 935, 1086, 18446744073709551615, 0, 3), - (13, 515, 1086, 1087, 18446744073709551615, 3, 5), - (13, 1024, 1097, 164, 18446744073709551615, 0, 1), - (13, 513, 934, 1085, 18446744073709551615, 0, 2), - (13, 514, 1085, 935, 18446744073709551615, 0, 2), - (13, 515, 935, 1086, 18446744073709551615, 0, 3), - (13, 542, 1107, 1108, 18446744073709551615, 4, 9), - (13, 1024, 1092, 162, 18446744073709551615, 0, 1), - (13, 513, 165, 934, 18446744073709551615, 0, 1), - (13, 514, 934, 1085, 18446744073709551615, 0, 1), - (13, 515, 1085, 935, 18446744073709551615, 0, 1), - (13, 543, 1107, 1108, 18446744073709551615, 5, 7), - (13, 161, 929, 1120, 18446744073709551615, 3, 4), - (13, 161, 929, 1095, 18446744073709551615, 8, 9), - (13, 1024, 1095, 162, 18446744073709551615, 0, 1), - (13, 1024, 929, 161, 18446744073709551615, 104, 105), - (13, 513, 934, 1085, 18446744073709551615, 1, 2), - (13, 514, 1085, 935, 18446744073709551615, 1, 2), - (13, 515, 935, 1086, 18446744073709551615, 1, 3), - (13, 543, 1108, 1109, 18446744073709551615, 6, 9), - (13, 1024, 1097, 161, 18446744073709551615, 0, 1), - (13, 513, 1085, 935, 18446744073709551615, 1, 2), - (13, 514, 935, 1086, 18446744073709551615, 1, 3), - (13, 515, 1086, 1087, 18446744073709551615, 4, 5), - (13, 542, 1108, 1109, 18446744073709551615, 8, 10), - (13, 159, 927, 1122, 18446744073709551615, 3, 4), - (13, 159, 927, 1099, 18446744073709551615, 2, 3), - (13, 1024, 1099, 160, 18446744073709551615, 0, 1), - (13, 1024, 927, 159, 18446744073709551615, 106, 107), - (13, 513, 935, 1086, 18446744073709551615, 0, 1), - (13, 514, 1086, 1087, 18446744073709551615, 2, 4), - (13, 515, 1087, 1088, 18446744073709551615, 2, 4), - (13, 543, 1110, 1111, 18446744073709551615, 7, 9), - (13, 1024, 1088, 158, 18446744073709551615, 0, 1), - (13, 513, 160, 934, 18446744073709551615, 0, 1), - (13, 514, 934, 935, 18446744073709551615, 0, 1), - (13, 515, 935, 928, 18446744073709551615, 0, 1), - (13, 542, 1106, 1107, 18446744073709551615, 6, 7), - (13, 157, 925, 1122, 18446744073709551615, 3, 4), - (13, 157, 925, 1097, 18446744073709551615, 4, 5), - (13, 1024, 1097, 159, 18446744073709551615, 0, 1), - (13, 1024, 925, 157, 18446744073709551615, 108, 109), - (13, 513, 928, 1086, 18446744073709551615, 0, 1), - (13, 514, 1086, 1087, 18446744073709551615, 3, 4), - (13, 515, 1087, 1088, 18446744073709551615, 3, 4), - (13, 542, 1109, 1110, 18446744073709551615, 8, 9), - (13, 156, 924, 1123, 18446744073709551615, 3, 4), - (13, 156, 924, 1099, 18446744073709551615, 2, 3), - (13, 1024, 1099, 157, 18446744073709551615, 0, 1), - (13, 1024, 924, 156, 18446744073709551615, 109, 110), - (13, 513, 1086, 1087, 18446744073709551615, 0, 1), - (13, 514, 1087, 1088, 18446744073709551615, 0, 2), - (13, 515, 1088, 1089, 18446744073709551615, 0, 3), - (13, 1024, 1088, 155, 18446744073709551615, 0, 1), - (13, 513, 157, 935, 18446744073709551615, 0, 1), - (13, 514, 935, 1086, 18446744073709551615, 2, 3), - (13, 515, 1086, 925, 18446744073709551615, 0, 1), - (13, 543, 1108, 1109, 18446744073709551615, 8, 9), - (13, 154, 922, 1124, 18446744073709551615, 0, 1), - (13, 154, 922, 1097, 18446744073709551615, 4, 5), - (13, 1024, 1097, 156, 18446744073709551615, 0, 1), - (13, 1024, 922, 154, 18446744073709551615, 111, 112), - (13, 513, 925, 1087, 18446744073709551615, 0, 1), - (13, 514, 1087, 1088, 18446744073709551615, 1, 2), - (13, 515, 1088, 1089, 18446744073709551615, 1, 3), - (13, 542, 1110, 1111, 18446744073709551615, 5, 8), - (13, 543, 1111, 1112, 18446744073709551615, 5, 8), - (13, 153, 921, 1124, 18446744073709551615, 3, 4), - (13, 153, 921, 1099, 18446744073709551615, 1, 2), - (13, 1024, 1099, 154, 18446744073709551615, 0, 1), - (13, 1024, 921, 153, 18446744073709551615, 112, 113), - (13, 513, 1087, 1088, 18446744073709551615, 0, 1), - (13, 514, 1088, 1089, 18446744073709551615, 0, 2), - (13, 515, 1089, 1090, 18446744073709551615, 0, 6), - (13, 542, 1111, 1112, 18446744073709551615, 2, 10), - (13, 152, 920, 1124, 18446744073709551615, 0, 1), - (13, 152, 920, 1095, 18446744073709551615, 6, 7), - (13, 1024, 1095, 153, 18446744073709551615, 0, 1), - (13, 1024, 920, 152, 18446744073709551615, 113, 114), - (13, 513, 1087, 922, 18446744073709551615, 0, 1), - (13, 514, 922, 1088, 18446744073709551615, 0, 1), - (13, 515, 1088, 1089, 18446744073709551615, 2, 3), - (13, 542, 1110, 1111, 18446744073709551615, 6, 8), - (13, 151, 919, 1125, 18446744073709551615, 0, 1), - (13, 151, 919, 1097, 18446744073709551615, 3, 4), - (13, 1024, 1097, 152, 18446744073709551615, 0, 1), - (13, 1024, 919, 151, 18446744073709551615, 114, 115), - (13, 513, 922, 1088, 18446744073709551615, 0, 1), - (13, 514, 1088, 1089, 18446744073709551615, 1, 2), - (13, 515, 1089, 1090, 18446744073709551615, 1, 6), - (13, 543, 1113, 1114, 18446744073709551615, 1, 9), - (13, 543, 1112, 1113, 18446744073709551615, 4, 10), - (13, 150, 918, 1126, 18446744073709551615, 0, 1), - (13, 150, 918, 1099, 18446744073709551615, 2, 3), - (13, 1024, 1099, 151, 18446744073709551615, 0, 1), - (13, 1024, 918, 150, 18446744073709551615, 115, 116), - (13, 513, 1088, 1089, 18446744073709551615, 0, 1), - (13, 514, 1089, 1090, 18446744073709551615, 0, 3), - (13, 515, 1090, 1091, 18446744073709551615, 0, 3), - (13, 543, 1113, 1114, 18446744073709551615, 2, 9), - (13, 149, 917, 1125, 18446744073709551615, 1, 2), - (13, 149, 917, 1095, 18446744073709551615, 5, 6), - (13, 1024, 1095, 150, 18446744073709551615, 0, 1), - (13, 1024, 917, 149, 18446744073709551615, 116, 117), - (13, 513, 1088, 919, 18446744073709551615, 0, 1), - (13, 514, 919, 1089, 18446744073709551615, 0, 3), - (13, 515, 1089, 1090, 18446744073709551615, 2, 6), - (13, 542, 1111, 1112, 18446744073709551615, 5, 10), - (13, 543, 1112, 1113, 18446744073709551615, 5, 10), - (13, 148, 916, 1126, 18446744073709551615, 0, 1), - (13, 148, 916, 1097, 18446744073709551615, 4, 5), - (13, 1024, 1097, 149, 18446744073709551615, 0, 1), - (13, 1024, 916, 148, 18446744073709551615, 117, 118), - (13, 513, 919, 1089, 18446744073709551615, 0, 2), - (13, 514, 1089, 1090, 18446744073709551615, 1, 3), - (13, 515, 1090, 1091, 18446744073709551615, 1, 3), - (13, 542, 1112, 1113, 18446744073709551615, 4, 9), - (13, 543, 1113, 1114, 18446744073709551615, 4, 9), - (13, 1024, 1092, 147, 18446744073709551615, 0, 1), - (13, 513, 917, 919, 18446744073709551615, 0, 1), - (13, 514, 919, 1089, 18446744073709551615, 1, 3), - (13, 515, 1089, 1090, 18446744073709551615, 3, 6), - (13, 1024, 919, 146, 18446744073709551615, 0, 1), - (13, 513, 917, 148, 18446744073709551615, 0, 1), - (13, 514, 148, 919, 18446744073709551615, 0, 1), - (13, 515, 919, 1089, 18446744073709551615, 0, 1), - (13, 542, 1110, 1111, 18446744073709551615, 7, 8), - (13, 1024, 1090, 145, 18446744073709551615, 0, 1), - (13, 513, 148, 919, 18446744073709551615, 0, 1), - (13, 514, 919, 1089, 18446744073709551615, 2, 3), - (13, 515, 1089, 1090, 18446744073709551615, 4, 6), - (13, 543, 1113, 1114, 18446744073709551615, 6, 9), - (13, 1024, 1092, 144, 18446744073709551615, 0, 1), - (13, 513, 919, 1089, 18446744073709551615, 1, 2), - (13, 514, 1089, 1090, 18446744073709551615, 2, 3), - (13, 515, 1090, 1091, 18446744073709551615, 2, 3), - (13, 542, 1112, 1113, 18446744073709551615, 7, 9), - (13, 543, 1113, 1114, 18446744073709551615, 7, 9), - (13, 1024, 912, 143, 18446744073709551615, 0, 1), - (13, 513, 919, 912, 18446744073709551615, 0, 1), - (13, 514, 912, 1089, 18446744073709551615, 0, 1), - (13, 515, 1089, 1090, 18446744073709551615, 5, 6), - (13, 542, 1111, 1112, 18446744073709551615, 9, 10), - (13, 543, 1112, 1113, 18446744073709551615, 9, 10), - (13, 142, 910, 1129, 18446744073709551615, 3, 4), - (13, 142, 910, 1097, 18446744073709551615, 4, 5), - (13, 1024, 1097, 911, 18446744073709551615, 0, 1), - (13, 1024, 910, 142, 18446744073709551615, 123, 124), - (13, 513, 1090, 1091, 18446744073709551615, 0, 1), - (13, 514, 1091, 1092, 18446744073709551615, 0, 1), - (13, 515, 1092, 1093, 18446744073709551615, 0, 2), - (13, 542, 1114, 1115, 18446744073709551615, 0, 6), - (13, 543, 1115, 1116, 18446744073709551615, 0, 6), - (13, 141, 909, 1129, 18446744073709551615, 0, 1), - (13, 141, 909, 1099, 18446744073709551615, 0, 1), - (13, 1024, 1099, 142, 18446744073709551615, 0, 1), - (13, 513, 1091, 1092, 18446744073709551615, 0, 1), - (13, 514, 1092, 1093, 18446744073709551615, 0, 1), - (13, 515, 1093, 1094, 18446744073709551615, 0, 2), - (13, 543, 1116, 1117, 18446744073709551615, 1, 4), - (13, 140, 908, 1128, 18446744073709551615, 1, 2), - (13, 140, 908, 1095, 18446744073709551615, 6, 7), - (13, 1024, 1095, 141, 18446744073709551615, 0, 1), - (13, 1024, 908, 140, 18446744073709551615, 125, 126), - (13, 513, 1091, 910, 18446744073709551615, 0, 1), - (13, 514, 910, 1092, 18446744073709551615, 0, 1), - (13, 515, 1092, 1093, 18446744073709551615, 1, 2), - (13, 543, 1115, 1116, 18446744073709551615, 1, 6), - (13, 1024, 1091, 139, 18446744073709551615, 0, 1), - (13, 513, 909, 1091, 18446744073709551615, 0, 1), - (13, 514, 1091, 910, 18446744073709551615, 0, 1), - (13, 515, 910, 1092, 18446744073709551615, 0, 1), - (13, 138, 906, 1130, 18446744073709551615, 0, 1), - (13, 138, 906, 1099, 18446744073709551615, 4, 5), - (13, 1024, 1099, 140, 18446744073709551615, 0, 1), - (13, 1024, 906, 138, 18446744073709551615, 127, 128), - (13, 513, 1092, 1093, 18446744073709551615, 0, 1), - (13, 514, 1093, 1094, 18446744073709551615, 0, 2), - (13, 515, 1094, 1095, 18446744073709551615, 0, 3), - (13, 542, 1116, 1117, 18446744073709551615, 1, 7), - (13, 137, 905, 1129, 18446744073709551615, 1, 2), - (13, 137, 905, 1095, 18446744073709551615, 2, 3), - (13, 1024, 1095, 138, 18446744073709551615, 0, 1), - (13, 1024, 905, 137, 18446744073709551615, 128, 129), - (13, 513, 1092, 909, 18446744073709551615, 0, 1), - (13, 514, 909, 1093, 18446744073709551615, 0, 1), - (13, 515, 1093, 1094, 18446744073709551615, 1, 2), - (13, 542, 1115, 1116, 18446744073709551615, 3, 4), - (13, 136, 904, 1130, 18446744073709551615, 0, 1), - (13, 136, 904, 1097, 18446744073709551615, 6, 7), - (13, 1024, 1097, 137, 18446744073709551615, 0, 1), - (13, 1024, 904, 136, 18446744073709551615, 129, 130), - (13, 513, 909, 1093, 18446744073709551615, 0, 1), - (13, 514, 1093, 1094, 18446744073709551615, 1, 2), - (13, 515, 1094, 1095, 18446744073709551615, 1, 3), - (13, 543, 1118, 1119, 18446744073709551615, 1, 10), - (13, 543, 1117, 1118, 18446744073709551615, 3, 6), - (13, 135, 903, 1131, 18446744073709551615, 0, 1), - (13, 135, 903, 1099, 18446744073709551615, 0, 1), - (13, 513, 1093, 1094, 18446744073709551615, 0, 1), - (13, 514, 1094, 1095, 18446744073709551615, 0, 2), - (13, 515, 1095, 1096, 18446744073709551615, 0, 7), - (13, 542, 1117, 1118, 18446744073709551615, 2, 10), - (13, 543, 1118, 1119, 18446744073709551615, 2, 10), - (13, 134, 902, 1131, 18446744073709551615, 3, 4), - (13, 134, 902, 1095, 18446744073709551615, 8, 9), - (13, 1024, 1095, 135, 18446744073709551615, 0, 1), - (13, 1024, 902, 134, 18446744073709551615, 131, 132), - (13, 513, 1093, 904, 18446744073709551615, 0, 1), - (13, 514, 904, 1094, 18446744073709551615, 0, 1), - (13, 515, 1094, 1095, 18446744073709551615, 2, 3), - (13, 543, 1117, 1118, 18446744073709551615, 4, 6), - (13, 133, 901, 1132, 18446744073709551615, 3, 4), - (13, 133, 901, 1097, 18446744073709551615, 2, 3), - (13, 1024, 1097, 134, 18446744073709551615, 0, 1), - (13, 1024, 901, 133, 18446744073709551615, 132, 133), - (13, 513, 904, 1094, 18446744073709551615, 0, 1), - (13, 514, 1094, 1095, 18446744073709551615, 1, 2), - (13, 515, 1095, 1096, 18446744073709551615, 1, 7), - (13, 543, 1118, 1119, 18446744073709551615, 4, 10), - (13, 132, 900, 1133, 18446744073709551615, 3, 4), - (13, 132, 900, 1099, 18446744073709551615, 4, 5), - (13, 1024, 1099, 133, 18446744073709551615, 0, 1), - (13, 1024, 900, 132, 18446744073709551615, 133, 134), - (13, 513, 1094, 1095, 18446744073709551615, 0, 1), - (13, 514, 1095, 1096, 18446744073709551615, 0, 4), - (13, 515, 1096, 1097, 18446744073709551615, 0, 4), - (13, 543, 1119, 1120, 18446744073709551615, 2, 10), - (13, 131, 899, 1132, 18446744073709551615, 4, 5), - (13, 131, 899, 1095, 18446744073709551615, 4, 5), - (13, 1024, 1095, 132, 18446744073709551615, 0, 1), - (13, 1024, 899, 131, 18446744073709551615, 134, 135), - (13, 513, 1094, 901, 18446744073709551615, 0, 1), - (13, 514, 901, 1095, 18446744073709551615, 0, 3), - (13, 515, 1095, 1096, 18446744073709551615, 2, 7), - (13, 130, 898, 1132, 18446744073709551615, 0, 1), - (13, 130, 898, 1097, 18446744073709551615, 6, 7), - (13, 513, 901, 1095, 18446744073709551615, 0, 2), - (13, 514, 1095, 1096, 18446744073709551615, 1, 4), - (13, 515, 1096, 1097, 18446744073709551615, 1, 4), - (13, 543, 1119, 1120, 18446744073709551615, 4, 10), - (13, 1024, 898, 129, 18446744073709551615, 0, 1), - (13, 513, 899, 901, 18446744073709551615, 0, 1), - (13, 514, 901, 1095, 18446744073709551615, 1, 3), - (13, 515, 1095, 1096, 18446744073709551615, 3, 7), - (13, 542, 1117, 1118, 18446744073709551615, 6, 10), - (13, 1024, 1150, 768, 18446744073709551615, 136, 145), - (13, 513, 899, 130, 18446744073709551615, 0, 1), - (13, 514, 130, 901, 18446744073709551615, 0, 1), - (13, 515, 901, 1095, 18446744073709551615, 0, 1), - (13, 543, 1118, 1119, 18446744073709551615, 7, 10), - (13, 542, 1116, 1117, 18446744073709551615, 5, 7), - (13, 1024, 895, 127, 18446744073709551615, 138, 139), - (13, 513, 130, 901, 18446744073709551615, 0, 1), - (13, 514, 901, 1095, 18446744073709551615, 2, 3), - (13, 515, 1095, 1096, 18446744073709551615, 4, 7), - (13, 542, 1117, 1118, 18446744073709551615, 8, 10), - (13, 543, 1118, 1119, 18446744073709551615, 8, 10), - (13, 513, 901, 1095, 18446744073709551615, 1, 2), - (13, 514, 1095, 1096, 18446744073709551615, 2, 4), - (13, 515, 1096, 1097, 18446744073709551615, 2, 4), - (13, 542, 1118, 1119, 18446744073709551615, 7, 11), - (13, 543, 1119, 1120, 18446744073709551615, 7, 10), - (13, 1024, 1149, 768, 18446744073709551615, 0, 2), - (13, 513, 901, 894, 18446744073709551615, 0, 1), - (13, 514, 894, 1095, 18446744073709551615, 0, 1), - (13, 515, 1095, 1096, 18446744073709551615, 5, 7), - (13, 543, 1118, 1119, 18446744073709551615, 9, 10), - (13, 513, 894, 1095, 18446744073709551615, 0, 1), - (13, 514, 1095, 1096, 18446744073709551615, 3, 4), - (13, 515, 1096, 1097, 18446744073709551615, 3, 4), - (13, 542, 1118, 1119, 18446744073709551615, 9, 11), - (13, 543, 1119, 1120, 18446744073709551615, 9, 10), - (13, 123, 891, 1137, 18446744073709551615, 0, 1), - (13, 123, 891, 1099, 18446744073709551615, 2, 3), - (13, 1024, 1099, 892, 18446744073709551615, 0, 1), - (13, 1024, 891, 123, 18446744073709551615, 142, 143), - (13, 513, 1097, 1098, 18446744073709551615, 0, 1), - (13, 514, 1098, 1099, 18446744073709551615, 0, 5), - (13, 515, 1099, 1100, 18446744073709551615, 0, 6), - (13, 542, 1121, 1122, 18446744073709551615, 0, 10), - (13, 543, 1122, 1123, 18446744073709551615, 0, 10), - (13, 122, 890, 1135, 18446744073709551615, 6, 7), - (13, 1024, 901, 123, 18446744073709551615, 0, 1), - (13, 1024, 890, 122, 18446744073709551615, 143, 144), - (13, 513, 1097, 894, 18446744073709551615, 0, 2), - (13, 514, 894, 1098, 18446744073709551615, 0, 3), - (13, 515, 1098, 1099, 18446744073709551615, 0, 4), - (13, 121, 889, 1137, 18446744073709551615, 0, 1), - (13, 121, 889, 894, 18446744073709551615, 0, 1), - (13, 1024, 894, 122, 18446744073709551615, 0, 1), - (13, 1024, 889, 121, 18446744073709551615, 144, 145), - (13, 513, 894, 1098, 18446744073709551615, 0, 3), - (13, 514, 1098, 1099, 18446744073709551615, 1, 5), - (13, 515, 1099, 1100, 18446744073709551615, 1, 6), - (13, 543, 1122, 1123, 18446744073709551615, 2, 10), - (13, 1024, 1150, 768, 18446744073709551615, 143, 145), - (13, 513, 890, 894, 18446744073709551615, 0, 1), - (13, 514, 894, 1098, 18446744073709551615, 1, 3), - (13, 515, 1098, 1099, 18446744073709551615, 1, 4), - (13, 542, 1120, 1121, 18446744073709551615, 1, 4), - (13, 119, 887, 1137, 18446744073709551615, 0, 1), - (13, 513, 894, 1098, 18446744073709551615, 1, 3), - (13, 514, 1098, 1099, 18446744073709551615, 2, 5), - (13, 515, 1099, 1100, 18446744073709551615, 2, 6), - (13, 542, 1121, 1122, 18446744073709551615, 4, 10), - (13, 543, 1122, 1123, 18446744073709551615, 4, 10), - (13, 513, 1097, 894, 18446744073709551615, 1, 2), - (13, 514, 894, 1098, 18446744073709551615, 2, 3), - (13, 515, 1098, 1099, 18446744073709551615, 2, 4), - (13, 542, 1120, 1121, 18446744073709551615, 2, 4), - (13, 1024, 1149, 768, 18446744073709551615, 1, 2), - (13, 513, 894, 1098, 18446744073709551615, 2, 3), - (13, 514, 1098, 1099, 18446744073709551615, 3, 5), - (13, 515, 1099, 1100, 18446744073709551615, 3, 6), - (13, 1024, 1146, 768, 18446744073709551615, 0, 3), - (13, 513, 894, 885, 18446744073709551615, 0, 1), - (13, 514, 885, 1098, 18446744073709551615, 0, 1), - (13, 515, 1098, 1099, 18446744073709551615, 3, 4), - (13, 542, 1120, 1121, 18446744073709551615, 3, 4), - (13, 543, 1121, 1122, 18446744073709551615, 3, 4), - (13, 513, 885, 1098, 18446744073709551615, 0, 1), - (13, 514, 1098, 1099, 18446744073709551615, 4, 5), - (13, 515, 1099, 1100, 18446744073709551615, 4, 6), - (13, 543, 1123, 1124, 18446744073709551615, 4, 9), - (13, 1024, 1148, 768, 18446744073709551615, 1, 2), - (13, 513, 1098, 1099, 18446744073709551615, 0, 1), - (13, 514, 1099, 1100, 18446744073709551615, 0, 2), - (13, 515, 1100, 1101, 18446744073709551615, 0, 3), - (13, 112, 880, 1137, 18446744073709551615, 8, 9), - (13, 112, 880, 1145, 18446744073709551615, 6, 7), - (13, 1024, 1145, 768, 18446744073709551615, 0, 3), - (13, 513, 1098, 882, 18446744073709551615, 0, 1), - (13, 514, 882, 1099, 18446744073709551615, 0, 1), - (13, 515, 1099, 1100, 18446744073709551615, 5, 6), - (13, 542, 1121, 1122, 18446744073709551615, 9, 10), - (13, 513, 882, 1099, 18446744073709551615, 0, 1), - (13, 514, 1099, 1100, 18446744073709551615, 1, 2), - (13, 515, 1100, 1101, 18446744073709551615, 1, 3), - (13, 110, 878, 1139, 18446744073709551615, 0, 1), - (13, 110, 878, 1147, 18446744073709551615, 1, 2), - (13, 1024, 1147, 768, 18446744073709551615, 1, 2), - (13, 513, 1099, 1100, 18446744073709551615, 0, 1), - (13, 514, 1100, 1101, 18446744073709551615, 0, 2), - (13, 515, 1101, 1102, 18446744073709551615, 0, 3), - (13, 542, 1123, 1124, 18446744073709551615, 2, 6), - (13, 543, 1124, 1125, 18446744073709551615, 2, 6), - (13, 109, 877, 1138, 18446744073709551615, 1, 2), - (13, 109, 877, 1144, 18446744073709551615, 2, 3), - (13, 513, 1099, 879, 18446744073709551615, 0, 1), - (13, 514, 879, 1100, 18446744073709551615, 0, 1), - (13, 515, 1100, 1101, 18446744073709551615, 2, 3), - (13, 543, 1124, 1125, 18446744073709551615, 3, 6), - (13, 542, 1122, 1123, 18446744073709551615, 8, 9), - (13, 543, 1123, 1124, 18446744073709551615, 8, 9), - (13, 1024, 1145, 768, 18446744073709551615, 1, 3), - (13, 513, 879, 1100, 18446744073709551615, 0, 1), - (13, 514, 1100, 1101, 18446744073709551615, 1, 2), - (13, 515, 1101, 1102, 18446744073709551615, 1, 3), - (13, 542, 1123, 1124, 18446744073709551615, 4, 6), - (13, 543, 1124, 1125, 18446744073709551615, 4, 6), - (13, 1024, 1146, 768, 18446744073709551615, 2, 3), - (13, 513, 1100, 1101, 18446744073709551615, 0, 1), - (13, 514, 1101, 1102, 18446744073709551615, 0, 2), - (13, 515, 1102, 1103, 18446744073709551615, 0, 3), - (13, 1024, 1143, 768, 18446744073709551615, 0, 3), - (13, 513, 1100, 876, 18446744073709551615, 0, 1), - (13, 514, 876, 1101, 18446744073709551615, 0, 1), - (13, 515, 1101, 1102, 18446744073709551615, 2, 3), - (13, 542, 1123, 1124, 18446744073709551615, 5, 6), - (13, 543, 1124, 1125, 18446744073709551615, 5, 6), - (13, 1024, 1144, 768, 18446744073709551615, 1, 3), - (13, 513, 876, 1101, 18446744073709551615, 0, 1), - (13, 514, 1101, 1102, 18446744073709551615, 1, 2), - (13, 515, 1102, 1103, 18446744073709551615, 1, 3), - (13, 543, 1125, 1126, 18446744073709551615, 4, 6), - (13, 1024, 1145, 768, 18446744073709551615, 2, 3), - (13, 513, 1101, 1102, 18446744073709551615, 0, 1), - (13, 514, 1102, 1103, 18446744073709551615, 0, 2), - (13, 515, 1103, 1104, 18446744073709551615, 0, 3), - (13, 543, 1126, 1127, 18446744073709551615, 2, 6), - (13, 103, 871, 1140, 18446744073709551615, 4, 5), - (13, 103, 871, 1142, 18446744073709551615, 2, 3), - (13, 513, 1101, 873, 18446744073709551615, 0, 1), - (13, 514, 873, 1102, 18446744073709551615, 0, 1), - (13, 515, 1102, 1103, 18446744073709551615, 2, 3), - (13, 543, 1125, 1126, 18446744073709551615, 5, 6), - (13, 1024, 1143, 768, 18446744073709551615, 1, 3), - (13, 513, 873, 1102, 18446744073709551615, 0, 1), - (13, 514, 1102, 1103, 18446744073709551615, 1, 2), - (13, 515, 1103, 1104, 18446744073709551615, 1, 3), - (13, 542, 1125, 1126, 18446744073709551615, 4, 6), - (13, 543, 1126, 1127, 18446744073709551615, 4, 6), - (13, 1024, 1144, 768, 18446744073709551615, 2, 3), - (13, 513, 1102, 1103, 18446744073709551615, 0, 1), - (13, 514, 1103, 1104, 18446744073709551615, 0, 2), - (13, 515, 1104, 1105, 18446744073709551615, 0, 3), - (13, 543, 1127, 1128, 18446744073709551615, 2, 6), - (13, 100, 868, 1142, 18446744073709551615, 1, 2), - (13, 100, 868, 1141, 18446744073709551615, 4, 5), - (13, 1024, 1141, 768, 18446744073709551615, 0, 4), - (13, 513, 1102, 870, 18446744073709551615, 0, 1), - (13, 514, 870, 1103, 18446744073709551615, 0, 1), - (13, 515, 1103, 1104, 18446744073709551615, 2, 3), - (13, 543, 1126, 1127, 18446744073709551615, 5, 6), - (13, 1024, 1142, 768, 18446744073709551615, 1, 3), - (13, 513, 870, 1103, 18446744073709551615, 0, 1), - (13, 514, 1103, 1104, 18446744073709551615, 1, 2), - (13, 515, 1104, 1105, 18446744073709551615, 1, 3), - (13, 1024, 1143, 768, 18446744073709551615, 2, 3), - (13, 513, 1103, 1104, 18446744073709551615, 0, 1), - (13, 514, 1104, 1105, 18446744073709551615, 0, 2), - (13, 515, 1105, 1106, 18446744073709551615, 0, 3), - (13, 97, 865, 1143, 18446744073709551615, 1, 2), - (13, 97, 865, 1140, 18446744073709551615, 2, 3), - (13, 1024, 1140, 768, 18446744073709551615, 0, 3), - (13, 1024, 865, 97, 18446744073709551615, 167, 168), - (13, 513, 1103, 867, 18446744073709551615, 0, 1), - (13, 514, 867, 1104, 18446744073709551615, 0, 1), - (13, 515, 1104, 1105, 18446744073709551615, 2, 3), - (13, 96, 864, 1145, 18446744073709551615, 2, 3), - (13, 96, 864, 1141, 18446744073709551615, 1, 2), - (13, 1024, 1141, 768, 18446744073709551615, 1, 4), - (13, 1024, 864, 96, 18446744073709551615, 168, 169), - (13, 513, 867, 1104, 18446744073709551615, 0, 1), - (13, 514, 1104, 1105, 18446744073709551615, 1, 2), - (13, 515, 1105, 1106, 18446744073709551615, 1, 3), - (13, 542, 1127, 1128, 18446744073709551615, 4, 6), - (13, 95, 863, 1145, 18446744073709551615, 3, 4), - (13, 95, 863, 1142, 18446744073709551615, 1, 2), - (13, 513, 1104, 1105, 18446744073709551615, 0, 1), - (13, 514, 1105, 1106, 18446744073709551615, 0, 2), - (13, 515, 1106, 1107, 18446744073709551615, 0, 3), - (13, 542, 1128, 1129, 18446744073709551615, 2, 6), - (13, 543, 1129, 1130, 18446744073709551615, 2, 6), - (13, 94, 862, 1144, 18446744073709551615, 4, 5), - (13, 94, 862, 1139, 18446744073709551615, 2, 3), - (13, 513, 1104, 864, 18446744073709551615, 0, 1), - (13, 514, 864, 1105, 18446744073709551615, 0, 1), - (13, 515, 1105, 1106, 18446744073709551615, 2, 3), - (13, 543, 1128, 1129, 18446744073709551615, 5, 6), - (13, 93, 861, 1146, 18446744073709551615, 3, 4), - (13, 93, 861, 1140, 18446744073709551615, 2, 3), - (13, 1024, 1140, 768, 18446744073709551615, 1, 3), - (13, 1024, 861, 93, 18446744073709551615, 171, 172), - (13, 513, 864, 1105, 18446744073709551615, 0, 1), - (13, 514, 1105, 1106, 18446744073709551615, 1, 2), - (13, 515, 1106, 1107, 18446744073709551615, 1, 3), - (13, 543, 1130, 1131, 18446744073709551615, 1, 6), - (13, 542, 1128, 1129, 18446744073709551615, 4, 6), - (13, 92, 860, 1147, 18446744073709551615, 3, 4), - (13, 92, 860, 1141, 18446744073709551615, 3, 4), - (13, 1024, 1141, 768, 18446744073709551615, 2, 4), - (13, 1024, 860, 92, 18446744073709551615, 172, 173), - (13, 513, 1105, 1106, 18446744073709551615, 0, 1), - (13, 514, 1106, 1107, 18446744073709551615, 0, 2), - (13, 515, 1107, 1108, 18446744073709551615, 0, 3), - (13, 542, 1129, 1130, 18446744073709551615, 2, 6), - (13, 543, 1130, 1131, 18446744073709551615, 2, 6), - (13, 91, 859, 1146, 18446744073709551615, 4, 5), - (13, 91, 859, 1138, 18446744073709551615, 3, 4), - (13, 1024, 1138, 768, 18446744073709551615, 0, 3), - (13, 1024, 859, 91, 18446744073709551615, 173, 174), - (13, 513, 1105, 861, 18446744073709551615, 0, 1), - (13, 514, 861, 1106, 18446744073709551615, 0, 1), - (13, 515, 1106, 1107, 18446744073709551615, 2, 3), - (13, 542, 1128, 1129, 18446744073709551615, 5, 6), - (13, 543, 1129, 1130, 18446744073709551615, 5, 6), - (13, 90, 858, 1148, 18446744073709551615, 3, 4), - (13, 90, 858, 1139, 18446744073709551615, 4, 5), - (13, 1024, 1139, 768, 18446744073709551615, 1, 4), - (13, 1024, 858, 90, 18446744073709551615, 174, 175), - (13, 513, 861, 1106, 18446744073709551615, 0, 1), - (13, 514, 1106, 1107, 18446744073709551615, 1, 2), - (13, 515, 1107, 1108, 18446744073709551615, 1, 3), - (13, 89, 857, 1148, 18446744073709551615, 3, 4), - (13, 89, 857, 1140, 18446744073709551615, 3, 4), - (13, 1024, 1140, 768, 18446744073709551615, 2, 3), - (13, 1024, 857, 89, 18446744073709551615, 175, 176), - (13, 513, 1106, 1107, 18446744073709551615, 0, 1), - (13, 514, 1107, 1108, 18446744073709551615, 0, 2), - (13, 515, 1108, 1109, 18446744073709551615, 0, 3), - (13, 543, 1131, 1132, 18446744073709551615, 2, 6), - (13, 88, 856, 1147, 18446744073709551615, 4, 5), - (13, 88, 856, 1137, 18446744073709551615, 5, 6), - (13, 1024, 1137, 768, 18446744073709551615, 0, 3), - (13, 1024, 856, 88, 18446744073709551615, 176, 177), - (13, 513, 1106, 858, 18446744073709551615, 0, 1), - (13, 514, 858, 1107, 18446744073709551615, 0, 1), - (13, 515, 1107, 1108, 18446744073709551615, 2, 3), - (13, 543, 1130, 1131, 18446744073709551615, 5, 6), - (13, 87, 855, 1149, 18446744073709551615, 3, 4), - (13, 87, 855, 1138, 18446744073709551615, 4, 5), - (13, 1024, 1138, 768, 18446744073709551615, 1, 3), - (13, 1024, 855, 87, 18446744073709551615, 177, 178), - (13, 513, 858, 1107, 18446744073709551615, 0, 1), - (13, 514, 1107, 1108, 18446744073709551615, 1, 2), - (13, 515, 1108, 1109, 18446744073709551615, 1, 3), - (13, 543, 1132, 1133, 18446744073709551615, 1, 6), - (13, 542, 1130, 1131, 18446744073709551615, 4, 6), - (13, 86, 854, 1149, 18446744073709551615, 3, 4), - (13, 86, 854, 1139, 18446744073709551615, 4, 5), - (13, 513, 1107, 1108, 18446744073709551615, 0, 1), - (13, 514, 1108, 1109, 18446744073709551615, 0, 2), - (13, 515, 1109, 1110, 18446744073709551615, 0, 3), - (13, 543, 1132, 1133, 18446744073709551615, 2, 6), - (13, 85, 853, 1148, 18446744073709551615, 4, 5), - (13, 85, 853, 1136, 18446744073709551615, 5, 6), - (13, 513, 1107, 855, 18446744073709551615, 0, 1), - (13, 514, 855, 1108, 18446744073709551615, 0, 1), - (13, 515, 1108, 1109, 18446744073709551615, 2, 3), - (13, 543, 1131, 1132, 18446744073709551615, 5, 6), - (13, 84, 852, 1150, 18446744073709551615, 3, 4), - (13, 84, 852, 1137, 18446744073709551615, 5, 6), - (13, 1024, 1137, 768, 18446744073709551615, 1, 3), - (13, 1024, 852, 84, 18446744073709551615, 180, 181), - (13, 513, 855, 1108, 18446744073709551615, 0, 1), - (13, 514, 1108, 1109, 18446744073709551615, 1, 2), - (13, 515, 1109, 1110, 18446744073709551615, 1, 3), - (13, 543, 1133, 1134, 18446744073709551615, 1, 6), - (13, 542, 1131, 1132, 18446744073709551615, 4, 6), - (13, 83, 851, 1151, 18446744073709551615, 0, 1), - (13, 83, 851, 1138, 18446744073709551615, 5, 6), - (13, 1024, 1138, 768, 18446744073709551615, 2, 3), - (13, 1024, 851, 83, 18446744073709551615, 181, 182), - (13, 513, 1108, 1109, 18446744073709551615, 0, 1), - (13, 514, 1109, 1110, 18446744073709551615, 0, 2), - (13, 515, 1110, 1111, 18446744073709551615, 0, 3), - (13, 542, 1132, 1133, 18446744073709551615, 2, 6), - (13, 543, 1133, 1134, 18446744073709551615, 2, 6), - (13, 82, 850, 1150, 18446744073709551615, 4, 5), - (13, 82, 850, 1135, 18446744073709551615, 6, 7), - (13, 1024, 1135, 768, 18446744073709551615, 0, 3), - (13, 1024, 850, 82, 18446744073709551615, 182, 183), - (13, 513, 1108, 852, 18446744073709551615, 0, 1), - (13, 514, 852, 1109, 18446744073709551615, 0, 1), - (13, 515, 1109, 1110, 18446744073709551615, 2, 3), - (13, 543, 1132, 1133, 18446744073709551615, 5, 6), - (13, 81, 849, 1152, 18446744073709551615, 0, 1), - (13, 81, 849, 1136, 18446744073709551615, 6, 7), - (13, 1024, 1136, 768, 18446744073709551615, 1, 3), - (13, 1024, 849, 81, 18446744073709551615, 183, 184), - (13, 513, 852, 1109, 18446744073709551615, 0, 1), - (13, 514, 1109, 1110, 18446744073709551615, 1, 2), - (13, 515, 1110, 1111, 18446744073709551615, 1, 3), - (13, 542, 1132, 1133, 18446744073709551615, 4, 6), - (13, 80, 848, 1152, 18446744073709551615, 0, 1), - (13, 80, 848, 1137, 18446744073709551615, 3, 4), - (13, 1024, 1137, 768, 18446744073709551615, 2, 3), - (13, 513, 1109, 1110, 18446744073709551615, 0, 1), - (13, 514, 1110, 1111, 18446744073709551615, 0, 2), - (13, 515, 1111, 1112, 18446744073709551615, 0, 3), - (13, 543, 1134, 1135, 18446744073709551615, 2, 7), - (13, 79, 847, 1152, 18446744073709551615, 0, 1), - (13, 79, 847, 1134, 18446744073709551615, 7, 8), - (13, 1024, 1134, 768, 18446744073709551615, 0, 2), - (13, 1024, 847, 79, 18446744073709551615, 185, 186), - (13, 513, 1109, 849, 18446744073709551615, 0, 1), - (13, 514, 849, 1110, 18446744073709551615, 0, 1), - (13, 515, 1110, 1111, 18446744073709551615, 2, 3), - (13, 78, 846, 1152, 18446744073709551615, 0, 1), - (13, 78, 846, 1135, 18446744073709551615, 4, 5), - (13, 1024, 1135, 768, 18446744073709551615, 1, 3), - (13, 1024, 846, 78, 18446744073709551615, 186, 187), - (13, 513, 849, 1110, 18446744073709551615, 0, 1), - (13, 514, 1110, 1111, 18446744073709551615, 1, 2), - (13, 515, 1111, 1112, 18446744073709551615, 1, 3), - (13, 543, 1134, 1135, 18446744073709551615, 4, 7), - (13, 77, 845, 1153, 18446744073709551615, 0, 1), - (13, 77, 845, 1136, 18446744073709551615, 5, 6), - (13, 1024, 1136, 768, 18446744073709551615, 2, 3), - (13, 1024, 845, 77, 18446744073709551615, 187, 188), - (13, 513, 1110, 1111, 18446744073709551615, 0, 1), - (13, 514, 1111, 1112, 18446744073709551615, 0, 2), - (13, 515, 1112, 1113, 18446744073709551615, 0, 3), - (13, 542, 1134, 1135, 18446744073709551615, 2, 6), - (13, 543, 1135, 1136, 18446744073709551615, 2, 6), - (13, 76, 844, 1153, 18446744073709551615, 0, 1), - (13, 76, 844, 1133, 18446744073709551615, 5, 6), - (13, 1024, 1133, 768, 18446744073709551615, 0, 1), - (13, 1024, 844, 76, 18446744073709551615, 188, 189), - (13, 513, 1110, 846, 18446744073709551615, 0, 1), - (13, 514, 846, 1111, 18446744073709551615, 0, 1), - (13, 515, 1111, 1112, 18446744073709551615, 2, 3), - (13, 542, 1133, 1134, 18446744073709551615, 5, 6), - (13, 543, 1134, 1135, 18446744073709551615, 5, 7), - (13, 75, 843, 1153, 18446744073709551615, 0, 1), - (13, 75, 843, 1134, 18446744073709551615, 6, 7), - (13, 1024, 1134, 768, 18446744073709551615, 1, 2), - (13, 1024, 843, 75, 18446744073709551615, 189, 190), - (13, 513, 846, 1111, 18446744073709551615, 0, 1), - (13, 514, 1111, 1112, 18446744073709551615, 1, 2), - (13, 515, 1112, 1113, 18446744073709551615, 1, 3), - (13, 543, 1136, 1137, 18446744073709551615, 1, 6), - (13, 542, 1134, 1135, 18446744073709551615, 4, 6), - (13, 543, 1135, 1136, 18446744073709551615, 4, 6), - (13, 74, 842, 1153, 18446744073709551615, 0, 1), - (13, 74, 842, 1135, 18446744073709551615, 3, 4), - (13, 1024, 1135, 768, 18446744073709551615, 2, 3), - (13, 1024, 842, 74, 18446744073709551615, 190, 191), - (13, 513, 1111, 1112, 18446744073709551615, 0, 1), - (13, 514, 1112, 1113, 18446744073709551615, 0, 2), - (13, 515, 1113, 1114, 18446744073709551615, 0, 7), - (13, 73, 841, 1153, 18446744073709551615, 0, 1), - (13, 1024, 841, 73, 18446744073709551615, 191, 192), - (13, 513, 1111, 843, 18446744073709551615, 0, 1), - (13, 514, 843, 1112, 18446744073709551615, 0, 1), - (13, 515, 1112, 1113, 18446744073709551615, 2, 3), - (13, 542, 1134, 1135, 18446744073709551615, 5, 6), - (13, 72, 840, 1153, 18446744073709551615, 1, 2), - (13, 1024, 840, 72, 18446744073709551615, 192, 193), - (13, 513, 843, 1112, 18446744073709551615, 0, 1), - (13, 514, 1112, 1113, 18446744073709551615, 1, 2), - (13, 515, 1113, 1114, 18446744073709551615, 1, 7), - (13, 543, 1136, 1137, 18446744073709551615, 4, 6), - (13, 71, 839, 1153, 18446744073709551615, 1, 2), - (13, 513, 1112, 1113, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 0, 6), - (13, 515, 1114, 1115, 18446744073709551615, 0, 2), - (13, 542, 1136, 1137, 18446744073709551615, 2, 6), - (13, 70, 838, 1153, 18446744073709551615, 1, 2), - (13, 513, 1112, 840, 18446744073709551615, 0, 1), - (13, 514, 840, 1113, 18446744073709551615, 0, 1), - (13, 515, 1113, 1114, 18446744073709551615, 2, 7), - (13, 69, 837, 1153, 18446744073709551615, 1, 4), - (13, 1024, 837, 69, 18446744073709551615, 195, 391), - (13, 513, 840, 1113, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 1, 6), - (13, 515, 1114, 1115, 18446744073709551615, 1, 2), - (13, 542, 1136, 1137, 18446744073709551615, 4, 6), - (13, 68, 836, 1153, 18446744073709551615, 1, 2), - (13, 1024, 836, 68, 18446744073709551615, 196, 197), - (13, 513, 1114, 1115, 18446744073709551615, 0, 1), - (13, 514, 1115, 1116, 18446744073709551615, 0, 1), - (13, 515, 1116, 1113, 18446744073709551615, 0, 1), - (13, 512, 1116, 1115, 18446744073709551615, 0, 1), - (13, 513, 1121, 1118, 18446744073709551615, 0, 2), - (13, 514, 1120, 1117, 18446744073709551615, 0, 1), - (13, 542, 1137, 1138, 18446744073709551615, 2, 6), - (13, 67, 835, 1153, 18446744073709551615, 1, 2), - (13, 513, 1119, 840, 18446744073709551615, 0, 1), - (13, 514, 840, 1120, 18446744073709551615, 0, 1), - (13, 515, 1120, 1121, 18446744073709551615, 0, 1), - (13, 542, 1136, 1137, 18446744073709551615, 5, 6), - (13, 66, 834, 1153, 18446744073709551615, 1, 4), - (13, 513, 1120, 1121, 18446744073709551615, 0, 1), - (13, 514, 1121, 1116, 18446744073709551615, 0, 1), - (13, 515, 1116, 840, 18446744073709551615, 0, 6), - (13, 512, 1116, 1121, 18446744073709551615, 0, 1), - (13, 513, 1117, 1114, 18446744073709551615, 0, 1), - (13, 514, 1118, 1113, 18446744073709551615, 0, 3), - (13, 542, 1137, 1138, 18446744073709551615, 4, 6), - (13, 65, 833, 1153, 18446744073709551615, 1, 2), - (13, 1024, 833, 65, 18446744073709551615, 199, 200), - (13, 513, 1117, 1116, 18446744073709551615, 0, 1), - (13, 514, 1116, 840, 18446744073709551615, 0, 6), - (13, 515, 840, 1118, 18446744073709551615, 0, 5), - (13, 542, 1113, 1114, 18446744073709551615, 4, 9), - (13, 512, 840, 1116, 18446744073709551615, 0, 3), - (13, 513, 1122, 1121, 18446744073709551615, 0, 1), - (13, 514, 1113, 1120, 18446744073709551615, 0, 1), - (13, 543, 1139, 1140, 18446744073709551615, 0, 3), - (13, 64, 832, 1153, 18446744073709551615, 1, 2), - (13, 513, 1115, 1113, 18446744073709551615, 0, 3), - (13, 514, 1113, 1122, 18446744073709551615, 0, 1), - (13, 515, 1122, 1114, 18446744073709551615, 0, 1), - (13, 542, 1116, 1117, 18446744073709551615, 6, 7), - (13, 512, 1122, 1113, 18446744073709551615, 0, 1), - (13, 513, 1121, 1118, 18446744073709551615, 1, 2), - (13, 514, 1116, 840, 18446744073709551615, 1, 6), - (13, 543, 1138, 1139, 18446744073709551615, 5, 6), - (13, 63, 831, 1153, 18446744073709551615, 1, 2), - (13, 1024, 831, 63, 18446744073709551615, 201, 202), - (13, 513, 1121, 1122, 18446744073709551615, 0, 1), - (13, 514, 1122, 1114, 18446744073709551615, 0, 1), - (13, 515, 1114, 1116, 18446744073709551615, 0, 5), - (13, 512, 1114, 1122, 18446744073709551615, 0, 1), - (13, 513, 1120, 1113, 18446744073709551615, 0, 1), - (13, 514, 840, 1115, 18446744073709551615, 0, 3), - (13, 543, 1139, 1140, 18446744073709551615, 1, 3), - (13, 62, 830, 1153, 18446744073709551615, 1, 2), - (13, 1024, 830, 62, 18446744073709551615, 202, 203), - (13, 513, 1120, 1114, 18446744073709551615, 0, 1), - (13, 514, 1114, 1116, 18446744073709551615, 0, 5), - (13, 515, 1116, 840, 18446744073709551615, 1, 6), - (13, 512, 1116, 1114, 18446744073709551615, 0, 3), - (13, 513, 1123, 1122, 18446744073709551615, 0, 1), - (13, 514, 1115, 1121, 18446744073709551615, 0, 1), - (13, 542, 1139, 1140, 18446744073709551615, 0, 3), - (13, 61, 829, 1153, 18446744073709551615, 1, 2), - (13, 1024, 829, 61, 18446744073709551615, 203, 204), - (13, 513, 1118, 1115, 18446744073709551615, 0, 2), - (13, 514, 1115, 1123, 18446744073709551615, 0, 1), - (13, 515, 1123, 1113, 18446744073709551615, 0, 1), - (13, 512, 1123, 1115, 18446744073709551615, 0, 1), - (13, 513, 1122, 840, 18446744073709551615, 0, 1), - (13, 514, 1114, 1116, 18446744073709551615, 1, 5), - (13, 542, 1138, 1139, 18446744073709551615, 2, 3), - (13, 60, 828, 1153, 18446744073709551615, 1, 2), - (13, 1024, 828, 60, 18446744073709551615, 204, 205), - (13, 513, 1122, 1123, 18446744073709551615, 0, 1), - (13, 514, 1123, 1113, 18446744073709551615, 0, 1), - (13, 515, 1113, 1114, 18446744073709551615, 3, 7), - (13, 512, 1113, 1123, 18446744073709551615, 0, 1), - (13, 513, 1121, 1115, 18446744073709551615, 0, 1), - (13, 514, 1116, 1118, 18446744073709551615, 0, 2), - (13, 59, 827, 1153, 18446744073709551615, 1, 2), - (13, 1024, 827, 59, 18446744073709551615, 205, 206), - (13, 513, 1121, 1113, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 2, 6), - (13, 515, 1114, 1116, 18446744073709551615, 1, 5), - (13, 543, 1115, 1114, 18446744073709551615, 0, 2), - (13, 512, 1114, 1113, 18446744073709551615, 0, 2), - (13, 513, 1124, 1123, 18446744073709551615, 0, 1), - (13, 514, 1118, 1122, 18446744073709551615, 0, 1), - (13, 542, 1140, 1141, 18446744073709551615, 0, 3), - (13, 543, 1141, 1142, 18446744073709551615, 0, 3), - (13, 58, 826, 1153, 18446744073709551615, 1, 2), - (13, 1024, 826, 58, 18446744073709551615, 206, 207), - (13, 513, 840, 1118, 18446744073709551615, 0, 2), - (13, 514, 1118, 1124, 18446744073709551615, 0, 1), - (13, 515, 1124, 1115, 18446744073709551615, 0, 1), - (13, 512, 1124, 1118, 18446744073709551615, 0, 1), - (13, 513, 1123, 1116, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 3, 6), - (13, 543, 1140, 1141, 18446744073709551615, 2, 3), - (13, 57, 825, 1153, 18446744073709551615, 1, 2), - (13, 1024, 825, 57, 18446744073709551615, 207, 208), - (13, 513, 1123, 1124, 18446744073709551615, 0, 1), - (13, 514, 1124, 1115, 18446744073709551615, 0, 1), - (13, 515, 1115, 1113, 18446744073709551615, 0, 4), - (13, 542, 1114, 1116, 18446744073709551615, 0, 4), - (13, 512, 1115, 1124, 18446744073709551615, 0, 1), - (13, 513, 1122, 1118, 18446744073709551615, 0, 1), - (13, 514, 1114, 840, 18446744073709551615, 0, 2), - (13, 56, 824, 1153, 18446744073709551615, 1, 2), - (13, 1024, 824, 56, 18446744073709551615, 208, 209), - (13, 513, 1122, 1115, 18446744073709551615, 0, 1), - (13, 514, 1115, 1113, 18446744073709551615, 0, 4), - (13, 515, 1113, 1114, 18446744073709551615, 4, 7), - (13, 512, 1113, 1115, 18446744073709551615, 0, 2), - (13, 513, 1125, 1124, 18446744073709551615, 0, 1), - (13, 514, 840, 1123, 18446744073709551615, 0, 1), - (13, 542, 1141, 1142, 18446744073709551615, 0, 3), - (13, 543, 1142, 1143, 18446744073709551615, 0, 3), - (13, 55, 823, 1153, 18446744073709551615, 1, 2), - (13, 1024, 823, 55, 18446744073709551615, 209, 210), - (13, 513, 1116, 840, 18446744073709551615, 0, 2), - (13, 514, 840, 1125, 18446744073709551615, 0, 1), - (13, 515, 1125, 1118, 18446744073709551615, 0, 1), - (13, 512, 1125, 840, 18446744073709551615, 0, 1), - (13, 513, 1124, 1114, 18446744073709551615, 0, 1), - (13, 514, 1115, 1113, 18446744073709551615, 1, 4), - (13, 542, 1140, 1141, 18446744073709551615, 2, 3), - (13, 54, 822, 1153, 18446744073709551615, 1, 2), - (13, 1024, 822, 54, 18446744073709551615, 210, 211), - (13, 513, 1124, 1125, 18446744073709551615, 0, 1), - (13, 514, 1125, 1118, 18446744073709551615, 0, 1), - (13, 515, 1118, 1115, 18446744073709551615, 0, 4), - (13, 512, 1118, 1125, 18446744073709551615, 0, 1), - (13, 513, 1123, 840, 18446744073709551615, 0, 1), - (13, 514, 1113, 1116, 18446744073709551615, 0, 2), - (13, 542, 1141, 1142, 18446744073709551615, 1, 3), - (13, 543, 1142, 1143, 18446744073709551615, 1, 3), - (13, 53, 821, 1153, 18446744073709551615, 1, 2), - (13, 1024, 821, 53, 18446744073709551615, 211, 212), - (13, 513, 1123, 1118, 18446744073709551615, 0, 1), - (13, 514, 1118, 1115, 18446744073709551615, 0, 4), - (13, 515, 1115, 1113, 18446744073709551615, 1, 4), - (13, 512, 1115, 1118, 18446744073709551615, 0, 2), - (13, 513, 1126, 1125, 18446744073709551615, 0, 1), - (13, 514, 1116, 1124, 18446744073709551615, 0, 1), - (13, 52, 820, 1153, 18446744073709551615, 1, 2), - (13, 1024, 820, 52, 18446744073709551615, 212, 213), - (13, 513, 1114, 1116, 18446744073709551615, 0, 2), - (13, 514, 1116, 1126, 18446744073709551615, 0, 1), - (13, 515, 1126, 840, 18446744073709551615, 0, 1), - (13, 512, 1126, 1116, 18446744073709551615, 0, 1), - (13, 513, 1125, 1113, 18446744073709551615, 0, 1), - (13, 514, 1118, 1115, 18446744073709551615, 1, 4), - (13, 51, 819, 1153, 18446744073709551615, 1, 2), - (13, 1024, 819, 51, 18446744073709551615, 213, 214), - (13, 513, 1125, 1126, 18446744073709551615, 0, 1), - (13, 514, 1126, 840, 18446744073709551615, 0, 1), - (13, 515, 840, 1118, 18446744073709551615, 1, 5), - (13, 512, 840, 1126, 18446744073709551615, 0, 1), - (13, 513, 1124, 1116, 18446744073709551615, 0, 1), - (13, 514, 1115, 1114, 18446744073709551615, 0, 2), - (13, 50, 818, 1153, 18446744073709551615, 1, 2), - (13, 1024, 818, 50, 18446744073709551615, 214, 215), - (13, 513, 1124, 840, 18446744073709551615, 0, 1), - (13, 514, 840, 1118, 18446744073709551615, 0, 4), - (13, 515, 1118, 1115, 18446744073709551615, 1, 4), - (13, 512, 1118, 840, 18446744073709551615, 0, 2), - (13, 513, 1127, 1126, 18446744073709551615, 0, 1), - (13, 514, 1114, 1125, 18446744073709551615, 0, 1), - (13, 542, 1143, 1144, 18446744073709551615, 0, 3), - (13, 49, 817, 1153, 18446744073709551615, 1, 2), - (13, 513, 1113, 1114, 18446744073709551615, 0, 2), - (13, 514, 1114, 1127, 18446744073709551615, 0, 1), - (13, 515, 1127, 1116, 18446744073709551615, 0, 1), - (13, 512, 1127, 1114, 18446744073709551615, 0, 1), - (13, 513, 1126, 1115, 18446744073709551615, 0, 1), - (13, 514, 840, 1118, 18446744073709551615, 1, 4), - (13, 48, 816, 1153, 18446744073709551615, 1, 2), - (13, 513, 1126, 1127, 18446744073709551615, 0, 1), - (13, 514, 1127, 1116, 18446744073709551615, 0, 1), - (13, 515, 1116, 840, 18446744073709551615, 2, 6), - (13, 543, 1115, 1116, 18446744073709551615, 4, 6), - (13, 512, 1116, 1127, 18446744073709551615, 0, 1), - (13, 513, 1125, 1114, 18446744073709551615, 0, 1), - (13, 514, 1118, 1113, 18446744073709551615, 1, 3), - (13, 543, 1144, 1145, 18446744073709551615, 1, 3), - (13, 47, 815, 1153, 18446744073709551615, 1, 2), - (13, 513, 1125, 1116, 18446744073709551615, 0, 1), - (13, 514, 1116, 840, 18446744073709551615, 2, 6), - (13, 515, 840, 1118, 18446744073709551615, 2, 5), - (13, 512, 840, 1116, 18446744073709551615, 1, 3), - (13, 513, 1128, 1127, 18446744073709551615, 0, 1), - (13, 514, 1113, 1126, 18446744073709551615, 0, 1), - (13, 542, 1144, 1145, 18446744073709551615, 0, 3), - (13, 543, 1145, 1146, 18446744073709551615, 0, 3), - (13, 46, 814, 1153, 18446744073709551615, 1, 2), - (13, 513, 1115, 1113, 18446744073709551615, 1, 3), - (13, 514, 1113, 1128, 18446744073709551615, 0, 1), - (13, 515, 1128, 1114, 18446744073709551615, 0, 1), - (13, 512, 1128, 1113, 18446744073709551615, 0, 1), - (13, 513, 1127, 1118, 18446744073709551615, 0, 1), - (13, 514, 1116, 840, 18446744073709551615, 3, 6), - (13, 45, 813, 1153, 18446744073709551615, 1, 2), - (13, 513, 1127, 1128, 18446744073709551615, 0, 1), - (13, 514, 1128, 1114, 18446744073709551615, 0, 1), - (13, 515, 1114, 1116, 18446744073709551615, 2, 5), - (13, 512, 1114, 1128, 18446744073709551615, 0, 1), - (13, 513, 1126, 1113, 18446744073709551615, 0, 1), - (13, 514, 840, 1115, 18446744073709551615, 1, 3), - (13, 543, 1145, 1146, 18446744073709551615, 1, 3), - (13, 44, 812, 1153, 18446744073709551615, 1, 2), - (13, 1024, 812, 44, 18446744073709551615, 220, 221), - (13, 513, 1126, 1114, 18446744073709551615, 0, 1), - (13, 514, 1114, 1116, 18446744073709551615, 2, 5), - (13, 515, 1116, 840, 18446744073709551615, 3, 6), - (13, 543, 1113, 1116, 18446744073709551615, 1, 3), - (13, 512, 1116, 1114, 18446744073709551615, 1, 3), - (13, 513, 1129, 1128, 18446744073709551615, 0, 1), - (13, 514, 1115, 1127, 18446744073709551615, 0, 1), - (13, 543, 1146, 1148, 18446744073709551615, 0, 3), - (13, 43, 811, 1153, 18446744073709551615, 1, 2), - (13, 1024, 811, 43, 18446744073709551615, 221, 222), - (13, 513, 1118, 1115, 18446744073709551615, 1, 2), - (13, 514, 1115, 1129, 18446744073709551615, 0, 1), - (13, 515, 1129, 1113, 18446744073709551615, 0, 1), - (13, 512, 1129, 1115, 18446744073709551615, 0, 1), - (13, 513, 1128, 840, 18446744073709551615, 0, 1), - (13, 514, 1114, 1116, 18446744073709551615, 3, 5), - (13, 543, 1145, 1146, 18446744073709551615, 2, 3), - (13, 42, 810, 1153, 18446744073709551615, 1, 2), - (13, 1024, 810, 42, 18446744073709551615, 222, 223), - (13, 513, 1128, 1129, 18446744073709551615, 0, 1), - (13, 514, 1129, 1113, 18446744073709551615, 0, 1), - (13, 515, 1113, 1114, 18446744073709551615, 5, 7), - (13, 512, 1113, 1129, 18446744073709551615, 0, 1), - (13, 513, 1127, 1115, 18446744073709551615, 0, 1), - (13, 514, 1116, 1118, 18446744073709551615, 1, 2), - (13, 542, 1145, 1146, 18446744073709551615, 1, 3), - (13, 543, 1146, 1148, 18446744073709551615, 1, 3), - (13, 41, 809, 1153, 18446744073709551615, 1, 2), - (13, 1024, 809, 41, 18446744073709551615, 223, 224), - (13, 513, 1127, 1113, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 4, 6), - (13, 515, 1114, 1116, 18446744073709551615, 3, 5), - (13, 512, 1114, 1113, 18446744073709551615, 1, 2), - (13, 513, 1130, 1129, 18446744073709551615, 0, 1), - (13, 514, 1118, 1128, 18446744073709551615, 0, 1), - (13, 542, 1146, 1147, 18446744073709551615, 0, 1), - (13, 40, 808, 1153, 18446744073709551615, 1, 2), - (13, 1024, 808, 40, 18446744073709551615, 224, 225), - (13, 513, 840, 1118, 18446744073709551615, 1, 2), - (13, 514, 1118, 1130, 18446744073709551615, 0, 1), - (13, 515, 1130, 1115, 18446744073709551615, 0, 1), - (13, 512, 1130, 1118, 18446744073709551615, 0, 1), - (13, 513, 1129, 1116, 18446744073709551615, 0, 1), - (13, 514, 1113, 1114, 18446744073709551615, 5, 6), - (13, 542, 1145, 1146, 18446744073709551615, 2, 3), - (13, 39, 807, 1153, 18446744073709551615, 1, 2), - (13, 1024, 807, 39, 18446744073709551615, 225, 226), - (13, 513, 1129, 1130, 18446744073709551615, 0, 1), - (13, 514, 1130, 1115, 18446744073709551615, 0, 1), - (13, 515, 1115, 1113, 18446744073709551615, 2, 4), - (13, 512, 1115, 1130, 18446744073709551615, 0, 1), - (13, 513, 1128, 1118, 18446744073709551615, 0, 1), - (13, 514, 1114, 840, 18446744073709551615, 1, 2), - (13, 542, 1147, 1148, 18446744073709551615, 0, 9), - (13, 543, 1148, 1149, 18446744073709551615, 0, 10), - (13, 38, 806, 1153, 18446744073709551615, 1, 2), - (13, 1024, 806, 38, 18446744073709551615, 226, 227), - (13, 513, 1128, 1115, 18446744073709551615, 0, 1), - (13, 514, 1115, 1113, 18446744073709551615, 2, 4), - (13, 515, 1113, 1114, 18446744073709551615, 6, 7), - (13, 512, 1113, 1115, 18446744073709551615, 1, 2), - (13, 513, 1131, 1130, 18446744073709551615, 0, 1), - (13, 514, 840, 1129, 18446744073709551615, 0, 1), - (13, 542, 1148, 1149, 18446744073709551615, 0, 20), - (13, 543, 1149, 1150, 18446744073709551615, 0, 20), - (13, 37, 805, 1153, 18446744073709551615, 1, 2), - (13, 1024, 805, 37, 18446744073709551615, 227, 228), - (13, 513, 1116, 840, 18446744073709551615, 1, 2), - (13, 514, 840, 1131, 18446744073709551615, 0, 1), - (13, 515, 1131, 1118, 18446744073709551615, 0, 1), - (13, 512, 1131, 840, 18446744073709551615, 0, 1), - (13, 513, 1130, 1114, 18446744073709551615, 0, 1), - (13, 514, 1115, 1113, 18446744073709551615, 3, 4), - (13, 543, 1148, 1149, 18446744073709551615, 2, 10), - (13, 36, 804, 1153, 18446744073709551615, 0, 1), - (13, 1024, 804, 36, 18446744073709551615, 228, 229), - (13, 513, 1130, 1131, 18446744073709551615, 0, 1), - (13, 514, 1131, 1118, 18446744073709551615, 0, 1), - (13, 515, 1118, 1115, 18446744073709551615, 2, 4), - (13, 542, 1113, 1114, 18446744073709551615, 7, 9), - (13, 512, 1118, 1131, 18446744073709551615, 0, 1), - (13, 513, 1129, 840, 18446744073709551615, 0, 1), - (13, 514, 1113, 1116, 18446744073709551615, 1, 2), - (13, 542, 1148, 1149, 18446744073709551615, 2, 20), - (13, 543, 1149, 1150, 18446744073709551615, 2, 20), - (13, 35, 803, 1153, 18446744073709551615, 0, 1), - (13, 1024, 803, 35, 18446744073709551615, 229, 230), - (13, 513, 1129, 1118, 18446744073709551615, 0, 1), - (13, 514, 1118, 1115, 18446744073709551615, 2, 4), - (13, 515, 1115, 1113, 18446744073709551615, 3, 4), - (13, 512, 1115, 1118, 18446744073709551615, 1, 2), - (13, 513, 1132, 1131, 18446744073709551615, 0, 1), - (13, 514, 1116, 1130, 18446744073709551615, 0, 1), - (13, 543, 1149, 1150, 18446744073709551615, 4, 20), - (13, 34, 802, 1153, 18446744073709551615, 0, 1), - (13, 1024, 802, 34, 18446744073709551615, 230, 231), - (13, 513, 1114, 1116, 18446744073709551615, 1, 2), - (13, 514, 1116, 1132, 18446744073709551615, 0, 1), - (13, 515, 1132, 840, 18446744073709551615, 0, 1), - (13, 512, 1132, 1116, 18446744073709551615, 0, 1), - (13, 513, 1131, 1113, 18446744073709551615, 0, 1), - (13, 514, 1118, 1115, 18446744073709551615, 3, 4), - (13, 542, 1148, 1149, 18446744073709551615, 6, 20), - (13, 543, 1149, 1150, 18446744073709551615, 6, 20), - (13, 33, 801, 1153, 18446744073709551615, 0, 1), - (13, 1024, 801, 33, 18446744073709551615, 231, 232), - (13, 513, 1131, 1132, 18446744073709551615, 0, 1), - (13, 514, 1132, 840, 18446744073709551615, 0, 1), - (13, 515, 840, 1118, 18446744073709551615, 3, 5), - (13, 512, 840, 1132, 18446744073709551615, 0, 1), - (13, 513, 1130, 1116, 18446744073709551615, 0, 1), - (13, 514, 1115, 1114, 18446744073709551615, 1, 2), - (13, 542, 1148, 1149, 18446744073709551615, 8, 20), - (13, 543, 1149, 1150, 18446744073709551615, 8, 20), - (13, 32, 800, 1153, 18446744073709551615, 0, 1), - (13, 1024, 800, 32, 18446744073709551615, 232, 233), - (13, 513, 1130, 840, 18446744073709551615, 0, 1), - (13, 514, 840, 1118, 18446744073709551615, 2, 4), - (13, 515, 1118, 1115, 18446744073709551615, 3, 4), - (13, 543, 1116, 1118, 18446744073709551615, 1, 2), - (13, 512, 1118, 840, 18446744073709551615, 1, 2), - (13, 513, 1133, 1132, 18446744073709551615, 0, 1), - (13, 514, 1114, 1131, 18446744073709551615, 0, 1), - (13, 543, 1150, 1152, 18446744073709551615, 0, 12), - (13, 31, 799, 1152, 18446744073709551615, 1, 2), - (13, 1024, 799, 31, 18446744073709551615, 233, 234), - (13, 513, 1113, 1114, 18446744073709551615, 1, 2), - (13, 514, 1114, 1133, 18446744073709551615, 0, 1), - (13, 515, 1133, 1116, 18446744073709551615, 0, 1), - (13, 543, 1130, 1133, 18446744073709551615, 0, 1), - (13, 512, 1133, 1114, 18446744073709551615, 0, 1), - (13, 513, 1132, 1115, 18446744073709551615, 0, 1), - (13, 514, 840, 1118, 18446744073709551615, 3, 4), - (13, 542, 1148, 1149, 18446744073709551615, 10, 20), - (13, 543, 1149, 1150, 18446744073709551615, 10, 20), - (13, 30, 798, 1152, 18446744073709551615, 1, 2), - (13, 1024, 798, 30, 18446744073709551615, 234, 235), - (13, 513, 1132, 1133, 18446744073709551615, 0, 1), - (13, 514, 1133, 1116, 18446744073709551615, 0, 1), - (13, 515, 1116, 840, 18446744073709551615, 4, 6), - (13, 543, 1115, 1116, 18446744073709551615, 5, 6), - (13, 542, 1118, 1115, 18446744073709551615, 4, 6), - (13, 512, 1116, 1133, 18446744073709551615, 0, 1), - (13, 513, 1131, 1114, 18446744073709551615, 0, 1), - (13, 514, 1118, 1113, 18446744073709551615, 2, 3), - (13, 542, 1149, 1150, 18446744073709551615, 2, 12), - (13, 543, 1150, 1152, 18446744073709551615, 2, 12), - (13, 29, 797, 1152, 18446744073709551615, 0, 1), - (13, 1024, 797, 29, 18446744073709551615, 235, 236), - (13, 513, 1131, 1116, 18446744073709551615, 0, 1), - (13, 514, 1116, 840, 18446744073709551615, 4, 6), - (13, 515, 840, 1118, 18446744073709551615, 4, 5), - (13, 543, 1114, 840, 18446744073709551615, 2, 3), - (13, 512, 840, 1116, 18446744073709551615, 2, 3), - (13, 513, 1134, 1133, 18446744073709551615, 0, 1), - (13, 514, 1113, 1132, 18446744073709551615, 0, 1), - (13, 542, 1152, 1151, 18446744073709551615, 0, 6), - (13, 543, 1151, 1146, 18446744073709551615, 0, 2), - (13, 28, 796, 1149, 18446744073709551615, 2, 3), - (13, 1024, 796, 28, 18446744073709551615, 236, 237), - (13, 513, 1115, 1113, 18446744073709551615, 2, 3), - (13, 514, 1113, 1134, 18446744073709551615, 0, 1), - (13, 515, 1134, 1114, 18446744073709551615, 0, 2), - (13, 543, 1131, 1134, 18446744073709551615, 0, 1), - (13, 512, 1134, 1113, 18446744073709551615, 0, 1), - (13, 513, 1133, 1118, 18446744073709551615, 0, 1), - (13, 514, 1116, 840, 18446744073709551615, 5, 6), - (13, 542, 1149, 1150, 18446744073709551615, 4, 12), - (13, 543, 1150, 1152, 18446744073709551615, 4, 12), - (13, 27, 795, 1149, 18446744073709551615, 1, 2), - (13, 1024, 795, 27, 18446744073709551615, 237, 238), - (13, 513, 1133, 1134, 18446744073709551615, 0, 1), - (13, 514, 1134, 1114, 18446744073709551615, 0, 1), - (13, 515, 1114, 1116, 18446744073709551615, 4, 5), - (13, 542, 840, 1118, 18446744073709551615, 4, 5), - (13, 512, 1114, 1134, 18446744073709551615, 0, 1), - (13, 513, 1132, 1113, 18446744073709551615, 0, 1), - (13, 514, 840, 1115, 18446744073709551615, 2, 3), - (13, 542, 1152, 1151, 18446744073709551615, 2, 6), - (13, 543, 1151, 1146, 18446744073709551615, 1, 2), - (13, 26, 794, 1149, 18446744073709551615, 0, 1), - (13, 1024, 794, 26, 18446744073709551615, 238, 239), - (13, 513, 1132, 1114, 18446744073709551615, 0, 1), - (13, 514, 1114, 1116, 18446744073709551615, 4, 5), - (13, 515, 1116, 840, 18446744073709551615, 5, 6), - (13, 542, 1115, 1113, 18446744073709551615, 4, 5), - (13, 512, 1116, 1114, 18446744073709551615, 2, 3), - (13, 513, 1135, 1134, 18446744073709551615, 0, 1), - (13, 514, 1115, 1133, 18446744073709551615, 0, 1), - (13, 542, 1151, 1153, 18446744073709551615, 0, 2), - (13, 543, 1153, 1146, 18446744073709551615, 0, 1), - (13, 513, 794, 27, 18446744073709551615, 0, 1), - (13, 514, 27, 836, 18446744073709551615, 0, 1), - (13, 515, 836, 793, 18446744073709551615, 0, 1), - (13, 543, 1115, 836, 18446744073709551615, 0, 1), - (13, 512, 836, 27, 18446744073709551615, 0, 1), - (13, 513, 1116, 1118, 18446744073709551615, 0, 1), - (13, 514, 1135, 1113, 18446744073709551615, 0, 1), - (13, 542, 1147, 1148, 18446744073709551615, 4, 9), - (13, 543, 1148, 1149, 18446744073709551615, 4, 10), - (13, 513, 1116, 836, 18446744073709551615, 0, 1), - (13, 514, 836, 793, 18446744073709551615, 0, 1), - (13, 515, 793, 1135, 18446744073709551615, 0, 2), - (13, 564, 840, 1132, 18446744073709551615, 0, 1), - (13, 512, 793, 836, 18446744073709551615, 0, 1), - (13, 513, 840, 27, 18446744073709551615, 0, 1), - (13, 514, 1113, 794, 18446744073709551615, 0, 1), - (13, 542, 1148, 1149, 18446744073709551615, 12, 20), - (13, 543, 1149, 1150, 18446744073709551615, 12, 20), - (13, 513, 840, 793, 18446744073709551615, 0, 1), - (13, 514, 793, 1135, 18446744073709551615, 0, 3), - (13, 515, 1135, 1113, 18446744073709551615, 0, 1), - (13, 542, 794, 27, 18446744073709551615, 0, 1), - (13, 512, 1135, 793, 18446744073709551615, 0, 2), - (13, 513, 1132, 836, 18446744073709551615, 0, 2), - (13, 514, 794, 1116, 18446744073709551615, 0, 1), - (13, 541, 1148, 1149, 18446744073709551615, 6, 13), - (13, 542, 1149, 1150, 18446744073709551615, 6, 12), - (13, 543, 1150, 1152, 18446744073709551615, 6, 12), - (13, 513, 1118, 794, 18446744073709551615, 0, 1), - (13, 514, 794, 1132, 18446744073709551615, 0, 1), - (13, 515, 1132, 27, 18446744073709551615, 0, 1), - (13, 543, 840, 1132, 18446744073709551615, 0, 1), - (13, 512, 1132, 794, 18446744073709551615, 0, 1), - (13, 513, 836, 1113, 18446744073709551615, 0, 1), - (13, 514, 793, 1135, 18446744073709551615, 1, 3), - (13, 541, 1147, 1148, 18446744073709551615, 14, 20), - (13, 542, 1148, 1149, 18446744073709551615, 14, 20), - (13, 543, 1149, 1150, 18446744073709551615, 14, 20), - (13, 563, 1150, 1152, 18446744073709551615, 16, 20), - (13, 513, 836, 1132, 18446744073709551615, 0, 1), - (13, 514, 1132, 27, 18446744073709551615, 0, 1), - (13, 515, 27, 793, 18446744073709551615, 0, 1), - (13, 564, 1116, 1114, 18446744073709551615, 0, 1), - (13, 541, 1116, 1135, 18446744073709551615, 1, 2), - (13, 512, 27, 1132, 18446744073709551615, 0, 1), - (13, 513, 1116, 794, 18446744073709551615, 0, 1), - (13, 514, 1135, 1118, 18446744073709551615, 0, 2), - (13, 541, 1148, 1149, 18446744073709551615, 8, 13), - (13, 542, 1149, 1150, 18446744073709551615, 8, 12), - (13, 543, 1150, 1152, 18446744073709551615, 8, 12), - (13, 563, 1151, 1150, 18446744073709551615, 12, 14), - (13, 513, 1116, 27, 18446744073709551615, 0, 1), - (13, 514, 27, 793, 18446744073709551615, 0, 1), - (13, 515, 793, 1135, 18446744073709551615, 1, 2), - (13, 542, 1132, 794, 18446744073709551615, 0, 1), - (13, 564, 1114, 1134, 18446744073709551615, 0, 1), - (13, 542, 1118, 794, 18446744073709551615, 0, 1), - (13, 512, 793, 27, 18446744073709551615, 0, 1), - (13, 513, 1114, 1132, 18446744073709551615, 0, 1), - (13, 514, 1118, 836, 18446744073709551615, 0, 1), - (13, 541, 1149, 1150, 18446744073709551615, 0, 6), - (13, 542, 1150, 1152, 18446744073709551615, 0, 6), - (13, 543, 1152, 1145, 18446744073709551615, 0, 2), - (13, 563, 1152, 1150, 18446744073709551615, 7, 9), - (13, 18, 786, 1141, 18446744073709551615, 1, 2), - (13, 1024, 786, 18, 18446744073709551615, 245, 246), - (13, 513, 1114, 793, 18446744073709551615, 0, 1), - (13, 514, 793, 1135, 18446744073709551615, 2, 3), - (13, 515, 1135, 1118, 18446744073709551615, 0, 2), - (13, 542, 27, 1132, 18446744073709551615, 0, 1), - (13, 564, 1134, 1133, 18446744073709551615, 0, 1), - (13, 542, 836, 1132, 18446744073709551615, 0, 2), - (13, 512, 1135, 793, 18446744073709551615, 1, 2), - (13, 513, 1134, 27, 18446744073709551615, 0, 1), - (13, 514, 836, 1116, 18446744073709551615, 0, 1), - (13, 540, 1149, 1150, 18446744073709551615, 4, 6), - (13, 541, 1150, 1152, 18446744073709551615, 4, 6), - (13, 542, 1152, 1151, 18446744073709551615, 4, 6), - (13, 543, 1151, 1145, 18446744073709551615, 0, 1), - (13, 562, 1148, 1149, 18446744073709551615, 9, 10), - (13, 563, 1149, 1150, 18446744073709551615, 12, 14), - (13, 17, 785, 1141, 18446744073709551615, 0, 1), - (13, 1024, 785, 17, 18446744073709551615, 246, 248), - (13, 513, 1134, 1135, 18446744073709551615, 0, 1), - (13, 514, 1135, 1118, 18446744073709551615, 1, 2), - (13, 515, 1118, 836, 18446744073709551615, 0, 1), - (13, 542, 793, 27, 18446744073709551615, 0, 1), - (13, 543, 27, 1118, 18446744073709551615, 0, 1), - (13, 563, 1138, 1133, 18446744073709551615, 0, 1), - (13, 564, 1133, 1136, 18446744073709551615, 0, 1), - (13, 562, 1137, 1138, 18446744073709551615, 11, 12), - (13, 540, 1118, 1133, 18446744073709551615, 2, 3), - (13, 541, 1133, 1116, 18446744073709551615, 1, 2), - (13, 542, 1116, 27, 18446744073709551615, 0, 1), - (13, 512, 1118, 1135, 18446744073709551615, 0, 1), - (13, 513, 1133, 793, 18446744073709551615, 0, 1), - (13, 514, 1116, 1114, 18446744073709551615, 0, 1), - (13, 539, 1149, 1150, 18446744073709551615, 2, 6), - (13, 540, 1150, 1152, 18446744073709551615, 2, 4), - (13, 541, 1152, 1151, 18446744073709551615, 2, 4), - (13, 542, 1151, 1145, 18446744073709551615, 0, 1), - (13, 543, 1145, 1147, 18446744073709551615, 0, 1), - (13, 562, 1149, 1150, 18446744073709551615, 18, 21), - (13, 563, 1150, 1152, 18446744073709551615, 17, 20), - (13, 16, 784, 1143, 18446744073709551615, 0, 1), - (13, 17, 785, 1144, 18446744073709551615, 0, 1), - (13, 16, 784, 1140, 18446744073709551615, 1, 2), - (13, 1024, 785, 17, 18446744073709551615, 247, 248), - (13, 1024, 784, 16, 18446744073709551615, 247, 249), - (13, 513, 836, 1134, 18446744073709551615, 0, 1), - (13, 514, 1134, 1135, 18446744073709551615, 0, 1), - (13, 515, 1135, 1118, 18446744073709551615, 1, 2), - (13, 541, 793, 1114, 18446744073709551615, 0, 1), - (13, 543, 1136, 1135, 18446744073709551615, 0, 1), - (13, 563, 1141, 1138, 18446744073709551615, 0, 1), - (13, 564, 1138, 1139, 18446744073709551615, 0, 1), - (13, 562, 1140, 1141, 18446744073709551615, 7, 10), - (13, 540, 1135, 1138, 18446744073709551615, 0, 1), - (13, 541, 1138, 1137, 18446744073709551615, 0, 1), - (13, 512, 1135, 1134, 18446744073709551615, 0, 1), - (13, 513, 1138, 1114, 18446744073709551615, 0, 1), - (13, 514, 1137, 793, 18446744073709551615, 0, 1), - (13, 539, 1151, 1145, 18446744073709551615, 0, 2), - (13, 540, 1145, 1147, 18446744073709551615, 5, 7), - (13, 541, 1147, 1148, 18446744073709551615, 16, 20), - (13, 542, 1148, 1149, 18446744073709551615, 16, 20), - (13, 543, 1149, 1150, 18446744073709551615, 16, 20), - (13, 561, 1151, 1149, 18446744073709551615, 10, 12), - (13, 562, 1149, 1150, 18446744073709551615, 19, 21), - (13, 563, 1150, 1152, 18446744073709551615, 18, 20), - (13, 15, 783, 1141, 18446744073709551615, 0, 1), - (13, 16, 784, 1142, 18446744073709551615, 0, 1), - (13, 15, 783, 793, 18446744073709551615, 0, 1), - (13, 1024, 784, 16, 18446744073709551615, 248, 249), - (13, 1024, 783, 15, 18446744073709551615, 248, 250), - (13, 513, 1136, 1138, 18446744073709551615, 0, 1), - (13, 514, 1138, 1135, 18446744073709551615, 0, 1), - (13, 515, 1135, 1137, 18446744073709551615, 0, 1), - (13, 563, 1140, 1132, 18446744073709551615, 0, 1), - (13, 564, 1132, 793, 18446744073709551615, 0, 1), - (13, 562, 1139, 1140, 18446744073709551615, 9, 10), - (13, 540, 1135, 1132, 18446744073709551615, 1, 2), - (13, 512, 1135, 1138, 18446744073709551615, 0, 1), - (13, 513, 1132, 836, 18446744073709551615, 1, 2), - (13, 514, 1114, 1118, 18446744073709551615, 0, 1), - (13, 539, 1152, 1151, 18446744073709551615, 0, 2), - (13, 540, 1151, 1145, 18446744073709551615, 0, 1), - (13, 541, 1145, 1147, 18446744073709551615, 3, 4), - (13, 542, 1147, 1148, 18446744073709551615, 6, 9), - (13, 543, 1148, 1149, 18446744073709551615, 6, 10), - (13, 561, 1152, 1151, 18446744073709551615, 20, 24), - (13, 562, 1151, 1149, 18446744073709551615, 7, 8), - (13, 563, 1149, 1150, 18446744073709551615, 13, 14), - (13, 14, 782, 1141, 18446744073709551615, 1, 2), - (13, 15, 783, 1142, 18446744073709551615, 1, 2), - (13, 14, 782, 793, 18446744073709551615, 0, 1), - (13, 1024, 783, 15, 18446744073709551615, 249, 250), - (13, 1024, 782, 14, 18446744073709551615, 249, 252), - (13, 513, 1135, 1137, 18446744073709551615, 0, 1), - (13, 514, 1137, 1136, 18446744073709551615, 0, 1), - (13, 515, 1136, 1132, 18446744073709551615, 0, 1), - (13, 539, 836, 1114, 18446744073709551615, 0, 1), - (13, 543, 17, 1136, 18446744073709551615, 0, 1), - (13, 562, 1140, 1141, 18446744073709551615, 8, 10), - (13, 563, 1141, 793, 18446744073709551615, 0, 1), - (13, 564, 793, 1139, 18446744073709551615, 0, 1), - (13, 561, 1139, 1140, 18446744073709551615, 3, 4), - (13, 562, 1140, 1141, 18446744073709551615, 9, 10), - (13, 512, 1136, 1137, 18446744073709551615, 0, 1), - (13, 513, 793, 836, 18446744073709551615, 0, 1), - (13, 514, 1118, 1138, 18446744073709551615, 0, 1), - (13, 538, 1152, 1151, 18446744073709551615, 2, 4), - (13, 539, 1151, 1145, 18446744073709551615, 1, 2), - (13, 540, 1145, 1147, 18446744073709551615, 6, 7), - (13, 541, 1147, 1148, 18446744073709551615, 18, 20), - (13, 542, 1148, 1149, 18446744073709551615, 18, 20), - (13, 543, 1149, 1150, 18446744073709551615, 18, 20), - (13, 560, 1152, 1151, 18446744073709551615, 46, 48), - (13, 561, 1151, 1149, 18446744073709551615, 11, 12), - (13, 562, 1149, 1150, 18446744073709551615, 20, 21), - (13, 563, 1150, 1152, 18446744073709551615, 19, 20), - (13, 13, 781, 1141, 18446744073709551615, 0, 1), - (13, 14, 782, 1142, 18446744073709551615, 0, 1), - (13, 13, 781, 1138, 18446744073709551615, 0, 1), - (13, 1024, 782, 14, 18446744073709551615, 250, 252), - (13, 1024, 781, 13, 18446744073709551615, 250, 255), - (13, 513, 1136, 1132, 18446744073709551615, 0, 1), - (13, 514, 1132, 1135, 18446744073709551615, 0, 1), - (13, 515, 1135, 793, 18446744073709551615, 0, 1), - (13, 539, 836, 1118, 18446744073709551615, 1, 2), - (13, 540, 1118, 1137, 18446744073709551615, 0, 1), - (13, 543, 16, 1135, 18446744073709551615, 0, 1), - (13, 561, 1140, 1141, 18446744073709551615, 4, 6), - (13, 562, 1141, 1142, 18446744073709551615, 7, 9), - (13, 563, 1142, 1139, 18446744073709551615, 0, 1), - (13, 564, 1139, 1140, 18446744073709551615, 0, 1), - (13, 560, 1139, 1140, 18446744073709551615, 12, 13), - (13, 561, 1140, 1141, 18446744073709551615, 5, 6), - (13, 562, 1141, 1142, 18446744073709551615, 8, 9), - (13, 540, 1135, 1139, 18446744073709551615, 0, 1), - (13, 541, 1139, 1138, 18446744073709551615, 0, 1), - (13, 542, 1138, 16, 18446744073709551615, 0, 1), - (13, 538, 1139, 1138, 18446744073709551615, 0, 1), - (13, 512, 1135, 1132, 18446744073709551615, 0, 1), - (13, 513, 1139, 836, 18446744073709551615, 0, 1), - (13, 514, 1138, 1137, 18446744073709551615, 0, 1), - (13, 537, 1152, 1151, 18446744073709551615, 0, 2), - (13, 538, 1151, 1145, 18446744073709551615, 0, 1), - (13, 539, 1145, 1147, 18446744073709551615, 2, 3), - (13, 540, 1147, 1148, 18446744073709551615, 10, 12), - (13, 541, 1148, 1149, 18446744073709551615, 10, 13), - (13, 542, 1149, 1150, 18446744073709551615, 10, 12), - (13, 543, 1150, 1152, 18446744073709551615, 10, 12), - (13, 560, 1151, 1149, 18446744073709551615, 11, 12), - (13, 561, 1149, 1152, 18446744073709551615, 11, 12), - (13, 562, 1152, 1151, 18446744073709551615, 38, 40), - (13, 563, 1151, 1150, 18446744073709551615, 13, 14), - (13, 1025, 12, 13, 18446744073709551615, 250, 251), - (13, 12, 780, 1141, 18446744073709551615, 0, 1), - (13, 13, 781, 1142, 18446744073709551615, 0, 1), - (13, 14, 782, 1143, 18446744073709551615, 0, 1), - (13, 1028, 781, 13, 18446744073709551615, 249, 253), - (13, 12, 780, 1137, 18446744073709551615, 0, 1), - (13, 13, 781, 15, 18446744073709551615, 0, 1), - (13, 1024, 782, 14, 18446744073709551615, 251, 252), - (13, 1024, 781, 13, 18446744073709551615, 251, 255), - (13, 1024, 780, 12, 18446744073709551615, 251, 255), - (13, 513, 1135, 793, 18446744073709551615, 0, 1), - (13, 514, 793, 1136, 18446744073709551615, 0, 1), - (13, 515, 1136, 1139, 18446744073709551615, 0, 1), - (13, 539, 836, 16, 18446744073709551615, 0, 1), - (13, 540, 16, 1132, 18446744073709551615, 0, 1), - (13, 541, 1132, 836, 18446744073709551615, 0, 1), - (13, 542, 836, 1137, 18446744073709551615, 0, 1), - (13, 543, 1137, 1136, 18446744073709551615, 0, 1), - (13, 561, 1141, 1142, 18446744073709551615, 6, 8), - (13, 562, 1142, 1143, 18446744073709551615, 9, 11), - (13, 563, 1143, 1140, 18446744073709551615, 0, 1), - (13, 564, 1140, 1141, 18446744073709551615, 0, 1), - (13, 560, 1140, 1141, 18446744073709551615, 18, 19), - (13, 561, 1141, 1142, 18446744073709551615, 7, 8), - (13, 562, 1142, 1143, 18446744073709551615, 10, 11), - (13, 540, 1136, 1140, 18446744073709551615, 0, 1), - (13, 541, 1140, 15, 18446744073709551615, 0, 1), - (13, 542, 15, 1137, 18446744073709551615, 0, 1), - (13, 538, 1140, 15, 18446744073709551615, 0, 1), - (13, 512, 1136, 793, 18446744073709551615, 0, 1), - (13, 513, 1140, 836, 18446744073709551615, 0, 1), - (13, 514, 15, 1132, 18446744073709551615, 0, 1), - (13, 537, 1144, 1146, 18446744073709551615, 1, 2), - (13, 538, 1146, 1147, 18446744073709551615, 2, 6), - (13, 539, 1147, 1148, 18446744073709551615, 2, 6), - (13, 540, 1148, 1149, 18446744073709551615, 2, 6), - (13, 541, 1149, 1150, 18446744073709551615, 2, 6), - (13, 542, 1150, 1152, 18446744073709551615, 2, 6), - (13, 543, 1152, 1145, 18446744073709551615, 1, 2), - (13, 559, 1148, 1150, 18446744073709551615, 8, 9), - (13, 560, 1150, 1152, 18446744073709551615, 30, 34), - (13, 561, 1152, 1149, 18446744073709551615, 5, 6), - (13, 562, 1149, 1152, 18446744073709551615, 4, 5), - (13, 563, 1152, 1150, 18446744073709551615, 8, 9), - (13, 1025, 11, 12, 18446744073709551615, 251, 254), - (13, 11, 779, 783, 18446744073709551615, 0, 4), - (13, 12, 780, 1142, 18446744073709551615, 0, 1), - (13, 13, 781, 1143, 18446744073709551615, 0, 1), - (13, 11, 779, 836, 18446744073709551615, 8, 10), - (13, 12, 780, 1132, 18446744073709551615, 4, 5), - (13, 1024, 781, 13, 18446744073709551615, 252, 255), - (13, 1024, 780, 12, 18446744073709551615, 252, 255), - (13, 1024, 779, 11, 18446744073709551615, 252, 257), - (13, 513, 1136, 1139, 18446744073709551615, 0, 1), - (13, 514, 1139, 1135, 18446744073709551615, 0, 1), - (13, 515, 1135, 1140, 18446744073709551615, 0, 1), - (13, 539, 836, 15, 18446744073709551615, 0, 1), - (13, 540, 15, 793, 18446744073709551615, 0, 1), - (13, 541, 793, 836, 18446744073709551615, 0, 1), - (13, 542, 836, 1132, 18446744073709551615, 1, 2), - (13, 543, 1132, 1135, 18446744073709551615, 1, 2), - (13, 560, 1141, 1142, 18446744073709551615, 9, 10), - (13, 561, 1142, 1143, 18446744073709551615, 3, 5), - (13, 562, 1143, 1144, 18446744073709551615, 6, 8), - (13, 563, 1144, 783, 18446744073709551615, 0, 1), - (13, 564, 783, 1142, 18446744073709551615, 0, 1), - (13, 560, 783, 1142, 18446744073709551615, 0, 1), - (13, 561, 1142, 1143, 18446744073709551615, 4, 5), - (13, 562, 1143, 1144, 18446744073709551615, 7, 8), - (13, 540, 1135, 783, 18446744073709551615, 0, 1), - (13, 541, 783, 1141, 18446744073709551615, 0, 1), - (13, 542, 1141, 1132, 18446744073709551615, 0, 2), - (13, 537, 1135, 783, 18446744073709551615, 0, 1), - (13, 512, 1135, 1139, 18446744073709551615, 0, 1), - (13, 513, 783, 836, 18446744073709551615, 0, 1), - (13, 514, 1141, 793, 18446744073709551615, 0, 1), - (13, 536, 1151, 0, 18446744073709551615, 0, 1), - (13, 537, 0, 1146, 18446744073709551615, 0, 1), - (13, 538, 1146, 1147, 18446744073709551615, 4, 6), - (13, 539, 1147, 1148, 18446744073709551615, 4, 6), - (13, 540, 1148, 1149, 18446744073709551615, 4, 6), - (13, 541, 1149, 1150, 18446744073709551615, 4, 6), - (13, 542, 1150, 1152, 18446744073709551615, 4, 6), - (13, 543, 1152, 1151, 18446744073709551615, 0, 2), - (13, 558, 1147, 1149, 18446744073709551615, 0, 1), - (13, 559, 1149, 1150, 18446744073709551615, 21, 23), - (13, 560, 1150, 1152, 18446744073709551615, 32, 34), - (13, 561, 1152, 1151, 18446744073709551615, 22, 24), - (13, 562, 1151, 1148, 18446744073709551615, 0, 1), - (13, 563, 1148, 1149, 18446744073709551615, 3, 4), - (13, 1025, 11, 12, 18446744073709551615, 252, 254), - (13, 10, 778, 1144, 18446744073709551615, 0, 3), - (13, 11, 779, 14, 18446744073709551615, 0, 3), - (13, 12, 780, 1145, 18446744073709551615, 0, 1), - (13, 13, 781, 1146, 18446744073709551615, 0, 1), - (13, 1028, 780, 12, 18446744073709551615, 251, 253), - (13, 1028, 781, 13, 18446744073709551615, 251, 253), - (13, 10, 778, 793, 18446744073709551615, 3, 5), - (13, 11, 779, 1142, 18446744073709551615, 0, 1), - (13, 12, 780, 1143, 18446744073709551615, 0, 1), - (13, 1024, 781, 13, 18446744073709551615, 253, 255), - (13, 1024, 780, 12, 18446744073709551615, 253, 255), - (13, 1024, 779, 11, 18446744073709551615, 253, 257), - (13, 1024, 778, 10, 18446744073709551615, 253, 257), - (13, 513, 1132, 1141, 18446744073709551615, 0, 2), - (13, 514, 1141, 783, 18446744073709551615, 0, 2), - (13, 515, 783, 1135, 18446744073709551615, 0, 2), - (13, 538, 1151, 1150, 18446744073709551615, 0, 1), - (13, 539, 1151, 1152, 18446744073709551615, 0, 1), - (13, 540, 1151, 1150, 18446744073709551615, 0, 1), - (13, 541, 1151, 1152, 18446744073709551615, 0, 1), - (13, 542, 1151, 1150, 18446744073709551615, 0, 1), - (13, 543, 1151, 1152, 18446744073709551615, 0, 1), - (13, 559, 1151, 1152, 18446744073709551615, 6, 7), - (13, 560, 1151, 1150, 18446744073709551615, 0, 1), - (13, 561, 1151, 1152, 18446744073709551615, 4, 5), - (13, 562, 1151, 1150, 18446744073709551615, 3, 4), - (13, 563, 1151, 1152, 18446744073709551615, 8, 9), - (13, 536, 1148, 1149, 18446744073709551615, 2, 4), - (13, 537, 1149, 1152, 18446744073709551615, 0, 2), - (13, 538, 1152, 1150, 18446744073709551615, 0, 2), - (13, 539, 1150, 1151, 18446744073709551615, 0, 2), - (13, 540, 1151, 0, 18446744073709551615, 0, 2), - (13, 541, 0, 1146, 18446744073709551615, 0, 1), - (13, 542, 1146, 1148, 18446744073709551615, 0, 1), - (13, 543, 1148, 1149, 18446744073709551615, 8, 10), - (13, 557, 1150, 1151, 18446744073709551615, 0, 2), - (13, 558, 1151, 0, 18446744073709551615, 1, 3), - (13, 559, 0, 1149, 18446744073709551615, 3, 4), - (13, 560, 1149, 1150, 18446744073709551615, 13, 14), - (13, 561, 1150, 1151, 18446744073709551615, 6, 8), - (13, 562, 1151, 0, 18446744073709551615, 0, 2), - (13, 563, 0, 1152, 18446744073709551615, 0, 1), - (13, 1025, 10, 11, 18446744073709551615, 253, 254), - (13, 1025, 11, 12, 18446744073709551615, 253, 254), - (13, 9, 777, 1144, 18446744073709551615, 0, 1), - (13, 10, 778, 1145, 18446744073709551615, 0, 1), - (13, 11, 779, 1146, 18446744073709551615, 0, 4), - (13, 12, 780, 1147, 18446744073709551615, 0, 1), - (13, 13, 781, 1148, 18446744073709551615, 0, 1), - (13, 1028, 778, 10, 18446744073709551615, 252, 255), - (13, 1028, 779, 11, 18446744073709551615, 252, 255), - (13, 1028, 780, 12, 18446744073709551615, 252, 253), - (13, 1028, 781, 13, 18446744073709551615, 252, 253), - (13, 9, 777, 793, 18446744073709551615, 2, 3), - (13, 10, 778, 1142, 18446744073709551615, 0, 1), - (13, 11, 779, 1143, 18446744073709551615, 0, 2), - (13, 12, 780, 1144, 18446744073709551615, 0, 1), - (13, 1024, 781, 13, 18446744073709551615, 254, 255), - (13, 1024, 780, 12, 18446744073709551615, 254, 255), - (13, 1024, 779, 11, 18446744073709551615, 254, 257), - (13, 1024, 778, 10, 18446744073709551615, 254, 257), - (13, 1024, 777, 9, 18446744073709551615, 254, 258), - (13, 513, 1141, 15, 18446744073709551615, 0, 2), - (13, 514, 15, 1136, 18446744073709551615, 0, 2), - (13, 515, 1136, 1140, 18446744073709551615, 0, 2), - (13, 537, 1132, 1150, 18446744073709551615, 0, 1), - (13, 538, 1132, 1151, 18446744073709551615, 0, 3), - (13, 539, 1132, 1150, 18446744073709551615, 0, 1), - (13, 540, 1132, 1151, 18446744073709551615, 0, 1), - (13, 541, 1132, 1150, 18446744073709551615, 0, 1), - (13, 542, 1132, 1151, 18446744073709551615, 0, 1), - (13, 543, 1132, 1150, 18446744073709551615, 0, 1), - (13, 559, 1132, 1150, 18446744073709551615, 0, 1), - (13, 560, 1132, 1151, 18446744073709551615, 0, 2), - (13, 561, 1132, 1150, 18446744073709551615, 0, 1), - (13, 562, 1132, 1151, 18446744073709551615, 0, 1), - (13, 563, 1132, 1150, 18446744073709551615, 0, 1), - (13, 535, 1149, 1152, 18446744073709551615, 0, 4), - (13, 536, 1152, 1150, 18446744073709551615, 0, 4), - (13, 537, 1150, 1151, 18446744073709551615, 0, 2), - (13, 538, 1151, 1132, 18446744073709551615, 0, 2), - (13, 539, 1132, 0, 18446744073709551615, 0, 2), - (13, 540, 0, 1147, 18446744073709551615, 3, 4), - (13, 541, 1147, 1149, 18446744073709551615, 0, 1), - (13, 542, 1149, 1152, 18446744073709551615, 0, 3), - (13, 543, 1152, 1150, 18446744073709551615, 0, 4), - (13, 556, 1151, 1132, 18446744073709551615, 0, 3), - (13, 557, 1132, 0, 18446744073709551615, 0, 2), - (13, 558, 0, 1152, 18446744073709551615, 0, 1), - (13, 559, 1152, 1151, 18446744073709551615, 28, 29), - (13, 560, 1151, 1132, 18446744073709551615, 0, 2), - (13, 561, 1132, 0, 18446744073709551615, 0, 2), - (13, 562, 0, 1150, 18446744073709551615, 6, 7), - (13, 563, 1150, 1151, 18446744073709551615, 1, 2), - (13, 1025, 8, 9, 18446744073709551615, 254, 256), - (13, 1025, 9, 10, 18446744073709551615, 254, 256), - (13, 8, 776, 1142, 18446744073709551615, 1, 3), - (13, 9, 777, 1143, 18446744073709551615, 1, 4), - (13, 10, 778, 1144, 18446744073709551615, 1, 3), - (13, 11, 779, 1145, 18446744073709551615, 0, 1), - (13, 1028, 777, 9, 18446744073709551615, 253, 256), - (13, 1028, 778, 10, 18446744073709551615, 253, 255), - (13, 1028, 779, 11, 18446744073709551615, 253, 255), - (13, 8, 776, 836, 18446744073709551615, 10, 11), - (13, 9, 777, 1146, 18446744073709551615, 0, 1), - (13, 10, 778, 793, 18446744073709551615, 4, 5), - (13, 1024, 779, 11, 18446744073709551615, 255, 257), - (13, 1024, 778, 10, 18446744073709551615, 255, 257), - (13, 1024, 777, 9, 18446744073709551615, 255, 258), - (13, 1024, 776, 8, 18446744073709551615, 255, 262), - (13, 513, 12, 13, 18446744073709551615, 0, 2), - (13, 514, 13, 780, 18446744073709551615, 0, 2), - (13, 515, 780, 781, 18446744073709551615, 0, 2), - (13, 536, 1141, 1151, 18446744073709551615, 0, 1), - (13, 537, 1141, 1132, 18446744073709551615, 0, 1), - (13, 538, 1141, 1151, 18446744073709551615, 0, 1), - (13, 539, 1141, 1132, 18446744073709551615, 0, 1), - (13, 540, 1141, 1151, 18446744073709551615, 0, 1), - (13, 541, 1141, 1132, 18446744073709551615, 0, 1), - (13, 542, 1141, 1151, 18446744073709551615, 0, 1), - (13, 543, 1141, 1132, 18446744073709551615, 0, 1), - (13, 558, 1141, 1151, 18446744073709551615, 0, 1), - (13, 559, 1141, 1132, 18446744073709551615, 0, 1), - (13, 560, 1141, 1151, 18446744073709551615, 0, 1), - (13, 561, 1141, 1132, 18446744073709551615, 0, 1), - (13, 562, 1141, 1151, 18446744073709551615, 0, 1), - (13, 563, 1141, 1132, 18446744073709551615, 0, 1), - (13, 533, 0, 1147, 18446744073709551615, 0, 1), - (13, 536, 1152, 1150, 18446744073709551615, 2, 4), - (13, 538, 1132, 1151, 18446744073709551615, 1, 3), - (13, 539, 1151, 1141, 18446744073709551615, 0, 2), - (13, 540, 1141, 0, 18446744073709551615, 0, 2), - (13, 541, 0, 1148, 18446744073709551615, 0, 1), - (13, 542, 1148, 1152, 18446744073709551615, 0, 1), - (13, 543, 1152, 1150, 18446744073709551615, 2, 4), - (13, 556, 1132, 1151, 18446744073709551615, 1, 3), - (13, 557, 1151, 1141, 18446744073709551615, 0, 2), - (13, 558, 1141, 0, 18446744073709551615, 0, 2), - (13, 559, 0, 1150, 18446744073709551615, 9, 10), - (13, 560, 1150, 1151, 18446744073709551615, 10, 11), - (13, 561, 1151, 1141, 18446744073709551615, 0, 2), - (13, 562, 1141, 0, 18446744073709551615, 0, 2), - (13, 563, 0, 1132, 18446744073709551615, 0, 1), - (13, 1025, 8, 9, 18446744073709551615, 255, 256), - (13, 1025, 9, 10, 18446744073709551615, 255, 256), - (13, 7, 775, 1144, 18446744073709551615, 0, 2), - (13, 8, 776, 1147, 18446744073709551615, 0, 1), - (13, 9, 777, 1148, 18446744073709551615, 0, 1), - (13, 10, 778, 1149, 18446744073709551615, 0, 1), - (13, 11, 779, 1152, 18446744073709551615, 0, 2), - (13, 1028, 776, 8, 18446744073709551615, 254, 260), - (13, 1028, 777, 9, 18446744073709551615, 254, 256), - (13, 1028, 778, 10, 18446744073709551615, 254, 255), - (13, 1028, 779, 11, 18446744073709551615, 254, 255), - (13, 7, 775, 793, 18446744073709551615, 4, 5), - (13, 8, 776, 1142, 18446744073709551615, 2, 3), - (13, 9, 777, 1143, 18446744073709551615, 2, 4), - (13, 10, 778, 1144, 18446744073709551615, 2, 3), - (13, 1024, 779, 11, 18446744073709551615, 256, 257), - (13, 1024, 778, 10, 18446744073709551615, 256, 257), - (13, 1024, 777, 9, 18446744073709551615, 256, 258), - (13, 1024, 776, 8, 18446744073709551615, 256, 262), - (13, 1024, 775, 7, 18446744073709551615, 256, 262), - (13, 513, 1139, 14, 18446744073709551615, 0, 2), - (13, 514, 14, 836, 18446744073709551615, 0, 2), - (13, 515, 836, 1145, 18446744073709551615, 0, 2), - (13, 536, 1141, 1132, 18446744073709551615, 0, 1), - (13, 537, 1141, 1151, 18446744073709551615, 0, 1), - (13, 538, 1141, 1132, 18446744073709551615, 0, 1), - (13, 539, 1141, 1151, 18446744073709551615, 0, 1), - (13, 540, 1141, 1132, 18446744073709551615, 0, 1), - (13, 541, 1141, 1151, 18446744073709551615, 0, 1), - (13, 542, 1141, 1132, 18446744073709551615, 1, 2), - (13, 543, 1141, 1151, 18446744073709551615, 0, 1), - (13, 557, 1141, 1151, 18446744073709551615, 0, 1), - (13, 558, 1141, 1132, 18446744073709551615, 0, 1), - (13, 559, 1141, 1151, 18446744073709551615, 0, 1), - (13, 560, 1141, 1132, 18446744073709551615, 0, 1), - (13, 561, 1141, 1151, 18446744073709551615, 0, 1), - (13, 562, 1141, 1132, 18446744073709551615, 0, 1), - (13, 563, 1141, 1151, 18446744073709551615, 0, 1), - (13, 532, 1149, 1150, 18446744073709551615, 0, 2), - (13, 533, 1150, 1151, 18446744073709551615, 0, 2), - (13, 534, 1151, 1132, 18446744073709551615, 0, 3), - (13, 535, 1132, 1141, 18446744073709551615, 0, 2), - (13, 536, 1141, 12, 18446744073709551615, 0, 2), - (13, 539, 1149, 1150, 18446744073709551615, 4, 6), - (13, 540, 1150, 1151, 18446744073709551615, 0, 2), - (13, 541, 1151, 1132, 18446744073709551615, 0, 2), - (13, 542, 1132, 1141, 18446744073709551615, 0, 2), - (13, 554, 1141, 12, 18446744073709551615, 0, 2), - (13, 555, 12, 1150, 18446744073709551615, 0, 1), - (13, 556, 1150, 1132, 18446744073709551615, 0, 1), - (13, 558, 1141, 12, 18446744073709551615, 0, 2), - (13, 559, 12, 1151, 18446744073709551615, 0, 1), - (13, 560, 1151, 1141, 18446744073709551615, 0, 1), - (13, 561, 1141, 12, 18446744073709551615, 0, 2), - (13, 562, 12, 1132, 18446744073709551615, 0, 1), - (13, 563, 1132, 1141, 18446744073709551615, 0, 1), - (13, 1025, 6, 7, 18446744073709551615, 256, 261), - (13, 1025, 7, 8, 18446744073709551615, 256, 257), - (13, 7, 775, 1142, 18446744073709551615, 1, 2), - (13, 8, 776, 1152, 18446744073709551615, 0, 1), - (13, 9, 777, 1143, 18446744073709551615, 3, 4), - (13, 1028, 775, 7, 18446744073709551615, 255, 260), - (13, 1028, 776, 8, 18446744073709551615, 255, 260), - (13, 1028, 777, 9, 18446744073709551615, 255, 256), - (13, 7, 775, 781, 18446744073709551615, 0, 1), - (13, 8, 776, 793, 18446744073709551615, 4, 5), - (13, 1024, 777, 9, 18446744073709551615, 257, 258), - (13, 1024, 776, 8, 18446744073709551615, 257, 262), - (13, 1024, 775, 7, 18446744073709551615, 257, 262), - (13, 513, 10, 11, 18446744073709551615, 0, 2), - (13, 514, 11, 778, 18446744073709551615, 0, 2), - (13, 515, 778, 779, 18446744073709551615, 0, 2), - (13, 535, 1139, 12, 18446744073709551615, 0, 1), - (13, 536, 1139, 1141, 18446744073709551615, 0, 1), - (13, 537, 1139, 12, 18446744073709551615, 0, 1), - (13, 538, 1139, 1141, 18446744073709551615, 0, 1), - (13, 539, 1139, 12, 18446744073709551615, 0, 1), - (13, 540, 1139, 1141, 18446744073709551615, 0, 1), - (13, 541, 1139, 12, 18446744073709551615, 0, 1), - (13, 542, 1139, 1141, 18446744073709551615, 0, 1), - (13, 543, 1139, 12, 18446744073709551615, 0, 1), - (13, 557, 1139, 12, 18446744073709551615, 0, 1), - (13, 558, 1139, 1141, 18446744073709551615, 0, 1), - (13, 559, 1139, 12, 18446744073709551615, 0, 1), - (13, 560, 1139, 1141, 18446744073709551615, 0, 1), - (13, 561, 1139, 12, 18446744073709551615, 0, 1), - (13, 562, 1139, 1141, 18446744073709551615, 6, 7), - (13, 563, 1139, 12, 18446744073709551615, 0, 1), - (13, 533, 0, 1148, 18446744073709551615, 0, 1), - (13, 534, 1148, 1150, 18446744073709551615, 0, 1), - (13, 535, 1150, 1151, 18446744073709551615, 0, 2), - (13, 536, 1151, 1132, 18446744073709551615, 0, 2), - (13, 537, 1132, 12, 18446744073709551615, 0, 2), - (13, 539, 1141, 1139, 18446744073709551615, 0, 2), - (13, 540, 1139, 0, 18446744073709551615, 0, 2), - (13, 541, 0, 1149, 18446744073709551615, 0, 1), - (13, 542, 1149, 1151, 18446744073709551615, 0, 1), - (13, 543, 1151, 1132, 18446744073709551615, 0, 2), - (13, 554, 0, 1151, 18446744073709551615, 0, 1), - (13, 555, 1151, 12, 18446744073709551615, 0, 1), - (13, 556, 12, 1141, 18446744073709551615, 0, 2), - (13, 557, 1141, 1139, 18446744073709551615, 0, 2), - (13, 558, 1139, 0, 18446744073709551615, 0, 2), - (13, 559, 0, 1132, 18446744073709551615, 0, 1), - (13, 560, 1132, 1141, 18446744073709551615, 1, 2), - (13, 561, 1141, 1139, 18446744073709551615, 6, 8), - (13, 562, 1139, 0, 18446744073709551615, 0, 2), - (13, 563, 0, 12, 18446744073709551615, 0, 1), - (13, 1025, 5, 6, 18446744073709551615, 257, 261), - (13, 1025, 6, 7, 18446744073709551615, 257, 261), - (13, 5, 773, 1146, 18446744073709551615, 0, 1), - (13, 6, 774, 1142, 18446744073709551615, 0, 2), - (13, 7, 775, 1152, 18446744073709551615, 0, 2), - (13, 8, 776, 1143, 18446744073709551615, 1, 2), - (13, 1028, 774, 6, 18446744073709551615, 256, 260), - (13, 1028, 775, 7, 18446744073709551615, 256, 260), - (13, 1028, 776, 8, 18446744073709551615, 256, 260), - (13, 6, 774, 793, 18446744073709551615, 6, 7), - (13, 7, 775, 1147, 18446744073709551615, 0, 1), - (13, 1024, 776, 8, 18446744073709551615, 258, 262), - (13, 1024, 775, 7, 18446744073709551615, 258, 262), - (13, 1024, 774, 6, 18446744073709551615, 258, 262), - (13, 1024, 773, 5, 18446744073709551615, 258, 262), - (13, 513, 9, 777, 18446744073709551615, 0, 2), - (13, 514, 777, 14, 18446744073709551615, 0, 2), - (13, 515, 14, 781, 18446744073709551615, 0, 2), - (13, 534, 1149, 1144, 18446744073709551615, 0, 1), - (13, 535, 1149, 1148, 18446744073709551615, 0, 1), - (13, 536, 1149, 1144, 18446744073709551615, 0, 1), - (13, 537, 1149, 1148, 18446744073709551615, 0, 1), - (13, 538, 1149, 1144, 18446744073709551615, 0, 1), - (13, 539, 1149, 1148, 18446744073709551615, 0, 1), - (13, 540, 1149, 1144, 18446744073709551615, 0, 1), - (13, 541, 1149, 1148, 18446744073709551615, 0, 1), - (13, 542, 1149, 1144, 18446744073709551615, 0, 1), - (13, 543, 1149, 1148, 18446744073709551615, 0, 1), - (13, 556, 1149, 1144, 18446744073709551615, 0, 1), - (13, 557, 1149, 1148, 18446744073709551615, 0, 1), - (13, 558, 1149, 1144, 18446744073709551615, 0, 1), - (13, 559, 1149, 1148, 18446744073709551615, 0, 1), - (13, 560, 1149, 1144, 18446744073709551615, 0, 1), - (13, 561, 1149, 1148, 18446744073709551615, 0, 1), - (13, 562, 1149, 1144, 18446744073709551615, 0, 1), - (13, 563, 1149, 1148, 18446744073709551615, 6, 7), - (13, 530, 1139, 10, 18446744073709551615, 0, 2), - (13, 531, 10, 0, 18446744073709551615, 0, 2), - (13, 532, 0, 1153, 18446744073709551615, 0, 2), - (13, 533, 1153, 1150, 18446744073709551615, 0, 1), - (13, 535, 1132, 12, 18446744073709551615, 0, 2), - (13, 537, 1141, 1139, 18446744073709551615, 0, 2), - (13, 538, 1139, 10, 18446744073709551615, 0, 2), - (13, 539, 10, 0, 18446744073709551615, 0, 2), - (13, 540, 0, 1153, 18446744073709551615, 0, 2), - (13, 541, 1153, 1151, 18446744073709551615, 0, 1), - (13, 542, 1151, 12, 18446744073709551615, 0, 1), - (13, 543, 12, 1141, 18446744073709551615, 0, 2), - (13, 554, 1153, 12, 18446744073709551615, 0, 1), - (13, 555, 12, 1139, 18446744073709551615, 0, 1), - (13, 556, 1139, 10, 18446744073709551615, 0, 3), - (13, 557, 10, 0, 18446744073709551615, 0, 2), - (13, 558, 0, 1153, 18446744073709551615, 0, 4), - (13, 559, 1153, 1141, 18446744073709551615, 0, 1), - (13, 560, 1141, 10, 18446744073709551615, 0, 1), - (13, 561, 10, 0, 18446744073709551615, 0, 2), - (13, 562, 0, 1153, 18446744073709551615, 0, 2), - (13, 563, 1153, 1139, 18446744073709551615, 0, 1), - (13, 1025, 4, 5, 18446744073709551615, 258, 261), - (13, 1025, 5, 6, 18446744073709551615, 258, 261), - (13, 1025, 6, 7, 18446744073709551615, 258, 261), - (13, 4, 772, 1152, 18446744073709551615, 0, 3), - (13, 5, 773, 1143, 18446744073709551615, 0, 1), - (13, 6, 774, 1144, 18446744073709551615, 0, 1), - (13, 7, 775, 1149, 18446744073709551615, 0, 1), - (13, 8, 776, 1150, 18446744073709551615, 0, 1), - (13, 1028, 773, 5, 18446744073709551615, 257, 260), - (13, 1028, 774, 6, 18446744073709551615, 257, 260), - (13, 1028, 775, 7, 18446744073709551615, 257, 260), - (13, 1028, 776, 8, 18446744073709551615, 257, 260), - (13, 6, 774, 1142, 18446744073709551615, 1, 2), - (13, 7, 775, 1152, 18446744073709551615, 1, 2), - (13, 1024, 776, 8, 18446744073709551615, 259, 262), - (13, 1024, 775, 7, 18446744073709551615, 259, 262), - (13, 1024, 774, 6, 18446744073709551615, 259, 262), - (13, 1024, 773, 5, 18446744073709551615, 259, 262), - (13, 1024, 772, 4, 18446744073709551615, 259, 521), - (13, 513, 793, 1147, 18446744073709551615, 0, 2), - (13, 514, 1147, 1146, 18446744073709551615, 0, 2), - (13, 515, 1146, 1148, 18446744073709551615, 0, 2), - (13, 534, 1150, 1149, 18446744073709551615, 0, 1), - (13, 535, 1150, 1144, 18446744073709551615, 0, 1), - (13, 536, 1150, 1149, 18446744073709551615, 0, 1), - (13, 537, 1150, 1144, 18446744073709551615, 0, 1), - (13, 538, 1150, 1149, 18446744073709551615, 0, 1), - (13, 539, 1150, 1144, 18446744073709551615, 0, 1), - (13, 540, 1150, 1149, 18446744073709551615, 0, 1), - (13, 541, 1150, 1144, 18446744073709551615, 0, 1), - (13, 542, 1150, 1149, 18446744073709551615, 0, 1), - (13, 543, 1150, 1144, 18446744073709551615, 0, 1), - (13, 556, 1150, 1149, 18446744073709551615, 0, 1), - (13, 557, 1150, 1144, 18446744073709551615, 0, 1), - (13, 558, 1150, 1149, 18446744073709551615, 0, 1), - (13, 559, 1150, 1144, 18446744073709551615, 0, 1), - (13, 560, 1150, 1149, 18446744073709551615, 0, 1), - (13, 561, 1150, 1144, 18446744073709551615, 0, 1), - (13, 562, 1150, 1149, 18446744073709551615, 0, 1), - (13, 563, 1150, 1144, 18446744073709551615, 0, 1), - (13, 529, 0, 1150, 18446744073709551615, 0, 1), - (13, 531, 1132, 12, 18446744073709551615, 0, 2), - (13, 533, 1141, 1139, 18446744073709551615, 0, 2), - (13, 534, 1139, 10, 18446744073709551615, 0, 2), - (13, 535, 10, 9, 18446744073709551615, 0, 2), - (13, 536, 9, 0, 18446744073709551615, 0, 2), - (13, 537, 0, 1151, 18446744073709551615, 0, 1), - (13, 538, 1151, 12, 18446744073709551615, 0, 1), - (13, 539, 12, 1141, 18446744073709551615, 0, 2), - (13, 540, 1141, 1139, 18446744073709551615, 0, 2), - (13, 541, 1139, 10, 18446744073709551615, 0, 2), - (13, 542, 10, 9, 18446744073709551615, 0, 2), - (13, 552, 1139, 10, 18446744073709551615, 0, 2), - (13, 553, 10, 9, 18446744073709551615, 0, 2), - (13, 554, 9, 0, 18446744073709551615, 0, 2), - (13, 556, 1141, 10, 18446744073709551615, 0, 1), - (13, 557, 10, 9, 18446744073709551615, 0, 2), - (13, 558, 9, 0, 18446744073709551615, 0, 2), - (13, 560, 1139, 9, 18446744073709551615, 0, 1), - (13, 561, 9, 0, 18446744073709551615, 0, 2), - (13, 562, 0, 10, 18446744073709551615, 0, 1), - (13, 563, 10, 9, 18446744073709551615, 0, 1), - (13, 1025, 3, 4, 18446744073709551615, 259, 261), - (13, 1025, 4, 5, 18446744073709551615, 259, 261), - (13, 1025, 5, 6, 18446744073709551615, 259, 261), - (13, 1025, 6, 7, 18446744073709551615, 259, 261), - (13, 4, 772, 1144, 18446744073709551615, 0, 1), - (13, 5, 773, 1149, 18446744073709551615, 0, 1), - (13, 6, 774, 1150, 18446744073709551615, 0, 2), - (13, 7, 775, 1151, 18446744073709551615, 0, 2), - (13, 8, 776, 1132, 18446744073709551615, 5, 6), - (13, 1028, 772, 4, 18446744073709551615, 258, 521), - (13, 1028, 773, 5, 18446744073709551615, 258, 260), - (13, 1028, 774, 6, 18446744073709551615, 258, 260), - (13, 1028, 775, 7, 18446744073709551615, 258, 260), - (13, 1028, 776, 8, 18446744073709551615, 258, 260), - (13, 6, 774, 1143, 18446744073709551615, 1, 2), - (13, 7, 775, 1144, 18446744073709551615, 1, 2), - (13, 1024, 776, 8, 18446744073709551615, 260, 262), - (13, 1024, 775, 7, 18446744073709551615, 260, 262), - (13, 1024, 774, 6, 18446744073709551615, 260, 262), - (13, 1024, 773, 5, 18446744073709551615, 260, 262), - (13, 1024, 772, 4, 18446744073709551615, 260, 521), - (13, 1024, 771, 3, 18446744073709551615, 260, 262), - (13, 513, 1147, 781, 18446744073709551615, 0, 2), - (13, 514, 781, 1152, 18446744073709551615, 0, 2), - (13, 515, 1152, 1142, 18446744073709551615, 0, 2), - (13, 535, 1153, 793, 18446744073709551615, 0, 1), - (13, 536, 1153, 9, 18446744073709551615, 0, 1), - (13, 537, 1153, 793, 18446744073709551615, 0, 1), - (13, 538, 1153, 9, 18446744073709551615, 0, 1), - (13, 539, 1153, 793, 18446744073709551615, 0, 1), - (13, 540, 1153, 9, 18446744073709551615, 0, 1), - (13, 541, 1153, 793, 18446744073709551615, 0, 1), - (13, 542, 1153, 9, 18446744073709551615, 0, 1), - (13, 543, 1153, 793, 18446744073709551615, 0, 1), - (13, 556, 1153, 9, 18446744073709551615, 0, 1), - (13, 557, 1153, 793, 18446744073709551615, 0, 1), - (13, 558, 1153, 9, 18446744073709551615, 0, 1), - (13, 559, 1153, 793, 18446744073709551615, 0, 2), - (13, 560, 1153, 9, 18446744073709551615, 0, 1), - (13, 561, 1153, 793, 18446744073709551615, 0, 1), - (13, 562, 1153, 9, 18446744073709551615, 0, 2), - (13, 563, 1153, 793, 18446744073709551615, 0, 1), - (13, 528, 0, 1153, 18446744073709551615, 0, 2), - (13, 530, 1151, 12, 18446744073709551615, 0, 1), - (13, 531, 12, 1141, 18446744073709551615, 0, 2), - (13, 533, 10, 793, 18446744073709551615, 0, 2), - (13, 534, 793, 9, 18446744073709551615, 0, 2), - (13, 536, 0, 1153, 18446744073709551615, 0, 2), - (13, 537, 1153, 1132, 18446744073709551615, 0, 1), - (13, 538, 1132, 1141, 18446744073709551615, 0, 1), - (13, 539, 1141, 10, 18446744073709551615, 0, 2), - (13, 540, 10, 793, 18446744073709551615, 0, 2), - (13, 541, 793, 9, 18446744073709551615, 0, 2), - (13, 542, 9, 0, 18446744073709551615, 0, 2), - (13, 543, 0, 1153, 18446744073709551615, 0, 2), - (13, 550, 1153, 1141, 18446744073709551615, 0, 1), - (13, 551, 1141, 793, 18446744073709551615, 0, 1), - (13, 552, 793, 9, 18446744073709551615, 0, 2), - (13, 553, 9, 0, 18446744073709551615, 0, 2), - (13, 554, 0, 1153, 18446744073709551615, 0, 2), - (13, 555, 1153, 10, 18446744073709551615, 0, 1), - (13, 556, 10, 9, 18446744073709551615, 0, 1), - (13, 557, 9, 0, 18446744073709551615, 0, 2), - (13, 558, 0, 1153, 18446744073709551615, 2, 4), - (13, 559, 1153, 793, 18446744073709551615, 1, 2), - (13, 560, 793, 0, 18446744073709551615, 0, 1), - (13, 561, 0, 1153, 18446744073709551615, 0, 2), - (13, 562, 1153, 9, 18446744073709551615, 1, 2), - (13, 563, 9, 0, 18446744073709551615, 0, 1), - (13, 1025, 2, 3, 18446744073709551615, 260, 261), - (13, 1025, 3, 4, 18446744073709551615, 260, 261), - (13, 1025, 4, 5, 18446744073709551615, 260, 261), - (13, 1025, 5, 6, 18446744073709551615, 260, 261), - (13, 1025, 6, 7, 18446744073709551615, 260, 261), - (13, 2, 770, 1139, 18446744073709551615, 1, 2), - (13, 3, 771, 1150, 18446744073709551615, 0, 1), - (13, 4, 772, 1151, 18446744073709551615, 0, 5), - (13, 5, 773, 1132, 18446744073709551615, 5, 6), - (13, 6, 774, 12, 18446744073709551615, 0, 1), - (13, 7, 775, 1141, 18446744073709551615, 0, 1), - (13, 8, 776, 10, 18446744073709551615, 0, 1), - (13, 1028, 770, 2, 18446744073709551615, 259, 260), - (13, 1028, 771, 3, 18446744073709551615, 259, 260), - (13, 1028, 772, 4, 18446744073709551615, 259, 521), - (13, 1028, 773, 5, 18446744073709551615, 259, 260), - (13, 1028, 774, 6, 18446744073709551615, 259, 260), - (13, 1028, 775, 7, 18446744073709551615, 259, 260), - (13, 1028, 776, 8, 18446744073709551615, 259, 260), - (13, 6, 774, 1150, 18446744073709551615, 1, 2), - (13, 7, 775, 1151, 18446744073709551615, 1, 2), - (13, 1024, 776, 8, 18446744073709551615, 261, 262), - (13, 1024, 775, 7, 18446744073709551615, 261, 262), - (13, 1024, 774, 6, 18446744073709551615, 261, 262), - (13, 1024, 773, 5, 18446744073709551615, 261, 262), - (13, 1024, 772, 4, 18446744073709551615, 261, 521), - (13, 1024, 771, 3, 18446744073709551615, 261, 262), - (13, 1024, 770, 2, 18446744073709551615, 261, 262), - (13, 1024, 769, 1, 18446744073709551615, 261, 262), - (13, 533, 1149, 1144, 18446744073709551615, 0, 1), - (13, 534, 1149, 1143, 18446744073709551615, 0, 1), - (13, 535, 1149, 1144, 18446744073709551615, 0, 1), - (13, 536, 1149, 1143, 18446744073709551615, 0, 1), - (13, 537, 1149, 1144, 18446744073709551615, 0, 1), - (13, 538, 1149, 1143, 18446744073709551615, 0, 1), - (13, 539, 1149, 1144, 18446744073709551615, 0, 1), - (13, 540, 1149, 1143, 18446744073709551615, 0, 1), - (13, 541, 1149, 1144, 18446744073709551615, 0, 1), - (13, 542, 1149, 1143, 18446744073709551615, 0, 1), - (13, 543, 1149, 1144, 18446744073709551615, 0, 1), - (13, 554, 1149, 1143, 18446744073709551615, 0, 1), - (13, 555, 1149, 1144, 18446744073709551615, 0, 1), - (13, 556, 1149, 1143, 18446744073709551615, 0, 1), - (13, 557, 1149, 1144, 18446744073709551615, 0, 1), - (13, 558, 1149, 1143, 18446744073709551615, 0, 1), - (13, 559, 1149, 1144, 18446744073709551615, 0, 1), - (13, 560, 1149, 1143, 18446744073709551615, 0, 1), - (13, 561, 1149, 1144, 18446744073709551615, 0, 1), - (13, 562, 1149, 1143, 18446744073709551615, 0, 1), - (13, 563, 1149, 1144, 18446744073709551615, 0, 1), - (13, 754, 763, 1144, 18446744073709551615, 0, 1), - (13, 753, 762, 745, 18446744073709551615, 0, 1), - (13, 752, 761, 744, 18446744073709551615, 0, 1), - (13, 751, 760, 743, 18446744073709551615, 0, 1), - (13, 750, 759, 742, 18446744073709551615, 0, 1), - (13, 749, 758, 741, 18446744073709551615, 0, 1), - (13, 748, 757, 740, 18446744073709551615, 0, 1), - (13, 747, 756, 739, 18446744073709551615, 0, 1), - (13, 764, 748, 749, 18446744073709551615, 0, 261), - (13, 764, 749, 750, 18446744073709551615, 0, 261), - (13, 764, 750, 751, 18446744073709551615, 0, 261), - (13, 764, 751, 752, 18446744073709551615, 0, 261), - (13, 764, 752, 753, 18446744073709551615, 0, 261), - (13, 764, 753, 754, 18446744073709551615, 0, 261), - (13, 754, 763, 767, 18446744073709551615, 0, 260), - (13, 753, 762, 1142, 18446744073709551615, 0, 2), - (13, 752, 761, 1152, 18446744073709551615, 0, 2), - (13, 751, 760, 781, 18446744073709551615, 0, 2), - (13, 750, 759, 746, 18446744073709551615, 0, 6), - (13, 749, 758, 1143, 18446744073709551615, 0, 1), - (13, 748, 757, 1144, 18446744073709551615, 0, 1), - (13, 766, 756, 747, 18446744073709551615, 0, 261), - (13, 766, 757, 748, 18446744073709551615, 0, 261), - (13, 766, 758, 749, 18446744073709551615, 0, 261), - (13, 766, 759, 750, 18446744073709551615, 0, 261), - (13, 766, 760, 751, 18446744073709551615, 0, 261), - (13, 766, 761, 752, 18446744073709551615, 0, 261), - (13, 766, 762, 753, 18446744073709551615, 0, 261), - (13, 766, 763, 754, 18446744073709551615, 0, 261), - (13, 765, 761, 752, 18446744073709551615, 0, 259), - (13, 765, 760, 751, 18446744073709551615, 0, 259), - (13, 765, 759, 750, 18446744073709551615, 0, 259), - (13, 765, 758, 749, 18446744073709551615, 0, 259), - (13, 765, 757, 748, 18446744073709551615, 0, 259), - (13, 765, 756, 747, 18446744073709551615, 0, 259), - (13, 752, 761, 1143, 18446744073709551615, 0, 1), - (13, 751, 760, 1144, 18446744073709551615, 0, 1), - (13, 750, 759, 745, 18446744073709551615, 0, 1), - (13, 749, 758, 744, 18446744073709551615, 0, 1), - (13, 748, 757, 743, 18446744073709551615, 0, 1), - (13, 747, 756, 742, 18446744073709551615, 0, 1), - (13, 764, 748, 749, 18446744073709551615, 1, 261), - (13, 764, 749, 750, 18446744073709551615, 1, 261), - (13, 764, 750, 751, 18446744073709551615, 1, 261), - (13, 764, 751, 752, 18446744073709551615, 1, 261), - (13, 751, 760, 1152, 18446744073709551615, 0, 2), - (13, 750, 759, 746, 18446744073709551615, 1, 6), - (13, 749, 758, 781, 18446744073709551615, 0, 3), - (13, 748, 757, 1143, 18446744073709551615, 0, 3), - (13, 766, 756, 747, 18446744073709551615, 1, 261), - (13, 766, 757, 748, 18446744073709551615, 1, 261), - (13, 766, 758, 749, 18446744073709551615, 1, 261), - (13, 766, 759, 750, 18446744073709551615, 1, 261), - (13, 766, 760, 751, 18446744073709551615, 1, 261), - (13, 765, 760, 751, 18446744073709551615, 1, 259), - (13, 765, 759, 750, 18446744073709551615, 1, 259), - (13, 765, 758, 749, 18446744073709551615, 1, 259), - (13, 765, 757, 748, 18446744073709551615, 1, 259), - (13, 765, 756, 747, 18446744073709551615, 1, 259), - (13, 751, 760, 1143, 18446744073709551615, 0, 1), - (13, 750, 759, 1144, 18446744073709551615, 0, 1), - (13, 749, 758, 745, 18446744073709551615, 0, 1), - (13, 748, 757, 744, 18446744073709551615, 0, 1), - (13, 747, 756, 743, 18446744073709551615, 0, 1), - (13, 764, 748, 749, 18446744073709551615, 2, 261), - (13, 764, 749, 750, 18446744073709551615, 2, 261), - (13, 764, 750, 751, 18446744073709551615, 2, 261), - (13, 749, 758, 1146, 18446744073709551615, 0, 2), - (13, 748, 757, 1152, 18446744073709551615, 0, 1), - (13, 766, 756, 747, 18446744073709551615, 2, 261), - (13, 766, 757, 748, 18446744073709551615, 2, 261), - (13, 766, 758, 749, 18446744073709551615, 2, 261), - (13, 765, 757, 748, 18446744073709551615, 2, 259), - (13, 765, 756, 747, 18446744073709551615, 2, 259), - (13, 750, 759, 746, 18446744073709551615, 2, 6), - (13, 749, 758, 781, 18446744073709551615, 1, 3), - (13, 748, 757, 1143, 18446744073709551615, 1, 3), - (13, 747, 756, 1144, 18446744073709551615, 0, 2), - (13, 764, 748, 749, 18446744073709551615, 3, 261), - (13, 764, 749, 750, 18446744073709551615, 3, 261), - (13, 748, 757, 1146, 18446744073709551615, 0, 4), - (13, 747, 756, 1152, 18446744073709551615, 0, 2), - (13, 766, 1142, 14, 18446744073709551615, 0, 258), - (13, 766, 756, 747, 18446744073709551615, 3, 261), - (13, 766, 757, 748, 18446744073709551615, 3, 261), - (13, 765, 757, 748, 18446744073709551615, 3, 259), - (13, 765, 1142, 14, 18446744073709551615, 0, 256), - (13, 749, 758, 746, 18446744073709551615, 0, 1), - (13, 748, 757, 781, 18446744073709551615, 0, 4), - (13, 747, 756, 1143, 18446744073709551615, 0, 4), - (13, 14, 1142, 1144, 18446744073709551615, 0, 4), - (13, 764, 747, 748, 18446744073709551615, 0, 257), - (13, 764, 748, 749, 18446744073709551615, 4, 261), - (13, 14, 1142, 1144, 18446744073709551615, 1, 4), - (13, 11, 779, 745, 18446744073709551615, 0, 3), - (13, 766, 778, 777, 18446744073709551615, 0, 257), - (13, 766, 779, 11, 18446744073709551615, 0, 257), - (13, 766, 1142, 14, 18446744073709551615, 1, 258), - (13, 766, 757, 748, 18446744073709551615, 4, 261), - (13, 765, 756, 747, 18446744073709551615, 4, 259), - (13, 765, 1142, 14, 18446744073709551615, 1, 256), - (13, 765, 779, 11, 18446744073709551615, 0, 255), - (13, 765, 778, 777, 18446744073709551615, 0, 255), - (13, 748, 757, 745, 18446744073709551615, 0, 1), - (13, 747, 756, 744, 18446744073709551615, 0, 1), - (13, 14, 1142, 743, 18446744073709551615, 0, 1), - (13, 11, 779, 742, 18446744073709551615, 0, 1), - (13, 777, 778, 741, 18446744073709551615, 0, 1), - (13, 764, 11, 14, 18446744073709551615, 0, 256), - (13, 764, 14, 747, 18446744073709551615, 0, 256), - (13, 764, 747, 748, 18446744073709551615, 1, 257), - (13, 14, 1142, 1152, 18446744073709551615, 0, 3), - (13, 766, 778, 777, 18446744073709551615, 1, 257), - (13, 766, 1142, 14, 18446744073709551615, 2, 258), - (13, 766, 756, 747, 18446744073709551615, 5, 261), - (13, 765, 1142, 14, 18446744073709551615, 2, 256), - (13, 765, 778, 777, 18446744073709551615, 1, 255), - (13, 747, 756, 1143, 18446744073709551615, 2, 4), - (13, 14, 1142, 1144, 18446744073709551615, 2, 4), - (13, 11, 779, 745, 18446744073709551615, 1, 3), - (13, 777, 778, 744, 18446744073709551615, 0, 2), - (13, 764, 11, 14, 18446744073709551615, 1, 256), - (13, 764, 14, 747, 18446744073709551615, 1, 256), - (13, 14, 1142, 781, 18446744073709551615, 0, 1), - (13, 11, 779, 1143, 18446744073709551615, 1, 2), - (13, 777, 778, 1144, 18446744073709551615, 0, 1), - (13, 13, 1148, 745, 18446744073709551615, 0, 1), - (13, 766, 780, 1145, 18446744073709551615, 0, 255), - (13, 766, 1148, 13, 18446744073709551615, 0, 255), - (13, 766, 778, 777, 18446744073709551615, 2, 257), - (13, 766, 779, 11, 18446744073709551615, 2, 257), - (13, 766, 1142, 14, 18446744073709551615, 3, 258), - (13, 765, 779, 11, 18446744073709551615, 2, 255), - (13, 765, 1148, 13, 18446744073709551615, 0, 253), - (13, 765, 780, 1145, 18446744073709551615, 0, 253), - (13, 14, 1142, 745, 18446744073709551615, 0, 1), - (13, 11, 779, 744, 18446744073709551615, 0, 1), - (13, 777, 778, 743, 18446744073709551615, 0, 1), - (13, 13, 1148, 742, 18446744073709551615, 0, 1), - (13, 1145, 780, 741, 18446744073709551615, 0, 1), - (13, 764, 13, 777, 18446744073709551615, 0, 254), - (13, 764, 777, 11, 18446744073709551615, 0, 254), - (13, 11, 779, 781, 18446744073709551615, 1, 3), - (13, 777, 778, 1143, 18446744073709551615, 0, 2), - (13, 13, 1148, 1144, 18446744073709551615, 0, 2), - (13, 766, 780, 1145, 18446744073709551615, 1, 255), - (13, 766, 1148, 13, 18446744073709551615, 1, 255), - (13, 766, 778, 777, 18446744073709551615, 3, 257), - (13, 766, 779, 11, 18446744073709551615, 3, 257), - (13, 11, 779, 745, 18446744073709551615, 2, 3), - (13, 777, 778, 744, 18446744073709551615, 1, 2), - (13, 13, 1148, 743, 18446744073709551615, 0, 1), - (13, 1145, 780, 742, 18446744073709551615, 0, 1), - (13, 764, 13, 777, 18446744073709551615, 1, 254), - (13, 764, 777, 11, 18446744073709551615, 1, 254), - (13, 777, 778, 746, 18446744073709551615, 0, 3), - (13, 13, 1148, 1152, 18446744073709551615, 0, 3), - (13, 766, 780, 1145, 18446744073709551615, 2, 255), - (13, 766, 1148, 13, 18446744073709551615, 2, 255), - (13, 766, 778, 777, 18446744073709551615, 4, 257), - (13, 777, 778, 1143, 18446744073709551615, 1, 2), - (13, 13, 1148, 1144, 18446744073709551615, 1, 2), - (13, 1145, 780, 745, 18446744073709551615, 0, 1), - (13, 764, 13, 777, 18446744073709551615, 2, 254), - (13, 13, 1148, 746, 18446744073709551615, 0, 2), - (13, 1145, 780, 1152, 18446744073709551615, 0, 2), - (13, 766, 1140, 1137, 18446744073709551615, 0, 252), - (13, 766, 780, 1145, 18446744073709551615, 3, 255), - (13, 766, 1148, 13, 18446744073709551615, 3, 255), - (13, 765, 1140, 1137, 18446744073709551615, 0, 250), - (13, 13, 1148, 1143, 18446744073709551615, 0, 1), - (13, 1145, 780, 1144, 18446744073709551615, 0, 1), - (13, 1137, 1140, 745, 18446744073709551615, 0, 1), - (13, 764, 1145, 13, 18446744073709551615, 0, 251), - (13, 1145, 780, 746, 18446744073709551615, 0, 1), - (13, 766, 1140, 1137, 18446744073709551615, 1, 252), - (13, 766, 780, 1145, 18446744073709551615, 4, 255), - (13, 1145, 780, 1143, 18446744073709551615, 0, 1), - (13, 1137, 1140, 1144, 18446744073709551615, 0, 1), - (13, 1137, 1140, 746, 18446744073709551615, 0, 3), - (13, 766, 1118, 17, 18446744073709551615, 0, 250), - (13, 766, 1140, 1137, 18446744073709551615, 2, 252), - (13, 765, 1118, 17, 18446744073709551615, 0, 248), - (13, 1137, 1140, 1143, 18446744073709551615, 0, 2), - (13, 17, 1118, 1144, 18446744073709551615, 0, 2), - (13, 766, 16, 1134, 18446744073709551615, 0, 249), - (13, 765, 16, 1134, 18446744073709551615, 0, 247), - (13, 17, 1118, 1143, 18446744073709551615, 0, 1), - (13, 1134, 16, 1144, 18446744073709551615, 0, 1), - (13, 766, 1113, 27, 18446744073709551615, 0, 248), - (13, 765, 1113, 27, 18446744073709551615, 0, 246), - (13, 1134, 16, 745, 18446744073709551615, 0, 1), - (13, 27, 1113, 744, 18446744073709551615, 0, 1), - (13, 27, 1113, 1143, 18446744073709551615, 0, 1), - (13, 786, 785, 1143, 18446744073709551615, 0, 2), - (13, 20, 25, 742, 18446744073709551615, 0, 4), - (13, 766, 24, 18, 18446744073709551615, 0, 239), - (13, 766, 25, 20, 18446744073709551615, 0, 239), - (13, 765, 25, 20, 18446744073709551615, 0, 237), - (13, 765, 24, 18, 18446744073709551615, 0, 237), - (13, 20, 25, 740, 18446744073709551615, 0, 1), - (13, 18, 24, 739, 18446744073709551615, 0, 1), - (13, 764, 20, 23, 18446744073709551615, 0, 238), - (13, 766, 1131, 795, 18446744073709551615, 0, 238), - (13, 765, 24, 18, 18446744073709551615, 1, 237), - (13, 765, 1131, 795, 18446744073709551615, 0, 236), - (13, 18, 24, 740, 18446744073709551615, 0, 2), - (13, 795, 1131, 739, 18446744073709551615, 0, 2), - (13, 766, 792, 796, 18446744073709551615, 0, 237), - (13, 765, 792, 796, 18446744073709551615, 0, 235), - (13, 795, 1131, 740, 18446744073709551615, 0, 3), - (13, 796, 792, 739, 18446744073709551615, 0, 3), - (13, 796, 792, 738, 18446744073709551615, 0, 1), - (13, 797, 30, 737, 18446744073709551615, 0, 1), - (13, 797, 30, 738, 18446744073709551615, 0, 2), - (13, 798, 1130, 737, 18446744073709551615, 0, 2), - (13, 798, 1130, 738, 18446744073709551615, 0, 3), - (13, 799, 29, 737, 18446744073709551615, 0, 3), - (13, 799, 29, 736, 18446744073709551615, 0, 1), - (13, 800, 33, 735, 18446744073709551615, 0, 1), - (13, 766, 1129, 801, 18446744073709551615, 0, 232), - (13, 765, 1129, 801, 18446744073709551615, 0, 230), - (13, 800, 33, 736, 18446744073709551615, 0, 2), - (13, 801, 1129, 735, 18446744073709551615, 0, 2), - (13, 801, 1129, 736, 18446744073709551615, 0, 3), - (13, 802, 32, 735, 18446744073709551615, 0, 3), - (13, 766, 36, 803, 18446744073709551615, 0, 230), - (13, 765, 36, 803, 18446744073709551615, 0, 228), - (13, 802, 32, 734, 18446744073709551615, 0, 1), - (13, 803, 36, 733, 18446744073709551615, 0, 1), - (13, 803, 36, 734, 18446744073709551615, 0, 2), - (13, 804, 1128, 733, 18446744073709551615, 0, 2), - (13, 804, 1128, 734, 18446744073709551615, 0, 3), - (13, 805, 35, 733, 18446744073709551615, 0, 3), - (13, 805, 35, 732, 18446744073709551615, 0, 1), - (13, 806, 39, 731, 18446744073709551615, 0, 1), - (13, 806, 39, 732, 18446744073709551615, 0, 2), - (13, 807, 1127, 731, 18446744073709551615, 0, 2), - (13, 807, 1127, 732, 18446744073709551615, 0, 3), - (13, 808, 38, 731, 18446744073709551615, 0, 3), - (13, 808, 38, 730, 18446744073709551615, 0, 1), - (13, 809, 42, 729, 18446744073709551615, 0, 1), - (13, 809, 42, 730, 18446744073709551615, 0, 2), - (13, 810, 1126, 729, 18446744073709551615, 0, 2), - (13, 810, 1126, 730, 18446744073709551615, 0, 1), - (13, 811, 41, 729, 18446744073709551615, 0, 1), - (13, 766, 45, 812, 18446744073709551615, 0, 221), - (13, 765, 45, 812, 18446744073709551615, 0, 219), - (13, 811, 41, 728, 18446744073709551615, 0, 1), - (13, 812, 45, 727, 18446744073709551615, 0, 1), - (13, 765, 1125, 813, 18446744073709551615, 0, 218), - (13, 812, 45, 729, 18446744073709551615, 0, 2), - (13, 813, 1125, 728, 18446744073709551615, 0, 2), - (13, 765, 44, 814, 18446744073709551615, 0, 217), - (13, 814, 44, 728, 18446744073709551615, 0, 4), - (13, 765, 48, 815, 18446744073709551615, 0, 216), - (13, 814, 44, 727, 18446744073709551615, 0, 1), - (13, 815, 48, 726, 18446744073709551615, 0, 1), - (13, 765, 1124, 816, 18446744073709551615, 0, 215), - (13, 816, 1124, 726, 18446744073709551615, 0, 2), - (13, 765, 47, 817, 18446744073709551615, 0, 214), - (13, 817, 47, 726, 18446744073709551615, 0, 4), - (13, 765, 51, 818, 18446744073709551615, 0, 213), - (13, 818, 51, 724, 18446744073709551615, 0, 1), - (13, 765, 1123, 819, 18446744073709551615, 0, 212), - (13, 819, 1123, 724, 18446744073709551615, 0, 2), - (13, 765, 50, 820, 18446744073709551615, 0, 211), - (13, 820, 50, 724, 18446744073709551615, 0, 2), - (13, 821, 54, 722, 18446744073709551615, 0, 1), - (13, 765, 1122, 822, 18446744073709551615, 0, 209), - (13, 822, 1122, 723, 18446744073709551615, 0, 2), - (13, 765, 53, 823, 18446744073709551615, 0, 208), - (13, 823, 53, 724, 18446744073709551615, 0, 5), - (13, 824, 57, 723, 18446744073709551615, 0, 4), - (13, 765, 1121, 825, 18446744073709551615, 0, 206), - (13, 825, 1121, 724, 18446744073709551615, 0, 4), - (13, 765, 56, 826, 18446744073709551615, 0, 205), - (13, 826, 56, 725, 18446744073709551615, 0, 4), - (13, 827, 60, 725, 18446744073709551615, 0, 4), - (13, 828, 1120, 725, 18446744073709551615, 0, 4), - (13, 765, 59, 829, 18446744073709551615, 0, 202), - (13, 829, 59, 728, 18446744073709551615, 0, 4), - (13, 765, 63, 830, 18446744073709551615, 0, 201), - (13, 830, 63, 726, 18446744073709551615, 0, 4), - (13, 765, 1117, 831, 18446744073709551615, 0, 200), - (13, 831, 1117, 727, 18446744073709551615, 0, 4), - (13, 765, 62, 832, 18446744073709551615, 0, 199), - (13, 832, 62, 730, 18446744073709551615, 0, 4), - (13, 765, 66, 833, 18446744073709551615, 0, 198), - (13, 833, 66, 728, 18446744073709551615, 0, 4), - (13, 765, 1119, 834, 18446744073709551615, 0, 197), - (13, 834, 1119, 731, 18446744073709551615, 0, 7), - (13, 765, 65, 835, 18446744073709551615, 0, 196), - (13, 835, 65, 732, 18446744073709551615, 0, 2), - (13, 765, 1112, 69, 18446744073709551615, 0, 195), - (13, 69, 1112, 731, 18446744073709551615, 0, 1), - (13, 765, 838, 837, 18446744073709551615, 0, 194), - (13, 837, 838, 731, 18446744073709551615, 0, 5), - (13, 765, 68, 839, 18446744073709551615, 0, 193), - (13, 839, 68, 733, 18446744073709551615, 0, 4), - (13, 765, 1111, 72, 18446744073709551615, 0, 192), - (13, 72, 1111, 732, 18446744073709551615, 0, 3), - (13, 765, 843, 841, 18446744073709551615, 0, 191), - (13, 841, 843, 733, 18446744073709551615, 0, 2), - (13, 765, 71, 842, 18446744073709551615, 0, 190), - (13, 842, 71, 734, 18446744073709551615, 0, 8), - (13, 765, 1110, 75, 18446744073709551615, 0, 189), - (13, 75, 1110, 733, 18446744073709551615, 0, 7), - (13, 765, 846, 844, 18446744073709551615, 0, 188), - (13, 844, 846, 734, 18446744073709551615, 0, 5), - (13, 765, 74, 845, 18446744073709551615, 0, 187), - (13, 845, 74, 734, 18446744073709551615, 0, 6), - (13, 765, 1109, 78, 18446744073709551615, 0, 186), - (13, 78, 1109, 734, 18446744073709551615, 0, 6), - (13, 765, 849, 847, 18446744073709551615, 0, 185), - (13, 847, 849, 736, 18446744073709551615, 0, 4), - (13, 765, 77, 848, 18446744073709551615, 0, 184), - (13, 848, 77, 737, 18446744073709551615, 0, 5), - (13, 765, 1108, 81, 18446744073709551615, 0, 183), - (13, 81, 1108, 736, 18446744073709551615, 0, 4), - (13, 765, 852, 850, 18446744073709551615, 0, 182), - (13, 850, 852, 737, 18446744073709551615, 0, 4), - (13, 765, 80, 851, 18446744073709551615, 0, 181), - (13, 851, 80, 738, 18446744073709551615, 0, 5), - (13, 765, 1107, 84, 18446744073709551615, 0, 180), - (13, 84, 1107, 737, 18446744073709551615, 0, 4), - (13, 765, 855, 853, 18446744073709551615, 0, 179), - (13, 853, 855, 738, 18446744073709551615, 0, 4), - (13, 765, 83, 854, 18446744073709551615, 0, 178), - (13, 854, 83, 740, 18446744073709551615, 0, 5), - (13, 765, 1106, 87, 18446744073709551615, 0, 177), - (13, 87, 1106, 739, 18446744073709551615, 0, 4), - (13, 765, 858, 856, 18446744073709551615, 0, 176), - (13, 856, 858, 739, 18446744073709551615, 0, 4), - (13, 765, 86, 857, 18446744073709551615, 0, 175), - (13, 857, 86, 741, 18446744073709551615, 0, 5), - (13, 90, 1105, 740, 18446744073709551615, 0, 4), - (13, 859, 861, 740, 18446744073709551615, 0, 4), - (13, 765, 89, 860, 18446744073709551615, 0, 172), - (13, 860, 89, 742, 18446744073709551615, 0, 5), - (13, 765, 1104, 93, 18446744073709551615, 0, 171), - (13, 93, 1104, 741, 18446744073709551615, 0, 4), - (13, 765, 864, 862, 18446744073709551615, 0, 170), - (13, 862, 864, 742, 18446744073709551615, 0, 4), - (13, 765, 92, 863, 18446744073709551615, 0, 169), - (13, 863, 92, 744, 18446744073709551615, 0, 5), - (13, 765, 1103, 96, 18446744073709551615, 0, 168), - (13, 96, 1103, 743, 18446744073709551615, 0, 4), - (13, 765, 867, 865, 18446744073709551615, 0, 167), - (13, 865, 867, 743, 18446744073709551615, 0, 3), - (13, 765, 95, 866, 18446744073709551615, 0, 166), - (13, 866, 95, 745, 18446744073709551615, 0, 2), - (13, 765, 1102, 99, 18446744073709551615, 0, 165), - (13, 99, 1102, 744, 18446744073709551615, 0, 1), - (13, 765, 870, 868, 18446744073709551615, 0, 164), - (13, 868, 870, 745, 18446744073709551615, 0, 2), - (13, 765, 98, 869, 18446744073709551615, 0, 163), - (13, 869, 98, 1144, 18446744073709551615, 0, 2), - (13, 765, 1101, 102, 18446744073709551615, 0, 162), - (13, 102, 1101, 745, 18446744073709551615, 0, 1), - (13, 871, 873, 745, 18446744073709551615, 0, 2), - (13, 765, 101, 872, 18446744073709551615, 0, 160), - (13, 872, 101, 781, 18446744073709551615, 0, 2), - (13, 765, 1100, 105, 18446744073709551615, 0, 159), - (13, 105, 1100, 1144, 18446744073709551615, 0, 1), - (13, 874, 876, 1143, 18446744073709551615, 0, 1), - (13, 765, 104, 875, 18446744073709551615, 0, 157), - (13, 875, 104, 1152, 18446744073709551615, 0, 3), - (13, 765, 1099, 108, 18446744073709551615, 0, 156), - (13, 108, 1099, 781, 18446744073709551615, 0, 2), - (13, 877, 879, 1152, 18446744073709551615, 0, 1), - (13, 765, 107, 878, 18446744073709551615, 0, 154), - (13, 878, 107, 746, 18446744073709551615, 0, 2), - (13, 111, 1098, 1152, 18446744073709551615, 0, 1), - (13, 880, 882, 1146, 18446744073709551615, 0, 1), - (13, 765, 110, 881, 18446744073709551615, 0, 151), - (13, 881, 110, 1146, 18446744073709551615, 0, 3), - (13, 114, 894, 746, 18446744073709551615, 0, 2), - (13, 883, 885, 15, 18446744073709551615, 0, 1), - (13, 765, 113, 884, 18446744073709551615, 0, 148), - (13, 884, 113, 15, 18446744073709551615, 0, 1), - (13, 117, 887, 15, 18446744073709551615, 0, 1), - (13, 119, 1097, 836, 18446744073709551615, 0, 2), - (13, 766, 886, 115, 18446744073709551615, 0, 147), - (13, 765, 886, 115, 18446744073709551615, 0, 145), - (13, 118, 116, 15, 18446744073709551615, 0, 1), - (13, 115, 886, 1146, 18446744073709551615, 0, 1), - (13, 115, 886, 836, 18446744073709551615, 0, 2), - (13, 766, 888, 1116, 18446744073709551615, 0, 145), - (13, 765, 888, 1116, 18446744073709551615, 0, 143), - (13, 1116, 888, 1146, 18446744073709551615, 0, 1), - (13, 765, 121, 891, 18446744073709551615, 0, 142), - (13, 891, 121, 836, 18446744073709551615, 0, 1), - (13, 765, 901, 892, 18446744073709551615, 0, 141), - (13, 892, 901, 1146, 18446744073709551615, 0, 1), - (13, 129, 1094, 1135, 18446744073709551615, 0, 1), - (13, 766, 897, 1095, 18446744073709551615, 0, 136), - (13, 765, 897, 1095, 18446744073709551615, 0, 134), - (13, 1095, 897, 1135, 18446744073709551615, 0, 1), - (13, 765, 128, 900, 18446744073709551615, 0, 133), - (13, 900, 128, 1135, 18446744073709551615, 0, 2), - (13, 765, 1093, 133, 18446744073709551615, 0, 132), - (13, 133, 1093, 783, 18446744073709551615, 0, 1), - (13, 765, 904, 902, 18446744073709551615, 0, 131), - (13, 902, 904, 1135, 18446744073709551615, 0, 1), - (13, 765, 132, 903, 18446744073709551615, 0, 130), - (13, 903, 132, 1114, 18446744073709551615, 0, 1), - (13, 765, 1092, 136, 18446744073709551615, 0, 129), - (13, 136, 1092, 1114, 18446744073709551615, 0, 1), - (13, 765, 909, 905, 18446744073709551615, 0, 128), - (13, 905, 909, 1138, 18446744073709551615, 0, 1), - (13, 765, 135, 906, 18446744073709551615, 0, 127), - (13, 906, 135, 782, 18446744073709551615, 0, 2), - (13, 765, 908, 140, 18446744073709551615, 0, 126), - (13, 140, 908, 1138, 18446744073709551615, 0, 1), - (13, 766, 907, 910, 18446744073709551615, 0, 126), - (13, 765, 907, 910, 18446744073709551615, 0, 124), - (13, 910, 907, 784, 18446744073709551615, 0, 2), - (13, 765, 1089, 142, 18446744073709551615, 0, 123), - (13, 142, 1089, 782, 18446744073709551615, 0, 1), - (13, 919, 1090, 782, 18446744073709551615, 0, 1), - (13, 766, 915, 911, 18446744073709551615, 0, 118), - (13, 765, 915, 911, 18446744073709551615, 0, 116), - (13, 911, 915, 19, 18446744073709551615, 0, 1), - (13, 765, 146, 918, 18446744073709551615, 0, 115), - (13, 918, 146, 28, 18446744073709551615, 0, 2), - (13, 765, 1087, 151, 18446744073709551615, 0, 114), - (13, 151, 1087, 19, 18446744073709551615, 0, 1), - (13, 765, 922, 920, 18446744073709551615, 0, 113), - (13, 920, 922, 28, 18446744073709551615, 0, 1), - (13, 765, 150, 921, 18446744073709551615, 0, 112), - (13, 921, 150, 31, 18446744073709551615, 0, 1), - (13, 765, 1086, 154, 18446744073709551615, 0, 111), - (13, 154, 1086, 31, 18446744073709551615, 0, 1), - (13, 765, 925, 157, 18446744073709551615, 0, 110), - (13, 157, 925, 31, 18446744073709551615, 0, 1), - (13, 766, 923, 153, 18446744073709551615, 0, 110), - (13, 765, 923, 153, 18446744073709551615, 0, 108), - (13, 153, 923, 34, 18446744073709551615, 0, 1), - (13, 160, 928, 37, 18446744073709551615, 0, 1), - (13, 766, 926, 935, 18446744073709551615, 0, 107), - (13, 765, 926, 935, 18446744073709551615, 0, 105), - (13, 935, 926, 37, 18446744073709551615, 0, 1), - (13, 929, 1085, 43, 18446744073709551615, 0, 1), - (13, 765, 934, 933, 18446744073709551615, 0, 103), - (13, 933, 934, 43, 18446744073709551615, 0, 1), - (13, 766, 930, 161, 18446744073709551615, 0, 103), - (13, 765, 930, 161, 18446744073709551615, 0, 101), - (13, 161, 930, 46, 18446744073709551615, 0, 3), - (13, 766, 932, 162, 18446744073709551615, 0, 102), - (13, 765, 163, 164, 18446744073709551615, 0, 100), - (13, 765, 932, 162, 18446744073709551615, 0, 100), - (13, 164, 163, 43, 18446744073709551615, 0, 2), - (13, 162, 932, 40, 18446744073709551615, 0, 2), - (13, 765, 940, 167, 18446744073709551615, 0, 99), - (13, 162, 932, 40, 18446744073709551615, 1, 2), - (13, 167, 940, 37, 18446744073709551615, 0, 1), - (13, 765, 171, 936, 18446744073709551615, 0, 98), - (13, 167, 940, 40, 18446744073709551615, 0, 1), - (13, 936, 171, 37, 18446744073709551615, 0, 1), - (13, 765, 166, 937, 18446744073709551615, 0, 97), - (13, 936, 171, 49, 18446744073709551615, 0, 3), - (13, 937, 166, 46, 18446744073709551615, 0, 3), - (13, 765, 1084, 170, 18446744073709551615, 0, 96), - (13, 937, 166, 46, 18446744073709551615, 1, 3), - (13, 170, 1084, 43, 18446744073709551615, 0, 2), - (13, 766, 938, 156, 18446744073709551615, 0, 97), - (13, 765, 939, 168, 18446744073709551615, 0, 95), - (13, 765, 938, 156, 18446744073709551615, 0, 95), - (13, 168, 939, 40, 18446744073709551615, 0, 1), - (13, 156, 938, 37, 18446744073709551615, 0, 1), - (13, 765, 169, 1082, 18446744073709551615, 0, 94), - (13, 156, 938, 40, 18446744073709551615, 0, 1), - (13, 1082, 169, 37, 18446744073709551615, 0, 1), - (13, 1082, 169, 46, 18446744073709551615, 0, 1), - (13, 765, 944, 942, 18446744073709551615, 0, 92), - (13, 942, 944, 46, 18446744073709551615, 0, 1), - (13, 765, 941, 943, 18446744073709551615, 0, 91), - (13, 943, 941, 52, 18446744073709551615, 0, 2), - (13, 765, 1081, 176, 18446744073709551615, 0, 90), - (13, 176, 1081, 49, 18446744073709551615, 0, 1), - (13, 945, 947, 52, 18446744073709551615, 0, 1), - (13, 765, 175, 946, 18446744073709551615, 0, 88), - (13, 946, 175, 55, 18446744073709551615, 0, 2), - (13, 765, 1080, 179, 18446744073709551615, 0, 87), - (13, 179, 1080, 52, 18446744073709551615, 0, 1), - (13, 948, 950, 55, 18446744073709551615, 0, 1), - (13, 765, 178, 949, 18446744073709551615, 0, 85), - (13, 949, 178, 61, 18446744073709551615, 0, 3), - (13, 765, 1079, 182, 18446744073709551615, 0, 84), - (13, 182, 1079, 58, 18446744073709551615, 0, 2), - (13, 951, 953, 55, 18446744073709551615, 0, 1), - (13, 765, 181, 952, 18446744073709551615, 0, 82), - (13, 952, 181, 61, 18446744073709551615, 0, 2), - (13, 765, 1078, 185, 18446744073709551615, 0, 81), - (13, 185, 1078, 58, 18446744073709551615, 0, 1), - (13, 765, 956, 954, 18446744073709551615, 0, 80), - (13, 954, 956, 64, 18446744073709551615, 0, 1), - (13, 765, 184, 955, 18446744073709551615, 0, 79), - (13, 955, 184, 67, 18446744073709551615, 0, 1), - (13, 765, 1077, 188, 18446744073709551615, 0, 78), - (13, 188, 1077, 67, 18446744073709551615, 0, 1), - (13, 765, 959, 957, 18446744073709551615, 0, 77), - (13, 957, 959, 67, 18446744073709551615, 0, 1), - (13, 958, 187, 67, 18446744073709551615, 0, 1), - (13, 765, 1076, 191, 18446744073709551615, 0, 75), - (13, 191, 1076, 67, 18446744073709551615, 0, 1), - (13, 765, 962, 960, 18446744073709551615, 0, 74), - (13, 960, 962, 70, 18446744073709551615, 0, 1), - (13, 765, 1075, 194, 18446744073709551615, 0, 72), - (13, 194, 1075, 73, 18446744073709551615, 0, 1), - (13, 765, 965, 963, 18446744073709551615, 0, 71), - (13, 963, 965, 76, 18446744073709551615, 0, 1), - (13, 765, 193, 964, 18446744073709551615, 0, 70), - (13, 964, 193, 79, 18446744073709551615, 0, 2), - (13, 765, 1074, 197, 18446744073709551615, 0, 69), - (13, 197, 1074, 76, 18446744073709551615, 0, 1), - (13, 765, 968, 966, 18446744073709551615, 0, 68), - (13, 966, 968, 79, 18446744073709551615, 0, 1), - (13, 765, 196, 967, 18446744073709551615, 0, 67), - (13, 967, 196, 85, 18446744073709551615, 0, 2), - (13, 765, 1073, 200, 18446744073709551615, 0, 66), - (13, 200, 1073, 82, 18446744073709551615, 0, 1), - (13, 765, 971, 969, 18446744073709551615, 0, 65), - (13, 969, 971, 85, 18446744073709551615, 0, 1), - (13, 970, 199, 88, 18446744073709551615, 0, 2), - (13, 765, 1072, 203, 18446744073709551615, 0, 63), - (13, 203, 1072, 85, 18446744073709551615, 0, 1), - (13, 765, 974, 972, 18446744073709551615, 0, 62), - (13, 972, 974, 88, 18446744073709551615, 0, 1), - (13, 765, 202, 973, 18446744073709551615, 0, 61), - (13, 973, 202, 91, 18446744073709551615, 0, 2), - (13, 765, 1071, 206, 18446744073709551615, 0, 60), - (13, 206, 1071, 88, 18446744073709551615, 0, 1), - (13, 765, 977, 975, 18446744073709551615, 0, 59), - (13, 975, 977, 91, 18446744073709551615, 0, 1), - (13, 765, 205, 976, 18446744073709551615, 0, 58), - (13, 976, 205, 94, 18446744073709551615, 0, 2), - (13, 765, 1070, 209, 18446744073709551615, 0, 57), - (13, 209, 1070, 91, 18446744073709551615, 0, 1), - (13, 978, 980, 94, 18446744073709551615, 0, 1), - (13, 765, 208, 979, 18446744073709551615, 0, 55), - (13, 979, 208, 100, 18446744073709551615, 0, 2), - (13, 765, 1069, 212, 18446744073709551615, 0, 54), - (13, 212, 1069, 97, 18446744073709551615, 0, 1), - (13, 765, 983, 981, 18446744073709551615, 0, 53), - (13, 981, 983, 100, 18446744073709551615, 0, 1), - (13, 982, 211, 103, 18446744073709551615, 0, 2), - (13, 765, 1068, 215, 18446744073709551615, 0, 51), - (13, 215, 1068, 100, 18446744073709551615, 0, 1), - (13, 765, 214, 985, 18446744073709551615, 0, 49), - (13, 985, 214, 109, 18446744073709551615, 0, 1), - (13, 765, 1067, 218, 18446744073709551615, 0, 48), - (13, 218, 1067, 103, 18446744073709551615, 0, 1), - (13, 765, 989, 987, 18446744073709551615, 0, 47), - (13, 987, 989, 109, 18446744073709551615, 0, 1), - (13, 765, 217, 988, 18446744073709551615, 0, 46), - (13, 988, 217, 109, 18446744073709551615, 0, 1), - (13, 765, 1066, 221, 18446744073709551615, 0, 45), - (13, 221, 1066, 109, 18446744073709551615, 0, 1), - (13, 990, 992, 120, 18446744073709551615, 0, 1), - (13, 765, 220, 991, 18446744073709551615, 0, 43), - (13, 991, 220, 112, 18446744073709551615, 0, 2), - (13, 765, 1065, 224, 18446744073709551615, 0, 42), - (13, 224, 1065, 120, 18446744073709551615, 0, 1), - (13, 765, 995, 993, 18446744073709551615, 0, 41), - (13, 993, 995, 122, 18446744073709551615, 0, 1), - (13, 765, 223, 994, 18446744073709551615, 0, 40), - (13, 994, 223, 122, 18446744073709551615, 0, 2), - (13, 765, 1064, 227, 18446744073709551615, 0, 39), - (13, 996, 998, 122, 18446744073709551615, 0, 1), - (13, 765, 226, 997, 18446744073709551615, 0, 37), - (13, 997, 226, 131, 18446744073709551615, 0, 1), - (13, 765, 1063, 230, 18446744073709551615, 0, 36), - (13, 230, 1063, 122, 18446744073709551615, 0, 1), - (13, 999, 1001, 131, 18446744073709551615, 0, 1), - (13, 765, 229, 1000, 18446744073709551615, 0, 34), - (13, 1000, 229, 134, 18446744073709551615, 0, 2), - (13, 233, 1062, 131, 18446744073709551615, 0, 1), - (13, 765, 1004, 1002, 18446744073709551615, 0, 32), - (13, 1002, 1004, 134, 18446744073709551615, 0, 1), - (13, 765, 232, 1003, 18446744073709551615, 0, 31), - (13, 1003, 232, 1096, 18446744073709551615, 0, 1), - (13, 236, 1061, 131, 18446744073709551615, 0, 1), - (13, 765, 1007, 1005, 18446744073709551615, 0, 29), - (13, 1005, 1007, 1096, 18446744073709551615, 0, 1), - (13, 1006, 235, 1091, 18446744073709551615, 0, 1), - (13, 239, 1060, 137, 18446744073709551615, 0, 1), - (13, 765, 1010, 1008, 18446744073709551615, 0, 26), - (13, 1008, 1010, 1091, 18446744073709551615, 0, 1), - (13, 765, 238, 1009, 18446744073709551615, 0, 25), - (13, 1009, 238, 141, 18446744073709551615, 0, 1), - (13, 242, 1059, 1096, 18446744073709551615, 0, 1), - (13, 765, 1013, 1011, 18446744073709551615, 0, 23), - (13, 1011, 1013, 1091, 18446744073709551615, 0, 1), - (13, 1012, 241, 152, 18446744073709551615, 0, 1), - (13, 765, 1058, 245, 18446744073709551615, 0, 21), - (13, 245, 1058, 141, 18446744073709551615, 0, 1), - (13, 1014, 1016, 149, 18446744073709551615, 0, 1), - (13, 248, 1057, 152, 18446744073709551615, 0, 1), - (13, 765, 1056, 251, 18446744073709551615, 0, 15), - (13, 251, 1056, 912, 18446744073709551615, 0, 1), - (13, 1020, 1022, 159, 18446744073709551615, 0, 1), - (13, 765, 250, 1021, 18446744073709551615, 0, 13), - (13, 1021, 250, 173, 18446744073709551615, 0, 2), - (13, 765, 1054, 254, 18446744073709551615, 0, 12), - (13, 254, 1054, 159, 18446744073709551615, 0, 1), - (13, 765, 1055, 1023, 18446744073709551615, 0, 11), - (13, 1023, 1055, 173, 18446744073709551615, 0, 1), - (13, 765, 253, 1049, 18446744073709551615, 0, 10), - (13, 1049, 253, 1083, 18446744073709551615, 0, 1), - (13, 799, 172, 249, 18446744073709551615, 0, 1), - (13, 898, 1053, 734, 18446744073709551615, 0, 2), - (13, 898, 255, 734, 18446744073709551615, 0, 2), - (13, 898, 1047, 734, 18446744073709551615, 0, 2), - (13, 898, 252, 734, 18446744073709551615, 0, 2), - (13, 898, 172, 734, 18446744073709551615, 0, 2), - (13, 898, 249, 734, 18446744073709551615, 0, 2), - (13, 898, 246, 734, 18446744073709551615, 0, 2), - (13, 898, 243, 734, 18446744073709551615, 0, 2), - (13, 898, 240, 734, 18446744073709551615, 0, 2), - (13, 898, 237, 734, 18446744073709551615, 0, 2), - (13, 898, 234, 734, 18446744073709551615, 0, 2), - (13, 898, 231, 734, 18446744073709551615, 0, 2), - (13, 898, 228, 734, 18446744073709551615, 0, 2), - (13, 898, 225, 734, 18446744073709551615, 0, 2), - (13, 898, 222, 734, 18446744073709551615, 0, 2), - (13, 898, 219, 734, 18446744073709551615, 0, 2), - (13, 898, 216, 734, 18446744073709551615, 0, 2), - (13, 898, 213, 734, 18446744073709551615, 0, 2), - (13, 898, 210, 734, 18446744073709551615, 0, 2), - (13, 898, 207, 734, 18446744073709551615, 0, 2), - (13, 898, 204, 734, 18446744073709551615, 0, 2), - (13, 898, 201, 734, 18446744073709551615, 0, 2), - (13, 898, 198, 734, 18446744073709551615, 0, 2), - (13, 898, 195, 734, 18446744073709551615, 0, 2), - (13, 898, 192, 734, 18446744073709551615, 0, 2), - (13, 898, 189, 734, 18446744073709551615, 0, 2), - (13, 898, 186, 734, 18446744073709551615, 0, 2), - (13, 898, 183, 734, 18446744073709551615, 0, 2), - (13, 898, 180, 734, 18446744073709551615, 0, 2), - (13, 898, 177, 734, 18446744073709551615, 0, 2), - (13, 898, 174, 734, 18446744073709551615, 0, 2), - (13, 898, 1083, 734, 18446744073709551615, 0, 2), - (13, 898, 173, 734, 18446744073709551615, 0, 2), - (13, 898, 159, 734, 18446744073709551615, 0, 2), - (13, 898, 912, 734, 18446744073709551615, 0, 2), - (13, 898, 152, 734, 18446744073709551615, 0, 2), - (13, 898, 149, 734, 18446744073709551615, 0, 2), - (13, 898, 141, 734, 18446744073709551615, 0, 2), - (13, 898, 1091, 734, 18446744073709551615, 0, 2), - (13, 898, 1096, 734, 18446744073709551615, 0, 2), - (13, 898, 137, 734, 18446744073709551615, 0, 2), - (13, 898, 134, 734, 18446744073709551615, 0, 2), - (13, 898, 131, 734, 18446744073709551615, 0, 2), - (13, 898, 124, 734, 18446744073709551615, 0, 2), - (13, 898, 122, 734, 18446744073709551615, 0, 2), - (13, 898, 112, 734, 18446744073709551615, 0, 2), - (13, 898, 120, 734, 18446744073709551615, 0, 2), - (13, 898, 109, 734, 18446744073709551615, 0, 2), - (13, 898, 106, 734, 18446744073709551615, 0, 2), - (13, 898, 103, 734, 18446744073709551615, 0, 2), - (13, 898, 100, 734, 18446744073709551615, 0, 2), - (13, 898, 97, 734, 18446744073709551615, 0, 2), - (13, 898, 94, 734, 18446744073709551615, 0, 2), - (13, 898, 91, 734, 18446744073709551615, 0, 2), - (13, 898, 88, 734, 18446744073709551615, 0, 2), - (13, 898, 85, 734, 18446744073709551615, 0, 2), - (13, 898, 82, 734, 18446744073709551615, 0, 2), - (13, 898, 79, 734, 18446744073709551615, 0, 2), - (13, 898, 76, 734, 18446744073709551615, 0, 2), - (13, 898, 73, 734, 18446744073709551615, 0, 2), - (13, 898, 70, 734, 18446744073709551615, 0, 2), - (13, 898, 67, 734, 18446744073709551615, 0, 2), - (13, 898, 64, 734, 18446744073709551615, 0, 2), - (13, 898, 61, 734, 18446744073709551615, 0, 2), - (13, 898, 58, 734, 18446744073709551615, 0, 2), - (13, 898, 55, 734, 18446744073709551615, 0, 2), - (13, 898, 52, 734, 18446744073709551615, 0, 2), - (13, 898, 49, 734, 18446744073709551615, 0, 2), - (13, 898, 46, 734, 18446744073709551615, 0, 2), - (13, 898, 43, 734, 18446744073709551615, 0, 2), - (13, 898, 40, 734, 18446744073709551615, 0, 2), - (13, 898, 37, 734, 18446744073709551615, 0, 2), - (13, 898, 34, 734, 18446744073709551615, 0, 2), - (13, 898, 31, 734, 18446744073709551615, 0, 2), - (13, 898, 28, 734, 18446744073709551615, 0, 2), - (13, 898, 19, 734, 18446744073709551615, 0, 2), - (13, 898, 1133, 734, 18446744073709551615, 0, 2), - (13, 898, 735, 605, 18446744073709551615, 0, 1), - (13, 626, 1042, 627, 18446744073709551615, 0, 1), - (13, 627, 1052, 628, 18446744073709551615, 0, 1), - (13, 628, 1051, 629, 18446744073709551615, 0, 1), - (13, 630, 255, 631, 18446744073709551615, 0, 1), - (13, 631, 1047, 632, 18446744073709551615, 0, 1), - (13, 632, 252, 633, 18446744073709551615, 0, 1), - (13, 633, 172, 634, 18446744073709551615, 0, 1), - (13, 634, 249, 635, 18446744073709551615, 0, 1), - (13, 635, 246, 636, 18446744073709551615, 0, 1), - (13, 636, 243, 637, 18446744073709551615, 0, 1), - (13, 637, 240, 638, 18446744073709551615, 0, 1), - (13, 638, 237, 639, 18446744073709551615, 0, 1), - (13, 639, 234, 640, 18446744073709551615, 0, 1), - (13, 640, 231, 641, 18446744073709551615, 0, 1), - (13, 641, 228, 642, 18446744073709551615, 0, 1), - (13, 642, 225, 643, 18446744073709551615, 0, 1), - (13, 643, 222, 644, 18446744073709551615, 0, 1), - (13, 644, 219, 645, 18446744073709551615, 0, 1), - (13, 645, 216, 646, 18446744073709551615, 0, 1), - (13, 646, 213, 647, 18446744073709551615, 0, 1), - (13, 647, 210, 648, 18446744073709551615, 0, 1), - (13, 648, 207, 649, 18446744073709551615, 0, 1), - (13, 649, 204, 650, 18446744073709551615, 0, 1), - (13, 650, 201, 651, 18446744073709551615, 0, 1), - (13, 651, 198, 652, 18446744073709551615, 0, 1), - (13, 652, 195, 653, 18446744073709551615, 0, 1), - (13, 653, 192, 654, 18446744073709551615, 0, 1), - (13, 654, 189, 655, 18446744073709551615, 0, 1), - (13, 655, 186, 656, 18446744073709551615, 0, 1), - (13, 656, 183, 657, 18446744073709551615, 0, 1), - (13, 657, 180, 658, 18446744073709551615, 0, 1), - (13, 658, 177, 659, 18446744073709551615, 0, 1), - (13, 659, 174, 660, 18446744073709551615, 0, 1), - (13, 660, 1083, 661, 18446744073709551615, 0, 1), - (13, 661, 173, 662, 18446744073709551615, 0, 1), - (13, 662, 159, 663, 18446744073709551615, 0, 1), - (13, 663, 912, 664, 18446744073709551615, 0, 1), - (13, 664, 152, 665, 18446744073709551615, 0, 1), - (13, 665, 149, 666, 18446744073709551615, 0, 1), - (13, 666, 141, 667, 18446744073709551615, 0, 1), - (13, 667, 1091, 668, 18446744073709551615, 0, 1), - (13, 668, 1096, 669, 18446744073709551615, 0, 1), - (13, 669, 137, 670, 18446744073709551615, 0, 1), - (13, 670, 134, 671, 18446744073709551615, 0, 1), - (13, 671, 131, 672, 18446744073709551615, 0, 1), - (13, 672, 124, 673, 18446744073709551615, 0, 1), - (13, 673, 122, 674, 18446744073709551615, 0, 1), - (13, 674, 112, 675, 18446744073709551615, 0, 1), - (13, 675, 120, 676, 18446744073709551615, 0, 1), - (13, 676, 109, 677, 18446744073709551615, 0, 1), - (13, 677, 106, 678, 18446744073709551615, 0, 1), - (13, 678, 103, 679, 18446744073709551615, 0, 1), - (13, 679, 100, 680, 18446744073709551615, 0, 1), - (13, 680, 97, 681, 18446744073709551615, 0, 1), - (13, 681, 94, 682, 18446744073709551615, 0, 1), - (13, 682, 91, 683, 18446744073709551615, 0, 1), - (13, 683, 88, 684, 18446744073709551615, 0, 1), - (13, 684, 85, 685, 18446744073709551615, 0, 1), - (13, 685, 82, 686, 18446744073709551615, 0, 1), - (13, 686, 79, 687, 18446744073709551615, 0, 1), - (13, 687, 76, 688, 18446744073709551615, 0, 1), - (13, 688, 73, 689, 18446744073709551615, 0, 1), - (13, 689, 70, 690, 18446744073709551615, 0, 1), - (13, 690, 67, 691, 18446744073709551615, 0, 1), - (13, 691, 64, 692, 18446744073709551615, 0, 1), - (13, 692, 61, 693, 18446744073709551615, 0, 1), - (13, 693, 58, 694, 18446744073709551615, 0, 1), - (13, 694, 55, 695, 18446744073709551615, 0, 1), - (13, 695, 52, 696, 18446744073709551615, 0, 1), - (13, 696, 49, 697, 18446744073709551615, 0, 1), - (13, 697, 46, 698, 18446744073709551615, 0, 1), - (13, 698, 43, 699, 18446744073709551615, 0, 1), - (13, 699, 40, 700, 18446744073709551615, 0, 1), - (13, 700, 37, 701, 18446744073709551615, 0, 1), - (13, 701, 34, 702, 18446744073709551615, 0, 1), - (13, 702, 31, 703, 18446744073709551615, 0, 1), - (13, 703, 28, 704, 18446744073709551615, 0, 1), - (13, 704, 19, 705, 18446744073709551615, 0, 1), - (13, 705, 1133, 706, 18446744073709551615, 0, 1), - (13, 706, 784, 707, 18446744073709551615, 0, 1), - (13, 707, 782, 708, 18446744073709551615, 0, 1), - (13, 708, 1138, 709, 18446744073709551615, 0, 1), - (13, 709, 1114, 710, 18446744073709551615, 0, 1), - (13, 710, 1135, 711, 18446744073709551615, 0, 1), - (13, 711, 783, 712, 18446744073709551615, 0, 1), - (13, 712, 1136, 713, 18446744073709551615, 0, 1), - (13, 713, 836, 714, 18446744073709551615, 0, 1), - (13, 714, 15, 715, 18446744073709551615, 0, 1), - (13, 715, 1146, 716, 18446744073709551615, 0, 1), - (13, 716, 746, 717, 18446744073709551615, 0, 1), - (13, 717, 1152, 718, 18446744073709551615, 0, 1), - (13, 718, 781, 719, 18446744073709551615, 0, 1), - (13, 719, 1143, 720, 18446744073709551615, 0, 1), - (13, 720, 1144, 721, 18446744073709551615, 0, 1), - (13, 721, 745, 722, 18446744073709551615, 0, 1), - (13, 722, 744, 723, 18446744073709551615, 0, 1), - (13, 723, 743, 724, 18446744073709551615, 0, 1), - (13, 724, 742, 725, 18446744073709551615, 0, 1), - (13, 725, 741, 726, 18446744073709551615, 0, 1), - (13, 726, 740, 727, 18446744073709551615, 0, 1), - (13, 727, 739, 728, 18446744073709551615, 0, 1), - (13, 728, 738, 729, 18446744073709551615, 0, 1), - (13, 729, 737, 730, 18446744073709551615, 0, 1), - (13, 730, 736, 731, 18446744073709551615, 0, 1), - (13, 731, 735, 732, 18446744073709551615, 0, 1), - (13, 799, 574, 573, 18446744073709551615, 0, 1), - (13, 151, 626, 627, 18446744073709551615, 0, 2), - (13, 921, 628, 629, 18446744073709551615, 0, 2), - (13, 154, 629, 630, 18446744073709551615, 0, 2), - (13, 157, 630, 631, 18446744073709551615, 0, 2), - (13, 155, 631, 632, 18446744073709551615, 0, 2), - (13, 153, 632, 633, 18446744073709551615, 0, 2), - (13, 160, 633, 634, 18446744073709551615, 0, 2), - (13, 158, 634, 635, 18446744073709551615, 0, 2), - (13, 935, 635, 636, 18446744073709551615, 0, 2), - (13, 929, 636, 637, 18446744073709551615, 0, 2), - (13, 933, 637, 638, 18446744073709551615, 0, 2), - (13, 165, 638, 639, 18446744073709551615, 0, 2), - (13, 161, 639, 640, 18446744073709551615, 0, 2), - (13, 164, 640, 641, 18446744073709551615, 0, 2), - (13, 162, 641, 642, 18446744073709551615, 0, 2), - (13, 167, 642, 643, 18446744073709551615, 0, 2), - (13, 936, 643, 644, 18446744073709551615, 0, 2), - (13, 937, 644, 645, 18446744073709551615, 0, 2), - (13, 170, 645, 646, 18446744073709551615, 0, 2), - (13, 168, 646, 647, 18446744073709551615, 0, 2), - (13, 156, 647, 648, 18446744073709551615, 0, 2), - (13, 1082, 648, 649, 18446744073709551615, 0, 2), - (13, 942, 649, 650, 18446744073709551615, 0, 2), - (13, 943, 650, 651, 18446744073709551615, 0, 2), - (13, 176, 651, 652, 18446744073709551615, 0, 2), - (13, 945, 652, 653, 18446744073709551615, 0, 2), - (13, 946, 653, 654, 18446744073709551615, 0, 2), - (13, 179, 654, 655, 18446744073709551615, 0, 2), - (13, 948, 655, 656, 18446744073709551615, 0, 2), - (13, 949, 656, 657, 18446744073709551615, 0, 2), - (13, 182, 657, 658, 18446744073709551615, 0, 2), - (13, 951, 658, 659, 18446744073709551615, 0, 2), - (13, 952, 659, 660, 18446744073709551615, 0, 2), - (13, 185, 660, 661, 18446744073709551615, 0, 2), - (13, 954, 661, 662, 18446744073709551615, 0, 2), - (13, 955, 662, 663, 18446744073709551615, 0, 2), - (13, 188, 663, 664, 18446744073709551615, 0, 2), - (13, 957, 664, 665, 18446744073709551615, 0, 2), - (13, 958, 665, 666, 18446744073709551615, 0, 2), - (13, 191, 666, 667, 18446744073709551615, 0, 2), - (13, 960, 667, 668, 18446744073709551615, 0, 2), - (13, 961, 668, 669, 18446744073709551615, 0, 2), - (13, 194, 669, 670, 18446744073709551615, 0, 2), - (13, 963, 670, 671, 18446744073709551615, 0, 2), - (13, 964, 671, 672, 18446744073709551615, 0, 2), - (13, 197, 672, 673, 18446744073709551615, 0, 2), - (13, 966, 673, 674, 18446744073709551615, 0, 2), - (13, 967, 674, 675, 18446744073709551615, 0, 2), - (13, 200, 675, 676, 18446744073709551615, 0, 2), - (13, 969, 676, 677, 18446744073709551615, 0, 2), - (13, 970, 677, 678, 18446744073709551615, 0, 2), - (13, 203, 678, 679, 18446744073709551615, 0, 2), - (13, 972, 679, 680, 18446744073709551615, 0, 2), - (13, 973, 680, 681, 18446744073709551615, 0, 2), - (13, 206, 681, 682, 18446744073709551615, 0, 2), - (13, 975, 682, 683, 18446744073709551615, 0, 2), - (13, 976, 683, 684, 18446744073709551615, 0, 2), - (13, 209, 684, 685, 18446744073709551615, 0, 2), - (13, 978, 685, 686, 18446744073709551615, 0, 2), - (13, 979, 686, 687, 18446744073709551615, 0, 2), - (13, 212, 687, 688, 18446744073709551615, 0, 2), - (13, 981, 688, 689, 18446744073709551615, 0, 2), - (13, 982, 689, 690, 18446744073709551615, 0, 2), - (13, 215, 690, 691, 18446744073709551615, 0, 2), - (13, 984, 691, 692, 18446744073709551615, 0, 2), - (13, 985, 692, 693, 18446744073709551615, 0, 2), - (13, 218, 693, 694, 18446744073709551615, 0, 2), - (13, 987, 694, 695, 18446744073709551615, 0, 2), - (13, 988, 695, 696, 18446744073709551615, 0, 2), - (13, 221, 696, 697, 18446744073709551615, 0, 2), - (13, 990, 697, 698, 18446744073709551615, 0, 2), - (13, 991, 698, 699, 18446744073709551615, 0, 2), - (13, 224, 699, 700, 18446744073709551615, 0, 2), - (13, 993, 700, 701, 18446744073709551615, 0, 2), - (13, 994, 701, 702, 18446744073709551615, 0, 2), - (13, 227, 702, 703, 18446744073709551615, 0, 2), - (13, 996, 703, 704, 18446744073709551615, 0, 2), - (13, 997, 704, 705, 18446744073709551615, 0, 2), - (13, 230, 705, 706, 18446744073709551615, 0, 2), - (13, 999, 706, 707, 18446744073709551615, 0, 2), - (13, 1000, 707, 708, 18446744073709551615, 0, 2), - (13, 233, 708, 709, 18446744073709551615, 0, 4), - (13, 1002, 709, 710, 18446744073709551615, 0, 4), - (13, 1003, 710, 711, 18446744073709551615, 0, 4), - (13, 236, 711, 712, 18446744073709551615, 0, 4), - (13, 1005, 712, 713, 18446744073709551615, 0, 4), - (13, 1006, 713, 714, 18446744073709551615, 0, 4), - (13, 239, 714, 715, 18446744073709551615, 0, 4), - (13, 1008, 715, 716, 18446744073709551615, 0, 4), - (13, 1009, 716, 717, 18446744073709551615, 0, 4), - (13, 242, 717, 718, 18446744073709551615, 0, 4), - (13, 1011, 718, 719, 18446744073709551615, 0, 4), - (13, 1012, 719, 720, 18446744073709551615, 0, 4), - (13, 245, 720, 721, 18446744073709551615, 0, 4), - (13, 1014, 721, 722, 18446744073709551615, 0, 4), - (13, 1015, 722, 723, 18446744073709551615, 0, 4), - (13, 248, 723, 724, 18446744073709551615, 0, 4), - (13, 1017, 724, 725, 18446744073709551615, 0, 4), - (13, 1018, 725, 726, 18446744073709551615, 0, 4), - (13, 251, 726, 727, 18446744073709551615, 0, 4), - (13, 1020, 727, 728, 18446744073709551615, 0, 4), - (13, 1021, 728, 729, 18446744073709551615, 0, 4), - (13, 254, 729, 730, 18446744073709551615, 0, 2), - (13, 1023, 730, 731, 18446744073709551615, 0, 4), - (13, 731, 1049, 732, 18446744073709551615, 0, 1), - (13, 1023, 730, 731, 18446744073709551615, 1, 4), - (13, 254, 729, 730, 18446744073709551615, 1, 2), - (13, 1021, 728, 729, 18446744073709551615, 1, 4), - (13, 1020, 727, 728, 18446744073709551615, 1, 4), - (13, 251, 726, 727, 18446744073709551615, 1, 4), - (13, 1018, 725, 726, 18446744073709551615, 1, 4), - (13, 1017, 724, 725, 18446744073709551615, 1, 4), - (13, 248, 723, 724, 18446744073709551615, 1, 4), - (13, 1015, 722, 723, 18446744073709551615, 1, 4), - (13, 1014, 721, 722, 18446744073709551615, 1, 4), - (13, 245, 720, 721, 18446744073709551615, 1, 4), - (13, 1012, 719, 720, 18446744073709551615, 1, 4), - (13, 1011, 718, 719, 18446744073709551615, 1, 4), - (13, 242, 717, 718, 18446744073709551615, 1, 4), - (13, 1009, 716, 717, 18446744073709551615, 1, 4), - (13, 1008, 715, 716, 18446744073709551615, 1, 4), - (13, 239, 714, 715, 18446744073709551615, 1, 4), - (13, 1006, 713, 714, 18446744073709551615, 1, 4), - (13, 1005, 712, 713, 18446744073709551615, 1, 4), - (13, 236, 711, 712, 18446744073709551615, 1, 4), - (13, 1003, 710, 711, 18446744073709551615, 1, 4), - (13, 1002, 709, 710, 18446744073709551615, 1, 4), - (13, 233, 708, 709, 18446744073709551615, 1, 4), - (13, 1000, 707, 708, 18446744073709551615, 1, 2), - (13, 999, 706, 707, 18446744073709551615, 1, 2), - (13, 230, 705, 706, 18446744073709551615, 1, 2), - (13, 997, 704, 705, 18446744073709551615, 1, 2), - (13, 996, 703, 704, 18446744073709551615, 1, 2), - (13, 227, 702, 703, 18446744073709551615, 1, 2), - (13, 994, 701, 702, 18446744073709551615, 1, 2), - (13, 993, 700, 701, 18446744073709551615, 1, 2), - (13, 224, 699, 700, 18446744073709551615, 1, 2), - (13, 991, 698, 699, 18446744073709551615, 1, 2), - (13, 990, 697, 698, 18446744073709551615, 1, 2), - (13, 221, 696, 697, 18446744073709551615, 1, 2), - (13, 988, 695, 696, 18446744073709551615, 1, 2), - (13, 987, 694, 695, 18446744073709551615, 1, 2), - (13, 218, 693, 694, 18446744073709551615, 1, 2), - (13, 985, 692, 693, 18446744073709551615, 1, 2), - (13, 984, 691, 692, 18446744073709551615, 1, 2), - (13, 215, 690, 691, 18446744073709551615, 1, 2), - (13, 982, 689, 690, 18446744073709551615, 1, 2), - (13, 981, 688, 689, 18446744073709551615, 1, 2), - (13, 212, 687, 688, 18446744073709551615, 1, 2), - (13, 979, 686, 687, 18446744073709551615, 1, 2), - (13, 978, 685, 686, 18446744073709551615, 1, 2), - (13, 209, 684, 685, 18446744073709551615, 1, 2), - (13, 976, 683, 684, 18446744073709551615, 1, 2), - (13, 975, 682, 683, 18446744073709551615, 1, 2), - (13, 206, 681, 682, 18446744073709551615, 1, 2), - (13, 973, 680, 681, 18446744073709551615, 1, 2), - (13, 972, 679, 680, 18446744073709551615, 1, 2), - (13, 203, 678, 679, 18446744073709551615, 1, 2), - (13, 970, 677, 678, 18446744073709551615, 1, 2), - (13, 969, 676, 677, 18446744073709551615, 1, 2), - (13, 200, 675, 676, 18446744073709551615, 1, 2), - (13, 967, 674, 675, 18446744073709551615, 1, 2), - (13, 966, 673, 674, 18446744073709551615, 1, 2), - (13, 197, 672, 673, 18446744073709551615, 1, 2), - (13, 964, 671, 672, 18446744073709551615, 1, 2), - (13, 963, 670, 671, 18446744073709551615, 1, 2), - (13, 194, 669, 670, 18446744073709551615, 1, 2), - (13, 961, 668, 669, 18446744073709551615, 1, 2), - (13, 960, 667, 668, 18446744073709551615, 1, 2), - (13, 191, 666, 667, 18446744073709551615, 1, 2), - (13, 958, 665, 666, 18446744073709551615, 1, 2), - (13, 957, 664, 665, 18446744073709551615, 1, 2), - (13, 188, 663, 664, 18446744073709551615, 1, 2), - (13, 955, 662, 663, 18446744073709551615, 1, 2), - (13, 954, 661, 662, 18446744073709551615, 1, 2), - (13, 185, 660, 661, 18446744073709551615, 1, 2), - (13, 952, 659, 660, 18446744073709551615, 1, 2), - (13, 951, 658, 659, 18446744073709551615, 1, 2), - (13, 182, 657, 658, 18446744073709551615, 1, 2), - (13, 949, 656, 657, 18446744073709551615, 1, 2), - (13, 948, 655, 656, 18446744073709551615, 1, 2), - (13, 179, 654, 655, 18446744073709551615, 1, 2), - (13, 946, 653, 654, 18446744073709551615, 1, 2), - (13, 945, 652, 653, 18446744073709551615, 1, 2), - (13, 176, 651, 652, 18446744073709551615, 1, 2), - (13, 943, 650, 651, 18446744073709551615, 1, 2), - (13, 942, 649, 650, 18446744073709551615, 1, 2), - (13, 1082, 648, 649, 18446744073709551615, 1, 2), - (13, 156, 647, 648, 18446744073709551615, 1, 2), - (13, 168, 646, 647, 18446744073709551615, 1, 2), - (13, 170, 645, 646, 18446744073709551615, 1, 2), - (13, 937, 644, 645, 18446744073709551615, 1, 2), - (13, 936, 643, 644, 18446744073709551615, 1, 2), - (13, 167, 642, 643, 18446744073709551615, 1, 2), - (13, 162, 641, 642, 18446744073709551615, 1, 2), - (13, 164, 640, 641, 18446744073709551615, 1, 2), - (13, 161, 639, 640, 18446744073709551615, 1, 2), - (13, 165, 638, 639, 18446744073709551615, 1, 2), - (13, 933, 637, 638, 18446744073709551615, 1, 2), - (13, 929, 636, 637, 18446744073709551615, 1, 2), - (13, 935, 635, 636, 18446744073709551615, 1, 2), - (13, 158, 634, 635, 18446744073709551615, 1, 2), - (13, 160, 633, 634, 18446744073709551615, 1, 2), - (13, 153, 632, 633, 18446744073709551615, 1, 2), - (13, 155, 631, 632, 18446744073709551615, 1, 2), - (13, 157, 630, 631, 18446744073709551615, 1, 2), - (13, 154, 629, 630, 18446744073709551615, 1, 2), - (13, 921, 628, 629, 18446744073709551615, 1, 2), - (13, 151, 626, 627, 18446744073709551615, 1, 2), - (13, 732, 755, 733, 18446744073709551615, 0, 5), - (13, 754, 733, 605, 18446744073709551615, 0, 5), - (13, 753, 605, 604, 18446744073709551615, 0, 5), - (13, 752, 604, 603, 18446744073709551615, 0, 5), - (13, 751, 603, 602, 18446744073709551615, 0, 5), - (13, 750, 602, 601, 18446744073709551615, 0, 5), - (13, 749, 601, 600, 18446744073709551615, 0, 5), - (13, 748, 600, 599, 18446744073709551615, 0, 5), - (13, 747, 599, 598, 18446744073709551615, 0, 5), - (13, 14, 598, 597, 18446744073709551615, 0, 5), - (13, 11, 597, 596, 18446744073709551615, 0, 5), - (13, 777, 596, 595, 18446744073709551615, 0, 5), - (13, 13, 595, 594, 18446744073709551615, 0, 5), - (13, 1145, 594, 593, 18446744073709551615, 0, 5), - (13, 1137, 593, 592, 18446744073709551615, 0, 5), - (13, 17, 592, 591, 18446744073709551615, 0, 5), - (13, 1134, 591, 590, 18446744073709551615, 0, 5), - (13, 27, 590, 589, 18446744073709551615, 0, 5), - (13, 786, 589, 588, 18446744073709551615, 0, 5), - (13, 787, 588, 587, 18446744073709551615, 0, 5), - (13, 788, 587, 586, 18446744073709551615, 0, 5), - (13, 789, 586, 585, 18446744073709551615, 0, 5), - (13, 790, 585, 584, 18446744073709551615, 0, 5), - (13, 791, 584, 583, 18446744073709551615, 0, 5), - (13, 23, 583, 582, 18446744073709551615, 0, 5), - (13, 20, 582, 581, 18446744073709551615, 0, 5), - (13, 18, 581, 580, 18446744073709551615, 0, 5), - (13, 795, 580, 579, 18446744073709551615, 0, 5), - (13, 796, 579, 578, 18446744073709551615, 0, 5), - (13, 797, 578, 577, 18446744073709551615, 0, 5), - (13, 798, 577, 576, 18446744073709551615, 0, 5), - (13, 799, 576, 575, 18446744073709551615, 0, 5), - (13, 800, 575, 574, 18446744073709551615, 0, 5), - (13, 801, 574, 573, 18446744073709551615, 0, 5), - (13, 802, 573, 572, 18446744073709551615, 0, 5), - (13, 803, 572, 571, 18446744073709551615, 0, 5), - (13, 804, 571, 570, 18446744073709551615, 0, 5), - (13, 805, 570, 569, 18446744073709551615, 0, 5), - (13, 806, 569, 568, 18446744073709551615, 0, 5), - (13, 807, 568, 567, 18446744073709551615, 0, 5), - (13, 808, 567, 566, 18446744073709551615, 0, 5), - (13, 809, 566, 565, 18446744073709551615, 0, 5), - (13, 810, 565, 564, 18446744073709551615, 0, 5), - (13, 811, 564, 563, 18446744073709551615, 0, 5), - (13, 812, 563, 562, 18446744073709551615, 0, 5), - (13, 813, 562, 561, 18446744073709551615, 0, 5), - (13, 814, 561, 560, 18446744073709551615, 0, 5), - (13, 815, 560, 558, 18446744073709551615, 0, 5), - (13, 816, 558, 557, 18446744073709551615, 0, 10), - (13, 817, 557, 559, 18446744073709551615, 0, 5), - (13, 818, 559, 557, 18446744073709551615, 0, 5), - (13, 819, 557, 558, 18446744073709551615, 0, 5), - (14, 732, 819, 557, 18446744073709551615, 0, 5), - (14, 732, 817, 557, 18446744073709551615, 0, 5), - (13, 713, 1006, 604, 18446744073709551615, 0, 1), - (13, 714, 239, 603, 18446744073709551615, 0, 1), - (13, 715, 1008, 602, 18446744073709551615, 0, 1), - (13, 716, 1009, 601, 18446744073709551615, 0, 1), - (13, 717, 242, 600, 18446744073709551615, 0, 1), - (13, 718, 1011, 599, 18446744073709551615, 0, 1), - (13, 719, 1012, 598, 18446744073709551615, 0, 1), - (13, 720, 245, 597, 18446744073709551615, 0, 1), - (13, 721, 1014, 596, 18446744073709551615, 0, 1), - (13, 722, 1015, 595, 18446744073709551615, 0, 1), - (13, 723, 248, 594, 18446744073709551615, 0, 1), - (13, 724, 1017, 593, 18446744073709551615, 0, 1), - (13, 725, 1018, 592, 18446744073709551615, 0, 1), - (13, 726, 251, 591, 18446744073709551615, 0, 1), - (13, 727, 1020, 590, 18446744073709551615, 0, 1), - (13, 728, 1021, 589, 18446744073709551615, 0, 1), - (13, 729, 254, 588, 18446744073709551615, 0, 1), - (13, 730, 1023, 587, 18446744073709551615, 0, 1), - (13, 731, 1049, 586, 18446744073709551615, 0, 1), - (13, 155, 710, 709, 18446744073709551615, 0, 2), - (13, 153, 709, 708, 18446744073709551615, 0, 2), - (13, 160, 708, 707, 18446744073709551615, 0, 2), - (13, 158, 707, 706, 18446744073709551615, 0, 2), - (13, 933, 704, 703, 18446744073709551615, 0, 2), - (13, 165, 703, 702, 18446744073709551615, 0, 2), - (13, 161, 702, 701, 18446744073709551615, 0, 2), - (13, 164, 701, 700, 18446744073709551615, 0, 2), - (13, 162, 700, 699, 18446744073709551615, 0, 2), - (13, 167, 699, 698, 18446744073709551615, 0, 2), - (13, 936, 698, 697, 18446744073709551615, 0, 2), - (13, 937, 697, 696, 18446744073709551615, 0, 2), - (13, 170, 696, 695, 18446744073709551615, 0, 2), - (13, 168, 695, 694, 18446744073709551615, 0, 2), - (13, 156, 694, 693, 18446744073709551615, 0, 2), - (13, 1082, 693, 692, 18446744073709551615, 0, 2), - (13, 942, 692, 691, 18446744073709551615, 0, 2), - (13, 943, 691, 690, 18446744073709551615, 0, 2), - (13, 176, 690, 689, 18446744073709551615, 0, 2), - (13, 945, 689, 688, 18446744073709551615, 0, 2), - (13, 946, 688, 687, 18446744073709551615, 0, 2), - (13, 179, 687, 686, 18446744073709551615, 0, 2), - (13, 948, 686, 685, 18446744073709551615, 0, 2), - (13, 949, 685, 684, 18446744073709551615, 0, 2), - (13, 182, 684, 683, 18446744073709551615, 0, 2), - (13, 951, 683, 682, 18446744073709551615, 0, 2), - (13, 952, 682, 681, 18446744073709551615, 0, 2), - (13, 185, 681, 680, 18446744073709551615, 0, 2), - (13, 954, 680, 679, 18446744073709551615, 0, 2), - (13, 955, 679, 678, 18446744073709551615, 0, 2), - (13, 188, 678, 677, 18446744073709551615, 0, 2), - (13, 957, 677, 676, 18446744073709551615, 0, 2), - (13, 958, 676, 675, 18446744073709551615, 0, 2), - (13, 191, 675, 674, 18446744073709551615, 0, 2), - (13, 960, 674, 673, 18446744073709551615, 0, 2), - (13, 961, 673, 672, 18446744073709551615, 0, 2), - (13, 194, 672, 671, 18446744073709551615, 0, 2), - (13, 963, 671, 670, 18446744073709551615, 0, 2), - (13, 964, 670, 669, 18446744073709551615, 0, 2), - (13, 197, 669, 668, 18446744073709551615, 0, 2), - (13, 966, 668, 667, 18446744073709551615, 0, 2), - (13, 967, 667, 666, 18446744073709551615, 0, 2), - (13, 200, 666, 665, 18446744073709551615, 0, 2), - (13, 969, 665, 664, 18446744073709551615, 0, 2), - (13, 970, 664, 663, 18446744073709551615, 0, 2), - (13, 203, 663, 662, 18446744073709551615, 0, 2), - (13, 972, 662, 661, 18446744073709551615, 0, 2), - (13, 973, 661, 660, 18446744073709551615, 0, 2), - (13, 206, 660, 659, 18446744073709551615, 0, 2), - (13, 975, 659, 658, 18446744073709551615, 0, 2), - (13, 976, 658, 657, 18446744073709551615, 0, 2), - (13, 209, 657, 656, 18446744073709551615, 0, 2), - (13, 978, 656, 655, 18446744073709551615, 0, 2), - (13, 979, 655, 654, 18446744073709551615, 0, 2), - (13, 212, 654, 653, 18446744073709551615, 0, 2), - (13, 981, 653, 652, 18446744073709551615, 0, 2), - (13, 982, 652, 651, 18446744073709551615, 0, 2), - (13, 215, 651, 650, 18446744073709551615, 0, 2), - (13, 984, 650, 649, 18446744073709551615, 0, 2), - (13, 985, 649, 648, 18446744073709551615, 0, 2), - (13, 218, 648, 647, 18446744073709551615, 0, 2), - (13, 987, 647, 646, 18446744073709551615, 0, 2), - (13, 988, 646, 645, 18446744073709551615, 0, 2), - (13, 221, 645, 644, 18446744073709551615, 0, 2), - (13, 990, 644, 643, 18446744073709551615, 0, 2), - (13, 991, 643, 642, 18446744073709551615, 0, 2), - (13, 224, 642, 641, 18446744073709551615, 0, 2), - (13, 993, 641, 640, 18446744073709551615, 0, 2), - (13, 994, 640, 639, 18446744073709551615, 0, 2), - (13, 227, 639, 638, 18446744073709551615, 0, 2), - (13, 996, 638, 637, 18446744073709551615, 0, 2), - (13, 997, 637, 636, 18446744073709551615, 0, 2), - (13, 230, 636, 635, 18446744073709551615, 0, 2), - (13, 999, 635, 634, 18446744073709551615, 0, 2), - (13, 1000, 634, 633, 18446744073709551615, 0, 2), - (13, 233, 633, 632, 18446744073709551615, 0, 2), - (13, 1002, 632, 631, 18446744073709551615, 0, 2), - (13, 1003, 631, 630, 18446744073709551615, 0, 2), - (13, 236, 630, 629, 18446744073709551615, 0, 2), - (13, 1005, 629, 628, 18446744073709551615, 0, 2), - (13, 1006, 628, 627, 18446744073709551615, 0, 2), - (13, 239, 627, 626, 18446744073709551615, 0, 2), - (13, 1008, 626, 625, 18446744073709551615, 0, 2), - (13, 1009, 625, 624, 18446744073709551615, 0, 2), - (13, 242, 624, 623, 18446744073709551615, 0, 2), - (13, 1011, 623, 622, 18446744073709551615, 0, 2), - (13, 1012, 622, 621, 18446744073709551615, 0, 2), - (13, 245, 621, 620, 18446744073709551615, 0, 2), - (13, 1014, 620, 619, 18446744073709551615, 0, 2), - (13, 1015, 619, 618, 18446744073709551615, 0, 2), - (13, 248, 618, 617, 18446744073709551615, 0, 2), - (13, 1017, 617, 616, 18446744073709551615, 0, 2), - (13, 1018, 616, 615, 18446744073709551615, 0, 2), - (13, 251, 615, 614, 18446744073709551615, 0, 2), - (13, 1020, 614, 613, 18446744073709551615, 0, 2), - (13, 1021, 613, 612, 18446744073709551615, 0, 2), - (13, 254, 612, 611, 18446744073709551615, 0, 2), - (13, 1023, 611, 610, 18446744073709551615, 0, 4), - (13, 610, 1049, 609, 18446744073709551615, 0, 1), - (13, 1023, 611, 610, 18446744073709551615, 1, 4), - (13, 254, 612, 611, 18446744073709551615, 1, 2), - (13, 1021, 613, 612, 18446744073709551615, 1, 2), - (13, 1020, 614, 613, 18446744073709551615, 1, 2), - (13, 251, 615, 614, 18446744073709551615, 1, 2), - (13, 1018, 616, 615, 18446744073709551615, 1, 2), - (13, 1017, 617, 616, 18446744073709551615, 1, 2), - (13, 248, 618, 617, 18446744073709551615, 1, 2), - (13, 1015, 619, 618, 18446744073709551615, 1, 2), - (13, 1014, 620, 619, 18446744073709551615, 1, 2), - (13, 245, 621, 620, 18446744073709551615, 1, 2), - (13, 1012, 622, 621, 18446744073709551615, 1, 2), - (13, 1011, 623, 622, 18446744073709551615, 1, 2), - (13, 242, 624, 623, 18446744073709551615, 1, 2), - (13, 1009, 625, 624, 18446744073709551615, 1, 2), - (13, 1008, 626, 625, 18446744073709551615, 1, 2), - (13, 239, 627, 626, 18446744073709551615, 1, 2), - (13, 1006, 628, 627, 18446744073709551615, 1, 2), - (13, 1005, 629, 628, 18446744073709551615, 1, 2), - (13, 236, 630, 629, 18446744073709551615, 1, 2), - (13, 1003, 631, 630, 18446744073709551615, 1, 2), - (13, 1002, 632, 631, 18446744073709551615, 1, 2), - (13, 233, 633, 632, 18446744073709551615, 1, 2), - (13, 1000, 634, 633, 18446744073709551615, 1, 2), - (13, 999, 635, 634, 18446744073709551615, 1, 2), - (13, 230, 636, 635, 18446744073709551615, 1, 2), - (13, 997, 637, 636, 18446744073709551615, 1, 2), - (13, 996, 638, 637, 18446744073709551615, 1, 2), - (13, 227, 639, 638, 18446744073709551615, 1, 2), - (13, 994, 640, 639, 18446744073709551615, 1, 2), - (13, 993, 641, 640, 18446744073709551615, 1, 2), - (13, 224, 642, 641, 18446744073709551615, 1, 2), - (13, 991, 643, 642, 18446744073709551615, 1, 2), - (13, 990, 644, 643, 18446744073709551615, 1, 2), - (13, 221, 645, 644, 18446744073709551615, 1, 2), - (13, 988, 646, 645, 18446744073709551615, 1, 2), - (13, 987, 647, 646, 18446744073709551615, 1, 2), - (13, 218, 648, 647, 18446744073709551615, 1, 2), - (13, 985, 649, 648, 18446744073709551615, 1, 2), - (13, 984, 650, 649, 18446744073709551615, 1, 2), - (13, 215, 651, 650, 18446744073709551615, 1, 2), - (13, 982, 652, 651, 18446744073709551615, 1, 2), - (13, 981, 653, 652, 18446744073709551615, 1, 2), - (13, 212, 654, 653, 18446744073709551615, 1, 2), - (13, 979, 655, 654, 18446744073709551615, 1, 2), - (13, 978, 656, 655, 18446744073709551615, 1, 2), - (13, 209, 657, 656, 18446744073709551615, 1, 2), - (13, 976, 658, 657, 18446744073709551615, 1, 2), - (13, 975, 659, 658, 18446744073709551615, 1, 2), - (13, 206, 660, 659, 18446744073709551615, 1, 2), - (13, 973, 661, 660, 18446744073709551615, 1, 2), - (13, 972, 662, 661, 18446744073709551615, 1, 2), - (13, 203, 663, 662, 18446744073709551615, 1, 2), - (13, 970, 664, 663, 18446744073709551615, 1, 2), - (13, 969, 665, 664, 18446744073709551615, 1, 2), - (13, 200, 666, 665, 18446744073709551615, 1, 2), - (13, 967, 667, 666, 18446744073709551615, 1, 2), - (13, 966, 668, 667, 18446744073709551615, 1, 2), - (13, 197, 669, 668, 18446744073709551615, 1, 2), - (13, 964, 670, 669, 18446744073709551615, 1, 2), - (13, 963, 671, 670, 18446744073709551615, 1, 2), - (13, 194, 672, 671, 18446744073709551615, 1, 2), - (13, 961, 673, 672, 18446744073709551615, 1, 2), - (13, 960, 674, 673, 18446744073709551615, 1, 2), - (13, 191, 675, 674, 18446744073709551615, 1, 2), - (13, 958, 676, 675, 18446744073709551615, 1, 2), - (13, 957, 677, 676, 18446744073709551615, 1, 2), - (13, 188, 678, 677, 18446744073709551615, 1, 2), - (13, 955, 679, 678, 18446744073709551615, 1, 2), - (13, 954, 680, 679, 18446744073709551615, 1, 2), - (13, 185, 681, 680, 18446744073709551615, 1, 2), - (13, 952, 682, 681, 18446744073709551615, 1, 2), - (13, 951, 683, 682, 18446744073709551615, 1, 2), - (13, 182, 684, 683, 18446744073709551615, 1, 2), - (13, 949, 685, 684, 18446744073709551615, 1, 2), - (13, 948, 686, 685, 18446744073709551615, 1, 2), - (13, 179, 687, 686, 18446744073709551615, 1, 2), - (13, 946, 688, 687, 18446744073709551615, 1, 2), - (13, 945, 689, 688, 18446744073709551615, 1, 2), - (13, 176, 690, 689, 18446744073709551615, 1, 2), - (13, 943, 691, 690, 18446744073709551615, 1, 2), - (13, 942, 692, 691, 18446744073709551615, 1, 2), - (13, 1082, 693, 692, 18446744073709551615, 1, 2), - (13, 156, 694, 693, 18446744073709551615, 1, 2), - (13, 168, 695, 694, 18446744073709551615, 1, 2), - (13, 170, 696, 695, 18446744073709551615, 1, 2), - (13, 937, 697, 696, 18446744073709551615, 1, 2), - (13, 936, 698, 697, 18446744073709551615, 1, 2), - (13, 167, 699, 698, 18446744073709551615, 1, 2), - (13, 162, 700, 699, 18446744073709551615, 1, 2), - (13, 164, 701, 700, 18446744073709551615, 1, 2), - (13, 161, 702, 701, 18446744073709551615, 1, 2), - (13, 165, 703, 702, 18446744073709551615, 1, 2), - (13, 933, 704, 703, 18446744073709551615, 1, 2), - (13, 158, 707, 706, 18446744073709551615, 1, 2), - (13, 160, 708, 707, 18446744073709551615, 1, 2), - (13, 153, 709, 708, 18446744073709551615, 1, 2), - (13, 155, 710, 709, 18446744073709551615, 1, 2), - (13, 609, 755, 608, 18446744073709551615, 0, 3), - (13, 754, 608, 607, 18446744073709551615, 0, 3), - (13, 753, 607, 606, 18446744073709551615, 0, 3), - (13, 752, 606, 732, 18446744073709551615, 0, 3), - (13, 751, 732, 733, 18446744073709551615, 0, 3), - (13, 750, 733, 605, 18446744073709551615, 0, 3), - (13, 749, 605, 604, 18446744073709551615, 0, 3), - (13, 748, 604, 603, 18446744073709551615, 0, 3), - (13, 747, 603, 602, 18446744073709551615, 0, 3), - (13, 14, 602, 601, 18446744073709551615, 0, 3), - (13, 11, 601, 600, 18446744073709551615, 0, 3), - (13, 777, 600, 599, 18446744073709551615, 0, 3), - (13, 13, 599, 598, 18446744073709551615, 0, 3), - (13, 1145, 598, 597, 18446744073709551615, 0, 3), - (13, 1137, 597, 596, 18446744073709551615, 0, 3), - (13, 17, 596, 595, 18446744073709551615, 0, 3), - (13, 1134, 595, 594, 18446744073709551615, 0, 3), - (13, 27, 594, 593, 18446744073709551615, 0, 3), - (13, 786, 593, 592, 18446744073709551615, 0, 3), - (13, 787, 592, 591, 18446744073709551615, 0, 3), - (13, 788, 591, 590, 18446744073709551615, 0, 3), - (13, 789, 590, 589, 18446744073709551615, 0, 3), - (13, 790, 589, 588, 18446744073709551615, 0, 3), - (13, 791, 588, 587, 18446744073709551615, 0, 3), - (13, 23, 587, 586, 18446744073709551615, 0, 3), - (13, 20, 586, 585, 18446744073709551615, 0, 3), - (13, 18, 585, 584, 18446744073709551615, 0, 3), - (13, 795, 584, 583, 18446744073709551615, 0, 3), - (13, 796, 583, 582, 18446744073709551615, 0, 3), - (13, 797, 582, 581, 18446744073709551615, 0, 3), - (13, 798, 581, 580, 18446744073709551615, 0, 3), - (13, 799, 580, 579, 18446744073709551615, 0, 3), - (13, 800, 579, 578, 18446744073709551615, 0, 3), - (13, 801, 578, 577, 18446744073709551615, 0, 3), - (13, 802, 577, 576, 18446744073709551615, 0, 3), - (13, 803, 576, 575, 18446744073709551615, 0, 3), - (13, 804, 575, 574, 18446744073709551615, 0, 3), - (13, 805, 574, 573, 18446744073709551615, 0, 3), - (13, 806, 573, 572, 18446744073709551615, 0, 3), - (13, 807, 572, 571, 18446744073709551615, 0, 3), - (13, 808, 571, 570, 18446744073709551615, 0, 3), - (13, 809, 570, 569, 18446744073709551615, 0, 3), - (13, 810, 569, 568, 18446744073709551615, 0, 3), - (13, 811, 568, 567, 18446744073709551615, 0, 3), - (13, 812, 567, 566, 18446744073709551615, 0, 3), - (13, 813, 566, 565, 18446744073709551615, 0, 3), - (13, 814, 565, 564, 18446744073709551615, 0, 3), - (13, 815, 564, 562, 18446744073709551615, 0, 3), - (13, 816, 562, 561, 18446744073709551615, 0, 6), - (13, 817, 561, 563, 18446744073709551615, 0, 3), - (13, 818, 563, 561, 18446744073709551615, 0, 3), - (13, 819, 561, 562, 18446744073709551615, 0, 3), - (14, 609, 819, 561, 18446744073709551615, 0, 3), - (14, 609, 817, 561, 18446744073709551615, 0, 3), - (13, 628, 1006, 606, 18446744073709551615, 0, 1), - (13, 627, 239, 732, 18446744073709551615, 0, 1), - (13, 626, 1008, 733, 18446744073709551615, 0, 1), - (13, 625, 1009, 605, 18446744073709551615, 0, 1), - (13, 624, 242, 604, 18446744073709551615, 0, 1), - (13, 623, 1011, 603, 18446744073709551615, 0, 1), - (13, 622, 1012, 602, 18446744073709551615, 0, 1), - (13, 621, 245, 601, 18446744073709551615, 0, 1), - (13, 620, 1014, 600, 18446744073709551615, 0, 1), - (13, 619, 1015, 599, 18446744073709551615, 0, 1), - (13, 618, 248, 598, 18446744073709551615, 0, 1), - (13, 617, 1017, 597, 18446744073709551615, 0, 1), - (13, 616, 1018, 596, 18446744073709551615, 0, 1), - (13, 615, 251, 595, 18446744073709551615, 0, 1), - (13, 614, 1020, 594, 18446744073709551615, 0, 1), - (13, 613, 1021, 593, 18446744073709551615, 0, 1), - (13, 612, 254, 592, 18446744073709551615, 0, 1), - (13, 611, 1023, 591, 18446744073709551615, 0, 1), - (13, 610, 1049, 590, 18446744073709551615, 0, 1), - (13, 160, 631, 632, 18446744073709551615, 0, 2), - (13, 158, 632, 633, 18446744073709551615, 0, 2), - (13, 935, 633, 634, 18446744073709551615, 0, 2), - (13, 933, 635, 636, 18446744073709551615, 0, 2), - (13, 165, 636, 637, 18446744073709551615, 0, 2), - (13, 161, 637, 638, 18446744073709551615, 0, 2), - (13, 164, 638, 639, 18446744073709551615, 0, 2), - (13, 162, 639, 640, 18446744073709551615, 0, 2), - (13, 167, 640, 641, 18446744073709551615, 0, 2), - (13, 936, 641, 642, 18446744073709551615, 0, 2), - (13, 937, 642, 643, 18446744073709551615, 0, 2), - (13, 170, 643, 644, 18446744073709551615, 0, 2), - (13, 168, 644, 645, 18446744073709551615, 0, 2), - (13, 156, 645, 646, 18446744073709551615, 0, 2), - (13, 1082, 646, 647, 18446744073709551615, 0, 2), - (13, 942, 647, 648, 18446744073709551615, 0, 2), - (13, 943, 648, 649, 18446744073709551615, 0, 2), - (13, 176, 649, 650, 18446744073709551615, 0, 2), - (13, 945, 650, 651, 18446744073709551615, 0, 2), - (13, 946, 651, 652, 18446744073709551615, 0, 2), - (13, 179, 652, 653, 18446744073709551615, 0, 2), - (13, 948, 653, 654, 18446744073709551615, 0, 2), - (13, 949, 654, 655, 18446744073709551615, 0, 2), - (13, 182, 655, 656, 18446744073709551615, 0, 2), - (13, 951, 656, 657, 18446744073709551615, 0, 2), - (13, 952, 657, 658, 18446744073709551615, 0, 2), - (13, 185, 658, 659, 18446744073709551615, 0, 2), - (13, 954, 659, 660, 18446744073709551615, 0, 2), - (13, 955, 660, 661, 18446744073709551615, 0, 2), - (13, 188, 661, 662, 18446744073709551615, 0, 2), - (13, 957, 662, 663, 18446744073709551615, 0, 2), - (13, 958, 663, 664, 18446744073709551615, 0, 2), - (13, 191, 664, 665, 18446744073709551615, 0, 2), - (13, 960, 665, 666, 18446744073709551615, 0, 2), - (13, 961, 666, 667, 18446744073709551615, 0, 2), - (13, 194, 667, 668, 18446744073709551615, 0, 2), - (13, 963, 668, 669, 18446744073709551615, 0, 2), - (13, 964, 669, 670, 18446744073709551615, 0, 2), - (13, 197, 670, 671, 18446744073709551615, 0, 2), - (13, 966, 671, 672, 18446744073709551615, 0, 2), - (13, 967, 672, 673, 18446744073709551615, 0, 2), - (13, 200, 673, 674, 18446744073709551615, 0, 2), - (13, 969, 674, 675, 18446744073709551615, 0, 2), - (13, 970, 675, 676, 18446744073709551615, 0, 2), - (13, 203, 676, 677, 18446744073709551615, 0, 2), - (13, 972, 677, 678, 18446744073709551615, 0, 2), - (13, 973, 678, 679, 18446744073709551615, 0, 2), - (13, 206, 679, 680, 18446744073709551615, 0, 2), - (13, 975, 680, 681, 18446744073709551615, 0, 2), - (13, 976, 681, 682, 18446744073709551615, 0, 2), - (13, 209, 682, 683, 18446744073709551615, 0, 2), - (13, 978, 683, 684, 18446744073709551615, 0, 2), - (13, 979, 684, 685, 18446744073709551615, 0, 2), - (13, 212, 685, 686, 18446744073709551615, 0, 2), - (13, 981, 686, 687, 18446744073709551615, 0, 2), - (13, 982, 687, 688, 18446744073709551615, 0, 2), - (13, 215, 688, 689, 18446744073709551615, 0, 2), - (13, 984, 689, 690, 18446744073709551615, 0, 2), - (13, 985, 690, 691, 18446744073709551615, 0, 2), - (13, 218, 691, 692, 18446744073709551615, 0, 2), - (13, 987, 692, 693, 18446744073709551615, 0, 2), - (13, 988, 693, 694, 18446744073709551615, 0, 2), - (13, 221, 694, 695, 18446744073709551615, 0, 2), - (13, 990, 695, 696, 18446744073709551615, 0, 2), - (13, 991, 696, 697, 18446744073709551615, 0, 2), - (13, 224, 697, 698, 18446744073709551615, 0, 2), - (13, 993, 698, 699, 18446744073709551615, 0, 2), - (13, 994, 699, 700, 18446744073709551615, 0, 2), - (13, 227, 700, 701, 18446744073709551615, 0, 2), - (13, 996, 701, 702, 18446744073709551615, 0, 2), - (13, 997, 702, 703, 18446744073709551615, 0, 2), - (13, 230, 703, 704, 18446744073709551615, 0, 2), - (13, 999, 704, 705, 18446744073709551615, 0, 2), - (13, 1000, 705, 706, 18446744073709551615, 0, 2), - (13, 233, 706, 707, 18446744073709551615, 0, 2), - (13, 1002, 707, 708, 18446744073709551615, 0, 2), - (13, 1003, 708, 709, 18446744073709551615, 0, 2), - (13, 236, 709, 710, 18446744073709551615, 0, 2), - (13, 1005, 710, 711, 18446744073709551615, 0, 2), - (13, 1006, 711, 712, 18446744073709551615, 0, 2), - (13, 239, 712, 713, 18446744073709551615, 0, 2), - (13, 1008, 713, 714, 18446744073709551615, 0, 2), - (13, 1009, 714, 715, 18446744073709551615, 0, 2), - (13, 242, 715, 716, 18446744073709551615, 0, 2), - (13, 1011, 716, 717, 18446744073709551615, 0, 2), - (13, 1012, 717, 718, 18446744073709551615, 0, 2), - (13, 245, 718, 719, 18446744073709551615, 0, 2), - (13, 1014, 719, 720, 18446744073709551615, 0, 2), - (13, 1015, 720, 721, 18446744073709551615, 0, 2), - (13, 248, 721, 722, 18446744073709551615, 0, 2), - (13, 1017, 722, 723, 18446744073709551615, 0, 2), - (13, 1018, 723, 724, 18446744073709551615, 0, 2), - (13, 251, 724, 725, 18446744073709551615, 0, 2), - (13, 1020, 725, 726, 18446744073709551615, 0, 2), - (13, 1021, 726, 727, 18446744073709551615, 0, 2), - (13, 254, 727, 728, 18446744073709551615, 0, 2), - (13, 1023, 728, 729, 18446744073709551615, 0, 2), - (13, 729, 1049, 730, 18446744073709551615, 0, 1), - (13, 1023, 728, 729, 18446744073709551615, 1, 2), - (13, 254, 727, 728, 18446744073709551615, 1, 2), - (13, 1021, 726, 727, 18446744073709551615, 1, 2), - (13, 1020, 725, 726, 18446744073709551615, 1, 2), - (13, 251, 724, 725, 18446744073709551615, 1, 2), - (13, 1018, 723, 724, 18446744073709551615, 1, 2), - (13, 1017, 722, 723, 18446744073709551615, 1, 2), - (13, 248, 721, 722, 18446744073709551615, 1, 2), - (13, 1015, 720, 721, 18446744073709551615, 1, 2), - (13, 1014, 719, 720, 18446744073709551615, 1, 2), - (13, 245, 718, 719, 18446744073709551615, 1, 2), - (13, 1012, 717, 718, 18446744073709551615, 1, 2), - (13, 1011, 716, 717, 18446744073709551615, 1, 2), - (13, 242, 715, 716, 18446744073709551615, 1, 2), - (13, 1009, 714, 715, 18446744073709551615, 1, 2), - (13, 1008, 713, 714, 18446744073709551615, 1, 2), - (13, 239, 712, 713, 18446744073709551615, 1, 2), - (13, 1006, 711, 712, 18446744073709551615, 1, 2), - (13, 1005, 710, 711, 18446744073709551615, 1, 2), - (13, 236, 709, 710, 18446744073709551615, 1, 2), - (13, 1003, 708, 709, 18446744073709551615, 1, 2), - (13, 1002, 707, 708, 18446744073709551615, 1, 2), - (13, 233, 706, 707, 18446744073709551615, 1, 2), - (13, 1000, 705, 706, 18446744073709551615, 1, 2), - (13, 999, 704, 705, 18446744073709551615, 1, 2), - (13, 230, 703, 704, 18446744073709551615, 1, 2), - (13, 997, 702, 703, 18446744073709551615, 1, 2), - (13, 996, 701, 702, 18446744073709551615, 1, 2), - (13, 227, 700, 701, 18446744073709551615, 1, 2), - (13, 994, 699, 700, 18446744073709551615, 1, 2), - (13, 993, 698, 699, 18446744073709551615, 1, 2), - (13, 224, 697, 698, 18446744073709551615, 1, 2), - (13, 991, 696, 697, 18446744073709551615, 1, 2), - (13, 990, 695, 696, 18446744073709551615, 1, 2), - (13, 221, 694, 695, 18446744073709551615, 1, 2), - (13, 988, 693, 694, 18446744073709551615, 1, 2), - (13, 987, 692, 693, 18446744073709551615, 1, 2), - (13, 218, 691, 692, 18446744073709551615, 1, 2), - (13, 985, 690, 691, 18446744073709551615, 1, 2), - (13, 984, 689, 690, 18446744073709551615, 1, 2), - (13, 215, 688, 689, 18446744073709551615, 1, 2), - (13, 982, 687, 688, 18446744073709551615, 1, 2), - (13, 981, 686, 687, 18446744073709551615, 1, 2), - (13, 212, 685, 686, 18446744073709551615, 1, 2), - (13, 979, 684, 685, 18446744073709551615, 1, 2), - (13, 978, 683, 684, 18446744073709551615, 1, 2), - (13, 209, 682, 683, 18446744073709551615, 1, 2), - (13, 976, 681, 682, 18446744073709551615, 1, 2), - (13, 975, 680, 681, 18446744073709551615, 1, 2), - (13, 206, 679, 680, 18446744073709551615, 1, 2), - (13, 973, 678, 679, 18446744073709551615, 1, 2), - (13, 972, 677, 678, 18446744073709551615, 1, 2), - (13, 203, 676, 677, 18446744073709551615, 1, 2), - (13, 970, 675, 676, 18446744073709551615, 1, 2), - (13, 969, 674, 675, 18446744073709551615, 1, 2), - (13, 200, 673, 674, 18446744073709551615, 1, 2), - (13, 967, 672, 673, 18446744073709551615, 1, 2), - (13, 966, 671, 672, 18446744073709551615, 1, 2), - (13, 197, 670, 671, 18446744073709551615, 1, 2), - (13, 964, 669, 670, 18446744073709551615, 1, 2), - (13, 963, 668, 669, 18446744073709551615, 1, 2), - (13, 194, 667, 668, 18446744073709551615, 1, 2), - (13, 961, 666, 667, 18446744073709551615, 1, 2), - (13, 960, 665, 666, 18446744073709551615, 1, 2), - (13, 191, 664, 665, 18446744073709551615, 1, 2), - (13, 958, 663, 664, 18446744073709551615, 1, 2), - (13, 957, 662, 663, 18446744073709551615, 1, 2), - (13, 188, 661, 662, 18446744073709551615, 1, 2), - (13, 955, 660, 661, 18446744073709551615, 1, 2), - (13, 954, 659, 660, 18446744073709551615, 1, 2), - (13, 185, 658, 659, 18446744073709551615, 1, 2), - (13, 952, 657, 658, 18446744073709551615, 1, 2), - (13, 951, 656, 657, 18446744073709551615, 1, 2), - (13, 182, 655, 656, 18446744073709551615, 1, 2), - (13, 949, 654, 655, 18446744073709551615, 1, 2), - (13, 948, 653, 654, 18446744073709551615, 1, 2), - (13, 179, 652, 653, 18446744073709551615, 1, 2), - (13, 946, 651, 652, 18446744073709551615, 1, 2), - (13, 945, 650, 651, 18446744073709551615, 1, 2), - (13, 176, 649, 650, 18446744073709551615, 1, 2), - (13, 943, 648, 649, 18446744073709551615, 1, 2), - (13, 942, 647, 648, 18446744073709551615, 1, 2), - (13, 1082, 646, 647, 18446744073709551615, 1, 2), - (13, 156, 645, 646, 18446744073709551615, 1, 2), - (13, 168, 644, 645, 18446744073709551615, 1, 2), - (13, 170, 643, 644, 18446744073709551615, 1, 2), - (13, 937, 642, 643, 18446744073709551615, 1, 2), - (13, 936, 641, 642, 18446744073709551615, 1, 2), - (13, 167, 640, 641, 18446744073709551615, 1, 2), - (13, 162, 639, 640, 18446744073709551615, 1, 2), - (13, 164, 638, 639, 18446744073709551615, 1, 2), - (13, 161, 637, 638, 18446744073709551615, 1, 2), - (13, 165, 636, 637, 18446744073709551615, 1, 2), - (13, 933, 635, 636, 18446744073709551615, 1, 2), - (13, 935, 633, 634, 18446744073709551615, 1, 2), - (13, 158, 632, 633, 18446744073709551615, 1, 2), - (13, 160, 631, 632, 18446744073709551615, 1, 2), - (13, 730, 755, 731, 18446744073709551615, 0, 2), - (13, 754, 731, 609, 18446744073709551615, 0, 1), - (13, 753, 609, 608, 18446744073709551615, 0, 3), - (13, 752, 608, 607, 18446744073709551615, 0, 3), - (13, 751, 607, 606, 18446744073709551615, 0, 3), - (13, 750, 606, 732, 18446744073709551615, 0, 3), - (13, 749, 732, 733, 18446744073709551615, 0, 3), - (13, 748, 733, 605, 18446744073709551615, 0, 3), - (13, 747, 605, 604, 18446744073709551615, 0, 3), - (13, 14, 604, 603, 18446744073709551615, 0, 3), - (13, 11, 603, 602, 18446744073709551615, 0, 3), - (13, 777, 602, 601, 18446744073709551615, 0, 3), - (13, 13, 601, 600, 18446744073709551615, 0, 3), - (13, 1145, 600, 599, 18446744073709551615, 0, 3), - (13, 1137, 599, 598, 18446744073709551615, 0, 3), - (13, 17, 598, 597, 18446744073709551615, 0, 3), - (13, 1134, 597, 596, 18446744073709551615, 0, 3), - (13, 27, 596, 595, 18446744073709551615, 0, 3), - (13, 786, 595, 594, 18446744073709551615, 0, 3), - (13, 787, 594, 593, 18446744073709551615, 0, 3), - (13, 788, 593, 592, 18446744073709551615, 0, 3), - (13, 789, 592, 591, 18446744073709551615, 0, 3), - (13, 790, 591, 590, 18446744073709551615, 0, 3), - (13, 791, 590, 589, 18446744073709551615, 0, 3), - (13, 23, 589, 588, 18446744073709551615, 0, 3), - (13, 20, 588, 587, 18446744073709551615, 0, 3), - (13, 18, 587, 586, 18446744073709551615, 0, 3), - (13, 795, 586, 585, 18446744073709551615, 0, 3), - (13, 796, 585, 584, 18446744073709551615, 0, 3), - (13, 797, 584, 583, 18446744073709551615, 0, 3), - (13, 798, 583, 582, 18446744073709551615, 0, 3), - (13, 799, 582, 581, 18446744073709551615, 0, 3), - (13, 800, 581, 580, 18446744073709551615, 0, 3), - (13, 801, 580, 579, 18446744073709551615, 0, 3), - (13, 802, 579, 578, 18446744073709551615, 0, 3), - (13, 803, 578, 577, 18446744073709551615, 0, 3), - (13, 804, 577, 576, 18446744073709551615, 0, 3), - (13, 805, 576, 575, 18446744073709551615, 0, 3), - (13, 806, 575, 574, 18446744073709551615, 0, 3), - (13, 807, 574, 573, 18446744073709551615, 0, 3), - (13, 808, 573, 572, 18446744073709551615, 0, 3), - (13, 809, 572, 571, 18446744073709551615, 0, 3), - (13, 810, 571, 570, 18446744073709551615, 0, 3), - (13, 811, 570, 569, 18446744073709551615, 0, 3), - (13, 812, 569, 568, 18446744073709551615, 0, 3), - (13, 813, 568, 567, 18446744073709551615, 0, 3), - (13, 814, 567, 566, 18446744073709551615, 0, 3), - (13, 815, 566, 564, 18446744073709551615, 0, 3), - (13, 816, 564, 563, 18446744073709551615, 0, 6), - (13, 817, 563, 565, 18446744073709551615, 0, 3), - (13, 818, 565, 563, 18446744073709551615, 0, 3), - (13, 819, 563, 564, 18446744073709551615, 0, 3), - (14, 730, 819, 563, 18446744073709551615, 0, 1), - (14, 730, 817, 563, 18446744073709551615, 0, 1), - (13, 1006, 711, 609, 18446744073709551615, 0, 1), - (13, 239, 712, 608, 18446744073709551615, 0, 1), - (13, 1008, 713, 607, 18446744073709551615, 0, 1), - (13, 1009, 714, 606, 18446744073709551615, 0, 1), - (13, 242, 715, 732, 18446744073709551615, 0, 1), - (13, 1011, 716, 733, 18446744073709551615, 0, 1), - (13, 1012, 717, 605, 18446744073709551615, 0, 1), - (13, 245, 718, 604, 18446744073709551615, 0, 1), - (13, 1014, 719, 603, 18446744073709551615, 0, 1), - (13, 1015, 720, 602, 18446744073709551615, 0, 1), - (13, 248, 721, 601, 18446744073709551615, 0, 1), - (13, 1017, 722, 600, 18446744073709551615, 0, 1), - (13, 1018, 723, 599, 18446744073709551615, 0, 1), - (13, 251, 724, 598, 18446744073709551615, 0, 1), - (13, 1020, 725, 597, 18446744073709551615, 0, 1), - (13, 1021, 726, 596, 18446744073709551615, 0, 1), - (13, 254, 727, 595, 18446744073709551615, 0, 1), - (13, 1023, 728, 594, 18446744073709551615, 0, 1), - (13, 1049, 729, 593, 18446744073709551615, 0, 1), - (13, 929, 709, 708, 18446744073709551615, 0, 4), - (13, 933, 708, 707, 18446744073709551615, 0, 2), - (13, 165, 707, 706, 18446744073709551615, 0, 2), - (13, 164, 705, 704, 18446744073709551615, 0, 2), - (13, 162, 704, 703, 18446744073709551615, 0, 2), - (13, 167, 703, 702, 18446744073709551615, 0, 2), - (13, 936, 702, 701, 18446744073709551615, 0, 2), - (13, 937, 701, 700, 18446744073709551615, 0, 2), - (13, 170, 700, 699, 18446744073709551615, 0, 2), - (13, 168, 699, 698, 18446744073709551615, 0, 2), - (13, 156, 698, 697, 18446744073709551615, 0, 2), - (13, 1082, 697, 696, 18446744073709551615, 0, 2), - (13, 942, 696, 695, 18446744073709551615, 0, 2), - (13, 943, 695, 694, 18446744073709551615, 0, 2), - (13, 176, 694, 693, 18446744073709551615, 0, 2), - (13, 945, 693, 692, 18446744073709551615, 0, 2), - (13, 946, 692, 691, 18446744073709551615, 0, 2), - (13, 179, 691, 690, 18446744073709551615, 0, 2), - (13, 948, 690, 689, 18446744073709551615, 0, 2), - (13, 949, 689, 688, 18446744073709551615, 0, 2), - (13, 182, 688, 687, 18446744073709551615, 0, 2), - (13, 951, 687, 686, 18446744073709551615, 0, 2), - (13, 952, 686, 685, 18446744073709551615, 0, 2), - (13, 185, 685, 684, 18446744073709551615, 0, 2), - (13, 954, 684, 683, 18446744073709551615, 0, 2), - (13, 955, 683, 682, 18446744073709551615, 0, 2), - (13, 188, 682, 681, 18446744073709551615, 0, 2), - (13, 957, 681, 680, 18446744073709551615, 0, 2), - (13, 958, 680, 679, 18446744073709551615, 0, 2), - (13, 191, 679, 678, 18446744073709551615, 0, 2), - (13, 960, 678, 677, 18446744073709551615, 0, 2), - (13, 961, 677, 676, 18446744073709551615, 0, 2), - (13, 194, 676, 675, 18446744073709551615, 0, 2), - (13, 963, 675, 674, 18446744073709551615, 0, 2), - (13, 964, 674, 673, 18446744073709551615, 0, 2), - (13, 197, 673, 672, 18446744073709551615, 0, 2), - (13, 966, 672, 671, 18446744073709551615, 0, 2), - (13, 967, 671, 670, 18446744073709551615, 0, 2), - (13, 200, 670, 669, 18446744073709551615, 0, 2), - (13, 969, 669, 668, 18446744073709551615, 0, 2), - (13, 970, 668, 667, 18446744073709551615, 0, 2), - (13, 203, 667, 666, 18446744073709551615, 0, 2), - (13, 972, 666, 665, 18446744073709551615, 0, 2), - (13, 973, 665, 664, 18446744073709551615, 0, 2), - (13, 206, 664, 663, 18446744073709551615, 0, 2), - (13, 975, 663, 662, 18446744073709551615, 0, 2), - (13, 976, 662, 661, 18446744073709551615, 0, 2), - (13, 209, 661, 660, 18446744073709551615, 0, 2), - (13, 978, 660, 659, 18446744073709551615, 0, 2), - (13, 979, 659, 658, 18446744073709551615, 0, 2), - (13, 212, 658, 657, 18446744073709551615, 0, 2), - (13, 981, 657, 656, 18446744073709551615, 0, 2), - (13, 982, 656, 655, 18446744073709551615, 0, 2), - (13, 215, 655, 654, 18446744073709551615, 0, 2), - (13, 984, 654, 653, 18446744073709551615, 0, 2), - (13, 985, 653, 652, 18446744073709551615, 0, 2), - (13, 218, 652, 651, 18446744073709551615, 0, 2), - (13, 987, 651, 650, 18446744073709551615, 0, 2), - (13, 988, 650, 649, 18446744073709551615, 0, 2), - (13, 221, 649, 648, 18446744073709551615, 0, 2), - (13, 990, 648, 647, 18446744073709551615, 0, 2), - (13, 991, 647, 646, 18446744073709551615, 0, 2), - (13, 224, 646, 645, 18446744073709551615, 0, 2), - (13, 993, 645, 644, 18446744073709551615, 0, 2), - (13, 994, 644, 643, 18446744073709551615, 0, 2), - (13, 227, 643, 642, 18446744073709551615, 0, 2), - (13, 996, 642, 641, 18446744073709551615, 0, 2), - (13, 997, 641, 640, 18446744073709551615, 0, 2), - (13, 230, 640, 639, 18446744073709551615, 0, 2), - (13, 999, 639, 638, 18446744073709551615, 0, 2), - (13, 1000, 638, 637, 18446744073709551615, 0, 2), - (13, 233, 637, 636, 18446744073709551615, 0, 2), - (13, 1002, 636, 635, 18446744073709551615, 0, 2), - (13, 1003, 635, 634, 18446744073709551615, 0, 2), - (13, 236, 634, 633, 18446744073709551615, 0, 2), - (13, 1005, 633, 632, 18446744073709551615, 0, 2), - (13, 1006, 632, 631, 18446744073709551615, 0, 2), - (13, 239, 631, 630, 18446744073709551615, 0, 2), - (13, 1008, 630, 629, 18446744073709551615, 0, 2), - (13, 1009, 629, 628, 18446744073709551615, 0, 2), - (13, 242, 628, 627, 18446744073709551615, 0, 2), - (13, 1011, 627, 626, 18446744073709551615, 0, 2), - (13, 1012, 626, 625, 18446744073709551615, 0, 2), - (13, 245, 625, 624, 18446744073709551615, 0, 2), - (13, 1014, 624, 623, 18446744073709551615, 0, 2), - (13, 1015, 623, 622, 18446744073709551615, 0, 2), - (13, 248, 622, 621, 18446744073709551615, 0, 2), - (13, 1017, 621, 620, 18446744073709551615, 0, 2), - (13, 1018, 620, 619, 18446744073709551615, 0, 2), - (13, 251, 619, 618, 18446744073709551615, 0, 2), - (13, 1020, 618, 617, 18446744073709551615, 0, 2), - (13, 1021, 617, 616, 18446744073709551615, 0, 2), - (13, 254, 616, 615, 18446744073709551615, 0, 2), - (13, 1023, 615, 614, 18446744073709551615, 0, 2), - (13, 614, 1049, 613, 18446744073709551615, 0, 1), - (13, 1023, 615, 614, 18446744073709551615, 1, 2), - (13, 254, 616, 615, 18446744073709551615, 1, 2), - (13, 1021, 617, 616, 18446744073709551615, 1, 2), - (13, 1020, 618, 617, 18446744073709551615, 1, 2), - (13, 251, 619, 618, 18446744073709551615, 1, 2), - (13, 1018, 620, 619, 18446744073709551615, 1, 2), - (13, 1017, 621, 620, 18446744073709551615, 1, 2), - (13, 248, 622, 621, 18446744073709551615, 1, 2), - (13, 1015, 623, 622, 18446744073709551615, 1, 2), - (13, 1014, 624, 623, 18446744073709551615, 1, 2), - (13, 245, 625, 624, 18446744073709551615, 1, 2), - (13, 1012, 626, 625, 18446744073709551615, 1, 2), - (13, 1011, 627, 626, 18446744073709551615, 1, 2), - (13, 242, 628, 627, 18446744073709551615, 1, 2), - (13, 1009, 629, 628, 18446744073709551615, 1, 2), - (13, 1008, 630, 629, 18446744073709551615, 1, 2), - (13, 239, 631, 630, 18446744073709551615, 1, 2), - (13, 1006, 632, 631, 18446744073709551615, 1, 2), - (13, 1005, 633, 632, 18446744073709551615, 1, 2), - (13, 236, 634, 633, 18446744073709551615, 1, 2), - (13, 1003, 635, 634, 18446744073709551615, 1, 2), - (13, 1002, 636, 635, 18446744073709551615, 1, 2), - (13, 233, 637, 636, 18446744073709551615, 1, 2), - (13, 1000, 638, 637, 18446744073709551615, 1, 2), - (13, 999, 639, 638, 18446744073709551615, 1, 2), - (13, 230, 640, 639, 18446744073709551615, 1, 2), - (13, 997, 641, 640, 18446744073709551615, 1, 2), - (13, 996, 642, 641, 18446744073709551615, 1, 2), - (13, 227, 643, 642, 18446744073709551615, 1, 2), - (13, 994, 644, 643, 18446744073709551615, 1, 2), - (13, 993, 645, 644, 18446744073709551615, 1, 2), - (13, 224, 646, 645, 18446744073709551615, 1, 2), - (13, 991, 647, 646, 18446744073709551615, 1, 2), - (13, 990, 648, 647, 18446744073709551615, 1, 2), - (13, 221, 649, 648, 18446744073709551615, 1, 2), - (13, 988, 650, 649, 18446744073709551615, 1, 2), - (13, 987, 651, 650, 18446744073709551615, 1, 2), - (13, 218, 652, 651, 18446744073709551615, 1, 2), - (13, 985, 653, 652, 18446744073709551615, 1, 2), - (13, 984, 654, 653, 18446744073709551615, 1, 2), - (13, 215, 655, 654, 18446744073709551615, 1, 2), - (13, 982, 656, 655, 18446744073709551615, 1, 2), - (13, 981, 657, 656, 18446744073709551615, 1, 2), - (13, 212, 658, 657, 18446744073709551615, 1, 2), - (13, 979, 659, 658, 18446744073709551615, 1, 2), - (13, 978, 660, 659, 18446744073709551615, 1, 2), - (13, 209, 661, 660, 18446744073709551615, 1, 2), - (13, 976, 662, 661, 18446744073709551615, 1, 2), - (13, 975, 663, 662, 18446744073709551615, 1, 2), - (13, 206, 664, 663, 18446744073709551615, 1, 2), - (13, 973, 665, 664, 18446744073709551615, 1, 2), - (13, 972, 666, 665, 18446744073709551615, 1, 2), - (13, 203, 667, 666, 18446744073709551615, 1, 2), - (13, 970, 668, 667, 18446744073709551615, 1, 2), - (13, 969, 669, 668, 18446744073709551615, 1, 2), - (13, 200, 670, 669, 18446744073709551615, 1, 2), - (13, 967, 671, 670, 18446744073709551615, 1, 2), - (13, 966, 672, 671, 18446744073709551615, 1, 2), - (13, 197, 673, 672, 18446744073709551615, 1, 2), - (13, 964, 674, 673, 18446744073709551615, 1, 2), - (13, 963, 675, 674, 18446744073709551615, 1, 2), - (13, 194, 676, 675, 18446744073709551615, 1, 2), - (13, 961, 677, 676, 18446744073709551615, 1, 2), - (13, 960, 678, 677, 18446744073709551615, 1, 2), - (13, 191, 679, 678, 18446744073709551615, 1, 2), - (13, 958, 680, 679, 18446744073709551615, 1, 2), - (13, 957, 681, 680, 18446744073709551615, 1, 2), - (13, 188, 682, 681, 18446744073709551615, 1, 2), - (13, 955, 683, 682, 18446744073709551615, 1, 2), - (13, 954, 684, 683, 18446744073709551615, 1, 2), - (13, 185, 685, 684, 18446744073709551615, 1, 2), - (13, 952, 686, 685, 18446744073709551615, 1, 2), - (13, 951, 687, 686, 18446744073709551615, 1, 2), - (13, 182, 688, 687, 18446744073709551615, 1, 2), - (13, 949, 689, 688, 18446744073709551615, 1, 2), - (13, 948, 690, 689, 18446744073709551615, 1, 2), - (13, 179, 691, 690, 18446744073709551615, 1, 2), - (13, 946, 692, 691, 18446744073709551615, 1, 2), - (13, 945, 693, 692, 18446744073709551615, 1, 2), - (13, 176, 694, 693, 18446744073709551615, 1, 2), - (13, 943, 695, 694, 18446744073709551615, 1, 2), - (13, 942, 696, 695, 18446744073709551615, 1, 2), - (13, 1082, 697, 696, 18446744073709551615, 1, 2), - (13, 156, 698, 697, 18446744073709551615, 1, 2), - (13, 168, 699, 698, 18446744073709551615, 1, 2), - (13, 170, 700, 699, 18446744073709551615, 1, 2), - (13, 937, 701, 700, 18446744073709551615, 1, 2), - (13, 936, 702, 701, 18446744073709551615, 1, 2), - (13, 167, 703, 702, 18446744073709551615, 1, 2), - (13, 162, 704, 703, 18446744073709551615, 1, 2), - (13, 164, 705, 704, 18446744073709551615, 1, 2), - (13, 165, 707, 706, 18446744073709551615, 1, 2), - (13, 933, 708, 707, 18446744073709551615, 1, 2), - (13, 929, 709, 708, 18446744073709551615, 1, 4), - (13, 613, 755, 612, 18446744073709551615, 0, 1), - (13, 754, 612, 611, 18446744073709551615, 0, 1), - (13, 753, 611, 610, 18446744073709551615, 0, 1), - (13, 752, 610, 730, 18446744073709551615, 0, 1), - (13, 751, 730, 731, 18446744073709551615, 0, 1), - (13, 750, 731, 609, 18446744073709551615, 0, 1), - (13, 749, 609, 608, 18446744073709551615, 0, 3), - (13, 748, 608, 607, 18446744073709551615, 0, 3), - (13, 747, 607, 606, 18446744073709551615, 0, 3), - (13, 14, 606, 732, 18446744073709551615, 0, 3), - (13, 11, 732, 733, 18446744073709551615, 0, 3), - (13, 777, 733, 605, 18446744073709551615, 0, 3), - (13, 13, 605, 604, 18446744073709551615, 0, 3), - (13, 1145, 604, 603, 18446744073709551615, 0, 3), - (13, 1137, 603, 602, 18446744073709551615, 0, 3), - (13, 17, 602, 601, 18446744073709551615, 0, 3), - (13, 1134, 601, 600, 18446744073709551615, 0, 3), - (13, 27, 600, 599, 18446744073709551615, 0, 3), - (13, 786, 599, 598, 18446744073709551615, 0, 3), - (13, 787, 598, 597, 18446744073709551615, 0, 3), - (13, 788, 597, 596, 18446744073709551615, 0, 3), - (13, 789, 596, 595, 18446744073709551615, 0, 3), - (13, 790, 595, 594, 18446744073709551615, 0, 3), - (13, 791, 594, 593, 18446744073709551615, 0, 3), - (13, 23, 593, 592, 18446744073709551615, 0, 3), - (13, 20, 592, 591, 18446744073709551615, 0, 3), - (13, 18, 591, 590, 18446744073709551615, 0, 3), - (13, 795, 590, 589, 18446744073709551615, 0, 3), - (13, 796, 589, 588, 18446744073709551615, 0, 3), - (13, 797, 588, 587, 18446744073709551615, 0, 3), - (13, 798, 587, 586, 18446744073709551615, 0, 3), - (13, 799, 586, 585, 18446744073709551615, 0, 3), - (13, 800, 585, 584, 18446744073709551615, 0, 3), - (13, 801, 584, 583, 18446744073709551615, 0, 3), - (13, 802, 583, 582, 18446744073709551615, 0, 3), - (13, 803, 582, 581, 18446744073709551615, 0, 3), - (13, 804, 581, 580, 18446744073709551615, 0, 3), - (13, 805, 580, 579, 18446744073709551615, 0, 3), - (13, 806, 579, 578, 18446744073709551615, 0, 3), - (13, 807, 578, 577, 18446744073709551615, 0, 3), - (13, 808, 577, 576, 18446744073709551615, 0, 3), - (13, 809, 576, 575, 18446744073709551615, 0, 3), - (13, 810, 575, 574, 18446744073709551615, 0, 3), - (13, 811, 574, 573, 18446744073709551615, 0, 3), - (13, 812, 573, 572, 18446744073709551615, 0, 3), - (13, 813, 572, 571, 18446744073709551615, 0, 3), - (13, 814, 571, 570, 18446744073709551615, 0, 3), - (13, 815, 570, 568, 18446744073709551615, 0, 3), - (13, 816, 568, 567, 18446744073709551615, 0, 6), - (13, 817, 567, 569, 18446744073709551615, 0, 3), - (13, 818, 569, 567, 18446744073709551615, 0, 3), - (13, 819, 567, 568, 18446744073709551615, 0, 3), - (14, 613, 819, 567, 18446744073709551615, 0, 1), - (14, 613, 817, 567, 18446744073709551615, 0, 1), - (13, 632, 1006, 610, 18446744073709551615, 0, 1), - (13, 631, 239, 730, 18446744073709551615, 0, 1), - (13, 630, 1008, 731, 18446744073709551615, 0, 1), - (13, 629, 1009, 609, 18446744073709551615, 0, 1), - (13, 628, 242, 608, 18446744073709551615, 0, 1), - (13, 627, 1011, 607, 18446744073709551615, 0, 1), - (13, 626, 1012, 606, 18446744073709551615, 0, 1), - (13, 625, 245, 732, 18446744073709551615, 0, 1), - (13, 624, 1014, 733, 18446744073709551615, 0, 1), - (13, 623, 1015, 605, 18446744073709551615, 0, 1), - (13, 622, 248, 604, 18446744073709551615, 0, 1), - (13, 621, 1017, 603, 18446744073709551615, 0, 1), - (13, 620, 1018, 602, 18446744073709551615, 0, 1), - (13, 619, 251, 601, 18446744073709551615, 0, 1), - (13, 618, 1020, 600, 18446744073709551615, 0, 1), - (13, 617, 1021, 599, 18446744073709551615, 0, 1), - (13, 616, 254, 598, 18446744073709551615, 0, 1), - (13, 615, 1023, 597, 18446744073709551615, 0, 1), - (13, 614, 1049, 596, 18446744073709551615, 0, 1), - (13, 951, 634, 1151, 18446744073709551615, 0, 1), - (13, 952, 635, 1132, 18446744073709551615, 0, 1), - (13, 955, 638, 10, 18446744073709551615, 0, 1), - (13, 188, 639, 793, 18446744073709551615, 0, 1), - (13, 958, 641, 1147, 18446744073709551615, 0, 1), - (13, 191, 642, 1153, 18446744073709551615, 0, 1), - (13, 960, 643, 644, 18446744073709551615, 0, 4), - (13, 961, 644, 645, 18446744073709551615, 0, 4), - (13, 194, 645, 646, 18446744073709551615, 0, 4), - (13, 963, 646, 647, 18446744073709551615, 0, 4), - (13, 964, 647, 648, 18446744073709551615, 0, 4), - (13, 197, 648, 649, 18446744073709551615, 0, 4), - (13, 966, 649, 650, 18446744073709551615, 0, 4), - (13, 967, 650, 651, 18446744073709551615, 0, 4), - (13, 200, 651, 652, 18446744073709551615, 0, 4), - (13, 969, 652, 653, 18446744073709551615, 0, 4), - (13, 970, 653, 654, 18446744073709551615, 0, 4), - (13, 203, 654, 655, 18446744073709551615, 0, 4), - (13, 972, 655, 656, 18446744073709551615, 0, 4), - (13, 973, 656, 657, 18446744073709551615, 0, 4), - (13, 206, 657, 658, 18446744073709551615, 0, 4), - (13, 975, 658, 659, 18446744073709551615, 0, 4), - (13, 976, 659, 660, 18446744073709551615, 0, 4), - (13, 209, 660, 661, 18446744073709551615, 0, 4), - (13, 978, 661, 662, 18446744073709551615, 0, 4), - (13, 979, 662, 663, 18446744073709551615, 0, 4), - (13, 212, 663, 664, 18446744073709551615, 0, 4), - (13, 981, 664, 665, 18446744073709551615, 0, 4), - (13, 982, 665, 666, 18446744073709551615, 0, 4), - (13, 215, 666, 667, 18446744073709551615, 0, 4), - (13, 984, 667, 668, 18446744073709551615, 0, 4), - (13, 985, 668, 669, 18446744073709551615, 0, 4), - (13, 218, 669, 670, 18446744073709551615, 0, 4), - (13, 987, 670, 671, 18446744073709551615, 0, 4), - (13, 988, 671, 672, 18446744073709551615, 0, 4), - (13, 221, 672, 673, 18446744073709551615, 0, 4), - (13, 990, 673, 674, 18446744073709551615, 0, 4), - (13, 991, 674, 675, 18446744073709551615, 0, 4), - (13, 224, 675, 676, 18446744073709551615, 0, 4), - (13, 993, 676, 677, 18446744073709551615, 0, 4), - (13, 994, 677, 678, 18446744073709551615, 0, 4), - (13, 227, 678, 679, 18446744073709551615, 0, 4), - (13, 996, 679, 680, 18446744073709551615, 0, 4), - (13, 997, 680, 681, 18446744073709551615, 0, 4), - (13, 230, 681, 682, 18446744073709551615, 0, 4), - (13, 999, 682, 683, 18446744073709551615, 0, 4), - (13, 1000, 683, 684, 18446744073709551615, 0, 4), - (13, 233, 684, 685, 18446744073709551615, 0, 4), - (13, 1002, 685, 686, 18446744073709551615, 0, 4), - (13, 1003, 686, 687, 18446744073709551615, 0, 4), - (13, 236, 687, 688, 18446744073709551615, 0, 4), - (13, 1005, 688, 689, 18446744073709551615, 0, 4), - (13, 1006, 689, 690, 18446744073709551615, 0, 4), - (13, 239, 690, 691, 18446744073709551615, 0, 4), - (13, 1008, 691, 692, 18446744073709551615, 0, 4), - (13, 1009, 692, 693, 18446744073709551615, 0, 4), - (13, 242, 693, 694, 18446744073709551615, 0, 4), - (13, 1011, 694, 695, 18446744073709551615, 0, 4), - (13, 1012, 695, 696, 18446744073709551615, 0, 4), - (13, 245, 696, 697, 18446744073709551615, 0, 4), - (13, 1014, 697, 698, 18446744073709551615, 0, 4), - (13, 1015, 698, 699, 18446744073709551615, 0, 4), - (13, 248, 699, 700, 18446744073709551615, 0, 4), - (13, 1017, 700, 701, 18446744073709551615, 0, 4), - (13, 1018, 701, 702, 18446744073709551615, 0, 4), - (13, 251, 702, 703, 18446744073709551615, 0, 4), - (13, 1020, 703, 704, 18446744073709551615, 0, 4), - (13, 1021, 704, 705, 18446744073709551615, 0, 4), - (13, 254, 705, 706, 18446744073709551615, 0, 4), - (13, 1023, 706, 707, 18446744073709551615, 0, 4), - (13, 707, 1049, 708, 18446744073709551615, 0, 1), - (13, 1023, 706, 707, 18446744073709551615, 1, 4), - (13, 254, 705, 706, 18446744073709551615, 1, 4), - (13, 1021, 704, 705, 18446744073709551615, 1, 4), - (13, 1020, 703, 704, 18446744073709551615, 1, 4), - (13, 251, 702, 703, 18446744073709551615, 1, 4), - (13, 1018, 701, 702, 18446744073709551615, 1, 4), - (13, 1017, 700, 701, 18446744073709551615, 1, 4), - (13, 248, 699, 700, 18446744073709551615, 1, 4), - (13, 1015, 698, 699, 18446744073709551615, 1, 4), - (13, 1014, 697, 698, 18446744073709551615, 1, 4), - (13, 245, 696, 697, 18446744073709551615, 1, 4), - (13, 1012, 695, 696, 18446744073709551615, 1, 4), - (13, 1011, 694, 695, 18446744073709551615, 1, 4), - (13, 242, 693, 694, 18446744073709551615, 1, 4), - (13, 1009, 692, 693, 18446744073709551615, 1, 4), - (13, 1008, 691, 692, 18446744073709551615, 1, 4), - (13, 239, 690, 691, 18446744073709551615, 1, 4), - (13, 1006, 689, 690, 18446744073709551615, 1, 4), - (13, 1005, 688, 689, 18446744073709551615, 1, 4), - (13, 236, 687, 688, 18446744073709551615, 1, 4), - (13, 1003, 686, 687, 18446744073709551615, 1, 4), - (13, 1002, 685, 686, 18446744073709551615, 1, 4), - (13, 233, 684, 685, 18446744073709551615, 1, 4), - (13, 1000, 683, 684, 18446744073709551615, 1, 4), - (13, 999, 682, 683, 18446744073709551615, 1, 4), - (13, 230, 681, 682, 18446744073709551615, 1, 4), - (13, 997, 680, 681, 18446744073709551615, 1, 4), - (13, 996, 679, 680, 18446744073709551615, 1, 4), - (13, 227, 678, 679, 18446744073709551615, 1, 4), - (13, 994, 677, 678, 18446744073709551615, 1, 4), - (13, 993, 676, 677, 18446744073709551615, 1, 4), - (13, 224, 675, 676, 18446744073709551615, 1, 4), - (13, 991, 674, 675, 18446744073709551615, 1, 4), - (13, 990, 673, 674, 18446744073709551615, 1, 4), - (13, 221, 672, 673, 18446744073709551615, 1, 4), - (13, 988, 671, 672, 18446744073709551615, 1, 4), - (13, 987, 670, 671, 18446744073709551615, 1, 4), - (13, 218, 669, 670, 18446744073709551615, 1, 4), - (13, 985, 668, 669, 18446744073709551615, 1, 4), - (13, 984, 667, 668, 18446744073709551615, 1, 4), - (13, 215, 666, 667, 18446744073709551615, 1, 4), - (13, 982, 665, 666, 18446744073709551615, 1, 4), - (13, 981, 664, 665, 18446744073709551615, 1, 4), - (13, 212, 663, 664, 18446744073709551615, 1, 4), - (13, 979, 662, 663, 18446744073709551615, 1, 4), - (13, 978, 661, 662, 18446744073709551615, 1, 4), - (13, 209, 660, 661, 18446744073709551615, 1, 4), - (13, 976, 659, 660, 18446744073709551615, 1, 4), - (13, 975, 658, 659, 18446744073709551615, 1, 4), - (13, 206, 657, 658, 18446744073709551615, 1, 4), - (13, 973, 656, 657, 18446744073709551615, 1, 4), - (13, 972, 655, 656, 18446744073709551615, 1, 4), - (13, 203, 654, 655, 18446744073709551615, 1, 4), - (13, 970, 653, 654, 18446744073709551615, 1, 4), - (13, 969, 652, 653, 18446744073709551615, 1, 4), - (13, 200, 651, 652, 18446744073709551615, 1, 4), - (13, 967, 650, 651, 18446744073709551615, 1, 4), - (13, 966, 649, 650, 18446744073709551615, 1, 4), - (13, 197, 648, 649, 18446744073709551615, 1, 4), - (13, 964, 647, 648, 18446744073709551615, 1, 4), - (13, 963, 646, 647, 18446744073709551615, 1, 4), - (13, 194, 645, 646, 18446744073709551615, 1, 4), - (13, 961, 644, 645, 18446744073709551615, 1, 4), - (13, 960, 643, 644, 18446744073709551615, 1, 4), - (13, 708, 755, 709, 18446744073709551615, 0, 1), - (13, 754, 709, 710, 18446744073709551615, 0, 1), - (13, 753, 710, 711, 18446744073709551615, 0, 1), - (13, 752, 711, 712, 18446744073709551615, 0, 1), - (13, 751, 712, 713, 18446744073709551615, 0, 1), - (13, 750, 713, 714, 18446744073709551615, 0, 1), - (13, 749, 714, 715, 18446744073709551615, 0, 1), - (13, 748, 715, 716, 18446744073709551615, 0, 1), - (13, 747, 716, 717, 18446744073709551615, 0, 1), - (13, 14, 717, 718, 18446744073709551615, 0, 1), - (13, 11, 718, 719, 18446744073709551615, 0, 1), - (13, 777, 719, 720, 18446744073709551615, 0, 1), - (13, 13, 720, 721, 18446744073709551615, 0, 1), - (13, 1145, 721, 722, 18446744073709551615, 0, 1), - (13, 1137, 722, 723, 18446744073709551615, 0, 1), - (13, 17, 723, 724, 18446744073709551615, 0, 1), - (13, 1134, 724, 725, 18446744073709551615, 0, 1), - (13, 27, 725, 726, 18446744073709551615, 0, 1), - (13, 786, 726, 727, 18446744073709551615, 0, 1), - (13, 787, 727, 728, 18446744073709551615, 0, 1), - (13, 788, 728, 729, 18446744073709551615, 0, 1), - (13, 789, 729, 613, 18446744073709551615, 0, 1), - (13, 790, 613, 612, 18446744073709551615, 0, 1), - (13, 791, 612, 611, 18446744073709551615, 0, 1), - (13, 23, 611, 610, 18446744073709551615, 0, 1), - (13, 20, 610, 730, 18446744073709551615, 0, 1), - (13, 18, 730, 731, 18446744073709551615, 0, 1), - (13, 795, 731, 609, 18446744073709551615, 0, 1), - (13, 796, 609, 608, 18446744073709551615, 0, 3), - (13, 797, 608, 607, 18446744073709551615, 0, 3), - (13, 798, 607, 606, 18446744073709551615, 0, 3), - (13, 799, 606, 732, 18446744073709551615, 0, 3), - (13, 800, 732, 733, 18446744073709551615, 0, 3), - (13, 801, 733, 605, 18446744073709551615, 0, 3), - (13, 802, 605, 604, 18446744073709551615, 0, 3), - (13, 803, 604, 603, 18446744073709551615, 0, 3), - (13, 804, 603, 602, 18446744073709551615, 0, 3), - (13, 805, 602, 601, 18446744073709551615, 0, 3), - (13, 806, 601, 600, 18446744073709551615, 0, 3), - (13, 807, 600, 599, 18446744073709551615, 0, 3), - (13, 808, 599, 598, 18446744073709551615, 0, 3), - (13, 809, 598, 597, 18446744073709551615, 0, 3), - (13, 810, 597, 596, 18446744073709551615, 0, 3), - (13, 811, 596, 595, 18446744073709551615, 0, 3), - (13, 812, 595, 594, 18446744073709551615, 0, 3), - (13, 813, 594, 593, 18446744073709551615, 0, 3), - (13, 814, 593, 592, 18446744073709551615, 0, 3), - (13, 815, 592, 590, 18446744073709551615, 0, 3), - (13, 816, 590, 589, 18446744073709551615, 0, 6), - (13, 817, 589, 591, 18446744073709551615, 0, 3), - (13, 818, 591, 589, 18446744073709551615, 0, 3), - (13, 819, 589, 590, 18446744073709551615, 0, 3), - (14, 708, 819, 589, 18446744073709551615, 0, 1), - (14, 708, 817, 589, 18446744073709551615, 0, 1), - (13, 689, 1006, 711, 18446744073709551615, 0, 1), - (13, 690, 239, 712, 18446744073709551615, 0, 1), - (13, 691, 1008, 713, 18446744073709551615, 0, 1), - (13, 692, 1009, 714, 18446744073709551615, 0, 1), - (13, 693, 242, 715, 18446744073709551615, 0, 1), - (13, 694, 1011, 716, 18446744073709551615, 0, 1), - (13, 695, 1012, 717, 18446744073709551615, 0, 1), - (13, 696, 245, 718, 18446744073709551615, 0, 1), - (13, 697, 1014, 719, 18446744073709551615, 0, 1), - (13, 698, 1015, 720, 18446744073709551615, 0, 1), - (13, 699, 248, 721, 18446744073709551615, 0, 1), - (13, 700, 1017, 722, 18446744073709551615, 0, 1), - (13, 701, 1018, 723, 18446744073709551615, 0, 1), - (13, 702, 251, 724, 18446744073709551615, 0, 1), - (13, 703, 1020, 725, 18446744073709551615, 0, 1), - (13, 704, 1021, 726, 18446744073709551615, 0, 1), - (13, 705, 254, 727, 18446744073709551615, 0, 1), - (13, 706, 1023, 728, 18446744073709551615, 0, 1), - (13, 707, 1049, 729, 18446744073709551615, 0, 1), - (13, 604, 128, 762, 18446744073709551615, 0, 2), - (13, 686, 1042, 685, 18446744073709551615, 0, 1), - (13, 685, 1052, 684, 18446744073709551615, 0, 1), - (13, 684, 1051, 683, 18446744073709551615, 0, 1), - (13, 682, 255, 681, 18446744073709551615, 0, 1), - (13, 681, 1047, 680, 18446744073709551615, 0, 1), - (13, 680, 252, 679, 18446744073709551615, 0, 1), - (13, 679, 172, 678, 18446744073709551615, 0, 1), - (13, 678, 249, 677, 18446744073709551615, 0, 1), - (13, 677, 246, 676, 18446744073709551615, 0, 1), - (13, 676, 243, 675, 18446744073709551615, 0, 1), - (13, 675, 240, 674, 18446744073709551615, 0, 1), - (13, 674, 237, 673, 18446744073709551615, 0, 1), - (13, 673, 234, 672, 18446744073709551615, 0, 1), - (13, 672, 231, 671, 18446744073709551615, 0, 1), - (13, 671, 228, 670, 18446744073709551615, 0, 1), - (13, 670, 225, 669, 18446744073709551615, 0, 1), - (13, 669, 222, 668, 18446744073709551615, 0, 1), - (13, 668, 219, 667, 18446744073709551615, 0, 1), - (13, 667, 216, 666, 18446744073709551615, 0, 1), - (13, 666, 213, 665, 18446744073709551615, 0, 1), - (13, 665, 210, 664, 18446744073709551615, 0, 1), - (13, 664, 207, 663, 18446744073709551615, 0, 1), - (13, 663, 204, 662, 18446744073709551615, 0, 1), - (13, 662, 201, 661, 18446744073709551615, 0, 1), - (13, 661, 198, 660, 18446744073709551615, 0, 1), - (13, 660, 195, 659, 18446744073709551615, 0, 1), - (13, 659, 192, 658, 18446744073709551615, 0, 1), - (13, 658, 189, 657, 18446744073709551615, 0, 1), - (13, 657, 186, 656, 18446744073709551615, 0, 1), - (13, 656, 183, 655, 18446744073709551615, 0, 1), - (13, 655, 180, 654, 18446744073709551615, 0, 1), - (13, 654, 177, 653, 18446744073709551615, 0, 1), - (13, 653, 174, 652, 18446744073709551615, 0, 1), - (13, 652, 1083, 651, 18446744073709551615, 0, 1), - (13, 651, 173, 650, 18446744073709551615, 0, 1), - (13, 650, 159, 649, 18446744073709551615, 0, 1), - (13, 649, 912, 648, 18446744073709551615, 0, 1), - (13, 648, 152, 647, 18446744073709551615, 0, 1), - (13, 647, 149, 646, 18446744073709551615, 0, 1), - (13, 646, 141, 645, 18446744073709551615, 0, 1), - (13, 645, 1091, 644, 18446744073709551615, 0, 1), - (13, 644, 1096, 643, 18446744073709551615, 0, 1), - (13, 643, 137, 642, 18446744073709551615, 0, 1), - (13, 642, 134, 641, 18446744073709551615, 0, 1), - (13, 641, 131, 640, 18446744073709551615, 0, 1), - (13, 640, 124, 639, 18446744073709551615, 0, 1), - (13, 639, 122, 638, 18446744073709551615, 0, 1), - (13, 638, 112, 637, 18446744073709551615, 0, 1), - (13, 637, 120, 636, 18446744073709551615, 0, 1), - (13, 636, 109, 635, 18446744073709551615, 0, 1), - (13, 635, 106, 634, 18446744073709551615, 0, 1), - (13, 634, 103, 633, 18446744073709551615, 0, 1), - (13, 633, 100, 632, 18446744073709551615, 0, 1), - (13, 632, 97, 631, 18446744073709551615, 0, 1), - (13, 631, 94, 630, 18446744073709551615, 0, 1), - (13, 630, 91, 629, 18446744073709551615, 0, 1), - (13, 629, 88, 628, 18446744073709551615, 0, 1), - (13, 628, 85, 627, 18446744073709551615, 0, 1), - (13, 627, 82, 626, 18446744073709551615, 0, 1), - (13, 626, 79, 625, 18446744073709551615, 0, 1), - (13, 625, 76, 624, 18446744073709551615, 0, 1), - (13, 624, 73, 623, 18446744073709551615, 0, 1), - (13, 623, 70, 622, 18446744073709551615, 0, 1), - (13, 622, 67, 621, 18446744073709551615, 0, 1), - (13, 621, 64, 620, 18446744073709551615, 0, 1), - (13, 620, 61, 619, 18446744073709551615, 0, 1), - (13, 619, 58, 618, 18446744073709551615, 0, 1), - (13, 618, 55, 617, 18446744073709551615, 0, 1), - (13, 617, 52, 616, 18446744073709551615, 0, 1), - (13, 616, 49, 615, 18446744073709551615, 0, 1), - (13, 615, 46, 614, 18446744073709551615, 0, 1), - (13, 614, 43, 708, 18446744073709551615, 0, 1), - (13, 708, 40, 709, 18446744073709551615, 0, 1), - (13, 709, 37, 710, 18446744073709551615, 0, 1), - (13, 710, 34, 711, 18446744073709551615, 0, 1), - (13, 711, 31, 712, 18446744073709551615, 0, 1), - (13, 712, 28, 713, 18446744073709551615, 0, 1), - (13, 713, 19, 714, 18446744073709551615, 0, 1), - (13, 714, 1133, 715, 18446744073709551615, 0, 1), - (13, 715, 784, 716, 18446744073709551615, 0, 1), - (13, 716, 782, 717, 18446744073709551615, 0, 1), - (13, 717, 1138, 718, 18446744073709551615, 0, 1), - (13, 718, 1114, 719, 18446744073709551615, 0, 1), - (13, 719, 1135, 720, 18446744073709551615, 0, 1), - (13, 720, 783, 721, 18446744073709551615, 0, 1), - (13, 721, 1136, 722, 18446744073709551615, 0, 1), - (13, 722, 836, 723, 18446744073709551615, 0, 1), - (13, 723, 15, 724, 18446744073709551615, 0, 1), - (13, 724, 1146, 725, 18446744073709551615, 0, 1), - (13, 725, 746, 726, 18446744073709551615, 0, 1), - (13, 726, 1152, 727, 18446744073709551615, 0, 1), - (13, 727, 781, 728, 18446744073709551615, 0, 1), - (13, 728, 1143, 729, 18446744073709551615, 0, 1), - (13, 729, 1144, 613, 18446744073709551615, 0, 1), - (13, 613, 745, 612, 18446744073709551615, 0, 1), - (13, 612, 744, 611, 18446744073709551615, 0, 1), - (13, 611, 743, 610, 18446744073709551615, 0, 1), - (13, 610, 742, 730, 18446744073709551615, 0, 1), - (13, 730, 741, 731, 18446744073709551615, 0, 1), - (13, 731, 740, 609, 18446744073709551615, 0, 1), - (13, 609, 739, 608, 18446744073709551615, 0, 1), - (13, 608, 738, 607, 18446744073709551615, 0, 1), - (13, 607, 737, 606, 18446744073709551615, 0, 1), - (13, 606, 736, 732, 18446744073709551615, 0, 1), - (13, 732, 735, 733, 18446744073709551615, 0, 1), - (13, 604, 128, 762, 18446744073709551615, 1, 2), - (13, 898, 735, 707, 18446744073709551615, 0, 1), - (13, 898, 1133, 734, 18446744073709551615, 1, 2), - (13, 898, 19, 734, 18446744073709551615, 1, 2), - (13, 898, 28, 734, 18446744073709551615, 1, 2), - (13, 898, 31, 734, 18446744073709551615, 1, 2), - (13, 898, 34, 734, 18446744073709551615, 1, 2), - (13, 898, 37, 734, 18446744073709551615, 1, 2), - (13, 898, 40, 734, 18446744073709551615, 1, 2), - (13, 898, 43, 734, 18446744073709551615, 1, 2), - (13, 898, 46, 734, 18446744073709551615, 1, 2), - (13, 898, 49, 734, 18446744073709551615, 1, 2), - (13, 898, 52, 734, 18446744073709551615, 1, 2), - (13, 898, 55, 734, 18446744073709551615, 1, 2), - (13, 898, 58, 734, 18446744073709551615, 1, 2), - (13, 898, 61, 734, 18446744073709551615, 1, 2), - (13, 898, 64, 734, 18446744073709551615, 1, 2), - (13, 898, 67, 734, 18446744073709551615, 1, 2), - (13, 898, 70, 734, 18446744073709551615, 1, 2), - (13, 898, 73, 734, 18446744073709551615, 1, 2), - (13, 898, 76, 734, 18446744073709551615, 1, 2), - (13, 898, 79, 734, 18446744073709551615, 1, 2), - (13, 898, 82, 734, 18446744073709551615, 1, 2), - (13, 898, 85, 734, 18446744073709551615, 1, 2), - (13, 898, 88, 734, 18446744073709551615, 1, 2), - (13, 898, 91, 734, 18446744073709551615, 1, 2), - (13, 898, 94, 734, 18446744073709551615, 1, 2), - (13, 898, 97, 734, 18446744073709551615, 1, 2), - (13, 898, 100, 734, 18446744073709551615, 1, 2), - (13, 898, 103, 734, 18446744073709551615, 1, 2), - (13, 898, 106, 734, 18446744073709551615, 1, 2), - (13, 898, 109, 734, 18446744073709551615, 1, 2), - (13, 898, 120, 734, 18446744073709551615, 1, 2), - (13, 898, 112, 734, 18446744073709551615, 1, 2), - (13, 898, 122, 734, 18446744073709551615, 1, 2), - (13, 898, 124, 734, 18446744073709551615, 1, 2), - (13, 898, 131, 734, 18446744073709551615, 1, 2), - (13, 898, 134, 734, 18446744073709551615, 1, 2), - (13, 898, 137, 734, 18446744073709551615, 1, 2), - (13, 898, 1096, 734, 18446744073709551615, 1, 2), - (13, 898, 1091, 734, 18446744073709551615, 1, 2), - (13, 898, 141, 734, 18446744073709551615, 1, 2), - (13, 898, 149, 734, 18446744073709551615, 1, 2), - (13, 898, 152, 734, 18446744073709551615, 1, 2), - (13, 898, 912, 734, 18446744073709551615, 1, 2), - (13, 898, 159, 734, 18446744073709551615, 1, 2), - (13, 898, 173, 734, 18446744073709551615, 1, 2), - (13, 898, 1083, 734, 18446744073709551615, 1, 2), - (13, 898, 174, 734, 18446744073709551615, 1, 2), - (13, 898, 177, 734, 18446744073709551615, 1, 2), - (13, 898, 180, 734, 18446744073709551615, 1, 2), - (13, 898, 183, 734, 18446744073709551615, 1, 2), - (13, 898, 186, 734, 18446744073709551615, 1, 2), - (13, 898, 189, 734, 18446744073709551615, 1, 2), - (13, 898, 192, 734, 18446744073709551615, 1, 2), - (13, 898, 195, 734, 18446744073709551615, 1, 2), - (13, 898, 198, 734, 18446744073709551615, 1, 2), - (13, 898, 201, 734, 18446744073709551615, 1, 2), - (13, 898, 204, 734, 18446744073709551615, 1, 2), - (13, 898, 207, 734, 18446744073709551615, 1, 2), - (13, 898, 210, 734, 18446744073709551615, 1, 2), - (13, 898, 213, 734, 18446744073709551615, 1, 2), - (13, 898, 216, 734, 18446744073709551615, 1, 2), - (13, 898, 219, 734, 18446744073709551615, 1, 2), - (13, 898, 222, 734, 18446744073709551615, 1, 2), - (13, 898, 225, 734, 18446744073709551615, 1, 2), - (13, 898, 228, 734, 18446744073709551615, 1, 2), - (13, 898, 231, 734, 18446744073709551615, 1, 2), - (13, 898, 234, 734, 18446744073709551615, 1, 2), - (13, 898, 237, 734, 18446744073709551615, 1, 2), - (13, 898, 240, 734, 18446744073709551615, 1, 2), - (13, 898, 243, 734, 18446744073709551615, 1, 2), - (13, 898, 246, 734, 18446744073709551615, 1, 2), - (13, 898, 249, 734, 18446744073709551615, 1, 2), - (13, 898, 172, 734, 18446744073709551615, 1, 2), - (13, 898, 252, 734, 18446744073709551615, 1, 2), - (13, 898, 1047, 734, 18446744073709551615, 1, 2), - (13, 898, 255, 734, 18446744073709551615, 1, 2), - (13, 898, 1053, 734, 18446744073709551615, 1, 2), - (13, 382, 1007, 904, 18446744073709551615, 0, 2), - (13, 382, 1061, 904, 18446744073709551615, 0, 2), - (13, 382, 232, 904, 18446744073709551615, 0, 2), - (13, 382, 1004, 904, 18446744073709551615, 0, 2), - (13, 382, 1062, 904, 18446744073709551615, 0, 2), - (13, 382, 229, 904, 18446744073709551615, 0, 2), - (13, 382, 1001, 904, 18446744073709551615, 0, 2), - (13, 382, 1063, 904, 18446744073709551615, 0, 2), - (13, 382, 226, 904, 18446744073709551615, 0, 2), - (13, 382, 998, 904, 18446744073709551615, 0, 2), - (13, 382, 1064, 904, 18446744073709551615, 0, 2), - (13, 382, 223, 904, 18446744073709551615, 0, 2), - (13, 382, 995, 904, 18446744073709551615, 0, 2), - (13, 382, 1065, 904, 18446744073709551615, 0, 2), - (13, 382, 220, 904, 18446744073709551615, 0, 2), - (13, 382, 992, 904, 18446744073709551615, 0, 2), - (13, 382, 1066, 904, 18446744073709551615, 0, 2), - (13, 382, 217, 904, 18446744073709551615, 0, 2), - (13, 382, 989, 904, 18446744073709551615, 0, 2), - (13, 382, 1067, 904, 18446744073709551615, 0, 2), - (13, 382, 214, 904, 18446744073709551615, 0, 2), - (13, 382, 986, 904, 18446744073709551615, 0, 2), - (13, 382, 1068, 904, 18446744073709551615, 0, 2), - (13, 382, 211, 904, 18446744073709551615, 0, 2), - (13, 382, 983, 904, 18446744073709551615, 0, 2), - (13, 382, 1069, 904, 18446744073709551615, 0, 2), - (13, 382, 208, 904, 18446744073709551615, 0, 2), - (13, 382, 980, 904, 18446744073709551615, 0, 2), - (13, 382, 1070, 904, 18446744073709551615, 0, 2), - (13, 382, 205, 904, 18446744073709551615, 0, 2), - (13, 382, 977, 904, 18446744073709551615, 0, 2), - (13, 382, 1071, 904, 18446744073709551615, 0, 2), - (13, 382, 202, 904, 18446744073709551615, 0, 2), - (13, 382, 974, 904, 18446744073709551615, 0, 2), - (13, 382, 1072, 904, 18446744073709551615, 0, 2), - (13, 382, 199, 904, 18446744073709551615, 0, 2), - (13, 382, 971, 904, 18446744073709551615, 0, 2), - (13, 382, 1073, 904, 18446744073709551615, 0, 2), - (13, 382, 196, 904, 18446744073709551615, 0, 2), - (13, 382, 968, 904, 18446744073709551615, 0, 2), - (13, 382, 1074, 904, 18446744073709551615, 0, 2), - (13, 382, 193, 904, 18446744073709551615, 0, 2), - (13, 382, 965, 904, 18446744073709551615, 0, 2), - (13, 382, 1075, 904, 18446744073709551615, 0, 2), - (13, 382, 190, 904, 18446744073709551615, 0, 2), - (13, 382, 962, 904, 18446744073709551615, 0, 2), - (13, 382, 1076, 904, 18446744073709551615, 0, 2), - (13, 382, 187, 904, 18446744073709551615, 0, 2), - (13, 382, 959, 904, 18446744073709551615, 0, 2), - (13, 382, 1077, 904, 18446744073709551615, 0, 2), - (13, 382, 184, 904, 18446744073709551615, 0, 2), - (13, 382, 956, 904, 18446744073709551615, 0, 2), - (13, 382, 1078, 904, 18446744073709551615, 0, 2), - (13, 382, 181, 904, 18446744073709551615, 0, 2), - (13, 382, 953, 904, 18446744073709551615, 0, 2), - (13, 382, 1079, 904, 18446744073709551615, 0, 2), - (13, 382, 178, 904, 18446744073709551615, 0, 2), - (13, 382, 950, 904, 18446744073709551615, 0, 2), - (13, 382, 1080, 904, 18446744073709551615, 0, 2), - (13, 382, 175, 904, 18446744073709551615, 0, 2), - (13, 382, 947, 904, 18446744073709551615, 0, 2), - (13, 382, 1081, 904, 18446744073709551615, 0, 2), - (13, 382, 941, 904, 18446744073709551615, 0, 2), - (13, 382, 944, 904, 18446744073709551615, 0, 2), - (13, 382, 169, 904, 18446744073709551615, 0, 2), - (13, 382, 938, 904, 18446744073709551615, 0, 2), - (13, 382, 939, 904, 18446744073709551615, 0, 2), - (13, 382, 1084, 904, 18446744073709551615, 0, 2), - (13, 382, 166, 904, 18446744073709551615, 0, 2), - (13, 382, 171, 904, 18446744073709551615, 0, 2), - (13, 382, 940, 904, 18446744073709551615, 0, 2), - (13, 382, 932, 904, 18446744073709551615, 0, 2), - (13, 382, 163, 904, 18446744073709551615, 0, 2), - (13, 382, 930, 904, 18446744073709551615, 0, 2), - (13, 382, 931, 904, 18446744073709551615, 0, 2), - (13, 382, 934, 904, 18446744073709551615, 0, 2), - (13, 382, 1085, 904, 18446744073709551615, 0, 2), - (13, 382, 926, 904, 18446744073709551615, 0, 2), - (13, 382, 132, 606, 18446744073709551615, 0, 1), - (13, 720, 238, 719, 18446744073709551615, 0, 1), - (13, 717, 235, 716, 18446744073709551615, 0, 1), - (13, 716, 1007, 715, 18446744073709551615, 0, 1), - (13, 712, 1062, 711, 18446744073709551615, 0, 1), - (13, 710, 1001, 709, 18446744073709551615, 0, 1), - (13, 709, 1063, 708, 18446744073709551615, 0, 1), - (13, 708, 226, 614, 18446744073709551615, 0, 1), - (13, 614, 998, 615, 18446744073709551615, 0, 1), - (13, 615, 1064, 616, 18446744073709551615, 0, 1), - (13, 616, 223, 617, 18446744073709551615, 0, 1), - (13, 617, 995, 618, 18446744073709551615, 0, 1), - (13, 618, 1065, 619, 18446744073709551615, 0, 1), - (13, 619, 220, 620, 18446744073709551615, 0, 1), - (13, 620, 992, 621, 18446744073709551615, 0, 1), - (13, 621, 1066, 622, 18446744073709551615, 0, 1), - (13, 622, 217, 623, 18446744073709551615, 0, 1), - (13, 623, 989, 624, 18446744073709551615, 0, 1), - (13, 624, 1067, 625, 18446744073709551615, 0, 1), - (13, 625, 214, 626, 18446744073709551615, 0, 1), - (13, 626, 986, 627, 18446744073709551615, 0, 1), - (13, 627, 1068, 628, 18446744073709551615, 0, 1), - (13, 628, 211, 629, 18446744073709551615, 0, 1), - (13, 629, 983, 630, 18446744073709551615, 0, 1), - (13, 630, 1069, 631, 18446744073709551615, 0, 1), - (13, 631, 208, 632, 18446744073709551615, 0, 1), - (13, 632, 980, 633, 18446744073709551615, 0, 1), - (13, 633, 1070, 634, 18446744073709551615, 0, 1), - (13, 634, 205, 635, 18446744073709551615, 0, 1), - (13, 635, 977, 636, 18446744073709551615, 0, 1), - (13, 636, 1071, 637, 18446744073709551615, 0, 1), - (13, 637, 202, 638, 18446744073709551615, 0, 1), - (13, 638, 974, 639, 18446744073709551615, 0, 1), - (13, 639, 1072, 640, 18446744073709551615, 0, 1), - (13, 640, 199, 641, 18446744073709551615, 0, 1), - (13, 641, 971, 642, 18446744073709551615, 0, 1), - (13, 642, 1073, 643, 18446744073709551615, 0, 1), - (13, 643, 196, 644, 18446744073709551615, 0, 1), - (13, 644, 968, 645, 18446744073709551615, 0, 1), - (13, 645, 1074, 646, 18446744073709551615, 0, 1), - (13, 646, 193, 647, 18446744073709551615, 0, 1), - (13, 647, 965, 648, 18446744073709551615, 0, 1), - (13, 648, 1075, 649, 18446744073709551615, 0, 1), - (13, 649, 190, 650, 18446744073709551615, 0, 1), - (13, 650, 962, 651, 18446744073709551615, 0, 1), - (13, 651, 1076, 652, 18446744073709551615, 0, 1), - (13, 652, 187, 653, 18446744073709551615, 0, 1), - (13, 653, 959, 654, 18446744073709551615, 0, 1), - (13, 654, 1077, 655, 18446744073709551615, 0, 1), - (13, 655, 184, 656, 18446744073709551615, 0, 1), - (13, 656, 956, 657, 18446744073709551615, 0, 1), - (13, 657, 1078, 658, 18446744073709551615, 0, 1), - (13, 658, 181, 659, 18446744073709551615, 0, 1), - (13, 659, 953, 660, 18446744073709551615, 0, 1), - (13, 660, 1079, 661, 18446744073709551615, 0, 1), - (13, 661, 178, 662, 18446744073709551615, 0, 1), - (13, 662, 950, 663, 18446744073709551615, 0, 1), - (13, 663, 1080, 664, 18446744073709551615, 0, 1), - (13, 664, 175, 665, 18446744073709551615, 0, 1), - (13, 665, 947, 666, 18446744073709551615, 0, 1), - (13, 666, 1081, 667, 18446744073709551615, 0, 1), - (13, 667, 941, 668, 18446744073709551615, 0, 1), - (13, 668, 944, 669, 18446744073709551615, 0, 1), - (13, 669, 169, 670, 18446744073709551615, 0, 1), - (13, 670, 938, 671, 18446744073709551615, 0, 1), - (13, 671, 939, 672, 18446744073709551615, 0, 1), - (13, 672, 1084, 673, 18446744073709551615, 0, 1), - (13, 673, 166, 674, 18446744073709551615, 0, 1), - (13, 674, 171, 675, 18446744073709551615, 0, 1), - (13, 675, 940, 676, 18446744073709551615, 0, 1), - (13, 676, 932, 677, 18446744073709551615, 0, 1), - (13, 677, 163, 678, 18446744073709551615, 0, 1), - (13, 678, 930, 679, 18446744073709551615, 0, 1), - (13, 679, 931, 680, 18446744073709551615, 0, 1), - (13, 680, 934, 681, 18446744073709551615, 0, 1), - (13, 681, 1085, 682, 18446744073709551615, 0, 1), - (13, 682, 926, 683, 18446744073709551615, 0, 1), - (13, 683, 927, 684, 18446744073709551615, 0, 1), - (13, 684, 928, 685, 18446744073709551615, 0, 1), - (13, 685, 923, 686, 18446744073709551615, 0, 1), - (13, 686, 924, 687, 18446744073709551615, 0, 1), - (13, 687, 925, 688, 18446744073709551615, 0, 1), - (13, 688, 1086, 689, 18446744073709551615, 0, 1), - (13, 689, 150, 690, 18446744073709551615, 0, 1), - (13, 690, 922, 691, 18446744073709551615, 0, 1), - (13, 691, 1087, 692, 18446744073709551615, 0, 1), - (13, 692, 146, 693, 18446744073709551615, 0, 1), - (13, 693, 915, 694, 18446744073709551615, 0, 1), - (13, 694, 916, 695, 18446744073709551615, 0, 1), - (13, 695, 1088, 696, 18446744073709551615, 0, 1), - (13, 696, 143, 697, 18446744073709551615, 0, 1), - (13, 697, 148, 698, 18446744073709551615, 0, 1), - (13, 698, 917, 699, 18446744073709551615, 0, 1), - (13, 699, 1090, 700, 18446744073709551615, 0, 1), - (13, 700, 1089, 701, 18446744073709551615, 0, 1), - (13, 701, 907, 702, 18446744073709551615, 0, 1), - (13, 702, 138, 703, 18446744073709551615, 0, 1), - (13, 703, 908, 704, 18446744073709551615, 0, 1), - (13, 704, 135, 705, 18446744073709551615, 0, 1), - (13, 705, 909, 706, 18446744073709551615, 0, 1), - (13, 706, 1092, 707, 18446744073709551615, 0, 1), - (13, 707, 132, 128, 18446744073709551615, 0, 1), - (13, 798, 679, 678, 18446744073709551615, 0, 1), - (13, 911, 719, 718, 18446744073709551615, 0, 2), - (13, 151, 717, 716, 18446744073709551615, 0, 2), - (13, 920, 716, 715, 18446744073709551615, 0, 2), - (13, 921, 715, 714, 18446744073709551615, 0, 2), - (13, 155, 712, 711, 18446744073709551615, 0, 2), - (13, 153, 711, 710, 18446744073709551615, 0, 2), - (13, 160, 710, 709, 18446744073709551615, 0, 2), - (13, 158, 709, 708, 18446744073709551615, 0, 2), - (13, 935, 708, 614, 18446744073709551615, 0, 2), - (13, 929, 614, 615, 18446744073709551615, 0, 2), - (13, 933, 615, 616, 18446744073709551615, 0, 2), - (13, 165, 616, 617, 18446744073709551615, 0, 2), - (13, 161, 617, 618, 18446744073709551615, 0, 2), - (13, 164, 618, 619, 18446744073709551615, 0, 2), - (13, 162, 619, 620, 18446744073709551615, 0, 2), - (13, 167, 620, 621, 18446744073709551615, 0, 2), - (13, 936, 621, 622, 18446744073709551615, 0, 2), - (13, 937, 622, 623, 18446744073709551615, 0, 2), - (13, 170, 623, 624, 18446744073709551615, 0, 2), - (13, 168, 624, 625, 18446744073709551615, 0, 2), - (13, 156, 625, 626, 18446744073709551615, 0, 2), - (13, 1082, 626, 627, 18446744073709551615, 0, 2), - (13, 942, 627, 628, 18446744073709551615, 0, 2), - (13, 943, 628, 629, 18446744073709551615, 0, 2), - (13, 176, 629, 630, 18446744073709551615, 0, 2), - (13, 945, 630, 631, 18446744073709551615, 0, 2), - (13, 946, 631, 632, 18446744073709551615, 0, 2), - (13, 179, 632, 633, 18446744073709551615, 0, 2), - (13, 948, 633, 634, 18446744073709551615, 0, 2), - (13, 949, 634, 635, 18446744073709551615, 0, 2), - (13, 182, 635, 636, 18446744073709551615, 0, 2), - (13, 951, 636, 637, 18446744073709551615, 0, 2), - (13, 952, 637, 638, 18446744073709551615, 0, 2), - (13, 185, 638, 639, 18446744073709551615, 0, 2), - (13, 954, 639, 640, 18446744073709551615, 0, 2), - (13, 955, 640, 641, 18446744073709551615, 0, 2), - (13, 188, 641, 642, 18446744073709551615, 0, 2), - (13, 957, 642, 643, 18446744073709551615, 0, 2), - (13, 958, 643, 644, 18446744073709551615, 0, 2), - (13, 191, 644, 645, 18446744073709551615, 0, 2), - (13, 960, 645, 646, 18446744073709551615, 0, 2), - (13, 961, 646, 647, 18446744073709551615, 0, 2), - (13, 194, 647, 648, 18446744073709551615, 0, 2), - (13, 963, 648, 649, 18446744073709551615, 0, 2), - (13, 964, 649, 650, 18446744073709551615, 0, 2), - (13, 197, 650, 651, 18446744073709551615, 0, 2), - (13, 966, 651, 652, 18446744073709551615, 0, 2), - (13, 967, 652, 653, 18446744073709551615, 0, 2), - (13, 200, 653, 654, 18446744073709551615, 0, 2), - (13, 969, 654, 655, 18446744073709551615, 0, 2), - (13, 970, 655, 656, 18446744073709551615, 0, 2), - (13, 203, 656, 657, 18446744073709551615, 0, 2), - (13, 972, 657, 658, 18446744073709551615, 0, 2), - (13, 973, 658, 659, 18446744073709551615, 0, 2), - (13, 206, 659, 660, 18446744073709551615, 0, 2), - (13, 975, 660, 661, 18446744073709551615, 0, 2), - (13, 976, 661, 662, 18446744073709551615, 0, 2), - (13, 209, 662, 663, 18446744073709551615, 0, 2), - (13, 978, 663, 664, 18446744073709551615, 0, 2), - (13, 979, 664, 665, 18446744073709551615, 0, 2), - (13, 212, 665, 666, 18446744073709551615, 0, 2), - (13, 981, 666, 667, 18446744073709551615, 0, 2), - (13, 982, 667, 668, 18446744073709551615, 0, 2), - (13, 215, 668, 669, 18446744073709551615, 0, 2), - (13, 984, 669, 670, 18446744073709551615, 0, 2), - (13, 985, 670, 671, 18446744073709551615, 0, 2), - (13, 218, 671, 672, 18446744073709551615, 0, 2), - (13, 987, 672, 673, 18446744073709551615, 0, 2), - (13, 988, 673, 674, 18446744073709551615, 0, 2), - (13, 221, 674, 675, 18446744073709551615, 0, 2), - (13, 990, 675, 676, 18446744073709551615, 0, 2), - (13, 991, 676, 677, 18446744073709551615, 0, 2), - (13, 224, 677, 678, 18446744073709551615, 0, 2), - (13, 993, 678, 679, 18446744073709551615, 0, 2), - (13, 994, 679, 680, 18446744073709551615, 0, 2), - (13, 227, 680, 681, 18446744073709551615, 0, 2), - (13, 996, 681, 682, 18446744073709551615, 0, 2), - (13, 997, 682, 683, 18446744073709551615, 0, 2), - (13, 230, 683, 684, 18446744073709551615, 0, 2), - (13, 999, 684, 685, 18446744073709551615, 0, 2), - (13, 1000, 685, 686, 18446744073709551615, 0, 2), - (13, 233, 686, 687, 18446744073709551615, 0, 4), - (13, 1002, 687, 688, 18446744073709551615, 0, 4), - (13, 1003, 688, 689, 18446744073709551615, 0, 4), - (13, 236, 689, 690, 18446744073709551615, 0, 4), - (13, 1005, 690, 691, 18446744073709551615, 0, 4), - (13, 1006, 691, 692, 18446744073709551615, 0, 4), - (13, 239, 692, 693, 18446744073709551615, 0, 4), - (13, 1008, 693, 694, 18446744073709551615, 0, 4), - (13, 1009, 694, 695, 18446744073709551615, 0, 4), - (13, 242, 695, 696, 18446744073709551615, 0, 4), - (13, 1011, 696, 697, 18446744073709551615, 0, 4), - (13, 1012, 697, 698, 18446744073709551615, 0, 4), - (13, 245, 698, 699, 18446744073709551615, 0, 4), - (13, 1014, 699, 700, 18446744073709551615, 0, 4), - (13, 1015, 700, 701, 18446744073709551615, 0, 4), - (13, 248, 701, 702, 18446744073709551615, 0, 4), - (13, 1017, 702, 703, 18446744073709551615, 0, 4), - (13, 1018, 703, 704, 18446744073709551615, 0, 4), - (13, 251, 704, 705, 18446744073709551615, 0, 4), - (13, 1020, 705, 706, 18446744073709551615, 0, 4), - (13, 1021, 706, 707, 18446744073709551615, 0, 4), - (13, 254, 707, 128, 18446744073709551615, 0, 2), - (13, 1023, 128, 1093, 18446744073709551615, 0, 4), - (13, 1049, 1093, 732, 18446744073709551615, 0, 1), - (13, 1023, 128, 1093, 18446744073709551615, 1, 4), - (13, 254, 707, 128, 18446744073709551615, 1, 2), - (13, 1021, 706, 707, 18446744073709551615, 1, 4), - (13, 1020, 705, 706, 18446744073709551615, 1, 4), - (13, 251, 704, 705, 18446744073709551615, 1, 4), - (13, 1018, 703, 704, 18446744073709551615, 1, 4), - (13, 1017, 702, 703, 18446744073709551615, 1, 4), - (13, 248, 701, 702, 18446744073709551615, 1, 4), - (13, 1015, 700, 701, 18446744073709551615, 1, 4), - (13, 1014, 699, 700, 18446744073709551615, 1, 4), - (13, 245, 698, 699, 18446744073709551615, 1, 4), - (13, 1012, 697, 698, 18446744073709551615, 1, 4), - (13, 1011, 696, 697, 18446744073709551615, 1, 4), - (13, 242, 695, 696, 18446744073709551615, 1, 4), - (13, 1009, 694, 695, 18446744073709551615, 1, 4), - (13, 1008, 693, 694, 18446744073709551615, 1, 4), - (13, 239, 692, 693, 18446744073709551615, 1, 4), - (13, 1006, 691, 692, 18446744073709551615, 1, 4), - (13, 1005, 690, 691, 18446744073709551615, 1, 4), - (13, 236, 689, 690, 18446744073709551615, 1, 4), - (13, 1003, 688, 689, 18446744073709551615, 1, 4), - (13, 1002, 687, 688, 18446744073709551615, 1, 4), - (13, 233, 686, 687, 18446744073709551615, 1, 4), - (13, 1000, 685, 686, 18446744073709551615, 1, 2), - (13, 999, 684, 685, 18446744073709551615, 1, 2), - (13, 230, 683, 684, 18446744073709551615, 1, 2), - (13, 997, 682, 683, 18446744073709551615, 1, 2), - (13, 996, 681, 682, 18446744073709551615, 1, 2), - (13, 227, 680, 681, 18446744073709551615, 1, 2), - (13, 994, 679, 680, 18446744073709551615, 1, 2), - (13, 993, 678, 679, 18446744073709551615, 1, 2), - (13, 224, 677, 678, 18446744073709551615, 1, 2), - (13, 991, 676, 677, 18446744073709551615, 1, 2), - (13, 990, 675, 676, 18446744073709551615, 1, 2), - (13, 221, 674, 675, 18446744073709551615, 1, 2), - (13, 988, 673, 674, 18446744073709551615, 1, 2), - (13, 987, 672, 673, 18446744073709551615, 1, 2), - (13, 218, 671, 672, 18446744073709551615, 1, 2), - (13, 985, 670, 671, 18446744073709551615, 1, 2), - (13, 984, 669, 670, 18446744073709551615, 1, 2), - (13, 215, 668, 669, 18446744073709551615, 1, 2), - (13, 982, 667, 668, 18446744073709551615, 1, 2), - (13, 981, 666, 667, 18446744073709551615, 1, 2), - (13, 212, 665, 666, 18446744073709551615, 1, 2), - (13, 979, 664, 665, 18446744073709551615, 1, 2), - (13, 978, 663, 664, 18446744073709551615, 1, 2), - (13, 209, 662, 663, 18446744073709551615, 1, 2), - (13, 976, 661, 662, 18446744073709551615, 1, 2), - (13, 975, 660, 661, 18446744073709551615, 1, 2), - (13, 206, 659, 660, 18446744073709551615, 1, 2), - (13, 973, 658, 659, 18446744073709551615, 1, 2), - (13, 972, 657, 658, 18446744073709551615, 1, 2), - (13, 203, 656, 657, 18446744073709551615, 1, 2), - (13, 970, 655, 656, 18446744073709551615, 1, 2), - (13, 969, 654, 655, 18446744073709551615, 1, 2), - (13, 200, 653, 654, 18446744073709551615, 1, 2), - (13, 967, 652, 653, 18446744073709551615, 1, 2), - (13, 966, 651, 652, 18446744073709551615, 1, 2), - (13, 197, 650, 651, 18446744073709551615, 1, 2), - (13, 964, 649, 650, 18446744073709551615, 1, 2), - (13, 963, 648, 649, 18446744073709551615, 1, 2), - (13, 194, 647, 648, 18446744073709551615, 1, 2), - (13, 961, 646, 647, 18446744073709551615, 1, 2), - (13, 960, 645, 646, 18446744073709551615, 1, 2), - (13, 191, 644, 645, 18446744073709551615, 1, 2), - (13, 958, 643, 644, 18446744073709551615, 1, 2), - (13, 957, 642, 643, 18446744073709551615, 1, 2), - (13, 188, 641, 642, 18446744073709551615, 1, 2), - (13, 955, 640, 641, 18446744073709551615, 1, 2), - (13, 954, 639, 640, 18446744073709551615, 1, 2), - (13, 185, 638, 639, 18446744073709551615, 1, 2), - (13, 952, 637, 638, 18446744073709551615, 1, 2), - (13, 951, 636, 637, 18446744073709551615, 1, 2), - (13, 182, 635, 636, 18446744073709551615, 1, 2), - (13, 949, 634, 635, 18446744073709551615, 1, 2), - (13, 948, 633, 634, 18446744073709551615, 1, 2), - (13, 179, 632, 633, 18446744073709551615, 1, 2), - (13, 946, 631, 632, 18446744073709551615, 1, 2), - (13, 945, 630, 631, 18446744073709551615, 1, 2), - (13, 176, 629, 630, 18446744073709551615, 1, 2), - (13, 943, 628, 629, 18446744073709551615, 1, 2), - (13, 942, 627, 628, 18446744073709551615, 1, 2), - (13, 1082, 626, 627, 18446744073709551615, 1, 2), - (13, 156, 625, 626, 18446744073709551615, 1, 2), - (13, 168, 624, 625, 18446744073709551615, 1, 2), - (13, 170, 623, 624, 18446744073709551615, 1, 2), - (13, 937, 622, 623, 18446744073709551615, 1, 2), - (13, 936, 621, 622, 18446744073709551615, 1, 2), - (13, 167, 620, 621, 18446744073709551615, 1, 2), - (13, 162, 619, 620, 18446744073709551615, 1, 2), - (13, 164, 618, 619, 18446744073709551615, 1, 2), - (13, 161, 617, 618, 18446744073709551615, 1, 2), - (13, 165, 616, 617, 18446744073709551615, 1, 2), - (13, 933, 615, 616, 18446744073709551615, 1, 2), - (13, 929, 614, 615, 18446744073709551615, 1, 2), - (13, 935, 708, 614, 18446744073709551615, 1, 2), - (13, 158, 709, 708, 18446744073709551615, 1, 2), - (13, 160, 710, 709, 18446744073709551615, 1, 2), - (13, 153, 711, 710, 18446744073709551615, 1, 2), - (13, 155, 712, 711, 18446744073709551615, 1, 2), - (13, 921, 715, 714, 18446744073709551615, 1, 2), - (13, 920, 716, 715, 18446744073709551615, 1, 2), - (13, 151, 717, 716, 18446744073709551615, 1, 2), - (13, 911, 719, 718, 18446744073709551615, 1, 2), - (13, 732, 755, 733, 18446744073709551615, 2, 5), - (13, 754, 733, 605, 18446744073709551615, 2, 5), - (13, 753, 605, 604, 18446744073709551615, 2, 5), - (13, 752, 604, 603, 18446744073709551615, 2, 5), - (13, 751, 603, 602, 18446744073709551615, 2, 5), - (13, 750, 602, 601, 18446744073709551615, 2, 5), - (13, 749, 601, 600, 18446744073709551615, 2, 5), - (13, 748, 600, 599, 18446744073709551615, 2, 5), - (13, 747, 599, 598, 18446744073709551615, 2, 5), - (13, 14, 598, 597, 18446744073709551615, 2, 5), - (13, 11, 597, 596, 18446744073709551615, 2, 5), - (13, 777, 596, 595, 18446744073709551615, 2, 5), - (13, 13, 595, 594, 18446744073709551615, 2, 5), - (13, 1145, 594, 593, 18446744073709551615, 2, 5), - (13, 1137, 593, 592, 18446744073709551615, 2, 5), - (13, 17, 592, 591, 18446744073709551615, 2, 5), - (13, 1134, 591, 590, 18446744073709551615, 2, 5), - (13, 27, 590, 589, 18446744073709551615, 2, 5), - (13, 786, 589, 588, 18446744073709551615, 2, 5), - (13, 787, 588, 587, 18446744073709551615, 2, 5), - (13, 788, 587, 586, 18446744073709551615, 2, 5), - (13, 789, 586, 585, 18446744073709551615, 2, 5), - (13, 790, 585, 584, 18446744073709551615, 2, 5), - (13, 791, 584, 583, 18446744073709551615, 2, 5), - (13, 23, 583, 582, 18446744073709551615, 2, 5), - (13, 20, 582, 581, 18446744073709551615, 2, 5), - (13, 18, 581, 580, 18446744073709551615, 2, 5), - (13, 795, 580, 579, 18446744073709551615, 2, 5), - (13, 796, 579, 578, 18446744073709551615, 2, 5), - (13, 797, 578, 577, 18446744073709551615, 2, 5), - (13, 798, 577, 576, 18446744073709551615, 2, 5), - (13, 799, 576, 575, 18446744073709551615, 2, 5), - (13, 800, 575, 574, 18446744073709551615, 2, 5), - (13, 801, 574, 573, 18446744073709551615, 2, 5), - (13, 802, 573, 572, 18446744073709551615, 2, 5), - (13, 803, 572, 571, 18446744073709551615, 2, 5), - (13, 804, 571, 570, 18446744073709551615, 2, 5), - (13, 805, 570, 569, 18446744073709551615, 2, 5), - (13, 806, 569, 568, 18446744073709551615, 2, 5), - (13, 807, 568, 567, 18446744073709551615, 2, 5), - (13, 808, 567, 566, 18446744073709551615, 2, 5), - (13, 809, 566, 565, 18446744073709551615, 2, 5), - (13, 810, 565, 564, 18446744073709551615, 2, 5), - (13, 811, 564, 563, 18446744073709551615, 2, 5), - (13, 812, 563, 562, 18446744073709551615, 2, 5), - (13, 813, 562, 561, 18446744073709551615, 2, 5), - (13, 814, 561, 560, 18446744073709551615, 2, 5), - (13, 815, 560, 558, 18446744073709551615, 2, 5), - (13, 816, 558, 557, 18446744073709551615, 4, 10), - (13, 817, 557, 559, 18446744073709551615, 2, 5), - (13, 818, 559, 557, 18446744073709551615, 2, 5), - (13, 819, 557, 558, 18446744073709551615, 2, 5), - (14, 732, 819, 557, 18446744073709551615, 2, 5), - (14, 732, 817, 557, 18446744073709551615, 2, 5), - (13, 1006, 691, 605, 18446744073709551615, 0, 1), - (13, 239, 692, 604, 18446744073709551615, 0, 1), - (13, 1008, 693, 603, 18446744073709551615, 0, 1), - (13, 1009, 694, 602, 18446744073709551615, 0, 1), - (13, 242, 695, 601, 18446744073709551615, 0, 1), - (13, 1011, 696, 600, 18446744073709551615, 0, 1), - (13, 1012, 697, 599, 18446744073709551615, 0, 1), - (13, 245, 698, 598, 18446744073709551615, 0, 1), - (13, 1014, 699, 597, 18446744073709551615, 0, 1), - (13, 1015, 700, 596, 18446744073709551615, 0, 1), - (13, 248, 701, 595, 18446744073709551615, 0, 1), - (13, 1017, 702, 594, 18446744073709551615, 0, 1), - (13, 1018, 703, 593, 18446744073709551615, 0, 1), - (13, 251, 704, 592, 18446744073709551615, 0, 1), - (13, 1020, 705, 591, 18446744073709551615, 0, 1), - (13, 1021, 706, 590, 18446744073709551615, 0, 1), - (13, 254, 707, 589, 18446744073709551615, 0, 1), - (13, 1023, 128, 588, 18446744073709551615, 0, 1), - (13, 1049, 1093, 587, 18446744073709551615, 0, 1), - (13, 154, 688, 687, 18446744073709551615, 0, 2), - (13, 153, 685, 684, 18446744073709551615, 0, 2), - (13, 160, 684, 683, 18446744073709551615, 0, 2), - (13, 935, 682, 681, 18446744073709551615, 0, 2), - (13, 929, 681, 680, 18446744073709551615, 0, 2), - (13, 933, 680, 679, 18446744073709551615, 0, 2), - (13, 165, 679, 678, 18446744073709551615, 0, 2), - (13, 161, 678, 677, 18446744073709551615, 0, 2), - (13, 164, 677, 676, 18446744073709551615, 0, 2), - (13, 162, 676, 675, 18446744073709551615, 0, 2), - (13, 167, 675, 674, 18446744073709551615, 0, 2), - (13, 936, 674, 673, 18446744073709551615, 0, 2), - (13, 937, 673, 672, 18446744073709551615, 0, 2), - (13, 170, 672, 671, 18446744073709551615, 0, 2), - (13, 168, 671, 670, 18446744073709551615, 0, 2), - (13, 156, 670, 669, 18446744073709551615, 0, 2), - (13, 1082, 669, 668, 18446744073709551615, 0, 2), - (13, 942, 668, 667, 18446744073709551615, 0, 2), - (13, 943, 667, 666, 18446744073709551615, 0, 2), - (13, 176, 666, 665, 18446744073709551615, 0, 2), - (13, 945, 665, 664, 18446744073709551615, 0, 2), - (13, 946, 664, 663, 18446744073709551615, 0, 2), - (13, 179, 663, 662, 18446744073709551615, 0, 2), - (13, 948, 662, 661, 18446744073709551615, 0, 2), - (13, 949, 661, 660, 18446744073709551615, 0, 2), - (13, 182, 660, 659, 18446744073709551615, 0, 2), - (13, 951, 659, 658, 18446744073709551615, 0, 2), - (13, 952, 658, 657, 18446744073709551615, 0, 2), - (13, 185, 657, 656, 18446744073709551615, 0, 2), - (13, 954, 656, 655, 18446744073709551615, 0, 2), - (13, 955, 655, 654, 18446744073709551615, 0, 2), - (13, 188, 654, 653, 18446744073709551615, 0, 2), - (13, 957, 653, 652, 18446744073709551615, 0, 2), - (13, 958, 652, 651, 18446744073709551615, 0, 2), - (13, 191, 651, 650, 18446744073709551615, 0, 2), - (13, 960, 650, 649, 18446744073709551615, 0, 2), - (13, 961, 649, 648, 18446744073709551615, 0, 2), - (13, 194, 648, 647, 18446744073709551615, 0, 2), - (13, 963, 647, 646, 18446744073709551615, 0, 2), - (13, 964, 646, 645, 18446744073709551615, 0, 2), - (13, 197, 645, 644, 18446744073709551615, 0, 2), - (13, 966, 644, 643, 18446744073709551615, 0, 2), - (13, 967, 643, 642, 18446744073709551615, 0, 2), - (13, 200, 642, 641, 18446744073709551615, 0, 2), - (13, 969, 641, 640, 18446744073709551615, 0, 2), - (13, 970, 640, 639, 18446744073709551615, 0, 2), - (13, 203, 639, 638, 18446744073709551615, 0, 2), - (13, 972, 638, 637, 18446744073709551615, 0, 2), - (13, 973, 637, 636, 18446744073709551615, 0, 2), - (13, 206, 636, 635, 18446744073709551615, 0, 2), - (13, 975, 635, 634, 18446744073709551615, 0, 2), - (13, 976, 634, 633, 18446744073709551615, 0, 2), - (13, 209, 633, 632, 18446744073709551615, 0, 2), - (13, 978, 632, 631, 18446744073709551615, 0, 2), - (13, 979, 631, 630, 18446744073709551615, 0, 2), - (13, 212, 630, 629, 18446744073709551615, 0, 2), - (13, 981, 629, 628, 18446744073709551615, 0, 2), - (13, 982, 628, 627, 18446744073709551615, 0, 2), - (13, 215, 627, 626, 18446744073709551615, 0, 2), - (13, 984, 626, 625, 18446744073709551615, 0, 2), - (13, 985, 625, 624, 18446744073709551615, 0, 2), - (13, 218, 624, 623, 18446744073709551615, 0, 2), - (13, 987, 623, 622, 18446744073709551615, 0, 2), - (13, 988, 622, 621, 18446744073709551615, 0, 2), - (13, 221, 621, 620, 18446744073709551615, 0, 2), - (13, 990, 620, 619, 18446744073709551615, 0, 2), - (13, 991, 619, 618, 18446744073709551615, 0, 2), - (13, 224, 618, 617, 18446744073709551615, 0, 2), - (13, 993, 617, 616, 18446744073709551615, 0, 2), - (13, 994, 616, 615, 18446744073709551615, 0, 2), - (13, 227, 615, 614, 18446744073709551615, 0, 2), - (13, 996, 614, 708, 18446744073709551615, 0, 2), - (13, 997, 708, 709, 18446744073709551615, 0, 2), - (13, 230, 709, 710, 18446744073709551615, 0, 2), - (13, 999, 710, 711, 18446744073709551615, 0, 2), - (13, 1000, 711, 712, 18446744073709551615, 0, 2), - (13, 233, 712, 713, 18446744073709551615, 0, 2), - (13, 1002, 713, 714, 18446744073709551615, 0, 2), - (13, 1003, 714, 715, 18446744073709551615, 0, 2), - (13, 236, 715, 716, 18446744073709551615, 0, 2), - (13, 1005, 716, 717, 18446744073709551615, 0, 2), - (13, 1006, 717, 718, 18446744073709551615, 0, 2), - (13, 239, 718, 719, 18446744073709551615, 0, 2), - (13, 1008, 719, 720, 18446744073709551615, 0, 2), - (13, 1009, 720, 721, 18446744073709551615, 0, 2), - (13, 242, 721, 722, 18446744073709551615, 0, 2), - (13, 1011, 722, 723, 18446744073709551615, 0, 2), - (13, 1012, 723, 724, 18446744073709551615, 0, 2), - (13, 245, 724, 725, 18446744073709551615, 0, 2), - (13, 1014, 725, 726, 18446744073709551615, 0, 2), - (13, 1015, 726, 727, 18446744073709551615, 0, 2), - (13, 248, 727, 728, 18446744073709551615, 0, 2), - (13, 1017, 728, 729, 18446744073709551615, 0, 2), - (13, 1018, 729, 613, 18446744073709551615, 0, 2), - (13, 251, 613, 612, 18446744073709551615, 0, 2), - (13, 1020, 612, 611, 18446744073709551615, 0, 2), - (13, 1021, 611, 610, 18446744073709551615, 0, 2), - (13, 254, 610, 730, 18446744073709551615, 0, 2), - (13, 1023, 730, 731, 18446744073709551615, 2, 4), - (13, 731, 1049, 609, 18446744073709551615, 0, 1), - (13, 1023, 730, 731, 18446744073709551615, 3, 4), - (13, 254, 610, 730, 18446744073709551615, 1, 2), - (13, 1021, 611, 610, 18446744073709551615, 1, 2), - (13, 1020, 612, 611, 18446744073709551615, 1, 2), - (13, 251, 613, 612, 18446744073709551615, 1, 2), - (13, 1018, 729, 613, 18446744073709551615, 1, 2), - (13, 1017, 728, 729, 18446744073709551615, 1, 2), - (13, 248, 727, 728, 18446744073709551615, 1, 2), - (13, 1015, 726, 727, 18446744073709551615, 1, 2), - (13, 1014, 725, 726, 18446744073709551615, 1, 2), - (13, 245, 724, 725, 18446744073709551615, 1, 2), - (13, 1012, 723, 724, 18446744073709551615, 1, 2), - (13, 1011, 722, 723, 18446744073709551615, 1, 2), - (13, 242, 721, 722, 18446744073709551615, 1, 2), - (13, 1009, 720, 721, 18446744073709551615, 1, 2), - (13, 1008, 719, 720, 18446744073709551615, 1, 2), - (13, 239, 718, 719, 18446744073709551615, 1, 2), - (13, 1006, 717, 718, 18446744073709551615, 1, 2), - (13, 1005, 716, 717, 18446744073709551615, 1, 2), - (13, 236, 715, 716, 18446744073709551615, 1, 2), - (13, 1003, 714, 715, 18446744073709551615, 1, 2), - (13, 1002, 713, 714, 18446744073709551615, 1, 2), - (13, 233, 712, 713, 18446744073709551615, 1, 2), - (13, 1000, 711, 712, 18446744073709551615, 1, 2), - (13, 999, 710, 711, 18446744073709551615, 1, 2), - (13, 230, 709, 710, 18446744073709551615, 1, 2), - (13, 997, 708, 709, 18446744073709551615, 1, 2), - (13, 996, 614, 708, 18446744073709551615, 1, 2), - (13, 227, 615, 614, 18446744073709551615, 1, 2), - (13, 994, 616, 615, 18446744073709551615, 1, 2), - (13, 993, 617, 616, 18446744073709551615, 1, 2), - (13, 224, 618, 617, 18446744073709551615, 1, 2), - (13, 991, 619, 618, 18446744073709551615, 1, 2), - (13, 990, 620, 619, 18446744073709551615, 1, 2), - (13, 221, 621, 620, 18446744073709551615, 1, 2), - (13, 988, 622, 621, 18446744073709551615, 1, 2), - (13, 987, 623, 622, 18446744073709551615, 1, 2), - (13, 218, 624, 623, 18446744073709551615, 1, 2), - (13, 985, 625, 624, 18446744073709551615, 1, 2), - (13, 984, 626, 625, 18446744073709551615, 1, 2), - (13, 215, 627, 626, 18446744073709551615, 1, 2), - (13, 982, 628, 627, 18446744073709551615, 1, 2), - (13, 981, 629, 628, 18446744073709551615, 1, 2), - (13, 212, 630, 629, 18446744073709551615, 1, 2), - (13, 979, 631, 630, 18446744073709551615, 1, 2), - (13, 978, 632, 631, 18446744073709551615, 1, 2), - (13, 209, 633, 632, 18446744073709551615, 1, 2), - (13, 976, 634, 633, 18446744073709551615, 1, 2), - (13, 975, 635, 634, 18446744073709551615, 1, 2), - (13, 206, 636, 635, 18446744073709551615, 1, 2), - (13, 973, 637, 636, 18446744073709551615, 1, 2), - (13, 972, 638, 637, 18446744073709551615, 1, 2), - (13, 203, 639, 638, 18446744073709551615, 1, 2), - (13, 970, 640, 639, 18446744073709551615, 1, 2), - (13, 969, 641, 640, 18446744073709551615, 1, 2), - (13, 200, 642, 641, 18446744073709551615, 1, 2), - (13, 967, 643, 642, 18446744073709551615, 1, 2), - (13, 966, 644, 643, 18446744073709551615, 1, 2), - (13, 197, 645, 644, 18446744073709551615, 1, 2), - (13, 964, 646, 645, 18446744073709551615, 1, 2), - (13, 963, 647, 646, 18446744073709551615, 1, 2), - (13, 194, 648, 647, 18446744073709551615, 1, 2), - (13, 961, 649, 648, 18446744073709551615, 1, 2), - (13, 960, 650, 649, 18446744073709551615, 1, 2), - (13, 191, 651, 650, 18446744073709551615, 1, 2), - (13, 958, 652, 651, 18446744073709551615, 1, 2), - (13, 957, 653, 652, 18446744073709551615, 1, 2), - (13, 188, 654, 653, 18446744073709551615, 1, 2), - (13, 955, 655, 654, 18446744073709551615, 1, 2), - (13, 954, 656, 655, 18446744073709551615, 1, 2), - (13, 185, 657, 656, 18446744073709551615, 1, 2), - (13, 952, 658, 657, 18446744073709551615, 1, 2), - (13, 951, 659, 658, 18446744073709551615, 1, 2), - (13, 182, 660, 659, 18446744073709551615, 1, 2), - (13, 949, 661, 660, 18446744073709551615, 1, 2), - (13, 948, 662, 661, 18446744073709551615, 1, 2), - (13, 179, 663, 662, 18446744073709551615, 1, 2), - (13, 946, 664, 663, 18446744073709551615, 1, 2), - (13, 945, 665, 664, 18446744073709551615, 1, 2), - (13, 176, 666, 665, 18446744073709551615, 1, 2), - (13, 943, 667, 666, 18446744073709551615, 1, 2), - (13, 942, 668, 667, 18446744073709551615, 1, 2), - (13, 1082, 669, 668, 18446744073709551615, 1, 2), - (13, 156, 670, 669, 18446744073709551615, 1, 2), - (13, 168, 671, 670, 18446744073709551615, 1, 2), - (13, 170, 672, 671, 18446744073709551615, 1, 2), - (13, 937, 673, 672, 18446744073709551615, 1, 2), - (13, 936, 674, 673, 18446744073709551615, 1, 2), - (13, 167, 675, 674, 18446744073709551615, 1, 2), - (13, 162, 676, 675, 18446744073709551615, 1, 2), - (13, 164, 677, 676, 18446744073709551615, 1, 2), - (13, 161, 678, 677, 18446744073709551615, 1, 2), - (13, 165, 679, 678, 18446744073709551615, 1, 2), - (13, 933, 680, 679, 18446744073709551615, 1, 2), - (13, 929, 681, 680, 18446744073709551615, 1, 2), - (13, 935, 682, 681, 18446744073709551615, 1, 2), - (13, 160, 684, 683, 18446744073709551615, 1, 2), - (13, 153, 685, 684, 18446744073709551615, 1, 2), - (13, 154, 688, 687, 18446744073709551615, 1, 2), - (13, 609, 755, 608, 18446744073709551615, 1, 3), - (13, 754, 608, 607, 18446744073709551615, 1, 3), - (13, 753, 607, 606, 18446744073709551615, 1, 3), - (13, 752, 606, 732, 18446744073709551615, 1, 3), - (13, 751, 732, 733, 18446744073709551615, 1, 3), - (13, 750, 733, 605, 18446744073709551615, 1, 3), - (13, 749, 605, 604, 18446744073709551615, 1, 3), - (13, 748, 604, 603, 18446744073709551615, 1, 3), - (13, 747, 603, 602, 18446744073709551615, 1, 3), - (13, 14, 602, 601, 18446744073709551615, 1, 3), - (13, 11, 601, 600, 18446744073709551615, 1, 3), - (13, 777, 600, 599, 18446744073709551615, 1, 3), - (13, 13, 599, 598, 18446744073709551615, 1, 3), - (13, 1145, 598, 597, 18446744073709551615, 1, 3), - (13, 1137, 597, 596, 18446744073709551615, 1, 3), - (13, 17, 596, 595, 18446744073709551615, 1, 3), - (13, 1134, 595, 594, 18446744073709551615, 1, 3), - (13, 27, 594, 593, 18446744073709551615, 1, 3), - (13, 786, 593, 592, 18446744073709551615, 1, 3), - (13, 787, 592, 591, 18446744073709551615, 1, 3), - (13, 788, 591, 590, 18446744073709551615, 1, 3), - (13, 789, 590, 589, 18446744073709551615, 1, 3), - (13, 790, 589, 588, 18446744073709551615, 1, 3), - (13, 791, 588, 587, 18446744073709551615, 1, 3), - (13, 23, 587, 586, 18446744073709551615, 1, 3), - (13, 20, 586, 585, 18446744073709551615, 1, 3), - (13, 18, 585, 584, 18446744073709551615, 1, 3), - (13, 795, 584, 583, 18446744073709551615, 1, 3), - (13, 796, 583, 582, 18446744073709551615, 1, 3), - (13, 797, 582, 581, 18446744073709551615, 1, 3), - (13, 798, 581, 580, 18446744073709551615, 1, 3), - (13, 799, 580, 579, 18446744073709551615, 1, 3), - (13, 800, 579, 578, 18446744073709551615, 1, 3), - (13, 801, 578, 577, 18446744073709551615, 1, 3), - (13, 802, 577, 576, 18446744073709551615, 1, 3), - (13, 803, 576, 575, 18446744073709551615, 1, 3), - (13, 804, 575, 574, 18446744073709551615, 1, 3), - (13, 805, 574, 573, 18446744073709551615, 1, 3), - (13, 806, 573, 572, 18446744073709551615, 1, 3), - (13, 807, 572, 571, 18446744073709551615, 1, 3), - (13, 808, 571, 570, 18446744073709551615, 1, 3), - (13, 809, 570, 569, 18446744073709551615, 1, 3), - (13, 810, 569, 568, 18446744073709551615, 1, 3), - (13, 811, 568, 567, 18446744073709551615, 1, 3), - (13, 812, 567, 566, 18446744073709551615, 1, 3), - (13, 813, 566, 565, 18446744073709551615, 1, 3), - (13, 814, 565, 564, 18446744073709551615, 1, 3), - (13, 815, 564, 562, 18446744073709551615, 1, 3), - (13, 816, 562, 561, 18446744073709551615, 2, 6), - (13, 817, 561, 563, 18446744073709551615, 1, 3), - (13, 818, 563, 561, 18446744073709551615, 1, 3), - (13, 819, 561, 562, 18446744073709551615, 1, 3), - (14, 609, 819, 561, 18446744073709551615, 1, 3), - (14, 609, 817, 561, 18446744073709551615, 1, 3), - (13, 1006, 717, 607, 18446744073709551615, 0, 1), - (13, 239, 718, 606, 18446744073709551615, 0, 1), - (13, 1008, 719, 732, 18446744073709551615, 0, 1), - (13, 1009, 720, 733, 18446744073709551615, 0, 1), - (13, 242, 721, 605, 18446744073709551615, 0, 1), - (13, 1011, 722, 604, 18446744073709551615, 0, 1), - (13, 1012, 723, 603, 18446744073709551615, 0, 1), - (13, 245, 724, 602, 18446744073709551615, 0, 1), - (13, 1014, 725, 601, 18446744073709551615, 0, 1), - (13, 1015, 726, 600, 18446744073709551615, 0, 1), - (13, 248, 727, 599, 18446744073709551615, 0, 1), - (13, 1017, 728, 598, 18446744073709551615, 0, 1), - (13, 1018, 729, 597, 18446744073709551615, 0, 1), - (13, 251, 613, 596, 18446744073709551615, 0, 1), - (13, 1020, 612, 595, 18446744073709551615, 0, 1), - (13, 1021, 611, 594, 18446744073709551615, 0, 1), - (13, 254, 610, 593, 18446744073709551615, 0, 1), - (13, 1023, 730, 592, 18446744073709551615, 0, 1), - (13, 1049, 731, 591, 18446744073709551615, 0, 1), - (13, 153, 713, 712, 18446744073709551615, 2, 4), - (13, 160, 712, 711, 18446744073709551615, 2, 4), - (13, 935, 710, 709, 18446744073709551615, 2, 4), - (13, 933, 708, 614, 18446744073709551615, 0, 2), - (13, 165, 614, 615, 18446744073709551615, 0, 2), - (13, 161, 615, 616, 18446744073709551615, 0, 2), - (13, 164, 616, 617, 18446744073709551615, 0, 2), - (13, 162, 617, 618, 18446744073709551615, 0, 2), - (13, 167, 618, 619, 18446744073709551615, 0, 2), - (13, 936, 619, 620, 18446744073709551615, 0, 2), - (13, 937, 620, 621, 18446744073709551615, 0, 2), - (13, 170, 621, 622, 18446744073709551615, 0, 2), - (13, 168, 622, 623, 18446744073709551615, 0, 2), - (13, 156, 623, 624, 18446744073709551615, 0, 2), - (13, 1082, 624, 625, 18446744073709551615, 0, 2), - (13, 942, 625, 626, 18446744073709551615, 0, 2), - (13, 943, 626, 627, 18446744073709551615, 0, 2), - (13, 176, 627, 628, 18446744073709551615, 0, 2), - (13, 945, 628, 629, 18446744073709551615, 0, 2), - (13, 946, 629, 630, 18446744073709551615, 0, 2), - (13, 179, 630, 631, 18446744073709551615, 0, 2), - (13, 948, 631, 632, 18446744073709551615, 0, 2), - (13, 949, 632, 633, 18446744073709551615, 0, 2), - (13, 182, 633, 634, 18446744073709551615, 0, 2), - (13, 951, 634, 635, 18446744073709551615, 0, 2), - (13, 952, 635, 636, 18446744073709551615, 0, 2), - (13, 185, 636, 637, 18446744073709551615, 0, 2), - (13, 954, 637, 638, 18446744073709551615, 0, 2), - (13, 955, 638, 639, 18446744073709551615, 0, 2), - (13, 188, 639, 640, 18446744073709551615, 0, 2), - (13, 957, 640, 641, 18446744073709551615, 0, 2), - (13, 958, 641, 642, 18446744073709551615, 0, 2), - (13, 191, 642, 643, 18446744073709551615, 0, 2), - (13, 960, 643, 644, 18446744073709551615, 2, 4), - (13, 961, 644, 645, 18446744073709551615, 2, 4), - (13, 194, 645, 646, 18446744073709551615, 2, 4), - (13, 963, 646, 647, 18446744073709551615, 2, 4), - (13, 964, 647, 648, 18446744073709551615, 2, 4), - (13, 197, 648, 649, 18446744073709551615, 2, 4), - (13, 966, 649, 650, 18446744073709551615, 2, 4), - (13, 967, 650, 651, 18446744073709551615, 2, 4), - (13, 200, 651, 652, 18446744073709551615, 2, 4), - (13, 969, 652, 653, 18446744073709551615, 2, 4), - (13, 970, 653, 654, 18446744073709551615, 2, 4), - (13, 203, 654, 655, 18446744073709551615, 2, 4), - (13, 972, 655, 656, 18446744073709551615, 2, 4), - (13, 973, 656, 657, 18446744073709551615, 2, 4), - (13, 206, 657, 658, 18446744073709551615, 2, 4), - (13, 975, 658, 659, 18446744073709551615, 2, 4), - (13, 976, 659, 660, 18446744073709551615, 2, 4), - (13, 209, 660, 661, 18446744073709551615, 2, 4), - (13, 978, 661, 662, 18446744073709551615, 2, 4), - (13, 979, 662, 663, 18446744073709551615, 2, 4), - (13, 212, 663, 664, 18446744073709551615, 2, 4), - (13, 981, 664, 665, 18446744073709551615, 2, 4), - (13, 982, 665, 666, 18446744073709551615, 2, 4), - (13, 215, 666, 667, 18446744073709551615, 2, 4), - (13, 984, 667, 668, 18446744073709551615, 2, 4), - (13, 985, 668, 669, 18446744073709551615, 2, 4), - (13, 218, 669, 670, 18446744073709551615, 2, 4), - (13, 987, 670, 671, 18446744073709551615, 2, 4), - (13, 988, 671, 672, 18446744073709551615, 2, 4), - (13, 221, 672, 673, 18446744073709551615, 2, 4), - (13, 990, 673, 674, 18446744073709551615, 2, 4), - (13, 991, 674, 675, 18446744073709551615, 2, 4), - (13, 224, 675, 676, 18446744073709551615, 2, 4), - (13, 993, 676, 677, 18446744073709551615, 2, 4), - (13, 994, 677, 678, 18446744073709551615, 2, 4), - (13, 227, 678, 679, 18446744073709551615, 2, 4), - (13, 996, 679, 680, 18446744073709551615, 2, 4), - (13, 997, 680, 681, 18446744073709551615, 2, 4), - (13, 230, 681, 682, 18446744073709551615, 2, 4), - (13, 999, 682, 683, 18446744073709551615, 2, 4), - (13, 1000, 683, 684, 18446744073709551615, 2, 4), - (13, 233, 684, 685, 18446744073709551615, 2, 4), - (13, 1002, 685, 686, 18446744073709551615, 2, 4), - (13, 1003, 686, 687, 18446744073709551615, 2, 4), - (13, 236, 687, 688, 18446744073709551615, 2, 4), - (13, 1005, 688, 689, 18446744073709551615, 2, 4), - (13, 1006, 689, 690, 18446744073709551615, 2, 4), - (13, 239, 690, 691, 18446744073709551615, 2, 4), - (13, 1008, 691, 692, 18446744073709551615, 2, 4), - (13, 1009, 692, 693, 18446744073709551615, 2, 4), - (13, 242, 693, 694, 18446744073709551615, 2, 4), - (13, 1011, 694, 695, 18446744073709551615, 2, 4), - (13, 1012, 695, 696, 18446744073709551615, 2, 4), - (13, 245, 696, 697, 18446744073709551615, 2, 4), - (13, 1014, 697, 698, 18446744073709551615, 2, 4), - (13, 1015, 698, 699, 18446744073709551615, 2, 4), - (13, 248, 699, 700, 18446744073709551615, 2, 4), - (13, 1017, 700, 701, 18446744073709551615, 2, 4), - (13, 1018, 701, 702, 18446744073709551615, 2, 4), - (13, 251, 702, 703, 18446744073709551615, 2, 4), - (13, 1020, 703, 704, 18446744073709551615, 2, 4), - (13, 1021, 704, 705, 18446744073709551615, 2, 4), - (13, 254, 705, 706, 18446744073709551615, 2, 4), - (13, 1023, 706, 707, 18446744073709551615, 2, 4), - (13, 707, 1049, 128, 18446744073709551615, 0, 1), - (13, 1023, 706, 707, 18446744073709551615, 3, 4), - (13, 254, 705, 706, 18446744073709551615, 3, 4), - (13, 1021, 704, 705, 18446744073709551615, 3, 4), - (13, 1020, 703, 704, 18446744073709551615, 3, 4), - (13, 251, 702, 703, 18446744073709551615, 3, 4), - (13, 1018, 701, 702, 18446744073709551615, 3, 4), - (13, 1017, 700, 701, 18446744073709551615, 3, 4), - (13, 248, 699, 700, 18446744073709551615, 3, 4), - (13, 1015, 698, 699, 18446744073709551615, 3, 4), - (13, 1014, 697, 698, 18446744073709551615, 3, 4), - (13, 245, 696, 697, 18446744073709551615, 3, 4), - (13, 1012, 695, 696, 18446744073709551615, 3, 4), - (13, 1011, 694, 695, 18446744073709551615, 3, 4), - (13, 242, 693, 694, 18446744073709551615, 3, 4), - (13, 1009, 692, 693, 18446744073709551615, 3, 4), - (13, 1008, 691, 692, 18446744073709551615, 3, 4), - (13, 239, 690, 691, 18446744073709551615, 3, 4), - (13, 1006, 689, 690, 18446744073709551615, 3, 4), - (13, 1005, 688, 689, 18446744073709551615, 3, 4), - (13, 236, 687, 688, 18446744073709551615, 3, 4), - (13, 1003, 686, 687, 18446744073709551615, 3, 4), - (13, 1002, 685, 686, 18446744073709551615, 3, 4), - (13, 233, 684, 685, 18446744073709551615, 3, 4), - (13, 1000, 683, 684, 18446744073709551615, 3, 4), - (13, 999, 682, 683, 18446744073709551615, 3, 4), - (13, 230, 681, 682, 18446744073709551615, 3, 4), - (13, 997, 680, 681, 18446744073709551615, 3, 4), - (13, 996, 679, 680, 18446744073709551615, 3, 4), - (13, 227, 678, 679, 18446744073709551615, 3, 4), - (13, 994, 677, 678, 18446744073709551615, 3, 4), - (13, 993, 676, 677, 18446744073709551615, 3, 4), - (13, 224, 675, 676, 18446744073709551615, 3, 4), - (13, 991, 674, 675, 18446744073709551615, 3, 4), - (13, 990, 673, 674, 18446744073709551615, 3, 4), - (13, 221, 672, 673, 18446744073709551615, 3, 4), - (13, 988, 671, 672, 18446744073709551615, 3, 4), - (13, 987, 670, 671, 18446744073709551615, 3, 4), - (13, 218, 669, 670, 18446744073709551615, 3, 4), - (13, 985, 668, 669, 18446744073709551615, 3, 4), - (13, 984, 667, 668, 18446744073709551615, 3, 4), - (13, 215, 666, 667, 18446744073709551615, 3, 4), - (13, 982, 665, 666, 18446744073709551615, 3, 4), - (13, 981, 664, 665, 18446744073709551615, 3, 4), - (13, 212, 663, 664, 18446744073709551615, 3, 4), - (13, 979, 662, 663, 18446744073709551615, 3, 4), - (13, 978, 661, 662, 18446744073709551615, 3, 4), - (13, 209, 660, 661, 18446744073709551615, 3, 4), - (13, 976, 659, 660, 18446744073709551615, 3, 4), - (13, 975, 658, 659, 18446744073709551615, 3, 4), - (13, 206, 657, 658, 18446744073709551615, 3, 4), - (13, 973, 656, 657, 18446744073709551615, 3, 4), - (13, 972, 655, 656, 18446744073709551615, 3, 4), - (13, 203, 654, 655, 18446744073709551615, 3, 4), - (13, 970, 653, 654, 18446744073709551615, 3, 4), - (13, 969, 652, 653, 18446744073709551615, 3, 4), - (13, 200, 651, 652, 18446744073709551615, 3, 4), - (13, 967, 650, 651, 18446744073709551615, 3, 4), - (13, 966, 649, 650, 18446744073709551615, 3, 4), - (13, 197, 648, 649, 18446744073709551615, 3, 4), - (13, 964, 647, 648, 18446744073709551615, 3, 4), - (13, 963, 646, 647, 18446744073709551615, 3, 4), - (13, 194, 645, 646, 18446744073709551615, 3, 4), - (13, 961, 644, 645, 18446744073709551615, 3, 4), - (13, 960, 643, 644, 18446744073709551615, 3, 4), - (13, 191, 642, 643, 18446744073709551615, 1, 2), - (13, 958, 641, 642, 18446744073709551615, 1, 2), - (13, 957, 640, 641, 18446744073709551615, 1, 2), - (13, 188, 639, 640, 18446744073709551615, 1, 2), - (13, 955, 638, 639, 18446744073709551615, 1, 2), - (13, 954, 637, 638, 18446744073709551615, 1, 2), - (13, 185, 636, 637, 18446744073709551615, 1, 2), - (13, 952, 635, 636, 18446744073709551615, 1, 2), - (13, 951, 634, 635, 18446744073709551615, 1, 2), - (13, 182, 633, 634, 18446744073709551615, 1, 2), - (13, 949, 632, 633, 18446744073709551615, 1, 2), - (13, 948, 631, 632, 18446744073709551615, 1, 2), - (13, 179, 630, 631, 18446744073709551615, 1, 2), - (13, 946, 629, 630, 18446744073709551615, 1, 2), - (13, 945, 628, 629, 18446744073709551615, 1, 2), - (13, 176, 627, 628, 18446744073709551615, 1, 2), - (13, 943, 626, 627, 18446744073709551615, 1, 2), - (13, 942, 625, 626, 18446744073709551615, 1, 2), - (13, 1082, 624, 625, 18446744073709551615, 1, 2), - (13, 156, 623, 624, 18446744073709551615, 1, 2), - (13, 168, 622, 623, 18446744073709551615, 1, 2), - (13, 170, 621, 622, 18446744073709551615, 1, 2), - (13, 937, 620, 621, 18446744073709551615, 1, 2), - (13, 936, 619, 620, 18446744073709551615, 1, 2), - (13, 167, 618, 619, 18446744073709551615, 1, 2), - (13, 162, 617, 618, 18446744073709551615, 1, 2), - (13, 164, 616, 617, 18446744073709551615, 1, 2), - (13, 161, 615, 616, 18446744073709551615, 1, 2), - (13, 165, 614, 615, 18446744073709551615, 1, 2), - (13, 933, 708, 614, 18446744073709551615, 1, 2), - (13, 935, 710, 709, 18446744073709551615, 3, 4), - (13, 160, 712, 711, 18446744073709551615, 3, 4), - (13, 153, 713, 712, 18446744073709551615, 3, 4), - (13, 128, 755, 1093, 18446744073709551615, 0, 1), - (13, 754, 1093, 609, 18446744073709551615, 0, 1), - (13, 753, 609, 608, 18446744073709551615, 1, 3), - (13, 752, 608, 607, 18446744073709551615, 1, 3), - (13, 751, 607, 606, 18446744073709551615, 1, 3), - (13, 750, 606, 732, 18446744073709551615, 1, 3), - (13, 749, 732, 733, 18446744073709551615, 1, 3), - (13, 748, 733, 605, 18446744073709551615, 1, 3), - (13, 747, 605, 604, 18446744073709551615, 1, 3), - (13, 14, 604, 603, 18446744073709551615, 1, 3), - (13, 11, 603, 602, 18446744073709551615, 1, 3), - (13, 777, 602, 601, 18446744073709551615, 1, 3), - (13, 13, 601, 600, 18446744073709551615, 1, 3), - (13, 1145, 600, 599, 18446744073709551615, 1, 3), - (13, 1137, 599, 598, 18446744073709551615, 1, 3), - (13, 17, 598, 597, 18446744073709551615, 1, 3), - (13, 1134, 597, 596, 18446744073709551615, 1, 3), - (13, 27, 596, 595, 18446744073709551615, 1, 3), - (13, 786, 595, 594, 18446744073709551615, 1, 3), - (13, 787, 594, 593, 18446744073709551615, 1, 3), - (13, 788, 593, 592, 18446744073709551615, 1, 3), - (13, 789, 592, 591, 18446744073709551615, 1, 3), - (13, 790, 591, 590, 18446744073709551615, 1, 3), - (13, 791, 590, 589, 18446744073709551615, 1, 3), - (13, 23, 589, 588, 18446744073709551615, 1, 3), - (13, 20, 588, 587, 18446744073709551615, 1, 3), - (13, 18, 587, 586, 18446744073709551615, 1, 3), - (13, 795, 586, 585, 18446744073709551615, 1, 3), - (13, 796, 585, 584, 18446744073709551615, 1, 3), - (13, 797, 584, 583, 18446744073709551615, 1, 3), - (13, 798, 583, 582, 18446744073709551615, 1, 3), - (13, 799, 582, 581, 18446744073709551615, 1, 3), - (13, 800, 581, 580, 18446744073709551615, 1, 3), - (13, 801, 580, 579, 18446744073709551615, 1, 3), - (13, 802, 579, 578, 18446744073709551615, 1, 3), - (13, 803, 578, 577, 18446744073709551615, 1, 3), - (13, 804, 577, 576, 18446744073709551615, 1, 3), - (13, 805, 576, 575, 18446744073709551615, 1, 3), - (13, 806, 575, 574, 18446744073709551615, 1, 3), - (13, 807, 574, 573, 18446744073709551615, 1, 3), - (13, 808, 573, 572, 18446744073709551615, 1, 3), - (13, 809, 572, 571, 18446744073709551615, 1, 3), - (13, 810, 571, 570, 18446744073709551615, 1, 3), - (13, 811, 570, 569, 18446744073709551615, 1, 3), - (13, 812, 569, 568, 18446744073709551615, 1, 3), - (13, 813, 568, 567, 18446744073709551615, 1, 3), - (13, 814, 567, 566, 18446744073709551615, 1, 3), - (13, 815, 566, 564, 18446744073709551615, 1, 3), - (13, 816, 564, 563, 18446744073709551615, 2, 6), - (13, 817, 563, 565, 18446744073709551615, 1, 3), - (13, 818, 565, 563, 18446744073709551615, 1, 3), - (13, 819, 563, 564, 18446744073709551615, 1, 3), - (14, 128, 819, 563, 18446744073709551615, 0, 1), - (14, 128, 817, 563, 18446744073709551615, 0, 1), - (13, 689, 1006, 608, 18446744073709551615, 0, 1), - (13, 690, 239, 607, 18446744073709551615, 0, 1), - (13, 691, 1008, 606, 18446744073709551615, 0, 1), - (13, 692, 1009, 732, 18446744073709551615, 0, 1), - (13, 693, 242, 733, 18446744073709551615, 0, 1), - (13, 694, 1011, 605, 18446744073709551615, 0, 1), - (13, 695, 1012, 604, 18446744073709551615, 0, 1), - (13, 696, 245, 603, 18446744073709551615, 0, 1), - (13, 697, 1014, 602, 18446744073709551615, 0, 1), - (13, 698, 1015, 601, 18446744073709551615, 0, 1), - (13, 699, 248, 600, 18446744073709551615, 0, 1), - (13, 700, 1017, 599, 18446744073709551615, 0, 1), - (13, 701, 1018, 598, 18446744073709551615, 0, 1), - (13, 702, 251, 597, 18446744073709551615, 0, 1), - (13, 703, 1020, 596, 18446744073709551615, 0, 1), - (13, 704, 1021, 595, 18446744073709551615, 0, 1), - (13, 705, 254, 594, 18446744073709551615, 0, 1), - (13, 706, 1023, 593, 18446744073709551615, 0, 1), - (13, 707, 1049, 592, 18446744073709551615, 0, 1), - (13, 158, 687, 686, 18446744073709551615, 0, 4), - (13, 929, 685, 684, 18446744073709551615, 0, 2), - (13, 164, 681, 680, 18446744073709551615, 0, 2), - (13, 162, 680, 679, 18446744073709551615, 0, 2), - (13, 167, 679, 678, 18446744073709551615, 0, 2), - (13, 936, 678, 677, 18446744073709551615, 0, 2), - (13, 937, 677, 676, 18446744073709551615, 0, 2), - (13, 170, 676, 675, 18446744073709551615, 0, 2), - (13, 168, 675, 674, 18446744073709551615, 0, 2), - (13, 156, 674, 673, 18446744073709551615, 0, 2), - (13, 1082, 673, 672, 18446744073709551615, 0, 2), - (13, 942, 672, 671, 18446744073709551615, 0, 2), - (13, 943, 671, 670, 18446744073709551615, 0, 2), - (13, 176, 670, 669, 18446744073709551615, 0, 2), - (13, 945, 669, 668, 18446744073709551615, 0, 2), - (13, 946, 668, 667, 18446744073709551615, 0, 2), - (13, 179, 667, 666, 18446744073709551615, 0, 2), - (13, 948, 666, 665, 18446744073709551615, 0, 2), - (13, 949, 665, 664, 18446744073709551615, 0, 2), - (13, 182, 664, 663, 18446744073709551615, 0, 2), - (13, 951, 663, 662, 18446744073709551615, 0, 2), - (13, 952, 662, 661, 18446744073709551615, 0, 2), - (13, 185, 661, 660, 18446744073709551615, 0, 2), - (13, 954, 660, 659, 18446744073709551615, 0, 2), - (13, 955, 659, 658, 18446744073709551615, 0, 2), - (13, 188, 658, 657, 18446744073709551615, 0, 2), - (13, 957, 657, 656, 18446744073709551615, 0, 2), - (13, 958, 656, 655, 18446744073709551615, 0, 2), - (13, 191, 655, 654, 18446744073709551615, 0, 2), - (13, 960, 654, 653, 18446744073709551615, 0, 2), - (13, 961, 653, 652, 18446744073709551615, 0, 2), - (13, 194, 652, 651, 18446744073709551615, 0, 2), - (13, 963, 651, 650, 18446744073709551615, 0, 2), - (13, 964, 650, 649, 18446744073709551615, 0, 2), - (13, 197, 649, 648, 18446744073709551615, 0, 2), - (13, 966, 648, 647, 18446744073709551615, 0, 2), - (13, 967, 647, 646, 18446744073709551615, 0, 2), - (13, 200, 646, 645, 18446744073709551615, 0, 2), - (13, 969, 645, 644, 18446744073709551615, 0, 2), - (13, 970, 644, 643, 18446744073709551615, 0, 2), - (13, 203, 643, 642, 18446744073709551615, 0, 2), - (13, 972, 642, 641, 18446744073709551615, 0, 2), - (13, 973, 641, 640, 18446744073709551615, 0, 2), - (13, 206, 640, 639, 18446744073709551615, 0, 2), - (13, 975, 639, 638, 18446744073709551615, 0, 2), - (13, 976, 638, 637, 18446744073709551615, 0, 2), - (13, 209, 637, 636, 18446744073709551615, 0, 2), - (13, 978, 636, 635, 18446744073709551615, 0, 2), - (13, 979, 635, 634, 18446744073709551615, 0, 2), - (13, 212, 634, 633, 18446744073709551615, 0, 2), - (13, 981, 633, 632, 18446744073709551615, 0, 2), - (13, 982, 632, 631, 18446744073709551615, 0, 2), - (13, 215, 631, 630, 18446744073709551615, 0, 2), - (13, 984, 630, 629, 18446744073709551615, 0, 2), - (13, 985, 629, 628, 18446744073709551615, 0, 2), - (13, 218, 628, 627, 18446744073709551615, 0, 2), - (13, 987, 627, 626, 18446744073709551615, 0, 2), - (13, 988, 626, 625, 18446744073709551615, 0, 2), - (13, 221, 625, 624, 18446744073709551615, 0, 2), - (13, 990, 624, 623, 18446744073709551615, 0, 2), - (13, 991, 623, 622, 18446744073709551615, 0, 2), - (13, 224, 622, 621, 18446744073709551615, 0, 2), - (13, 993, 621, 620, 18446744073709551615, 0, 2), - (13, 994, 620, 619, 18446744073709551615, 0, 2), - (13, 227, 619, 618, 18446744073709551615, 0, 2), - (13, 996, 618, 617, 18446744073709551615, 0, 2), - (13, 997, 617, 616, 18446744073709551615, 0, 2), - (13, 230, 616, 615, 18446744073709551615, 0, 2), - (13, 999, 615, 614, 18446744073709551615, 0, 2), - (13, 1000, 614, 708, 18446744073709551615, 0, 2), - (13, 233, 708, 709, 18446744073709551615, 2, 4), - (13, 1002, 709, 710, 18446744073709551615, 2, 4), - (13, 1003, 710, 711, 18446744073709551615, 2, 4), - (13, 236, 711, 712, 18446744073709551615, 2, 4), - (13, 1005, 712, 713, 18446744073709551615, 2, 4), - (13, 1006, 713, 714, 18446744073709551615, 2, 4), - (13, 239, 714, 715, 18446744073709551615, 2, 4), - (13, 1008, 715, 716, 18446744073709551615, 2, 4), - (13, 1009, 716, 717, 18446744073709551615, 2, 4), - (13, 242, 717, 718, 18446744073709551615, 2, 4), - (13, 1011, 718, 719, 18446744073709551615, 2, 4), - (13, 1012, 719, 720, 18446744073709551615, 2, 4), - (13, 245, 720, 721, 18446744073709551615, 2, 4), - (13, 1014, 721, 722, 18446744073709551615, 2, 4), - (13, 1015, 722, 723, 18446744073709551615, 2, 4), - (13, 248, 723, 724, 18446744073709551615, 2, 4), - (13, 1017, 724, 725, 18446744073709551615, 2, 4), - (13, 1018, 725, 726, 18446744073709551615, 2, 4), - (13, 251, 726, 727, 18446744073709551615, 2, 4), - (13, 1020, 727, 728, 18446744073709551615, 2, 4), - (13, 1021, 728, 729, 18446744073709551615, 2, 4), - (13, 254, 729, 613, 18446744073709551615, 0, 2), - (13, 1023, 613, 612, 18446744073709551615, 0, 2), - (13, 612, 1049, 611, 18446744073709551615, 0, 1), - (13, 1023, 613, 612, 18446744073709551615, 1, 2), - (13, 254, 729, 613, 18446744073709551615, 1, 2), - (13, 1021, 728, 729, 18446744073709551615, 3, 4), - (13, 1020, 727, 728, 18446744073709551615, 3, 4), - (13, 251, 726, 727, 18446744073709551615, 3, 4), - (13, 1018, 725, 726, 18446744073709551615, 3, 4), - (13, 1017, 724, 725, 18446744073709551615, 3, 4), - (13, 248, 723, 724, 18446744073709551615, 3, 4), - (13, 1015, 722, 723, 18446744073709551615, 3, 4), - (13, 1014, 721, 722, 18446744073709551615, 3, 4), - (13, 245, 720, 721, 18446744073709551615, 3, 4), - (13, 1012, 719, 720, 18446744073709551615, 3, 4), - (13, 1011, 718, 719, 18446744073709551615, 3, 4), - (13, 242, 717, 718, 18446744073709551615, 3, 4), - (13, 1009, 716, 717, 18446744073709551615, 3, 4), - (13, 1008, 715, 716, 18446744073709551615, 3, 4), - (13, 239, 714, 715, 18446744073709551615, 3, 4), - (13, 1006, 713, 714, 18446744073709551615, 3, 4), - (13, 1005, 712, 713, 18446744073709551615, 3, 4), - (13, 236, 711, 712, 18446744073709551615, 3, 4), - (13, 1003, 710, 711, 18446744073709551615, 3, 4), - (13, 1002, 709, 710, 18446744073709551615, 3, 4), - (13, 233, 708, 709, 18446744073709551615, 3, 4), - (13, 1000, 614, 708, 18446744073709551615, 1, 2), - (13, 999, 615, 614, 18446744073709551615, 1, 2), - (13, 230, 616, 615, 18446744073709551615, 1, 2), - (13, 997, 617, 616, 18446744073709551615, 1, 2), - (13, 996, 618, 617, 18446744073709551615, 1, 2), - (13, 227, 619, 618, 18446744073709551615, 1, 2), - (13, 994, 620, 619, 18446744073709551615, 1, 2), - (13, 993, 621, 620, 18446744073709551615, 1, 2), - (13, 224, 622, 621, 18446744073709551615, 1, 2), - (13, 991, 623, 622, 18446744073709551615, 1, 2), - (13, 990, 624, 623, 18446744073709551615, 1, 2), - (13, 221, 625, 624, 18446744073709551615, 1, 2), - (13, 988, 626, 625, 18446744073709551615, 1, 2), - (13, 987, 627, 626, 18446744073709551615, 1, 2), - (13, 218, 628, 627, 18446744073709551615, 1, 2), - (13, 985, 629, 628, 18446744073709551615, 1, 2), - (13, 984, 630, 629, 18446744073709551615, 1, 2), - (13, 215, 631, 630, 18446744073709551615, 1, 2), - (13, 982, 632, 631, 18446744073709551615, 1, 2), - (13, 981, 633, 632, 18446744073709551615, 1, 2), - (13, 212, 634, 633, 18446744073709551615, 1, 2), - (13, 979, 635, 634, 18446744073709551615, 1, 2), - (13, 978, 636, 635, 18446744073709551615, 1, 2), - (13, 209, 637, 636, 18446744073709551615, 1, 2), - (13, 976, 638, 637, 18446744073709551615, 1, 2), - (13, 975, 639, 638, 18446744073709551615, 1, 2), - (13, 206, 640, 639, 18446744073709551615, 1, 2), - (13, 973, 641, 640, 18446744073709551615, 1, 2), - (13, 972, 642, 641, 18446744073709551615, 1, 2), - (13, 203, 643, 642, 18446744073709551615, 1, 2), - (13, 970, 644, 643, 18446744073709551615, 1, 2), - (13, 969, 645, 644, 18446744073709551615, 1, 2), - (13, 200, 646, 645, 18446744073709551615, 1, 2), - (13, 967, 647, 646, 18446744073709551615, 1, 2), - (13, 966, 648, 647, 18446744073709551615, 1, 2), - (13, 197, 649, 648, 18446744073709551615, 1, 2), - (13, 964, 650, 649, 18446744073709551615, 1, 2), - (13, 963, 651, 650, 18446744073709551615, 1, 2), - (13, 194, 652, 651, 18446744073709551615, 1, 2), - (13, 961, 653, 652, 18446744073709551615, 1, 2), - (13, 960, 654, 653, 18446744073709551615, 1, 2), - (13, 191, 655, 654, 18446744073709551615, 1, 2), - (13, 958, 656, 655, 18446744073709551615, 1, 2), - (13, 957, 657, 656, 18446744073709551615, 1, 2), - (13, 188, 658, 657, 18446744073709551615, 1, 2), - (13, 955, 659, 658, 18446744073709551615, 1, 2), - (13, 954, 660, 659, 18446744073709551615, 1, 2), - (13, 185, 661, 660, 18446744073709551615, 1, 2), - (13, 952, 662, 661, 18446744073709551615, 1, 2), - (13, 951, 663, 662, 18446744073709551615, 1, 2), - (13, 182, 664, 663, 18446744073709551615, 1, 2), - (13, 949, 665, 664, 18446744073709551615, 1, 2), - (13, 948, 666, 665, 18446744073709551615, 1, 2), - (13, 179, 667, 666, 18446744073709551615, 1, 2), - (13, 946, 668, 667, 18446744073709551615, 1, 2), - (13, 945, 669, 668, 18446744073709551615, 1, 2), - (13, 176, 670, 669, 18446744073709551615, 1, 2), - (13, 943, 671, 670, 18446744073709551615, 1, 2), - (13, 942, 672, 671, 18446744073709551615, 1, 2), - (13, 1082, 673, 672, 18446744073709551615, 1, 2), - (13, 156, 674, 673, 18446744073709551615, 1, 2), - (13, 168, 675, 674, 18446744073709551615, 1, 2), - (13, 170, 676, 675, 18446744073709551615, 1, 2), - (13, 937, 677, 676, 18446744073709551615, 1, 2), - (13, 936, 678, 677, 18446744073709551615, 1, 2), - (13, 167, 679, 678, 18446744073709551615, 1, 2), - (13, 162, 680, 679, 18446744073709551615, 1, 2), - (13, 164, 681, 680, 18446744073709551615, 1, 2), - (13, 929, 685, 684, 18446744073709551615, 1, 2), - (13, 158, 687, 686, 18446744073709551615, 1, 4), - (13, 611, 755, 610, 18446744073709551615, 0, 1), - (13, 754, 610, 730, 18446744073709551615, 0, 1), - (13, 753, 730, 731, 18446744073709551615, 0, 1), - (13, 752, 731, 128, 18446744073709551615, 0, 1), - (13, 751, 128, 1093, 18446744073709551615, 0, 1), - (13, 750, 1093, 609, 18446744073709551615, 0, 1), - (13, 749, 609, 608, 18446744073709551615, 1, 3), - (13, 748, 608, 607, 18446744073709551615, 1, 3), - (13, 747, 607, 606, 18446744073709551615, 1, 3), - (13, 14, 606, 732, 18446744073709551615, 1, 3), - (13, 11, 732, 733, 18446744073709551615, 1, 3), - (13, 777, 733, 605, 18446744073709551615, 1, 3), - (13, 13, 605, 604, 18446744073709551615, 1, 3), - (13, 1145, 604, 603, 18446744073709551615, 1, 3), - (13, 1137, 603, 602, 18446744073709551615, 1, 3), - (13, 17, 602, 601, 18446744073709551615, 1, 3), - (13, 1134, 601, 600, 18446744073709551615, 1, 3), - (13, 27, 600, 599, 18446744073709551615, 1, 3), - (13, 786, 599, 598, 18446744073709551615, 1, 3), - (13, 787, 598, 597, 18446744073709551615, 1, 3), - (13, 788, 597, 596, 18446744073709551615, 1, 3), - (13, 789, 596, 595, 18446744073709551615, 1, 3), - (13, 790, 595, 594, 18446744073709551615, 1, 3), - (13, 791, 594, 593, 18446744073709551615, 1, 3), - (13, 23, 593, 592, 18446744073709551615, 1, 3), - (13, 20, 592, 591, 18446744073709551615, 1, 3), - (13, 18, 591, 590, 18446744073709551615, 1, 3), - (13, 795, 590, 589, 18446744073709551615, 1, 3), - (13, 796, 589, 588, 18446744073709551615, 1, 3), - (13, 797, 588, 587, 18446744073709551615, 1, 3), - (13, 798, 587, 586, 18446744073709551615, 1, 3), - (13, 799, 586, 585, 18446744073709551615, 1, 3), - (13, 800, 585, 584, 18446744073709551615, 1, 3), - (13, 801, 584, 583, 18446744073709551615, 1, 3), - (13, 802, 583, 582, 18446744073709551615, 1, 3), - (13, 803, 582, 581, 18446744073709551615, 1, 3), - (13, 804, 581, 580, 18446744073709551615, 1, 3), - (13, 805, 580, 579, 18446744073709551615, 1, 3), - (13, 806, 579, 578, 18446744073709551615, 1, 3), - (13, 807, 578, 577, 18446744073709551615, 1, 3), - (13, 808, 577, 576, 18446744073709551615, 1, 3), - (13, 809, 576, 575, 18446744073709551615, 1, 3), - (13, 810, 575, 574, 18446744073709551615, 1, 3), - (13, 811, 574, 573, 18446744073709551615, 1, 3), - (13, 812, 573, 572, 18446744073709551615, 1, 3), - (13, 813, 572, 571, 18446744073709551615, 1, 3), - (13, 814, 571, 570, 18446744073709551615, 1, 3), - (13, 815, 570, 568, 18446744073709551615, 1, 3), - (13, 816, 568, 567, 18446744073709551615, 2, 6), - (13, 817, 567, 569, 18446744073709551615, 1, 3), - (13, 818, 569, 567, 18446744073709551615, 1, 3), - (13, 819, 567, 568, 18446744073709551615, 1, 3), - (14, 611, 819, 567, 18446744073709551615, 0, 1), - (14, 611, 817, 567, 18446744073709551615, 0, 1), - (13, 1006, 713, 730, 18446744073709551615, 0, 1), - (13, 239, 714, 731, 18446744073709551615, 0, 1), - (13, 1008, 715, 128, 18446744073709551615, 0, 1), - (13, 1009, 716, 1093, 18446744073709551615, 0, 1), - (13, 242, 717, 609, 18446744073709551615, 0, 1), - (13, 1011, 718, 608, 18446744073709551615, 0, 1), - (13, 1012, 719, 607, 18446744073709551615, 0, 1), - (13, 245, 720, 606, 18446744073709551615, 0, 1), - (13, 1014, 721, 732, 18446744073709551615, 0, 1), - (13, 1015, 722, 733, 18446744073709551615, 0, 1), - (13, 248, 723, 605, 18446744073709551615, 0, 1), - (13, 1017, 724, 604, 18446744073709551615, 0, 1), - (13, 1018, 725, 603, 18446744073709551615, 0, 1), - (13, 251, 726, 602, 18446744073709551615, 0, 1), - (13, 1020, 727, 601, 18446744073709551615, 0, 1), - (13, 1021, 728, 600, 18446744073709551615, 0, 1), - (13, 254, 729, 599, 18446744073709551615, 0, 1), - (13, 1023, 613, 598, 18446744073709551615, 0, 1), - (13, 1049, 612, 597, 18446744073709551615, 0, 1), - (13, 949, 711, 1139, 18446744073709551615, 0, 1), - (13, 952, 708, 1132, 18446744073709551615, 0, 1), - (13, 954, 615, 1141, 18446744073709551615, 0, 1), - (13, 955, 616, 10, 18446744073709551615, 0, 1), - (13, 188, 617, 793, 18446744073709551615, 0, 1), - (13, 957, 618, 9, 18446744073709551615, 0, 1), - (13, 958, 619, 1147, 18446744073709551615, 0, 1), - (13, 191, 620, 1153, 18446744073709551615, 0, 1), - (13, 960, 621, 622, 18446744073709551615, 0, 4), - (13, 961, 622, 623, 18446744073709551615, 0, 4), - (13, 194, 623, 624, 18446744073709551615, 0, 4), - (13, 963, 624, 625, 18446744073709551615, 0, 4), - (13, 964, 625, 626, 18446744073709551615, 0, 4), - (13, 197, 626, 627, 18446744073709551615, 0, 4), - (13, 966, 627, 628, 18446744073709551615, 0, 4), - (13, 967, 628, 629, 18446744073709551615, 0, 4), - (13, 200, 629, 630, 18446744073709551615, 0, 4), - (13, 969, 630, 631, 18446744073709551615, 0, 4), - (13, 970, 631, 632, 18446744073709551615, 0, 4), - (13, 203, 632, 633, 18446744073709551615, 0, 4), - (13, 972, 633, 634, 18446744073709551615, 0, 4), - (13, 973, 634, 635, 18446744073709551615, 0, 4), - (13, 206, 635, 636, 18446744073709551615, 0, 4), - (13, 975, 636, 637, 18446744073709551615, 0, 4), - (13, 976, 637, 638, 18446744073709551615, 0, 4), - (13, 209, 638, 639, 18446744073709551615, 0, 4), - (13, 978, 639, 640, 18446744073709551615, 0, 4), - (13, 979, 640, 641, 18446744073709551615, 0, 4), - (13, 212, 641, 642, 18446744073709551615, 0, 4), - (13, 981, 642, 643, 18446744073709551615, 0, 4), - (13, 982, 643, 644, 18446744073709551615, 0, 4), - (13, 215, 644, 645, 18446744073709551615, 0, 4), - (13, 984, 645, 646, 18446744073709551615, 0, 4), - (13, 985, 646, 647, 18446744073709551615, 0, 4), - (13, 218, 647, 648, 18446744073709551615, 0, 4), - (13, 987, 648, 649, 18446744073709551615, 0, 4), - (13, 988, 649, 650, 18446744073709551615, 0, 4), - (13, 221, 650, 651, 18446744073709551615, 0, 4), - (13, 990, 651, 652, 18446744073709551615, 0, 4), - (13, 991, 652, 653, 18446744073709551615, 0, 4), - (13, 224, 653, 654, 18446744073709551615, 0, 4), - (13, 993, 654, 655, 18446744073709551615, 0, 4), - (13, 994, 655, 656, 18446744073709551615, 0, 4), - (13, 227, 656, 657, 18446744073709551615, 0, 4), - (13, 996, 657, 658, 18446744073709551615, 0, 4), - (13, 997, 658, 659, 18446744073709551615, 0, 4), - (13, 230, 659, 660, 18446744073709551615, 0, 4), - (13, 999, 660, 661, 18446744073709551615, 0, 4), - (13, 1000, 661, 662, 18446744073709551615, 0, 4), - (13, 233, 662, 663, 18446744073709551615, 0, 4), - (13, 1002, 663, 664, 18446744073709551615, 0, 4), - (13, 1003, 664, 665, 18446744073709551615, 0, 4), - (13, 236, 665, 666, 18446744073709551615, 0, 4), - (13, 1005, 666, 667, 18446744073709551615, 0, 4), - (13, 1006, 667, 668, 18446744073709551615, 0, 4), - (13, 239, 668, 669, 18446744073709551615, 0, 4), - (13, 1008, 669, 670, 18446744073709551615, 0, 4), - (13, 1009, 670, 671, 18446744073709551615, 0, 4), - (13, 242, 671, 672, 18446744073709551615, 0, 4), - (13, 1011, 672, 673, 18446744073709551615, 0, 4), - (13, 1012, 673, 674, 18446744073709551615, 0, 4), - (13, 245, 674, 675, 18446744073709551615, 0, 4), - (13, 1014, 675, 676, 18446744073709551615, 0, 4), - (13, 1015, 676, 677, 18446744073709551615, 0, 4), - (13, 248, 677, 678, 18446744073709551615, 0, 4), - (13, 1017, 678, 679, 18446744073709551615, 0, 4), - (13, 1018, 679, 680, 18446744073709551615, 0, 4), - (13, 251, 680, 681, 18446744073709551615, 0, 4), - (13, 1020, 681, 682, 18446744073709551615, 0, 4), - (13, 1021, 682, 683, 18446744073709551615, 0, 4), - (13, 254, 683, 684, 18446744073709551615, 0, 4), - (13, 1023, 684, 685, 18446744073709551615, 0, 4), - (13, 685, 1049, 686, 18446744073709551615, 0, 1), - (13, 1023, 684, 685, 18446744073709551615, 1, 4), - (13, 254, 683, 684, 18446744073709551615, 1, 4), - (13, 1021, 682, 683, 18446744073709551615, 1, 4), - (13, 1020, 681, 682, 18446744073709551615, 1, 4), - (13, 251, 680, 681, 18446744073709551615, 1, 4), - (13, 1018, 679, 680, 18446744073709551615, 1, 4), - (13, 1017, 678, 679, 18446744073709551615, 1, 4), - (13, 248, 677, 678, 18446744073709551615, 1, 4), - (13, 1015, 676, 677, 18446744073709551615, 1, 4), - (13, 1014, 675, 676, 18446744073709551615, 1, 4), - (13, 245, 674, 675, 18446744073709551615, 1, 4), - (13, 1012, 673, 674, 18446744073709551615, 1, 4), - (13, 1011, 672, 673, 18446744073709551615, 1, 4), - (13, 242, 671, 672, 18446744073709551615, 1, 4), - (13, 1009, 670, 671, 18446744073709551615, 1, 4), - (13, 1008, 669, 670, 18446744073709551615, 1, 4), - (13, 239, 668, 669, 18446744073709551615, 1, 4), - (13, 1006, 667, 668, 18446744073709551615, 1, 4), - (13, 1005, 666, 667, 18446744073709551615, 1, 4), - (13, 236, 665, 666, 18446744073709551615, 1, 4), - (13, 1003, 664, 665, 18446744073709551615, 1, 4), - (13, 1002, 663, 664, 18446744073709551615, 1, 4), - (13, 233, 662, 663, 18446744073709551615, 1, 4), - (13, 1000, 661, 662, 18446744073709551615, 1, 4), - (13, 999, 660, 661, 18446744073709551615, 1, 4), - (13, 230, 659, 660, 18446744073709551615, 1, 4), - (13, 997, 658, 659, 18446744073709551615, 1, 4), - (13, 996, 657, 658, 18446744073709551615, 1, 4), - (13, 227, 656, 657, 18446744073709551615, 1, 4), - (13, 994, 655, 656, 18446744073709551615, 1, 4), - (13, 993, 654, 655, 18446744073709551615, 1, 4), - (13, 224, 653, 654, 18446744073709551615, 1, 4), - (13, 991, 652, 653, 18446744073709551615, 1, 4), - (13, 990, 651, 652, 18446744073709551615, 1, 4), - (13, 221, 650, 651, 18446744073709551615, 1, 4), - (13, 988, 649, 650, 18446744073709551615, 1, 4), - (13, 987, 648, 649, 18446744073709551615, 1, 4), - (13, 218, 647, 648, 18446744073709551615, 1, 4), - (13, 985, 646, 647, 18446744073709551615, 1, 4), - (13, 984, 645, 646, 18446744073709551615, 1, 4), - (13, 215, 644, 645, 18446744073709551615, 1, 4), - (13, 982, 643, 644, 18446744073709551615, 1, 4), - (13, 981, 642, 643, 18446744073709551615, 1, 4), - (13, 212, 641, 642, 18446744073709551615, 1, 4), - (13, 979, 640, 641, 18446744073709551615, 1, 4), - (13, 978, 639, 640, 18446744073709551615, 1, 4), - (13, 209, 638, 639, 18446744073709551615, 1, 4), - (13, 976, 637, 638, 18446744073709551615, 1, 4), - (13, 975, 636, 637, 18446744073709551615, 1, 4), - (13, 206, 635, 636, 18446744073709551615, 1, 4), - (13, 973, 634, 635, 18446744073709551615, 1, 4), - (13, 972, 633, 634, 18446744073709551615, 1, 4), - (13, 203, 632, 633, 18446744073709551615, 1, 4), - (13, 970, 631, 632, 18446744073709551615, 1, 4), - (13, 969, 630, 631, 18446744073709551615, 1, 4), - (13, 200, 629, 630, 18446744073709551615, 1, 4), - (13, 967, 628, 629, 18446744073709551615, 1, 4), - (13, 966, 627, 628, 18446744073709551615, 1, 4), - (13, 197, 626, 627, 18446744073709551615, 1, 4), - (13, 964, 625, 626, 18446744073709551615, 1, 4), - (13, 963, 624, 625, 18446744073709551615, 1, 4), - (13, 194, 623, 624, 18446744073709551615, 1, 4), - (13, 961, 622, 623, 18446744073709551615, 1, 4), - (13, 960, 621, 622, 18446744073709551615, 1, 4), - (13, 686, 755, 687, 18446744073709551615, 0, 1), - (13, 754, 687, 688, 18446744073709551615, 0, 1), - (13, 753, 688, 689, 18446744073709551615, 0, 1), - (13, 752, 689, 690, 18446744073709551615, 0, 1), - (13, 751, 690, 691, 18446744073709551615, 0, 1), - (13, 750, 691, 692, 18446744073709551615, 0, 1), - (13, 749, 692, 693, 18446744073709551615, 0, 1), - (13, 748, 693, 694, 18446744073709551615, 0, 1), - (13, 747, 694, 695, 18446744073709551615, 0, 1), - (13, 14, 695, 696, 18446744073709551615, 0, 1), - (13, 11, 696, 697, 18446744073709551615, 0, 1), - (13, 777, 697, 698, 18446744073709551615, 0, 1), - (13, 13, 698, 699, 18446744073709551615, 0, 1), - (13, 1145, 699, 700, 18446744073709551615, 0, 1), - (13, 1137, 700, 701, 18446744073709551615, 0, 1), - (13, 17, 701, 702, 18446744073709551615, 0, 1), - (13, 1134, 702, 703, 18446744073709551615, 0, 1), - (13, 27, 703, 704, 18446744073709551615, 0, 1), - (13, 786, 704, 705, 18446744073709551615, 0, 1), - (13, 787, 705, 706, 18446744073709551615, 0, 1), - (13, 788, 706, 707, 18446744073709551615, 0, 1), - (13, 789, 707, 611, 18446744073709551615, 0, 1), - (13, 790, 611, 610, 18446744073709551615, 0, 1), - (13, 791, 610, 730, 18446744073709551615, 0, 1), - (13, 23, 730, 731, 18446744073709551615, 0, 1), - (13, 20, 731, 128, 18446744073709551615, 0, 1), - (13, 18, 128, 1093, 18446744073709551615, 0, 1), - (13, 795, 1093, 609, 18446744073709551615, 0, 1), - (13, 796, 609, 608, 18446744073709551615, 1, 3), - (13, 797, 608, 607, 18446744073709551615, 1, 3), - (13, 798, 607, 606, 18446744073709551615, 1, 3), - (13, 799, 606, 732, 18446744073709551615, 1, 3), - (13, 800, 732, 733, 18446744073709551615, 1, 3), - (13, 801, 733, 605, 18446744073709551615, 1, 3), - (13, 802, 605, 604, 18446744073709551615, 1, 3), - (13, 803, 604, 603, 18446744073709551615, 1, 3), - (13, 804, 603, 602, 18446744073709551615, 1, 3), - (13, 805, 602, 601, 18446744073709551615, 1, 3), - (13, 806, 601, 600, 18446744073709551615, 1, 3), - (13, 807, 600, 599, 18446744073709551615, 1, 3), - (13, 808, 599, 598, 18446744073709551615, 1, 3), - (13, 809, 598, 597, 18446744073709551615, 1, 3), - (13, 810, 597, 596, 18446744073709551615, 1, 3), - (13, 811, 596, 595, 18446744073709551615, 1, 3), - (13, 812, 595, 594, 18446744073709551615, 1, 3), - (13, 813, 594, 593, 18446744073709551615, 1, 3), - (13, 814, 593, 592, 18446744073709551615, 1, 3), - (13, 815, 592, 590, 18446744073709551615, 1, 3), - (13, 816, 590, 589, 18446744073709551615, 2, 6), - (13, 817, 589, 591, 18446744073709551615, 1, 3), - (13, 818, 591, 589, 18446744073709551615, 1, 3), - (13, 819, 589, 590, 18446744073709551615, 1, 3), - (14, 686, 819, 589, 18446744073709551615, 0, 1), - (14, 686, 817, 589, 18446744073709551615, 0, 1), - (13, 1006, 667, 688, 18446744073709551615, 0, 1), - (13, 239, 668, 689, 18446744073709551615, 0, 1), - (13, 1008, 669, 690, 18446744073709551615, 0, 1), - (13, 1009, 670, 691, 18446744073709551615, 0, 1), - (13, 242, 671, 692, 18446744073709551615, 0, 1), - (13, 1011, 672, 693, 18446744073709551615, 0, 1), - (13, 1012, 673, 694, 18446744073709551615, 0, 1), - (13, 245, 674, 695, 18446744073709551615, 0, 1), - (13, 1014, 675, 696, 18446744073709551615, 0, 1), - (13, 1015, 676, 697, 18446744073709551615, 0, 1), - (13, 248, 677, 698, 18446744073709551615, 0, 1), - (13, 1017, 678, 699, 18446744073709551615, 0, 1), - (13, 1018, 679, 700, 18446744073709551615, 0, 1), - (13, 251, 680, 701, 18446744073709551615, 0, 1), - (13, 1020, 681, 702, 18446744073709551615, 0, 1), - (13, 1021, 682, 703, 18446744073709551615, 0, 1), - (13, 254, 683, 704, 18446744073709551615, 0, 1), - (13, 1023, 684, 705, 18446744073709551615, 0, 1), - (13, 1049, 685, 706, 18446744073709551615, 0, 1), - (13, 732, 734, 256, 18446744073709551615, 0, 2), - (13, 666, 238, 665, 18446744073709551615, 0, 1), - (13, 663, 235, 662, 18446744073709551615, 0, 1), - (13, 662, 1007, 661, 18446744073709551615, 0, 1), - (13, 658, 1062, 657, 18446744073709551615, 0, 1), - (13, 656, 1001, 655, 18446744073709551615, 0, 1), - (13, 655, 1063, 654, 18446744073709551615, 0, 1), - (13, 654, 226, 653, 18446744073709551615, 0, 1), - (13, 653, 998, 652, 18446744073709551615, 0, 1), - (13, 652, 1064, 651, 18446744073709551615, 0, 1), - (13, 651, 223, 650, 18446744073709551615, 0, 1), - (13, 650, 995, 649, 18446744073709551615, 0, 1), - (13, 649, 1065, 648, 18446744073709551615, 0, 1), - (13, 648, 220, 647, 18446744073709551615, 0, 1), - (13, 647, 992, 646, 18446744073709551615, 0, 1), - (13, 646, 1066, 645, 18446744073709551615, 0, 1), - (13, 645, 217, 644, 18446744073709551615, 0, 1), - (13, 644, 989, 643, 18446744073709551615, 0, 1), - (13, 643, 1067, 642, 18446744073709551615, 0, 1), - (13, 642, 214, 641, 18446744073709551615, 0, 1), - (13, 641, 986, 640, 18446744073709551615, 0, 1), - (13, 640, 1068, 639, 18446744073709551615, 0, 1), - (13, 639, 211, 638, 18446744073709551615, 0, 1), - (13, 638, 983, 637, 18446744073709551615, 0, 1), - (13, 637, 1069, 636, 18446744073709551615, 0, 1), - (13, 636, 208, 635, 18446744073709551615, 0, 1), - (13, 635, 980, 634, 18446744073709551615, 0, 1), - (13, 634, 1070, 633, 18446744073709551615, 0, 1), - (13, 633, 205, 632, 18446744073709551615, 0, 1), - (13, 632, 977, 631, 18446744073709551615, 0, 1), - (13, 631, 1071, 630, 18446744073709551615, 0, 1), - (13, 630, 202, 629, 18446744073709551615, 0, 1), - (13, 629, 974, 628, 18446744073709551615, 0, 1), - (13, 628, 1072, 627, 18446744073709551615, 0, 1), - (13, 627, 199, 626, 18446744073709551615, 0, 1), - (13, 626, 971, 625, 18446744073709551615, 0, 1), - (13, 625, 1073, 624, 18446744073709551615, 0, 1), - (13, 624, 196, 623, 18446744073709551615, 0, 1), - (13, 623, 968, 622, 18446744073709551615, 0, 1), - (13, 622, 1074, 621, 18446744073709551615, 0, 1), - (13, 621, 193, 620, 18446744073709551615, 0, 1), - (13, 620, 965, 619, 18446744073709551615, 0, 1), - (13, 619, 1075, 618, 18446744073709551615, 0, 1), - (13, 618, 190, 617, 18446744073709551615, 0, 1), - (13, 617, 962, 616, 18446744073709551615, 0, 1), - (13, 616, 1076, 615, 18446744073709551615, 0, 1), - (13, 615, 187, 614, 18446744073709551615, 0, 1), - (13, 614, 959, 708, 18446744073709551615, 0, 1), - (13, 708, 1077, 709, 18446744073709551615, 0, 1), - (13, 709, 184, 710, 18446744073709551615, 0, 1), - (13, 710, 956, 711, 18446744073709551615, 0, 1), - (13, 711, 1078, 712, 18446744073709551615, 0, 1), - (13, 712, 181, 713, 18446744073709551615, 0, 1), - (13, 713, 953, 714, 18446744073709551615, 0, 1), - (13, 714, 1079, 715, 18446744073709551615, 0, 1), - (13, 715, 178, 716, 18446744073709551615, 0, 1), - (13, 716, 950, 717, 18446744073709551615, 0, 1), - (13, 717, 1080, 718, 18446744073709551615, 0, 1), - (13, 718, 175, 719, 18446744073709551615, 0, 1), - (13, 719, 947, 720, 18446744073709551615, 0, 1), - (13, 720, 1081, 721, 18446744073709551615, 0, 1), - (13, 721, 941, 722, 18446744073709551615, 0, 1), - (13, 722, 944, 723, 18446744073709551615, 0, 1), - (13, 723, 169, 724, 18446744073709551615, 0, 1), - (13, 724, 938, 725, 18446744073709551615, 0, 1), - (13, 725, 939, 726, 18446744073709551615, 0, 1), - (13, 726, 1084, 727, 18446744073709551615, 0, 1), - (13, 727, 166, 728, 18446744073709551615, 0, 1), - (13, 728, 171, 729, 18446744073709551615, 0, 1), - (13, 729, 940, 613, 18446744073709551615, 0, 1), - (13, 613, 932, 612, 18446744073709551615, 0, 1), - (13, 612, 163, 686, 18446744073709551615, 0, 1), - (13, 686, 930, 687, 18446744073709551615, 0, 1), - (13, 687, 931, 688, 18446744073709551615, 0, 1), - (13, 688, 934, 689, 18446744073709551615, 0, 1), - (13, 689, 1085, 690, 18446744073709551615, 0, 1), - (13, 690, 926, 691, 18446744073709551615, 0, 1), - (13, 691, 927, 692, 18446744073709551615, 0, 1), - (13, 692, 928, 693, 18446744073709551615, 0, 1), - (13, 693, 923, 694, 18446744073709551615, 0, 1), - (13, 694, 924, 695, 18446744073709551615, 0, 1), - (13, 695, 925, 696, 18446744073709551615, 0, 1), - (13, 696, 1086, 697, 18446744073709551615, 0, 1), - (13, 697, 150, 698, 18446744073709551615, 0, 1), - (13, 698, 922, 699, 18446744073709551615, 0, 1), - (13, 699, 1087, 700, 18446744073709551615, 0, 1), - (13, 700, 146, 701, 18446744073709551615, 0, 1), - (13, 701, 915, 702, 18446744073709551615, 0, 1), - (13, 702, 916, 703, 18446744073709551615, 0, 1), - (13, 703, 1088, 704, 18446744073709551615, 0, 1), - (13, 704, 143, 705, 18446744073709551615, 0, 1), - (13, 705, 148, 706, 18446744073709551615, 0, 1), - (13, 706, 917, 707, 18446744073709551615, 0, 1), - (13, 707, 1090, 611, 18446744073709551615, 0, 1), - (13, 611, 1089, 610, 18446744073709551615, 0, 1), - (13, 610, 907, 730, 18446744073709551615, 0, 1), - (13, 730, 138, 731, 18446744073709551615, 0, 1), - (13, 731, 908, 128, 18446744073709551615, 0, 1), - (13, 128, 135, 1093, 18446744073709551615, 0, 1), - (13, 1093, 909, 609, 18446744073709551615, 0, 1), - (13, 609, 1092, 608, 18446744073709551615, 0, 1), - (13, 608, 132, 607, 18446744073709551615, 0, 1), - (13, 732, 734, 256, 18446744073709551615, 1, 2), - (13, 382, 132, 685, 18446744073709551615, 0, 1), - (13, 382, 926, 904, 18446744073709551615, 1, 2), - (13, 382, 1085, 904, 18446744073709551615, 1, 2), - (13, 382, 934, 904, 18446744073709551615, 1, 2), - (13, 382, 931, 904, 18446744073709551615, 1, 2), - (13, 382, 930, 904, 18446744073709551615, 1, 2), - (13, 382, 163, 904, 18446744073709551615, 1, 2), - (13, 382, 932, 904, 18446744073709551615, 1, 2), - (13, 382, 940, 904, 18446744073709551615, 1, 2), - (13, 382, 171, 904, 18446744073709551615, 1, 2), - (13, 382, 166, 904, 18446744073709551615, 1, 2), - (13, 382, 1084, 904, 18446744073709551615, 1, 2), - (13, 382, 939, 904, 18446744073709551615, 1, 2), - (13, 382, 938, 904, 18446744073709551615, 1, 2), - (13, 382, 169, 904, 18446744073709551615, 1, 2), - (13, 382, 944, 904, 18446744073709551615, 1, 2), - (13, 382, 941, 904, 18446744073709551615, 1, 2), - (13, 382, 1081, 904, 18446744073709551615, 1, 2), - (13, 382, 947, 904, 18446744073709551615, 1, 2), - (13, 382, 175, 904, 18446744073709551615, 1, 2), - (13, 382, 1080, 904, 18446744073709551615, 1, 2), - (13, 382, 950, 904, 18446744073709551615, 1, 2), - (13, 382, 178, 904, 18446744073709551615, 1, 2), - (13, 382, 1079, 904, 18446744073709551615, 1, 2), - (13, 382, 953, 904, 18446744073709551615, 1, 2), - (13, 382, 181, 904, 18446744073709551615, 1, 2), - (13, 382, 1078, 904, 18446744073709551615, 1, 2), - (13, 382, 956, 904, 18446744073709551615, 1, 2), - (13, 382, 184, 904, 18446744073709551615, 1, 2), - (13, 382, 1077, 904, 18446744073709551615, 1, 2), - (13, 382, 959, 904, 18446744073709551615, 1, 2), - (13, 382, 187, 904, 18446744073709551615, 1, 2), - (13, 382, 1076, 904, 18446744073709551615, 1, 2), - (13, 382, 962, 904, 18446744073709551615, 1, 2), - (13, 382, 190, 904, 18446744073709551615, 1, 2), - (13, 382, 1075, 904, 18446744073709551615, 1, 2), - (13, 382, 965, 904, 18446744073709551615, 1, 2), - (13, 382, 193, 904, 18446744073709551615, 1, 2), - (13, 382, 1074, 904, 18446744073709551615, 1, 2), - (13, 382, 968, 904, 18446744073709551615, 1, 2), - (13, 382, 196, 904, 18446744073709551615, 1, 2), - (13, 382, 1073, 904, 18446744073709551615, 1, 2), - (13, 382, 971, 904, 18446744073709551615, 1, 2), - (13, 382, 199, 904, 18446744073709551615, 1, 2), - (13, 382, 1072, 904, 18446744073709551615, 1, 2), - (13, 382, 974, 904, 18446744073709551615, 1, 2), - (13, 382, 202, 904, 18446744073709551615, 1, 2), - (13, 382, 1071, 904, 18446744073709551615, 1, 2), - (13, 382, 977, 904, 18446744073709551615, 1, 2), - (13, 382, 205, 904, 18446744073709551615, 1, 2), - (13, 382, 1070, 904, 18446744073709551615, 1, 2), - (13, 382, 980, 904, 18446744073709551615, 1, 2), - (13, 382, 208, 904, 18446744073709551615, 1, 2), - (13, 382, 1069, 904, 18446744073709551615, 1, 2), - (13, 382, 983, 904, 18446744073709551615, 1, 2), - (13, 382, 211, 904, 18446744073709551615, 1, 2), - (13, 382, 1068, 904, 18446744073709551615, 1, 2), - (13, 382, 986, 904, 18446744073709551615, 1, 2), - (13, 382, 214, 904, 18446744073709551615, 1, 2), - (13, 382, 1067, 904, 18446744073709551615, 1, 2), - (13, 382, 989, 904, 18446744073709551615, 1, 2), - (13, 382, 217, 904, 18446744073709551615, 1, 2), - (13, 382, 1066, 904, 18446744073709551615, 1, 2), - (13, 382, 992, 904, 18446744073709551615, 1, 2), - (13, 382, 220, 904, 18446744073709551615, 1, 2), - (13, 382, 1065, 904, 18446744073709551615, 1, 2), - (13, 382, 995, 904, 18446744073709551615, 1, 2), - (13, 382, 223, 904, 18446744073709551615, 1, 2), - (13, 382, 1064, 904, 18446744073709551615, 1, 2), - (13, 382, 998, 904, 18446744073709551615, 1, 2), - (13, 382, 226, 904, 18446744073709551615, 1, 2), - (13, 382, 1063, 904, 18446744073709551615, 1, 2), - (13, 382, 1001, 904, 18446744073709551615, 1, 2), - (13, 382, 229, 904, 18446744073709551615, 1, 2), - (13, 382, 1062, 904, 18446744073709551615, 1, 2), - (13, 382, 1004, 904, 18446744073709551615, 1, 2), - (13, 382, 232, 904, 18446744073709551615, 1, 2), - (13, 382, 1061, 904, 18446744073709551615, 1, 2), - (13, 382, 1007, 904, 18446744073709551615, 1, 2), - (13, 510, 1053, 734, 18446744073709551615, 0, 2), - (13, 510, 255, 734, 18446744073709551615, 0, 2), - (13, 510, 1047, 734, 18446744073709551615, 0, 2), - (13, 510, 252, 734, 18446744073709551615, 0, 2), - (13, 510, 172, 734, 18446744073709551615, 0, 2), - (13, 510, 249, 734, 18446744073709551615, 0, 2), - (13, 510, 246, 734, 18446744073709551615, 0, 2), - (13, 510, 243, 734, 18446744073709551615, 0, 2), - (13, 510, 240, 734, 18446744073709551615, 0, 2), - (13, 510, 237, 734, 18446744073709551615, 0, 2), - (13, 510, 234, 734, 18446744073709551615, 0, 2), - (13, 510, 231, 734, 18446744073709551615, 0, 2), - (13, 510, 228, 734, 18446744073709551615, 0, 2), - (13, 510, 225, 734, 18446744073709551615, 0, 2), - (13, 510, 222, 734, 18446744073709551615, 0, 2), - (13, 510, 219, 734, 18446744073709551615, 0, 2), - (13, 510, 216, 734, 18446744073709551615, 0, 2), - (13, 510, 213, 734, 18446744073709551615, 0, 2), - (13, 510, 210, 734, 18446744073709551615, 0, 2), - (13, 510, 207, 734, 18446744073709551615, 0, 2), - (13, 510, 204, 734, 18446744073709551615, 0, 2), - (13, 510, 201, 734, 18446744073709551615, 0, 2), - (13, 510, 198, 734, 18446744073709551615, 0, 2), - (13, 510, 195, 734, 18446744073709551615, 0, 2), - (13, 510, 192, 734, 18446744073709551615, 0, 2), - (13, 510, 189, 734, 18446744073709551615, 0, 2), - (13, 510, 186, 734, 18446744073709551615, 0, 2), - (13, 510, 183, 734, 18446744073709551615, 0, 2), - (13, 510, 180, 734, 18446744073709551615, 0, 2), - (13, 510, 177, 734, 18446744073709551615, 0, 2), - (13, 510, 174, 734, 18446744073709551615, 0, 2), - (13, 510, 1083, 734, 18446744073709551615, 0, 2), - (13, 510, 173, 734, 18446744073709551615, 0, 2), - (13, 510, 159, 734, 18446744073709551615, 0, 2), - (13, 510, 912, 734, 18446744073709551615, 0, 2), - (13, 510, 152, 734, 18446744073709551615, 0, 2), - (13, 510, 149, 734, 18446744073709551615, 0, 2), - (13, 510, 141, 734, 18446744073709551615, 0, 2), - (13, 510, 1091, 734, 18446744073709551615, 0, 2), - (13, 510, 1096, 734, 18446744073709551615, 0, 2), - (13, 510, 137, 734, 18446744073709551615, 0, 2), - (13, 510, 134, 734, 18446744073709551615, 0, 2), - (13, 510, 131, 734, 18446744073709551615, 0, 2), - (13, 510, 124, 734, 18446744073709551615, 0, 2), - (13, 510, 122, 734, 18446744073709551615, 0, 2), - (13, 510, 112, 734, 18446744073709551615, 0, 2), - (13, 510, 120, 734, 18446744073709551615, 0, 2), - (13, 510, 109, 734, 18446744073709551615, 0, 2), - (13, 510, 106, 734, 18446744073709551615, 0, 2), - (13, 510, 103, 734, 18446744073709551615, 0, 2), - (13, 510, 100, 734, 18446744073709551615, 0, 2), - (13, 510, 97, 734, 18446744073709551615, 0, 2), - (13, 510, 94, 734, 18446744073709551615, 0, 2), - (13, 510, 91, 734, 18446744073709551615, 0, 2), - (13, 510, 88, 734, 18446744073709551615, 0, 2), - (13, 510, 85, 734, 18446744073709551615, 0, 2), - (13, 510, 82, 734, 18446744073709551615, 0, 2), - (13, 510, 79, 734, 18446744073709551615, 0, 2), - (13, 510, 76, 734, 18446744073709551615, 0, 2), - (13, 510, 73, 734, 18446744073709551615, 0, 2), - (13, 510, 70, 734, 18446744073709551615, 0, 2), - (13, 510, 67, 734, 18446744073709551615, 0, 2), - (13, 510, 64, 734, 18446744073709551615, 0, 2), - (13, 510, 61, 734, 18446744073709551615, 0, 2), - (13, 510, 58, 734, 18446744073709551615, 0, 2), - (13, 510, 55, 734, 18446744073709551615, 0, 2), - (13, 510, 52, 734, 18446744073709551615, 0, 2), - (13, 510, 49, 734, 18446744073709551615, 0, 2), - (13, 510, 46, 734, 18446744073709551615, 0, 2), - (13, 510, 43, 734, 18446744073709551615, 0, 2), - (13, 510, 40, 734, 18446744073709551615, 0, 2), - (13, 510, 37, 734, 18446744073709551615, 0, 2), - (13, 510, 34, 734, 18446744073709551615, 0, 2), - (13, 510, 31, 734, 18446744073709551615, 0, 2), - (13, 510, 28, 734, 18446744073709551615, 0, 2), - (13, 510, 19, 734, 18446744073709551615, 0, 2), - (13, 510, 1133, 734, 18446744073709551615, 0, 2), - (13, 510, 784, 734, 18446744073709551615, 0, 2), - (13, 510, 735, 606, 18446744073709551615, 0, 1), - (13, 697, 1042, 696, 18446744073709551615, 0, 1), - (13, 696, 1052, 695, 18446744073709551615, 0, 1), - (13, 695, 1051, 694, 18446744073709551615, 0, 1), - (13, 694, 1053, 693, 18446744073709551615, 0, 1), - (13, 693, 255, 692, 18446744073709551615, 0, 1), - (13, 692, 1047, 691, 18446744073709551615, 0, 1), - (13, 691, 252, 690, 18446744073709551615, 0, 1), - (13, 690, 172, 689, 18446744073709551615, 0, 1), - (13, 689, 249, 688, 18446744073709551615, 0, 1), - (13, 688, 246, 687, 18446744073709551615, 0, 1), - (13, 687, 243, 686, 18446744073709551615, 0, 1), - (13, 686, 240, 612, 18446744073709551615, 0, 1), - (13, 612, 237, 613, 18446744073709551615, 0, 1), - (13, 613, 234, 729, 18446744073709551615, 0, 1), - (13, 729, 231, 728, 18446744073709551615, 0, 1), - (13, 728, 228, 727, 18446744073709551615, 0, 1), - (13, 727, 225, 726, 18446744073709551615, 0, 1), - (13, 726, 222, 725, 18446744073709551615, 0, 1), - (13, 725, 219, 724, 18446744073709551615, 0, 1), - (13, 724, 216, 723, 18446744073709551615, 0, 1), - (13, 723, 213, 722, 18446744073709551615, 0, 1), - (13, 722, 210, 721, 18446744073709551615, 0, 1), - (13, 721, 207, 720, 18446744073709551615, 0, 1), - (13, 720, 204, 719, 18446744073709551615, 0, 1), - (13, 719, 201, 718, 18446744073709551615, 0, 1), - (13, 718, 198, 717, 18446744073709551615, 0, 1), - (13, 717, 195, 716, 18446744073709551615, 0, 1), - (13, 716, 192, 715, 18446744073709551615, 0, 1), - (13, 715, 189, 714, 18446744073709551615, 0, 1), - (13, 714, 186, 713, 18446744073709551615, 0, 1), - (13, 713, 183, 712, 18446744073709551615, 0, 1), - (13, 712, 180, 711, 18446744073709551615, 0, 1), - (13, 711, 177, 710, 18446744073709551615, 0, 1), - (13, 710, 174, 709, 18446744073709551615, 0, 1), - (13, 709, 1083, 708, 18446744073709551615, 0, 1), - (13, 708, 173, 614, 18446744073709551615, 0, 1), - (13, 614, 159, 615, 18446744073709551615, 0, 1), - (13, 615, 912, 616, 18446744073709551615, 0, 1), - (13, 616, 152, 617, 18446744073709551615, 0, 1), - (13, 617, 149, 618, 18446744073709551615, 0, 1), - (13, 618, 141, 619, 18446744073709551615, 0, 1), - (13, 619, 1091, 620, 18446744073709551615, 0, 1), - (13, 620, 1096, 621, 18446744073709551615, 0, 1), - (13, 621, 137, 622, 18446744073709551615, 0, 1), - (13, 622, 134, 623, 18446744073709551615, 0, 1), - (13, 623, 131, 624, 18446744073709551615, 0, 1), - (13, 624, 124, 625, 18446744073709551615, 0, 1), - (13, 625, 122, 626, 18446744073709551615, 0, 1), - (13, 626, 112, 627, 18446744073709551615, 0, 1), - (13, 627, 120, 628, 18446744073709551615, 0, 1), - (13, 628, 109, 629, 18446744073709551615, 0, 1), - (13, 629, 106, 630, 18446744073709551615, 0, 1), - (13, 630, 103, 631, 18446744073709551615, 0, 1), - (13, 631, 100, 632, 18446744073709551615, 0, 1), - (13, 632, 97, 633, 18446744073709551615, 0, 1), - (13, 633, 94, 634, 18446744073709551615, 0, 1), - (13, 634, 91, 635, 18446744073709551615, 0, 1), - (13, 635, 88, 636, 18446744073709551615, 0, 1), - (13, 636, 85, 637, 18446744073709551615, 0, 1), - (13, 637, 82, 638, 18446744073709551615, 0, 1), - (13, 638, 79, 639, 18446744073709551615, 0, 1), - (13, 639, 76, 640, 18446744073709551615, 0, 1), - (13, 640, 73, 641, 18446744073709551615, 0, 1), - (13, 641, 70, 642, 18446744073709551615, 0, 1), - (13, 642, 67, 643, 18446744073709551615, 0, 1), - (13, 643, 64, 644, 18446744073709551615, 0, 1), - (13, 644, 61, 645, 18446744073709551615, 0, 1), - (13, 645, 58, 646, 18446744073709551615, 0, 1), - (13, 646, 55, 647, 18446744073709551615, 0, 1), - (13, 647, 52, 648, 18446744073709551615, 0, 1), - (13, 648, 49, 649, 18446744073709551615, 0, 1), - (13, 649, 46, 650, 18446744073709551615, 0, 1), - (13, 650, 43, 651, 18446744073709551615, 0, 1), - (13, 651, 40, 652, 18446744073709551615, 0, 1), - (13, 652, 37, 653, 18446744073709551615, 0, 1), - (13, 653, 34, 654, 18446744073709551615, 0, 1), - (13, 654, 31, 655, 18446744073709551615, 0, 1), - (13, 655, 28, 656, 18446744073709551615, 0, 1), - (13, 656, 19, 657, 18446744073709551615, 0, 1), - (13, 657, 1133, 658, 18446744073709551615, 0, 1), - (13, 658, 784, 659, 18446744073709551615, 0, 1), - (13, 659, 782, 660, 18446744073709551615, 0, 1), - (13, 660, 1138, 661, 18446744073709551615, 0, 1), - (13, 661, 1114, 662, 18446744073709551615, 0, 1), - (13, 662, 1135, 663, 18446744073709551615, 0, 1), - (13, 663, 783, 664, 18446744073709551615, 0, 1), - (13, 664, 1136, 665, 18446744073709551615, 0, 1), - (13, 665, 836, 666, 18446744073709551615, 0, 1), - (13, 666, 15, 667, 18446744073709551615, 0, 1), - (13, 667, 1146, 668, 18446744073709551615, 0, 1), - (13, 668, 746, 669, 18446744073709551615, 0, 1), - (13, 669, 1152, 670, 18446744073709551615, 0, 1), - (13, 670, 781, 671, 18446744073709551615, 0, 1), - (13, 671, 1143, 672, 18446744073709551615, 0, 1), - (13, 672, 1144, 673, 18446744073709551615, 0, 1), - (13, 673, 745, 674, 18446744073709551615, 0, 1), - (13, 674, 744, 675, 18446744073709551615, 0, 1), - (13, 675, 743, 676, 18446744073709551615, 0, 1), - (13, 676, 742, 677, 18446744073709551615, 0, 1), - (13, 677, 741, 678, 18446744073709551615, 0, 1), - (13, 678, 740, 679, 18446744073709551615, 0, 1), - (13, 679, 739, 680, 18446744073709551615, 0, 1), - (13, 680, 738, 681, 18446744073709551615, 0, 1), - (13, 681, 737, 682, 18446744073709551615, 0, 1), - (13, 682, 736, 683, 18446744073709551615, 0, 1), - (13, 683, 735, 684, 18446744073709551615, 0, 1), - (13, 799, 576, 575, 18446744073709551615, 3, 5), - (13, 911, 697, 696, 18446744073709551615, 2, 4), - (13, 151, 695, 694, 18446744073709551615, 2, 4), - (13, 920, 694, 693, 18446744073709551615, 2, 4), - (13, 157, 691, 690, 18446744073709551615, 2, 4), - (13, 155, 690, 689, 18446744073709551615, 2, 4), - (13, 153, 689, 688, 18446744073709551615, 2, 4), - (13, 160, 688, 687, 18446744073709551615, 2, 4), - (13, 158, 687, 686, 18446744073709551615, 2, 4), - (13, 935, 686, 612, 18446744073709551615, 0, 2), - (13, 929, 612, 613, 18446744073709551615, 0, 2), - (13, 933, 613, 729, 18446744073709551615, 0, 2), - (13, 165, 729, 728, 18446744073709551615, 0, 2), - (13, 161, 728, 727, 18446744073709551615, 0, 2), - (13, 164, 727, 726, 18446744073709551615, 0, 2), - (13, 162, 726, 725, 18446744073709551615, 0, 2), - (13, 167, 725, 724, 18446744073709551615, 0, 2), - (13, 936, 724, 723, 18446744073709551615, 0, 2), - (13, 937, 723, 722, 18446744073709551615, 0, 2), - (13, 170, 722, 721, 18446744073709551615, 0, 2), - (13, 168, 721, 720, 18446744073709551615, 0, 2), - (13, 156, 720, 719, 18446744073709551615, 0, 2), - (13, 1082, 719, 718, 18446744073709551615, 0, 2), - (13, 942, 718, 717, 18446744073709551615, 0, 2), - (13, 943, 717, 716, 18446744073709551615, 0, 2), - (13, 176, 716, 715, 18446744073709551615, 0, 2), - (13, 945, 715, 714, 18446744073709551615, 0, 2), - (13, 946, 714, 713, 18446744073709551615, 0, 2), - (13, 179, 713, 712, 18446744073709551615, 0, 2), - (13, 948, 712, 711, 18446744073709551615, 0, 2), - (13, 949, 711, 710, 18446744073709551615, 0, 2), - (13, 182, 710, 709, 18446744073709551615, 0, 2), - (13, 951, 709, 708, 18446744073709551615, 0, 2), - (13, 952, 708, 614, 18446744073709551615, 0, 2), - (13, 185, 614, 615, 18446744073709551615, 0, 2), - (13, 954, 615, 616, 18446744073709551615, 0, 2), - (13, 955, 616, 617, 18446744073709551615, 0, 2), - (13, 188, 617, 618, 18446744073709551615, 0, 2), - (13, 957, 618, 619, 18446744073709551615, 0, 2), - (13, 958, 619, 620, 18446744073709551615, 0, 2), - (13, 191, 620, 621, 18446744073709551615, 0, 2), - (13, 960, 621, 622, 18446744073709551615, 2, 4), - (13, 961, 622, 623, 18446744073709551615, 2, 4), - (13, 194, 623, 624, 18446744073709551615, 2, 4), - (13, 963, 624, 625, 18446744073709551615, 2, 4), - (13, 964, 625, 626, 18446744073709551615, 2, 4), - (13, 197, 626, 627, 18446744073709551615, 2, 4), - (13, 966, 627, 628, 18446744073709551615, 2, 4), - (13, 967, 628, 629, 18446744073709551615, 2, 4), - (13, 200, 629, 630, 18446744073709551615, 2, 4), - (13, 969, 630, 631, 18446744073709551615, 2, 4), - (13, 970, 631, 632, 18446744073709551615, 2, 4), - (13, 203, 632, 633, 18446744073709551615, 2, 4), - (13, 972, 633, 634, 18446744073709551615, 2, 4), - (13, 973, 634, 635, 18446744073709551615, 2, 4), - (13, 206, 635, 636, 18446744073709551615, 2, 4), - (13, 975, 636, 637, 18446744073709551615, 2, 4), - (13, 976, 637, 638, 18446744073709551615, 2, 4), - (13, 209, 638, 639, 18446744073709551615, 2, 4), - (13, 978, 639, 640, 18446744073709551615, 2, 4), - (13, 979, 640, 641, 18446744073709551615, 2, 4), - (13, 212, 641, 642, 18446744073709551615, 2, 4), - (13, 981, 642, 643, 18446744073709551615, 2, 4), - (13, 982, 643, 644, 18446744073709551615, 2, 4), - (13, 215, 644, 645, 18446744073709551615, 2, 4), - (13, 984, 645, 646, 18446744073709551615, 2, 4), - (13, 985, 646, 647, 18446744073709551615, 2, 4), - (13, 218, 647, 648, 18446744073709551615, 2, 4), - (13, 987, 648, 649, 18446744073709551615, 2, 4), - (13, 988, 649, 650, 18446744073709551615, 2, 4), - (13, 221, 650, 651, 18446744073709551615, 2, 4), - (13, 990, 651, 652, 18446744073709551615, 2, 4), - (13, 991, 652, 653, 18446744073709551615, 2, 4), - (13, 224, 653, 654, 18446744073709551615, 2, 4), - (13, 993, 654, 655, 18446744073709551615, 2, 4), - (13, 994, 655, 656, 18446744073709551615, 2, 4), - (13, 227, 656, 657, 18446744073709551615, 2, 4), - (13, 996, 657, 658, 18446744073709551615, 2, 4), - (13, 997, 658, 659, 18446744073709551615, 2, 4), - (13, 230, 659, 660, 18446744073709551615, 2, 4), - (13, 999, 660, 661, 18446744073709551615, 2, 4), - (13, 1000, 661, 662, 18446744073709551615, 2, 4), - (13, 233, 662, 663, 18446744073709551615, 2, 4), - (13, 1002, 663, 664, 18446744073709551615, 2, 4), - (13, 1003, 664, 665, 18446744073709551615, 2, 4), - (13, 236, 665, 666, 18446744073709551615, 2, 4), - (13, 1005, 666, 667, 18446744073709551615, 2, 4), - (13, 1006, 667, 668, 18446744073709551615, 2, 4), - (13, 239, 668, 669, 18446744073709551615, 2, 4), - (13, 1008, 669, 670, 18446744073709551615, 2, 4), - (13, 1009, 670, 671, 18446744073709551615, 2, 4), - (13, 242, 671, 672, 18446744073709551615, 2, 4), - (13, 1011, 672, 673, 18446744073709551615, 2, 4), - (13, 1012, 673, 674, 18446744073709551615, 2, 4), - (13, 245, 674, 675, 18446744073709551615, 2, 4), - (13, 1014, 675, 676, 18446744073709551615, 2, 4), - (13, 1015, 676, 677, 18446744073709551615, 2, 4), - (13, 248, 677, 678, 18446744073709551615, 2, 4), - (13, 1017, 678, 679, 18446744073709551615, 2, 4), - (13, 1018, 679, 680, 18446744073709551615, 2, 4), - (13, 251, 680, 681, 18446744073709551615, 2, 4), - (13, 1020, 681, 682, 18446744073709551615, 2, 4), - (13, 1021, 682, 683, 18446744073709551615, 2, 4), - (13, 254, 683, 684, 18446744073709551615, 2, 4), - (13, 1023, 684, 685, 18446744073709551615, 2, 4), - (13, 685, 1049, 732, 18446744073709551615, 0, 1), - (13, 1023, 684, 685, 18446744073709551615, 3, 4), - (13, 254, 683, 684, 18446744073709551615, 3, 4), - (13, 1021, 682, 683, 18446744073709551615, 3, 4), - (13, 1020, 681, 682, 18446744073709551615, 3, 4), - (13, 251, 680, 681, 18446744073709551615, 3, 4), - (13, 1018, 679, 680, 18446744073709551615, 3, 4), - (13, 1017, 678, 679, 18446744073709551615, 3, 4), - (13, 248, 677, 678, 18446744073709551615, 3, 4), - (13, 1015, 676, 677, 18446744073709551615, 3, 4), - (13, 1014, 675, 676, 18446744073709551615, 3, 4), - (13, 245, 674, 675, 18446744073709551615, 3, 4), - (13, 1012, 673, 674, 18446744073709551615, 3, 4), - (13, 1011, 672, 673, 18446744073709551615, 3, 4), - (13, 242, 671, 672, 18446744073709551615, 3, 4), - (13, 1009, 670, 671, 18446744073709551615, 3, 4), - (13, 1008, 669, 670, 18446744073709551615, 3, 4), - (13, 239, 668, 669, 18446744073709551615, 3, 4), - (13, 1006, 667, 668, 18446744073709551615, 3, 4), - (13, 1005, 666, 667, 18446744073709551615, 3, 4), - (13, 236, 665, 666, 18446744073709551615, 3, 4), - (13, 1003, 664, 665, 18446744073709551615, 3, 4), - (13, 1002, 663, 664, 18446744073709551615, 3, 4), - (13, 233, 662, 663, 18446744073709551615, 3, 4), - (13, 1000, 661, 662, 18446744073709551615, 3, 4), - (13, 999, 660, 661, 18446744073709551615, 3, 4), - (13, 230, 659, 660, 18446744073709551615, 3, 4), - (13, 997, 658, 659, 18446744073709551615, 3, 4), - (13, 996, 657, 658, 18446744073709551615, 3, 4), - (13, 227, 656, 657, 18446744073709551615, 3, 4), - (13, 994, 655, 656, 18446744073709551615, 3, 4), - (13, 993, 654, 655, 18446744073709551615, 3, 4), - (13, 224, 653, 654, 18446744073709551615, 3, 4), - (13, 991, 652, 653, 18446744073709551615, 3, 4), - (13, 990, 651, 652, 18446744073709551615, 3, 4), - (13, 221, 650, 651, 18446744073709551615, 3, 4), - (13, 988, 649, 650, 18446744073709551615, 3, 4), - (13, 987, 648, 649, 18446744073709551615, 3, 4), - (13, 218, 647, 648, 18446744073709551615, 3, 4), - (13, 985, 646, 647, 18446744073709551615, 3, 4), - (13, 984, 645, 646, 18446744073709551615, 3, 4), - (13, 215, 644, 645, 18446744073709551615, 3, 4), - (13, 982, 643, 644, 18446744073709551615, 3, 4), - (13, 981, 642, 643, 18446744073709551615, 3, 4), - (13, 212, 641, 642, 18446744073709551615, 3, 4), - (13, 979, 640, 641, 18446744073709551615, 3, 4), - (13, 978, 639, 640, 18446744073709551615, 3, 4), - (13, 209, 638, 639, 18446744073709551615, 3, 4), - (13, 976, 637, 638, 18446744073709551615, 3, 4), - (13, 975, 636, 637, 18446744073709551615, 3, 4), - (13, 206, 635, 636, 18446744073709551615, 3, 4), - (13, 973, 634, 635, 18446744073709551615, 3, 4), - (13, 972, 633, 634, 18446744073709551615, 3, 4), - (13, 203, 632, 633, 18446744073709551615, 3, 4), - (13, 970, 631, 632, 18446744073709551615, 3, 4), - (13, 969, 630, 631, 18446744073709551615, 3, 4), - (13, 200, 629, 630, 18446744073709551615, 3, 4), - (13, 967, 628, 629, 18446744073709551615, 3, 4), - (13, 966, 627, 628, 18446744073709551615, 3, 4), - (13, 197, 626, 627, 18446744073709551615, 3, 4), - (13, 964, 625, 626, 18446744073709551615, 3, 4), - (13, 963, 624, 625, 18446744073709551615, 3, 4), - (13, 194, 623, 624, 18446744073709551615, 3, 4), - (13, 961, 622, 623, 18446744073709551615, 3, 4), - (13, 960, 621, 622, 18446744073709551615, 3, 4), - (13, 191, 620, 621, 18446744073709551615, 1, 2), - (13, 958, 619, 620, 18446744073709551615, 1, 2), - (13, 957, 618, 619, 18446744073709551615, 1, 2), - (13, 188, 617, 618, 18446744073709551615, 1, 2), - (13, 955, 616, 617, 18446744073709551615, 1, 2), - (13, 954, 615, 616, 18446744073709551615, 1, 2), - (13, 185, 614, 615, 18446744073709551615, 1, 2), - (13, 952, 708, 614, 18446744073709551615, 1, 2), - (13, 951, 709, 708, 18446744073709551615, 1, 2), - (13, 182, 710, 709, 18446744073709551615, 1, 2), - (13, 949, 711, 710, 18446744073709551615, 1, 2), - (13, 948, 712, 711, 18446744073709551615, 1, 2), - (13, 179, 713, 712, 18446744073709551615, 1, 2), - (13, 946, 714, 713, 18446744073709551615, 1, 2), - (13, 945, 715, 714, 18446744073709551615, 1, 2), - (13, 176, 716, 715, 18446744073709551615, 1, 2), - (13, 943, 717, 716, 18446744073709551615, 1, 2), - (13, 942, 718, 717, 18446744073709551615, 1, 2), - (13, 1082, 719, 718, 18446744073709551615, 1, 2), - (13, 156, 720, 719, 18446744073709551615, 1, 2), - (13, 168, 721, 720, 18446744073709551615, 1, 2), - (13, 170, 722, 721, 18446744073709551615, 1, 2), - (13, 937, 723, 722, 18446744073709551615, 1, 2), - (13, 936, 724, 723, 18446744073709551615, 1, 2), - (13, 167, 725, 724, 18446744073709551615, 1, 2), - (13, 162, 726, 725, 18446744073709551615, 1, 2), - (13, 164, 727, 726, 18446744073709551615, 1, 2), - (13, 161, 728, 727, 18446744073709551615, 1, 2), - (13, 165, 729, 728, 18446744073709551615, 1, 2), - (13, 933, 613, 729, 18446744073709551615, 1, 2), - (13, 929, 612, 613, 18446744073709551615, 1, 2), - (13, 935, 686, 612, 18446744073709551615, 1, 2), - (13, 158, 687, 686, 18446744073709551615, 3, 4), - (13, 160, 688, 687, 18446744073709551615, 3, 4), - (13, 153, 689, 688, 18446744073709551615, 3, 4), - (13, 155, 690, 689, 18446744073709551615, 3, 4), - (13, 157, 691, 690, 18446744073709551615, 3, 4), - (13, 920, 694, 693, 18446744073709551615, 3, 4), - (13, 151, 695, 694, 18446744073709551615, 3, 4), - (13, 911, 697, 696, 18446744073709551615, 3, 4), - (13, 732, 755, 733, 18446744073709551615, 4, 5), - (13, 754, 733, 605, 18446744073709551615, 4, 5), - (13, 753, 605, 604, 18446744073709551615, 4, 5), - (13, 752, 604, 603, 18446744073709551615, 4, 5), - (13, 751, 603, 602, 18446744073709551615, 4, 5), - (13, 750, 602, 601, 18446744073709551615, 4, 5), - (13, 749, 601, 600, 18446744073709551615, 4, 5), - (13, 748, 600, 599, 18446744073709551615, 4, 5), - (13, 747, 599, 598, 18446744073709551615, 4, 5), - (13, 14, 598, 597, 18446744073709551615, 4, 5), - (13, 11, 597, 596, 18446744073709551615, 4, 5), - (13, 777, 596, 595, 18446744073709551615, 4, 5), - (13, 13, 595, 594, 18446744073709551615, 4, 5), - (13, 1145, 594, 593, 18446744073709551615, 4, 5), - (13, 1137, 593, 592, 18446744073709551615, 4, 5), - (13, 17, 592, 591, 18446744073709551615, 4, 5), - (13, 1134, 591, 590, 18446744073709551615, 4, 5), - (13, 27, 590, 589, 18446744073709551615, 4, 5), - (13, 786, 589, 588, 18446744073709551615, 4, 5), - (13, 787, 588, 587, 18446744073709551615, 4, 5), - (13, 788, 587, 586, 18446744073709551615, 4, 5), - (13, 789, 586, 585, 18446744073709551615, 4, 5), - (13, 790, 585, 584, 18446744073709551615, 4, 5), - (13, 791, 584, 583, 18446744073709551615, 4, 5), - (13, 23, 583, 582, 18446744073709551615, 4, 5), - (13, 20, 582, 581, 18446744073709551615, 4, 5), - (13, 18, 581, 580, 18446744073709551615, 4, 5), - (13, 795, 580, 579, 18446744073709551615, 4, 5), - (13, 796, 579, 578, 18446744073709551615, 4, 5), - (13, 797, 578, 577, 18446744073709551615, 4, 5), - (13, 798, 577, 576, 18446744073709551615, 4, 5), - (13, 799, 576, 575, 18446744073709551615, 4, 5), - (13, 800, 575, 574, 18446744073709551615, 4, 5), - (13, 801, 574, 573, 18446744073709551615, 4, 5), - (13, 802, 573, 572, 18446744073709551615, 4, 5), - (13, 803, 572, 571, 18446744073709551615, 4, 5), - (13, 804, 571, 570, 18446744073709551615, 4, 5), - (13, 805, 570, 569, 18446744073709551615, 4, 5), - (13, 806, 569, 568, 18446744073709551615, 4, 5), - (13, 807, 568, 567, 18446744073709551615, 4, 5), - (13, 808, 567, 566, 18446744073709551615, 4, 5), - (13, 809, 566, 565, 18446744073709551615, 4, 5), - (13, 810, 565, 564, 18446744073709551615, 4, 5), - (13, 811, 564, 563, 18446744073709551615, 4, 5), - (13, 812, 563, 562, 18446744073709551615, 4, 5), - (13, 813, 562, 561, 18446744073709551615, 4, 5), - (13, 814, 561, 560, 18446744073709551615, 4, 5), - (13, 815, 560, 558, 18446744073709551615, 4, 5), - (13, 816, 558, 557, 18446744073709551615, 8, 10), - (13, 817, 557, 559, 18446744073709551615, 4, 5), - (13, 818, 559, 557, 18446744073709551615, 4, 5), - (13, 819, 557, 558, 18446744073709551615, 4, 5), - (14, 732, 819, 557, 18446744073709551615, 4, 5), - (14, 732, 817, 557, 18446744073709551615, 4, 5), - (13, 1006, 667, 605, 18446744073709551615, 0, 1), - (13, 239, 668, 604, 18446744073709551615, 0, 1), - (13, 1008, 669, 603, 18446744073709551615, 0, 1), - (13, 1009, 670, 602, 18446744073709551615, 0, 1), - (13, 242, 671, 601, 18446744073709551615, 0, 1), - (13, 1011, 672, 600, 18446744073709551615, 0, 1), - (13, 1012, 673, 599, 18446744073709551615, 0, 1), - (13, 245, 674, 598, 18446744073709551615, 0, 1), - (13, 1014, 675, 597, 18446744073709551615, 0, 1), - (13, 1015, 676, 596, 18446744073709551615, 0, 1), - (13, 248, 677, 595, 18446744073709551615, 0, 1), - (13, 1017, 678, 594, 18446744073709551615, 0, 1), - (13, 1018, 679, 593, 18446744073709551615, 0, 1), - (13, 251, 680, 592, 18446744073709551615, 0, 1), - (13, 1020, 681, 591, 18446744073709551615, 0, 1), - (13, 1021, 682, 590, 18446744073709551615, 0, 1), - (13, 254, 683, 589, 18446744073709551615, 0, 1), - (13, 1023, 684, 588, 18446744073709551615, 0, 1), - (13, 1049, 685, 587, 18446744073709551615, 0, 1), - (13, 157, 663, 662, 18446744073709551615, 0, 2), - (13, 155, 662, 661, 18446744073709551615, 0, 2), - (13, 153, 661, 660, 18446744073709551615, 0, 2), - (13, 935, 658, 657, 18446744073709551615, 0, 2), - (13, 929, 657, 656, 18446744073709551615, 0, 2), - (13, 933, 656, 655, 18446744073709551615, 0, 2), - (13, 165, 655, 654, 18446744073709551615, 0, 2), - (13, 161, 654, 653, 18446744073709551615, 0, 2), - (13, 164, 653, 652, 18446744073709551615, 0, 2), - (13, 162, 652, 651, 18446744073709551615, 0, 2), - (13, 167, 651, 650, 18446744073709551615, 0, 2), - (13, 936, 650, 649, 18446744073709551615, 0, 2), - (13, 937, 649, 648, 18446744073709551615, 0, 2), - (13, 170, 648, 647, 18446744073709551615, 0, 2), - (13, 168, 647, 646, 18446744073709551615, 0, 2), - (13, 156, 646, 645, 18446744073709551615, 0, 2), - (13, 1082, 645, 644, 18446744073709551615, 0, 2), - (13, 942, 644, 643, 18446744073709551615, 0, 2), - (13, 943, 643, 642, 18446744073709551615, 0, 2), - (13, 176, 642, 641, 18446744073709551615, 0, 2), - (13, 945, 641, 640, 18446744073709551615, 0, 2), - (13, 946, 640, 639, 18446744073709551615, 0, 2), - (13, 179, 639, 638, 18446744073709551615, 0, 2), - (13, 948, 638, 637, 18446744073709551615, 0, 2), - (13, 949, 637, 636, 18446744073709551615, 0, 2), - (13, 182, 636, 635, 18446744073709551615, 0, 2), - (13, 951, 635, 634, 18446744073709551615, 0, 2), - (13, 952, 634, 633, 18446744073709551615, 0, 2), - (13, 185, 633, 632, 18446744073709551615, 0, 2), - (13, 954, 632, 631, 18446744073709551615, 0, 2), - (13, 955, 631, 630, 18446744073709551615, 0, 2), - (13, 188, 630, 629, 18446744073709551615, 0, 2), - (13, 957, 629, 628, 18446744073709551615, 0, 2), - (13, 958, 628, 627, 18446744073709551615, 0, 2), - (13, 191, 627, 626, 18446744073709551615, 0, 2), - (13, 960, 626, 625, 18446744073709551615, 0, 2), - (13, 961, 625, 624, 18446744073709551615, 0, 2), - (13, 194, 624, 623, 18446744073709551615, 0, 2), - (13, 963, 623, 622, 18446744073709551615, 0, 2), - (13, 964, 622, 621, 18446744073709551615, 0, 2), - (13, 197, 621, 620, 18446744073709551615, 0, 2), - (13, 966, 620, 619, 18446744073709551615, 0, 2), - (13, 967, 619, 618, 18446744073709551615, 0, 2), - (13, 200, 618, 617, 18446744073709551615, 0, 2), - (13, 969, 617, 616, 18446744073709551615, 0, 2), - (13, 970, 616, 615, 18446744073709551615, 0, 2), - (13, 203, 615, 614, 18446744073709551615, 0, 2), - (13, 972, 614, 708, 18446744073709551615, 0, 2), - (13, 973, 708, 709, 18446744073709551615, 0, 2), - (13, 206, 709, 710, 18446744073709551615, 0, 2), - (13, 975, 710, 711, 18446744073709551615, 0, 2), - (13, 976, 711, 712, 18446744073709551615, 0, 2), - (13, 209, 712, 713, 18446744073709551615, 0, 2), - (13, 978, 713, 714, 18446744073709551615, 0, 2), - (13, 979, 714, 715, 18446744073709551615, 0, 2), - (13, 212, 715, 716, 18446744073709551615, 0, 2), - (13, 981, 716, 717, 18446744073709551615, 0, 2), - (13, 982, 717, 718, 18446744073709551615, 0, 2), - (13, 215, 718, 719, 18446744073709551615, 0, 2), - (13, 984, 719, 720, 18446744073709551615, 0, 2), - (13, 985, 720, 721, 18446744073709551615, 0, 2), - (13, 218, 721, 722, 18446744073709551615, 0, 2), - (13, 987, 722, 723, 18446744073709551615, 0, 2), - (13, 988, 723, 724, 18446744073709551615, 0, 2), - (13, 221, 724, 725, 18446744073709551615, 0, 2), - (13, 990, 725, 726, 18446744073709551615, 0, 2), - (13, 991, 726, 727, 18446744073709551615, 0, 2), - (13, 224, 727, 728, 18446744073709551615, 0, 2), - (13, 993, 728, 729, 18446744073709551615, 0, 2), - (13, 994, 729, 613, 18446744073709551615, 0, 2), - (13, 227, 613, 612, 18446744073709551615, 0, 2), - (13, 996, 612, 686, 18446744073709551615, 0, 2), - (13, 997, 686, 687, 18446744073709551615, 0, 2), - (13, 230, 687, 688, 18446744073709551615, 0, 2), - (13, 999, 688, 689, 18446744073709551615, 0, 2), - (13, 1000, 689, 690, 18446744073709551615, 0, 2), - (13, 233, 690, 691, 18446744073709551615, 0, 2), - (13, 1002, 691, 692, 18446744073709551615, 0, 2), - (13, 1003, 692, 693, 18446744073709551615, 0, 2), - (13, 236, 693, 694, 18446744073709551615, 0, 2), - (13, 1005, 694, 695, 18446744073709551615, 0, 2), - (13, 1006, 695, 696, 18446744073709551615, 0, 2), - (13, 239, 696, 697, 18446744073709551615, 0, 2), - (13, 1008, 697, 698, 18446744073709551615, 0, 2), - (13, 1009, 698, 699, 18446744073709551615, 0, 2), - (13, 242, 699, 700, 18446744073709551615, 0, 2), - (13, 1011, 700, 701, 18446744073709551615, 0, 2), - (13, 1012, 701, 702, 18446744073709551615, 0, 2), - (13, 245, 702, 703, 18446744073709551615, 0, 2), - (13, 1014, 703, 704, 18446744073709551615, 0, 2), - (13, 1015, 704, 705, 18446744073709551615, 0, 2), - (13, 248, 705, 706, 18446744073709551615, 0, 2), - (13, 1017, 706, 707, 18446744073709551615, 0, 2), - (13, 1018, 707, 611, 18446744073709551615, 0, 2), - (13, 251, 611, 610, 18446744073709551615, 0, 2), - (13, 1020, 610, 730, 18446744073709551615, 0, 2), - (13, 1021, 730, 731, 18446744073709551615, 0, 2), - (13, 254, 731, 128, 18446744073709551615, 0, 2), - (13, 1023, 128, 1093, 18446744073709551615, 2, 4), - (13, 1049, 1093, 609, 18446744073709551615, 0, 1), - (13, 1023, 128, 1093, 18446744073709551615, 3, 4), - (13, 254, 731, 128, 18446744073709551615, 1, 2), - (13, 1021, 730, 731, 18446744073709551615, 1, 2), - (13, 1020, 610, 730, 18446744073709551615, 1, 2), - (13, 251, 611, 610, 18446744073709551615, 1, 2), - (13, 1018, 707, 611, 18446744073709551615, 1, 2), - (13, 1017, 706, 707, 18446744073709551615, 1, 2), - (13, 248, 705, 706, 18446744073709551615, 1, 2), - (13, 1015, 704, 705, 18446744073709551615, 1, 2), - (13, 1014, 703, 704, 18446744073709551615, 1, 2), - (13, 245, 702, 703, 18446744073709551615, 1, 2), - (13, 1012, 701, 702, 18446744073709551615, 1, 2), - (13, 1011, 700, 701, 18446744073709551615, 1, 2), - (13, 242, 699, 700, 18446744073709551615, 1, 2), - (13, 1009, 698, 699, 18446744073709551615, 1, 2), - (13, 1008, 697, 698, 18446744073709551615, 1, 2), - (13, 239, 696, 697, 18446744073709551615, 1, 2), - (13, 1006, 695, 696, 18446744073709551615, 1, 2), - (13, 1005, 694, 695, 18446744073709551615, 1, 2), - (13, 236, 693, 694, 18446744073709551615, 1, 2), - (13, 1003, 692, 693, 18446744073709551615, 1, 2), - (13, 1002, 691, 692, 18446744073709551615, 1, 2), - (13, 233, 690, 691, 18446744073709551615, 1, 2), - (13, 1000, 689, 690, 18446744073709551615, 1, 2), - (13, 999, 688, 689, 18446744073709551615, 1, 2), - (13, 230, 687, 688, 18446744073709551615, 1, 2), - (13, 997, 686, 687, 18446744073709551615, 1, 2), - (13, 996, 612, 686, 18446744073709551615, 1, 2), - (13, 227, 613, 612, 18446744073709551615, 1, 2), - (13, 994, 729, 613, 18446744073709551615, 1, 2), - (13, 993, 728, 729, 18446744073709551615, 1, 2), - (13, 224, 727, 728, 18446744073709551615, 1, 2), - (13, 991, 726, 727, 18446744073709551615, 1, 2), - (13, 990, 725, 726, 18446744073709551615, 1, 2), - (13, 221, 724, 725, 18446744073709551615, 1, 2), - (13, 988, 723, 724, 18446744073709551615, 1, 2), - (13, 987, 722, 723, 18446744073709551615, 1, 2), - (13, 218, 721, 722, 18446744073709551615, 1, 2), - (13, 985, 720, 721, 18446744073709551615, 1, 2), - (13, 984, 719, 720, 18446744073709551615, 1, 2), - (13, 215, 718, 719, 18446744073709551615, 1, 2), - (13, 982, 717, 718, 18446744073709551615, 1, 2), - (13, 981, 716, 717, 18446744073709551615, 1, 2), - (13, 212, 715, 716, 18446744073709551615, 1, 2), - (13, 979, 714, 715, 18446744073709551615, 1, 2), - (13, 978, 713, 714, 18446744073709551615, 1, 2), - (13, 209, 712, 713, 18446744073709551615, 1, 2), - (13, 976, 711, 712, 18446744073709551615, 1, 2), - (13, 975, 710, 711, 18446744073709551615, 1, 2), - (13, 206, 709, 710, 18446744073709551615, 1, 2), - (13, 973, 708, 709, 18446744073709551615, 1, 2), - (13, 972, 614, 708, 18446744073709551615, 1, 2), - (13, 203, 615, 614, 18446744073709551615, 1, 2), - (13, 970, 616, 615, 18446744073709551615, 1, 2), - (13, 969, 617, 616, 18446744073709551615, 1, 2), - (13, 200, 618, 617, 18446744073709551615, 1, 2), - (13, 967, 619, 618, 18446744073709551615, 1, 2), - (13, 966, 620, 619, 18446744073709551615, 1, 2), - (13, 197, 621, 620, 18446744073709551615, 1, 2), - (13, 964, 622, 621, 18446744073709551615, 1, 2), - (13, 963, 623, 622, 18446744073709551615, 1, 2), - (13, 194, 624, 623, 18446744073709551615, 1, 2), - (13, 961, 625, 624, 18446744073709551615, 1, 2), - (13, 960, 626, 625, 18446744073709551615, 1, 2), - (13, 191, 627, 626, 18446744073709551615, 1, 2), - (13, 958, 628, 627, 18446744073709551615, 1, 2), - (13, 957, 629, 628, 18446744073709551615, 1, 2), - (13, 188, 630, 629, 18446744073709551615, 1, 2), - (13, 955, 631, 630, 18446744073709551615, 1, 2), - (13, 954, 632, 631, 18446744073709551615, 1, 2), - (13, 185, 633, 632, 18446744073709551615, 1, 2), - (13, 952, 634, 633, 18446744073709551615, 1, 2), - (13, 951, 635, 634, 18446744073709551615, 1, 2), - (13, 182, 636, 635, 18446744073709551615, 1, 2), - (13, 949, 637, 636, 18446744073709551615, 1, 2), - (13, 948, 638, 637, 18446744073709551615, 1, 2), - (13, 179, 639, 638, 18446744073709551615, 1, 2), - (13, 946, 640, 639, 18446744073709551615, 1, 2), - (13, 945, 641, 640, 18446744073709551615, 1, 2), - (13, 176, 642, 641, 18446744073709551615, 1, 2), - (13, 943, 643, 642, 18446744073709551615, 1, 2), - (13, 942, 644, 643, 18446744073709551615, 1, 2), - (13, 1082, 645, 644, 18446744073709551615, 1, 2), - (13, 156, 646, 645, 18446744073709551615, 1, 2), - (13, 168, 647, 646, 18446744073709551615, 1, 2), - (13, 170, 648, 647, 18446744073709551615, 1, 2), - (13, 937, 649, 648, 18446744073709551615, 1, 2), - (13, 936, 650, 649, 18446744073709551615, 1, 2), - (13, 167, 651, 650, 18446744073709551615, 1, 2), - (13, 162, 652, 651, 18446744073709551615, 1, 2), - (13, 164, 653, 652, 18446744073709551615, 1, 2), - (13, 161, 654, 653, 18446744073709551615, 1, 2), - (13, 165, 655, 654, 18446744073709551615, 1, 2), - (13, 933, 656, 655, 18446744073709551615, 1, 2), - (13, 929, 657, 656, 18446744073709551615, 1, 2), - (13, 935, 658, 657, 18446744073709551615, 1, 2), - (13, 153, 661, 660, 18446744073709551615, 1, 2), - (13, 155, 662, 661, 18446744073709551615, 1, 2), - (13, 157, 663, 662, 18446744073709551615, 1, 2), - (13, 609, 755, 608, 18446744073709551615, 2, 3), - (13, 754, 608, 607, 18446744073709551615, 2, 3), - (13, 753, 607, 606, 18446744073709551615, 2, 3), - (13, 752, 606, 732, 18446744073709551615, 2, 3), - (13, 751, 732, 733, 18446744073709551615, 2, 3), - (13, 750, 733, 605, 18446744073709551615, 2, 3), - (13, 749, 605, 604, 18446744073709551615, 2, 3), - (13, 748, 604, 603, 18446744073709551615, 2, 3), - (13, 747, 603, 602, 18446744073709551615, 2, 3), - (13, 14, 602, 601, 18446744073709551615, 2, 3), - (13, 11, 601, 600, 18446744073709551615, 2, 3), - (13, 777, 600, 599, 18446744073709551615, 2, 3), - (13, 13, 599, 598, 18446744073709551615, 2, 3), - (13, 1145, 598, 597, 18446744073709551615, 2, 3), - (13, 1137, 597, 596, 18446744073709551615, 2, 3), - (13, 17, 596, 595, 18446744073709551615, 2, 3), - (13, 1134, 595, 594, 18446744073709551615, 2, 3), - (13, 27, 594, 593, 18446744073709551615, 2, 3), - (13, 786, 593, 592, 18446744073709551615, 2, 3), - (13, 787, 592, 591, 18446744073709551615, 2, 3), - (13, 788, 591, 590, 18446744073709551615, 2, 3), - (13, 789, 590, 589, 18446744073709551615, 2, 3), - (13, 790, 589, 588, 18446744073709551615, 2, 3), - (13, 791, 588, 587, 18446744073709551615, 2, 3), - (13, 23, 587, 586, 18446744073709551615, 2, 3), - (13, 20, 586, 585, 18446744073709551615, 2, 3), - (13, 18, 585, 584, 18446744073709551615, 2, 3), - (13, 795, 584, 583, 18446744073709551615, 2, 3), - (13, 796, 583, 582, 18446744073709551615, 2, 3), - (13, 797, 582, 581, 18446744073709551615, 2, 3), - (13, 798, 581, 580, 18446744073709551615, 2, 3), - (13, 799, 580, 579, 18446744073709551615, 2, 3), - (13, 800, 579, 578, 18446744073709551615, 2, 3), - (13, 801, 578, 577, 18446744073709551615, 2, 3), - (13, 802, 577, 576, 18446744073709551615, 2, 3), - (13, 803, 576, 575, 18446744073709551615, 2, 3), - (13, 804, 575, 574, 18446744073709551615, 2, 3), - (13, 805, 574, 573, 18446744073709551615, 2, 3), - (13, 806, 573, 572, 18446744073709551615, 2, 3), - (13, 807, 572, 571, 18446744073709551615, 2, 3), - (13, 808, 571, 570, 18446744073709551615, 2, 3), - (13, 809, 570, 569, 18446744073709551615, 2, 3), - (13, 810, 569, 568, 18446744073709551615, 2, 3), - (13, 811, 568, 567, 18446744073709551615, 2, 3), - (13, 812, 567, 566, 18446744073709551615, 2, 3), - (13, 813, 566, 565, 18446744073709551615, 2, 3), - (13, 814, 565, 564, 18446744073709551615, 2, 3), - (13, 815, 564, 562, 18446744073709551615, 2, 3), - (13, 816, 562, 561, 18446744073709551615, 4, 6), - (13, 817, 561, 563, 18446744073709551615, 2, 3), - (13, 818, 563, 561, 18446744073709551615, 2, 3), - (13, 819, 561, 562, 18446744073709551615, 2, 3), - (14, 609, 819, 561, 18446744073709551615, 2, 3), - (14, 609, 817, 561, 18446744073709551615, 2, 3), - (13, 1006, 695, 607, 18446744073709551615, 0, 1), - (13, 239, 696, 606, 18446744073709551615, 0, 1), - (13, 1008, 697, 732, 18446744073709551615, 0, 1), - (13, 1009, 698, 733, 18446744073709551615, 0, 1), - (13, 242, 699, 605, 18446744073709551615, 0, 1), - (13, 1011, 700, 604, 18446744073709551615, 0, 1), - (13, 1012, 701, 603, 18446744073709551615, 0, 1), - (13, 245, 702, 602, 18446744073709551615, 0, 1), - (13, 1014, 703, 601, 18446744073709551615, 0, 1), - (13, 1015, 704, 600, 18446744073709551615, 0, 1), - (13, 248, 705, 599, 18446744073709551615, 0, 1), - (13, 1017, 706, 598, 18446744073709551615, 0, 1), - (13, 1018, 707, 597, 18446744073709551615, 0, 1), - (13, 251, 611, 596, 18446744073709551615, 0, 1), - (13, 1020, 610, 595, 18446744073709551615, 0, 1), - (13, 1021, 730, 594, 18446744073709551615, 0, 1), - (13, 254, 731, 593, 18446744073709551615, 0, 1), - (13, 1023, 128, 592, 18446744073709551615, 0, 1), - (13, 1049, 1093, 591, 18446744073709551615, 0, 1), - (13, 155, 692, 691, 18446744073709551615, 0, 2), - (13, 935, 688, 687, 18446744073709551615, 0, 2), - (13, 929, 687, 686, 18446744073709551615, 0, 2), - (13, 161, 613, 729, 18446744073709551615, 0, 2), - (13, 164, 729, 728, 18446744073709551615, 0, 2), - (13, 162, 728, 727, 18446744073709551615, 0, 2), - (13, 167, 727, 726, 18446744073709551615, 0, 2), - (13, 936, 726, 725, 18446744073709551615, 0, 2), - (13, 937, 725, 724, 18446744073709551615, 0, 2), - (13, 170, 724, 723, 18446744073709551615, 0, 2), - (13, 168, 723, 722, 18446744073709551615, 0, 2), - (13, 156, 722, 721, 18446744073709551615, 0, 2), - (13, 1082, 721, 720, 18446744073709551615, 0, 2), - (13, 942, 720, 719, 18446744073709551615, 0, 2), - (13, 943, 719, 718, 18446744073709551615, 0, 2), - (13, 176, 718, 717, 18446744073709551615, 0, 2), - (13, 945, 717, 716, 18446744073709551615, 0, 2), - (13, 946, 716, 715, 18446744073709551615, 0, 2), - (13, 179, 715, 714, 18446744073709551615, 0, 2), - (13, 948, 714, 713, 18446744073709551615, 0, 2), - (13, 949, 713, 712, 18446744073709551615, 0, 2), - (13, 182, 712, 711, 18446744073709551615, 0, 2), - (13, 951, 711, 710, 18446744073709551615, 0, 2), - (13, 952, 710, 709, 18446744073709551615, 0, 2), - (13, 185, 709, 708, 18446744073709551615, 0, 2), - (13, 954, 708, 614, 18446744073709551615, 0, 2), - (13, 955, 614, 615, 18446744073709551615, 0, 2), - (13, 188, 615, 616, 18446744073709551615, 0, 2), - (13, 957, 616, 617, 18446744073709551615, 0, 2), - (13, 958, 617, 618, 18446744073709551615, 0, 2), - (13, 191, 618, 619, 18446744073709551615, 0, 2), - (13, 960, 619, 620, 18446744073709551615, 0, 2), - (13, 961, 620, 621, 18446744073709551615, 0, 2), - (13, 194, 621, 622, 18446744073709551615, 0, 2), - (13, 963, 622, 623, 18446744073709551615, 0, 2), - (13, 964, 623, 624, 18446744073709551615, 0, 2), - (13, 197, 624, 625, 18446744073709551615, 0, 2), - (13, 966, 625, 626, 18446744073709551615, 0, 2), - (13, 967, 626, 627, 18446744073709551615, 0, 2), - (13, 200, 627, 628, 18446744073709551615, 0, 2), - (13, 969, 628, 629, 18446744073709551615, 0, 2), - (13, 970, 629, 630, 18446744073709551615, 0, 2), - (13, 203, 630, 631, 18446744073709551615, 0, 2), - (13, 972, 631, 632, 18446744073709551615, 0, 2), - (13, 973, 632, 633, 18446744073709551615, 0, 2), - (13, 206, 633, 634, 18446744073709551615, 0, 2), - (13, 975, 634, 635, 18446744073709551615, 0, 2), - (13, 976, 635, 636, 18446744073709551615, 0, 2), - (13, 209, 636, 637, 18446744073709551615, 0, 2), - (13, 978, 637, 638, 18446744073709551615, 0, 2), - (13, 979, 638, 639, 18446744073709551615, 0, 2), - (13, 212, 639, 640, 18446744073709551615, 0, 2), - (13, 981, 640, 641, 18446744073709551615, 0, 2), - (13, 982, 641, 642, 18446744073709551615, 0, 2), - (13, 215, 642, 643, 18446744073709551615, 0, 2), - (13, 984, 643, 644, 18446744073709551615, 0, 2), - (13, 985, 644, 645, 18446744073709551615, 0, 2), - (13, 218, 645, 646, 18446744073709551615, 0, 2), - (13, 987, 646, 647, 18446744073709551615, 0, 2), - (13, 988, 647, 648, 18446744073709551615, 0, 2), - (13, 221, 648, 649, 18446744073709551615, 0, 2), - (13, 990, 649, 650, 18446744073709551615, 0, 2), - (13, 991, 650, 651, 18446744073709551615, 0, 2), - (13, 224, 651, 652, 18446744073709551615, 0, 2), - (13, 993, 652, 653, 18446744073709551615, 0, 2), - (13, 994, 653, 654, 18446744073709551615, 0, 2), - (13, 227, 654, 655, 18446744073709551615, 0, 2), - (13, 996, 655, 656, 18446744073709551615, 0, 2), - (13, 997, 656, 657, 18446744073709551615, 0, 2), - (13, 230, 657, 658, 18446744073709551615, 0, 2), - (13, 999, 658, 659, 18446744073709551615, 0, 2), - (13, 1000, 659, 660, 18446744073709551615, 0, 2), - (13, 233, 660, 661, 18446744073709551615, 0, 2), - (13, 1002, 661, 662, 18446744073709551615, 0, 2), - (13, 1003, 662, 663, 18446744073709551615, 0, 2), - (13, 236, 663, 664, 18446744073709551615, 0, 2), - (13, 1005, 664, 665, 18446744073709551615, 0, 2), - (13, 1006, 665, 666, 18446744073709551615, 0, 2), - (13, 239, 666, 667, 18446744073709551615, 0, 2), - (13, 1008, 667, 668, 18446744073709551615, 0, 2), - (13, 1009, 668, 669, 18446744073709551615, 0, 2), - (13, 242, 669, 670, 18446744073709551615, 0, 2), - (13, 1011, 670, 671, 18446744073709551615, 0, 2), - (13, 1012, 671, 672, 18446744073709551615, 0, 2), - (13, 245, 672, 673, 18446744073709551615, 0, 2), - (13, 1014, 673, 674, 18446744073709551615, 0, 2), - (13, 1015, 674, 675, 18446744073709551615, 0, 2), - (13, 248, 675, 676, 18446744073709551615, 0, 2), - (13, 1017, 676, 677, 18446744073709551615, 0, 2), - (13, 1018, 677, 678, 18446744073709551615, 0, 2), - (13, 251, 678, 679, 18446744073709551615, 0, 2), - (13, 1020, 679, 680, 18446744073709551615, 0, 2), - (13, 1021, 680, 681, 18446744073709551615, 0, 2), - (13, 254, 681, 682, 18446744073709551615, 0, 2), - (13, 1023, 682, 683, 18446744073709551615, 0, 2), - (13, 683, 1049, 684, 18446744073709551615, 0, 1), - (13, 1023, 682, 683, 18446744073709551615, 1, 2), - (13, 254, 681, 682, 18446744073709551615, 1, 2), - (13, 1021, 680, 681, 18446744073709551615, 1, 2), - (13, 1020, 679, 680, 18446744073709551615, 1, 2), - (13, 251, 678, 679, 18446744073709551615, 1, 2), - (13, 1018, 677, 678, 18446744073709551615, 1, 2), - (13, 1017, 676, 677, 18446744073709551615, 1, 2), - (13, 248, 675, 676, 18446744073709551615, 1, 2), - (13, 1015, 674, 675, 18446744073709551615, 1, 2), - (13, 1014, 673, 674, 18446744073709551615, 1, 2), - (13, 245, 672, 673, 18446744073709551615, 1, 2), - (13, 1012, 671, 672, 18446744073709551615, 1, 2), - (13, 1011, 670, 671, 18446744073709551615, 1, 2), - (13, 242, 669, 670, 18446744073709551615, 1, 2), - (13, 1009, 668, 669, 18446744073709551615, 1, 2), - (13, 1008, 667, 668, 18446744073709551615, 1, 2), - (13, 239, 666, 667, 18446744073709551615, 1, 2), - (13, 1006, 665, 666, 18446744073709551615, 1, 2), - (13, 1005, 664, 665, 18446744073709551615, 1, 2), - (13, 236, 663, 664, 18446744073709551615, 1, 2), - (13, 1003, 662, 663, 18446744073709551615, 1, 2), - (13, 1002, 661, 662, 18446744073709551615, 1, 2), - (13, 233, 660, 661, 18446744073709551615, 1, 2), - (13, 1000, 659, 660, 18446744073709551615, 1, 2), - (13, 999, 658, 659, 18446744073709551615, 1, 2), - (13, 230, 657, 658, 18446744073709551615, 1, 2), - (13, 997, 656, 657, 18446744073709551615, 1, 2), - (13, 996, 655, 656, 18446744073709551615, 1, 2), - (13, 227, 654, 655, 18446744073709551615, 1, 2), - (13, 994, 653, 654, 18446744073709551615, 1, 2), - (13, 993, 652, 653, 18446744073709551615, 1, 2), - (13, 224, 651, 652, 18446744073709551615, 1, 2), - (13, 991, 650, 651, 18446744073709551615, 1, 2), - (13, 990, 649, 650, 18446744073709551615, 1, 2), - (13, 221, 648, 649, 18446744073709551615, 1, 2), - (13, 988, 647, 648, 18446744073709551615, 1, 2), - (13, 987, 646, 647, 18446744073709551615, 1, 2), - (13, 218, 645, 646, 18446744073709551615, 1, 2), - (13, 985, 644, 645, 18446744073709551615, 1, 2), - (13, 984, 643, 644, 18446744073709551615, 1, 2), - (13, 215, 642, 643, 18446744073709551615, 1, 2), - (13, 982, 641, 642, 18446744073709551615, 1, 2), - (13, 981, 640, 641, 18446744073709551615, 1, 2), - (13, 212, 639, 640, 18446744073709551615, 1, 2), - (13, 979, 638, 639, 18446744073709551615, 1, 2), - (13, 978, 637, 638, 18446744073709551615, 1, 2), - (13, 209, 636, 637, 18446744073709551615, 1, 2), - (13, 976, 635, 636, 18446744073709551615, 1, 2), - (13, 975, 634, 635, 18446744073709551615, 1, 2), - (13, 206, 633, 634, 18446744073709551615, 1, 2), - (13, 973, 632, 633, 18446744073709551615, 1, 2), - (13, 972, 631, 632, 18446744073709551615, 1, 2), - (13, 203, 630, 631, 18446744073709551615, 1, 2), - (13, 970, 629, 630, 18446744073709551615, 1, 2), - (13, 969, 628, 629, 18446744073709551615, 1, 2), - (13, 200, 627, 628, 18446744073709551615, 1, 2), - (13, 967, 626, 627, 18446744073709551615, 1, 2), - (13, 966, 625, 626, 18446744073709551615, 1, 2), - (13, 197, 624, 625, 18446744073709551615, 1, 2), - (13, 964, 623, 624, 18446744073709551615, 1, 2), - (13, 963, 622, 623, 18446744073709551615, 1, 2), - (13, 194, 621, 622, 18446744073709551615, 1, 2), - (13, 961, 620, 621, 18446744073709551615, 1, 2), - (13, 960, 619, 620, 18446744073709551615, 1, 2), - (13, 191, 618, 619, 18446744073709551615, 1, 2), - (13, 958, 617, 618, 18446744073709551615, 1, 2), - (13, 957, 616, 617, 18446744073709551615, 1, 2), - (13, 188, 615, 616, 18446744073709551615, 1, 2), - (13, 955, 614, 615, 18446744073709551615, 1, 2), - (13, 954, 708, 614, 18446744073709551615, 1, 2), - (13, 185, 709, 708, 18446744073709551615, 1, 2), - (13, 952, 710, 709, 18446744073709551615, 1, 2), - (13, 951, 711, 710, 18446744073709551615, 1, 2), - (13, 182, 712, 711, 18446744073709551615, 1, 2), - (13, 949, 713, 712, 18446744073709551615, 1, 2), - (13, 948, 714, 713, 18446744073709551615, 1, 2), - (13, 179, 715, 714, 18446744073709551615, 1, 2), - (13, 946, 716, 715, 18446744073709551615, 1, 2), - (13, 945, 717, 716, 18446744073709551615, 1, 2), - (13, 176, 718, 717, 18446744073709551615, 1, 2), - (13, 943, 719, 718, 18446744073709551615, 1, 2), - (13, 942, 720, 719, 18446744073709551615, 1, 2), - (13, 1082, 721, 720, 18446744073709551615, 1, 2), - (13, 156, 722, 721, 18446744073709551615, 1, 2), - (13, 168, 723, 722, 18446744073709551615, 1, 2), - (13, 170, 724, 723, 18446744073709551615, 1, 2), - (13, 937, 725, 724, 18446744073709551615, 1, 2), - (13, 936, 726, 725, 18446744073709551615, 1, 2), - (13, 167, 727, 726, 18446744073709551615, 1, 2), - (13, 162, 728, 727, 18446744073709551615, 1, 2), - (13, 164, 729, 728, 18446744073709551615, 1, 2), - (13, 161, 613, 729, 18446744073709551615, 1, 2), - (13, 929, 687, 686, 18446744073709551615, 1, 2), - (13, 935, 688, 687, 18446744073709551615, 1, 2), - (13, 155, 692, 691, 18446744073709551615, 1, 2), - (13, 684, 755, 685, 18446744073709551615, 0, 1), - (13, 754, 685, 609, 18446744073709551615, 0, 1), - (13, 753, 609, 608, 18446744073709551615, 2, 3), - (13, 752, 608, 607, 18446744073709551615, 2, 3), - (13, 751, 607, 606, 18446744073709551615, 2, 3), - (13, 750, 606, 732, 18446744073709551615, 2, 3), - (13, 749, 732, 733, 18446744073709551615, 2, 3), - (13, 748, 733, 605, 18446744073709551615, 2, 3), - (13, 747, 605, 604, 18446744073709551615, 2, 3), - (13, 14, 604, 603, 18446744073709551615, 2, 3), - (13, 11, 603, 602, 18446744073709551615, 2, 3), - (13, 777, 602, 601, 18446744073709551615, 2, 3), - (13, 13, 601, 600, 18446744073709551615, 2, 3), - (13, 1145, 600, 599, 18446744073709551615, 2, 3), - (13, 1137, 599, 598, 18446744073709551615, 2, 3), - (13, 17, 598, 597, 18446744073709551615, 2, 3), - (13, 1134, 597, 596, 18446744073709551615, 2, 3), - (13, 27, 596, 595, 18446744073709551615, 2, 3), - (13, 786, 595, 594, 18446744073709551615, 2, 3), - (13, 787, 594, 593, 18446744073709551615, 2, 3), - (13, 788, 593, 592, 18446744073709551615, 2, 3), - (13, 789, 592, 591, 18446744073709551615, 2, 3), - (13, 790, 591, 590, 18446744073709551615, 2, 3), - (13, 791, 590, 589, 18446744073709551615, 2, 3), - (13, 23, 589, 588, 18446744073709551615, 2, 3), - (13, 20, 588, 587, 18446744073709551615, 2, 3), - (13, 18, 587, 586, 18446744073709551615, 2, 3), - (13, 795, 586, 585, 18446744073709551615, 2, 3), - (13, 796, 585, 584, 18446744073709551615, 2, 3), - (13, 797, 584, 583, 18446744073709551615, 2, 3), - (13, 798, 583, 582, 18446744073709551615, 2, 3), - (13, 799, 582, 581, 18446744073709551615, 2, 3), - (13, 800, 581, 580, 18446744073709551615, 2, 3), - (13, 801, 580, 579, 18446744073709551615, 2, 3), - (13, 802, 579, 578, 18446744073709551615, 2, 3), - (13, 803, 578, 577, 18446744073709551615, 2, 3), - (13, 804, 577, 576, 18446744073709551615, 2, 3), - (13, 805, 576, 575, 18446744073709551615, 2, 3), - (13, 806, 575, 574, 18446744073709551615, 2, 3), - (13, 807, 574, 573, 18446744073709551615, 2, 3), - (13, 808, 573, 572, 18446744073709551615, 2, 3), - (13, 809, 572, 571, 18446744073709551615, 2, 3), - (13, 810, 571, 570, 18446744073709551615, 2, 3), - (13, 811, 570, 569, 18446744073709551615, 2, 3), - (13, 812, 569, 568, 18446744073709551615, 2, 3), - (13, 813, 568, 567, 18446744073709551615, 2, 3), - (13, 814, 567, 566, 18446744073709551615, 2, 3), - (13, 815, 566, 564, 18446744073709551615, 2, 3), - (13, 816, 564, 563, 18446744073709551615, 4, 6), - (13, 817, 563, 565, 18446744073709551615, 2, 3), - (13, 818, 565, 563, 18446744073709551615, 2, 3), - (13, 819, 563, 564, 18446744073709551615, 2, 3), - (14, 684, 819, 563, 18446744073709551615, 0, 1), - (14, 684, 817, 563, 18446744073709551615, 0, 1), - (13, 665, 1006, 608, 18446744073709551615, 0, 1), - (13, 666, 239, 607, 18446744073709551615, 0, 1), - (13, 667, 1008, 606, 18446744073709551615, 0, 1), - (13, 668, 1009, 732, 18446744073709551615, 0, 1), - (13, 669, 242, 733, 18446744073709551615, 0, 1), - (13, 670, 1011, 605, 18446744073709551615, 0, 1), - (13, 671, 1012, 604, 18446744073709551615, 0, 1), - (13, 672, 245, 603, 18446744073709551615, 0, 1), - (13, 673, 1014, 602, 18446744073709551615, 0, 1), - (13, 674, 1015, 601, 18446744073709551615, 0, 1), - (13, 675, 248, 600, 18446744073709551615, 0, 1), - (13, 676, 1017, 599, 18446744073709551615, 0, 1), - (13, 677, 1018, 598, 18446744073709551615, 0, 1), - (13, 678, 251, 597, 18446744073709551615, 0, 1), - (13, 679, 1020, 596, 18446744073709551615, 0, 1), - (13, 680, 1021, 595, 18446744073709551615, 0, 1), - (13, 681, 254, 594, 18446744073709551615, 0, 1), - (13, 682, 1023, 593, 18446744073709551615, 0, 1), - (13, 683, 1049, 592, 18446744073709551615, 0, 1), - (13, 935, 662, 661, 18446744073709551615, 0, 2), - (13, 933, 660, 659, 18446744073709551615, 0, 2), - (13, 165, 659, 658, 18446744073709551615, 0, 2), - (13, 161, 658, 657, 18446744073709551615, 0, 2), - (13, 164, 657, 656, 18446744073709551615, 0, 2), - (13, 162, 656, 655, 18446744073709551615, 0, 2), - (13, 167, 655, 654, 18446744073709551615, 0, 2), - (13, 936, 654, 653, 18446744073709551615, 0, 2), - (13, 937, 653, 652, 18446744073709551615, 0, 2), - (13, 170, 652, 651, 18446744073709551615, 0, 2), - (13, 168, 651, 650, 18446744073709551615, 0, 2), - (13, 156, 650, 649, 18446744073709551615, 0, 2), - (13, 1082, 649, 648, 18446744073709551615, 0, 2), - (13, 942, 648, 647, 18446744073709551615, 0, 2), - (13, 943, 647, 646, 18446744073709551615, 0, 2), - (13, 176, 646, 645, 18446744073709551615, 0, 2), - (13, 945, 645, 644, 18446744073709551615, 0, 2), - (13, 946, 644, 643, 18446744073709551615, 0, 2), - (13, 179, 643, 642, 18446744073709551615, 0, 2), - (13, 948, 642, 641, 18446744073709551615, 0, 2), - (13, 949, 641, 640, 18446744073709551615, 0, 2), - (13, 182, 640, 639, 18446744073709551615, 0, 2), - (13, 951, 639, 638, 18446744073709551615, 0, 2), - (13, 952, 638, 637, 18446744073709551615, 0, 2), - (13, 185, 637, 636, 18446744073709551615, 0, 2), - (13, 954, 636, 635, 18446744073709551615, 0, 2), - (13, 955, 635, 634, 18446744073709551615, 0, 2), - (13, 188, 634, 633, 18446744073709551615, 0, 2), - (13, 957, 633, 632, 18446744073709551615, 0, 2), - (13, 958, 632, 631, 18446744073709551615, 0, 2), - (13, 191, 631, 630, 18446744073709551615, 0, 2), - (13, 960, 630, 629, 18446744073709551615, 0, 2), - (13, 961, 629, 628, 18446744073709551615, 0, 2), - (13, 194, 628, 627, 18446744073709551615, 0, 2), - (13, 963, 627, 626, 18446744073709551615, 0, 2), - (13, 964, 626, 625, 18446744073709551615, 0, 2), - (13, 197, 625, 624, 18446744073709551615, 0, 2), - (13, 966, 624, 623, 18446744073709551615, 0, 2), - (13, 967, 623, 622, 18446744073709551615, 0, 2), - (13, 200, 622, 621, 18446744073709551615, 0, 2), - (13, 969, 621, 620, 18446744073709551615, 0, 2), - (13, 970, 620, 619, 18446744073709551615, 0, 2), - (13, 203, 619, 618, 18446744073709551615, 0, 2), - (13, 972, 618, 617, 18446744073709551615, 0, 2), - (13, 973, 617, 616, 18446744073709551615, 0, 2), - (13, 206, 616, 615, 18446744073709551615, 0, 2), - (13, 975, 615, 614, 18446744073709551615, 0, 2), - (13, 976, 614, 708, 18446744073709551615, 0, 2), - (13, 209, 708, 709, 18446744073709551615, 0, 2), - (13, 978, 709, 710, 18446744073709551615, 0, 2), - (13, 979, 710, 711, 18446744073709551615, 0, 2), - (13, 212, 711, 712, 18446744073709551615, 0, 2), - (13, 981, 712, 713, 18446744073709551615, 0, 2), - (13, 982, 713, 714, 18446744073709551615, 0, 2), - (13, 215, 714, 715, 18446744073709551615, 0, 2), - (13, 984, 715, 716, 18446744073709551615, 0, 2), - (13, 985, 716, 717, 18446744073709551615, 0, 2), - (13, 218, 717, 718, 18446744073709551615, 0, 2), - (13, 987, 718, 719, 18446744073709551615, 0, 2), - (13, 988, 719, 720, 18446744073709551615, 0, 2), - (13, 221, 720, 721, 18446744073709551615, 0, 2), - (13, 990, 721, 722, 18446744073709551615, 0, 2), - (13, 991, 722, 723, 18446744073709551615, 0, 2), - (13, 224, 723, 724, 18446744073709551615, 0, 2), - (13, 993, 724, 725, 18446744073709551615, 0, 2), - (13, 994, 725, 726, 18446744073709551615, 0, 2), - (13, 227, 726, 727, 18446744073709551615, 0, 2), - (13, 996, 727, 728, 18446744073709551615, 0, 2), - (13, 997, 728, 729, 18446744073709551615, 0, 2), - (13, 230, 729, 613, 18446744073709551615, 0, 2), - (13, 999, 613, 612, 18446744073709551615, 0, 2), - (13, 1000, 612, 686, 18446744073709551615, 0, 2), - (13, 233, 686, 687, 18446744073709551615, 2, 4), - (13, 1002, 687, 688, 18446744073709551615, 2, 4), - (13, 1003, 688, 689, 18446744073709551615, 2, 4), - (13, 236, 689, 690, 18446744073709551615, 2, 4), - (13, 1005, 690, 691, 18446744073709551615, 2, 4), - (13, 1006, 691, 692, 18446744073709551615, 2, 4), - (13, 239, 692, 693, 18446744073709551615, 2, 4), - (13, 1008, 693, 694, 18446744073709551615, 2, 4), - (13, 1009, 694, 695, 18446744073709551615, 2, 4), - (13, 242, 695, 696, 18446744073709551615, 2, 4), - (13, 1011, 696, 697, 18446744073709551615, 2, 4), - (13, 1012, 697, 698, 18446744073709551615, 2, 4), - (13, 245, 698, 699, 18446744073709551615, 2, 4), - (13, 1014, 699, 700, 18446744073709551615, 2, 4), - (13, 1015, 700, 701, 18446744073709551615, 2, 4), - (13, 248, 701, 702, 18446744073709551615, 2, 4), - (13, 1017, 702, 703, 18446744073709551615, 2, 4), - (13, 1018, 703, 704, 18446744073709551615, 2, 4), - (13, 251, 704, 705, 18446744073709551615, 2, 4), - (13, 1020, 705, 706, 18446744073709551615, 2, 4), - (13, 1021, 706, 707, 18446744073709551615, 2, 4), - (13, 254, 707, 611, 18446744073709551615, 0, 2), - (13, 1023, 611, 610, 18446744073709551615, 2, 4), - (13, 610, 1049, 730, 18446744073709551615, 0, 1), - (13, 1023, 611, 610, 18446744073709551615, 3, 4), - (13, 254, 707, 611, 18446744073709551615, 1, 2), - (13, 1021, 706, 707, 18446744073709551615, 3, 4), - (13, 1020, 705, 706, 18446744073709551615, 3, 4), - (13, 251, 704, 705, 18446744073709551615, 3, 4), - (13, 1018, 703, 704, 18446744073709551615, 3, 4), - (13, 1017, 702, 703, 18446744073709551615, 3, 4), - (13, 248, 701, 702, 18446744073709551615, 3, 4), - (13, 1015, 700, 701, 18446744073709551615, 3, 4), - (13, 1014, 699, 700, 18446744073709551615, 3, 4), - (13, 245, 698, 699, 18446744073709551615, 3, 4), - (13, 1012, 697, 698, 18446744073709551615, 3, 4), - (13, 1011, 696, 697, 18446744073709551615, 3, 4), - (13, 242, 695, 696, 18446744073709551615, 3, 4), - (13, 1009, 694, 695, 18446744073709551615, 3, 4), - (13, 1008, 693, 694, 18446744073709551615, 3, 4), - (13, 239, 692, 693, 18446744073709551615, 3, 4), - (13, 1006, 691, 692, 18446744073709551615, 3, 4), - (13, 1005, 690, 691, 18446744073709551615, 3, 4), - (13, 236, 689, 690, 18446744073709551615, 3, 4), - (13, 1003, 688, 689, 18446744073709551615, 3, 4), - (13, 1002, 687, 688, 18446744073709551615, 3, 4), - (13, 233, 686, 687, 18446744073709551615, 3, 4), - (13, 1000, 612, 686, 18446744073709551615, 1, 2), - (13, 999, 613, 612, 18446744073709551615, 1, 2), - (13, 230, 729, 613, 18446744073709551615, 1, 2), - (13, 997, 728, 729, 18446744073709551615, 1, 2), - (13, 996, 727, 728, 18446744073709551615, 1, 2), - (13, 227, 726, 727, 18446744073709551615, 1, 2), - (13, 994, 725, 726, 18446744073709551615, 1, 2), - (13, 993, 724, 725, 18446744073709551615, 1, 2), - (13, 224, 723, 724, 18446744073709551615, 1, 2), - (13, 991, 722, 723, 18446744073709551615, 1, 2), - (13, 990, 721, 722, 18446744073709551615, 1, 2), - (13, 221, 720, 721, 18446744073709551615, 1, 2), - (13, 988, 719, 720, 18446744073709551615, 1, 2), - (13, 987, 718, 719, 18446744073709551615, 1, 2), - (13, 218, 717, 718, 18446744073709551615, 1, 2), - (13, 985, 716, 717, 18446744073709551615, 1, 2), - (13, 984, 715, 716, 18446744073709551615, 1, 2), - (13, 215, 714, 715, 18446744073709551615, 1, 2), - (13, 982, 713, 714, 18446744073709551615, 1, 2), - (13, 981, 712, 713, 18446744073709551615, 1, 2), - (13, 212, 711, 712, 18446744073709551615, 1, 2), - (13, 979, 710, 711, 18446744073709551615, 1, 2), - (13, 978, 709, 710, 18446744073709551615, 1, 2), - (13, 209, 708, 709, 18446744073709551615, 1, 2), - (13, 976, 614, 708, 18446744073709551615, 1, 2), - (13, 975, 615, 614, 18446744073709551615, 1, 2), - (13, 206, 616, 615, 18446744073709551615, 1, 2), - (13, 973, 617, 616, 18446744073709551615, 1, 2), - (13, 972, 618, 617, 18446744073709551615, 1, 2), - (13, 203, 619, 618, 18446744073709551615, 1, 2), - (13, 970, 620, 619, 18446744073709551615, 1, 2), - (13, 969, 621, 620, 18446744073709551615, 1, 2), - (13, 200, 622, 621, 18446744073709551615, 1, 2), - (13, 967, 623, 622, 18446744073709551615, 1, 2), - (13, 966, 624, 623, 18446744073709551615, 1, 2), - (13, 197, 625, 624, 18446744073709551615, 1, 2), - (13, 964, 626, 625, 18446744073709551615, 1, 2), - (13, 963, 627, 626, 18446744073709551615, 1, 2), - (13, 194, 628, 627, 18446744073709551615, 1, 2), - (13, 961, 629, 628, 18446744073709551615, 1, 2), - (13, 960, 630, 629, 18446744073709551615, 1, 2), - (13, 191, 631, 630, 18446744073709551615, 1, 2), - (13, 958, 632, 631, 18446744073709551615, 1, 2), - (13, 957, 633, 632, 18446744073709551615, 1, 2), - (13, 188, 634, 633, 18446744073709551615, 1, 2), - (13, 955, 635, 634, 18446744073709551615, 1, 2), - (13, 954, 636, 635, 18446744073709551615, 1, 2), - (13, 185, 637, 636, 18446744073709551615, 1, 2), - (13, 952, 638, 637, 18446744073709551615, 1, 2), - (13, 951, 639, 638, 18446744073709551615, 1, 2), - (13, 182, 640, 639, 18446744073709551615, 1, 2), - (13, 949, 641, 640, 18446744073709551615, 1, 2), - (13, 948, 642, 641, 18446744073709551615, 1, 2), - (13, 179, 643, 642, 18446744073709551615, 1, 2), - (13, 946, 644, 643, 18446744073709551615, 1, 2), - (13, 945, 645, 644, 18446744073709551615, 1, 2), - (13, 176, 646, 645, 18446744073709551615, 1, 2), - (13, 943, 647, 646, 18446744073709551615, 1, 2), - (13, 942, 648, 647, 18446744073709551615, 1, 2), - (13, 1082, 649, 648, 18446744073709551615, 1, 2), - (13, 156, 650, 649, 18446744073709551615, 1, 2), - (13, 168, 651, 650, 18446744073709551615, 1, 2), - (13, 170, 652, 651, 18446744073709551615, 1, 2), - (13, 937, 653, 652, 18446744073709551615, 1, 2), - (13, 936, 654, 653, 18446744073709551615, 1, 2), - (13, 167, 655, 654, 18446744073709551615, 1, 2), - (13, 162, 656, 655, 18446744073709551615, 1, 2), - (13, 164, 657, 656, 18446744073709551615, 1, 2), - (13, 161, 658, 657, 18446744073709551615, 1, 2), - (13, 165, 659, 658, 18446744073709551615, 1, 2), - (13, 933, 660, 659, 18446744073709551615, 1, 2), - (13, 935, 662, 661, 18446744073709551615, 1, 2), - (13, 730, 755, 731, 18446744073709551615, 1, 2), - (13, 754, 731, 128, 18446744073709551615, 0, 1), - (13, 753, 128, 1093, 18446744073709551615, 0, 1), - (13, 752, 1093, 684, 18446744073709551615, 0, 1), - (13, 751, 684, 685, 18446744073709551615, 0, 1), - (13, 750, 685, 609, 18446744073709551615, 0, 1), - (13, 749, 609, 608, 18446744073709551615, 2, 3), - (13, 748, 608, 607, 18446744073709551615, 2, 3), - (13, 747, 607, 606, 18446744073709551615, 2, 3), - (13, 14, 606, 732, 18446744073709551615, 2, 3), - (13, 11, 732, 733, 18446744073709551615, 2, 3), - (13, 777, 733, 605, 18446744073709551615, 2, 3), - (13, 13, 605, 604, 18446744073709551615, 2, 3), - (13, 1145, 604, 603, 18446744073709551615, 2, 3), - (13, 1137, 603, 602, 18446744073709551615, 2, 3), - (13, 17, 602, 601, 18446744073709551615, 2, 3), - (13, 1134, 601, 600, 18446744073709551615, 2, 3), - (13, 27, 600, 599, 18446744073709551615, 2, 3), - (13, 786, 599, 598, 18446744073709551615, 2, 3), - (13, 787, 598, 597, 18446744073709551615, 2, 3), - (13, 788, 597, 596, 18446744073709551615, 2, 3), - (13, 789, 596, 595, 18446744073709551615, 2, 3), - (13, 790, 595, 594, 18446744073709551615, 2, 3), - (13, 791, 594, 593, 18446744073709551615, 2, 3), - (13, 23, 593, 592, 18446744073709551615, 2, 3), - (13, 20, 592, 591, 18446744073709551615, 2, 3), - (13, 18, 591, 590, 18446744073709551615, 2, 3), - (13, 795, 590, 589, 18446744073709551615, 2, 3), - (13, 796, 589, 588, 18446744073709551615, 2, 3), - (13, 797, 588, 587, 18446744073709551615, 2, 3), - (13, 798, 587, 586, 18446744073709551615, 2, 3), - (13, 799, 586, 585, 18446744073709551615, 2, 3), - (13, 800, 585, 584, 18446744073709551615, 2, 3), - (13, 801, 584, 583, 18446744073709551615, 2, 3), - (13, 802, 583, 582, 18446744073709551615, 2, 3), - (13, 803, 582, 581, 18446744073709551615, 2, 3), - (13, 804, 581, 580, 18446744073709551615, 2, 3), - (13, 805, 580, 579, 18446744073709551615, 2, 3), - (13, 806, 579, 578, 18446744073709551615, 2, 3), - (13, 807, 578, 577, 18446744073709551615, 2, 3), - (13, 808, 577, 576, 18446744073709551615, 2, 3), - (13, 809, 576, 575, 18446744073709551615, 2, 3), - (13, 810, 575, 574, 18446744073709551615, 2, 3), - (13, 811, 574, 573, 18446744073709551615, 2, 3), - (13, 812, 573, 572, 18446744073709551615, 2, 3), - (13, 813, 572, 571, 18446744073709551615, 2, 3), - (13, 814, 571, 570, 18446744073709551615, 2, 3), - (13, 815, 570, 568, 18446744073709551615, 2, 3), - (13, 816, 568, 567, 18446744073709551615, 4, 6), - (13, 817, 567, 569, 18446744073709551615, 2, 3), - (13, 818, 569, 567, 18446744073709551615, 2, 3), - (13, 819, 567, 568, 18446744073709551615, 2, 3), - (14, 730, 819, 567, 18446744073709551615, 0, 1), - (14, 730, 817, 567, 18446744073709551615, 0, 1), - (13, 1006, 691, 128, 18446744073709551615, 0, 1), - (13, 239, 692, 1093, 18446744073709551615, 0, 1), - (13, 1008, 693, 684, 18446744073709551615, 0, 1), - (13, 1009, 694, 685, 18446744073709551615, 0, 1), - (13, 242, 695, 609, 18446744073709551615, 0, 1), - (13, 1011, 696, 608, 18446744073709551615, 0, 1), - (13, 1012, 697, 607, 18446744073709551615, 0, 1), - (13, 245, 698, 606, 18446744073709551615, 0, 1), - (13, 1014, 699, 732, 18446744073709551615, 0, 1), - (13, 1015, 700, 733, 18446744073709551615, 0, 1), - (13, 248, 701, 605, 18446744073709551615, 0, 1), - (13, 1017, 702, 604, 18446744073709551615, 0, 1), - (13, 1018, 703, 603, 18446744073709551615, 0, 1), - (13, 251, 704, 602, 18446744073709551615, 0, 1), - (13, 1020, 705, 601, 18446744073709551615, 0, 1), - (13, 1021, 706, 600, 18446744073709551615, 0, 1), - (13, 254, 707, 599, 18446744073709551615, 0, 1), - (13, 1023, 611, 598, 18446744073709551615, 0, 1), - (13, 1049, 610, 597, 18446744073709551615, 0, 1), - (13, 182, 688, 1150, 18446744073709551615, 0, 1), - (13, 952, 686, 1132, 18446744073709551615, 0, 1), - (13, 185, 612, 12, 18446744073709551615, 0, 1), - (13, 954, 613, 1141, 18446744073709551615, 0, 1), - (13, 955, 729, 10, 18446744073709551615, 0, 1), - (13, 188, 728, 793, 18446744073709551615, 0, 1), - (13, 957, 727, 9, 18446744073709551615, 0, 1), - (13, 958, 726, 1147, 18446744073709551615, 0, 1), - (13, 191, 725, 1153, 18446744073709551615, 0, 1), - (13, 960, 724, 723, 18446744073709551615, 0, 2), - (13, 961, 723, 722, 18446744073709551615, 0, 2), - (13, 194, 722, 721, 18446744073709551615, 0, 2), - (13, 963, 721, 720, 18446744073709551615, 0, 2), - (13, 964, 720, 719, 18446744073709551615, 0, 2), - (13, 197, 719, 718, 18446744073709551615, 0, 2), - (13, 966, 718, 717, 18446744073709551615, 0, 2), - (13, 967, 717, 716, 18446744073709551615, 0, 2), - (13, 200, 716, 715, 18446744073709551615, 0, 2), - (13, 969, 715, 714, 18446744073709551615, 0, 2), - (13, 970, 714, 713, 18446744073709551615, 0, 2), - (13, 203, 713, 712, 18446744073709551615, 0, 2), - (13, 972, 712, 711, 18446744073709551615, 0, 2), - (13, 973, 711, 710, 18446744073709551615, 0, 2), - (13, 206, 710, 709, 18446744073709551615, 0, 2), - (13, 975, 709, 708, 18446744073709551615, 0, 2), - (13, 976, 708, 614, 18446744073709551615, 0, 2), - (13, 209, 614, 615, 18446744073709551615, 0, 2), - (13, 978, 615, 616, 18446744073709551615, 0, 2), - (13, 979, 616, 617, 18446744073709551615, 0, 2), - (13, 212, 617, 618, 18446744073709551615, 0, 2), - (13, 981, 618, 619, 18446744073709551615, 0, 2), - (13, 982, 619, 620, 18446744073709551615, 0, 2), - (13, 215, 620, 621, 18446744073709551615, 0, 2), - (13, 984, 621, 622, 18446744073709551615, 0, 2), - (13, 985, 622, 623, 18446744073709551615, 0, 2), - (13, 218, 623, 624, 18446744073709551615, 0, 2), - (13, 987, 624, 625, 18446744073709551615, 0, 2), - (13, 988, 625, 626, 18446744073709551615, 0, 2), - (13, 221, 626, 627, 18446744073709551615, 0, 2), - (13, 990, 627, 628, 18446744073709551615, 0, 2), - (13, 991, 628, 629, 18446744073709551615, 0, 2), - (13, 224, 629, 630, 18446744073709551615, 0, 2), - (13, 993, 630, 631, 18446744073709551615, 0, 2), - (13, 994, 631, 632, 18446744073709551615, 0, 2), - (13, 227, 632, 633, 18446744073709551615, 0, 2), - (13, 996, 633, 634, 18446744073709551615, 0, 2), - (13, 997, 634, 635, 18446744073709551615, 0, 2), - (13, 230, 635, 636, 18446744073709551615, 0, 2), - (13, 999, 636, 637, 18446744073709551615, 0, 2), - (13, 1000, 637, 638, 18446744073709551615, 0, 2), - (13, 233, 638, 639, 18446744073709551615, 0, 2), - (13, 1002, 639, 640, 18446744073709551615, 0, 2), - (13, 1003, 640, 641, 18446744073709551615, 0, 2), - (13, 236, 641, 642, 18446744073709551615, 0, 2), - (13, 1005, 642, 643, 18446744073709551615, 0, 2), - (13, 1006, 643, 644, 18446744073709551615, 0, 2), - (13, 239, 644, 645, 18446744073709551615, 0, 2), - (13, 1008, 645, 646, 18446744073709551615, 0, 2), - (13, 1009, 646, 647, 18446744073709551615, 0, 2), - (13, 242, 647, 648, 18446744073709551615, 0, 2), - (13, 1011, 648, 649, 18446744073709551615, 0, 2), - (13, 1012, 649, 650, 18446744073709551615, 0, 2), - (13, 245, 650, 651, 18446744073709551615, 0, 2), - (13, 1014, 651, 652, 18446744073709551615, 0, 2), - (13, 1015, 652, 653, 18446744073709551615, 0, 2), - (13, 248, 653, 654, 18446744073709551615, 0, 2), - (13, 1017, 654, 655, 18446744073709551615, 0, 2), - (13, 1018, 655, 656, 18446744073709551615, 0, 2), - (13, 251, 656, 657, 18446744073709551615, 0, 2), - (13, 1020, 657, 658, 18446744073709551615, 0, 2), - (13, 1021, 658, 659, 18446744073709551615, 0, 2), - (13, 254, 659, 660, 18446744073709551615, 0, 2), - (13, 1023, 660, 661, 18446744073709551615, 0, 2), - (13, 661, 1049, 662, 18446744073709551615, 0, 1), - (13, 1023, 660, 661, 18446744073709551615, 1, 2), - (13, 254, 659, 660, 18446744073709551615, 1, 2), - (13, 1021, 658, 659, 18446744073709551615, 1, 2), - (13, 1020, 657, 658, 18446744073709551615, 1, 2), - (13, 251, 656, 657, 18446744073709551615, 1, 2), - (13, 1018, 655, 656, 18446744073709551615, 1, 2), - (13, 1017, 654, 655, 18446744073709551615, 1, 2), - (13, 248, 653, 654, 18446744073709551615, 1, 2), - (13, 1015, 652, 653, 18446744073709551615, 1, 2), - (13, 1014, 651, 652, 18446744073709551615, 1, 2), - (13, 245, 650, 651, 18446744073709551615, 1, 2), - (13, 1012, 649, 650, 18446744073709551615, 1, 2), - (13, 1011, 648, 649, 18446744073709551615, 1, 2), - (13, 242, 647, 648, 18446744073709551615, 1, 2), - (13, 1009, 646, 647, 18446744073709551615, 1, 2), - (13, 1008, 645, 646, 18446744073709551615, 1, 2), - (13, 239, 644, 645, 18446744073709551615, 1, 2), - (13, 1006, 643, 644, 18446744073709551615, 1, 2), - (13, 1005, 642, 643, 18446744073709551615, 1, 2), - (13, 236, 641, 642, 18446744073709551615, 1, 2), - (13, 1003, 640, 641, 18446744073709551615, 1, 2), - (13, 1002, 639, 640, 18446744073709551615, 1, 2), - (13, 233, 638, 639, 18446744073709551615, 1, 2), - (13, 1000, 637, 638, 18446744073709551615, 1, 2), - (13, 999, 636, 637, 18446744073709551615, 1, 2), - (13, 230, 635, 636, 18446744073709551615, 1, 2), - (13, 997, 634, 635, 18446744073709551615, 1, 2), - (13, 996, 633, 634, 18446744073709551615, 1, 2), - (13, 227, 632, 633, 18446744073709551615, 1, 2), - (13, 994, 631, 632, 18446744073709551615, 1, 2), - (13, 993, 630, 631, 18446744073709551615, 1, 2), - (13, 224, 629, 630, 18446744073709551615, 1, 2), - (13, 991, 628, 629, 18446744073709551615, 1, 2), - (13, 990, 627, 628, 18446744073709551615, 1, 2), - (13, 221, 626, 627, 18446744073709551615, 1, 2), - (13, 988, 625, 626, 18446744073709551615, 1, 2), - (13, 987, 624, 625, 18446744073709551615, 1, 2), - (13, 218, 623, 624, 18446744073709551615, 1, 2), - (13, 985, 622, 623, 18446744073709551615, 1, 2), - (13, 984, 621, 622, 18446744073709551615, 1, 2), - (13, 215, 620, 621, 18446744073709551615, 1, 2), - (13, 982, 619, 620, 18446744073709551615, 1, 2), - (13, 981, 618, 619, 18446744073709551615, 1, 2), - (13, 212, 617, 618, 18446744073709551615, 1, 2), - (13, 979, 616, 617, 18446744073709551615, 1, 2), - (13, 978, 615, 616, 18446744073709551615, 1, 2), - (13, 209, 614, 615, 18446744073709551615, 1, 2), - (13, 976, 708, 614, 18446744073709551615, 1, 2), - (13, 975, 709, 708, 18446744073709551615, 1, 2), - (13, 206, 710, 709, 18446744073709551615, 1, 2), - (13, 973, 711, 710, 18446744073709551615, 1, 2), - (13, 972, 712, 711, 18446744073709551615, 1, 2), - (13, 203, 713, 712, 18446744073709551615, 1, 2), - (13, 970, 714, 713, 18446744073709551615, 1, 2), - (13, 969, 715, 714, 18446744073709551615, 1, 2), - (13, 200, 716, 715, 18446744073709551615, 1, 2), - (13, 967, 717, 716, 18446744073709551615, 1, 2), - (13, 966, 718, 717, 18446744073709551615, 1, 2), - (13, 197, 719, 718, 18446744073709551615, 1, 2), - (13, 964, 720, 719, 18446744073709551615, 1, 2), - (13, 963, 721, 720, 18446744073709551615, 1, 2), - (13, 194, 722, 721, 18446744073709551615, 1, 2), - (13, 961, 723, 722, 18446744073709551615, 1, 2), - (13, 960, 724, 723, 18446744073709551615, 1, 2), - (13, 662, 755, 663, 18446744073709551615, 0, 1), - (13, 754, 663, 664, 18446744073709551615, 0, 1), - (13, 753, 664, 665, 18446744073709551615, 0, 1), - (13, 752, 665, 666, 18446744073709551615, 0, 1), - (13, 751, 666, 667, 18446744073709551615, 0, 1), - (13, 750, 667, 668, 18446744073709551615, 0, 1), - (13, 749, 668, 669, 18446744073709551615, 0, 1), - (13, 748, 669, 670, 18446744073709551615, 0, 1), - (13, 747, 670, 671, 18446744073709551615, 0, 1), - (13, 14, 671, 672, 18446744073709551615, 0, 1), - (13, 11, 672, 673, 18446744073709551615, 0, 1), - (13, 777, 673, 674, 18446744073709551615, 0, 1), - (13, 13, 674, 675, 18446744073709551615, 0, 1), - (13, 1145, 675, 676, 18446744073709551615, 0, 1), - (13, 1137, 676, 677, 18446744073709551615, 0, 1), - (13, 17, 677, 678, 18446744073709551615, 0, 1), - (13, 1134, 678, 679, 18446744073709551615, 0, 1), - (13, 27, 679, 680, 18446744073709551615, 0, 1), - (13, 786, 680, 681, 18446744073709551615, 0, 1), - (13, 787, 681, 682, 18446744073709551615, 0, 1), - (13, 788, 682, 683, 18446744073709551615, 0, 1), - (13, 789, 683, 730, 18446744073709551615, 0, 1), - (13, 790, 730, 731, 18446744073709551615, 0, 1), - (13, 791, 731, 128, 18446744073709551615, 0, 1), - (13, 23, 128, 1093, 18446744073709551615, 0, 1), - (13, 20, 1093, 684, 18446744073709551615, 0, 1), - (13, 18, 684, 685, 18446744073709551615, 0, 1), - (13, 795, 685, 609, 18446744073709551615, 0, 1), - (13, 796, 609, 608, 18446744073709551615, 2, 3), - (13, 797, 608, 607, 18446744073709551615, 2, 3), - (13, 798, 607, 606, 18446744073709551615, 2, 3), - (13, 799, 606, 732, 18446744073709551615, 2, 3), - (13, 800, 732, 733, 18446744073709551615, 2, 3), - (13, 801, 733, 605, 18446744073709551615, 2, 3), - (13, 802, 605, 604, 18446744073709551615, 2, 3), - (13, 803, 604, 603, 18446744073709551615, 2, 3), - (13, 804, 603, 602, 18446744073709551615, 2, 3), - (13, 805, 602, 601, 18446744073709551615, 2, 3), - (13, 806, 601, 600, 18446744073709551615, 2, 3), - (13, 807, 600, 599, 18446744073709551615, 2, 3), - (13, 808, 599, 598, 18446744073709551615, 2, 3), - (13, 809, 598, 597, 18446744073709551615, 2, 3), - (13, 810, 597, 596, 18446744073709551615, 2, 3), - (13, 811, 596, 595, 18446744073709551615, 2, 3), - (13, 812, 595, 594, 18446744073709551615, 2, 3), - (13, 813, 594, 593, 18446744073709551615, 2, 3), - (13, 814, 593, 592, 18446744073709551615, 2, 3), - (13, 815, 592, 590, 18446744073709551615, 2, 3), - (13, 816, 590, 589, 18446744073709551615, 4, 6), - (13, 817, 589, 591, 18446744073709551615, 2, 3), - (13, 818, 591, 589, 18446744073709551615, 2, 3), - (13, 819, 589, 590, 18446744073709551615, 2, 3), - (14, 662, 819, 589, 18446744073709551615, 0, 1), - (14, 662, 817, 589, 18446744073709551615, 0, 1), - (13, 1006, 643, 664, 18446744073709551615, 0, 1), - (13, 239, 644, 665, 18446744073709551615, 0, 1), - (13, 1008, 645, 666, 18446744073709551615, 0, 1), - (13, 1009, 646, 667, 18446744073709551615, 0, 1), - (13, 242, 647, 668, 18446744073709551615, 0, 1), - (13, 1011, 648, 669, 18446744073709551615, 0, 1), - (13, 1012, 649, 670, 18446744073709551615, 0, 1), - (13, 245, 650, 671, 18446744073709551615, 0, 1), - (13, 1014, 651, 672, 18446744073709551615, 0, 1), - (13, 1015, 652, 673, 18446744073709551615, 0, 1), - (13, 248, 653, 674, 18446744073709551615, 0, 1), - (13, 1017, 654, 675, 18446744073709551615, 0, 1), - (13, 1018, 655, 676, 18446744073709551615, 0, 1), - (13, 251, 656, 677, 18446744073709551615, 0, 1), - (13, 1020, 657, 678, 18446744073709551615, 0, 1), - (13, 1021, 658, 679, 18446744073709551615, 0, 1), - (13, 254, 659, 680, 18446744073709551615, 0, 1), - (13, 1023, 660, 681, 18446744073709551615, 0, 1), - (13, 1049, 661, 682, 18446744073709551615, 0, 1), - (13, 799, 630, 629, 18446744073709551615, 0, 5), - (13, 798, 632, 631, 18446744073709551615, 0, 4), - (13, 799, 631, 630, 18446744073709551615, 0, 4), - (13, 799, 632, 631, 18446744073709551615, 0, 4), - (13, 802, 631, 630, 18446744073709551615, 0, 4), - (13, 799, 630, 629, 18446744073709551615, 2, 5), - (13, 802, 631, 630, 18446744073709551615, 1, 4), - (13, 802, 632, 631, 18446744073709551615, 0, 3), - (13, 803, 631, 630, 18446744073709551615, 0, 3), - (13, 804, 631, 630, 18446744073709551615, 0, 3), - (13, 799, 631, 630, 18446744073709551615, 2, 4), - (13, 800, 631, 630, 18446744073709551615, 2, 4), - (13, 801, 632, 631, 18446744073709551615, 2, 4), - (13, 802, 632, 631, 18446744073709551615, 1, 3), - (13, 804, 631, 630, 18446744073709551615, 1, 3), - (13, 805, 631, 630, 18446744073709551615, 0, 2), - (13, 805, 632, 631, 18446744073709551615, 0, 2), - (13, 806, 632, 631, 18446744073709551615, 0, 2), - (13, 807, 632, 631, 18446744073709551615, 0, 2), - (13, 808, 631, 630, 18446744073709551615, 0, 2), - (13, 799, 630, 629, 18446744073709551615, 4, 5), - (13, 800, 631, 630, 18446744073709551615, 3, 4), - (13, 804, 631, 630, 18446744073709551615, 2, 3), - (13, 809, 631, 630, 18446744073709551615, 0, 1), - (13, 809, 632, 631, 18446744073709551615, 0, 1), - (13, 810, 631, 630, 18446744073709551615, 0, 1), - (13, 812, 631, 630, 18446744073709551615, 0, 1), - (13, 814, 631, 630, 18446744073709551615, 0, 1), - (13, 815, 631, 630, 18446744073709551615, 0, 1), - (13, 819, 631, 630, 18446744073709551615, 0, 1), - (13, 820, 631, 630, 18446744073709551615, 0, 1), - (13, 821, 631, 630, 18446744073709551615, 0, 1), - (13, 824, 631, 630, 18446744073709551615, 0, 1), - (13, 828, 631, 630, 18446744073709551615, 0, 1), - (13, 829, 631, 630, 18446744073709551615, 0, 1), - (13, 732, 904, 384, 18446744073709551615, 0, 2), - (13, 641, 1042, 640, 18446744073709551615, 0, 1), - (13, 640, 1052, 639, 18446744073709551615, 0, 1), - (13, 639, 1051, 638, 18446744073709551615, 0, 1), - (13, 638, 1053, 637, 18446744073709551615, 0, 1), - (13, 637, 255, 636, 18446744073709551615, 0, 1), - (13, 636, 1047, 635, 18446744073709551615, 0, 1), - (13, 635, 252, 634, 18446744073709551615, 0, 1), - (13, 634, 172, 633, 18446744073709551615, 0, 1), - (13, 633, 249, 632, 18446744073709551615, 0, 1), - (13, 632, 246, 631, 18446744073709551615, 0, 1), - (13, 631, 243, 630, 18446744073709551615, 0, 1), - (13, 630, 240, 629, 18446744073709551615, 0, 1), - (13, 629, 237, 628, 18446744073709551615, 0, 1), - (13, 628, 234, 627, 18446744073709551615, 0, 1), - (13, 627, 231, 626, 18446744073709551615, 0, 1), - (13, 626, 228, 625, 18446744073709551615, 0, 1), - (13, 625, 225, 624, 18446744073709551615, 0, 1), - (13, 624, 222, 623, 18446744073709551615, 0, 1), - (13, 623, 219, 622, 18446744073709551615, 0, 1), - (13, 622, 216, 621, 18446744073709551615, 0, 1), - (13, 621, 213, 620, 18446744073709551615, 0, 1), - (13, 620, 210, 619, 18446744073709551615, 0, 1), - (13, 619, 207, 618, 18446744073709551615, 0, 1), - (13, 618, 204, 617, 18446744073709551615, 0, 1), - (13, 617, 201, 616, 18446744073709551615, 0, 1), - (13, 616, 198, 615, 18446744073709551615, 0, 1), - (13, 615, 195, 614, 18446744073709551615, 0, 1), - (13, 614, 192, 708, 18446744073709551615, 0, 1), - (13, 708, 189, 709, 18446744073709551615, 0, 1), - (13, 709, 186, 710, 18446744073709551615, 0, 1), - (13, 710, 183, 711, 18446744073709551615, 0, 1), - (13, 711, 180, 712, 18446744073709551615, 0, 1), - (13, 712, 177, 713, 18446744073709551615, 0, 1), - (13, 713, 174, 714, 18446744073709551615, 0, 1), - (13, 714, 1083, 715, 18446744073709551615, 0, 1), - (13, 715, 173, 716, 18446744073709551615, 0, 1), - (13, 716, 159, 717, 18446744073709551615, 0, 1), - (13, 717, 912, 718, 18446744073709551615, 0, 1), - (13, 718, 152, 719, 18446744073709551615, 0, 1), - (13, 719, 149, 720, 18446744073709551615, 0, 1), - (13, 720, 141, 721, 18446744073709551615, 0, 1), - (13, 721, 1091, 722, 18446744073709551615, 0, 1), - (13, 722, 1096, 723, 18446744073709551615, 0, 1), - (13, 723, 137, 724, 18446744073709551615, 0, 1), - (13, 724, 134, 725, 18446744073709551615, 0, 1), - (13, 725, 131, 726, 18446744073709551615, 0, 1), - (13, 726, 124, 727, 18446744073709551615, 0, 1), - (13, 727, 122, 728, 18446744073709551615, 0, 1), - (13, 728, 112, 729, 18446744073709551615, 0, 1), - (13, 729, 120, 613, 18446744073709551615, 0, 1), - (13, 613, 109, 612, 18446744073709551615, 0, 1), - (13, 612, 106, 686, 18446744073709551615, 0, 1), - (13, 686, 103, 687, 18446744073709551615, 0, 1), - (13, 687, 100, 688, 18446744073709551615, 0, 1), - (13, 688, 97, 689, 18446744073709551615, 0, 1), - (13, 689, 94, 690, 18446744073709551615, 0, 1), - (13, 690, 91, 691, 18446744073709551615, 0, 1), - (13, 691, 88, 692, 18446744073709551615, 0, 1), - (13, 692, 85, 693, 18446744073709551615, 0, 1), - (13, 693, 82, 694, 18446744073709551615, 0, 1), - (13, 694, 79, 695, 18446744073709551615, 0, 1), - (13, 695, 76, 696, 18446744073709551615, 0, 1), - (13, 696, 73, 697, 18446744073709551615, 0, 1), - (13, 697, 70, 698, 18446744073709551615, 0, 1), - (13, 698, 67, 699, 18446744073709551615, 0, 1), - (13, 699, 64, 700, 18446744073709551615, 0, 1), - (13, 700, 61, 701, 18446744073709551615, 0, 1), - (13, 701, 58, 702, 18446744073709551615, 0, 1), - (13, 702, 55, 703, 18446744073709551615, 0, 1), - (13, 703, 52, 704, 18446744073709551615, 0, 1), - (13, 704, 49, 705, 18446744073709551615, 0, 1), - (13, 705, 46, 706, 18446744073709551615, 0, 1), - (13, 706, 43, 707, 18446744073709551615, 0, 1), - (13, 707, 40, 611, 18446744073709551615, 0, 1), - (13, 611, 37, 610, 18446744073709551615, 0, 1), - (13, 610, 34, 662, 18446744073709551615, 0, 1), - (13, 662, 31, 663, 18446744073709551615, 0, 1), - (13, 663, 28, 664, 18446744073709551615, 0, 1), - (13, 664, 19, 665, 18446744073709551615, 0, 1), - (13, 665, 1133, 666, 18446744073709551615, 0, 1), - (13, 666, 784, 667, 18446744073709551615, 0, 1), - (13, 667, 782, 668, 18446744073709551615, 0, 1), - (13, 668, 1138, 669, 18446744073709551615, 0, 1), - (13, 669, 1114, 670, 18446744073709551615, 0, 1), - (13, 670, 1135, 671, 18446744073709551615, 0, 1), - (13, 671, 783, 672, 18446744073709551615, 0, 1), - (13, 672, 1136, 673, 18446744073709551615, 0, 1), - (13, 673, 836, 674, 18446744073709551615, 0, 1), - (13, 674, 15, 675, 18446744073709551615, 0, 1), - (13, 675, 1146, 676, 18446744073709551615, 0, 1), - (13, 676, 746, 677, 18446744073709551615, 0, 1), - (13, 677, 1152, 678, 18446744073709551615, 0, 1), - (13, 678, 781, 679, 18446744073709551615, 0, 1), - (13, 679, 1143, 680, 18446744073709551615, 0, 1), - (13, 680, 1144, 681, 18446744073709551615, 0, 1), - (13, 681, 745, 682, 18446744073709551615, 0, 1), - (13, 682, 744, 683, 18446744073709551615, 0, 1), - (13, 683, 743, 730, 18446744073709551615, 0, 1), - (13, 730, 742, 731, 18446744073709551615, 0, 1), - (13, 731, 741, 128, 18446744073709551615, 0, 1), - (13, 128, 740, 1093, 18446744073709551615, 0, 1), - (13, 1093, 739, 684, 18446744073709551615, 0, 1), - (13, 684, 738, 685, 18446744073709551615, 0, 1), - (13, 685, 737, 609, 18446744073709551615, 0, 1), - (13, 609, 736, 608, 18446744073709551615, 0, 1), - (13, 608, 735, 607, 18446744073709551615, 0, 1), - (13, 732, 904, 384, 18446744073709551615, 1, 2), - (13, 510, 735, 661, 18446744073709551615, 0, 1), - (13, 510, 784, 734, 18446744073709551615, 1, 2), - (13, 510, 1133, 734, 18446744073709551615, 1, 2), - (13, 510, 19, 734, 18446744073709551615, 1, 2), - (13, 510, 28, 734, 18446744073709551615, 1, 2), - (13, 510, 31, 734, 18446744073709551615, 1, 2), - (13, 510, 34, 734, 18446744073709551615, 1, 2), - (13, 510, 37, 734, 18446744073709551615, 1, 2), - (13, 510, 40, 734, 18446744073709551615, 1, 2), - (13, 510, 43, 734, 18446744073709551615, 1, 2), - (13, 510, 46, 734, 18446744073709551615, 1, 2), - (13, 510, 49, 734, 18446744073709551615, 1, 2), - (13, 510, 52, 734, 18446744073709551615, 1, 2), - (13, 510, 55, 734, 18446744073709551615, 1, 2), - (13, 510, 58, 734, 18446744073709551615, 1, 2), - (13, 510, 61, 734, 18446744073709551615, 1, 2), - (13, 510, 64, 734, 18446744073709551615, 1, 2), - (13, 510, 67, 734, 18446744073709551615, 1, 2), - (13, 510, 70, 734, 18446744073709551615, 1, 2), - (13, 510, 73, 734, 18446744073709551615, 1, 2), - (13, 510, 76, 734, 18446744073709551615, 1, 2), - (13, 510, 79, 734, 18446744073709551615, 1, 2), - (13, 510, 82, 734, 18446744073709551615, 1, 2), - (13, 510, 85, 734, 18446744073709551615, 1, 2), - (13, 510, 88, 734, 18446744073709551615, 1, 2), - (13, 510, 91, 734, 18446744073709551615, 1, 2), - (13, 510, 94, 734, 18446744073709551615, 1, 2), - (13, 510, 97, 734, 18446744073709551615, 1, 2), - (13, 510, 100, 734, 18446744073709551615, 1, 2), - (13, 510, 103, 734, 18446744073709551615, 1, 2), - (13, 510, 106, 734, 18446744073709551615, 1, 2), - (13, 510, 109, 734, 18446744073709551615, 1, 2), - (13, 510, 120, 734, 18446744073709551615, 1, 2), - (13, 510, 112, 734, 18446744073709551615, 1, 2), - (13, 510, 122, 734, 18446744073709551615, 1, 2), - (13, 510, 124, 734, 18446744073709551615, 1, 2), - (13, 510, 131, 734, 18446744073709551615, 1, 2), - (13, 510, 134, 734, 18446744073709551615, 1, 2), - (13, 510, 137, 734, 18446744073709551615, 1, 2), - (13, 510, 1096, 734, 18446744073709551615, 1, 2), - (13, 510, 1091, 734, 18446744073709551615, 1, 2), - (13, 510, 141, 734, 18446744073709551615, 1, 2), - (13, 510, 149, 734, 18446744073709551615, 1, 2), - (13, 510, 152, 734, 18446744073709551615, 1, 2), - (13, 510, 912, 734, 18446744073709551615, 1, 2), - (13, 510, 159, 734, 18446744073709551615, 1, 2), - (13, 510, 173, 734, 18446744073709551615, 1, 2), - (13, 510, 1083, 734, 18446744073709551615, 1, 2), - (13, 510, 174, 734, 18446744073709551615, 1, 2), - (13, 510, 177, 734, 18446744073709551615, 1, 2), - (13, 510, 180, 734, 18446744073709551615, 1, 2), - (13, 510, 183, 734, 18446744073709551615, 1, 2), - (13, 510, 186, 734, 18446744073709551615, 1, 2), - (13, 510, 189, 734, 18446744073709551615, 1, 2), - (13, 510, 192, 734, 18446744073709551615, 1, 2), - (13, 510, 195, 734, 18446744073709551615, 1, 2), - (13, 510, 198, 734, 18446744073709551615, 1, 2), - (13, 510, 201, 734, 18446744073709551615, 1, 2), - (13, 510, 204, 734, 18446744073709551615, 1, 2), - (13, 510, 207, 734, 18446744073709551615, 1, 2), - (13, 510, 210, 734, 18446744073709551615, 1, 2), - (13, 510, 213, 734, 18446744073709551615, 1, 2), - (13, 510, 216, 734, 18446744073709551615, 1, 2), - (13, 510, 219, 734, 18446744073709551615, 1, 2), - (13, 510, 222, 734, 18446744073709551615, 1, 2), - (13, 510, 225, 734, 18446744073709551615, 1, 2), - (13, 510, 228, 734, 18446744073709551615, 1, 2), - (13, 510, 231, 734, 18446744073709551615, 1, 2), - (13, 510, 234, 734, 18446744073709551615, 1, 2), - (13, 510, 237, 734, 18446744073709551615, 1, 2), - (13, 510, 240, 734, 18446744073709551615, 1, 2), - (13, 510, 243, 734, 18446744073709551615, 1, 2), - (13, 510, 246, 734, 18446744073709551615, 1, 2), - (13, 510, 249, 734, 18446744073709551615, 1, 2), - (13, 510, 172, 734, 18446744073709551615, 1, 2), - (13, 510, 252, 734, 18446744073709551615, 1, 2), - (13, 510, 1047, 734, 18446744073709551615, 1, 2), - (13, 510, 255, 734, 18446744073709551615, 1, 2), - (13, 510, 1053, 734, 18446744073709551615, 1, 2), - (13, 822, 74, 977, 18446744073709551615, 0, 1), - (13, 823, 846, 1071, 18446744073709551615, 0, 1), - (13, 824, 1110, 202, 18446744073709551615, 0, 1), - (13, 825, 71, 974, 18446744073709551615, 0, 1), - (13, 826, 843, 1072, 18446744073709551615, 0, 1), - (13, 827, 1111, 199, 18446744073709551615, 0, 1), - (13, 828, 68, 971, 18446744073709551615, 0, 1), - (13, 829, 838, 1073, 18446744073709551615, 0, 1), - (13, 830, 1112, 196, 18446744073709551615, 0, 1), - (13, 831, 65, 968, 18446744073709551615, 0, 1), - (13, 832, 1119, 1074, 18446744073709551615, 0, 1), - (13, 833, 66, 193, 18446744073709551615, 0, 1), - (13, 834, 62, 965, 18446744073709551615, 0, 1), - (13, 835, 1117, 1075, 18446744073709551615, 0, 1), - (13, 69, 63, 190, 18446744073709551615, 0, 1), - (13, 837, 59, 962, 18446744073709551615, 0, 1), - (13, 839, 1120, 1076, 18446744073709551615, 0, 1), - (13, 72, 60, 187, 18446744073709551615, 0, 2), - (13, 841, 56, 959, 18446744073709551615, 0, 1), - (13, 842, 1121, 1077, 18446744073709551615, 0, 2), - (13, 75, 57, 184, 18446744073709551615, 0, 3), - (13, 844, 53, 956, 18446744073709551615, 0, 3), - (13, 845, 1122, 1078, 18446744073709551615, 0, 3), - (13, 78, 54, 181, 18446744073709551615, 0, 3), - (13, 847, 50, 953, 18446744073709551615, 0, 3), - (13, 848, 1123, 1079, 18446744073709551615, 0, 3), - (13, 81, 51, 178, 18446744073709551615, 0, 3), - (13, 850, 47, 950, 18446744073709551615, 0, 3), - (13, 851, 1124, 1080, 18446744073709551615, 0, 3), - (13, 84, 48, 175, 18446744073709551615, 0, 3), - (13, 853, 44, 947, 18446744073709551615, 0, 3), - (13, 854, 1125, 1081, 18446744073709551615, 0, 3), - (13, 87, 45, 941, 18446744073709551615, 0, 3), - (13, 856, 41, 944, 18446744073709551615, 0, 3), - (13, 857, 1126, 169, 18446744073709551615, 0, 3), - (13, 90, 42, 938, 18446744073709551615, 0, 3), - (13, 859, 38, 939, 18446744073709551615, 0, 3), - (13, 860, 1127, 1084, 18446744073709551615, 0, 3), - (13, 93, 39, 166, 18446744073709551615, 0, 3), - (13, 862, 35, 171, 18446744073709551615, 0, 3), - (13, 863, 1128, 940, 18446744073709551615, 0, 3), - (13, 96, 36, 932, 18446744073709551615, 0, 3), - (13, 865, 32, 163, 18446744073709551615, 0, 3), - (13, 866, 1129, 930, 18446744073709551615, 0, 3), - (13, 99, 33, 931, 18446744073709551615, 0, 3), - (13, 868, 29, 934, 18446744073709551615, 0, 3), - (13, 869, 1130, 1085, 18446744073709551615, 0, 3), - (13, 102, 30, 926, 18446744073709551615, 0, 3), - (13, 871, 792, 927, 18446744073709551615, 0, 3), - (13, 872, 1131, 928, 18446744073709551615, 0, 3), - (13, 105, 24, 923, 18446744073709551615, 0, 3), - (13, 874, 25, 924, 18446744073709551615, 0, 3), - (13, 875, 26, 925, 18446744073709551615, 0, 3), - (13, 108, 21, 1086, 18446744073709551615, 0, 3), - (13, 877, 1115, 150, 18446744073709551615, 0, 3), - (13, 878, 22, 922, 18446744073709551615, 0, 3), - (13, 111, 794, 1087, 18446744073709551615, 0, 3), - (13, 880, 840, 146, 18446744073709551615, 0, 3), - (13, 881, 785, 915, 18446744073709551615, 0, 3), - (13, 114, 1113, 916, 18446744073709551615, 0, 2), - (13, 883, 16, 1088, 18446744073709551615, 0, 1), - (13, 884, 1118, 143, 18446744073709551615, 0, 1), - (13, 117, 1140, 148, 18446744073709551615, 0, 1), - (13, 119, 780, 917, 18446744073709551615, 0, 1), - (13, 118, 1148, 1090, 18446744073709551615, 0, 1), - (13, 115, 778, 1089, 18446744073709551615, 0, 1), - (13, 890, 779, 907, 18446744073709551615, 0, 1), - (13, 1116, 1142, 138, 18446744073709551615, 0, 1), - (13, 891, 756, 908, 18446744073709551615, 0, 1), - (13, 892, 757, 135, 18446744073709551615, 0, 1), - (13, 893, 758, 909, 18446744073709551615, 0, 1), - (13, 126, 759, 1092, 18446744073709551615, 0, 1), - (13, 895, 760, 132, 18446744073709551615, 0, 1), - (13, 896, 761, 904, 18446744073709551615, 0, 1), - (13, 129, 762, 661, 18446744073709551615, 0, 1), - (13, 127, 734, 660, 18446744073709551615, 0, 1), - (13, 1095, 735, 659, 18446744073709551615, 0, 1), - (13, 900, 736, 658, 18446744073709551615, 0, 1), - (13, 133, 737, 657, 18446744073709551615, 0, 1), - (13, 902, 738, 656, 18446744073709551615, 0, 1), - (13, 903, 739, 655, 18446744073709551615, 0, 1), - (13, 136, 740, 654, 18446744073709551615, 0, 1), - (13, 905, 741, 653, 18446744073709551615, 0, 1), - (13, 906, 742, 652, 18446744073709551615, 0, 1), - (13, 140, 743, 651, 18446744073709551615, 0, 1), - (13, 139, 744, 650, 18446744073709551615, 0, 1), - (13, 910, 745, 649, 18446744073709551615, 0, 1), - (13, 142, 1144, 648, 18446744073709551615, 0, 1), - (13, 919, 1143, 647, 18446744073709551615, 0, 1), - (13, 144, 781, 646, 18446744073709551615, 0, 1), - (13, 913, 1152, 645, 18446744073709551615, 0, 1), - (13, 914, 746, 644, 18446744073709551615, 0, 1), - (13, 147, 1146, 643, 18446744073709551615, 0, 1), - (13, 145, 15, 642, 18446744073709551615, 0, 1), - (13, 911, 836, 641, 18446744073709551615, 0, 1), - (13, 918, 1136, 640, 18446744073709551615, 0, 1), - (13, 151, 783, 639, 18446744073709551615, 0, 1), - (13, 920, 1135, 638, 18446744073709551615, 0, 1), - (13, 921, 1114, 637, 18446744073709551615, 0, 1), - (13, 154, 1138, 636, 18446744073709551615, 0, 1), - (13, 157, 782, 635, 18446744073709551615, 0, 1), - (13, 155, 784, 634, 18446744073709551615, 0, 1), - (13, 153, 1133, 633, 18446744073709551615, 0, 1), - (13, 160, 19, 632, 18446744073709551615, 0, 1), - (13, 158, 28, 631, 18446744073709551615, 0, 1), - (13, 935, 31, 630, 18446744073709551615, 0, 1), - (13, 929, 34, 629, 18446744073709551615, 0, 1), - (13, 933, 37, 628, 18446744073709551615, 0, 1), - (13, 165, 40, 627, 18446744073709551615, 0, 1), - (13, 161, 43, 626, 18446744073709551615, 0, 1), - (13, 164, 46, 625, 18446744073709551615, 0, 1), - (13, 162, 49, 624, 18446744073709551615, 0, 1), - (13, 167, 52, 623, 18446744073709551615, 0, 1), - (13, 936, 55, 622, 18446744073709551615, 0, 1), - (13, 937, 58, 621, 18446744073709551615, 0, 1), - (13, 170, 61, 620, 18446744073709551615, 0, 1), - (13, 168, 64, 619, 18446744073709551615, 0, 1), - (13, 156, 67, 618, 18446744073709551615, 0, 1), - (13, 1082, 70, 617, 18446744073709551615, 0, 1), - (13, 942, 73, 616, 18446744073709551615, 0, 1), - (13, 943, 76, 615, 18446744073709551615, 0, 1), - (13, 176, 79, 614, 18446744073709551615, 0, 1), - (13, 945, 82, 708, 18446744073709551615, 0, 1), - (13, 946, 85, 709, 18446744073709551615, 0, 1), - (13, 179, 88, 710, 18446744073709551615, 0, 1), - (13, 948, 91, 711, 18446744073709551615, 0, 1), - (13, 949, 94, 712, 18446744073709551615, 0, 1), - (13, 182, 97, 713, 18446744073709551615, 0, 1), - (13, 951, 100, 714, 18446744073709551615, 0, 1), - (13, 952, 103, 715, 18446744073709551615, 0, 1), - (13, 185, 106, 716, 18446744073709551615, 0, 1), - (13, 954, 109, 717, 18446744073709551615, 0, 1), - (13, 955, 120, 718, 18446744073709551615, 0, 1), - (13, 188, 112, 719, 18446744073709551615, 0, 1), - (13, 957, 122, 720, 18446744073709551615, 0, 1), - (13, 958, 124, 721, 18446744073709551615, 0, 1), - (13, 191, 131, 722, 18446744073709551615, 0, 1), - (13, 960, 134, 723, 18446744073709551615, 0, 1), - (13, 961, 137, 724, 18446744073709551615, 0, 1), - (13, 194, 1096, 725, 18446744073709551615, 0, 1), - (13, 963, 1091, 726, 18446744073709551615, 0, 1), - (13, 964, 141, 727, 18446744073709551615, 0, 1), - (13, 197, 149, 728, 18446744073709551615, 0, 1), - (13, 966, 152, 729, 18446744073709551615, 0, 1), - (13, 967, 912, 613, 18446744073709551615, 0, 1), - (13, 200, 159, 612, 18446744073709551615, 0, 1), - (13, 969, 173, 686, 18446744073709551615, 0, 1), - (13, 970, 1083, 687, 18446744073709551615, 0, 1), - (13, 203, 174, 688, 18446744073709551615, 0, 1), - (13, 972, 177, 689, 18446744073709551615, 0, 1), - (13, 973, 180, 690, 18446744073709551615, 0, 1), - (13, 206, 183, 691, 18446744073709551615, 0, 1), - (13, 975, 186, 692, 18446744073709551615, 0, 1), - (13, 976, 189, 693, 18446744073709551615, 0, 1), - (13, 209, 192, 694, 18446744073709551615, 0, 1), - (13, 978, 195, 695, 18446744073709551615, 0, 1), - (13, 979, 198, 696, 18446744073709551615, 0, 1), - (13, 212, 201, 697, 18446744073709551615, 0, 1), - (13, 981, 204, 698, 18446744073709551615, 0, 1), - (13, 982, 207, 699, 18446744073709551615, 0, 1), - (13, 215, 210, 700, 18446744073709551615, 0, 1), - (13, 984, 213, 701, 18446744073709551615, 0, 1), - (13, 985, 216, 702, 18446744073709551615, 0, 1), - (13, 218, 219, 703, 18446744073709551615, 0, 1), - (13, 987, 222, 704, 18446744073709551615, 0, 1), - (13, 988, 225, 705, 18446744073709551615, 0, 1), - (13, 221, 228, 706, 18446744073709551615, 0, 1), - (13, 990, 231, 707, 18446744073709551615, 0, 1), - (13, 991, 234, 611, 18446744073709551615, 0, 1), - (13, 224, 237, 610, 18446744073709551615, 0, 1), - (13, 993, 240, 662, 18446744073709551615, 0, 1), - (13, 994, 243, 663, 18446744073709551615, 0, 1), - (13, 227, 246, 664, 18446744073709551615, 0, 1), - (13, 996, 249, 665, 18446744073709551615, 0, 1), - (13, 997, 172, 666, 18446744073709551615, 0, 1), - (13, 230, 252, 667, 18446744073709551615, 0, 1), - (13, 999, 1047, 668, 18446744073709551615, 0, 1), - (13, 1000, 255, 669, 18446744073709551615, 0, 1), - (13, 233, 1053, 670, 18446744073709551615, 0, 1), - (13, 1002, 1051, 671, 18446744073709551615, 0, 1), - (13, 1003, 1052, 672, 18446744073709551615, 0, 1), - (13, 236, 1042, 673, 18446744073709551615, 0, 1), - (13, 1005, 1048, 674, 18446744073709551615, 0, 1), - (13, 1006, 1040, 675, 18446744073709551615, 0, 1), - (13, 239, 1050, 676, 18446744073709551615, 0, 1), - (13, 1008, 1046, 677, 18446744073709551615, 0, 1), - (13, 1009, 1044, 678, 18446744073709551615, 0, 1), - (13, 242, 1045, 679, 18446744073709551615, 0, 1), - (13, 1011, 1035, 680, 18446744073709551615, 0, 1), - (13, 1012, 1041, 681, 18446744073709551615, 0, 1), - (13, 245, 1033, 682, 18446744073709551615, 0, 1), - (13, 1014, 1043, 683, 18446744073709551615, 0, 1), - (13, 1015, 1039, 730, 18446744073709551615, 0, 1), - (13, 248, 1037, 731, 18446744073709551615, 0, 1), - (13, 1017, 1038, 128, 18446744073709551615, 0, 1), - (13, 1018, 1030, 1093, 18446744073709551615, 0, 1), - (13, 251, 1034, 684, 18446744073709551615, 0, 1), - (13, 1020, 1036, 685, 18446744073709551615, 0, 1), - (13, 1021, 1027, 609, 18446744073709551615, 0, 1), - (13, 254, 1031, 608, 18446744073709551615, 0, 1), - (13, 1023, 765, 607, 18446744073709551615, 0, 1), - (13, 1049, 1032, 214, 18446744073709551615, 0, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 7, 12), - (13, 1023, 765, 986, 18446744073709551615, 0, 1), - (13, 1049, 1032, 1068, 18446744073709551615, 0, 1), - (13, 1023, 765, 593, 18446744073709551615, 0, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 8, 12), - (13, 1029, 765, 1023, 18446744073709551615, 8, 13), - (13, 1023, 765, 208, 18446744073709551615, 0, 1), - (13, 1049, 1032, 980, 18446744073709551615, 0, 1), - (13, 1023, 765, 590, 18446744073709551615, 0, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 9, 12), - (13, 1029, 765, 1023, 18446744073709551615, 9, 13), - (13, 254, 1031, 1070, 18446744073709551615, 0, 1), - (13, 1023, 765, 205, 18446744073709551615, 0, 1), - (13, 1049, 1032, 977, 18446744073709551615, 0, 1), - (13, 254, 1031, 588, 18446744073709551615, 0, 1), - (13, 1023, 765, 587, 18446744073709551615, 0, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 10, 12), - (13, 1029, 765, 1023, 18446744073709551615, 10, 13), - (13, 1029, 1031, 254, 18446744073709551615, 10, 14), - (13, 1021, 1027, 977, 18446744073709551615, 0, 1), - (13, 254, 1031, 1071, 18446744073709551615, 0, 1), - (13, 1023, 765, 202, 18446744073709551615, 0, 1), - (13, 1049, 1032, 974, 18446744073709551615, 0, 1), - (13, 1021, 1027, 588, 18446744073709551615, 0, 1), - (13, 254, 1031, 587, 18446744073709551615, 0, 1), - (13, 1023, 765, 586, 18446744073709551615, 0, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 11, 12), - (13, 1029, 765, 1023, 18446744073709551615, 11, 13), - (13, 1029, 1031, 254, 18446744073709551615, 11, 14), - (13, 1029, 1027, 1021, 18446744073709551615, 11, 15), - (13, 1020, 1036, 1071, 18446744073709551615, 0, 1), - (13, 1021, 1027, 202, 18446744073709551615, 0, 1), - (13, 254, 1031, 974, 18446744073709551615, 0, 1), - (13, 1023, 765, 1072, 18446744073709551615, 0, 1), - (13, 1020, 1036, 588, 18446744073709551615, 0, 2), - (13, 1021, 1027, 587, 18446744073709551615, 0, 1), - (13, 254, 1031, 586, 18446744073709551615, 0, 1), - (13, 1029, 765, 1023, 18446744073709551615, 12, 13), - (13, 1029, 1031, 254, 18446744073709551615, 12, 14), - (13, 1029, 1027, 1021, 18446744073709551615, 12, 15), - (13, 1029, 1036, 1020, 18446744073709551615, 12, 16), - (13, 251, 1034, 202, 18446744073709551615, 0, 2), - (13, 1020, 1036, 974, 18446744073709551615, 0, 2), - (13, 1021, 1027, 1072, 18446744073709551615, 0, 2), - (13, 254, 1031, 199, 18446744073709551615, 0, 1), - (13, 251, 1034, 588, 18446744073709551615, 0, 2), - (13, 1020, 1036, 587, 18446744073709551615, 0, 1), - (13, 1021, 1027, 586, 18446744073709551615, 0, 1), - (13, 1029, 1031, 254, 18446744073709551615, 13, 14), - (13, 1029, 1027, 1021, 18446744073709551615, 13, 15), - (13, 1029, 1036, 1020, 18446744073709551615, 13, 16), - (13, 1029, 1034, 251, 18446744073709551615, 13, 17), - (13, 1018, 1030, 1071, 18446744073709551615, 1, 2), - (13, 251, 1034, 202, 18446744073709551615, 1, 2), - (13, 1020, 1036, 974, 18446744073709551615, 1, 2), - (13, 1021, 1027, 1072, 18446744073709551615, 1, 2), - (13, 1018, 1030, 590, 18446744073709551615, 1, 2), - (13, 251, 1034, 589, 18446744073709551615, 1, 2), - (13, 1020, 1036, 588, 18446744073709551615, 1, 2), - (13, 1029, 1027, 1021, 18446744073709551615, 14, 15), - (13, 1029, 1036, 1020, 18446744073709551615, 14, 16), - (13, 1029, 1034, 251, 18446744073709551615, 14, 17), - (13, 1029, 1030, 1018, 18446744073709551615, 14, 18), - (13, 1017, 1038, 202, 18446744073709551615, 0, 1), - (13, 1018, 1030, 974, 18446744073709551615, 0, 1), - (13, 251, 1034, 1072, 18446744073709551615, 0, 1), - (13, 1020, 1036, 199, 18446744073709551615, 0, 1), - (13, 1017, 1038, 590, 18446744073709551615, 1, 3), - (13, 1018, 1030, 589, 18446744073709551615, 1, 2), - (13, 251, 1034, 588, 18446744073709551615, 1, 2), - (13, 1029, 1036, 1020, 18446744073709551615, 15, 16), - (13, 1029, 1034, 251, 18446744073709551615, 15, 17), - (13, 1029, 1030, 1018, 18446744073709551615, 15, 18), - (13, 1029, 1038, 1017, 18446744073709551615, 15, 19), - (13, 248, 1037, 974, 18446744073709551615, 0, 1), - (13, 1017, 1038, 1072, 18446744073709551615, 0, 1), - (13, 1018, 1030, 199, 18446744073709551615, 0, 1), - (13, 251, 1034, 971, 18446744073709551615, 0, 1), - (13, 248, 1037, 590, 18446744073709551615, 0, 2), - (13, 1017, 1038, 589, 18446744073709551615, 0, 1), - (13, 1018, 1030, 588, 18446744073709551615, 0, 1), - (13, 1029, 1034, 251, 18446744073709551615, 16, 17), - (13, 1029, 1030, 1018, 18446744073709551615, 16, 18), - (13, 1029, 1038, 1017, 18446744073709551615, 16, 19), - (13, 1029, 1037, 248, 18446744073709551615, 16, 20), - (13, 1015, 1039, 974, 18446744073709551615, 0, 1), - (13, 248, 1037, 1072, 18446744073709551615, 0, 1), - (13, 1017, 1038, 199, 18446744073709551615, 0, 1), - (13, 1018, 1030, 971, 18446744073709551615, 0, 1), - (13, 1015, 1039, 592, 18446744073709551615, 2, 3), - (13, 248, 1037, 591, 18446744073709551615, 2, 3), - (13, 1017, 1038, 590, 18446744073709551615, 2, 3), - (13, 1029, 1030, 1018, 18446744073709551615, 17, 18), - (13, 1029, 1038, 1017, 18446744073709551615, 17, 19), - (13, 1029, 1037, 248, 18446744073709551615, 17, 20), - (13, 1029, 1039, 1015, 18446744073709551615, 17, 21), - (13, 1015, 1039, 199, 18446744073709551615, 0, 1), - (13, 248, 1037, 971, 18446744073709551615, 0, 1), - (13, 1017, 1038, 1073, 18446744073709551615, 0, 1), - (13, 1015, 1039, 591, 18446744073709551615, 1, 2), - (13, 248, 1037, 590, 18446744073709551615, 1, 2), - (13, 1029, 1038, 1017, 18446744073709551615, 18, 19), - (13, 1029, 1037, 248, 18446744073709551615, 18, 20), - (13, 1029, 1039, 1015, 18446744073709551615, 18, 21), - (13, 1014, 1043, 199, 18446744073709551615, 0, 1), - (13, 1015, 1039, 971, 18446744073709551615, 0, 1), - (13, 248, 1037, 1073, 18446744073709551615, 0, 1), - (13, 1014, 1043, 591, 18446744073709551615, 0, 1), - (13, 1015, 1039, 590, 18446744073709551615, 0, 1), - (13, 1029, 1037, 248, 18446744073709551615, 19, 20), - (13, 1029, 1039, 1015, 18446744073709551615, 19, 21), - (13, 1029, 1043, 1014, 18446744073709551615, 19, 22), - (13, 245, 1033, 199, 18446744073709551615, 0, 1), - (13, 1014, 1043, 971, 18446744073709551615, 0, 1), - (13, 1015, 1039, 1073, 18446744073709551615, 0, 1), - (13, 245, 1033, 593, 18446744073709551615, 2, 3), - (13, 1014, 1043, 592, 18446744073709551615, 2, 3), - (13, 1029, 1039, 1015, 18446744073709551615, 20, 21), - (13, 1029, 1043, 1014, 18446744073709551615, 20, 22), - (13, 1029, 1033, 245, 18446744073709551615, 20, 23), - (13, 1012, 1041, 971, 18446744073709551615, 0, 1), - (13, 245, 1033, 1073, 18446744073709551615, 0, 1), - (13, 1014, 1043, 196, 18446744073709551615, 0, 1), - (13, 1012, 1041, 593, 18446744073709551615, 1, 2), - (13, 245, 1033, 592, 18446744073709551615, 1, 2), - (13, 1029, 1043, 1014, 18446744073709551615, 21, 22), - (13, 1029, 1033, 245, 18446744073709551615, 21, 23), - (13, 1029, 1041, 1012, 18446744073709551615, 21, 24), - (13, 1011, 1035, 1073, 18446744073709551615, 0, 1), - (13, 1012, 1041, 196, 18446744073709551615, 0, 1), - (13, 245, 1033, 968, 18446744073709551615, 0, 1), - (13, 1011, 1035, 593, 18446744073709551615, 0, 1), - (13, 1012, 1041, 592, 18446744073709551615, 0, 1), - (13, 1029, 1033, 245, 18446744073709551615, 22, 23), - (13, 1029, 1041, 1012, 18446744073709551615, 22, 24), - (13, 1029, 1035, 1011, 18446744073709551615, 22, 25), - (13, 242, 1045, 199, 18446744073709551615, 0, 1), - (13, 1011, 1035, 971, 18446744073709551615, 0, 1), - (13, 1012, 1041, 1073, 18446744073709551615, 0, 1), - (13, 242, 1045, 595, 18446744073709551615, 2, 3), - (13, 1011, 1035, 594, 18446744073709551615, 2, 3), - (13, 1029, 1041, 1012, 18446744073709551615, 23, 24), - (13, 1029, 1035, 1011, 18446744073709551615, 23, 25), - (13, 1029, 1045, 242, 18446744073709551615, 23, 26), - (13, 1009, 1044, 196, 18446744073709551615, 0, 1), - (13, 242, 1045, 968, 18446744073709551615, 0, 1), - (13, 1011, 1035, 1074, 18446744073709551615, 0, 1), - (13, 1009, 1044, 595, 18446744073709551615, 1, 2), - (13, 242, 1045, 594, 18446744073709551615, 1, 2), - (13, 1029, 1035, 1011, 18446744073709551615, 24, 25), - (13, 1029, 1045, 242, 18446744073709551615, 24, 26), - (13, 1029, 1044, 1009, 18446744073709551615, 24, 27), - (13, 1008, 1046, 968, 18446744073709551615, 0, 1), - (13, 1009, 1044, 1074, 18446744073709551615, 0, 1), - (13, 242, 1045, 193, 18446744073709551615, 0, 1), - (13, 1008, 1046, 595, 18446744073709551615, 0, 1), - (13, 1009, 1044, 594, 18446744073709551615, 0, 1), - (13, 1029, 1045, 242, 18446744073709551615, 25, 26), - (13, 1029, 1044, 1009, 18446744073709551615, 25, 27), - (13, 1029, 1046, 1008, 18446744073709551615, 25, 28), - (13, 239, 1050, 1073, 18446744073709551615, 0, 1), - (13, 1008, 1046, 196, 18446744073709551615, 0, 1), - (13, 1009, 1044, 968, 18446744073709551615, 0, 1), - (13, 239, 1050, 597, 18446744073709551615, 2, 3), - (13, 1008, 1046, 596, 18446744073709551615, 2, 3), - (13, 1029, 1044, 1009, 18446744073709551615, 26, 27), - (13, 1029, 1046, 1008, 18446744073709551615, 26, 28), - (13, 1029, 1050, 239, 18446744073709551615, 26, 29), - (13, 1006, 1040, 196, 18446744073709551615, 0, 1), - (13, 239, 1050, 968, 18446744073709551615, 0, 1), - (13, 1008, 1046, 1074, 18446744073709551615, 0, 1), - (13, 1006, 1040, 597, 18446744073709551615, 1, 2), - (13, 239, 1050, 596, 18446744073709551615, 1, 2), - (13, 1029, 1046, 1008, 18446744073709551615, 27, 28), - (13, 1029, 1050, 239, 18446744073709551615, 27, 29), - (13, 1029, 1040, 1006, 18446744073709551615, 27, 30), - (13, 1005, 1048, 1074, 18446744073709551615, 0, 1), - (13, 1006, 1040, 193, 18446744073709551615, 0, 1), - (13, 239, 1050, 965, 18446744073709551615, 0, 1), - (13, 1005, 1048, 597, 18446744073709551615, 0, 1), - (13, 1006, 1040, 596, 18446744073709551615, 0, 1), - (13, 1029, 1050, 239, 18446744073709551615, 28, 29), - (13, 1029, 1040, 1006, 18446744073709551615, 28, 30), - (13, 1029, 1048, 1005, 18446744073709551615, 28, 31), - (13, 236, 1042, 196, 18446744073709551615, 0, 1), - (13, 1005, 1048, 968, 18446744073709551615, 0, 1), - (13, 1006, 1040, 1074, 18446744073709551615, 0, 1), - (13, 236, 1042, 599, 18446744073709551615, 2, 3), - (13, 1005, 1048, 598, 18446744073709551615, 2, 3), - (13, 1029, 1040, 1006, 18446744073709551615, 29, 30), - (13, 1029, 1048, 1005, 18446744073709551615, 29, 31), - (13, 1029, 1042, 236, 18446744073709551615, 29, 32), - (13, 1003, 1052, 968, 18446744073709551615, 0, 1), - (13, 236, 1042, 1074, 18446744073709551615, 0, 1), - (13, 1005, 1048, 193, 18446744073709551615, 0, 1), - (13, 1003, 1052, 599, 18446744073709551615, 1, 2), - (13, 236, 1042, 598, 18446744073709551615, 1, 2), - (13, 1029, 1048, 1005, 18446744073709551615, 30, 31), - (13, 1029, 1042, 236, 18446744073709551615, 30, 32), - (13, 1029, 1052, 1003, 18446744073709551615, 30, 33), - (13, 1002, 1051, 965, 18446744073709551615, 0, 1), - (13, 1003, 1052, 1075, 18446744073709551615, 0, 1), - (13, 236, 1042, 190, 18446744073709551615, 0, 1), - (13, 1002, 1051, 599, 18446744073709551615, 0, 1), - (13, 1003, 1052, 598, 18446744073709551615, 0, 1), - (13, 1029, 1042, 236, 18446744073709551615, 31, 32), - (13, 1029, 1052, 1003, 18446744073709551615, 31, 33), - (13, 1029, 1051, 1002, 18446744073709551615, 31, 34), - (13, 1002, 1051, 1074, 18446744073709551615, 0, 1), - (13, 1003, 1052, 193, 18446744073709551615, 0, 1), - (13, 1002, 1051, 600, 18446744073709551615, 2, 3), - (13, 1029, 1052, 1003, 18446744073709551615, 32, 33), - (13, 1029, 1051, 1002, 18446744073709551615, 32, 34), - (13, 233, 1053, 965, 18446744073709551615, 0, 1), - (13, 1002, 1051, 1075, 18446744073709551615, 0, 1), - (13, 233, 1053, 600, 18446744073709551615, 1, 2), - (13, 1029, 1051, 1002, 18446744073709551615, 33, 34), - (13, 1029, 1053, 233, 18446744073709551615, 33, 35), - (13, 1000, 255, 1075, 18446744073709551615, 0, 2), - (13, 233, 1053, 190, 18446744073709551615, 0, 1), - (13, 1000, 255, 600, 18446744073709551615, 0, 1), - (13, 1029, 1053, 233, 18446744073709551615, 34, 35), - (13, 1029, 255, 1000, 18446744073709551615, 34, 36), - (13, 999, 1047, 965, 18446744073709551615, 1, 2), - (13, 1000, 255, 1075, 18446744073709551615, 1, 2), - (13, 999, 1047, 602, 18446744073709551615, 2, 3), - (13, 1029, 255, 1000, 18446744073709551615, 35, 36), - (13, 1029, 1047, 999, 18446744073709551615, 35, 37), - (13, 230, 252, 1075, 18446744073709551615, 0, 1), - (13, 999, 1047, 190, 18446744073709551615, 0, 1), - (13, 230, 252, 602, 18446744073709551615, 1, 2), - (13, 1029, 1047, 999, 18446744073709551615, 36, 37), - (13, 1029, 252, 230, 18446744073709551615, 36, 38), - (13, 997, 172, 962, 18446744073709551615, 0, 1), - (13, 230, 252, 1076, 18446744073709551615, 0, 1), - (13, 997, 172, 602, 18446744073709551615, 0, 1), - (13, 1029, 252, 230, 18446744073709551615, 37, 38), - (13, 1029, 172, 997, 18446744073709551615, 37, 39), - (13, 996, 249, 1075, 18446744073709551615, 0, 1), - (13, 997, 172, 190, 18446744073709551615, 0, 1), - (13, 996, 249, 604, 18446744073709551615, 2, 3), - (13, 1029, 172, 997, 18446744073709551615, 38, 39), - (13, 1029, 249, 996, 18446744073709551615, 38, 40), - (13, 227, 246, 962, 18446744073709551615, 0, 1), - (13, 996, 249, 1076, 18446744073709551615, 0, 1), - (13, 227, 246, 604, 18446744073709551615, 1, 2), - (13, 1029, 249, 996, 18446744073709551615, 39, 40), - (13, 1029, 246, 227, 18446744073709551615, 39, 41), - (13, 994, 243, 1076, 18446744073709551615, 0, 2), - (13, 227, 246, 187, 18446744073709551615, 0, 1), - (13, 994, 243, 604, 18446744073709551615, 0, 1), - (13, 1029, 246, 227, 18446744073709551615, 40, 41), - (13, 1029, 243, 994, 18446744073709551615, 40, 42), - (13, 993, 240, 962, 18446744073709551615, 1, 2), - (13, 994, 243, 1076, 18446744073709551615, 1, 2), - (13, 993, 240, 733, 18446744073709551615, 2, 3), - (13, 1029, 243, 994, 18446744073709551615, 41, 42), - (13, 1029, 240, 993, 18446744073709551615, 41, 43), - (13, 224, 237, 962, 18446744073709551615, 0, 1), - (13, 993, 240, 1076, 18446744073709551615, 0, 1), - (13, 224, 237, 733, 18446744073709551615, 1, 2), - (13, 1029, 240, 993, 18446744073709551615, 42, 43), - (13, 1029, 237, 224, 18446744073709551615, 42, 44), - (13, 991, 234, 187, 18446744073709551615, 0, 2), - (13, 224, 237, 959, 18446744073709551615, 0, 1), - (13, 991, 234, 733, 18446744073709551615, 0, 1), - (13, 1029, 237, 224, 18446744073709551615, 43, 44), - (13, 1029, 234, 991, 18446744073709551615, 43, 45), - (13, 990, 231, 1076, 18446744073709551615, 1, 2), - (13, 991, 234, 187, 18446744073709551615, 1, 2), - (13, 990, 231, 606, 18446744073709551615, 2, 3), - (13, 1029, 234, 991, 18446744073709551615, 44, 45), - (13, 1029, 231, 990, 18446744073709551615, 44, 46), - (13, 221, 228, 187, 18446744073709551615, 0, 1), - (13, 990, 231, 959, 18446744073709551615, 0, 1), - (13, 221, 228, 606, 18446744073709551615, 1, 2), - (13, 1029, 231, 990, 18446744073709551615, 45, 46), - (13, 1029, 228, 221, 18446744073709551615, 45, 47), - (13, 988, 225, 959, 18446744073709551615, 0, 1), - (13, 221, 228, 1077, 18446744073709551615, 0, 1), - (13, 988, 225, 606, 18446744073709551615, 0, 1), - (13, 1029, 228, 221, 18446744073709551615, 46, 47), - (13, 1029, 225, 988, 18446744073709551615, 46, 48), - (13, 987, 222, 959, 18446744073709551615, 0, 1), - (13, 988, 225, 1077, 18446744073709551615, 0, 1), - (13, 987, 222, 608, 18446744073709551615, 2, 3), - (13, 1029, 225, 988, 18446744073709551615, 47, 48), - (13, 1029, 222, 987, 18446744073709551615, 47, 49), - (13, 218, 219, 959, 18446744073709551615, 0, 1), - (13, 987, 222, 1077, 18446744073709551615, 0, 1), - (13, 218, 219, 608, 18446744073709551615, 1, 2), - (13, 1029, 222, 987, 18446744073709551615, 48, 49), - (13, 1029, 219, 218, 18446744073709551615, 48, 50), - (13, 985, 216, 184, 18446744073709551615, 0, 1), - (13, 218, 219, 956, 18446744073709551615, 0, 1), - (13, 985, 216, 608, 18446744073709551615, 0, 1), - (13, 1029, 219, 218, 18446744073709551615, 49, 50), - (13, 1029, 216, 985, 18446744073709551615, 49, 51), - (13, 984, 213, 959, 18446744073709551615, 0, 1), - (13, 985, 216, 1077, 18446744073709551615, 0, 1), - (13, 984, 213, 685, 18446744073709551615, 2, 3), - (13, 1029, 216, 985, 18446744073709551615, 50, 51), - (13, 1029, 213, 984, 18446744073709551615, 50, 52), - (13, 215, 210, 184, 18446744073709551615, 0, 1), - (13, 984, 213, 956, 18446744073709551615, 0, 1), - (13, 215, 210, 685, 18446744073709551615, 1, 2), - (13, 1029, 213, 984, 18446744073709551615, 51, 52), - (13, 982, 207, 956, 18446744073709551615, 0, 2), - (13, 215, 210, 1078, 18446744073709551615, 0, 1), - (13, 982, 207, 685, 18446744073709551615, 0, 1), - (13, 1029, 210, 215, 18446744073709551615, 52, 53), - (13, 981, 204, 184, 18446744073709551615, 1, 2), - (13, 982, 207, 956, 18446744073709551615, 1, 2), - (13, 981, 204, 1093, 18446744073709551615, 2, 3), - (13, 1029, 207, 982, 18446744073709551615, 53, 54), - (13, 1029, 204, 981, 18446744073709551615, 53, 55), - (13, 981, 204, 1078, 18446744073709551615, 0, 1), - (13, 1029, 204, 981, 18446744073709551615, 54, 55), - (13, 979, 198, 1078, 18446744073709551615, 0, 2), - (13, 212, 201, 181, 18446744073709551615, 0, 1), - (13, 979, 198, 1093, 18446744073709551615, 0, 1), - (13, 1029, 201, 212, 18446744073709551615, 55, 56), - (13, 1029, 198, 979, 18446744073709551615, 55, 57), - (13, 979, 198, 1078, 18446744073709551615, 1, 2), - (13, 1029, 198, 979, 18446744073709551615, 56, 57), - (13, 978, 195, 953, 18446744073709551615, 0, 1), - (13, 1029, 195, 978, 18446744073709551615, 57, 58), - (13, 209, 192, 1079, 18446744073709551615, 0, 1), - (13, 1029, 192, 209, 18446744073709551615, 58, 59), - (13, 976, 189, 953, 18446744073709551615, 1, 2), - (13, 1029, 189, 976, 18446744073709551615, 59, 60), - (13, 975, 186, 1079, 18446744073709551615, 0, 1), - (13, 1029, 186, 975, 18446744073709551615, 60, 61), - (13, 206, 183, 178, 18446744073709551615, 0, 1), - (13, 1029, 183, 206, 18446744073709551615, 61, 62), - (13, 973, 180, 1079, 18446744073709551615, 1, 2), - (13, 1029, 180, 973, 18446744073709551615, 62, 63), - (13, 972, 177, 178, 18446744073709551615, 0, 1), - (13, 1029, 177, 972, 18446744073709551615, 63, 64), - (13, 203, 174, 950, 18446744073709551615, 0, 1), - (13, 1029, 174, 203, 18446744073709551615, 64, 65), - (13, 970, 1083, 178, 18446744073709551615, 1, 2), - (13, 1029, 1083, 970, 18446744073709551615, 65, 66), - (13, 969, 173, 950, 18446744073709551615, 0, 1), - (13, 1029, 173, 969, 18446744073709551615, 66, 67), - (13, 200, 159, 1080, 18446744073709551615, 0, 1), - (13, 1029, 159, 200, 18446744073709551615, 67, 68), - (13, 967, 912, 950, 18446744073709551615, 1, 2), - (13, 1029, 912, 967, 18446744073709551615, 68, 69), - (13, 966, 152, 175, 18446744073709551615, 0, 1), - (13, 1029, 152, 966, 18446744073709551615, 69, 70), - (13, 197, 149, 947, 18446744073709551615, 0, 1), - (13, 1029, 149, 197, 18446744073709551615, 70, 71), - (13, 964, 141, 175, 18446744073709551615, 1, 2), - (13, 1029, 141, 964, 18446744073709551615, 71, 72), - (13, 963, 1091, 947, 18446744073709551615, 0, 1), - (13, 1029, 1091, 963, 18446744073709551615, 72, 73), - (13, 194, 1096, 1081, 18446744073709551615, 0, 1), - (13, 1029, 1096, 194, 18446744073709551615, 73, 74), - (13, 961, 137, 947, 18446744073709551615, 1, 2), - (13, 1029, 137, 961, 18446744073709551615, 74, 75), - (13, 960, 134, 941, 18446744073709551615, 0, 1), - (13, 1029, 134, 960, 18446744073709551615, 75, 76), - (13, 191, 131, 944, 18446744073709551615, 0, 1), - (13, 1029, 131, 191, 18446744073709551615, 76, 77), - (13, 958, 124, 944, 18446744073709551615, 0, 1), - (13, 1029, 124, 958, 18446744073709551615, 77, 78), - (13, 957, 122, 944, 18446744073709551615, 0, 1), - (13, 1029, 122, 957, 18446744073709551615, 78, 79), - (13, 188, 112, 944, 18446744073709551615, 0, 1), - (13, 1029, 112, 188, 18446744073709551615, 79, 80), - (13, 955, 120, 944, 18446744073709551615, 0, 1), - (13, 1029, 120, 955, 18446744073709551615, 80, 81), - (13, 954, 109, 169, 18446744073709551615, 0, 1), - (13, 1029, 109, 954, 18446744073709551615, 81, 82), - (13, 185, 106, 939, 18446744073709551615, 0, 1), - (13, 1029, 106, 185, 18446744073709551615, 82, 83), - (13, 952, 103, 938, 18446744073709551615, 1, 2), - (13, 1029, 103, 952, 18446744073709551615, 83, 84), - (13, 951, 100, 1084, 18446744073709551615, 0, 1), - (13, 1029, 100, 951, 18446744073709551615, 84, 85), - (13, 182, 97, 939, 18446744073709551615, 1, 2), - (13, 1029, 97, 182, 18446744073709551615, 85, 86), - (13, 949, 94, 938, 18446744073709551615, 2, 3), - (13, 1029, 94, 949, 18446744073709551615, 86, 87), - (13, 948, 91, 1084, 18446744073709551615, 0, 1), - (13, 1029, 91, 948, 18446744073709551615, 87, 88), - (13, 179, 88, 166, 18446744073709551615, 0, 1), - (13, 1029, 88, 179, 18446744073709551615, 88, 89), - (13, 946, 85, 1084, 18446744073709551615, 1, 2), - (13, 1029, 85, 946, 18446744073709551615, 89, 90), - (13, 945, 82, 166, 18446744073709551615, 0, 1), - (13, 1029, 82, 945, 18446744073709551615, 90, 91), - (13, 176, 79, 171, 18446744073709551615, 0, 1), - (13, 1029, 79, 176, 18446744073709551615, 91, 92), - (13, 943, 76, 166, 18446744073709551615, 1, 2), - (13, 1029, 76, 943, 18446744073709551615, 92, 93), - (13, 942, 73, 940, 18446744073709551615, 0, 1), - (13, 1029, 73, 942, 18446744073709551615, 93, 94), - (13, 1082, 70, 940, 18446744073709551615, 0, 1), - (13, 1029, 70, 1082, 18446744073709551615, 94, 96), - (13, 156, 67, 163, 18446744073709551615, 0, 1), - (13, 1082, 70, 930, 18446744073709551615, 0, 1), - (13, 156, 67, 662, 18446744073709551615, 0, 1), - (13, 1029, 70, 1082, 18446744073709551615, 95, 96), - (13, 1029, 67, 156, 18446744073709551615, 95, 97), - (13, 168, 64, 163, 18446744073709551615, 0, 1), - (13, 156, 67, 930, 18446744073709551615, 0, 1), - (13, 168, 64, 662, 18446744073709551615, 0, 1), - (13, 1029, 67, 156, 18446744073709551615, 96, 97), - (13, 1029, 64, 168, 18446744073709551615, 96, 97), - (13, 170, 61, 932, 18446744073709551615, 1, 2), - (13, 1029, 61, 170, 18446744073709551615, 97, 98), - (13, 937, 58, 940, 18446744073709551615, 2, 3), - (13, 1029, 58, 937, 18446744073709551615, 98, 99), - (13, 936, 55, 930, 18446744073709551615, 0, 1), - (13, 1029, 55, 936, 18446744073709551615, 99, 100), - (13, 167, 52, 930, 18446744073709551615, 0, 1), - (13, 1029, 52, 167, 18446744073709551615, 100, 101), - (13, 162, 49, 163, 18446744073709551615, 1, 2), - (13, 1029, 49, 162, 18446744073709551615, 101, 102), - (13, 929, 34, 932, 18446744073709551615, 0, 1), - (13, 1029, 34, 929, 18446744073709551615, 105, 106), - (13, 935, 31, 930, 18446744073709551615, 0, 1), - (13, 1029, 31, 935, 18446744073709551615, 106, 107), - (13, 160, 19, 930, 18446744073709551615, 0, 1), - (13, 1029, 19, 160, 18446744073709551615, 108, 109), - (13, 153, 1133, 931, 18446744073709551615, 0, 1), - (13, 157, 782, 934, 18446744073709551615, 0, 1), - (13, 1029, 782, 157, 18446744073709551615, 111, 112), - (13, 154, 1138, 934, 18446744073709551615, 0, 1), - (13, 1029, 1138, 154, 18446744073709551615, 112, 113), - (13, 921, 1114, 934, 18446744073709551615, 0, 1), - (13, 1029, 1114, 921, 18446744073709551615, 113, 114), - (13, 920, 1135, 1085, 18446744073709551615, 0, 1), - (13, 1029, 1135, 920, 18446744073709551615, 114, 115), - (13, 151, 783, 926, 18446744073709551615, 0, 1), - (13, 1029, 783, 151, 18446744073709551615, 115, 116), - (13, 918, 1136, 1085, 18446744073709551615, 1, 2), - (13, 1029, 1136, 918, 18446744073709551615, 116, 117), - (13, 911, 836, 926, 18446744073709551615, 0, 1), - (13, 1029, 836, 911, 18446744073709551615, 117, 118), - (13, 919, 1143, 923, 18446744073709551615, 0, 1), - (13, 1029, 1143, 919, 18446744073709551615, 123, 124), - (13, 142, 1144, 923, 18446744073709551615, 0, 1), - (13, 910, 745, 928, 18446744073709551615, 1, 2), - (13, 1029, 745, 910, 18446744073709551615, 125, 126), - (13, 140, 743, 924, 18446744073709551615, 0, 1), - (13, 1029, 743, 140, 18446744073709551615, 127, 128), - (13, 906, 742, 923, 18446744073709551615, 1, 2), - (13, 905, 741, 924, 18446744073709551615, 0, 1), - (13, 136, 740, 925, 18446744073709551615, 0, 1), - (13, 1029, 740, 136, 18446744073709551615, 130, 131), - (13, 903, 739, 925, 18446744073709551615, 0, 1), - (13, 1029, 739, 903, 18446744073709551615, 131, 132), - (13, 902, 738, 1086, 18446744073709551615, 0, 1), - (13, 1029, 738, 902, 18446744073709551615, 132, 133), - (13, 133, 737, 150, 18446744073709551615, 0, 1), - (13, 1029, 737, 133, 18446744073709551615, 133, 134), - (13, 900, 736, 1086, 18446744073709551615, 1, 2), - (13, 1029, 736, 900, 18446744073709551615, 134, 135), - (13, 1095, 735, 1086, 18446744073709551615, 0, 1), - (13, 892, 757, 915, 18446744073709551615, 0, 1), - (13, 1029, 757, 892, 18446744073709551615, 142, 143), - (13, 891, 756, 1087, 18446744073709551615, 0, 1), - (13, 1116, 1142, 915, 18446744073709551615, 0, 1), - (13, 1029, 1142, 1116, 18446744073709551615, 144, 145), - (13, 115, 778, 915, 18446744073709551615, 0, 1), - (13, 1029, 778, 115, 18446744073709551615, 146, 147), - (13, 875, 26, 1088, 18446744073709551615, 2, 3), - (13, 105, 24, 917, 18446744073709551615, 0, 1), - (13, 869, 1130, 917, 18446744073709551615, 1, 2), - (13, 868, 29, 1090, 18446744073709551615, 1, 2), - (13, 866, 1129, 1090, 18446744073709551615, 1, 2), - (13, 865, 32, 907, 18446744073709551615, 2, 3), - (13, 96, 36, 907, 18446744073709551615, 3, 4), - (13, 863, 1128, 1089, 18446744073709551615, 4, 5), - (13, 862, 35, 138, 18446744073709551615, 3, 4), - (13, 93, 39, 908, 18446744073709551615, 3, 4), - (13, 860, 1127, 138, 18446744073709551615, 4, 5), - (13, 859, 38, 135, 18446744073709551615, 3, 4), - (13, 1029, 38, 859, 18446744073709551615, 174, 175), - (13, 90, 42, 135, 18446744073709551615, 3, 4), - (13, 1029, 42, 90, 18446744073709551615, 175, 176), - (13, 857, 1126, 908, 18446744073709551615, 4, 5), - (13, 856, 41, 909, 18446744073709551615, 3, 4), - (13, 1029, 41, 856, 18446744073709551615, 177, 178), - (13, 87, 45, 909, 18446744073709551615, 3, 4), - (13, 1029, 45, 87, 18446744073709551615, 178, 179), - (13, 854, 1125, 135, 18446744073709551615, 4, 5), - (13, 853, 44, 1092, 18446744073709551615, 3, 4), - (13, 84, 48, 132, 18446744073709551615, 3, 4), - (13, 851, 1124, 1092, 18446744073709551615, 4, 5), - (13, 850, 47, 132, 18446744073709551615, 3, 4), - (13, 81, 51, 904, 18446744073709551615, 3, 4), - (13, 848, 1123, 132, 18446744073709551615, 4, 5), - (13, 847, 50, 904, 18446744073709551615, 3, 4), - (13, 78, 54, 660, 18446744073709551615, 5, 6), - (13, 845, 1122, 660, 18446744073709551615, 5, 6), - (13, 1029, 1122, 845, 18446744073709551615, 188, 189), - (13, 844, 53, 660, 18446744073709551615, 4, 5), - (13, 1029, 53, 844, 18446744073709551615, 189, 190), - (13, 75, 57, 659, 18446744073709551615, 6, 7), - (13, 842, 1121, 660, 18446744073709551615, 7, 8), - (13, 841, 56, 659, 18446744073709551615, 1, 2), - (13, 72, 60, 658, 18446744073709551615, 2, 3), - (13, 839, 1120, 659, 18446744073709551615, 3, 4), - (13, 837, 59, 657, 18446744073709551615, 4, 5), - (13, 69, 63, 657, 18446744073709551615, 0, 1), - (13, 835, 1117, 658, 18446744073709551615, 1, 2), - (13, 834, 62, 657, 18446744073709551615, 6, 7), - (13, 833, 66, 654, 18446744073709551615, 3, 4), - (13, 1029, 66, 833, 18446744073709551615, 199, 200), - (13, 832, 1119, 656, 18446744073709551615, 3, 4), - (13, 1029, 1119, 832, 18446744073709551615, 200, 201), - (13, 831, 65, 653, 18446744073709551615, 3, 4), - (13, 1029, 65, 831, 18446744073709551615, 201, 202), - (13, 830, 1112, 652, 18446744073709551615, 3, 4), - (13, 1029, 1112, 830, 18446744073709551615, 202, 203), - (13, 829, 838, 654, 18446744073709551615, 3, 4), - (13, 1029, 838, 829, 18446744073709551615, 203, 204), - (13, 828, 68, 651, 18446744073709551615, 3, 4), - (13, 1029, 68, 828, 18446744073709551615, 204, 205), - (13, 827, 1111, 651, 18446744073709551615, 3, 4), - (13, 1029, 1111, 827, 18446744073709551615, 205, 206), - (13, 826, 843, 651, 18446744073709551615, 3, 4), - (13, 1029, 843, 826, 18446744073709551615, 206, 207), - (13, 825, 71, 650, 18446744073709551615, 3, 4), - (13, 1029, 71, 825, 18446744073709551615, 207, 208), - (13, 824, 1110, 649, 18446744073709551615, 3, 4), - (13, 1029, 1110, 824, 18446744073709551615, 208, 209), - (13, 823, 846, 650, 18446744073709551615, 4, 5), - (13, 1029, 846, 823, 18446744073709551615, 209, 210), - (13, 822, 74, 649, 18446744073709551615, 1, 2), - (13, 1029, 74, 822, 18446744073709551615, 210, 211), - (13, 821, 1109, 648, 18446744073709551615, 0, 1), - (13, 1029, 1109, 821, 18446744073709551615, 211, 212), - (13, 820, 849, 650, 18446744073709551615, 1, 2), - (13, 1029, 849, 820, 18446744073709551615, 212, 213), - (13, 819, 77, 650, 18446744073709551615, 1, 2), - (13, 1029, 77, 819, 18446744073709551615, 213, 214), - (13, 818, 1108, 650, 18446744073709551615, 0, 1), - (13, 1029, 1108, 818, 18446744073709551615, 214, 215), - (13, 817, 852, 652, 18446744073709551615, 3, 4), - (13, 816, 80, 652, 18446744073709551615, 1, 2), - (13, 815, 1107, 652, 18446744073709551615, 0, 1), - (13, 814, 855, 654, 18446744073709551615, 3, 4), - (13, 813, 83, 654, 18446744073709551615, 1, 2), - (13, 812, 1106, 653, 18446744073709551615, 0, 1), - (13, 1029, 1106, 812, 18446744073709551615, 220, 221), - (13, 811, 858, 655, 18446744073709551615, 0, 1), - (13, 1029, 858, 811, 18446744073709551615, 221, 222), - (13, 810, 86, 655, 18446744073709551615, 1, 2), - (13, 1029, 86, 810, 18446744073709551615, 222, 223), - (13, 809, 1105, 655, 18446744073709551615, 0, 1), - (13, 1029, 1105, 809, 18446744073709551615, 223, 224), - (13, 808, 861, 657, 18446744073709551615, 2, 3), - (13, 1029, 861, 808, 18446744073709551615, 224, 225), - (13, 807, 89, 657, 18446744073709551615, 1, 2), - (13, 1029, 89, 807, 18446744073709551615, 225, 226), - (13, 806, 1104, 657, 18446744073709551615, 0, 1), - (13, 1029, 1104, 806, 18446744073709551615, 226, 227), - (13, 805, 864, 659, 18446744073709551615, 2, 3), - (13, 1029, 864, 805, 18446744073709551615, 227, 228), - (13, 804, 92, 659, 18446744073709551615, 1, 2), - (13, 1029, 92, 804, 18446744073709551615, 228, 229), - (13, 803, 1103, 659, 18446744073709551615, 0, 1), - (13, 1029, 1103, 803, 18446744073709551615, 229, 230), - (13, 802, 867, 661, 18446744073709551615, 2, 3), - (13, 1029, 867, 802, 18446744073709551615, 230, 231), - (13, 801, 95, 661, 18446744073709551615, 1, 2), - (13, 1029, 95, 801, 18446744073709551615, 231, 232), - (13, 800, 1102, 661, 18446744073709551615, 0, 1), - (13, 1029, 1102, 800, 18446744073709551615, 232, 233), - (13, 799, 870, 132, 18446744073709551615, 2, 3), - (13, 1029, 870, 799, 18446744073709551615, 233, 234), - (13, 798, 98, 132, 18446744073709551615, 1, 2), - (13, 1029, 98, 798, 18446744073709551615, 234, 235), - (13, 797, 1101, 132, 18446744073709551615, 0, 1), - (13, 1029, 1101, 797, 18446744073709551615, 235, 236), - (13, 796, 873, 909, 18446744073709551615, 2, 3), - (13, 1029, 873, 796, 18446744073709551615, 236, 237), - (13, 795, 101, 909, 18446744073709551615, 1, 2), - (13, 1029, 101, 795, 18446744073709551615, 237, 238), - (13, 18, 1100, 909, 18446744073709551615, 0, 1), - (13, 1029, 1100, 18, 18446744073709551615, 238, 239), - (13, 786, 110, 148, 18446744073709551615, 1, 2), - (13, 1029, 110, 786, 18446744073709551615, 245, 246), - (13, 27, 894, 148, 18446744073709551615, 0, 1), - (13, 1029, 894, 27, 18446744073709551615, 246, 248), - (13, 1134, 885, 1090, 18446744073709551615, 0, 1), - (13, 27, 894, 1089, 18446744073709551615, 0, 1), - (13, 1134, 885, 143, 18446744073709551615, 1, 4), - (13, 1029, 894, 27, 18446744073709551615, 247, 248), - (13, 1029, 885, 1134, 18446744073709551615, 247, 249), - (13, 17, 113, 148, 18446744073709551615, 0, 1), - (13, 1134, 885, 917, 18446744073709551615, 0, 1), - (13, 17, 113, 916, 18446744073709551615, 2, 3), - (13, 1029, 885, 1134, 18446744073709551615, 248, 249), - (13, 1029, 113, 17, 18446744073709551615, 248, 250), - (13, 1137, 887, 148, 18446744073709551615, 1, 2), - (13, 17, 113, 917, 18446744073709551615, 1, 2), - (13, 1137, 887, 916, 18446744073709551615, 2, 4), - (13, 1029, 113, 17, 18446744073709551615, 249, 250), - (13, 1029, 887, 1137, 18446744073709551615, 249, 252), - (13, 1145, 1097, 148, 18446744073709551615, 0, 1), - (13, 1137, 887, 917, 18446744073709551615, 0, 1), - (13, 1145, 1097, 916, 18446744073709551615, 0, 1), - (13, 1029, 887, 1137, 18446744073709551615, 250, 252), - (13, 1029, 1097, 1145, 18446744073709551615, 250, 255), - (13, 1026, 13, 1145, 18446744073709551615, 250, 251), - (13, 13, 116, 148, 18446744073709551615, 0, 1), - (13, 1145, 1097, 917, 18446744073709551615, 0, 1), - (13, 1137, 887, 1090, 18446744073709551615, 0, 1), - (13, 13, 116, 916, 18446744073709551615, 1, 2), - (13, 1145, 1097, 1088, 18446744073709551615, 1, 2), - (13, 1029, 887, 1137, 18446744073709551615, 251, 252), - (13, 1029, 1097, 1145, 18446744073709551615, 251, 255), - (13, 1029, 116, 13, 18446744073709551615, 251, 255), - (13, 1026, 777, 13, 18446744073709551615, 251, 254), - (13, 777, 886, 148, 18446744073709551615, 0, 2), - (13, 13, 116, 917, 18446744073709551615, 0, 2), - (13, 1145, 1097, 1090, 18446744073709551615, 0, 1), - (13, 764, 116, 13, 18446744073709551615, 250, 253), - (13, 777, 886, 916, 18446744073709551615, 2, 3), - (13, 13, 116, 1088, 18446744073709551615, 2, 3), - (13, 1029, 1097, 1145, 18446744073709551615, 252, 255), - (13, 1029, 116, 13, 18446744073709551615, 252, 255), - (13, 1029, 886, 777, 18446744073709551615, 252, 257), - (13, 1026, 777, 13, 18446744073709551615, 252, 254), - (13, 11, 889, 1090, 18446744073709551615, 0, 3), - (13, 777, 886, 1089, 18446744073709551615, 0, 2), - (13, 13, 116, 907, 18446744073709551615, 0, 1), - (13, 1145, 1097, 138, 18446744073709551615, 0, 1), - (13, 764, 886, 777, 18446744073709551615, 251, 255), - (13, 764, 116, 13, 18446744073709551615, 251, 253), - (13, 764, 1097, 1145, 18446744073709551615, 251, 253), - (13, 11, 889, 143, 18446744073709551615, 1, 3), - (13, 777, 886, 148, 18446744073709551615, 1, 2), - (13, 13, 116, 917, 18446744073709551615, 1, 2), - (13, 1029, 1097, 1145, 18446744073709551615, 253, 255), - (13, 1029, 116, 13, 18446744073709551615, 253, 255), - (13, 1029, 886, 777, 18446744073709551615, 253, 257), - (13, 1029, 889, 11, 18446744073709551615, 253, 257), - (13, 1026, 14, 11, 18446744073709551615, 253, 256), - (13, 1026, 11, 777, 18446744073709551615, 253, 254), - (13, 1026, 777, 13, 18446744073709551615, 253, 254), - (13, 14, 888, 1090, 18446744073709551615, 0, 1), - (13, 11, 889, 1089, 18446744073709551615, 0, 1), - (13, 777, 886, 907, 18446744073709551615, 0, 1), - (13, 13, 116, 138, 18446744073709551615, 0, 1), - (13, 1145, 1097, 908, 18446744073709551615, 0, 1), - (13, 764, 886, 777, 18446744073709551615, 252, 255), - (13, 764, 116, 13, 18446744073709551615, 252, 253), - (13, 764, 1097, 1145, 18446744073709551615, 252, 253), - (13, 14, 888, 143, 18446744073709551615, 0, 7), - (13, 11, 889, 148, 18446744073709551615, 0, 1), - (13, 777, 886, 917, 18446744073709551615, 0, 1), - (13, 13, 116, 1090, 18446744073709551615, 0, 1), - (13, 1029, 1097, 1145, 18446744073709551615, 254, 255), - (13, 1029, 116, 13, 18446744073709551615, 254, 255), - (13, 1029, 886, 777, 18446744073709551615, 254, 257), - (13, 1029, 889, 11, 18446744073709551615, 254, 257), - (13, 1029, 888, 14, 18446744073709551615, 254, 258), - (13, 1026, 14, 11, 18446744073709551615, 254, 256), - (13, 747, 121, 148, 18446744073709551615, 1, 4), - (13, 14, 888, 917, 18446744073709551615, 1, 4), - (13, 11, 889, 1090, 18446744073709551615, 1, 3), - (13, 777, 886, 1089, 18446744073709551615, 1, 2), - (13, 764, 888, 14, 18446744073709551615, 253, 256), - (13, 764, 889, 11, 18446744073709551615, 253, 255), - (13, 764, 886, 777, 18446744073709551615, 253, 255), - (13, 747, 121, 916, 18446744073709551615, 2, 3), - (13, 14, 888, 1088, 18446744073709551615, 2, 3), - (13, 11, 889, 143, 18446744073709551615, 2, 3), - (13, 1029, 886, 777, 18446744073709551615, 255, 257), - (13, 1029, 889, 11, 18446744073709551615, 255, 257), - (13, 1029, 888, 14, 18446744073709551615, 255, 258), - (13, 1029, 121, 747, 18446744073709551615, 255, 262), - (13, 1026, 748, 747, 18446744073709551615, 255, 257), - (13, 1026, 747, 14, 18446744073709551615, 255, 256), - (13, 1026, 14, 11, 18446744073709551615, 255, 256), - (13, 748, 901, 1090, 18446744073709551615, 0, 1), - (13, 747, 121, 1089, 18446744073709551615, 0, 1), - (13, 14, 888, 907, 18446744073709551615, 0, 1), - (13, 11, 889, 138, 18446744073709551615, 0, 1), - (13, 777, 886, 908, 18446744073709551615, 0, 1), - (13, 764, 121, 747, 18446744073709551615, 254, 260), - (13, 764, 888, 14, 18446744073709551615, 254, 256), - (13, 764, 889, 11, 18446744073709551615, 254, 255), - (13, 764, 886, 777, 18446744073709551615, 254, 255), - (13, 748, 901, 143, 18446744073709551615, 2, 4), - (13, 747, 121, 148, 18446744073709551615, 2, 4), - (13, 14, 888, 917, 18446744073709551615, 2, 4), - (13, 11, 889, 1090, 18446744073709551615, 2, 3), - (13, 1029, 886, 777, 18446744073709551615, 256, 257), - (13, 1029, 889, 11, 18446744073709551615, 256, 257), - (13, 1029, 888, 14, 18446744073709551615, 256, 258), - (13, 1029, 121, 747, 18446744073709551615, 256, 262), - (13, 1029, 901, 748, 18446744073709551615, 256, 262), - (13, 1026, 749, 748, 18446744073709551615, 256, 261), - (13, 1026, 748, 747, 18446744073709551615, 256, 257), - (13, 749, 123, 916, 18446744073709551615, 0, 1), - (13, 748, 901, 143, 18446744073709551615, 3, 4), - (13, 747, 121, 148, 18446744073709551615, 3, 4), - (13, 14, 888, 917, 18446744073709551615, 3, 4), - (13, 764, 901, 748, 18446744073709551615, 255, 260), - (13, 764, 121, 747, 18446744073709551615, 255, 260), - (13, 764, 888, 14, 18446744073709551615, 255, 256), - (13, 748, 901, 116, 18446744073709551615, 0, 1), - (13, 747, 121, 1088, 18446744073709551615, 1, 2), - (13, 1029, 888, 14, 18446744073709551615, 257, 258), - (13, 1029, 121, 747, 18446744073709551615, 257, 262), - (13, 1029, 901, 748, 18446744073709551615, 257, 262), - (13, 1029, 123, 749, 18446744073709551615, 257, 262), - (13, 1026, 750, 749, 18446744073709551615, 257, 261), - (13, 1026, 749, 748, 18446744073709551615, 257, 261), - (13, 750, 899, 916, 18446744073709551615, 3, 6), - (13, 749, 123, 143, 18446744073709551615, 1, 3), - (13, 748, 901, 148, 18446744073709551615, 1, 3), - (13, 747, 121, 917, 18446744073709551615, 1, 2), - (13, 764, 123, 749, 18446744073709551615, 256, 260), - (13, 764, 901, 748, 18446744073709551615, 256, 260), - (13, 764, 121, 747, 18446744073709551615, 256, 260), - (13, 749, 123, 116, 18446744073709551615, 0, 1), - (13, 748, 901, 1088, 18446744073709551615, 0, 1), - (13, 1029, 121, 747, 18446744073709551615, 258, 262), - (13, 1029, 901, 748, 18446744073709551615, 258, 262), - (13, 1029, 123, 749, 18446744073709551615, 258, 262), - (13, 1029, 899, 750, 18446744073709551615, 258, 262), - (13, 1026, 751, 750, 18446744073709551615, 258, 261), - (13, 1026, 750, 749, 18446744073709551615, 258, 261), - (13, 1026, 749, 748, 18446744073709551615, 258, 261), - (13, 751, 130, 148, 18446744073709551615, 0, 1), - (13, 750, 899, 917, 18446744073709551615, 0, 1), - (13, 749, 123, 1090, 18446744073709551615, 0, 1), - (13, 748, 901, 1089, 18446744073709551615, 0, 1), - (13, 747, 121, 907, 18446744073709551615, 0, 1), - (13, 764, 899, 750, 18446744073709551615, 257, 260), - (13, 764, 123, 749, 18446744073709551615, 257, 260), - (13, 764, 901, 748, 18446744073709551615, 257, 260), - (13, 764, 121, 747, 18446744073709551615, 257, 260), - (13, 749, 123, 143, 18446744073709551615, 2, 3), - (13, 748, 901, 148, 18446744073709551615, 2, 3), - (13, 1029, 121, 747, 18446744073709551615, 259, 262), - (13, 1029, 901, 748, 18446744073709551615, 259, 262), - (13, 1029, 123, 749, 18446744073709551615, 259, 262), - (13, 1029, 899, 750, 18446744073709551615, 259, 262), - (13, 1029, 130, 751, 18446744073709551615, 259, 262), - (13, 1026, 752, 751, 18446744073709551615, 259, 261), - (13, 1026, 751, 750, 18446744073709551615, 259, 261), - (13, 1026, 750, 749, 18446744073709551615, 259, 261), - (13, 1026, 749, 748, 18446744073709551615, 259, 261), - (13, 751, 130, 917, 18446744073709551615, 0, 2), - (13, 750, 899, 1090, 18446744073709551615, 0, 2), - (13, 749, 123, 1089, 18446744073709551615, 0, 2), - (13, 748, 901, 907, 18446744073709551615, 0, 2), - (13, 747, 121, 138, 18446744073709551615, 0, 1), - (13, 764, 130, 751, 18446744073709551615, 258, 260), - (13, 764, 899, 750, 18446744073709551615, 258, 260), - (13, 764, 123, 749, 18446744073709551615, 258, 260), - (13, 764, 901, 748, 18446744073709551615, 258, 260), - (13, 764, 121, 747, 18446744073709551615, 258, 260), - (13, 749, 123, 148, 18446744073709551615, 0, 1), - (13, 748, 901, 917, 18446744073709551615, 0, 1), - (13, 1029, 121, 747, 18446744073709551615, 260, 262), - (13, 1029, 901, 748, 18446744073709551615, 260, 262), - (13, 1029, 123, 749, 18446744073709551615, 260, 262), - (13, 1029, 899, 750, 18446744073709551615, 260, 262), - (13, 1029, 130, 751, 18446744073709551615, 260, 262), - (13, 1029, 125, 752, 18446744073709551615, 260, 262), - (13, 1026, 753, 752, 18446744073709551615, 260, 261), - (13, 1026, 752, 751, 18446744073709551615, 260, 261), - (13, 1026, 751, 750, 18446744073709551615, 260, 261), - (13, 1026, 750, 749, 18446744073709551615, 260, 261), - (13, 1026, 749, 748, 18446744073709551615, 260, 261), - (13, 753, 1094, 1090, 18446744073709551615, 0, 1), - (13, 752, 125, 1089, 18446744073709551615, 0, 1), - (13, 751, 130, 907, 18446744073709551615, 0, 1), - (13, 750, 899, 138, 18446744073709551615, 0, 1), - (13, 749, 123, 908, 18446744073709551615, 0, 1), - (13, 748, 901, 135, 18446744073709551615, 0, 1), - (13, 747, 121, 909, 18446744073709551615, 0, 1), - (13, 764, 1094, 753, 18446744073709551615, 259, 260), - (13, 764, 125, 752, 18446744073709551615, 259, 260), - (13, 764, 130, 751, 18446744073709551615, 259, 260), - (13, 764, 899, 750, 18446744073709551615, 259, 260), - (13, 764, 123, 749, 18446744073709551615, 259, 260), - (13, 764, 901, 748, 18446744073709551615, 259, 260), - (13, 764, 121, 747, 18446744073709551615, 259, 260), - (13, 749, 123, 1089, 18446744073709551615, 1, 2), - (13, 748, 901, 907, 18446744073709551615, 1, 2), - (13, 1029, 121, 747, 18446744073709551615, 261, 262), - (13, 1029, 901, 748, 18446744073709551615, 261, 262), - (13, 1029, 123, 749, 18446744073709551615, 261, 262), - (13, 1029, 899, 750, 18446744073709551615, 261, 262), - (13, 1029, 130, 751, 18446744073709551615, 261, 262), - (13, 1029, 125, 752, 18446744073709551615, 261, 262), - (13, 1029, 1094, 753, 18446744073709551615, 261, 262), - (13, 1029, 898, 754, 18446744073709551615, 261, 262), - (14, 0, 304, 1147, 18446744073709551615, 0, 1), - (14, 0, 299, 1147, 18446744073709551615, 0, 1), - (14, 0, 293, 1147, 18446744073709551615, 0, 2), - (14, 0, 286, 1147, 18446744073709551615, 0, 1), - (14, 0, 278, 1147, 18446744073709551615, 0, 1), - (14, 0, 269, 1147, 18446744073709551615, 0, 1), - (13, 1028, 768, 8, 18446744073709551615, 0, 262), - (13, 1028, 769, 7, 18446744073709551615, 0, 262), - (13, 1028, 770, 6, 18446744073709551615, 0, 262), - (13, 1024, 770, 6, 18446744073709551615, 0, 260), - (13, 1024, 769, 7, 18446744073709551615, 0, 260), - (13, 1024, 768, 8, 18446744073709551615, 0, 260), - (13, 1, 775, 916, 18446744073709551615, 0, 2), - (13, 2, 774, 1139, 18446744073709551615, 0, 1), - (13, 3, 773, 1150, 18446744073709551615, 0, 1), - (13, 4, 772, 1151, 18446744073709551615, 1, 5), - (13, 5, 771, 1132, 18446744073709551615, 0, 11), - (13, 6, 770, 12, 18446744073709551615, 0, 12), - (13, 7, 769, 1141, 18446744073709551615, 0, 18), - (13, 8, 768, 10, 18446744073709551615, 0, 1), - (13, 776, 7, 6, 18446744073709551615, 0, 261), - (13, 776, 6, 5, 18446744073709551615, 0, 261), - (13, 776, 5, 4, 18446744073709551615, 0, 261), - (13, 776, 4, 3, 18446744073709551615, 0, 261), - (13, 776, 3, 2, 18446744073709551615, 0, 261), - (13, 776, 2, 1, 18446744073709551615, 0, 261), - (13, 256, 1026, 886, 18446744073709551615, 0, 1), - (13, 257, 764, 1097, 18446744073709551615, 0, 2), - (13, 258, 1029, 1149, 18446744073709551615, 0, 3), - (13, 259, 121, 148, 18446744073709551615, 0, 3), - (13, 260, 901, 916, 18446744073709551615, 0, 4), - (13, 261, 123, 1139, 18446744073709551615, 0, 5), - (13, 262, 899, 1150, 18446744073709551615, 0, 5), - (13, 263, 130, 1151, 18446744073709551615, 0, 2), - (13, 264, 125, 1132, 18446744073709551615, 0, 11), - (13, 265, 1094, 12, 18446744073709551615, 0, 8), - (13, 266, 898, 1141, 18446744073709551615, 0, 8), - (13, 267, 897, 10, 18446744073709551615, 0, 2), - (13, 268, 755, 793, 18446744073709551615, 0, 1), - (13, 269, 754, 9, 18446744073709551615, 0, 4), - (13, 270, 753, 1147, 18446744073709551615, 0, 3), - (13, 271, 752, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 143, 18446744073709551615, 0, 13), - (13, 272, 751, 1097, 18446744073709551615, 0, 2), - (13, 273, 750, 1149, 18446744073709551615, 0, 2), - (13, 274, 749, 148, 18446744073709551615, 0, 6), - (13, 275, 748, 916, 18446744073709551615, 0, 6), - (13, 276, 747, 1139, 18446744073709551615, 0, 10), - (13, 277, 917, 1150, 18446744073709551615, 0, 10), - (13, 278, 1090, 1151, 18446744073709551615, 0, 5), - (13, 279, 1089, 1132, 18446744073709551615, 0, 10), - (13, 280, 907, 12, 18446744073709551615, 0, 7), - (13, 281, 138, 1141, 18446744073709551615, 0, 10), - (13, 282, 908, 10, 18446744073709551615, 0, 5), - (13, 283, 135, 793, 18446744073709551615, 0, 5), - (13, 284, 909, 9, 18446744073709551615, 0, 8), - (13, 285, 1092, 1147, 18446744073709551615, 0, 5), - (13, 286, 132, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 886, 18446744073709551615, 0, 7), - (13, 287, 904, 1149, 18446744073709551615, 0, 2), - (13, 288, 661, 148, 18446744073709551615, 0, 2), - (13, 289, 660, 916, 18446744073709551615, 0, 6), - (13, 290, 659, 1139, 18446744073709551615, 0, 5), - (13, 291, 658, 1150, 18446744073709551615, 0, 5), - (13, 292, 657, 1151, 18446744073709551615, 0, 13), - (13, 293, 656, 1132, 18446744073709551615, 0, 10), - (13, 294, 655, 12, 18446744073709551615, 0, 11), - (13, 295, 654, 1141, 18446744073709551615, 0, 10), - (13, 296, 653, 10, 18446744073709551615, 0, 7), - (13, 297, 652, 793, 18446744073709551615, 0, 7), - (13, 298, 651, 9, 18446744073709551615, 0, 11), - (13, 299, 650, 1147, 18446744073709551615, 0, 2), - (13, 300, 649, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 1097, 18446744073709551615, 0, 4), - (13, 301, 648, 148, 18446744073709551615, 0, 3), - (13, 302, 647, 916, 18446744073709551615, 0, 11), - (13, 303, 646, 1139, 18446744073709551615, 0, 13), - (13, 304, 645, 1150, 18446744073709551615, 0, 12), - (13, 305, 644, 1151, 18446744073709551615, 0, 6), - (13, 306, 643, 1132, 18446744073709551615, 0, 9), - (13, 307, 642, 12, 18446744073709551615, 0, 9), - (13, 308, 641, 1141, 18446744073709551615, 0, 11), - (13, 309, 640, 10, 18446744073709551615, 0, 5), - (13, 310, 639, 793, 18446744073709551615, 0, 5), - (13, 311, 638, 9, 18446744073709551615, 0, 14), - (13, 312, 637, 1147, 18446744073709551615, 0, 7), - (13, 313, 636, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 1149, 18446744073709551615, 0, 6), - (13, 314, 635, 916, 18446744073709551615, 0, 9), - (13, 315, 634, 1139, 18446744073709551615, 0, 8), - (13, 316, 633, 1150, 18446744073709551615, 0, 6), - (13, 317, 632, 1151, 18446744073709551615, 0, 11), - (13, 318, 631, 1132, 18446744073709551615, 0, 7), - (13, 319, 630, 12, 18446744073709551615, 0, 8), - (13, 320, 629, 1141, 18446744073709551615, 0, 8), - (13, 321, 628, 10, 18446744073709551615, 0, 3), - (13, 322, 627, 793, 18446744073709551615, 0, 3), - (13, 323, 626, 9, 18446744073709551615, 0, 2), - (13, 324, 625, 1147, 18446744073709551615, 0, 3), - (13, 325, 624, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 148, 18446744073709551615, 0, 7), - (13, 326, 623, 1139, 18446744073709551615, 0, 14), - (13, 327, 622, 1150, 18446744073709551615, 0, 10), - (13, 328, 621, 1151, 18446744073709551615, 0, 8), - (13, 329, 620, 1132, 18446744073709551615, 0, 5), - (13, 330, 619, 12, 18446744073709551615, 0, 6), - (13, 331, 618, 1141, 18446744073709551615, 0, 18), - (13, 332, 617, 10, 18446744073709551615, 0, 14), - (13, 333, 616, 793, 18446744073709551615, 0, 11), - (13, 334, 615, 9, 18446744073709551615, 0, 11), - (13, 335, 614, 1147, 18446744073709551615, 0, 7), - (13, 336, 708, 1153, 18446744073709551615, 0, 2), - (13, 1028, 1153, 916, 18446744073709551615, 0, 10), - (13, 337, 709, 1150, 18446744073709551615, 0, 6), - (13, 338, 710, 1151, 18446744073709551615, 0, 5), - (13, 339, 711, 1132, 18446744073709551615, 0, 15), - (13, 340, 712, 12, 18446744073709551615, 0, 7), - (13, 341, 713, 1141, 18446744073709551615, 0, 6), - (13, 342, 714, 10, 18446744073709551615, 0, 3), - (13, 343, 715, 793, 18446744073709551615, 0, 3), - (13, 344, 716, 9, 18446744073709551615, 0, 11), - (13, 345, 717, 1147, 18446744073709551615, 0, 5), - (13, 346, 718, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 1139, 18446744073709551615, 0, 12), - (13, 347, 719, 1151, 18446744073709551615, 0, 10), - (13, 348, 720, 1132, 18446744073709551615, 0, 7), - (13, 349, 721, 12, 18446744073709551615, 0, 10), - (13, 350, 722, 1141, 18446744073709551615, 0, 8), - (13, 351, 723, 10, 18446744073709551615, 0, 9), - (13, 352, 724, 793, 18446744073709551615, 0, 9), - (13, 353, 725, 9, 18446744073709551615, 0, 15), - (13, 354, 726, 1147, 18446744073709551615, 0, 11), - (13, 355, 727, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 1150, 18446744073709551615, 0, 13), - (13, 356, 728, 1132, 18446744073709551615, 0, 9), - (13, 357, 729, 12, 18446744073709551615, 0, 8), - (13, 358, 613, 1141, 18446744073709551615, 0, 16), - (13, 359, 612, 10, 18446744073709551615, 0, 11), - (13, 360, 686, 793, 18446744073709551615, 0, 9), - (13, 361, 687, 9, 18446744073709551615, 0, 8), - (13, 362, 688, 1147, 18446744073709551615, 0, 11), - (13, 363, 689, 1153, 18446744073709551615, 0, 2), - (13, 1028, 1153, 1151, 18446744073709551615, 0, 13), - (13, 364, 690, 12, 18446744073709551615, 0, 9), - (13, 365, 691, 1141, 18446744073709551615, 0, 8), - (13, 366, 692, 10, 18446744073709551615, 0, 2), - (13, 367, 693, 793, 18446744073709551615, 0, 2), - (13, 368, 694, 9, 18446744073709551615, 0, 7), - (13, 369, 695, 1147, 18446744073709551615, 0, 2), - (13, 370, 696, 1153, 18446744073709551615, 0, 2), - (13, 1028, 1153, 1132, 18446744073709551615, 0, 12), - (13, 371, 697, 1141, 18446744073709551615, 0, 6), - (13, 372, 698, 10, 18446744073709551615, 0, 2), - (13, 373, 699, 793, 18446744073709551615, 0, 2), - (13, 374, 700, 9, 18446744073709551615, 0, 21), - (13, 375, 701, 1147, 18446744073709551615, 0, 2), - (13, 376, 702, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 12, 18446744073709551615, 0, 14), - (13, 377, 703, 10, 18446744073709551615, 0, 25), - (13, 378, 704, 793, 18446744073709551615, 0, 25), - (13, 379, 705, 9, 18446744073709551615, 0, 9), - (13, 380, 706, 1147, 18446744073709551615, 0, 17), - (13, 381, 707, 1153, 18446744073709551615, 0, 5), - (13, 1028, 1153, 1141, 18446744073709551615, 0, 13), - (13, 382, 611, 793, 18446744073709551615, 0, 13), - (13, 383, 610, 9, 18446744073709551615, 0, 4), - (13, 384, 662, 1147, 18446744073709551615, 0, 13), - (13, 385, 663, 1153, 18446744073709551615, 0, 2), - (13, 1028, 1153, 10, 18446744073709551615, 0, 9), - (13, 386, 664, 9, 18446744073709551615, 0, 6), - (13, 387, 665, 1147, 18446744073709551615, 0, 2), - (13, 388, 666, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 793, 18446744073709551615, 0, 8), - (13, 389, 667, 1147, 18446744073709551615, 0, 3), - (13, 390, 668, 1153, 18446744073709551615, 0, 3), - (13, 1028, 1153, 9, 18446744073709551615, 0, 11), - (13, 391, 669, 1153, 18446744073709551615, 0, 1), - (13, 1028, 1153, 1147, 18446744073709551615, 0, 8), - (13, 670, 392, 1147, 18446744073709551615, 0, 2), - (13, 671, 393, 1147, 18446744073709551615, 0, 2), - (13, 672, 394, 1147, 18446744073709551615, 0, 2), - (13, 673, 395, 1147, 18446744073709551615, 0, 2), - (13, 674, 396, 1147, 18446744073709551615, 0, 2), - (13, 675, 397, 1147, 18446744073709551615, 0, 2), - (13, 676, 398, 1147, 18446744073709551615, 0, 2), - (13, 677, 399, 1147, 18446744073709551615, 0, 2), - (13, 678, 400, 1147, 18446744073709551615, 0, 2), - (13, 679, 401, 1147, 18446744073709551615, 0, 2), - (13, 680, 402, 1147, 18446744073709551615, 0, 2), - (13, 681, 403, 1147, 18446744073709551615, 0, 2), - (13, 682, 404, 1147, 18446744073709551615, 0, 2), - (13, 683, 405, 1147, 18446744073709551615, 0, 2), - (13, 730, 406, 1147, 18446744073709551615, 0, 2), - (13, 731, 407, 1147, 18446744073709551615, 0, 2), - (13, 128, 408, 1147, 18446744073709551615, 0, 2), - (13, 1093, 409, 1147, 18446744073709551615, 0, 4), - (13, 684, 410, 1147, 18446744073709551615, 0, 4), - (13, 685, 411, 1147, 18446744073709551615, 0, 4), - (13, 609, 412, 1147, 18446744073709551615, 0, 4), - (13, 608, 413, 1147, 18446744073709551615, 0, 4), - (13, 607, 414, 1147, 18446744073709551615, 0, 4), - (13, 606, 415, 1147, 18446744073709551615, 0, 4), - (13, 732, 416, 1147, 18446744073709551615, 0, 4), - (13, 733, 417, 1147, 18446744073709551615, 0, 4), - (13, 605, 418, 1147, 18446744073709551615, 0, 4), - (13, 604, 419, 1147, 18446744073709551615, 0, 4), - (13, 603, 420, 1147, 18446744073709551615, 0, 4), - (13, 602, 421, 1147, 18446744073709551615, 0, 4), - (13, 601, 422, 1147, 18446744073709551615, 0, 4), - (13, 600, 423, 1147, 18446744073709551615, 0, 4), - (13, 599, 424, 1147, 18446744073709551615, 0, 4), - (13, 598, 425, 1147, 18446744073709551615, 0, 4), - (13, 597, 426, 1147, 18446744073709551615, 0, 4), - (13, 596, 427, 1147, 18446744073709551615, 0, 4), - (13, 595, 428, 1147, 18446744073709551615, 0, 4), - (13, 594, 429, 1147, 18446744073709551615, 0, 4), - (13, 593, 430, 1147, 18446744073709551615, 0, 4), - (13, 592, 431, 1147, 18446744073709551615, 0, 4), - (13, 591, 432, 1147, 18446744073709551615, 0, 4), - (13, 590, 433, 1147, 18446744073709551615, 0, 4), - (13, 589, 434, 1147, 18446744073709551615, 0, 4), - (13, 588, 435, 1147, 18446744073709551615, 0, 4), - (13, 587, 436, 1147, 18446744073709551615, 0, 4), - (13, 586, 437, 1147, 18446744073709551615, 0, 4), - (13, 585, 438, 1147, 18446744073709551615, 0, 4), - (13, 584, 439, 1147, 18446744073709551615, 0, 4), - (13, 583, 440, 1147, 18446744073709551615, 0, 4), - (13, 582, 441, 1147, 18446744073709551615, 0, 4), - (13, 581, 442, 1147, 18446744073709551615, 0, 4), - (13, 580, 443, 1147, 18446744073709551615, 0, 4), - (13, 579, 444, 1147, 18446744073709551615, 0, 4), - (13, 578, 445, 1147, 18446744073709551615, 0, 4), - (13, 577, 446, 1147, 18446744073709551615, 0, 4), - (13, 576, 447, 1147, 18446744073709551615, 0, 4), - (13, 575, 448, 1147, 18446744073709551615, 0, 4), - (13, 574, 449, 1147, 18446744073709551615, 0, 4), - (13, 573, 450, 1147, 18446744073709551615, 0, 4), - (13, 572, 451, 1147, 18446744073709551615, 0, 4), - (13, 571, 452, 1147, 18446744073709551615, 0, 4), - (13, 570, 453, 1147, 18446744073709551615, 0, 4), - (13, 569, 454, 1147, 18446744073709551615, 0, 4), - (13, 568, 455, 1147, 18446744073709551615, 0, 4), - (13, 567, 456, 1147, 18446744073709551615, 0, 4), - (13, 566, 457, 1147, 18446744073709551615, 0, 4), - (13, 565, 458, 1147, 18446744073709551615, 0, 4), - (13, 564, 459, 1147, 18446744073709551615, 0, 4), - (13, 563, 460, 1147, 18446744073709551615, 0, 4), - (13, 562, 461, 1147, 18446744073709551615, 0, 4), - (13, 561, 462, 1147, 18446744073709551615, 0, 4), - (13, 560, 463, 1147, 18446744073709551615, 0, 4), - (13, 559, 464, 1147, 18446744073709551615, 0, 4), - (13, 558, 465, 1147, 18446744073709551615, 0, 4), - (13, 557, 466, 1147, 18446744073709551615, 0, 4), - (13, 556, 467, 1147, 18446744073709551615, 0, 4), - (13, 555, 468, 1147, 18446744073709551615, 0, 4), - (13, 554, 469, 1147, 18446744073709551615, 0, 4), - (13, 553, 470, 1147, 18446744073709551615, 0, 4), - (13, 552, 471, 1147, 18446744073709551615, 0, 4), - (13, 551, 472, 1147, 18446744073709551615, 0, 4), - (13, 550, 473, 1147, 18446744073709551615, 0, 4), - (13, 549, 474, 1147, 18446744073709551615, 0, 4), - (13, 548, 475, 1147, 18446744073709551615, 0, 4), - (13, 547, 476, 1147, 18446744073709551615, 0, 4), - (13, 546, 477, 1147, 18446744073709551615, 0, 4), - (13, 545, 478, 1147, 18446744073709551615, 0, 4), - (13, 544, 479, 1147, 18446744073709551615, 0, 4), - (13, 543, 480, 1147, 18446744073709551615, 0, 4), - (13, 542, 481, 1147, 18446744073709551615, 0, 4), - (13, 541, 482, 1147, 18446744073709551615, 0, 4), - (13, 540, 483, 1147, 18446744073709551615, 0, 4), - (13, 539, 484, 1147, 18446744073709551615, 0, 4), - (13, 538, 485, 1147, 18446744073709551615, 0, 4), - (13, 537, 486, 1147, 18446744073709551615, 0, 4), - (13, 536, 487, 1147, 18446744073709551615, 0, 4), - (13, 535, 488, 1147, 18446744073709551615, 0, 4), - (13, 534, 489, 1147, 18446744073709551615, 0, 4), - (13, 533, 490, 1147, 18446744073709551615, 0, 4), - (13, 532, 491, 1147, 18446744073709551615, 0, 4), - (13, 531, 492, 1147, 18446744073709551615, 0, 4), - (13, 530, 493, 1147, 18446744073709551615, 0, 4), - (13, 529, 494, 1147, 18446744073709551615, 0, 4), - (13, 528, 495, 1147, 18446744073709551615, 0, 4), - (13, 527, 496, 1147, 18446744073709551615, 0, 4), - (13, 526, 497, 1147, 18446744073709551615, 0, 4), - (13, 525, 498, 1147, 18446744073709551615, 0, 4), - (13, 524, 499, 1147, 18446744073709551615, 0, 4), - (13, 523, 500, 1147, 18446744073709551615, 0, 4), - (13, 522, 501, 1147, 18446744073709551615, 0, 4), - (13, 521, 502, 1147, 18446744073709551615, 0, 4), - (13, 520, 503, 1147, 18446744073709551615, 0, 4), - (13, 519, 504, 1147, 18446744073709551615, 0, 4), - (13, 518, 505, 1147, 18446744073709551615, 0, 4), - (13, 517, 506, 1147, 18446744073709551615, 0, 4), - (13, 516, 507, 1147, 18446744073709551615, 0, 4), - (13, 515, 508, 1147, 18446744073709551615, 0, 4), - (13, 514, 509, 1147, 18446744073709551615, 0, 4), - (13, 513, 510, 1147, 18446744073709551615, 0, 4), - (13, 512, 511, 1147, 18446744073709551615, 0, 4), - (13, 1028, 1147, 0, 18446744073709551615, 0, 2), - (13, 512, 511, 1147, 18446744073709551615, 1, 4), - (13, 513, 510, 1147, 18446744073709551615, 1, 4), - (13, 514, 509, 1147, 18446744073709551615, 1, 4), - (13, 515, 508, 1147, 18446744073709551615, 1, 4), - (13, 516, 507, 1147, 18446744073709551615, 1, 4), - (13, 517, 506, 1147, 18446744073709551615, 1, 4), - (13, 518, 505, 1147, 18446744073709551615, 1, 4), - (13, 519, 504, 1147, 18446744073709551615, 1, 4), - (13, 520, 503, 1147, 18446744073709551615, 1, 4), - (13, 521, 502, 1147, 18446744073709551615, 1, 4), - (13, 522, 501, 1147, 18446744073709551615, 1, 4), - (13, 523, 500, 1147, 18446744073709551615, 1, 4), - (13, 524, 499, 1147, 18446744073709551615, 1, 4), - (13, 525, 498, 1147, 18446744073709551615, 1, 4), - (13, 526, 497, 1147, 18446744073709551615, 1, 4), - (13, 527, 496, 1147, 18446744073709551615, 1, 4), - (13, 528, 495, 1147, 18446744073709551615, 1, 4), - (13, 529, 494, 1147, 18446744073709551615, 1, 4), - (13, 530, 493, 1147, 18446744073709551615, 1, 4), - (13, 531, 492, 1147, 18446744073709551615, 1, 4), - (13, 532, 491, 1147, 18446744073709551615, 1, 4), - (13, 533, 490, 1147, 18446744073709551615, 1, 4), - (13, 534, 489, 1147, 18446744073709551615, 1, 4), - (13, 535, 488, 1147, 18446744073709551615, 1, 4), - (13, 536, 487, 1147, 18446744073709551615, 1, 4), - (13, 537, 486, 1147, 18446744073709551615, 1, 4), - (13, 538, 485, 1147, 18446744073709551615, 1, 4), - (13, 539, 484, 1147, 18446744073709551615, 1, 4), - (13, 540, 483, 1147, 18446744073709551615, 1, 4), - (13, 541, 482, 1147, 18446744073709551615, 1, 4), - (13, 542, 481, 1147, 18446744073709551615, 1, 4), - (13, 543, 480, 1147, 18446744073709551615, 1, 4), - (13, 544, 479, 1147, 18446744073709551615, 1, 4), - (13, 545, 478, 1147, 18446744073709551615, 1, 4), - (13, 546, 477, 1147, 18446744073709551615, 1, 4), - (13, 547, 476, 1147, 18446744073709551615, 1, 4), - (13, 548, 475, 1147, 18446744073709551615, 1, 4), - (13, 549, 474, 1147, 18446744073709551615, 1, 4), - (13, 550, 473, 1147, 18446744073709551615, 1, 4), - (13, 551, 472, 1147, 18446744073709551615, 1, 4), - (13, 552, 471, 1147, 18446744073709551615, 1, 4), - (13, 553, 470, 1147, 18446744073709551615, 1, 4), - (13, 554, 469, 1147, 18446744073709551615, 1, 4), - (13, 555, 468, 1147, 18446744073709551615, 1, 4), - (13, 556, 467, 1147, 18446744073709551615, 1, 4), - (13, 557, 466, 1147, 18446744073709551615, 1, 4), - (13, 558, 465, 1147, 18446744073709551615, 1, 4), - (13, 559, 464, 1147, 18446744073709551615, 1, 4), - (13, 560, 463, 1147, 18446744073709551615, 1, 4), - (13, 561, 462, 1147, 18446744073709551615, 1, 4), - (13, 562, 461, 1147, 18446744073709551615, 1, 4), - (13, 563, 460, 1147, 18446744073709551615, 1, 4), - (13, 564, 459, 1147, 18446744073709551615, 1, 4), - (13, 565, 458, 1147, 18446744073709551615, 1, 4), - (13, 566, 457, 1147, 18446744073709551615, 1, 4), - (13, 567, 456, 1147, 18446744073709551615, 1, 4), - (13, 568, 455, 1147, 18446744073709551615, 1, 4), - (13, 569, 454, 1147, 18446744073709551615, 1, 4), - (13, 570, 453, 1147, 18446744073709551615, 1, 4), - (13, 571, 452, 1147, 18446744073709551615, 1, 4), - (13, 572, 451, 1147, 18446744073709551615, 1, 4), - (13, 573, 450, 1147, 18446744073709551615, 1, 4), - (13, 574, 449, 1147, 18446744073709551615, 1, 4), - (13, 575, 448, 1147, 18446744073709551615, 1, 4), - (13, 576, 447, 1147, 18446744073709551615, 1, 4), - (13, 577, 446, 1147, 18446744073709551615, 1, 4), - (13, 578, 445, 1147, 18446744073709551615, 1, 4), - (13, 579, 444, 1147, 18446744073709551615, 1, 4), - (13, 580, 443, 1147, 18446744073709551615, 1, 4), - (13, 581, 442, 1147, 18446744073709551615, 1, 4), - (13, 582, 441, 1147, 18446744073709551615, 1, 4), - (13, 583, 440, 1147, 18446744073709551615, 1, 4), - (13, 584, 439, 1147, 18446744073709551615, 1, 4), - (13, 585, 438, 1147, 18446744073709551615, 1, 4), - (13, 586, 437, 1147, 18446744073709551615, 1, 4), - (13, 587, 436, 1147, 18446744073709551615, 1, 4), - (13, 588, 435, 1147, 18446744073709551615, 1, 4), - (13, 589, 434, 1147, 18446744073709551615, 1, 4), - (13, 590, 433, 1147, 18446744073709551615, 1, 4), - (13, 591, 432, 1147, 18446744073709551615, 1, 4), - (13, 592, 431, 1147, 18446744073709551615, 1, 4), - (13, 593, 430, 1147, 18446744073709551615, 1, 4), - (13, 594, 429, 1147, 18446744073709551615, 1, 4), - (13, 595, 428, 1147, 18446744073709551615, 1, 4), - (13, 596, 427, 1147, 18446744073709551615, 1, 4), - (13, 597, 426, 1147, 18446744073709551615, 1, 4), - (13, 598, 425, 1147, 18446744073709551615, 1, 4), - (13, 599, 424, 1147, 18446744073709551615, 1, 4), - (13, 600, 423, 1147, 18446744073709551615, 1, 4), - (13, 601, 422, 1147, 18446744073709551615, 1, 4), - (13, 602, 421, 1147, 18446744073709551615, 1, 4), - (13, 603, 420, 1147, 18446744073709551615, 1, 4), - (13, 604, 419, 1147, 18446744073709551615, 1, 4), - (13, 605, 418, 1147, 18446744073709551615, 1, 4), - (13, 733, 417, 1147, 18446744073709551615, 1, 4), - (13, 732, 416, 1147, 18446744073709551615, 1, 4), - (13, 606, 415, 1147, 18446744073709551615, 1, 4), - (13, 607, 414, 1147, 18446744073709551615, 1, 4), - (13, 608, 413, 1147, 18446744073709551615, 1, 4), - (13, 609, 412, 1147, 18446744073709551615, 1, 4), - (13, 685, 411, 1147, 18446744073709551615, 1, 4), - (13, 684, 410, 1147, 18446744073709551615, 1, 4), - (13, 1093, 409, 1147, 18446744073709551615, 1, 4), - (13, 128, 408, 1147, 18446744073709551615, 1, 2), - (13, 731, 407, 1147, 18446744073709551615, 1, 2), - (13, 730, 406, 1147, 18446744073709551615, 1, 2), - (13, 683, 405, 1147, 18446744073709551615, 1, 2), - (13, 682, 404, 1147, 18446744073709551615, 1, 2), - (13, 681, 403, 1147, 18446744073709551615, 1, 2), - (13, 680, 402, 1147, 18446744073709551615, 1, 2), - (13, 679, 401, 1147, 18446744073709551615, 1, 2), - (13, 678, 400, 1147, 18446744073709551615, 1, 2), - (13, 677, 399, 1147, 18446744073709551615, 1, 2), - (13, 676, 398, 1147, 18446744073709551615, 1, 2), - (13, 675, 397, 1147, 18446744073709551615, 1, 2), - (13, 674, 396, 1147, 18446744073709551615, 1, 2), - (13, 673, 395, 1147, 18446744073709551615, 1, 2), - (13, 672, 394, 1147, 18446744073709551615, 1, 2), - (13, 671, 393, 1147, 18446744073709551615, 1, 2), - (13, 670, 392, 1147, 18446744073709551615, 1, 2), - (14, 1028, 391, 669, 18446744073709551615, 0, 1), - (14, 1028, 390, 668, 18446744073709551615, 0, 4), - (14, 1028, 388, 666, 18446744073709551615, 0, 1), - (14, 1028, 385, 663, 18446744073709551615, 0, 13), - (14, 1028, 381, 707, 18446744073709551615, 0, 30), - (14, 1028, 376, 702, 18446744073709551615, 0, 1), - (14, 1028, 370, 696, 18446744073709551615, 0, 2), - (14, 1028, 363, 689, 18446744073709551615, 0, 8), - (14, 1028, 355, 727, 18446744073709551615, 0, 19), - (14, 1028, 346, 718, 18446744073709551615, 0, 1), - (14, 1028, 336, 708, 18446744073709551615, 0, 8), - (14, 1028, 325, 624, 18446744073709551615, 0, 2), - (14, 1028, 313, 636, 18446744073709551615, 0, 17), - (14, 1028, 300, 649, 18446744073709551615, 0, 1), - (14, 1028, 286, 132, 18446744073709551615, 0, 1), - (14, 1028, 271, 752, 18446744073709551615, 0, 1), - (13, 0, 256, 143, 18446744073709551615, 0, 1), - (13, 257, 143, 886, 18446744073709551615, 0, 1), - (13, 258, 886, 1097, 18446744073709551615, 0, 1), - (13, 259, 1097, 1149, 18446744073709551615, 0, 1), - (13, 260, 1149, 148, 18446744073709551615, 0, 1), - (13, 261, 148, 916, 18446744073709551615, 0, 1), - (13, 262, 916, 1139, 18446744073709551615, 0, 2), - (13, 263, 1139, 1151, 18446744073709551615, 0, 2), - (13, 264, 1151, 1132, 18446744073709551615, 0, 3), - (13, 265, 1132, 12, 18446744073709551615, 0, 5), - (13, 266, 12, 1141, 18446744073709551615, 0, 8), - (13, 267, 1141, 10, 18446744073709551615, 0, 3), - (13, 268, 10, 793, 18446744073709551615, 0, 3), - (13, 269, 793, 9, 18446744073709551615, 0, 3), - (13, 270, 9, 1147, 18446744073709551615, 0, 2), - (13, 271, 1147, 1025, 18446744073709551615, 0, 2), - (13, 272, 1025, 1150, 18446744073709551615, 0, 1), - (13, 273, 1150, 1132, 18446744073709551615, 0, 1), - (13, 274, 1132, 12, 18446744073709551615, 0, 4), - (13, 275, 12, 1141, 18446744073709551615, 0, 4), - (13, 276, 1141, 10, 18446744073709551615, 0, 4), - (13, 277, 10, 793, 18446744073709551615, 0, 3), - (13, 278, 793, 9, 18446744073709551615, 0, 2), - (13, 279, 9, 1147, 18446744073709551615, 0, 4), - (13, 280, 1147, 1025, 18446744073709551615, 0, 2), - (13, 281, 1025, 1151, 18446744073709551615, 0, 1), - (13, 282, 1151, 12, 18446744073709551615, 0, 1), - (13, 283, 12, 1141, 18446744073709551615, 0, 2), - (13, 284, 1141, 10, 18446744073709551615, 0, 2), - (13, 285, 10, 793, 18446744073709551615, 0, 6), - (13, 286, 793, 9, 18446744073709551615, 0, 2), - (13, 287, 9, 1147, 18446744073709551615, 0, 2), - (13, 288, 1147, 1025, 18446744073709551615, 0, 2), - (13, 289, 1025, 1132, 18446744073709551615, 0, 1), - (13, 290, 1132, 1141, 18446744073709551615, 0, 3), - (13, 291, 1141, 10, 18446744073709551615, 0, 2), - (13, 292, 10, 793, 18446744073709551615, 0, 8), - (13, 293, 793, 9, 18446744073709551615, 0, 2), - (13, 294, 9, 1147, 18446744073709551615, 0, 2), - (13, 295, 1147, 1025, 18446744073709551615, 0, 2), - (13, 296, 1025, 12, 18446744073709551615, 0, 1), - (13, 297, 12, 10, 18446744073709551615, 0, 1), - (13, 298, 10, 793, 18446744073709551615, 0, 8), - (13, 299, 793, 9, 18446744073709551615, 0, 2), - (13, 300, 9, 1147, 18446744073709551615, 0, 2), - (13, 301, 1147, 1025, 18446744073709551615, 0, 2), - (13, 302, 1025, 1141, 18446744073709551615, 0, 1), - (13, 303, 1141, 793, 18446744073709551615, 0, 1), - (13, 304, 793, 9, 18446744073709551615, 0, 2), - (13, 305, 9, 1147, 18446744073709551615, 0, 2), - (13, 306, 1147, 1025, 18446744073709551615, 0, 2), - (13, 307, 1025, 10, 18446744073709551615, 0, 1), - (14, 0, 307, 1025, 18446744073709551615, 0, 1), - (14, 0, 302, 1025, 18446744073709551615, 0, 1), - (14, 0, 296, 1025, 18446744073709551615, 0, 1), - (14, 0, 289, 1025, 18446744073709551615, 0, 1), - (14, 0, 281, 1025, 18446744073709551615, 0, 1), - (14, 0, 272, 1025, 18446744073709551615, 0, 1), - (13, 0, 256, 886, 18446744073709551615, 0, 2), - (13, 257, 886, 1097, 18446744073709551615, 0, 1), - (13, 258, 1097, 1149, 18446744073709551615, 0, 1), - (13, 259, 1149, 148, 18446744073709551615, 0, 1), - (13, 275, 1153, 1025, 18446744073709551615, 0, 1), - (13, 277, 1153, 1025, 18446744073709551615, 0, 1), - (13, 280, 1153, 1147, 18446744073709551615, 0, 1), - (13, 281, 1153, 1025, 18446744073709551615, 0, 1), - (13, 282, 1153, 1147, 18446744073709551615, 0, 1), - (13, 283, 1153, 1025, 18446744073709551615, 0, 1), - (13, 284, 1153, 1147, 18446744073709551615, 0, 1), - (13, 285, 1153, 1025, 18446744073709551615, 0, 1), - (13, 286, 1153, 1147, 18446744073709551615, 0, 1), - (13, 287, 1153, 1025, 18446744073709551615, 0, 1), - (13, 300, 1153, 1147, 18446744073709551615, 0, 1), - (13, 301, 1153, 1025, 18446744073709551615, 0, 1), - (13, 302, 1153, 1147, 18446744073709551615, 0, 1), - (13, 303, 1153, 1025, 18446744073709551615, 0, 1), - (13, 304, 1153, 1147, 18446744073709551615, 0, 1), - (13, 305, 1153, 1025, 18446744073709551615, 0, 1), - (13, 306, 1153, 1147, 18446744073709551615, 0, 1), - (13, 307, 1153, 1025, 18446744073709551615, 0, 1), - (13, 1, 775, 143, 18446744073709551615, 0, 1), - (13, 2, 774, 886, 18446744073709551615, 0, 1), - (13, 3, 773, 1097, 18446744073709551615, 0, 2), - (13, 4, 772, 1149, 18446744073709551615, 1, 4), - (13, 5, 771, 148, 18446744073709551615, 0, 1), - (13, 6, 770, 916, 18446744073709551615, 0, 2), - (13, 7, 769, 1139, 18446744073709551615, 0, 6), - (13, 1028, 768, 8, 18446744073709551615, 1, 262), - (13, 1028, 769, 7, 18446744073709551615, 1, 262), - (13, 1028, 770, 6, 18446744073709551615, 1, 262), - (13, 1028, 771, 5, 18446744073709551615, 0, 261), - (13, 1028, 772, 4, 18446744073709551615, 260, 521), - (13, 1028, 773, 3, 18446744073709551615, 0, 261), - (13, 1028, 774, 2, 18446744073709551615, 0, 261), - (13, 1028, 775, 1, 18446744073709551615, 0, 261), - (13, 1024, 773, 3, 18446744073709551615, 0, 259), - (13, 1024, 772, 4, 18446744073709551615, 262, 521), - (13, 1024, 771, 5, 18446744073709551615, 0, 259), - (13, 1024, 770, 6, 18446744073709551615, 1, 260), - (13, 1024, 769, 7, 18446744073709551615, 1, 260), - (13, 1024, 768, 8, 18446744073709551615, 1, 260), - (13, 3, 773, 916, 18446744073709551615, 0, 2), - (13, 4, 772, 1139, 18446744073709551615, 0, 3), - (13, 5, 771, 1150, 18446744073709551615, 0, 4), - (13, 6, 770, 793, 18446744073709551615, 0, 1), - (13, 7, 769, 1151, 18446744073709551615, 0, 2), - (13, 8, 768, 1132, 18446744073709551615, 0, 8), - (13, 776, 7, 6, 18446744073709551615, 1, 261), - (13, 776, 6, 5, 18446744073709551615, 1, 261), - (13, 776, 5, 4, 18446744073709551615, 1, 261), - (13, 776, 4, 3, 18446744073709551615, 1, 261), - (13, 272, 1147, 793, 18446744073709551615, 0, 1), - (13, 273, 793, 1132, 18446744073709551615, 0, 1), - (13, 277, 10, 9, 18446744073709551615, 0, 2), - (13, 278, 9, 143, 18446744073709551615, 0, 2), - (13, 279, 143, 1147, 18446744073709551615, 0, 2), - (13, 280, 1147, 1151, 18446744073709551615, 0, 1), - (13, 281, 1151, 12, 18446744073709551615, 0, 1), - (13, 283, 1141, 10, 18446744073709551615, 0, 2), - (13, 284, 10, 9, 18446744073709551615, 0, 2), - (13, 285, 9, 143, 18446744073709551615, 0, 2), - (13, 286, 143, 1147, 18446744073709551615, 0, 2), - (13, 287, 1147, 1132, 18446744073709551615, 0, 1), - (13, 294, 12, 10, 18446744073709551615, 0, 1), - (13, 295, 10, 9, 18446744073709551615, 0, 2), - (13, 297, 143, 1147, 18446744073709551615, 0, 2), - (13, 298, 1147, 1141, 18446744073709551615, 0, 1), - (13, 301, 143, 1147, 18446744073709551615, 0, 2), - (13, 302, 1147, 10, 18446744073709551615, 0, 1), - (13, 303, 10, 143, 18446744073709551615, 0, 1), - (13, 304, 143, 1147, 18446744073709551615, 0, 2), - (13, 305, 1147, 9, 18446744073709551615, 0, 1), - (13, 306, 9, 1147, 18446744073709551615, 0, 1), - (13, 307, 1147, 143, 18446744073709551615, 0, 1), - (13, 0, 256, 116, 18446744073709551615, 0, 1), - (13, 257, 116, 1097, 18446744073709551615, 0, 1), - (13, 258, 1097, 148, 18446744073709551615, 0, 1), - (13, 259, 148, 1149, 18446744073709551615, 0, 1), - (13, 275, 1153, 1147, 18446744073709551615, 0, 1), - (13, 277, 1153, 1147, 18446744073709551615, 0, 1), - (13, 280, 1153, 1025, 18446744073709551615, 0, 1), - (13, 282, 1153, 1025, 18446744073709551615, 0, 1), - (13, 283, 1153, 1147, 18446744073709551615, 0, 1), - (13, 284, 1153, 1025, 18446744073709551615, 0, 1), - (13, 285, 1153, 1147, 18446744073709551615, 0, 1), - (13, 286, 1153, 1025, 18446744073709551615, 0, 1), - (13, 287, 1153, 1147, 18446744073709551615, 0, 1), - (13, 297, 1153, 1147, 18446744073709551615, 0, 1), - (13, 299, 1153, 1147, 18446744073709551615, 0, 1), - (13, 300, 1153, 1025, 18446744073709551615, 0, 1), - (13, 301, 1153, 1147, 18446744073709551615, 0, 1), - (13, 303, 1153, 1147, 18446744073709551615, 0, 1), - (13, 304, 1153, 1025, 18446744073709551615, 0, 1), - (13, 305, 1153, 1147, 18446744073709551615, 0, 1), - (13, 306, 1153, 1025, 18446744073709551615, 0, 1), - (13, 4, 772, 148, 18446744073709551615, 0, 1), - (13, 5, 771, 1149, 18446744073709551615, 0, 2), - (13, 6, 770, 916, 18446744073709551615, 1, 2), - (13, 7, 769, 1139, 18446744073709551615, 1, 6), - (13, 1028, 768, 8, 18446744073709551615, 2, 262), - (13, 1028, 769, 7, 18446744073709551615, 2, 262), - (13, 1028, 770, 6, 18446744073709551615, 2, 262), - (13, 1028, 771, 5, 18446744073709551615, 1, 261), - (13, 1028, 772, 4, 18446744073709551615, 261, 521), - (13, 1024, 772, 4, 18446744073709551615, 263, 521), - (13, 1024, 771, 5, 18446744073709551615, 1, 259), - (13, 1024, 770, 6, 18446744073709551615, 2, 260), - (13, 1024, 769, 7, 18446744073709551615, 2, 260), - (13, 1024, 768, 8, 18446744073709551615, 2, 260), - (13, 4, 772, 1139, 18446744073709551615, 1, 3), - (13, 5, 771, 1150, 18446744073709551615, 1, 4), - (13, 6, 770, 10, 18446744073709551615, 0, 1), - (13, 7, 769, 793, 18446744073709551615, 0, 1), - (13, 8, 768, 1151, 18446744073709551615, 0, 3), - (13, 776, 7, 6, 18446744073709551615, 2, 261), - (13, 776, 6, 5, 18446744073709551615, 2, 261), - (13, 776, 5, 4, 18446744073709551615, 2, 261), - (13, 275, 1088, 793, 18446744073709551615, 0, 1), - (13, 276, 793, 1132, 18446744073709551615, 0, 1), - (13, 277, 1132, 12, 18446744073709551615, 0, 2), - (13, 279, 1141, 9, 18446744073709551615, 0, 4), - (13, 280, 9, 143, 18446744073709551615, 0, 4), - (13, 282, 1147, 1088, 18446744073709551615, 0, 4), - (13, 283, 1088, 1151, 18446744073709551615, 0, 1), - (13, 284, 1151, 12, 18446744073709551615, 0, 2), - (13, 285, 12, 1141, 18446744073709551615, 0, 6), - (13, 286, 1141, 9, 18446744073709551615, 0, 5), - (13, 287, 9, 143, 18446744073709551615, 0, 4), - (13, 296, 1088, 12, 18446744073709551615, 0, 2), - (13, 299, 143, 1147, 18446744073709551615, 0, 4), - (13, 300, 1147, 1088, 18446744073709551615, 0, 8), - (13, 303, 143, 1147, 18446744073709551615, 0, 4), - (13, 304, 1147, 1088, 18446744073709551615, 0, 8), - (13, 305, 1088, 9, 18446744073709551615, 0, 2), - (13, 306, 9, 143, 18446744073709551615, 0, 2), - (13, 307, 143, 1147, 18446744073709551615, 0, 2), - (13, 0, 256, 888, 18446744073709551615, 0, 1), - (13, 257, 888, 14, 18446744073709551615, 0, 1), - (13, 258, 14, 116, 18446744073709551615, 0, 1), - (13, 259, 116, 1097, 18446744073709551615, 0, 2), - (13, 279, 1025, 1147, 18446744073709551615, 0, 1), - (13, 282, 1025, 1088, 18446744073709551615, 0, 2), - (13, 283, 1025, 1147, 18446744073709551615, 0, 1), - (13, 284, 1025, 1088, 18446744073709551615, 0, 2), - (13, 285, 1025, 1147, 18446744073709551615, 0, 1), - (13, 286, 1025, 1088, 18446744073709551615, 0, 2), - (13, 287, 1025, 1147, 18446744073709551615, 0, 3), - (13, 298, 1025, 1088, 18446744073709551615, 0, 2), - (13, 304, 1025, 1088, 18446744073709551615, 0, 2), - (13, 305, 1025, 1147, 18446744073709551615, 0, 1), - (13, 306, 1025, 1088, 18446744073709551615, 0, 2), - (13, 307, 1025, 1147, 18446744073709551615, 0, 1), - (13, 6, 770, 148, 18446744073709551615, 0, 2), - (13, 7, 769, 1149, 18446744073709551615, 0, 2), - (13, 1028, 768, 8, 18446744073709551615, 3, 262), - (13, 1028, 769, 7, 18446744073709551615, 3, 262), - (13, 1028, 770, 6, 18446744073709551615, 3, 262), - (13, 1024, 770, 6, 18446744073709551615, 3, 260), - (13, 1024, 769, 7, 18446744073709551615, 3, 260), - (13, 1024, 768, 8, 18446744073709551615, 3, 260), - (13, 5, 771, 916, 18446744073709551615, 0, 4), - (13, 6, 770, 1132, 18446744073709551615, 0, 8), - (13, 7, 769, 1139, 18446744073709551615, 2, 6), - (13, 8, 768, 1150, 18446744073709551615, 0, 6), - (13, 776, 7, 6, 18446744073709551615, 3, 261), - (13, 776, 6, 5, 18446744073709551615, 3, 261), - (13, 277, 1151, 12, 18446744073709551615, 0, 2), - (13, 279, 1141, 9, 18446744073709551615, 2, 4), - (13, 280, 9, 143, 18446744073709551615, 2, 4), - (13, 282, 1147, 1088, 18446744073709551615, 2, 4), - (13, 283, 1088, 793, 18446744073709551615, 0, 1), - (13, 284, 793, 12, 18446744073709551615, 0, 1), - (13, 285, 12, 1141, 18446744073709551615, 2, 6), - (13, 286, 1141, 9, 18446744073709551615, 2, 5), - (13, 287, 9, 143, 18446744073709551615, 2, 4), - (13, 297, 12, 9, 18446744073709551615, 1, 2), - (13, 299, 143, 1147, 18446744073709551615, 2, 4), - (13, 301, 1088, 1141, 18446744073709551615, 1, 2), - (13, 302, 1141, 143, 18446744073709551615, 1, 2), - (13, 303, 143, 1147, 18446744073709551615, 2, 4), - (13, 304, 1147, 1088, 18446744073709551615, 2, 8), - (13, 306, 9, 143, 18446744073709551615, 1, 2), - (13, 307, 143, 1147, 18446744073709551615, 1, 2), - (13, 0, 256, 777, 18446744073709551615, 0, 1), - (13, 257, 777, 11, 18446744073709551615, 0, 1), - (13, 258, 11, 116, 18446744073709551615, 0, 1), - (13, 259, 116, 1097, 18446744073709551615, 1, 2), - (13, 278, 1025, 1088, 18446744073709551615, 1, 2), - (13, 279, 1025, 886, 18446744073709551615, 0, 1), - (13, 282, 1025, 1088, 18446744073709551615, 1, 2), - (13, 283, 1025, 886, 18446744073709551615, 0, 1), - (13, 285, 1025, 886, 18446744073709551615, 0, 1), - (13, 286, 1025, 1088, 18446744073709551615, 1, 2), - (13, 287, 1025, 886, 18446744073709551615, 0, 1), - (13, 304, 1025, 1088, 18446744073709551615, 1, 2), - (13, 305, 1025, 886, 18446744073709551615, 0, 1), - (13, 306, 1025, 1088, 18446744073709551615, 1, 2), - (13, 307, 1025, 886, 18446744073709551615, 0, 1), - (13, 7, 769, 1149, 18446744073709551615, 1, 2), - (13, 8, 768, 916, 18446744073709551615, 0, 1), - (13, 1028, 888, 14, 18446744073709551615, 0, 258), - (13, 1028, 768, 8, 18446744073709551615, 4, 262), - (13, 1028, 769, 7, 18446744073709551615, 4, 262), - (13, 1024, 769, 7, 18446744073709551615, 4, 260), - (13, 1024, 768, 8, 18446744073709551615, 4, 260), - (13, 1024, 888, 14, 18446744073709551615, 0, 256), - (13, 6, 770, 1151, 18446744073709551615, 0, 2), - (13, 7, 769, 1132, 18446744073709551615, 0, 8), - (13, 8, 768, 1139, 18446744073709551615, 0, 4), - (13, 14, 888, 1150, 18446744073709551615, 0, 2), - (13, 776, 8, 7, 18446744073709551615, 0, 257), - (13, 776, 7, 6, 18446744073709551615, 4, 261), - (13, 278, 1147, 886, 18446744073709551615, 0, 6), - (13, 279, 886, 1088, 18446744073709551615, 0, 6), - (13, 281, 889, 12, 18446744073709551615, 0, 1), - (13, 283, 9, 143, 18446744073709551615, 0, 2), - (13, 284, 143, 1147, 18446744073709551615, 0, 2), - (13, 285, 1147, 886, 18446744073709551615, 0, 9), - (13, 286, 886, 1088, 18446744073709551615, 0, 12), - (13, 287, 1088, 889, 18446744073709551615, 0, 2), - (13, 298, 1088, 889, 18446744073709551615, 0, 2), - (13, 299, 889, 143, 18446744073709551615, 0, 1), - (13, 301, 886, 1088, 18446744073709551615, 0, 16), - (13, 303, 889, 1147, 18446744073709551615, 0, 1), - (13, 304, 1147, 1088, 18446744073709551615, 4, 8), - (13, 306, 889, 886, 18446744073709551615, 0, 4), - (13, 307, 886, 1088, 18446744073709551615, 0, 14), - (13, 0, 256, 1087, 18446744073709551615, 0, 1), - (13, 257, 1087, 1149, 18446744073709551615, 0, 1), - (13, 258, 1149, 1151, 18446744073709551615, 0, 1), - (13, 259, 1151, 916, 18446744073709551615, 0, 2), - (13, 278, 1025, 889, 18446744073709551615, 0, 2), - (13, 279, 1025, 1088, 18446744073709551615, 0, 1), - (13, 281, 1025, 1088, 18446744073709551615, 0, 1), - (13, 283, 1025, 1088, 18446744073709551615, 0, 1), - (13, 284, 1025, 889, 18446744073709551615, 0, 2), - (13, 285, 1025, 1088, 18446744073709551615, 0, 1), - (13, 286, 1025, 889, 18446744073709551615, 0, 2), - (13, 287, 1025, 1088, 18446744073709551615, 0, 1), - (13, 302, 1025, 889, 18446744073709551615, 0, 2), - (13, 306, 1025, 889, 18446744073709551615, 0, 2), - (13, 307, 1025, 1088, 18446744073709551615, 0, 1), - (13, 14, 888, 143, 18446744073709551615, 1, 7), - (13, 116, 777, 10, 18446744073709551615, 0, 3), - (13, 1028, 11, 1097, 18446744073709551615, 0, 257), - (13, 1028, 777, 116, 18446744073709551615, 0, 257), - (13, 1028, 888, 14, 18446744073709551615, 1, 258), - (13, 1024, 768, 8, 18446744073709551615, 5, 260), - (13, 1024, 777, 116, 18446744073709551615, 0, 255), - (13, 1024, 11, 1097, 18446744073709551615, 0, 255), - (13, 7, 769, 10, 18446744073709551615, 0, 1), - (13, 8, 768, 793, 18446744073709551615, 0, 1), - (13, 14, 888, 12, 18446744073709551615, 0, 11), - (13, 116, 777, 1141, 18446744073709551615, 0, 10), - (13, 1097, 11, 9, 18446744073709551615, 0, 2), - (13, 776, 116, 14, 18446744073709551615, 0, 256), - (13, 776, 14, 8, 18446744073709551615, 0, 256), - (13, 776, 8, 7, 18446744073709551615, 1, 257), - (13, 280, 1147, 886, 18446744073709551615, 0, 6), - (13, 282, 143, 793, 18446744073709551615, 0, 1), - (13, 283, 793, 12, 18446744073709551615, 0, 2), - (13, 284, 12, 1141, 18446744073709551615, 0, 3), - (13, 286, 9, 1147, 18446744073709551615, 0, 2), - (13, 287, 1147, 886, 18446744073709551615, 0, 7), - (13, 302, 1147, 886, 18446744073709551615, 0, 8), - (13, 305, 1147, 886, 18446744073709551615, 0, 5), - (13, 306, 886, 9, 18446744073709551615, 0, 1), - (13, 307, 9, 1147, 18446744073709551615, 0, 1), - (13, 0, 256, 1145, 18446744073709551615, 0, 1), - (13, 257, 1145, 13, 18446744073709551615, 0, 1), - (13, 258, 13, 1087, 18446744073709551615, 0, 1), - (13, 259, 1087, 1149, 18446744073709551615, 0, 1), - (13, 279, 1025, 915, 18446744073709551615, 0, 1), - (13, 280, 1025, 889, 18446744073709551615, 1, 2), - (13, 281, 1025, 915, 18446744073709551615, 0, 1), - (13, 282, 1025, 889, 18446744073709551615, 1, 2), - (13, 284, 1025, 889, 18446744073709551615, 1, 2), - (13, 285, 1025, 915, 18446744073709551615, 0, 1), - (13, 286, 1025, 889, 18446744073709551615, 1, 2), - (13, 287, 1025, 915, 18446744073709551615, 0, 1), - (13, 302, 1025, 889, 18446744073709551615, 1, 2), - (13, 303, 1025, 915, 18446744073709551615, 0, 1), - (13, 304, 1025, 889, 18446744073709551615, 1, 2), - (13, 306, 1025, 889, 18446744073709551615, 1, 2), - (13, 307, 1025, 915, 18446744073709551615, 0, 1), - (13, 14, 888, 12, 18446744073709551615, 1, 11), - (13, 116, 777, 1139, 18446744073709551615, 0, 2), - (13, 1028, 11, 1097, 18446744073709551615, 1, 257), - (13, 1028, 777, 116, 18446744073709551615, 1, 257), - (13, 1028, 888, 14, 18446744073709551615, 2, 258), - (13, 1024, 888, 14, 18446744073709551615, 2, 256), - (13, 1024, 777, 116, 18446744073709551615, 1, 255), - (13, 1024, 11, 1097, 18446744073709551615, 1, 255), - (13, 8, 768, 1150, 18446744073709551615, 2, 6), - (13, 14, 888, 143, 18446744073709551615, 2, 7), - (13, 116, 777, 10, 18446744073709551615, 1, 3), - (13, 1097, 11, 793, 18446744073709551615, 0, 2), - (13, 776, 116, 14, 18446744073709551615, 1, 256), - (13, 776, 14, 8, 18446744073709551615, 1, 256), - (13, 280, 1088, 915, 18446744073709551615, 0, 4), - (13, 281, 915, 889, 18446744073709551615, 0, 4), - (13, 282, 889, 148, 18446744073709551615, 0, 4), - (13, 283, 148, 1141, 18446744073709551615, 0, 1), - (13, 284, 1141, 1147, 18446744073709551615, 0, 2), - (13, 287, 1088, 915, 18446744073709551615, 0, 10), - (13, 301, 148, 886, 18446744073709551615, 0, 2), - (13, 303, 915, 889, 18446744073709551615, 0, 30), - (13, 304, 889, 148, 18446744073709551615, 0, 4), - (13, 306, 1088, 915, 18446744073709551615, 0, 20), - (13, 0, 256, 923, 18446744073709551615, 0, 2), - (13, 257, 923, 1086, 18446744073709551615, 0, 1), - (13, 258, 1086, 1151, 18446744073709551615, 0, 1), - (13, 259, 1151, 916, 18446744073709551615, 1, 2), - (13, 281, 1025, 889, 18446744073709551615, 0, 1), - (13, 282, 1025, 148, 18446744073709551615, 0, 2), - (13, 284, 1025, 148, 18446744073709551615, 0, 2), - (13, 286, 1025, 148, 18446744073709551615, 0, 2), - (13, 287, 1025, 889, 18446744073709551615, 0, 1), - (13, 302, 1025, 148, 18446744073709551615, 0, 2), - (13, 304, 1025, 148, 18446744073709551615, 0, 2), - (13, 305, 1025, 889, 18446744073709551615, 0, 1), - (13, 306, 1025, 148, 18446744073709551615, 0, 2), - (13, 14, 888, 9, 18446744073709551615, 0, 1), - (13, 116, 777, 1150, 18446744073709551615, 0, 2), - (13, 1097, 11, 143, 18446744073709551615, 0, 5), - (13, 1087, 1145, 10, 18446744073709551615, 0, 2), - (13, 1028, 13, 1149, 18446744073709551615, 0, 255), - (13, 1028, 1145, 1087, 18446744073709551615, 0, 255), - (13, 1028, 11, 1097, 18446744073709551615, 2, 257), - (13, 1028, 777, 116, 18446744073709551615, 2, 257), - (13, 1028, 888, 14, 18446744073709551615, 3, 258), - (13, 1024, 777, 116, 18446744073709551615, 2, 255), - (13, 1024, 1145, 1087, 18446744073709551615, 0, 253), - (13, 1024, 13, 1149, 18446744073709551615, 0, 253), - (13, 14, 888, 10, 18446744073709551615, 0, 1), - (13, 116, 777, 793, 18446744073709551615, 0, 1), - (13, 1097, 11, 1141, 18446744073709551615, 0, 14), - (13, 1087, 1145, 1147, 18446744073709551615, 0, 2), - (13, 1149, 13, 886, 18446744073709551615, 0, 2), - (13, 776, 1087, 1097, 18446744073709551615, 0, 254), - (13, 776, 1097, 116, 18446744073709551615, 0, 254), - (13, 776, 116, 14, 18446744073709551615, 2, 256), - (13, 279, 886, 1088, 18446744073709551615, 4, 6), - (13, 280, 1088, 915, 18446744073709551615, 2, 4), - (13, 281, 915, 889, 18446744073709551615, 2, 4), - (13, 282, 889, 148, 18446744073709551615, 2, 4), - (13, 285, 1147, 886, 18446744073709551615, 4, 9), - (13, 286, 886, 1088, 18446744073709551615, 4, 12), - (13, 287, 1088, 915, 18446744073709551615, 2, 10), - (13, 301, 148, 886, 18446744073709551615, 1, 2), - (13, 302, 886, 915, 18446744073709551615, 1, 5), - (13, 307, 915, 889, 18446744073709551615, 1, 18), - (13, 0, 256, 150, 18446744073709551615, 0, 1), - (13, 257, 150, 1086, 18446744073709551615, 0, 1), - (13, 258, 1086, 916, 18446744073709551615, 0, 1), - (13, 259, 916, 1151, 18446744073709551615, 0, 1), - (13, 281, 1025, 146, 18446744073709551615, 0, 1), - (13, 282, 1025, 148, 18446744073709551615, 1, 2), - (13, 285, 1025, 146, 18446744073709551615, 0, 1), - (13, 287, 1025, 146, 18446744073709551615, 0, 1), - (13, 303, 1025, 146, 18446744073709551615, 0, 1), - (13, 305, 1025, 146, 18446744073709551615, 0, 1), - (13, 116, 777, 9, 18446744073709551615, 0, 2), - (13, 1097, 11, 1150, 18446744073709551615, 0, 3), - (13, 1087, 1145, 143, 18446744073709551615, 0, 6), - (13, 1028, 13, 1149, 18446744073709551615, 1, 255), - (13, 1028, 1145, 1087, 18446744073709551615, 1, 255), - (13, 1028, 11, 1097, 18446744073709551615, 3, 257), - (13, 1028, 777, 116, 18446744073709551615, 3, 257), - (13, 1024, 11, 1097, 18446744073709551615, 3, 255), - (13, 116, 777, 10, 18446744073709551615, 2, 3), - (13, 1097, 11, 793, 18446744073709551615, 1, 2), - (13, 1087, 1145, 1147, 18446744073709551615, 1, 2), - (13, 1149, 13, 886, 18446744073709551615, 1, 2), - (13, 776, 1087, 1097, 18446744073709551615, 1, 254), - (13, 776, 1097, 116, 18446744073709551615, 1, 254), - (13, 281, 1147, 886, 18446744073709551615, 0, 7), - (13, 282, 886, 1088, 18446744073709551615, 0, 10), - (13, 285, 143, 793, 18446744073709551615, 0, 1), - (13, 287, 1025, 1147, 18446744073709551615, 1, 3), - (13, 302, 915, 1025, 18446744073709551615, 0, 1), - (13, 303, 1025, 886, 18446744073709551615, 1, 2), - (13, 306, 915, 1147, 18446744073709551615, 0, 1), - (13, 307, 1147, 886, 18446744073709551615, 0, 4), - (13, 257, 1151, 1132, 18446744073709551615, 0, 1), - (13, 258, 1132, 12, 18446744073709551615, 0, 1), - (13, 259, 12, 916, 18446744073709551615, 0, 1), - (13, 283, 1141, 1086, 18446744073709551615, 0, 1), - (13, 284, 1086, 1139, 18446744073709551615, 0, 1), - (13, 285, 1139, 1141, 18446744073709551615, 0, 2), - (13, 287, 9, 12, 18446744073709551615, 0, 1), - (13, 305, 10, 793, 18446744073709551615, 0, 5), - (13, 306, 793, 1025, 18446744073709551615, 0, 2), - (13, 307, 1025, 143, 18446744073709551615, 0, 1), - (13, 308, 143, 10, 18446744073709551615, 0, 1), - (13, 305, 10, 793, 18446744073709551615, 1, 5), - (13, 306, 793, 1025, 18446744073709551615, 1, 2), - (13, 284, 12, 143, 18446744073709551615, 0, 1), - (13, 285, 143, 1150, 18446744073709551615, 0, 1), - (13, 286, 1150, 9, 18446744073709551615, 0, 4), - (13, 256, 12, 1132, 18446744073709551615, 0, 1), - (13, 257, 143, 1141, 18446744073709551615, 0, 3), - (13, 258, 1150, 1139, 18446744073709551615, 0, 1), - (13, 1097, 11, 1151, 18446744073709551615, 0, 2), - (13, 1087, 1145, 1132, 18446744073709551615, 0, 9), - (13, 1028, 13, 1149, 18446744073709551615, 2, 255), - (13, 1028, 1145, 1087, 18446744073709551615, 2, 255), - (13, 1028, 11, 1097, 18446744073709551615, 4, 257), - (13, 1097, 11, 1139, 18446744073709551615, 0, 1), - (13, 1087, 1145, 10, 18446744073709551615, 1, 2), - (13, 1149, 13, 793, 18446744073709551615, 0, 1), - (13, 776, 1087, 1097, 18446744073709551615, 2, 254), - (13, 282, 1147, 886, 18446744073709551615, 0, 9), - (13, 283, 886, 1088, 18446744073709551615, 0, 12), - (13, 284, 1088, 915, 18446744073709551615, 0, 12), - (13, 285, 915, 889, 18446744073709551615, 0, 12), - (13, 286, 889, 146, 18446744073709551615, 0, 12), - (13, 287, 146, 793, 18446744073709551615, 0, 2), - (13, 305, 146, 886, 18446744073709551615, 0, 2), - (13, 307, 1088, 915, 18446744073709551615, 0, 14), - (13, 257, 1150, 143, 18446744073709551615, 0, 1), - (13, 258, 143, 12, 18446744073709551615, 0, 1), - (13, 259, 12, 9, 18446744073709551615, 0, 1), - (13, 282, 916, 1151, 18446744073709551615, 0, 1), - (13, 284, 1086, 916, 18446744073709551615, 0, 1), - (13, 286, 1151, 1132, 18446744073709551615, 0, 1), - (13, 287, 1132, 12, 18446744073709551615, 0, 1), - (13, 305, 1025, 10, 18446744073709551615, 0, 2), - (13, 306, 10, 793, 18446744073709551615, 0, 11), - (13, 308, 1139, 1025, 18446744073709551615, 0, 1), - (13, 306, 10, 793, 18446744073709551615, 1, 11), - (13, 284, 12, 1139, 18446744073709551615, 0, 1), - (13, 286, 1141, 1132, 18446744073709551615, 0, 2), - (13, 282, 1139, 1141, 18446744073709551615, 1, 2), - (13, 256, 12, 143, 18446744073709551615, 0, 1), - (13, 257, 1139, 1151, 18446744073709551615, 0, 1), - (13, 258, 1141, 916, 18446744073709551615, 0, 1), - (13, 1087, 1145, 143, 18446744073709551615, 1, 6), - (13, 1149, 13, 1151, 18446744073709551615, 0, 4), - (13, 1028, 887, 1137, 18446744073709551615, 0, 252), - (13, 1028, 13, 1149, 18446744073709551615, 3, 255), - (13, 1028, 1145, 1087, 18446744073709551615, 3, 255), - (13, 1024, 887, 1137, 18446744073709551615, 0, 250), - (13, 1087, 1145, 925, 18446744073709551615, 0, 1), - (13, 1149, 13, 10, 18446744073709551615, 0, 1), - (13, 1137, 887, 793, 18446744073709551615, 0, 1), - (13, 776, 1149, 1087, 18446744073709551615, 0, 251), - (13, 285, 1088, 915, 18446744073709551615, 0, 16), - (13, 287, 889, 146, 18446744073709551615, 0, 16), - (13, 304, 915, 889, 18446744073709551615, 0, 32), - (13, 305, 889, 146, 18446744073709551615, 0, 32), - (13, 306, 146, 886, 18446744073709551615, 0, 1), - (13, 257, 1141, 1139, 18446744073709551615, 0, 1), - (13, 258, 1139, 12, 18446744073709551615, 0, 1), - (13, 259, 12, 1132, 18446744073709551615, 0, 1), - (13, 283, 1150, 150, 18446744073709551615, 0, 1), - (13, 286, 1150, 143, 18446744073709551615, 0, 1), - (13, 287, 143, 12, 18446744073709551615, 0, 1), - (13, 306, 925, 10, 18446744073709551615, 0, 9), - (13, 307, 10, 1025, 18446744073709551615, 0, 1), - (13, 308, 1025, 916, 18446744073709551615, 0, 1), - (13, 304, 1025, 916, 18446744073709551615, 0, 1), - (13, 306, 925, 10, 18446744073709551615, 1, 9), - (13, 286, 1151, 143, 18446744073709551615, 0, 2), - (13, 256, 12, 1139, 18446744073709551615, 0, 1), - (13, 257, 1025, 1150, 18446744073709551615, 0, 1), - (13, 258, 1151, 9, 18446744073709551615, 0, 1), - (13, 1149, 13, 1150, 18446744073709551615, 0, 1), - (13, 1028, 13, 1149, 18446744073709551615, 4, 255), - (13, 1149, 13, 925, 18446744073709551615, 0, 1), - (13, 1137, 887, 10, 18446744073709551615, 0, 1), - (13, 282, 793, 1147, 18446744073709551615, 0, 3), - (13, 284, 886, 1088, 18446744073709551615, 2, 15), - (13, 304, 1088, 889, 18446744073709551615, 0, 9), - (13, 305, 889, 146, 18446744073709551615, 2, 32), - (13, 306, 146, 915, 18446744073709551615, 0, 6), - (13, 307, 915, 889, 18446744073709551615, 2, 18), - (13, 257, 1151, 924, 18446744073709551615, 0, 1), - (13, 258, 924, 12, 18446744073709551615, 0, 2), - (13, 259, 12, 143, 18446744073709551615, 0, 1), - (13, 284, 150, 1132, 18446744073709551615, 0, 1), - (13, 305, 9, 916, 18446744073709551615, 0, 4), - (13, 305, 9, 916, 18446744073709551615, 1, 4), - (13, 306, 916, 925, 18446744073709551615, 1, 10), - (13, 284, 12, 1150, 18446744073709551615, 0, 1), - (13, 285, 1150, 1025, 18446744073709551615, 0, 1), - (13, 256, 12, 924, 18446744073709551615, 0, 1), - (13, 257, 1150, 1141, 18446744073709551615, 0, 1), - (13, 258, 1025, 1132, 18446744073709551615, 0, 1), - (13, 1137, 887, 1132, 18446744073709551615, 0, 6), - (13, 1028, 113, 17, 18446744073709551615, 0, 250), - (13, 1028, 887, 1137, 18446744073709551615, 2, 252), - (13, 1024, 113, 17, 18446744073709551615, 0, 248), - (13, 1137, 887, 925, 18446744073709551615, 8, 10), - (13, 17, 113, 10, 18446744073709551615, 0, 2), - (13, 283, 793, 1147, 18446744073709551615, 0, 2), - (13, 284, 1147, 886, 18446744073709551615, 0, 7), - (13, 287, 915, 889, 18446744073709551615, 0, 10), - (13, 305, 1088, 889, 18446744073709551615, 2, 7), - (13, 257, 1100, 1150, 18446744073709551615, 0, 1), - (13, 258, 1150, 12, 18446744073709551615, 0, 1), - (13, 259, 12, 1139, 18446744073709551615, 0, 1), - (13, 287, 924, 12, 18446744073709551615, 0, 1), - (13, 256, 12, 1150, 18446744073709551615, 0, 1), - (13, 257, 1141, 1151, 18446744073709551615, 0, 1), - (13, 258, 1025, 143, 18446744073709551615, 0, 1), - (13, 1028, 885, 1134, 18446744073709551615, 0, 249), - (13, 1024, 885, 1134, 18446744073709551615, 0, 247), - (13, 17, 113, 925, 18446744073709551615, 5, 6), - (13, 1134, 885, 10, 18446744073709551615, 0, 1), - (13, 283, 922, 1147, 18446744073709551615, 0, 1), - (13, 286, 915, 889, 18446744073709551615, 4, 16), - (13, 305, 922, 889, 18446744073709551615, 0, 1), - (13, 307, 146, 148, 18446744073709551615, 0, 2), - (13, 257, 12, 1139, 18446744073709551615, 0, 1), - (13, 258, 1139, 1100, 18446744073709551615, 0, 1), - (13, 259, 1100, 1141, 18446744073709551615, 0, 1), - (13, 286, 1151, 143, 18446744073709551615, 1, 2), - (13, 287, 143, 1100, 18446744073709551615, 0, 1), - (13, 284, 1100, 1132, 18446744073709551615, 0, 1), - (13, 256, 1100, 1139, 18446744073709551615, 0, 1), - (13, 257, 1132, 1151, 18446744073709551615, 0, 1), - (13, 258, 1025, 1150, 18446744073709551615, 0, 1), - (13, 1028, 894, 27, 18446744073709551615, 0, 248), - (13, 1024, 894, 27, 18446744073709551615, 0, 246), - (13, 1134, 885, 793, 18446744073709551615, 0, 1), - (13, 27, 894, 923, 18446744073709551615, 4, 5), - (13, 283, 925, 793, 18446744073709551615, 0, 1), - (13, 285, 923, 1147, 18446744073709551615, 0, 2), - (13, 287, 886, 1088, 18446744073709551615, 0, 9), - (13, 306, 1088, 915, 18446744073709551615, 2, 20), - (13, 257, 927, 924, 18446744073709551615, 0, 4), - (13, 258, 924, 143, 18446744073709551615, 0, 2), - (13, 259, 143, 150, 18446744073709551615, 0, 1), - (13, 285, 928, 1132, 18446744073709551615, 0, 1), - (13, 286, 1132, 1100, 18446744073709551615, 0, 1), - (13, 308, 12, 1139, 18446744073709551615, 0, 1), - (13, 306, 1151, 1150, 18446744073709551615, 1, 12), - (13, 285, 12, 1141, 18446744073709551615, 4, 6), - (13, 286, 1141, 1100, 18446744073709551615, 0, 3), - (13, 256, 143, 924, 18446744073709551615, 0, 1), - (13, 257, 12, 1132, 18446744073709551615, 0, 1), - (13, 258, 1141, 928, 18446744073709551615, 0, 1), - (13, 27, 894, 925, 18446744073709551615, 6, 7), - (13, 284, 889, 146, 18446744073709551615, 0, 6), - (13, 285, 146, 793, 18446744073709551615, 0, 1), - (13, 286, 793, 1147, 18446744073709551615, 0, 1), - (13, 287, 1147, 886, 18446744073709551615, 2, 7), - (13, 306, 889, 146, 18446744073709551615, 3, 27), - (13, 307, 146, 1088, 18446744073709551615, 0, 4), - (13, 257, 1100, 1141, 18446744073709551615, 0, 3), - (13, 258, 1141, 12, 18446744073709551615, 0, 2), - (13, 259, 12, 1142, 18446744073709551615, 0, 1), - (13, 287, 927, 12, 18446744073709551615, 0, 1), - (13, 308, 1132, 928, 18446744073709551615, 0, 1), - (13, 285, 1132, 924, 18446744073709551615, 0, 1), - (13, 256, 12, 1141, 18446744073709551615, 0, 1), - (13, 257, 1132, 150, 18446744073709551615, 0, 1), - (13, 258, 924, 143, 18446744073709551615, 1, 2), - (13, 110, 1086, 925, 18446744073709551615, 0, 2), - (13, 285, 889, 146, 18446744073709551615, 0, 8), - (13, 287, 793, 1147, 18446744073709551615, 0, 1), - (13, 257, 927, 924, 18446744073709551615, 1, 4), - (13, 258, 924, 1132, 18446744073709551615, 0, 2), - (13, 259, 1132, 787, 18446744073709551615, 0, 1), - (13, 285, 150, 1141, 18446744073709551615, 0, 1), - (13, 256, 1132, 924, 18446744073709551615, 0, 1), - (13, 257, 150, 1142, 18446744073709551615, 0, 1), - (13, 258, 1141, 12, 18446744073709551615, 1, 2), - (13, 257, 1100, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 150, 18446744073709551615, 0, 2), - (13, 259, 150, 786, 18446744073709551615, 0, 1), - (13, 285, 1142, 924, 18446744073709551615, 0, 1), - (13, 286, 924, 927, 18446744073709551615, 1, 2), - (13, 256, 150, 1141, 18446744073709551615, 0, 1), - (13, 257, 1142, 787, 18446744073709551615, 0, 1), - (13, 258, 924, 1132, 18446744073709551615, 1, 2), - (13, 286, 915, 889, 18446744073709551615, 6, 16), - (13, 287, 889, 146, 18446744073709551615, 6, 16), - (13, 257, 927, 924, 18446744073709551615, 2, 4), - (13, 258, 924, 1142, 18446744073709551615, 0, 1), - (13, 259, 1142, 104, 18446744073709551615, 0, 1), - (13, 286, 786, 1100, 18446744073709551615, 0, 1), - (13, 287, 1100, 1142, 18446744073709551615, 0, 1), - (13, 286, 1141, 1100, 18446744073709551615, 2, 3), - (13, 256, 1142, 924, 18446744073709551615, 0, 1), - (13, 257, 787, 786, 18446744073709551615, 0, 1), - (13, 258, 1141, 150, 18446744073709551615, 1, 2), - (13, 287, 146, 923, 18446744073709551615, 0, 1), - (13, 257, 787, 1142, 18446744073709551615, 0, 2), - (13, 258, 1142, 104, 18446744073709551615, 0, 2), - (13, 259, 104, 1100, 18446744073709551615, 0, 1), - (13, 287, 786, 104, 18446744073709551615, 0, 1), - (13, 256, 104, 1142, 18446744073709551615, 0, 1), - (13, 257, 1132, 924, 18446744073709551615, 0, 1), - (13, 258, 150, 927, 18446744073709551615, 0, 1), - (13, 285, 1088, 915, 18446744073709551615, 8, 16), - (13, 286, 915, 889, 18446744073709551615, 8, 16), - (13, 287, 889, 146, 18446744073709551615, 8, 16), - (13, 257, 786, 150, 18446744073709551615, 0, 1), - (13, 258, 150, 1132, 18446744073709551615, 0, 2), - (13, 259, 1132, 1141, 18446744073709551615, 0, 1), - (13, 287, 787, 1132, 18446744073709551615, 0, 1), - (13, 286, 1142, 787, 18446744073709551615, 0, 1), - (13, 256, 1132, 150, 18446744073709551615, 0, 1), - (13, 257, 924, 1100, 18446744073709551615, 0, 1), - (13, 258, 1142, 104, 18446744073709551615, 1, 2), - (13, 286, 1088, 915, 18446744073709551615, 2, 10), - (13, 287, 915, 889, 18446744073709551615, 2, 10), - (13, 257, 787, 1142, 18446744073709551615, 1, 2), - (13, 258, 1142, 924, 18446744073709551615, 0, 1), - (13, 259, 924, 788, 18446744073709551615, 0, 1), - (13, 287, 786, 924, 18446744073709551615, 0, 1), - (13, 256, 924, 1142, 18446744073709551615, 0, 1), - (13, 257, 1100, 1141, 18446744073709551615, 2, 3), - (13, 258, 150, 1132, 18446744073709551615, 1, 2), - (13, 257, 1142, 1141, 18446744073709551615, 0, 2), - (13, 258, 1141, 1132, 18446744073709551615, 0, 2), - (13, 259, 1132, 788, 18446744073709551615, 0, 1), - (13, 287, 12, 1132, 18446744073709551615, 0, 1), - (13, 256, 1132, 1141, 18446744073709551615, 0, 1), - (13, 257, 928, 927, 18446744073709551615, 0, 3), - (13, 258, 143, 104, 18446744073709551615, 0, 1), - (13, 786, 20, 886, 18446744073709551615, 0, 4), - (13, 1028, 23, 150, 18446744073709551615, 0, 239), - (13, 1028, 20, 786, 18446744073709551615, 0, 239), - (13, 1024, 20, 786, 18446744073709551615, 0, 237), - (13, 1024, 23, 150, 18446744073709551615, 0, 237), - (13, 786, 20, 915, 18446744073709551615, 0, 1), - (13, 150, 23, 889, 18446744073709551615, 0, 1), - (13, 776, 786, 791, 18446744073709551615, 0, 238), - (13, 286, 148, 922, 18446744073709551615, 0, 4), - (13, 257, 12, 143, 18446744073709551615, 0, 2), - (13, 258, 143, 928, 18446744073709551615, 0, 2), - (13, 259, 928, 787, 18446744073709551615, 0, 1), - (13, 287, 1142, 928, 18446744073709551615, 0, 1), - (13, 286, 1141, 1142, 18446744073709551615, 0, 1), - (13, 256, 928, 143, 18446744073709551615, 0, 1), - (13, 257, 927, 788, 18446744073709551615, 0, 1), - (13, 258, 1141, 1132, 18446744073709551615, 1, 2), - (13, 1028, 926, 101, 18446744073709551615, 0, 238), - (13, 1024, 926, 101, 18446744073709551615, 0, 236), - (13, 150, 23, 915, 18446744073709551615, 0, 2), - (13, 101, 926, 889, 18446744073709551615, 0, 2), - (13, 257, 1142, 1141, 18446744073709551615, 1, 2), - (13, 258, 1141, 927, 18446744073709551615, 0, 7), - (13, 259, 927, 924, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 0, 7), - (13, 257, 788, 787, 18446744073709551615, 0, 1), - (13, 258, 143, 928, 18446744073709551615, 1, 2), - (13, 1028, 1100, 873, 18446744073709551615, 0, 237), - (13, 1024, 1100, 873, 18446744073709551615, 0, 235), - (13, 101, 926, 915, 18446744073709551615, 0, 3), - (13, 873, 1100, 889, 18446744073709551615, 0, 3), - (13, 287, 922, 1147, 18446744073709551615, 1, 2), - (13, 257, 788, 927, 18446744073709551615, 0, 2), - (13, 258, 927, 924, 18446744073709551615, 0, 2), - (13, 259, 924, 12, 18446744073709551615, 0, 1), - (13, 286, 928, 787, 18446744073709551615, 0, 2), - (13, 256, 924, 927, 18446744073709551615, 0, 1), - (13, 257, 1132, 1141, 18446744073709551615, 0, 3), - (13, 258, 928, 1142, 18446744073709551615, 0, 1), - (13, 1028, 798, 1101, 18446744073709551615, 0, 236), - (13, 1024, 798, 1101, 18446744073709551615, 0, 234), - (13, 873, 1100, 146, 18446744073709551615, 0, 1), - (13, 1101, 798, 148, 18446744073709551615, 0, 1), - (13, 286, 146, 148, 18446744073709551615, 2, 6), - (13, 257, 787, 928, 18446744073709551615, 0, 2), - (13, 258, 928, 1132, 18446744073709551615, 0, 2), - (13, 259, 1132, 143, 18446744073709551615, 0, 1), - (13, 256, 1132, 928, 18446744073709551615, 0, 1), - (13, 257, 1141, 12, 18446744073709551615, 0, 1), - (13, 258, 927, 924, 18446744073709551615, 1, 2), - (13, 1101, 798, 146, 18446744073709551615, 0, 2), - (13, 98, 1085, 148, 18446744073709551615, 0, 2), - (13, 257, 788, 927, 18446744073709551615, 1, 2), - (13, 258, 927, 1141, 18446744073709551615, 0, 6), - (13, 259, 1141, 796, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 0, 6), - (13, 257, 12, 143, 18446744073709551615, 1, 2), - (13, 258, 928, 1132, 18446744073709551615, 1, 2), - (13, 1028, 797, 870, 18446744073709551615, 0, 234), - (13, 1024, 797, 870, 18446744073709551615, 0, 232), - (13, 98, 1085, 146, 18446744073709551615, 0, 2), - (13, 870, 797, 148, 18446744073709551615, 0, 2), - (13, 286, 146, 148, 18446744073709551615, 4, 6), - (13, 287, 148, 1147, 18446744073709551615, 2, 3), - (13, 257, 12, 1141, 18446744073709551615, 0, 2), - (13, 258, 1141, 796, 18446744073709551615, 0, 2), - (13, 259, 796, 787, 18446744073709551615, 0, 1), - (13, 256, 796, 1141, 18446744073709551615, 0, 1), - (13, 257, 924, 927, 18446744073709551615, 0, 3), - (13, 258, 1132, 788, 18446744073709551615, 0, 1), - (13, 870, 797, 922, 18446744073709551615, 0, 1), - (13, 1102, 801, 1153, 18446744073709551615, 0, 1), - (13, 286, 889, 146, 18446744073709551615, 8, 12), - (13, 287, 146, 148, 18446744073709551615, 2, 6), - (13, 257, 143, 1132, 18446744073709551615, 0, 2), - (13, 258, 1132, 924, 18446744073709551615, 0, 2), - (13, 259, 924, 928, 18446744073709551615, 0, 1), - (13, 256, 924, 1132, 18446744073709551615, 0, 1), - (13, 257, 927, 787, 18446744073709551615, 0, 1), - (13, 258, 1141, 796, 18446744073709551615, 1, 2), - (13, 1102, 801, 922, 18446744073709551615, 0, 1), - (13, 95, 934, 1153, 18446744073709551615, 0, 1), - (13, 287, 889, 146, 18446744073709551615, 10, 16), - (13, 257, 12, 1141, 18446744073709551615, 1, 2), - (13, 258, 1141, 927, 18446744073709551615, 1, 7), - (13, 259, 927, 799, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 1, 7), - (13, 257, 787, 928, 18446744073709551615, 1, 2), - (13, 258, 1132, 924, 18446744073709551615, 1, 2), - (13, 1028, 800, 867, 18446744073709551615, 0, 231), - (13, 1024, 800, 867, 18446744073709551615, 0, 229), - (13, 95, 934, 922, 18446744073709551615, 0, 1), - (13, 867, 800, 1153, 18446744073709551615, 0, 1), - (13, 257, 787, 927, 18446744073709551615, 0, 2), - (13, 258, 927, 799, 18446744073709551615, 0, 2), - (13, 259, 799, 143, 18446744073709551615, 0, 1), - (13, 256, 799, 927, 18446744073709551615, 0, 1), - (13, 257, 796, 1141, 18446744073709551615, 0, 3), - (13, 258, 924, 12, 18446744073709551615, 1, 2), - (13, 867, 800, 922, 18446744073709551615, 1, 2), - (13, 1103, 804, 1153, 18446744073709551615, 0, 1), - (13, 286, 915, 889, 18446744073709551615, 12, 16), - (13, 257, 928, 924, 18446744073709551615, 0, 2), - (13, 258, 924, 796, 18446744073709551615, 0, 2), - (13, 259, 796, 1132, 18446744073709551615, 0, 1), - (13, 256, 796, 924, 18446744073709551615, 0, 1), - (13, 257, 1141, 143, 18446744073709551615, 0, 1), - (13, 258, 927, 799, 18446744073709551615, 1, 2), - (13, 1103, 804, 922, 18446744073709551615, 1, 2), - (13, 92, 931, 1153, 18446744073709551615, 0, 1), - (13, 287, 915, 889, 18446744073709551615, 4, 10), - (13, 257, 787, 927, 18446744073709551615, 1, 2), - (13, 258, 927, 1141, 18446744073709551615, 1, 6), - (13, 259, 1141, 802, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 1, 6), - (13, 257, 143, 1132, 18446744073709551615, 1, 2), - (13, 258, 924, 796, 18446744073709551615, 1, 2), - (13, 92, 931, 922, 18446744073709551615, 1, 3), - (13, 864, 803, 1153, 18446744073709551615, 0, 2), - (13, 286, 915, 889, 18446744073709551615, 14, 16), - (13, 257, 143, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 802, 18446744073709551615, 0, 2), - (13, 259, 802, 928, 18446744073709551615, 0, 1), - (13, 287, 1132, 802, 18446744073709551615, 0, 1), - (13, 256, 802, 1141, 18446744073709551615, 0, 1), - (13, 257, 799, 927, 18446744073709551615, 0, 3), - (13, 258, 796, 787, 18446744073709551615, 0, 1), - (13, 864, 803, 922, 18446744073709551615, 0, 2), - (13, 1104, 807, 1153, 18446744073709551615, 0, 2), - (13, 286, 1088, 915, 18446744073709551615, 6, 10), - (13, 287, 915, 889, 18446744073709551615, 6, 10), - (13, 257, 1132, 796, 18446744073709551615, 0, 2), - (13, 258, 796, 799, 18446744073709551615, 0, 2), - (13, 259, 799, 924, 18446744073709551615, 0, 1), - (13, 256, 799, 796, 18446744073709551615, 0, 1), - (13, 257, 927, 928, 18446744073709551615, 0, 1), - (13, 258, 1141, 802, 18446744073709551615, 1, 2), - (13, 1104, 807, 922, 18446744073709551615, 0, 2), - (13, 89, 930, 1153, 18446744073709551615, 0, 2), - (13, 257, 143, 1141, 18446744073709551615, 2, 3), - (13, 258, 1141, 927, 18446744073709551615, 2, 7), - (13, 259, 927, 805, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 2, 7), - (13, 257, 928, 924, 18446744073709551615, 1, 2), - (13, 258, 796, 799, 18446744073709551615, 1, 2), - (13, 89, 930, 922, 18446744073709551615, 0, 2), - (13, 861, 806, 1153, 18446744073709551615, 0, 2), - (13, 257, 928, 927, 18446744073709551615, 1, 3), - (13, 258, 927, 805, 18446744073709551615, 0, 2), - (13, 259, 805, 1132, 18446744073709551615, 0, 1), - (13, 256, 805, 927, 18446744073709551615, 0, 1), - (13, 257, 802, 1141, 18446744073709551615, 0, 3), - (13, 258, 799, 143, 18446744073709551615, 0, 1), - (13, 861, 806, 922, 18446744073709551615, 0, 2), - (13, 1105, 810, 1153, 18446744073709551615, 0, 2), - (13, 287, 1088, 915, 18446744073709551615, 6, 10), - (13, 257, 924, 799, 18446744073709551615, 0, 2), - (13, 258, 799, 802, 18446744073709551615, 0, 2), - (13, 259, 802, 796, 18446744073709551615, 0, 1), - (13, 256, 802, 799, 18446744073709551615, 0, 1), - (13, 257, 1141, 1132, 18446744073709551615, 0, 1), - (13, 258, 927, 805, 18446744073709551615, 1, 2), - (13, 1105, 810, 922, 18446744073709551615, 0, 2), - (13, 86, 163, 1153, 18446744073709551615, 0, 2), - (13, 286, 923, 886, 18446744073709551615, 0, 3), - (13, 257, 928, 927, 18446744073709551615, 2, 3), - (13, 258, 927, 1141, 18446744073709551615, 2, 6), - (13, 259, 1141, 808, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 2, 6), - (13, 257, 1132, 796, 18446744073709551615, 1, 2), - (13, 258, 799, 802, 18446744073709551615, 1, 2), - (13, 86, 163, 922, 18446744073709551615, 0, 2), - (13, 858, 809, 1153, 18446744073709551615, 0, 2), - (13, 287, 1088, 915, 18446744073709551615, 8, 10), - (13, 257, 1132, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 808, 18446744073709551615, 0, 2), - (13, 259, 808, 924, 18446744073709551615, 0, 1), - (13, 256, 808, 1141, 18446744073709551615, 0, 1), - (13, 257, 805, 927, 18446744073709551615, 0, 3), - (13, 258, 802, 928, 18446744073709551615, 0, 1), - (13, 858, 809, 922, 18446744073709551615, 0, 2), - (13, 1106, 813, 1153, 18446744073709551615, 0, 2), - (13, 287, 886, 1088, 18446744073709551615, 5, 9), - (13, 257, 796, 802, 18446744073709551615, 0, 2), - (13, 258, 802, 805, 18446744073709551615, 0, 2), - (13, 259, 805, 799, 18446744073709551615, 0, 1), - (13, 256, 805, 802, 18446744073709551615, 0, 1), - (13, 257, 927, 924, 18446744073709551615, 3, 4), - (13, 258, 1141, 808, 18446744073709551615, 1, 2), - (13, 1024, 932, 83, 18446744073709551615, 0, 218), - (13, 1106, 813, 922, 18446744073709551615, 0, 2), - (13, 83, 932, 1153, 18446744073709551615, 0, 2), - (13, 286, 793, 923, 18446744073709551615, 0, 3), - (13, 287, 923, 886, 18446744073709551615, 0, 3), - (13, 257, 1132, 1141, 18446744073709551615, 2, 3), - (13, 258, 1141, 927, 18446744073709551615, 3, 7), - (13, 259, 927, 811, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 3, 7), - (13, 257, 924, 799, 18446744073709551615, 1, 2), - (13, 258, 802, 805, 18446744073709551615, 1, 2), - (13, 1024, 812, 855, 18446744073709551615, 0, 217), - (13, 855, 812, 1153, 18446744073709551615, 0, 2), - (13, 287, 886, 1088, 18446744073709551615, 7, 9), - (13, 257, 924, 927, 18446744073709551615, 1, 3), - (13, 258, 927, 811, 18446744073709551615, 0, 2), - (13, 259, 811, 796, 18446744073709551615, 0, 1), - (13, 256, 811, 927, 18446744073709551615, 0, 1), - (13, 257, 808, 1141, 18446744073709551615, 0, 3), - (13, 258, 805, 1132, 18446744073709551615, 0, 1), - (13, 1024, 816, 1107, 18446744073709551615, 0, 216), - (13, 855, 812, 922, 18446744073709551615, 0, 2), - (13, 1107, 816, 1153, 18446744073709551615, 0, 2), - (13, 257, 799, 805, 18446744073709551615, 0, 2), - (13, 258, 805, 808, 18446744073709551615, 0, 2), - (13, 259, 808, 802, 18446744073709551615, 0, 1), - (13, 256, 808, 805, 18446744073709551615, 0, 1), - (13, 257, 1141, 796, 18446744073709551615, 0, 1), - (13, 258, 927, 811, 18446744073709551615, 1, 2), - (13, 1024, 940, 80, 18446744073709551615, 0, 215), - (13, 80, 940, 1153, 18446744073709551615, 0, 2), - (13, 286, 10, 793, 18446744073709551615, 0, 3), - (13, 287, 793, 923, 18446744073709551615, 0, 3), - (13, 257, 924, 927, 18446744073709551615, 2, 3), - (13, 258, 927, 1141, 18446744073709551615, 3, 6), - (13, 259, 1141, 814, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 3, 6), - (13, 257, 796, 802, 18446744073709551615, 1, 2), - (13, 258, 805, 808, 18446744073709551615, 1, 2), - (13, 1024, 815, 852, 18446744073709551615, 0, 214), - (13, 852, 815, 1153, 18446744073709551615, 0, 2), - (13, 287, 923, 886, 18446744073709551615, 2, 3), - (13, 257, 796, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 814, 18446744073709551615, 0, 2), - (13, 259, 814, 799, 18446744073709551615, 0, 1), - (13, 256, 814, 1141, 18446744073709551615, 0, 1), - (13, 257, 811, 927, 18446744073709551615, 0, 2), - (13, 258, 808, 924, 18446744073709551615, 0, 1), - (13, 1024, 819, 1108, 18446744073709551615, 0, 213), - (13, 1108, 819, 1153, 18446744073709551615, 0, 2), - (13, 286, 10, 793, 18446744073709551615, 1, 3), - (13, 287, 793, 923, 18446744073709551615, 1, 3), - (13, 257, 802, 808, 18446744073709551615, 0, 2), - (13, 258, 808, 811, 18446744073709551615, 0, 2), - (13, 259, 811, 805, 18446744073709551615, 0, 1), - (13, 256, 811, 808, 18446744073709551615, 0, 1), - (13, 257, 927, 799, 18446744073709551615, 0, 1), - (13, 258, 1141, 814, 18446744073709551615, 1, 2), - (13, 1024, 171, 77, 18446744073709551615, 0, 212), - (13, 77, 171, 1153, 18446744073709551615, 0, 2), - (13, 286, 925, 10, 18446744073709551615, 0, 3), - (13, 287, 10, 793, 18446744073709551615, 0, 3), - (13, 257, 796, 1141, 18446744073709551615, 2, 3), - (13, 258, 1141, 927, 18446744073709551615, 4, 7), - (13, 259, 927, 817, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 4, 7), - (13, 257, 799, 805, 18446744073709551615, 1, 2), - (13, 258, 808, 811, 18446744073709551615, 1, 2), - (13, 1024, 818, 849, 18446744073709551615, 0, 211), - (13, 849, 818, 1153, 18446744073709551615, 0, 2), - (13, 286, 10, 793, 18446744073709551615, 2, 3), - (13, 287, 793, 923, 18446744073709551615, 2, 3), - (13, 257, 799, 927, 18446744073709551615, 1, 3), - (13, 258, 927, 817, 18446744073709551615, 0, 2), - (13, 259, 817, 802, 18446744073709551615, 0, 1), - (13, 256, 817, 927, 18446744073709551615, 0, 1), - (13, 257, 814, 1141, 18446744073709551615, 0, 1), - (13, 258, 811, 796, 18446744073709551615, 0, 1), - (13, 1109, 822, 1153, 18446744073709551615, 0, 2), - (13, 286, 925, 10, 18446744073709551615, 1, 3), - (13, 257, 805, 811, 18446744073709551615, 0, 2), - (13, 258, 811, 814, 18446744073709551615, 0, 2), - (13, 259, 814, 808, 18446744073709551615, 0, 1), - (13, 256, 814, 811, 18446744073709551615, 0, 1), - (13, 257, 1141, 802, 18446744073709551615, 0, 1), - (13, 258, 927, 817, 18446744073709551615, 1, 2), - (13, 74, 166, 1153, 18446744073709551615, 0, 2), - (13, 257, 799, 927, 18446744073709551615, 2, 3), - (13, 258, 927, 1141, 18446744073709551615, 4, 6), - (13, 259, 1141, 820, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 4, 6), - (13, 257, 802, 808, 18446744073709551615, 1, 2), - (13, 258, 811, 814, 18446744073709551615, 1, 2), - (13, 846, 821, 1153, 18446744073709551615, 0, 2), - (13, 286, 925, 10, 18446744073709551615, 2, 3), - (13, 287, 10, 793, 18446744073709551615, 2, 3), - (13, 257, 802, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 820, 18446744073709551615, 0, 2), - (13, 259, 820, 805, 18446744073709551615, 0, 1), - (13, 256, 820, 1141, 18446744073709551615, 0, 1), - (13, 257, 817, 927, 18446744073709551615, 0, 1), - (13, 258, 814, 799, 18446744073709551615, 0, 1), - (13, 1024, 825, 1110, 18446744073709551615, 0, 207), - (13, 1110, 825, 1153, 18446744073709551615, 0, 2), - (13, 287, 925, 10, 18446744073709551615, 1, 3), - (13, 257, 808, 814, 18446744073709551615, 0, 2), - (13, 258, 814, 817, 18446744073709551615, 0, 2), - (13, 259, 817, 811, 18446744073709551615, 0, 1), - (13, 286, 1141, 802, 18446744073709551615, 0, 1), - (13, 256, 817, 814, 18446744073709551615, 0, 1), - (13, 257, 927, 805, 18446744073709551615, 0, 1), - (13, 258, 1141, 820, 18446744073709551615, 1, 2), - (13, 71, 1084, 1153, 18446744073709551615, 0, 2), - (13, 287, 916, 925, 18446744073709551615, 0, 3), - (13, 257, 802, 1141, 18446744073709551615, 2, 3), - (13, 258, 1141, 927, 18446744073709551615, 5, 7), - (13, 259, 927, 823, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 5, 7), - (13, 257, 805, 811, 18446744073709551615, 1, 2), - (13, 258, 814, 817, 18446744073709551615, 1, 2), - (13, 843, 824, 1153, 18446744073709551615, 0, 2), - (13, 257, 805, 927, 18446744073709551615, 1, 3), - (13, 258, 927, 823, 18446744073709551615, 0, 2), - (13, 259, 823, 808, 18446744073709551615, 0, 1), - (13, 286, 817, 811, 18446744073709551615, 0, 2), - (13, 256, 823, 927, 18446744073709551615, 0, 1), - (13, 257, 820, 1141, 18446744073709551615, 0, 1), - (13, 258, 817, 802, 18446744073709551615, 0, 1), - (13, 1024, 828, 1111, 18446744073709551615, 0, 204), - (13, 1111, 828, 1153, 18446744073709551615, 0, 2), - (13, 257, 811, 817, 18446744073709551615, 0, 2), - (13, 258, 817, 820, 18446744073709551615, 0, 2), - (13, 259, 820, 814, 18446744073709551615, 0, 1), - (13, 256, 820, 817, 18446744073709551615, 0, 1), - (13, 257, 1141, 808, 18446744073709551615, 0, 1), - (13, 258, 927, 823, 18446744073709551615, 1, 2), - (13, 68, 939, 1153, 18446744073709551615, 0, 2), - (13, 286, 1150, 9, 18446744073709551615, 1, 4), - (13, 287, 9, 916, 18446744073709551615, 0, 3), - (13, 257, 805, 927, 18446744073709551615, 2, 3), - (13, 258, 927, 1141, 18446744073709551615, 5, 6), - (13, 259, 1141, 826, 18446744073709551615, 0, 1), - (13, 256, 1141, 927, 18446744073709551615, 5, 6), - (13, 257, 808, 814, 18446744073709551615, 1, 2), - (13, 258, 817, 820, 18446744073709551615, 1, 2), - (13, 1024, 827, 838, 18446744073709551615, 0, 202), - (13, 838, 827, 1153, 18446744073709551615, 0, 2), - (13, 286, 9, 916, 18446744073709551615, 2, 3), - (13, 287, 916, 925, 18446744073709551615, 2, 3), - (13, 257, 808, 1141, 18446744073709551615, 1, 3), - (13, 258, 1141, 826, 18446744073709551615, 0, 3), - (13, 259, 826, 811, 18446744073709551615, 0, 1), - (13, 286, 820, 814, 18446744073709551615, 0, 2), - (13, 256, 826, 1141, 18446744073709551615, 0, 2), - (13, 257, 823, 927, 18446744073709551615, 0, 1), - (13, 258, 820, 805, 18446744073709551615, 0, 1), - (13, 1024, 831, 1112, 18446744073709551615, 0, 201), - (13, 1112, 831, 1153, 18446744073709551615, 0, 2), - (13, 286, 1150, 9, 18446744073709551615, 2, 4), - (13, 257, 814, 820, 18446744073709551615, 0, 1), - (13, 258, 820, 823, 18446744073709551615, 0, 2), - (13, 259, 823, 817, 18446744073709551615, 0, 1), - (13, 286, 1141, 808, 18446744073709551615, 0, 1), - (13, 256, 823, 820, 18446744073709551615, 0, 1), - (13, 257, 927, 811, 18446744073709551615, 0, 1), - (13, 258, 1141, 826, 18446744073709551615, 1, 3), - (13, 65, 938, 1153, 18446744073709551615, 0, 2), - (13, 286, 1151, 1150, 18446744073709551615, 0, 6), - (13, 257, 808, 1141, 18446744073709551615, 2, 3), - (13, 258, 1141, 927, 18446744073709551615, 6, 7), - (13, 259, 927, 829, 18446744073709551615, 0, 1), - (13, 256, 927, 1141, 18446744073709551615, 6, 7), - (13, 257, 811, 817, 18446744073709551615, 1, 2), - (13, 258, 820, 823, 18446744073709551615, 1, 2), - (13, 1024, 830, 1119, 18446744073709551615, 0, 199), - (13, 1119, 830, 1153, 18446744073709551615, 0, 2), - (13, 286, 1150, 9, 18446744073709551615, 3, 4), - (13, 257, 811, 927, 18446744073709551615, 1, 2), - (13, 258, 927, 829, 18446744073709551615, 0, 2), - (13, 259, 829, 814, 18446744073709551615, 0, 1), - (13, 256, 829, 927, 18446744073709551615, 0, 1), - (13, 257, 826, 1141, 18446744073709551615, 0, 1), - (13, 258, 823, 808, 18446744073709551615, 0, 1), - (13, 1024, 834, 66, 18446744073709551615, 199, 397), - (13, 66, 834, 1153, 18446744073709551615, 2, 4), - (13, 286, 1151, 1150, 18446744073709551615, 1, 6), - (13, 287, 1150, 9, 18446744073709551615, 1, 6), - (13, 257, 817, 823, 18446744073709551615, 0, 1), - (13, 258, 823, 826, 18446744073709551615, 0, 1), - (13, 259, 826, 820, 18446744073709551615, 0, 1), - (13, 256, 826, 823, 18446744073709551615, 0, 1), - (13, 257, 1141, 814, 18446744073709551615, 0, 1), - (13, 258, 927, 829, 18446744073709551615, 1, 2), - (13, 1024, 169, 62, 18446744073709551615, 0, 197), - (13, 62, 169, 1153, 18446744073709551615, 0, 2), - (13, 257, 832, 811, 18446744073709551615, 0, 1), - (13, 258, 811, 927, 18446744073709551615, 0, 1), - (13, 259, 927, 1141, 18446744073709551615, 0, 1), - (13, 1024, 833, 1117, 18446744073709551615, 0, 196), - (13, 1117, 833, 1153, 18446744073709551615, 0, 2), - (13, 286, 1151, 1150, 18446744073709551615, 3, 6), - (13, 257, 927, 1141, 18446744073709551615, 0, 1), - (13, 258, 1141, 826, 18446744073709551615, 2, 3), - (13, 259, 826, 832, 18446744073709551615, 0, 1), - (13, 256, 826, 1141, 18446744073709551615, 1, 2), - (13, 257, 829, 817, 18446744073709551615, 0, 1), - (13, 258, 814, 820, 18446744073709551615, 0, 1), - (13, 1024, 837, 69, 18446744073709551615, 196, 391), - (13, 69, 837, 1153, 18446744073709551615, 2, 4), - (13, 286, 1139, 1151, 18446744073709551615, 1, 6), - (13, 287, 1151, 1150, 18446744073709551615, 1, 6), - (13, 257, 811, 823, 18446744073709551615, 0, 1), - (13, 258, 823, 814, 18446744073709551615, 0, 2), - (13, 259, 814, 829, 18446744073709551615, 0, 2), - (13, 1024, 944, 59, 18446744073709551615, 0, 194), - (13, 59, 944, 1153, 18446744073709551615, 0, 2), - (13, 257, 1120, 811, 18446744073709551615, 0, 1), - (13, 258, 811, 823, 18446744073709551615, 0, 1), - (13, 259, 823, 814, 18446744073709551615, 0, 3), - (13, 1024, 835, 839, 18446744073709551615, 0, 193), - (13, 839, 835, 1153, 18446744073709551615, 0, 2), - (13, 257, 1120, 823, 18446744073709551615, 0, 1), - (13, 258, 823, 814, 18446744073709551615, 1, 2), - (13, 259, 814, 829, 18446744073709551615, 1, 2), - (13, 1024, 841, 72, 18446744073709551615, 0, 192), - (13, 72, 841, 1153, 18446744073709551615, 0, 2), - (13, 287, 1139, 1151, 18446744073709551615, 1, 6), - (13, 257, 56, 1120, 18446744073709551615, 0, 1), - (13, 258, 1120, 823, 18446744073709551615, 0, 2), - (13, 259, 823, 814, 18446744073709551615, 1, 3), - (13, 1024, 941, 60, 18446744073709551615, 0, 191), - (13, 60, 941, 1153, 18446744073709551615, 0, 2), - (13, 286, 1142, 104, 18446744073709551615, 0, 6), - (13, 257, 1121, 56, 18446744073709551615, 0, 1), - (13, 258, 56, 1120, 18446744073709551615, 0, 1), - (13, 259, 1120, 823, 18446744073709551615, 0, 3), - (13, 1024, 63, 842, 18446744073709551615, 0, 190), - (13, 842, 63, 1153, 18446744073709551615, 0, 1), - (13, 287, 1139, 1151, 18446744073709551615, 3, 6), - (13, 257, 1121, 1120, 18446744073709551615, 0, 1), - (13, 258, 1120, 823, 18446744073709551615, 1, 2), - (13, 259, 823, 814, 18446744073709551615, 2, 3), - (13, 1028, 104, 1025, 18446744073709551615, 0, 9), - (13, 1024, 844, 75, 18446744073709551615, 0, 189), - (13, 75, 844, 1153, 18446744073709551615, 0, 1), - (13, 287, 104, 1139, 18446744073709551615, 1, 6), - (13, 257, 53, 1121, 18446744073709551615, 0, 1), - (13, 258, 1121, 1120, 18446744073709551615, 0, 2), - (13, 259, 1120, 823, 18446744073709551615, 1, 3), - (13, 1028, 1142, 1025, 18446744073709551615, 0, 5), - (13, 1024, 1081, 57, 18446744073709551615, 0, 188), - (13, 57, 1081, 1153, 18446744073709551615, 0, 1), - (13, 286, 788, 1142, 18446744073709551615, 1, 7), - (13, 287, 1142, 104, 18446744073709551615, 0, 6), - (13, 257, 1122, 53, 18446744073709551615, 0, 1), - (13, 258, 53, 1121, 18446744073709551615, 0, 1), - (13, 259, 1121, 1120, 18446744073709551615, 0, 3), - (13, 1028, 788, 1025, 18446744073709551615, 0, 7), - (13, 1024, 811, 845, 18446744073709551615, 0, 187), - (13, 845, 811, 1153, 18446744073709551615, 0, 1), - (13, 286, 1142, 104, 18446744073709551615, 3, 6), - (13, 257, 1122, 1121, 18446744073709551615, 0, 1), - (13, 258, 1121, 1120, 18446744073709551615, 1, 2), - (13, 259, 1120, 823, 18446744073709551615, 2, 3), - (13, 1028, 1139, 1025, 18446744073709551615, 0, 6), - (13, 78, 847, 1153, 18446744073709551615, 0, 1), - (13, 287, 1142, 104, 18446744073709551615, 1, 6), - (13, 257, 50, 1122, 18446744073709551615, 0, 1), - (13, 258, 1122, 1121, 18446744073709551615, 0, 2), - (13, 259, 1121, 1120, 18446744073709551615, 1, 3), - (13, 1028, 104, 1025, 18446744073709551615, 1, 9), - (13, 1024, 947, 54, 18446744073709551615, 0, 185), - (13, 54, 947, 148, 18446744073709551615, 0, 1), - (13, 286, 12, 788, 18446744073709551615, 1, 7), - (13, 287, 788, 1142, 18446744073709551615, 0, 6), - (13, 257, 1123, 50, 18446744073709551615, 0, 1), - (13, 258, 50, 1122, 18446744073709551615, 0, 1), - (13, 259, 1122, 1121, 18446744073709551615, 0, 3), - (13, 1028, 1142, 1025, 18446744073709551615, 1, 5), - (13, 1024, 56, 848, 18446744073709551615, 0, 184), - (13, 848, 56, 148, 18446744073709551615, 0, 1), - (13, 286, 788, 1142, 18446744073709551615, 4, 7), - (13, 287, 1142, 104, 18446744073709551615, 3, 6), - (13, 257, 1123, 1122, 18446744073709551615, 0, 1), - (13, 258, 1122, 1121, 18446744073709551615, 1, 2), - (13, 259, 1121, 1120, 18446744073709551615, 2, 3), - (13, 1028, 1151, 1025, 18446744073709551615, 0, 12), - (13, 1024, 850, 81, 18446744073709551615, 0, 183), - (13, 81, 850, 148, 18446744073709551615, 0, 1), - (13, 286, 12, 788, 18446744073709551615, 2, 7), - (13, 287, 788, 1142, 18446744073709551615, 1, 6), - (13, 257, 47, 1123, 18446744073709551615, 0, 1), - (13, 258, 1123, 1122, 18446744073709551615, 0, 2), - (13, 259, 1122, 1121, 18446744073709551615, 1, 3), - (13, 1028, 1139, 1025, 18446744073709551615, 1, 6), - (13, 1024, 175, 51, 18446744073709551615, 0, 182), - (13, 51, 175, 148, 18446744073709551615, 0, 1), - (13, 257, 1124, 47, 18446744073709551615, 0, 1), - (13, 258, 47, 1123, 18446744073709551615, 0, 1), - (13, 259, 1123, 1122, 18446744073709551615, 0, 3), - (13, 1028, 104, 1025, 18446744073709551615, 2, 9), - (13, 1024, 53, 851, 18446744073709551615, 0, 181), - (13, 851, 53, 146, 18446744073709551615, 0, 5), - (13, 287, 788, 1142, 18446744073709551615, 3, 6), - (13, 257, 1124, 1123, 18446744073709551615, 0, 1), - (13, 258, 1123, 1122, 18446744073709551615, 1, 2), - (13, 259, 1122, 1121, 18446744073709551615, 2, 3), - (13, 287, 1142, 104, 18446744073709551615, 5, 6), - (13, 1028, 1150, 1025, 18446744073709551615, 0, 14), - (13, 1024, 853, 84, 18446744073709551615, 0, 180), - (13, 84, 853, 922, 18446744073709551615, 0, 1), - (13, 287, 12, 788, 18446744073709551615, 1, 6), - (13, 257, 44, 1124, 18446744073709551615, 0, 1), - (13, 258, 1124, 1123, 18446744073709551615, 0, 2), - (13, 259, 1123, 1122, 18446744073709551615, 1, 3), - (13, 1028, 1151, 1025, 18446744073709551615, 1, 12), - (13, 1024, 1080, 48, 18446744073709551615, 0, 179), - (13, 48, 1080, 146, 18446744073709551615, 0, 4), - (13, 257, 1125, 44, 18446744073709551615, 0, 1), - (13, 258, 44, 1124, 18446744073709551615, 0, 1), - (13, 259, 1124, 1123, 18446744073709551615, 0, 3), - (13, 1028, 1139, 1025, 18446744073709551615, 2, 6), - (13, 1024, 50, 854, 18446744073709551615, 0, 178), - (13, 854, 50, 915, 18446744073709551615, 0, 5), - (13, 257, 1125, 1124, 18446744073709551615, 0, 1), - (13, 258, 1124, 1123, 18446744073709551615, 1, 2), - (13, 259, 1123, 1122, 18446744073709551615, 2, 3), - (13, 1028, 9, 1025, 18446744073709551615, 0, 11), - (13, 1024, 856, 87, 18446744073709551615, 0, 177), - (13, 87, 856, 889, 18446744073709551615, 0, 4), - (13, 286, 143, 787, 18446744073709551615, 3, 8), - (13, 287, 787, 12, 18446744073709551615, 1, 6), - (13, 257, 41, 1125, 18446744073709551615, 0, 1), - (13, 258, 1125, 1124, 18446744073709551615, 0, 2), - (13, 259, 1124, 1123, 18446744073709551615, 1, 3), - (13, 1028, 1150, 1025, 18446744073709551615, 1, 14), - (13, 45, 950, 889, 18446744073709551615, 0, 4), - (13, 287, 143, 787, 18446744073709551615, 0, 6), - (13, 257, 1126, 41, 18446744073709551615, 0, 1), - (13, 258, 41, 1125, 18446744073709551615, 0, 1), - (13, 259, 1125, 1124, 18446744073709551615, 0, 3), - (13, 1028, 1151, 1025, 18446744073709551615, 2, 12), - (13, 1024, 47, 857, 18446744073709551615, 0, 175), - (13, 857, 47, 1088, 18446744073709551615, 0, 5), - (13, 286, 143, 787, 18446744073709551615, 5, 8), - (13, 257, 1126, 1125, 18446744073709551615, 0, 1), - (13, 258, 1125, 1124, 18446744073709551615, 1, 2), - (13, 259, 1124, 1123, 18446744073709551615, 2, 3), - (13, 1028, 916, 1025, 18446744073709551615, 0, 3), - (13, 1024, 859, 90, 18446744073709551615, 0, 174), - (13, 90, 859, 915, 18446744073709551615, 0, 4), - (13, 287, 143, 787, 18446744073709551615, 1, 6), - (13, 257, 38, 1126, 18446744073709551615, 0, 1), - (13, 258, 1126, 1125, 18446744073709551615, 0, 2), - (13, 259, 1125, 1124, 18446744073709551615, 1, 3), - (13, 1028, 9, 1025, 18446744073709551615, 1, 11), - (13, 1024, 178, 42, 18446744073709551615, 0, 173), - (13, 42, 178, 915, 18446744073709551615, 0, 4), - (13, 287, 928, 143, 18446744073709551615, 0, 6), - (13, 257, 1127, 38, 18446744073709551615, 0, 1), - (13, 258, 38, 1126, 18446744073709551615, 0, 1), - (13, 259, 1126, 1125, 18446744073709551615, 0, 3), - (13, 1028, 1150, 1025, 18446744073709551615, 2, 14), - (13, 860, 44, 886, 18446744073709551615, 0, 5), - (13, 286, 928, 143, 18446744073709551615, 5, 8), - (13, 287, 143, 787, 18446744073709551615, 3, 6), - (13, 257, 1127, 1126, 18446744073709551615, 0, 1), - (13, 258, 1126, 1125, 18446744073709551615, 1, 2), - (13, 259, 1125, 1124, 18446744073709551615, 2, 3), - (13, 1028, 925, 1025, 18446744073709551615, 1, 18), - (13, 1024, 862, 93, 18446744073709551615, 0, 171), - (13, 93, 862, 1088, 18446744073709551615, 0, 4), - (13, 287, 928, 143, 18446744073709551615, 1, 6), - (13, 257, 35, 1127, 18446744073709551615, 0, 1), - (13, 258, 1127, 1126, 18446744073709551615, 0, 2), - (13, 259, 1126, 1125, 18446744073709551615, 1, 3), - (13, 1028, 916, 1025, 18446744073709551615, 1, 3), - (13, 1024, 1079, 39, 18446744073709551615, 0, 170), - (13, 39, 1079, 886, 18446744073709551615, 0, 4), - (13, 287, 1132, 928, 18446744073709551615, 0, 6), - (13, 257, 1128, 35, 18446744073709551615, 0, 1), - (13, 258, 35, 1127, 18446744073709551615, 0, 1), - (13, 259, 1127, 1126, 18446744073709551615, 0, 3), - (13, 1028, 9, 1025, 18446744073709551615, 2, 11), - (13, 1024, 41, 863, 18446744073709551615, 0, 169), - (13, 863, 41, 923, 18446744073709551615, 0, 5), - (13, 286, 1132, 928, 18446744073709551615, 5, 8), - (13, 287, 928, 143, 18446744073709551615, 3, 6), - (13, 257, 1128, 1127, 18446744073709551615, 0, 1), - (13, 258, 1127, 1126, 18446744073709551615, 1, 2), - (13, 259, 1126, 1125, 18446744073709551615, 2, 3), - (13, 1028, 10, 1025, 18446744073709551615, 5, 21), - (13, 1024, 865, 96, 18446744073709551615, 0, 168), - (13, 96, 865, 1147, 18446744073709551615, 0, 4), - (13, 287, 1132, 928, 18446744073709551615, 1, 6), - (13, 257, 32, 1128, 18446744073709551615, 0, 1), - (13, 258, 1128, 1127, 18446744073709551615, 0, 2), - (13, 259, 1127, 1126, 18446744073709551615, 1, 3), - (13, 1028, 925, 1025, 18446744073709551615, 4, 18), - (13, 1024, 953, 36, 18446744073709551615, 0, 167), - (13, 36, 953, 1147, 18446744073709551615, 0, 3), - (13, 287, 924, 1132, 18446744073709551615, 0, 6), - (13, 257, 1129, 32, 18446744073709551615, 0, 1), - (13, 258, 32, 1128, 18446744073709551615, 0, 1), - (13, 259, 1128, 1127, 18446744073709551615, 0, 3), - (13, 1028, 916, 1025, 18446744073709551615, 2, 3), - (13, 1024, 38, 866, 18446744073709551615, 0, 166), - (13, 866, 38, 793, 18446744073709551615, 0, 2), - (13, 286, 924, 1132, 18446744073709551615, 5, 8), - (13, 257, 1129, 1128, 18446744073709551615, 0, 1), - (13, 258, 1128, 1127, 18446744073709551615, 1, 2), - (13, 259, 1127, 1126, 18446744073709551615, 2, 3), - (13, 1028, 793, 1025, 18446744073709551615, 9, 19), - (13, 1024, 868, 99, 18446744073709551615, 0, 165), - (13, 99, 868, 923, 18446744073709551615, 0, 1), - (13, 286, 796, 924, 18446744073709551615, 3, 8), - (13, 287, 924, 1132, 18446744073709551615, 1, 6), - (13, 257, 29, 1129, 18446744073709551615, 0, 1), - (13, 258, 1129, 1128, 18446744073709551615, 0, 2), - (13, 259, 1128, 1127, 18446744073709551615, 1, 3), - (13, 1028, 10, 1025, 18446744073709551615, 6, 21), - (13, 1024, 181, 33, 18446744073709551615, 0, 164), - (13, 33, 181, 793, 18446744073709551615, 0, 2), - (13, 286, 799, 796, 18446744073709551615, 2, 8), - (13, 287, 796, 924, 18446744073709551615, 0, 6), - (13, 257, 1130, 29, 18446744073709551615, 0, 1), - (13, 258, 29, 1129, 18446744073709551615, 0, 1), - (13, 259, 1129, 1128, 18446744073709551615, 0, 3), - (13, 1028, 925, 1025, 18446744073709551615, 5, 18), - (13, 1024, 35, 869, 18446744073709551615, 0, 163), - (13, 869, 35, 10, 18446744073709551615, 0, 2), - (13, 286, 796, 924, 18446744073709551615, 5, 8), - (13, 257, 1130, 1129, 18446744073709551615, 0, 1), - (13, 258, 1129, 1128, 18446744073709551615, 1, 2), - (13, 259, 1128, 1127, 18446744073709551615, 2, 3), - (13, 1028, 923, 1025, 18446744073709551615, 18, 27), - (13, 102, 871, 793, 18446744073709551615, 0, 1), - (13, 286, 799, 796, 18446744073709551615, 3, 8), - (13, 287, 796, 924, 18446744073709551615, 1, 6), - (13, 257, 792, 1130, 18446744073709551615, 0, 1), - (13, 258, 1130, 1129, 18446744073709551615, 0, 2), - (13, 259, 1129, 1128, 18446744073709551615, 1, 3), - (13, 1028, 793, 1025, 18446744073709551615, 10, 19), - (13, 30, 1078, 793, 18446744073709551615, 1, 4), - (13, 287, 799, 796, 18446744073709551615, 0, 6), - (13, 257, 1131, 792, 18446744073709551615, 0, 1), - (13, 258, 792, 1130, 18446744073709551615, 0, 1), - (13, 259, 1130, 1129, 18446744073709551615, 0, 3), - (13, 1028, 10, 1025, 18446744073709551615, 7, 21), - (13, 872, 32, 916, 18446744073709551615, 0, 5), - (13, 287, 796, 924, 18446744073709551615, 3, 6), - (13, 257, 1131, 1130, 18446744073709551615, 0, 1), - (13, 258, 1130, 1129, 18446744073709551615, 1, 2), - (13, 259, 1129, 1128, 18446744073709551615, 2, 3), - (13, 1028, 1147, 1025, 18446744073709551615, 14, 26), - (13, 1024, 874, 105, 18446744073709551615, 0, 159), - (13, 105, 874, 10, 18446744073709551615, 0, 1), - (13, 287, 799, 796, 18446744073709551615, 1, 6), - (13, 257, 25, 1131, 18446744073709551615, 0, 1), - (13, 258, 1131, 1130, 18446744073709551615, 0, 2), - (13, 259, 1130, 1129, 18446744073709551615, 1, 3), - (13, 1028, 923, 1025, 18446744073709551615, 19, 27), - (13, 1024, 956, 24, 18446744073709551615, 0, 158), - (13, 24, 956, 925, 18446744073709551615, 0, 1), - (13, 287, 802, 799, 18446744073709551615, 0, 6), - (13, 257, 26, 25, 18446744073709551615, 0, 1), - (13, 258, 25, 1131, 18446744073709551615, 0, 1), - (13, 259, 1131, 1130, 18446744073709551615, 0, 3), - (13, 1028, 793, 1025, 18446744073709551615, 11, 19), - (13, 1024, 29, 875, 18446744073709551615, 0, 157), - (13, 875, 29, 9, 18446744073709551615, 0, 9), - (13, 286, 802, 799, 18446744073709551615, 5, 8), - (13, 287, 799, 796, 18446744073709551615, 3, 6), - (13, 257, 26, 1131, 18446744073709551615, 0, 1), - (13, 258, 1131, 1130, 18446744073709551615, 1, 2), - (13, 259, 1130, 1129, 18446744073709551615, 2, 3), - (13, 1028, 886, 1025, 18446744073709551615, 13, 19), - (13, 1024, 877, 108, 18446744073709551615, 0, 156), - (13, 108, 877, 916, 18446744073709551615, 0, 8), - (13, 287, 802, 799, 18446744073709551615, 1, 6), - (13, 257, 1115, 26, 18446744073709551615, 0, 1), - (13, 258, 26, 1131, 18446744073709551615, 0, 2), - (13, 259, 1131, 1130, 18446744073709551615, 1, 3), - (13, 287, 799, 796, 18446744073709551615, 4, 6), - (13, 1028, 1147, 1025, 18446744073709551615, 15, 26), - (13, 1024, 184, 21, 18446744073709551615, 0, 155), - (13, 21, 184, 9, 18446744073709551615, 0, 5), - (13, 287, 805, 802, 18446744073709551615, 0, 9), - (13, 257, 22, 1115, 18446744073709551615, 0, 1), - (13, 258, 1115, 26, 18446744073709551615, 0, 1), - (13, 259, 26, 1131, 18446744073709551615, 0, 3), - (13, 1028, 923, 1025, 18446744073709551615, 22, 27), - (13, 1024, 792, 878, 18446744073709551615, 0, 154), - (13, 878, 792, 1150, 18446744073709551615, 0, 2), - (13, 257, 22, 26, 18446744073709551615, 0, 1), - (13, 258, 26, 1131, 18446744073709551615, 1, 2), - (13, 259, 1131, 1130, 18446744073709551615, 2, 3), - (13, 287, 799, 796, 18446744073709551615, 5, 6), - (13, 1028, 1088, 1025, 18446744073709551615, 12, 18), - (13, 1024, 880, 111, 18446744073709551615, 0, 153), - (13, 111, 880, 9, 18446744073709551615, 0, 1), - (13, 287, 805, 802, 18446744073709551615, 1, 9), - (13, 257, 840, 22, 18446744073709551615, 0, 1), - (13, 258, 22, 26, 18446744073709551615, 0, 2), - (13, 259, 26, 1131, 18446744073709551615, 1, 3), - (13, 287, 802, 799, 18446744073709551615, 4, 6), - (13, 1028, 886, 1025, 18446744073709551615, 14, 19), - (13, 1024, 1077, 794, 18446744073709551615, 0, 152), - (13, 794, 1077, 1151, 18446744073709551615, 0, 1), - (13, 286, 820, 808, 18446744073709551615, 0, 10), - (13, 287, 808, 805, 18446744073709551615, 0, 10), - (13, 257, 785, 840, 18446744073709551615, 0, 1), - (13, 258, 840, 22, 18446744073709551615, 0, 1), - (13, 259, 22, 26, 18446744073709551615, 0, 6), - (13, 1028, 1147, 1025, 18446744073709551615, 16, 26), - (13, 881, 25, 1151, 18446744073709551615, 0, 9), - (13, 287, 805, 802, 18446744073709551615, 3, 9), - (13, 257, 785, 22, 18446744073709551615, 0, 1), - (13, 258, 22, 26, 18446744073709551615, 1, 2), - (13, 259, 26, 1131, 18446744073709551615, 2, 3), - (13, 1028, 915, 1025, 18446744073709551615, 9, 14), - (13, 114, 883, 1150, 18446744073709551615, 0, 8), - (13, 286, 820, 808, 18446744073709551615, 1, 10), - (13, 287, 808, 805, 18446744073709551615, 1, 10), - (13, 257, 16, 785, 18446744073709551615, 0, 1), - (13, 258, 785, 22, 18446744073709551615, 0, 5), - (13, 259, 22, 26, 18446744073709551615, 1, 6), - (13, 1028, 1088, 1025, 18446744073709551615, 13, 18), - (13, 1113, 187, 1139, 18446744073709551615, 0, 1), - (13, 286, 817, 820, 18446744073709551615, 0, 4), - (13, 257, 1118, 16, 18446744073709551615, 0, 1), - (13, 258, 16, 785, 18446744073709551615, 0, 1), - (13, 259, 785, 22, 18446744073709551615, 0, 4), - (13, 1028, 886, 1025, 18446744073709551615, 15, 19), - (13, 884, 1115, 1139, 18446744073709551615, 0, 3), - (13, 287, 808, 805, 18446744073709551615, 3, 10), - (13, 257, 1118, 785, 18446744073709551615, 0, 3), - (13, 258, 785, 22, 18446744073709551615, 1, 5), - (13, 259, 22, 26, 18446744073709551615, 2, 6), - (13, 1028, 889, 1025, 18446744073709551615, 6, 10), - (13, 117, 119, 1139, 18446744073709551615, 0, 1), - (13, 257, 780, 1118, 18446744073709551615, 0, 2), - (13, 258, 1118, 785, 18446744073709551615, 0, 3), - (13, 259, 785, 22, 18446744073709551615, 1, 4), - (13, 1028, 915, 1025, 18446744073709551615, 10, 14), - (13, 1140, 778, 104, 18446744073709551615, 0, 2), - (13, 286, 820, 808, 18446744073709551615, 5, 10), - (13, 287, 808, 805, 18446744073709551615, 5, 10), - (13, 257, 1118, 785, 18446744073709551615, 1, 3), - (13, 258, 785, 22, 18446744073709551615, 2, 5), - (13, 259, 22, 26, 18446744073709551615, 3, 6), - (13, 115, 118, 780, 18446744073709551615, 0, 3), - (13, 1028, 780, 959, 18446744073709551615, 0, 1), - (13, 1028, 118, 115, 18446744073709551615, 0, 147), - (14, 1028, 115, 118, 18446744073709551615, 0, 3), - (13, 1024, 118, 115, 18446744073709551615, 0, 145), - (13, 115, 118, 1151, 18446744073709551615, 0, 1), - (13, 287, 820, 808, 18446744073709551615, 2, 4), - (13, 257, 780, 1118, 18446744073709551615, 1, 2), - (13, 258, 1118, 785, 18446744073709551615, 1, 3), - (13, 259, 785, 22, 18446744073709551615, 2, 4), - (13, 115, 118, 104, 18446744073709551615, 0, 2), - (13, 286, 820, 808, 18446744073709551615, 7, 10), - (13, 287, 808, 805, 18446744073709551615, 7, 10), - (13, 257, 1118, 785, 18446744073709551615, 2, 3), - (13, 258, 785, 22, 18446744073709551615, 3, 5), - (13, 259, 22, 26, 18446744073709551615, 4, 6), - (13, 1116, 890, 1118, 18446744073709551615, 0, 2), - (13, 1028, 1118, 959, 18446744073709551615, 0, 1), - (13, 1028, 890, 1116, 18446744073709551615, 0, 145), - (14, 1028, 1116, 890, 18446744073709551615, 0, 1), - (13, 1024, 779, 744, 18446744073709551615, 0, 143), - (13, 1024, 890, 1116, 18446744073709551615, 0, 143), - (13, 1116, 890, 1151, 18446744073709551615, 0, 1), - (13, 257, 756, 1118, 18446744073709551615, 0, 1), - (13, 258, 1118, 785, 18446744073709551615, 2, 3), - (13, 259, 785, 22, 18446744073709551615, 3, 4), - (13, 1028, 757, 193, 18446744073709551615, 0, 1), - (13, 1024, 959, 891, 18446744073709551615, 0, 142), - (13, 891, 959, 104, 18446744073709551615, 0, 7), - (13, 286, 820, 808, 18446744073709551615, 9, 10), - (13, 287, 808, 805, 18446744073709551615, 9, 10), - (13, 257, 756, 785, 18446744073709551615, 0, 1), - (13, 258, 785, 22, 18446744073709551615, 4, 5), - (13, 259, 22, 26, 18446744073709551615, 5, 6), - (13, 1028, 22, 1076, 18446744073709551615, 0, 1), - (13, 1024, 193, 892, 18446744073709551615, 0, 141), - (13, 892, 193, 1151, 18446744073709551615, 0, 1), - (13, 287, 1141, 817, 18446744073709551615, 0, 10), - (13, 257, 757, 1118, 18446744073709551615, 0, 1), - (13, 258, 1118, 735, 18446744073709551615, 0, 4), - (13, 259, 735, 756, 18446744073709551615, 0, 4), - (13, 892, 193, 12, 18446744073709551615, 0, 5), - (13, 287, 927, 1141, 18446744073709551615, 0, 10), - (13, 257, 758, 757, 18446744073709551615, 0, 1), - (13, 258, 757, 1118, 18446744073709551615, 0, 1), - (13, 259, 1118, 735, 18446744073709551615, 0, 6), - (13, 1028, 889, 1025, 18446744073709551615, 7, 10), - (13, 893, 780, 12, 18446744073709551615, 0, 1), - (13, 287, 1141, 817, 18446744073709551615, 2, 10), - (13, 257, 758, 1118, 18446744073709551615, 0, 2), - (13, 258, 1118, 735, 18446744073709551615, 1, 4), - (13, 259, 735, 756, 18446744073709551615, 1, 4), - (13, 1028, 757, 962, 18446744073709551615, 0, 1), - (13, 287, 927, 1141, 18446744073709551615, 1, 10), - (13, 257, 760, 758, 18446744073709551615, 0, 1), - (13, 258, 758, 1118, 18446744073709551615, 0, 3), - (13, 259, 1118, 735, 18446744073709551615, 1, 6), - (13, 1028, 896, 1076, 18446744073709551615, 0, 1), - (13, 257, 761, 760, 18446744073709551615, 0, 1), - (13, 258, 760, 758, 18446744073709551615, 0, 1), - (13, 259, 758, 1118, 18446744073709551615, 0, 1), - (13, 1028, 146, 1025, 18446744073709551615, 8, 150), - (13, 286, 832, 927, 18446744073709551615, 3, 10), - (13, 257, 761, 758, 18446744073709551615, 0, 1), - (13, 258, 758, 1118, 18446744073709551615, 1, 3), - (13, 259, 1118, 735, 18446744073709551615, 2, 6), - (13, 1028, 1095, 734, 18446744073709551615, 0, 1), - (13, 286, 927, 1141, 18446744073709551615, 5, 10), - (13, 257, 758, 1118, 18446744073709551615, 1, 2), - (13, 258, 1118, 735, 18446744073709551615, 2, 4), - (13, 259, 735, 756, 18446744073709551615, 2, 4), - (13, 1095, 762, 756, 18446744073709551615, 0, 7), - (13, 1028, 756, 757, 18446744073709551615, 0, 1), - (13, 1028, 762, 1095, 18446744073709551615, 0, 136), - (14, 1028, 1095, 762, 18446744073709551615, 0, 1), - (13, 1024, 762, 1095, 18446744073709551615, 0, 134), - (13, 1095, 762, 12, 18446744073709551615, 0, 1), - (13, 286, 832, 927, 18446744073709551615, 4, 10), - (13, 287, 927, 1141, 18446744073709551615, 4, 10), - (13, 257, 736, 758, 18446744073709551615, 0, 1), - (13, 258, 758, 1118, 18446744073709551615, 2, 3), - (13, 259, 1118, 735, 18446744073709551615, 3, 6), - (13, 1028, 1118, 902, 18446744073709551615, 0, 1), - (13, 1024, 757, 900, 18446744073709551615, 0, 133), - (13, 900, 757, 12, 18446744073709551615, 0, 5), - (13, 286, 927, 1141, 18446744073709551615, 7, 10), - (13, 257, 736, 1118, 18446744073709551615, 0, 1), - (13, 258, 1118, 735, 18446744073709551615, 3, 4), - (13, 259, 735, 756, 18446744073709551615, 3, 4), - (13, 1028, 22, 190, 18446744073709551615, 0, 1), - (13, 1024, 902, 133, 18446744073709551615, 0, 132), - (13, 133, 902, 788, 18446744073709551615, 0, 4), - (13, 286, 832, 927, 18446744073709551615, 5, 10), - (13, 257, 738, 736, 18446744073709551615, 0, 1), - (13, 258, 736, 1118, 18446744073709551615, 0, 2), - (13, 259, 1118, 735, 18446744073709551615, 4, 6), - (13, 1028, 756, 761, 18446744073709551615, 0, 1), - (13, 1024, 190, 737, 18446744073709551615, 0, 131), - (13, 737, 190, 12, 18446744073709551615, 0, 4), - (13, 286, 826, 832, 18446744073709551615, 1, 6), - (13, 287, 832, 927, 18446744073709551615, 1, 6), - (13, 257, 739, 738, 18446744073709551615, 0, 1), - (13, 258, 738, 736, 18446744073709551615, 0, 1), - (13, 259, 736, 1118, 18446744073709551615, 0, 3), - (13, 1028, 1118, 905, 18446744073709551615, 0, 1), - (13, 1024, 761, 903, 18446744073709551615, 0, 130), - (13, 903, 761, 787, 18446744073709551615, 0, 4), - (13, 287, 927, 1141, 18446744073709551615, 7, 10), - (13, 257, 739, 736, 18446744073709551615, 0, 1), - (13, 258, 736, 1118, 18446744073709551615, 1, 2), - (13, 259, 1118, 735, 18446744073709551615, 5, 6), - (13, 1028, 22, 1075, 18446744073709551615, 0, 1), - (13, 1024, 905, 136, 18446744073709551615, 0, 129), - (13, 136, 905, 787, 18446744073709551615, 0, 1), - (13, 286, 826, 832, 18446744073709551615, 2, 6), - (13, 287, 832, 927, 18446744073709551615, 2, 6), - (13, 257, 741, 739, 18446744073709551615, 0, 1), - (13, 258, 739, 736, 18446744073709551615, 0, 2), - (13, 259, 736, 1118, 18446744073709551615, 1, 3), - (13, 1028, 756, 758, 18446744073709551615, 0, 1), - (13, 1024, 1075, 740, 18446744073709551615, 0, 128), - (13, 740, 1075, 143, 18446744073709551615, 0, 1), - (13, 286, 829, 826, 18446744073709551615, 0, 4), - (13, 287, 826, 832, 18446744073709551615, 0, 4), - (13, 257, 742, 741, 18446744073709551615, 0, 1), - (13, 258, 741, 739, 18446744073709551615, 0, 1), - (13, 259, 739, 736, 18446744073709551615, 0, 2), - (13, 1028, 1118, 745, 18446744073709551615, 0, 1), - (13, 1024, 758, 906, 18446744073709551615, 0, 127), - (13, 906, 758, 928, 18446744073709551615, 0, 2), - (13, 286, 826, 832, 18446744073709551615, 4, 6), - (13, 257, 742, 739, 18446744073709551615, 0, 1), - (13, 258, 739, 736, 18446744073709551615, 1, 2), - (13, 259, 736, 1118, 18446744073709551615, 2, 3), - (13, 1028, 22, 965, 18446744073709551615, 0, 1), - (13, 1024, 745, 140, 18446744073709551615, 0, 126), - (13, 140, 745, 143, 18446744073709551615, 0, 1), - (13, 286, 823, 814, 18446744073709551615, 0, 4), - (13, 257, 743, 741, 18446744073709551615, 0, 1), - (13, 258, 741, 836, 18446744073709551615, 0, 1), - (13, 259, 836, 742, 18446744073709551615, 0, 1), - (13, 286, 814, 829, 18446744073709551615, 1, 3), - (13, 287, 829, 826, 18446744073709551615, 1, 3), - (13, 257, 741, 836, 18446744073709551615, 0, 1), - (13, 258, 836, 742, 18446744073709551615, 0, 1), - (13, 259, 742, 739, 18446744073709551615, 0, 2), - (13, 910, 139, 1118, 18446744073709551615, 0, 7), - (13, 1028, 1118, 919, 18446744073709551615, 0, 1), - (13, 1028, 139, 910, 18446744073709551615, 0, 126), - (14, 1028, 910, 139, 18446744073709551615, 0, 1), - (13, 1024, 139, 910, 18446744073709551615, 0, 124), - (13, 910, 139, 1132, 18446744073709551615, 0, 2), - (13, 286, 829, 826, 18446744073709551615, 2, 4), - (13, 257, 741, 742, 18446744073709551615, 0, 1), - (13, 258, 742, 739, 18446744073709551615, 0, 1), - (13, 259, 739, 736, 18446744073709551615, 1, 2), - (13, 1028, 22, 1074, 18446744073709551615, 0, 1), - (13, 1024, 919, 142, 18446744073709551615, 0, 123), - (13, 142, 919, 928, 18446744073709551615, 0, 1), - (13, 286, 814, 829, 18446744073709551615, 2, 3), - (13, 257, 1143, 741, 18446744073709551615, 0, 1), - (13, 258, 741, 742, 18446744073709551615, 0, 1), - (13, 259, 742, 739, 18446744073709551615, 1, 2), - (13, 1028, 756, 743, 18446744073709551615, 0, 1), - (13, 1024, 1074, 1144, 18446744073709551615, 0, 122), - (13, 1144, 1074, 928, 18446744073709551615, 0, 4), - (13, 286, 1121, 1120, 18446744073709551615, 0, 10), - (13, 287, 1120, 823, 18446744073709551615, 0, 10), - (13, 257, 43, 836, 18446744073709551615, 0, 1), - (13, 258, 836, 971, 18446744073709551615, 0, 1), - (13, 259, 971, 1143, 18446744073709551615, 0, 6), - (13, 286, 1120, 823, 18446744073709551615, 1, 9), - (13, 287, 823, 814, 18446744073709551615, 1, 9), - (13, 257, 43, 971, 18446744073709551615, 0, 2), - (13, 258, 971, 1143, 18446744073709551615, 0, 3), - (13, 259, 1143, 741, 18446744073709551615, 0, 3), - (13, 1028, 742, 968, 18446744073709551615, 0, 1), - (13, 286, 1121, 1120, 18446744073709551615, 1, 10), - (13, 287, 1120, 823, 18446744073709551615, 1, 10), - (13, 257, 1152, 43, 18446744073709551615, 0, 1), - (13, 258, 43, 971, 18446744073709551615, 0, 3), - (13, 259, 971, 1143, 18446744073709551615, 1, 6), - (13, 1028, 1143, 743, 18446744073709551615, 0, 1), - (13, 287, 1121, 1120, 18446744073709551615, 0, 8), - (13, 257, 746, 1152, 18446744073709551615, 0, 1), - (13, 258, 1152, 43, 18446744073709551615, 0, 1), - (13, 259, 43, 971, 18446744073709551615, 0, 1), - (13, 1028, 43, 145, 18446744073709551615, 0, 1), - (13, 257, 746, 43, 18446744073709551615, 0, 1), - (13, 258, 43, 971, 18446744073709551615, 1, 3), - (13, 259, 971, 1143, 18446744073709551615, 2, 6), - (13, 287, 823, 814, 18446744073709551615, 3, 9), - (13, 1028, 742, 15, 18446744073709551615, 0, 1), - (13, 286, 1120, 823, 18446744073709551615, 4, 9), - (13, 257, 43, 971, 18446744073709551615, 1, 2), - (13, 258, 971, 1143, 18446744073709551615, 1, 3), - (13, 259, 1143, 741, 18446744073709551615, 1, 3), - (13, 911, 1146, 756, 18446744073709551615, 0, 5), - (13, 1028, 756, 836, 18446744073709551615, 0, 1), - (13, 1028, 1146, 911, 18446744073709551615, 0, 118), - (14, 1028, 911, 1146, 18446744073709551615, 0, 1), - (13, 1024, 1146, 911, 18446744073709551615, 0, 116), - (13, 911, 1146, 796, 18446744073709551615, 0, 1), - (13, 286, 1121, 1120, 18446744073709551615, 4, 10), - (13, 287, 1120, 823, 18446744073709551615, 4, 10), - (13, 257, 1136, 43, 18446744073709551615, 0, 1), - (13, 258, 43, 971, 18446744073709551615, 2, 3), - (13, 259, 971, 1143, 18446744073709551615, 3, 6), - (13, 1028, 1118, 920, 18446744073709551615, 0, 1), - (13, 1024, 836, 918, 18446744073709551615, 0, 115), - (13, 918, 836, 799, 18446744073709551615, 0, 2), - (13, 287, 823, 814, 18446744073709551615, 6, 9), - (13, 257, 1136, 971, 18446744073709551615, 0, 1), - (13, 258, 971, 1143, 18446744073709551615, 2, 3), - (13, 259, 1143, 741, 18446744073709551615, 2, 3), - (13, 1028, 22, 196, 18446744073709551615, 0, 1), - (13, 1024, 920, 151, 18446744073709551615, 0, 114), - (13, 151, 920, 796, 18446744073709551615, 0, 1), - (13, 286, 1121, 1120, 18446744073709551615, 5, 10), - (13, 287, 1120, 823, 18446744073709551615, 5, 10), - (13, 257, 1135, 1136, 18446744073709551615, 0, 1), - (13, 258, 1136, 971, 18446744073709551615, 0, 2), - (13, 259, 971, 1143, 18446744073709551615, 4, 6), - (13, 1028, 756, 746, 18446744073709551615, 0, 1), - (13, 1024, 196, 783, 18446744073709551615, 0, 113), - (13, 783, 196, 799, 18446744073709551615, 0, 1), - (13, 287, 1121, 1120, 18446744073709551615, 1, 8), - (13, 257, 1114, 1135, 18446744073709551615, 0, 1), - (13, 258, 1135, 1136, 18446744073709551615, 0, 1), - (13, 259, 1136, 971, 18446744073709551615, 0, 3), - (13, 1028, 1118, 157, 18446744073709551615, 0, 1), - (13, 1024, 746, 921, 18446744073709551615, 0, 112), - (13, 921, 746, 802, 18446744073709551615, 0, 1), - (13, 286, 1121, 1120, 18446744073709551615, 7, 10), - (13, 257, 1114, 1136, 18446744073709551615, 0, 1), - (13, 258, 1136, 971, 18446744073709551615, 1, 2), - (13, 259, 971, 1143, 18446744073709551615, 5, 6), - (13, 1028, 22, 1073, 18446744073709551615, 0, 1), - (13, 1024, 157, 154, 18446744073709551615, 0, 111), - (13, 154, 157, 802, 18446744073709551615, 0, 4), - (13, 286, 1122, 1121, 18446744073709551615, 2, 8), - (13, 287, 1121, 1120, 18446744073709551615, 2, 8), - (13, 257, 782, 1114, 18446744073709551615, 0, 1), - (13, 258, 1114, 1136, 18446744073709551615, 0, 2), - (13, 259, 1136, 971, 18446744073709551615, 1, 3), - (13, 287, 1120, 823, 18446744073709551615, 8, 10), - (13, 1028, 756, 43, 18446744073709551615, 0, 1), - (13, 1024, 1073, 1138, 18446744073709551615, 0, 110), - (13, 1138, 1073, 802, 18446744073709551615, 0, 1), - (13, 286, 1125, 1124, 18446744073709551615, 0, 9), - (13, 257, 1133, 1135, 18446744073709551615, 0, 1), - (13, 258, 1135, 160, 18446744073709551615, 0, 1), - (13, 259, 160, 782, 18446744073709551615, 0, 1), - (13, 287, 1121, 1120, 18446744073709551615, 3, 8), - (13, 257, 160, 1114, 18446744073709551615, 0, 1), - (13, 258, 1114, 1136, 18446744073709551615, 1, 2), - (13, 259, 1136, 971, 18446744073709551615, 2, 3), - (13, 153, 155, 22, 18446744073709551615, 0, 3), - (13, 1028, 22, 67, 18446744073709551615, 0, 1), - (13, 1028, 155, 153, 18446744073709551615, 0, 110), - (14, 1028, 153, 155, 18446744073709551615, 0, 1), - (13, 1024, 155, 153, 18446744073709551615, 0, 108), - (13, 153, 155, 805, 18446744073709551615, 0, 4), - (13, 286, 1123, 1122, 18446744073709551615, 0, 9), - (13, 287, 1122, 1121, 18446744073709551615, 0, 9), - (13, 257, 19, 160, 18446744073709551615, 0, 1), - (13, 258, 160, 1114, 18446744073709551615, 0, 4), - (13, 259, 1114, 1136, 18446744073709551615, 0, 4), - (13, 1028, 756, 1133, 18446744073709551615, 0, 1), - (13, 1024, 67, 1135, 18446744073709551615, 0, 107), - (13, 1135, 67, 808, 18446744073709551615, 0, 4), - (13, 287, 1125, 1124, 18446744073709551615, 0, 7), - (13, 257, 31, 782, 18446744073709551615, 0, 1), - (13, 258, 782, 929, 18446744073709551615, 0, 1), - (13, 259, 929, 19, 18446744073709551615, 0, 1), - (13, 257, 929, 160, 18446744073709551615, 0, 1), - (13, 258, 160, 1114, 18446744073709551615, 1, 4), - (13, 259, 1114, 1136, 18446744073709551615, 1, 4), - (13, 935, 158, 22, 18446744073709551615, 0, 3), - (13, 1028, 22, 1001, 18446744073709551615, 0, 1), - (13, 1028, 158, 935, 18446744073709551615, 0, 107), - (14, 1028, 935, 158, 18446744073709551615, 0, 4), - (13, 1024, 158, 935, 18446744073709551615, 0, 105), - (13, 935, 158, 808, 18446744073709551615, 0, 4), - (13, 287, 1123, 1122, 18446744073709551615, 1, 10), - (13, 257, 34, 929, 18446744073709551615, 0, 2), - (13, 258, 929, 160, 18446744073709551615, 0, 2), - (13, 259, 160, 1114, 18446744073709551615, 0, 5), - (13, 1028, 756, 31, 18446744073709551615, 0, 1), - (13, 782, 1001, 817, 18446744073709551615, 0, 1), - (13, 286, 1125, 1124, 18446744073709551615, 2, 9), - (13, 257, 37, 34, 18446744073709551615, 0, 2), - (13, 258, 34, 929, 18446744073709551615, 0, 2), - (13, 259, 929, 160, 18446744073709551615, 0, 2), - (13, 1028, 1118, 49, 18446744073709551615, 0, 1), - (13, 933, 31, 817, 18446744073709551615, 0, 4), - (13, 287, 1125, 1124, 18446744073709551615, 1, 7), - (13, 257, 19, 37, 18446744073709551615, 0, 1), - (13, 258, 37, 34, 18446744073709551615, 0, 1), - (13, 259, 34, 929, 18446744073709551615, 0, 1), - (13, 287, 1124, 1123, 18446744073709551615, 4, 9), - (13, 257, 37, 34, 18446744073709551615, 1, 2), - (13, 258, 34, 929, 18446744073709551615, 1, 2), - (13, 259, 929, 160, 18446744073709551615, 1, 2), - (13, 161, 165, 756, 18446744073709551615, 0, 7), - (13, 1028, 756, 49, 18446744073709551615, 0, 1), - (13, 1028, 165, 161, 18446744073709551615, 0, 103), - (14, 1028, 161, 165, 18446744073709551615, 0, 4), - (13, 1024, 165, 161, 18446744073709551615, 0, 101), - (13, 161, 165, 1141, 18446744073709551615, 0, 3), - (13, 287, 1123, 1122, 18446744073709551615, 4, 10), - (13, 257, 34, 929, 18446744073709551615, 1, 2), - (13, 258, 929, 160, 18446744073709551615, 1, 2), - (13, 259, 160, 1114, 18446744073709551615, 1, 5), - (13, 162, 164, 1130, 18446744073709551615, 0, 5), - (13, 1028, 1130, 936, 18446744073709551615, 0, 1), - (13, 1028, 164, 162, 18446744073709551615, 0, 102), - (13, 19, 49, 26, 18446744073709551615, 0, 2), - (14, 1028, 162, 164, 18446744073709551615, 0, 4), - (13, 1024, 49, 19, 18446744073709551615, 0, 100), - (13, 1024, 164, 162, 18446744073709551615, 0, 100), - (13, 19, 49, 817, 18446744073709551615, 0, 2), - (13, 162, 164, 820, 18446744073709551615, 0, 2), - (13, 287, 1122, 1121, 18446744073709551615, 4, 9), - (13, 257, 34, 160, 18446744073709551615, 0, 2), - (13, 258, 160, 1114, 18446744073709551615, 2, 4), - (13, 259, 1114, 1136, 18446744073709551615, 2, 4), - (13, 1028, 1126, 199, 18446744073709551615, 0, 1), - (13, 162, 164, 1131, 18446744073709551615, 0, 1), - (13, 1024, 936, 167, 18446744073709551615, 0, 99), - (13, 162, 164, 820, 18446744073709551615, 1, 2), - (13, 167, 936, 808, 18446744073709551615, 0, 1), - (13, 286, 1124, 1123, 18446744073709551615, 5, 10), - (13, 287, 1123, 1122, 18446744073709551615, 5, 10), - (13, 257, 55, 34, 18446744073709551615, 0, 1), - (13, 258, 34, 160, 18446744073709551615, 0, 3), - (13, 259, 160, 1114, 18446744073709551615, 2, 5), - (13, 1028, 1128, 37, 18446744073709551615, 0, 1), - (13, 167, 936, 26, 18446744073709551615, 0, 6), - (13, 1024, 199, 52, 18446744073709551615, 0, 98), - (13, 167, 936, 820, 18446744073709551615, 0, 4), - (13, 52, 199, 808, 18446744073709551615, 0, 4), - (13, 286, 1125, 1124, 18446744073709551615, 5, 9), - (13, 287, 1124, 1123, 18446744073709551615, 5, 9), - (13, 257, 58, 55, 18446744073709551615, 0, 1), - (13, 258, 55, 34, 18446744073709551615, 0, 1), - (13, 259, 34, 160, 18446744073709551615, 0, 2), - (13, 1028, 1130, 168, 18446744073709551615, 0, 1), - (13, 52, 199, 22, 18446744073709551615, 0, 2), - (13, 1024, 37, 937, 18446744073709551615, 0, 97), - (13, 52, 199, 927, 18446744073709551615, 0, 6), - (13, 937, 37, 1141, 18446744073709551615, 0, 6), - (13, 286, 1124, 1123, 18446744073709551615, 7, 10), - (13, 287, 1123, 1122, 18446744073709551615, 7, 10), - (13, 257, 58, 34, 18446744073709551615, 0, 1), - (13, 258, 34, 160, 18446744073709551615, 1, 3), - (13, 259, 160, 1114, 18446744073709551615, 3, 5), - (13, 1028, 1126, 64, 18446744073709551615, 0, 1), - (13, 937, 37, 26, 18446744073709551615, 0, 1), - (13, 1024, 168, 170, 18446744073709551615, 0, 96), - (13, 937, 37, 1141, 18446744073709551615, 1, 6), - (13, 170, 168, 817, 18446744073709551615, 0, 5), - (13, 257, 34, 160, 18446744073709551615, 1, 2), - (13, 258, 160, 1114, 18446744073709551615, 3, 4), - (13, 259, 1114, 1136, 18446744073709551615, 3, 4), - (13, 156, 61, 1121, 18446744073709551615, 0, 1), - (13, 1028, 1121, 929, 18446744073709551615, 0, 1), - (13, 1028, 61, 156, 18446744073709551615, 0, 97), - (13, 170, 168, 26, 18446744073709551615, 0, 6), - (13, 55, 64, 1131, 18446744073709551615, 0, 6), - (14, 1028, 156, 61, 18446744073709551615, 0, 4), - (13, 1024, 64, 55, 18446744073709551615, 0, 95), - (13, 1024, 61, 156, 18446744073709551615, 0, 95), - (13, 170, 168, 817, 18446744073709551615, 1, 5), - (13, 55, 64, 820, 18446744073709551615, 0, 4), - (13, 156, 61, 808, 18446744073709551615, 0, 4), - (13, 257, 70, 34, 18446744073709551615, 0, 1), - (13, 258, 34, 160, 18446744073709551615, 2, 3), - (13, 259, 160, 1114, 18446744073709551615, 4, 5), - (13, 1028, 1123, 1072, 18446744073709551615, 0, 1), - (13, 156, 61, 26, 18446744073709551615, 0, 1), - (13, 1024, 929, 1082, 18446744073709551615, 0, 94), - (13, 156, 61, 820, 18446744073709551615, 0, 1), - (13, 1082, 929, 808, 18446744073709551615, 0, 1), - (13, 286, 1125, 1124, 18446744073709551615, 6, 9), - (13, 287, 1124, 1123, 18446744073709551615, 6, 9), - (13, 257, 58, 70, 18446744073709551615, 0, 1), - (13, 258, 70, 34, 18446744073709551615, 0, 1), - (13, 259, 34, 160, 18446744073709551615, 1, 2), - (13, 1082, 929, 1141, 18446744073709551615, 0, 2), - (13, 287, 1125, 1124, 18446744073709551615, 2, 7), - (13, 257, 73, 58, 18446744073709551615, 0, 1), - (13, 258, 58, 70, 18446744073709551615, 0, 2), - (13, 259, 70, 34, 18446744073709551615, 0, 2), - (13, 1028, 1128, 1072, 18446744073709551615, 0, 1), - (13, 1024, 974, 942, 18446744073709551615, 0, 92), - (13, 942, 974, 1141, 18446744073709551615, 0, 1), - (13, 287, 1126, 1125, 18446744073709551615, 0, 6), - (13, 257, 76, 73, 18446744073709551615, 0, 1), - (13, 258, 73, 58, 18446744073709551615, 0, 1), - (13, 259, 58, 70, 18446744073709551615, 0, 3), - (13, 1028, 1130, 945, 18446744073709551615, 0, 1), - (13, 1024, 1072, 943, 18446744073709551615, 0, 91), - (13, 943, 1072, 832, 18446744073709551615, 0, 2), - (13, 286, 1126, 1125, 18446744073709551615, 4, 7), - (13, 287, 1125, 1124, 18446744073709551615, 4, 7), - (13, 257, 76, 58, 18446744073709551615, 0, 1), - (13, 258, 58, 70, 18446744073709551615, 1, 2), - (13, 259, 70, 34, 18446744073709551615, 1, 2), - (13, 1028, 1126, 202, 18446744073709551615, 0, 1), - (13, 176, 945, 927, 18446744073709551615, 0, 1), - (13, 286, 1127, 1126, 18446744073709551615, 1, 6), - (13, 257, 82, 76, 18446744073709551615, 0, 1), - (13, 258, 76, 58, 18446744073709551615, 0, 2), - (13, 259, 58, 70, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1004, 18446744073709551615, 0, 1), - (13, 1024, 202, 79, 18446744073709551615, 0, 89), - (13, 79, 202, 832, 18446744073709551615, 0, 1), - (13, 257, 85, 82, 18446744073709551615, 0, 1), - (13, 258, 82, 76, 18446744073709551615, 0, 1), - (13, 259, 76, 58, 18446744073709551615, 0, 3), - (13, 1028, 1130, 948, 18446744073709551615, 0, 1), - (13, 1024, 1004, 946, 18446744073709551615, 0, 88), - (13, 946, 1004, 826, 18446744073709551615, 0, 3), - (13, 287, 1126, 1125, 18446744073709551615, 3, 6), - (13, 257, 85, 76, 18446744073709551615, 0, 1), - (13, 258, 76, 58, 18446744073709551615, 1, 2), - (13, 259, 58, 70, 18446744073709551615, 2, 3), - (13, 287, 1125, 1124, 18446744073709551615, 6, 7), - (13, 1028, 1126, 1071, 18446744073709551615, 0, 1), - (13, 1024, 948, 179, 18446744073709551615, 0, 87), - (13, 179, 948, 832, 18446744073709551615, 0, 2), - (13, 286, 1128, 1127, 18446744073709551615, 1, 6), - (13, 257, 91, 85, 18446744073709551615, 0, 1), - (13, 258, 85, 76, 18446744073709551615, 0, 2), - (13, 259, 76, 58, 18446744073709551615, 1, 3), - (13, 1028, 1128, 73, 18446744073709551615, 0, 1), - (13, 1024, 1071, 88, 18446744073709551615, 0, 86), - (13, 88, 1071, 826, 18446744073709551615, 0, 1), - (13, 257, 94, 91, 18446744073709551615, 0, 1), - (13, 258, 91, 85, 18446744073709551615, 0, 1), - (13, 259, 85, 76, 18446744073709551615, 0, 3), - (13, 1028, 1130, 951, 18446744073709551615, 0, 1), - (13, 1024, 73, 949, 18446744073709551615, 0, 85), - (13, 949, 73, 814, 18446744073709551615, 0, 3), - (13, 257, 94, 85, 18446744073709551615, 0, 1), - (13, 258, 85, 76, 18446744073709551615, 1, 2), - (13, 259, 76, 58, 18446744073709551615, 2, 3), - (13, 1028, 1126, 977, 18446744073709551615, 0, 1), - (13, 1024, 951, 182, 18446744073709551615, 0, 84), - (13, 182, 951, 829, 18446744073709551615, 0, 2), - (13, 286, 1129, 1128, 18446744073709551615, 1, 6), - (13, 287, 1128, 1127, 18446744073709551615, 1, 6), - (13, 257, 100, 94, 18446744073709551615, 0, 1), - (13, 258, 94, 85, 18446744073709551615, 0, 2), - (13, 259, 85, 76, 18446744073709551615, 1, 3), - (13, 1028, 1128, 82, 18446744073709551615, 0, 1), - (13, 1024, 977, 97, 18446744073709551615, 0, 83), - (13, 97, 977, 826, 18446744073709551615, 0, 1), - (13, 286, 1130, 1129, 18446744073709551615, 0, 6), - (13, 287, 1129, 1128, 18446744073709551615, 0, 6), - (13, 257, 103, 100, 18446744073709551615, 0, 1), - (13, 258, 100, 94, 18446744073709551615, 0, 1), - (13, 259, 94, 85, 18446744073709551615, 0, 3), - (13, 1028, 1130, 954, 18446744073709551615, 0, 1), - (13, 952, 82, 814, 18446744073709551615, 0, 3), - (13, 286, 1129, 1128, 18446744073709551615, 3, 6), - (13, 257, 103, 94, 18446744073709551615, 0, 1), - (13, 258, 94, 85, 18446744073709551615, 1, 2), - (13, 259, 85, 76, 18446744073709551615, 2, 3), - (13, 1028, 1126, 205, 18446744073709551615, 0, 1), - (13, 1024, 954, 185, 18446744073709551615, 0, 81), - (13, 185, 954, 829, 18446744073709551615, 0, 2), - (13, 286, 1130, 1129, 18446744073709551615, 1, 6), - (13, 287, 1129, 1128, 18446744073709551615, 1, 6), - (13, 257, 109, 103, 18446744073709551615, 0, 1), - (13, 258, 103, 94, 18446744073709551615, 0, 2), - (13, 259, 94, 85, 18446744073709551615, 1, 3), - (13, 1028, 1128, 91, 18446744073709551615, 0, 1), - (13, 1024, 205, 106, 18446744073709551615, 0, 80), - (13, 106, 205, 823, 18446744073709551615, 0, 1), - (13, 257, 120, 109, 18446744073709551615, 0, 1), - (13, 258, 109, 103, 18446744073709551615, 0, 1), - (13, 259, 103, 94, 18446744073709551615, 0, 3), - (13, 1028, 1130, 957, 18446744073709551615, 0, 1), - (13, 955, 91, 1120, 18446744073709551615, 0, 1), - (13, 286, 1130, 1129, 18446744073709551615, 3, 6), - (13, 287, 1129, 1128, 18446744073709551615, 3, 6), - (13, 257, 120, 103, 18446744073709551615, 0, 1), - (13, 258, 103, 94, 18446744073709551615, 1, 2), - (13, 259, 94, 85, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1070, 18446744073709551615, 0, 1), - (13, 1024, 957, 188, 18446744073709551615, 0, 78), - (13, 188, 957, 1120, 18446744073709551615, 0, 2), - (13, 286, 1131, 1130, 18446744073709551615, 1, 6), - (13, 257, 122, 120, 18446744073709551615, 0, 1), - (13, 258, 120, 103, 18446744073709551615, 0, 2), - (13, 259, 103, 94, 18446744073709551615, 1, 3), - (13, 1028, 1128, 100, 18446744073709551615, 0, 1), - (13, 1024, 1070, 112, 18446744073709551615, 0, 77), - (13, 112, 1070, 1120, 18446744073709551615, 0, 1), - (13, 257, 124, 122, 18446744073709551615, 0, 1), - (13, 258, 122, 120, 18446744073709551615, 0, 1), - (13, 259, 120, 103, 18446744073709551615, 0, 3), - (13, 1028, 1130, 960, 18446744073709551615, 0, 1), - (13, 958, 100, 1120, 18446744073709551615, 0, 1), - (13, 287, 1130, 1129, 18446744073709551615, 3, 6), - (13, 257, 124, 120, 18446744073709551615, 0, 1), - (13, 258, 120, 103, 18446744073709551615, 1, 2), - (13, 259, 103, 94, 18446744073709551615, 2, 3), - (13, 1028, 1126, 980, 18446744073709551615, 0, 1), - (13, 1024, 960, 191, 18446744073709551615, 0, 75), - (13, 191, 960, 1120, 18446744073709551615, 0, 1), - (13, 286, 26, 1131, 18446744073709551615, 1, 6), - (13, 287, 1131, 1130, 18446744073709551615, 1, 6), - (13, 257, 134, 124, 18446744073709551615, 0, 1), - (13, 258, 124, 120, 18446744073709551615, 0, 2), - (13, 259, 120, 103, 18446744073709551615, 1, 3), - (13, 1028, 1128, 109, 18446744073709551615, 0, 1), - (13, 131, 980, 1121, 18446744073709551615, 0, 1), - (13, 257, 137, 134, 18446744073709551615, 0, 1), - (13, 258, 134, 124, 18446744073709551615, 0, 1), - (13, 259, 124, 120, 18446744073709551615, 0, 3), - (13, 1028, 1130, 963, 18446744073709551615, 0, 1), - (13, 961, 109, 1123, 18446744073709551615, 0, 3), - (13, 257, 137, 124, 18446744073709551615, 0, 1), - (13, 258, 124, 120, 18446744073709551615, 1, 2), - (13, 259, 120, 103, 18446744073709551615, 2, 3), - (13, 1028, 1126, 208, 18446744073709551615, 0, 1), - (13, 1024, 963, 194, 18446744073709551615, 0, 72), - (13, 194, 963, 1122, 18446744073709551615, 0, 2), - (13, 286, 22, 26, 18446744073709551615, 1, 6), - (13, 257, 1091, 137, 18446744073709551615, 0, 1), - (13, 258, 137, 124, 18446744073709551615, 0, 2), - (13, 259, 124, 120, 18446744073709551615, 1, 3), - (13, 1028, 1128, 122, 18446744073709551615, 0, 1), - (13, 1024, 208, 1096, 18446744073709551615, 0, 71), - (13, 1096, 208, 1123, 18446744073709551615, 0, 1), - (13, 257, 141, 1091, 18446744073709551615, 0, 1), - (13, 258, 1091, 137, 18446744073709551615, 0, 1), - (13, 259, 137, 124, 18446744073709551615, 0, 3), - (13, 1028, 1130, 966, 18446744073709551615, 0, 1), - (13, 964, 122, 1124, 18446744073709551615, 0, 2), - (13, 287, 26, 1131, 18446744073709551615, 3, 6), - (13, 257, 141, 137, 18446744073709551615, 0, 1), - (13, 258, 137, 124, 18446744073709551615, 1, 2), - (13, 259, 124, 120, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1069, 18446744073709551615, 0, 1), - (13, 1024, 966, 197, 18446744073709551615, 0, 69), - (13, 197, 966, 1123, 18446744073709551615, 0, 1), - (13, 286, 785, 22, 18446744073709551615, 1, 6), - (13, 287, 22, 26, 18446744073709551615, 1, 6), - (13, 257, 152, 141, 18446744073709551615, 0, 1), - (13, 258, 141, 137, 18446744073709551615, 0, 2), - (13, 259, 137, 124, 18446744073709551615, 1, 3), - (13, 1028, 1128, 134, 18446744073709551615, 0, 1), - (13, 1024, 1069, 149, 18446744073709551615, 0, 68), - (13, 149, 1069, 1124, 18446744073709551615, 0, 2), - (13, 287, 785, 22, 18446744073709551615, 0, 6), - (13, 257, 912, 152, 18446744073709551615, 0, 1), - (13, 258, 152, 141, 18446744073709551615, 0, 1), - (13, 259, 141, 137, 18446744073709551615, 0, 3), - (13, 1028, 1130, 969, 18446744073709551615, 0, 1), - (13, 1024, 134, 967, 18446744073709551615, 0, 67), - (13, 967, 134, 1126, 18446744073709551615, 0, 2), - (13, 286, 785, 22, 18446744073709551615, 3, 6), - (13, 257, 912, 141, 18446744073709551615, 0, 1), - (13, 258, 141, 137, 18446744073709551615, 1, 2), - (13, 259, 137, 124, 18446744073709551615, 2, 3), - (13, 1028, 1126, 983, 18446744073709551615, 0, 1), - (13, 1024, 969, 200, 18446744073709551615, 0, 66), - (13, 200, 969, 1125, 18446744073709551615, 0, 1), - (13, 286, 756, 785, 18446744073709551615, 1, 6), - (13, 287, 785, 22, 18446744073709551615, 1, 6), - (13, 257, 173, 912, 18446744073709551615, 0, 1), - (13, 258, 912, 141, 18446744073709551615, 0, 2), - (13, 259, 141, 137, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1091, 18446744073709551615, 0, 1), - (13, 159, 983, 1126, 18446744073709551615, 0, 1), - (13, 286, 735, 756, 18446744073709551615, 0, 6), - (13, 287, 756, 785, 18446744073709551615, 0, 6), - (13, 257, 1083, 173, 18446744073709551615, 0, 1), - (13, 258, 173, 912, 18446744073709551615, 0, 1), - (13, 259, 912, 141, 18446744073709551615, 0, 3), - (13, 1028, 1130, 972, 18446744073709551615, 0, 1), - (13, 1024, 1091, 970, 18446744073709551615, 0, 64), - (13, 970, 1091, 1127, 18446744073709551615, 0, 3), - (13, 257, 1083, 912, 18446744073709551615, 0, 1), - (13, 258, 912, 141, 18446744073709551615, 1, 2), - (13, 259, 141, 137, 18446744073709551615, 2, 3), - (13, 1028, 1126, 211, 18446744073709551615, 0, 1), - (13, 203, 972, 1126, 18446744073709551615, 1, 2), - (13, 287, 756, 785, 18446744073709551615, 1, 6), - (13, 257, 177, 1083, 18446744073709551615, 0, 1), - (13, 258, 1083, 912, 18446744073709551615, 0, 2), - (13, 259, 912, 141, 18446744073709551615, 1, 3), - (13, 1028, 1128, 152, 18446744073709551615, 0, 1), - (13, 1024, 211, 174, 18446744073709551615, 0, 62), - (13, 174, 211, 1127, 18446744073709551615, 0, 1), - (13, 257, 180, 177, 18446744073709551615, 0, 1), - (13, 258, 177, 1083, 18446744073709551615, 0, 1), - (13, 259, 1083, 912, 18446744073709551615, 0, 3), - (13, 1028, 1130, 975, 18446744073709551615, 0, 1), - (13, 1024, 152, 973, 18446744073709551615, 0, 61), - (13, 973, 152, 1128, 18446744073709551615, 0, 2), - (13, 287, 756, 785, 18446744073709551615, 3, 6), - (13, 257, 180, 1083, 18446744073709551615, 0, 1), - (13, 258, 1083, 912, 18446744073709551615, 1, 2), - (13, 259, 912, 141, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1068, 18446744073709551615, 0, 1), - (13, 1024, 975, 206, 18446744073709551615, 0, 60), - (13, 206, 975, 1127, 18446744073709551615, 0, 1), - (13, 286, 1118, 735, 18446744073709551615, 1, 6), - (13, 257, 186, 180, 18446744073709551615, 0, 1), - (13, 258, 180, 1083, 18446744073709551615, 0, 2), - (13, 259, 1083, 912, 18446744073709551615, 1, 3), - (13, 1028, 1128, 173, 18446744073709551615, 0, 1), - (13, 1024, 1068, 183, 18446744073709551615, 0, 59), - (13, 183, 1068, 1128, 18446744073709551615, 1, 3), - (13, 286, 736, 1118, 18446744073709551615, 0, 6), - (13, 257, 189, 186, 18446744073709551615, 0, 1), - (13, 258, 186, 180, 18446744073709551615, 0, 1), - (13, 259, 180, 1083, 18446744073709551615, 0, 3), - (13, 1028, 1130, 978, 18446744073709551615, 0, 1), - (13, 976, 173, 1129, 18446744073709551615, 0, 2), - (13, 257, 189, 180, 18446744073709551615, 0, 1), - (13, 258, 180, 1083, 18446744073709551615, 1, 2), - (13, 259, 1083, 912, 18446744073709551615, 2, 3), - (13, 287, 756, 785, 18446744073709551615, 5, 6), - (13, 1028, 1126, 986, 18446744073709551615, 0, 1), - (13, 1024, 978, 209, 18446744073709551615, 0, 57), - (13, 209, 978, 1128, 18446744073709551615, 0, 1), - (13, 286, 736, 1118, 18446744073709551615, 1, 6), - (13, 257, 195, 189, 18446744073709551615, 0, 1), - (13, 258, 189, 180, 18446744073709551615, 0, 2), - (13, 259, 180, 1083, 18446744073709551615, 1, 3), - (13, 1028, 1128, 177, 18446744073709551615, 0, 1), - (13, 192, 986, 1129, 18446744073709551615, 0, 1), - (13, 286, 739, 736, 18446744073709551615, 0, 6), - (13, 287, 736, 1118, 18446744073709551615, 0, 6), - (13, 257, 198, 195, 18446744073709551615, 0, 1), - (13, 258, 195, 189, 18446744073709551615, 0, 1), - (13, 259, 189, 180, 18446744073709551615, 0, 3), - (13, 1028, 1130, 981, 18446744073709551615, 0, 1), - (13, 1024, 177, 979, 18446744073709551615, 0, 55), - (13, 979, 177, 1131, 18446744073709551615, 0, 2), - (13, 286, 736, 1118, 18446744073709551615, 3, 6), - (13, 257, 198, 189, 18446744073709551615, 0, 1), - (13, 258, 189, 180, 18446744073709551615, 1, 2), - (13, 259, 180, 1083, 18446744073709551615, 2, 3), - (13, 1028, 1126, 214, 18446744073709551615, 0, 1), - (13, 1024, 981, 212, 18446744073709551615, 0, 54), - (13, 212, 981, 1130, 18446744073709551615, 0, 1), - (13, 286, 739, 736, 18446744073709551615, 1, 6), - (13, 287, 736, 1118, 18446744073709551615, 1, 6), - (13, 257, 204, 198, 18446744073709551615, 0, 1), - (13, 258, 198, 189, 18446744073709551615, 0, 2), - (13, 259, 189, 180, 18446744073709551615, 1, 3), - (13, 1028, 1128, 186, 18446744073709551615, 0, 1), - (13, 1024, 214, 201, 18446744073709551615, 0, 53), - (13, 201, 214, 1131, 18446744073709551615, 0, 4), - (13, 286, 742, 739, 18446744073709551615, 0, 6), - (13, 287, 739, 736, 18446744073709551615, 0, 6), - (13, 257, 207, 204, 18446744073709551615, 0, 1), - (13, 258, 204, 198, 18446744073709551615, 0, 1), - (13, 259, 198, 189, 18446744073709551615, 0, 3), - (13, 1028, 1130, 984, 18446744073709551615, 0, 1), - (13, 1024, 186, 982, 18446744073709551615, 0, 52), - (13, 982, 186, 26, 18446744073709551615, 0, 2), - (13, 287, 736, 1118, 18446744073709551615, 3, 6), - (13, 257, 207, 198, 18446744073709551615, 0, 1), - (13, 258, 198, 189, 18446744073709551615, 1, 2), - (13, 259, 189, 180, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1067, 18446744073709551615, 0, 1), - (13, 1024, 984, 215, 18446744073709551615, 0, 51), - (13, 215, 984, 1131, 18446744073709551615, 0, 1), - (13, 257, 213, 207, 18446744073709551615, 0, 1), - (13, 258, 207, 198, 18446744073709551615, 0, 2), - (13, 259, 198, 189, 18446744073709551615, 1, 3), - (13, 1028, 1128, 195, 18446744073709551615, 0, 1), - (13, 1024, 1067, 210, 18446744073709551615, 0, 50), - (13, 210, 1067, 26, 18446744073709551615, 0, 1), - (13, 286, 741, 742, 18446744073709551615, 0, 6), - (13, 257, 216, 213, 18446744073709551615, 0, 1), - (13, 258, 213, 207, 18446744073709551615, 0, 1), - (13, 259, 207, 198, 18446744073709551615, 0, 3), - (13, 1028, 1130, 987, 18446744073709551615, 0, 1), - (13, 1024, 195, 985, 18446744073709551615, 0, 49), - (13, 985, 195, 785, 18446744073709551615, 0, 1), - (13, 257, 216, 207, 18446744073709551615, 0, 1), - (13, 258, 207, 198, 18446744073709551615, 1, 2), - (13, 259, 198, 189, 18446744073709551615, 2, 3), - (13, 1028, 1126, 989, 18446744073709551615, 0, 1), - (13, 1024, 987, 218, 18446744073709551615, 0, 48), - (13, 218, 987, 26, 18446744073709551615, 0, 4), - (13, 286, 741, 742, 18446744073709551615, 1, 6), - (13, 257, 222, 216, 18446744073709551615, 0, 1), - (13, 258, 216, 207, 18446744073709551615, 0, 2), - (13, 259, 207, 198, 18446744073709551615, 1, 3), - (13, 1028, 1128, 204, 18446744073709551615, 0, 1), - (13, 1024, 989, 219, 18446744073709551615, 0, 47), - (13, 219, 989, 785, 18446744073709551615, 0, 4), - (13, 286, 1143, 741, 18446744073709551615, 0, 6), - (13, 257, 225, 222, 18446744073709551615, 0, 1), - (13, 258, 222, 216, 18446744073709551615, 0, 1), - (13, 259, 216, 207, 18446744073709551615, 0, 3), - (13, 1028, 1130, 990, 18446744073709551615, 0, 1), - (13, 1024, 204, 988, 18446744073709551615, 0, 46), - (13, 988, 204, 785, 18446744073709551615, 0, 1), - (13, 286, 741, 742, 18446744073709551615, 3, 6), - (13, 287, 742, 739, 18446744073709551615, 3, 6), - (13, 257, 225, 216, 18446744073709551615, 0, 1), - (13, 258, 216, 207, 18446744073709551615, 1, 2), - (13, 259, 207, 198, 18446744073709551615, 2, 3), - (13, 1028, 1126, 217, 18446744073709551615, 0, 1), - (13, 221, 990, 785, 18446744073709551615, 0, 1), - (13, 286, 1143, 741, 18446744073709551615, 1, 6), - (13, 287, 741, 742, 18446744073709551615, 1, 6), - (13, 257, 231, 225, 18446744073709551615, 0, 1), - (13, 258, 225, 216, 18446744073709551615, 0, 2), - (13, 259, 216, 207, 18446744073709551615, 1, 3), - (13, 1028, 1128, 213, 18446744073709551615, 0, 1), - (13, 1024, 217, 228, 18446744073709551615, 0, 44), - (13, 228, 217, 756, 18446744073709551615, 0, 1), - (13, 286, 971, 1143, 18446744073709551615, 0, 6), - (13, 287, 1143, 741, 18446744073709551615, 0, 6), - (13, 257, 234, 231, 18446744073709551615, 0, 1), - (13, 258, 231, 225, 18446744073709551615, 0, 1), - (13, 259, 225, 216, 18446744073709551615, 0, 3), - (13, 1028, 1130, 993, 18446744073709551615, 0, 1), - (13, 1024, 213, 991, 18446744073709551615, 0, 43), - (13, 991, 213, 735, 18446744073709551615, 0, 5), - (13, 287, 741, 742, 18446744073709551615, 3, 6), - (13, 257, 234, 225, 18446744073709551615, 0, 1), - (13, 258, 225, 216, 18446744073709551615, 1, 2), - (13, 259, 216, 207, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1066, 18446744073709551615, 0, 1), - (13, 1024, 993, 224, 18446744073709551615, 0, 42), - (13, 224, 993, 756, 18446744073709551615, 0, 4), - (13, 286, 971, 1143, 18446744073709551615, 1, 6), - (13, 257, 240, 234, 18446744073709551615, 0, 1), - (13, 258, 234, 225, 18446744073709551615, 0, 2), - (13, 259, 225, 216, 18446744073709551615, 1, 3), - (13, 1028, 1128, 222, 18446744073709551615, 0, 1), - (13, 287, 971, 1143, 18446744073709551615, 0, 6), - (13, 257, 243, 240, 18446744073709551615, 0, 1), - (13, 258, 240, 234, 18446744073709551615, 0, 1), - (13, 259, 234, 225, 18446744073709551615, 0, 3), - (13, 1028, 1130, 996, 18446744073709551615, 0, 1), - (13, 1024, 222, 994, 18446744073709551615, 0, 40), - (13, 994, 222, 1118, 18446744073709551615, 0, 2), - (13, 257, 243, 234, 18446744073709551615, 0, 1), - (13, 258, 234, 225, 18446744073709551615, 1, 2), - (13, 259, 225, 216, 18446744073709551615, 2, 3), - (13, 1028, 1126, 992, 18446744073709551615, 0, 1), - (13, 227, 996, 735, 18446744073709551615, 0, 1), - (13, 287, 971, 1143, 18446744073709551615, 1, 6), - (13, 257, 249, 243, 18446744073709551615, 0, 1), - (13, 258, 243, 234, 18446744073709551615, 0, 2), - (13, 259, 234, 225, 18446744073709551615, 1, 3), - (13, 1028, 1128, 231, 18446744073709551615, 0, 1), - (13, 1024, 992, 246, 18446744073709551615, 0, 38), - (13, 246, 992, 1118, 18446744073709551615, 0, 4), - (13, 257, 172, 249, 18446744073709551615, 0, 1), - (13, 258, 249, 243, 18446744073709551615, 0, 1), - (13, 259, 243, 234, 18446744073709551615, 0, 3), - (13, 1028, 1130, 999, 18446744073709551615, 0, 1), - (13, 997, 231, 739, 18446744073709551615, 0, 4), - (13, 286, 1136, 971, 18446744073709551615, 3, 6), - (13, 287, 971, 1143, 18446744073709551615, 3, 6), - (13, 257, 172, 243, 18446744073709551615, 0, 1), - (13, 258, 243, 234, 18446744073709551615, 1, 2), - (13, 259, 234, 225, 18446744073709551615, 2, 3), - (13, 1028, 1126, 220, 18446744073709551615, 0, 1), - (13, 230, 999, 1118, 18446744073709551615, 0, 1), - (13, 286, 1114, 1136, 18446744073709551615, 1, 6), - (13, 287, 1136, 971, 18446744073709551615, 1, 6), - (13, 257, 1047, 172, 18446744073709551615, 0, 1), - (13, 258, 172, 243, 18446744073709551615, 0, 2), - (13, 259, 243, 234, 18446744073709551615, 1, 3), - (13, 1028, 1128, 240, 18446744073709551615, 0, 1), - (13, 1024, 220, 252, 18446744073709551615, 0, 35), - (13, 252, 220, 739, 18446744073709551615, 0, 1), - (13, 286, 160, 1114, 18446744073709551615, 0, 6), - (13, 257, 255, 1047, 18446744073709551615, 0, 1), - (13, 258, 1047, 172, 18446744073709551615, 0, 1), - (13, 259, 172, 243, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1002, 18446744073709551615, 0, 1), - (13, 1024, 240, 1000, 18446744073709551615, 0, 34), - (13, 1000, 240, 742, 18446744073709551615, 0, 2), - (13, 287, 1136, 971, 18446744073709551615, 3, 6), - (13, 257, 255, 172, 18446744073709551615, 0, 1), - (13, 258, 172, 243, 18446744073709551615, 1, 2), - (13, 259, 243, 234, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1065, 18446744073709551615, 0, 1), - (13, 1024, 1002, 233, 18446744073709551615, 0, 33), - (13, 233, 1002, 739, 18446744073709551615, 0, 1), - (13, 286, 160, 1114, 18446744073709551615, 1, 6), - (13, 287, 1114, 1136, 18446744073709551615, 1, 6), - (13, 257, 1051, 255, 18446744073709551615, 0, 1), - (13, 258, 255, 172, 18446744073709551615, 0, 2), - (13, 259, 172, 243, 18446744073709551615, 1, 3), - (13, 1028, 1128, 249, 18446744073709551615, 0, 1), - (13, 1024, 1065, 1053, 18446744073709551615, 0, 32), - (13, 1053, 1065, 742, 18446744073709551615, 0, 4), - (13, 286, 34, 160, 18446744073709551615, 0, 6), - (13, 257, 1052, 1051, 18446744073709551615, 0, 1), - (13, 258, 1051, 255, 18446744073709551615, 0, 1), - (13, 259, 255, 172, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1005, 18446744073709551615, 0, 1), - (13, 1024, 249, 1003, 18446744073709551615, 0, 31), - (13, 1003, 249, 1143, 18446744073709551615, 0, 4), - (13, 257, 1052, 255, 18446744073709551615, 0, 1), - (13, 258, 255, 172, 18446744073709551615, 1, 2), - (13, 259, 172, 243, 18446744073709551615, 2, 3), - (13, 1028, 1126, 995, 18446744073709551615, 0, 1), - (13, 1024, 1005, 236, 18446744073709551615, 0, 30), - (13, 236, 1005, 739, 18446744073709551615, 0, 1), - (13, 286, 34, 160, 18446744073709551615, 1, 6), - (13, 287, 160, 1114, 18446744073709551615, 1, 6), - (13, 257, 1048, 1052, 18446744073709551615, 0, 1), - (13, 258, 1052, 255, 18446744073709551615, 0, 2), - (13, 259, 255, 172, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1047, 18446744073709551615, 0, 1), - (13, 1024, 995, 1042, 18446744073709551615, 0, 29), - (13, 1042, 995, 1143, 18446744073709551615, 0, 1), - (13, 287, 34, 160, 18446744073709551615, 0, 6), - (13, 257, 1040, 1048, 18446744073709551615, 0, 1), - (13, 258, 1048, 1052, 18446744073709551615, 0, 1), - (13, 259, 1052, 255, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1008, 18446744073709551615, 0, 1), - (13, 1024, 1047, 1006, 18446744073709551615, 0, 28), - (13, 1006, 1047, 971, 18446744073709551615, 0, 1), - (13, 286, 34, 160, 18446744073709551615, 3, 6), - (13, 257, 1040, 1052, 18446744073709551615, 0, 1), - (13, 258, 1052, 255, 18446744073709551615, 1, 2), - (13, 259, 255, 172, 18446744073709551615, 2, 3), - (13, 1028, 1126, 223, 18446744073709551615, 0, 1), - (13, 239, 1008, 741, 18446744073709551615, 0, 4), - (13, 287, 34, 160, 18446744073709551615, 1, 6), - (13, 257, 1046, 1040, 18446744073709551615, 0, 1), - (13, 258, 1040, 1052, 18446744073709551615, 0, 2), - (13, 259, 1052, 255, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1051, 18446744073709551615, 0, 1), - (13, 1024, 223, 1050, 18446744073709551615, 0, 26), - (13, 1050, 223, 971, 18446744073709551615, 0, 3), - (13, 286, 58, 70, 18446744073709551615, 0, 6), - (13, 287, 70, 34, 18446744073709551615, 0, 6), - (13, 257, 1044, 1046, 18446744073709551615, 0, 1), - (13, 258, 1046, 1040, 18446744073709551615, 0, 1), - (13, 259, 1040, 1052, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1011, 18446744073709551615, 0, 1), - (13, 1024, 1051, 1009, 18446744073709551615, 0, 25), - (13, 1009, 1051, 1136, 18446744073709551615, 0, 1), - (13, 257, 1044, 1040, 18446744073709551615, 0, 1), - (13, 258, 1040, 1052, 18446744073709551615, 1, 2), - (13, 259, 1052, 255, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1064, 18446744073709551615, 0, 1), - (13, 242, 1011, 1143, 18446744073709551615, 0, 1), - (13, 257, 1035, 1044, 18446744073709551615, 0, 1), - (13, 258, 1044, 1040, 18446744073709551615, 0, 2), - (13, 259, 1040, 1052, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1048, 18446744073709551615, 0, 1), - (13, 1045, 1064, 971, 18446744073709551615, 0, 2), - (13, 286, 76, 58, 18446744073709551615, 0, 6), - (13, 257, 1041, 1035, 18446744073709551615, 0, 1), - (13, 258, 1035, 1044, 18446744073709551615, 0, 1), - (13, 259, 1044, 1040, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1014, 18446744073709551615, 0, 1), - (13, 286, 58, 70, 18446744073709551615, 3, 6), - (13, 257, 1041, 1044, 18446744073709551615, 0, 1), - (13, 258, 1044, 1040, 18446744073709551615, 1, 2), - (13, 259, 1040, 1052, 18446744073709551615, 2, 3), - (13, 1028, 1126, 998, 18446744073709551615, 0, 1), - (13, 1024, 1014, 245, 18446744073709551615, 0, 21), - (13, 245, 1014, 1136, 18446744073709551615, 0, 2), - (13, 286, 76, 58, 18446744073709551615, 1, 6), - (13, 287, 58, 70, 18446744073709551615, 1, 6), - (13, 257, 1043, 1041, 18446744073709551615, 0, 1), - (13, 258, 1041, 1044, 18446744073709551615, 0, 2), - (13, 259, 1044, 1040, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1046, 18446744073709551615, 0, 1), - (13, 1033, 998, 1114, 18446744073709551615, 0, 1), - (13, 257, 1039, 1043, 18446744073709551615, 0, 1), - (13, 258, 1043, 1041, 18446744073709551615, 0, 1), - (13, 259, 1041, 1044, 18446744073709551615, 0, 3), - (13, 1028, 1130, 1017, 18446744073709551615, 0, 1), - (13, 1015, 1046, 160, 18446744073709551615, 0, 1), - (13, 286, 76, 58, 18446744073709551615, 3, 6), - (13, 257, 1039, 1041, 18446744073709551615, 0, 1), - (13, 258, 1041, 1044, 18446744073709551615, 1, 2), - (13, 259, 1044, 1040, 18446744073709551615, 2, 3), - (13, 1028, 1126, 226, 18446744073709551615, 0, 1), - (13, 1024, 1017, 248, 18446744073709551615, 0, 18), - (13, 248, 1017, 160, 18446744073709551615, 0, 1), - (13, 257, 1038, 1039, 18446744073709551615, 0, 1), - (13, 258, 1039, 1041, 18446744073709551615, 0, 2), - (13, 259, 1041, 1044, 18446744073709551615, 1, 3), - (13, 1028, 1128, 1035, 18446744073709551615, 0, 1), - (13, 1024, 226, 1037, 18446744073709551615, 0, 17), - (13, 287, 85, 76, 18446744073709551615, 0, 5), - (13, 257, 1030, 1038, 18446744073709551615, 0, 1), - (13, 258, 1038, 1039, 18446744073709551615, 0, 1), - (13, 259, 1039, 1041, 18446744073709551615, 0, 3), - (13, 287, 76, 58, 18446744073709551615, 2, 6), - (13, 1028, 1130, 1020, 18446744073709551615, 0, 1), - (13, 1024, 1035, 1018, 18446744073709551615, 0, 16), - (13, 286, 85, 76, 18446744073709551615, 3, 6), - (13, 257, 1030, 1039, 18446744073709551615, 0, 1), - (13, 258, 1039, 1041, 18446744073709551615, 1, 2), - (13, 259, 1041, 1044, 18446744073709551615, 2, 3), - (13, 1028, 1126, 1063, 18446744073709551615, 0, 1), - (13, 1024, 1020, 251, 18446744073709551615, 0, 15), - (13, 251, 1020, 34, 18446744073709551615, 0, 2), - (13, 257, 1036, 1030, 18446744073709551615, 0, 1), - (13, 258, 1030, 1039, 18446744073709551615, 0, 2), - (13, 259, 1039, 1041, 18446744073709551615, 1, 3), - (13, 287, 76, 58, 18446744073709551615, 4, 6), - (13, 1028, 1128, 1043, 18446744073709551615, 0, 1), - (13, 1024, 1063, 1034, 18446744073709551615, 0, 14), - (13, 1034, 1063, 70, 18446744073709551615, 0, 1), - (13, 287, 94, 85, 18446744073709551615, 0, 3), - (13, 257, 1027, 1036, 18446744073709551615, 0, 1), - (13, 258, 1036, 1030, 18446744073709551615, 0, 1), - (13, 259, 1030, 1039, 18446744073709551615, 0, 2), - (13, 1028, 1130, 1023, 18446744073709551615, 0, 1), - (13, 1024, 1043, 1021, 18446744073709551615, 0, 13), - (13, 1021, 1043, 58, 18446744073709551615, 0, 2), - (13, 286, 94, 85, 18446744073709551615, 3, 5), - (13, 257, 1027, 1030, 18446744073709551615, 0, 1), - (13, 258, 1030, 1039, 18446744073709551615, 1, 2), - (13, 259, 1039, 1041, 18446744073709551615, 2, 3), - (13, 1028, 1126, 229, 18446744073709551615, 0, 1), - (13, 254, 1023, 70, 18446744073709551615, 0, 1), - (13, 287, 94, 85, 18446744073709551615, 1, 3), - (13, 257, 765, 1027, 18446744073709551615, 0, 1), - (13, 258, 1027, 1030, 18446744073709551615, 0, 1), - (13, 259, 1030, 1039, 18446744073709551615, 1, 2), - (13, 1028, 1128, 1038, 18446744073709551615, 0, 1), - (13, 1024, 229, 1031, 18446744073709551615, 0, 11), - (13, 1031, 229, 58, 18446744073709551615, 0, 1), - (13, 286, 120, 103, 18446744073709551615, 0, 2), - (13, 287, 103, 94, 18446744073709551615, 0, 2), - (13, 257, 1032, 765, 18446744073709551615, 0, 1), - (13, 258, 765, 1027, 18446744073709551615, 0, 1), - (13, 259, 1027, 1030, 18446744073709551615, 0, 1), - (13, 287, 94, 85, 18446744073709551615, 2, 3), - (13, 1028, 1130, 1062, 18446744073709551615, 0, 1), - (13, 1049, 1038, 76, 18446744073709551615, 0, 1), - (13, 286, 124, 120, 18446744073709551615, 0, 1), - (13, 257, 1036, 1032, 18446744073709551615, 0, 1), - (13, 258, 1032, 765, 18446744073709551615, 0, 1), - (13, 259, 765, 1027, 18446744073709551615, 0, 1), - (13, 287, 141, 137, 18446744073709551615, 0, 1), - (13, 257, 1007, 235, 18446744073709551615, 0, 1), - (13, 258, 235, 1061, 18446744073709551615, 0, 1), - (13, 259, 1061, 1036, 18446744073709551615, 0, 1), - (13, 286, 189, 180, 18446744073709551615, 0, 2), - (13, 257, 238, 232, 18446744073709551615, 0, 1), - (13, 258, 232, 1060, 18446744073709551615, 0, 1), - (13, 259, 1060, 1007, 18446744073709551615, 0, 1), - (13, 287, 189, 180, 18446744073709551615, 0, 1), - (13, 257, 1062, 238, 18446744073709551615, 0, 1), - (13, 258, 238, 232, 18446744073709551615, 0, 1), - (13, 259, 232, 1060, 18446744073709551615, 0, 1), - (13, 286, 225, 216, 18446744073709551615, 0, 1), - (13, 287, 216, 207, 18446744073709551615, 0, 1), - (13, 257, 241, 1058, 18446744073709551615, 0, 1), - (13, 258, 1058, 1013, 18446744073709551615, 0, 1), - (13, 259, 1013, 1062, 18446744073709551615, 0, 1), - (13, 257, 1057, 1059, 18446744073709551615, 0, 1), - (13, 258, 1059, 1016, 18446744073709551615, 0, 1), - (13, 259, 1016, 241, 18446744073709551615, 0, 1), - (13, 286, 255, 172, 18446744073709551615, 0, 1), - (13, 287, 172, 243, 18446744073709551615, 0, 1), - (13, 257, 1010, 1057, 18446744073709551615, 0, 1), - (13, 258, 1057, 1059, 18446744073709551615, 0, 1), - (13, 259, 1059, 1016, 18446744073709551615, 0, 1), - (13, 286, 1044, 1040, 18446744073709551615, 0, 1), - (13, 287, 1040, 1052, 18446744073709551615, 0, 1), - (13, 257, 1056, 1022, 18446744073709551615, 0, 1), - (13, 258, 1022, 247, 18446744073709551615, 0, 1), - (13, 259, 247, 1010, 18446744073709551615, 0, 1), - (13, 257, 1054, 1019, 18446744073709551615, 0, 1), - (13, 258, 1019, 250, 18446744073709551615, 0, 1), - (13, 259, 250, 1056, 18446744073709551615, 0, 1), - (13, 277, 1062, 238, 18446744073709551615, 0, 3), - (13, 279, 232, 1060, 18446744073709551615, 0, 3), - (13, 280, 1060, 1007, 18446744073709551615, 0, 3), - (13, 283, 1061, 1036, 18446744073709551615, 0, 3), - (13, 284, 1036, 1032, 18446744073709551615, 0, 3), - (13, 285, 1032, 765, 18446744073709551615, 0, 3), - (13, 286, 765, 1027, 18446744073709551615, 0, 3), - (13, 287, 1027, 1030, 18446744073709551615, 0, 3), - (13, 298, 225, 216, 18446744073709551615, 0, 3), - (13, 300, 207, 198, 18446744073709551615, 0, 3), - (13, 302, 189, 180, 18446744073709551615, 0, 3), - (13, 303, 180, 912, 18446744073709551615, 0, 3), - (13, 304, 912, 141, 18446744073709551615, 0, 6), - (13, 305, 141, 1083, 18446744073709551615, 0, 3), - (13, 306, 1083, 141, 18446744073709551615, 0, 3), - (13, 307, 141, 912, 18446744073709551615, 0, 3), - (13, 0, 256, 1025, 18446744073709551615, 246, 248), - (13, 257, 1025, 766, 18446744073709551615, 1, 3), - (13, 258, 766, 1055, 18446744073709551615, 1, 3), - (13, 259, 1055, 1024, 18446744073709551615, 1, 3), - (13, 0, 256, 1025, 18446744073709551615, 247, 248), - (13, 257, 1025, 766, 18446744073709551615, 2, 3), - (13, 258, 766, 1055, 18446744073709551615, 2, 3), - (13, 259, 1055, 1024, 18446744073709551615, 2, 3), - (13, 285, 1032, 765, 18446744073709551615, 2, 3), - (13, 287, 1027, 1030, 18446744073709551615, 2, 3), - (13, 307, 141, 912, 18446744073709551615, 2, 3), - (13, 870, 996, 222, 18446744073709551615, 0, 1), -]; -pub(crate) const DOWNGRADE_KEYS: &[(u8, u64, u64, u64, u64, u32, u32, u8)] = &[ - (13, 31, 799, 800, 18446744073709551615, 0, 1, 2), - (13, 287, 799, 800, 18446744073709551615, 0, 1, 2), - (13, 1, 769, 768, 18446744073709551615, 0, 225, 1), - (13, 1024, 893, 125, 18446744073709551615, 1, 140, 2), - (13, 1024, 892, 124, 18446744073709551615, 1, 141, 2), - (13, 1024, 891, 123, 18446744073709551615, 1, 143, 2), - (13, 1024, 890, 122, 18446744073709551615, 1, 144, 2), - (13, 1024, 889, 121, 18446744073709551615, 1, 145, 2), - (13, 1024, 888, 120, 18446744073709551615, 1, 145, 2), - (13, 1024, 887, 119, 18446744073709551615, 1, 147, 2), - (13, 1024, 886, 118, 18446744073709551615, 1, 147, 2), - (13, 1024, 885, 117, 18446744073709551615, 1, 148, 2), - (13, 1024, 884, 116, 18446744073709551615, 1, 149, 2), - (13, 1024, 883, 115, 18446744073709551615, 1, 150, 2), - (13, 1024, 882, 114, 18446744073709551615, 1, 151, 2), - (13, 1024, 881, 113, 18446744073709551615, 1, 152, 2), - (13, 1024, 880, 112, 18446744073709551615, 1, 153, 2), - (13, 1024, 879, 111, 18446744073709551615, 1, 154, 2), - (13, 1024, 878, 110, 18446744073709551615, 1, 155, 2), - (13, 1024, 877, 109, 18446744073709551615, 1, 156, 2), - (13, 1024, 876, 108, 18446744073709551615, 1, 157, 2), - (13, 1024, 875, 107, 18446744073709551615, 1, 158, 2), - (13, 1024, 874, 106, 18446744073709551615, 1, 159, 2), - (13, 1024, 873, 105, 18446744073709551615, 1, 160, 2), - (13, 1024, 872, 104, 18446744073709551615, 1, 161, 2), - (13, 1024, 871, 103, 18446744073709551615, 1, 162, 2), - (13, 1024, 870, 102, 18446744073709551615, 1, 163, 2), - (13, 1024, 869, 101, 18446744073709551615, 1, 164, 2), - (13, 1024, 868, 100, 18446744073709551615, 1, 165, 2), - (13, 1024, 867, 99, 18446744073709551615, 1, 166, 2), - (13, 1024, 866, 98, 18446744073709551615, 1, 167, 2), - (13, 1024, 865, 97, 18446744073709551615, 1, 168, 2), - (13, 1024, 864, 96, 18446744073709551615, 1, 169, 2), - (13, 1024, 863, 95, 18446744073709551615, 1, 170, 2), - (13, 1024, 862, 94, 18446744073709551615, 1, 171, 2), - (13, 1024, 861, 93, 18446744073709551615, 1, 172, 2), - (13, 1024, 860, 92, 18446744073709551615, 1, 173, 2), - (13, 1024, 859, 91, 18446744073709551615, 1, 174, 2), - (13, 1024, 858, 90, 18446744073709551615, 1, 175, 2), - (13, 1024, 857, 89, 18446744073709551615, 1, 176, 2), - (13, 1024, 856, 88, 18446744073709551615, 1, 177, 2), - (13, 1024, 855, 87, 18446744073709551615, 1, 178, 2), - (13, 1024, 854, 86, 18446744073709551615, 1, 179, 2), - (13, 1024, 853, 85, 18446744073709551615, 1, 180, 2), - (13, 1024, 852, 84, 18446744073709551615, 1, 181, 2), - (13, 1024, 851, 83, 18446744073709551615, 1, 182, 2), - (13, 1024, 850, 82, 18446744073709551615, 1, 183, 2), - (13, 1024, 849, 81, 18446744073709551615, 1, 184, 2), - (13, 1024, 848, 80, 18446744073709551615, 1, 185, 2), - (13, 1024, 847, 79, 18446744073709551615, 1, 186, 2), - (13, 1024, 846, 78, 18446744073709551615, 1, 187, 2), - (13, 1024, 845, 77, 18446744073709551615, 1, 188, 2), - (13, 1024, 844, 76, 18446744073709551615, 1, 189, 2), - (13, 1024, 843, 75, 18446744073709551615, 1, 190, 2), - (13, 1024, 842, 74, 18446744073709551615, 1, 191, 2), - (13, 1024, 841, 73, 18446744073709551615, 1, 192, 2), - (13, 1024, 840, 72, 18446744073709551615, 1, 193, 2), - (13, 1024, 839, 71, 18446744073709551615, 1, 194, 2), - (13, 1024, 838, 70, 18446744073709551615, 1, 195, 2), - (13, 1024, 837, 69, 18446744073709551615, 1, 391, 2), - (13, 1024, 836, 68, 18446744073709551615, 1, 197, 2), - (13, 1024, 835, 67, 18446744073709551615, 1, 198, 2), - (13, 1024, 834, 66, 18446744073709551615, 1, 397, 2), - (13, 1024, 833, 65, 18446744073709551615, 1, 200, 2), - (13, 1024, 832, 64, 18446744073709551615, 1, 201, 2), - (13, 1024, 831, 63, 18446744073709551615, 1, 202, 2), - (13, 1024, 830, 62, 18446744073709551615, 1, 203, 2), - (13, 1024, 829, 61, 18446744073709551615, 1, 204, 2), - (13, 1024, 828, 60, 18446744073709551615, 1, 205, 2), - (13, 1024, 827, 59, 18446744073709551615, 1, 206, 2), - (13, 1024, 826, 58, 18446744073709551615, 1, 207, 2), - (13, 1024, 825, 57, 18446744073709551615, 1, 208, 2), - (13, 1024, 824, 56, 18446744073709551615, 1, 209, 2), - (13, 1024, 823, 55, 18446744073709551615, 1, 210, 2), - (13, 1024, 822, 54, 18446744073709551615, 1, 211, 2), - (13, 1024, 821, 53, 18446744073709551615, 1, 212, 2), - (13, 1024, 820, 52, 18446744073709551615, 1, 213, 2), - (13, 1024, 799, 31, 18446744073709551615, 1, 234, 2), - (13, 1024, 798, 30, 18446744073709551615, 1, 235, 2), - (13, 126, 894, 1027, 18446744073709551615, 0, 1, 1), - (13, 1024, 1017, 249, 18446744073709551615, 1, 18, 2), - (13, 1024, 1016, 248, 18446744073709551615, 1, 19, 2), - (13, 1024, 1015, 247, 18446744073709551615, 1, 20, 2), - (13, 1024, 1014, 246, 18446744073709551615, 1, 21, 2), - (13, 1024, 1013, 245, 18446744073709551615, 1, 22, 2), - (13, 1024, 1012, 244, 18446744073709551615, 1, 23, 2), - (13, 1024, 1011, 243, 18446744073709551615, 1, 24, 2), - (13, 1024, 1010, 242, 18446744073709551615, 1, 25, 2), - (13, 1024, 1009, 241, 18446744073709551615, 1, 26, 2), - (13, 1024, 1008, 240, 18446744073709551615, 1, 27, 2), - (13, 1024, 1007, 239, 18446744073709551615, 1, 28, 2), - (13, 1024, 1006, 238, 18446744073709551615, 1, 29, 2), - (13, 1024, 1005, 237, 18446744073709551615, 1, 30, 2), - (13, 1024, 1004, 236, 18446744073709551615, 1, 31, 2), - (13, 1024, 1003, 235, 18446744073709551615, 1, 32, 2), - (13, 1024, 1002, 234, 18446744073709551615, 1, 33, 2), - (13, 1024, 1001, 233, 18446744073709551615, 1, 34, 2), - (13, 1024, 1000, 232, 18446744073709551615, 1, 35, 2), - (13, 1024, 999, 231, 18446744073709551615, 1, 36, 2), - (13, 1024, 998, 230, 18446744073709551615, 1, 37, 2), - (13, 1024, 997, 229, 18446744073709551615, 1, 38, 2), - (13, 1024, 996, 228, 18446744073709551615, 1, 39, 2), - (13, 1024, 995, 227, 18446744073709551615, 1, 40, 2), - (13, 1024, 994, 226, 18446744073709551615, 1, 41, 2), - (13, 1024, 993, 225, 18446744073709551615, 1, 42, 2), - (13, 1024, 992, 224, 18446744073709551615, 1, 43, 2), - (13, 1024, 991, 223, 18446744073709551615, 1, 44, 2), - (13, 1024, 990, 222, 18446744073709551615, 1, 45, 2), - (13, 1024, 989, 221, 18446744073709551615, 1, 46, 2), - (13, 1024, 988, 220, 18446744073709551615, 1, 47, 2), - (13, 1024, 987, 219, 18446744073709551615, 1, 48, 2), - (13, 1024, 986, 218, 18446744073709551615, 1, 49, 2), - (13, 1024, 985, 217, 18446744073709551615, 1, 50, 2), - (13, 1024, 984, 216, 18446744073709551615, 1, 51, 2), - (13, 1024, 983, 215, 18446744073709551615, 1, 52, 2), - (13, 1024, 982, 214, 18446744073709551615, 1, 53, 2), - (13, 1024, 981, 213, 18446744073709551615, 1, 54, 2), - (13, 1024, 980, 212, 18446744073709551615, 1, 55, 2), - (13, 1024, 979, 211, 18446744073709551615, 1, 56, 2), - (13, 1024, 978, 210, 18446744073709551615, 1, 57, 2), - (13, 1024, 977, 209, 18446744073709551615, 1, 58, 2), - (13, 1024, 976, 208, 18446744073709551615, 1, 59, 2), - (13, 1024, 975, 207, 18446744073709551615, 1, 60, 2), - (13, 1024, 974, 206, 18446744073709551615, 1, 61, 2), - (13, 1024, 973, 205, 18446744073709551615, 1, 62, 2), - (13, 1024, 972, 204, 18446744073709551615, 1, 63, 2), - (13, 1024, 971, 203, 18446744073709551615, 1, 64, 2), - (13, 1024, 970, 202, 18446744073709551615, 1, 65, 2), - (13, 1024, 969, 201, 18446744073709551615, 1, 66, 2), - (13, 1024, 968, 200, 18446744073709551615, 1, 67, 2), - (13, 1024, 967, 199, 18446744073709551615, 1, 68, 2), - (13, 1024, 966, 198, 18446744073709551615, 1, 69, 2), - (13, 1024, 965, 197, 18446744073709551615, 1, 70, 2), - (13, 1024, 964, 196, 18446744073709551615, 1, 71, 2), - (13, 1024, 963, 195, 18446744073709551615, 1, 72, 2), - (13, 1024, 962, 194, 18446744073709551615, 1, 73, 2), - (13, 1024, 961, 193, 18446744073709551615, 1, 74, 2), - (13, 1024, 960, 192, 18446744073709551615, 1, 75, 2), - (13, 1024, 959, 191, 18446744073709551615, 1, 76, 2), - (13, 1024, 958, 190, 18446744073709551615, 1, 77, 2), - (13, 1024, 957, 189, 18446744073709551615, 1, 78, 2), - (13, 1024, 956, 188, 18446744073709551615, 1, 79, 2), - (13, 1024, 955, 187, 18446744073709551615, 1, 80, 2), - (13, 1024, 954, 186, 18446744073709551615, 1, 81, 2), - (13, 1024, 953, 185, 18446744073709551615, 1, 82, 2), - (13, 1024, 952, 184, 18446744073709551615, 1, 83, 2), - (13, 1024, 951, 183, 18446744073709551615, 1, 84, 2), - (13, 1024, 950, 182, 18446744073709551615, 1, 85, 2), - (13, 1024, 949, 181, 18446744073709551615, 1, 86, 2), - (13, 1024, 948, 180, 18446744073709551615, 1, 87, 2), - (13, 1024, 947, 179, 18446744073709551615, 1, 88, 2), - (13, 1024, 946, 178, 18446744073709551615, 1, 89, 2), - (13, 1024, 945, 177, 18446744073709551615, 1, 90, 2), - (13, 1024, 944, 176, 18446744073709551615, 1, 91, 2), - (13, 1024, 943, 175, 18446744073709551615, 1, 92, 2), - (13, 1024, 942, 174, 18446744073709551615, 1, 93, 2), - (13, 1024, 941, 173, 18446744073709551615, 1, 94, 2), - (13, 1024, 940, 172, 18446744073709551615, 1, 96, 2), - (13, 1024, 939, 171, 18446744073709551615, 1, 97, 2), - (13, 1024, 938, 170, 18446744073709551615, 1, 97, 2), - (13, 1024, 937, 169, 18446744073709551615, 1, 98, 2), - (13, 1024, 936, 168, 18446744073709551615, 1, 99, 2), - (13, 1024, 935, 167, 18446744073709551615, 1, 100, 2), - (13, 1024, 934, 166, 18446744073709551615, 1, 101, 2), - (13, 1024, 933, 165, 18446744073709551615, 1, 102, 2), - (13, 1024, 932, 164, 18446744073709551615, 1, 102, 2), - (13, 1024, 931, 163, 18446744073709551615, 1, 103, 2), - (13, 1024, 930, 162, 18446744073709551615, 1, 103, 2), - (13, 1024, 929, 161, 18446744073709551615, 1, 105, 2), - (13, 1024, 928, 160, 18446744073709551615, 1, 106, 2), - (13, 1024, 927, 159, 18446744073709551615, 1, 107, 2), - (13, 1024, 926, 158, 18446744073709551615, 1, 107, 2), - (13, 1024, 925, 157, 18446744073709551615, 1, 109, 2), - (13, 1024, 924, 156, 18446744073709551615, 1, 110, 2), - (13, 1024, 923, 155, 18446744073709551615, 1, 110, 2), - (13, 1024, 922, 154, 18446744073709551615, 1, 112, 2), - (13, 1024, 921, 153, 18446744073709551615, 1, 113, 2), - (13, 1024, 920, 152, 18446744073709551615, 1, 114, 2), - (13, 1024, 919, 151, 18446744073709551615, 1, 115, 2), - (13, 1024, 918, 150, 18446744073709551615, 1, 116, 2), - (13, 1024, 917, 149, 18446744073709551615, 1, 117, 2), - (13, 1024, 916, 148, 18446744073709551615, 1, 118, 2), - (13, 1024, 915, 147, 18446744073709551615, 1, 118, 2), - (13, 1024, 914, 146, 18446744073709551615, 1, 119, 2), - (13, 250, 1018, 1028, 18446744073709551615, 0, 2, 1), - (13, 254, 1022, 1032, 18446744073709551615, 0, 2, 1), - (13, 1024, 1023, 255, 18446744073709551615, 1, 12, 2), - (13, 541, 1054, 1055, 18446744073709551615, 0, 3, 2), - (13, 562, 1073, 1075, 18446744073709551615, 0, 3, 2), - (13, 563, 1075, 1074, 18446744073709551615, 0, 3, 2), - (13, 562, 1074, 1075, 18446744073709551615, 0, 3, 1), - (13, 512, 256, 1027, 18446744073709551615, 0, 2, 2), - (13, 1024, 1091, 768, 18446744073709551615, 0, 1, 1), - (13, 1024, 320, 576, 18446744073709551615, 1, 261, 2), - (13, 1024, 319, 575, 18446744073709551615, 1, 261, 2), - (13, 1024, 318, 574, 18446744073709551615, 1, 261, 2), - (13, 1024, 317, 573, 18446744073709551615, 1, 261, 2), - (13, 1024, 316, 572, 18446744073709551615, 1, 261, 2), - (13, 1024, 315, 571, 18446744073709551615, 1, 261, 2), - (13, 1024, 314, 570, 18446744073709551615, 1, 261, 2), - (13, 1024, 313, 569, 18446744073709551615, 1, 261, 2), - (13, 1024, 312, 568, 18446744073709551615, 1, 261, 2), - (13, 1024, 311, 567, 18446744073709551615, 1, 261, 2), - (13, 1024, 310, 566, 18446744073709551615, 1, 261, 2), - (13, 1024, 309, 565, 18446744073709551615, 1, 261, 2), - (13, 1024, 308, 564, 18446744073709551615, 1, 261, 2), - (13, 1024, 307, 563, 18446744073709551615, 1, 261, 2), - (13, 1024, 306, 562, 18446744073709551615, 1, 261, 2), - (13, 1024, 305, 561, 18446744073709551615, 1, 261, 2), - (13, 1024, 304, 560, 18446744073709551615, 1, 261, 2), - (13, 1024, 303, 559, 18446744073709551615, 1, 261, 2), - (13, 1024, 302, 558, 18446744073709551615, 1, 261, 2), - (13, 1024, 301, 557, 18446744073709551615, 1, 261, 2), - (13, 1024, 300, 556, 18446744073709551615, 1, 261, 2), - (13, 1024, 299, 555, 18446744073709551615, 1, 261, 2), - (13, 1024, 298, 554, 18446744073709551615, 1, 261, 2), - (13, 1024, 297, 553, 18446744073709551615, 1, 261, 2), - (13, 1024, 296, 552, 18446744073709551615, 1, 261, 2), - (13, 1024, 295, 551, 18446744073709551615, 1, 261, 2), - (13, 1024, 294, 550, 18446744073709551615, 1, 261, 2), - (13, 1024, 293, 549, 18446744073709551615, 1, 261, 2), - (13, 1024, 292, 548, 18446744073709551615, 1, 261, 2), - (13, 1024, 291, 547, 18446744073709551615, 1, 261, 2), - (13, 1024, 290, 546, 18446744073709551615, 1, 261, 2), - (13, 1024, 289, 545, 18446744073709551615, 1, 261, 2), - (13, 1024, 288, 544, 18446744073709551615, 1, 261, 2), - (13, 1024, 287, 543, 18446744073709551615, 1, 261, 2), - (13, 1024, 286, 542, 18446744073709551615, 1, 261, 2), - (13, 1024, 285, 541, 18446744073709551615, 1, 261, 2), - (13, 1024, 284, 540, 18446744073709551615, 1, 261, 2), - (13, 1024, 283, 539, 18446744073709551615, 1, 261, 2), - (13, 1024, 282, 538, 18446744073709551615, 1, 261, 2), - (13, 1024, 281, 537, 18446744073709551615, 1, 261, 2), - (13, 1024, 280, 536, 18446744073709551615, 1, 261, 2), - (13, 1024, 279, 535, 18446744073709551615, 1, 261, 2), - (13, 1024, 278, 534, 18446744073709551615, 1, 261, 2), - (13, 1024, 277, 533, 18446744073709551615, 1, 261, 2), - (13, 1024, 276, 532, 18446744073709551615, 1, 261, 2), - (13, 1024, 275, 531, 18446744073709551615, 1, 261, 2), - (13, 1024, 274, 530, 18446744073709551615, 1, 261, 2), - (13, 1024, 273, 529, 18446744073709551615, 1, 261, 2), - (13, 1024, 272, 528, 18446744073709551615, 1, 261, 2), - (13, 1024, 271, 527, 18446744073709551615, 1, 261, 2), - (13, 1024, 270, 526, 18446744073709551615, 1, 261, 2), - (13, 1024, 269, 525, 18446744073709551615, 1, 261, 2), - (13, 1024, 268, 524, 18446744073709551615, 1, 261, 2), - (13, 1024, 267, 523, 18446744073709551615, 1, 261, 2), - (13, 1024, 266, 522, 18446744073709551615, 1, 261, 2), - (13, 1024, 265, 521, 18446744073709551615, 1, 261, 2), - (13, 1024, 264, 520, 18446744073709551615, 1, 261, 2), - (13, 1024, 263, 519, 18446744073709551615, 1, 261, 2), - (13, 1024, 262, 518, 18446744073709551615, 1, 261, 2), - (13, 1024, 261, 517, 18446744073709551615, 1, 261, 2), - (13, 1024, 260, 516, 18446744073709551615, 1, 261, 2), - (13, 1024, 259, 515, 18446744073709551615, 1, 261, 2), - (13, 1024, 258, 514, 18446744073709551615, 1, 261, 2), - (13, 1024, 257, 513, 18446744073709551615, 1, 261, 2), - (13, 1024, 256, 512, 18446744073709551615, 1, 261, 2), - (13, 1024, 1092, 1027, 18446744073709551615, 0, 1, 1), - (13, 1024, 385, 641, 18446744073709551615, 1, 261, 2), - (13, 1024, 384, 640, 18446744073709551615, 1, 261, 2), - (13, 1024, 383, 639, 18446744073709551615, 1, 261, 2), - (13, 1024, 382, 638, 18446744073709551615, 1, 261, 2), - (13, 1024, 381, 637, 18446744073709551615, 1, 261, 2), - (13, 1024, 380, 636, 18446744073709551615, 1, 261, 2), - (13, 1024, 379, 635, 18446744073709551615, 1, 261, 2), - (13, 1024, 378, 634, 18446744073709551615, 1, 261, 2), - (13, 1024, 377, 633, 18446744073709551615, 1, 261, 2), - (13, 1024, 376, 632, 18446744073709551615, 1, 261, 2), - (13, 1024, 375, 631, 18446744073709551615, 1, 261, 2), - (13, 1024, 374, 630, 18446744073709551615, 1, 261, 2), - (13, 1024, 373, 629, 18446744073709551615, 1, 261, 2), - (13, 1024, 372, 628, 18446744073709551615, 1, 261, 2), - (13, 1024, 371, 627, 18446744073709551615, 1, 261, 2), - (13, 1024, 370, 626, 18446744073709551615, 1, 261, 2), - (13, 1024, 369, 625, 18446744073709551615, 1, 261, 2), - (13, 1024, 368, 624, 18446744073709551615, 1, 261, 2), - (13, 1024, 367, 623, 18446744073709551615, 1, 261, 2), - (13, 1024, 366, 622, 18446744073709551615, 1, 261, 2), - (13, 1024, 365, 621, 18446744073709551615, 1, 261, 2), - (13, 1024, 364, 620, 18446744073709551615, 1, 261, 2), - (13, 1024, 363, 619, 18446744073709551615, 1, 261, 2), - (13, 1024, 362, 618, 18446744073709551615, 1, 261, 2), - (13, 1024, 361, 617, 18446744073709551615, 1, 261, 2), - (13, 1024, 360, 616, 18446744073709551615, 1, 261, 2), - (13, 1024, 359, 615, 18446744073709551615, 1, 261, 2), - (13, 1024, 358, 614, 18446744073709551615, 1, 261, 2), - (13, 1024, 357, 613, 18446744073709551615, 1, 261, 2), - (13, 1024, 356, 612, 18446744073709551615, 1, 261, 2), - (13, 1024, 355, 611, 18446744073709551615, 1, 261, 2), - (13, 1024, 354, 610, 18446744073709551615, 1, 261, 2), - (13, 1024, 353, 609, 18446744073709551615, 1, 261, 2), - (13, 1024, 352, 608, 18446744073709551615, 1, 261, 2), - (13, 1024, 351, 607, 18446744073709551615, 1, 261, 2), - (13, 1024, 350, 606, 18446744073709551615, 1, 261, 2), - (13, 1024, 349, 605, 18446744073709551615, 1, 261, 2), - (13, 1024, 348, 604, 18446744073709551615, 1, 261, 2), - (13, 1024, 347, 603, 18446744073709551615, 1, 261, 2), - (13, 1024, 346, 602, 18446744073709551615, 1, 261, 2), - (13, 1024, 345, 601, 18446744073709551615, 1, 261, 2), - (13, 1024, 344, 600, 18446744073709551615, 1, 261, 2), - (13, 1024, 343, 599, 18446744073709551615, 1, 261, 2), - (13, 1024, 342, 598, 18446744073709551615, 1, 261, 2), - (13, 1024, 341, 597, 18446744073709551615, 1, 261, 2), - (13, 1024, 340, 596, 18446744073709551615, 1, 261, 2), - (13, 1024, 339, 595, 18446744073709551615, 1, 261, 2), - (13, 1024, 338, 594, 18446744073709551615, 1, 261, 2), - (13, 1024, 337, 593, 18446744073709551615, 1, 261, 2), - (13, 1024, 336, 592, 18446744073709551615, 1, 261, 2), - (13, 1024, 335, 591, 18446744073709551615, 1, 261, 2), - (13, 1024, 334, 590, 18446744073709551615, 1, 261, 2), - (13, 1024, 333, 589, 18446744073709551615, 1, 261, 2), - (13, 1024, 332, 588, 18446744073709551615, 1, 261, 2), - (13, 1024, 331, 587, 18446744073709551615, 1, 261, 2), - (13, 1024, 330, 586, 18446744073709551615, 1, 261, 2), - (13, 1024, 329, 585, 18446744073709551615, 1, 261, 2), - (13, 1024, 328, 584, 18446744073709551615, 1, 261, 2), - (13, 1024, 327, 583, 18446744073709551615, 1, 261, 2), - (13, 1024, 326, 582, 18446744073709551615, 1, 261, 2), - (13, 1024, 325, 581, 18446744073709551615, 1, 261, 2), - (13, 1024, 324, 580, 18446744073709551615, 1, 261, 2), - (13, 1024, 323, 579, 18446744073709551615, 1, 261, 2), - (13, 1024, 322, 578, 18446744073709551615, 1, 261, 2), - (13, 1024, 321, 577, 18446744073709551615, 1, 261, 2), - (13, 1024, 1153, 0, 18446744073709551615, 0, 1, 1), - (13, 1024, 511, 767, 18446744073709551615, 1, 261, 2), - (13, 1024, 510, 766, 18446744073709551615, 1, 261, 2), - (13, 1024, 509, 765, 18446744073709551615, 1, 261, 2), - (13, 1024, 508, 764, 18446744073709551615, 1, 261, 2), - (13, 1024, 507, 763, 18446744073709551615, 1, 261, 2), - (13, 1024, 506, 762, 18446744073709551615, 1, 261, 2), - (13, 1024, 505, 761, 18446744073709551615, 1, 261, 2), - (13, 1024, 504, 760, 18446744073709551615, 1, 261, 2), - (13, 1024, 503, 759, 18446744073709551615, 1, 261, 2), - (13, 1024, 502, 758, 18446744073709551615, 1, 261, 2), - (13, 1024, 501, 757, 18446744073709551615, 1, 261, 2), - (13, 1024, 500, 756, 18446744073709551615, 1, 261, 2), - (13, 1024, 499, 755, 18446744073709551615, 1, 261, 2), - (13, 1024, 498, 754, 18446744073709551615, 1, 261, 2), - (13, 1024, 497, 753, 18446744073709551615, 1, 261, 2), - (13, 1024, 496, 752, 18446744073709551615, 1, 261, 2), - (13, 1024, 495, 751, 18446744073709551615, 1, 261, 2), - (13, 1024, 494, 750, 18446744073709551615, 1, 261, 2), - (13, 1024, 493, 749, 18446744073709551615, 1, 261, 2), - (13, 1024, 492, 748, 18446744073709551615, 1, 261, 2), - (13, 1024, 491, 747, 18446744073709551615, 1, 261, 2), - (13, 1024, 490, 746, 18446744073709551615, 1, 261, 2), - (13, 1024, 489, 745, 18446744073709551615, 1, 261, 2), - (13, 1024, 488, 744, 18446744073709551615, 1, 261, 2), - (13, 1024, 487, 743, 18446744073709551615, 1, 261, 2), - (13, 1024, 486, 742, 18446744073709551615, 1, 261, 2), - (13, 1024, 485, 741, 18446744073709551615, 1, 261, 2), - (13, 1024, 484, 740, 18446744073709551615, 1, 261, 2), - (13, 1024, 483, 739, 18446744073709551615, 1, 261, 2), - (13, 1024, 482, 738, 18446744073709551615, 1, 261, 2), - (13, 1024, 481, 737, 18446744073709551615, 1, 261, 2), - (13, 1024, 480, 736, 18446744073709551615, 1, 261, 2), - (13, 1024, 479, 735, 18446744073709551615, 1, 261, 2), - (13, 1024, 478, 734, 18446744073709551615, 1, 261, 2), - (13, 1024, 477, 733, 18446744073709551615, 1, 261, 2), - (13, 1024, 476, 732, 18446744073709551615, 1, 261, 2), - (13, 1024, 475, 731, 18446744073709551615, 1, 261, 2), - (13, 1024, 474, 730, 18446744073709551615, 1, 261, 2), - (13, 1024, 473, 729, 18446744073709551615, 1, 261, 2), - (13, 1024, 472, 728, 18446744073709551615, 1, 261, 2), - (13, 1024, 471, 727, 18446744073709551615, 1, 261, 2), - (13, 1024, 470, 726, 18446744073709551615, 1, 261, 2), - (13, 1024, 469, 725, 18446744073709551615, 1, 261, 2), - (13, 1024, 468, 724, 18446744073709551615, 1, 261, 2), - (13, 1024, 467, 723, 18446744073709551615, 1, 261, 2), - (13, 1024, 466, 722, 18446744073709551615, 1, 261, 2), - (13, 1024, 465, 721, 18446744073709551615, 1, 261, 2), - (13, 1024, 464, 720, 18446744073709551615, 1, 261, 2), - (13, 1024, 463, 719, 18446744073709551615, 1, 261, 2), - (13, 1024, 462, 718, 18446744073709551615, 1, 261, 2), - (13, 1024, 461, 717, 18446744073709551615, 1, 261, 2), - (13, 1024, 460, 716, 18446744073709551615, 1, 261, 2), - (13, 1024, 459, 715, 18446744073709551615, 1, 261, 2), - (13, 1024, 458, 714, 18446744073709551615, 1, 261, 2), - (13, 1024, 457, 713, 18446744073709551615, 1, 261, 2), - (13, 1024, 456, 712, 18446744073709551615, 1, 261, 2), - (13, 1024, 455, 711, 18446744073709551615, 1, 261, 2), - (13, 1024, 454, 710, 18446744073709551615, 1, 261, 2), - (13, 1024, 453, 709, 18446744073709551615, 1, 261, 2), - (13, 1024, 452, 708, 18446744073709551615, 1, 261, 2), - (13, 1024, 451, 707, 18446744073709551615, 1, 261, 2), - (13, 1024, 450, 706, 18446744073709551615, 1, 261, 2), - (13, 1024, 449, 705, 18446744073709551615, 1, 261, 2), - (13, 1024, 448, 704, 18446744073709551615, 1, 261, 2), - (13, 1024, 447, 703, 18446744073709551615, 1, 261, 2), - (13, 1024, 446, 702, 18446744073709551615, 1, 261, 2), - (13, 1024, 445, 701, 18446744073709551615, 1, 261, 2), - (13, 1024, 444, 700, 18446744073709551615, 1, 261, 2), - (13, 1024, 443, 699, 18446744073709551615, 1, 261, 2), - (13, 1024, 442, 698, 18446744073709551615, 1, 261, 2), - (13, 1024, 441, 697, 18446744073709551615, 1, 261, 2), - (13, 1024, 440, 696, 18446744073709551615, 1, 261, 2), - (13, 1024, 439, 695, 18446744073709551615, 1, 261, 2), - (13, 1024, 438, 694, 18446744073709551615, 1, 261, 2), - (13, 1024, 437, 693, 18446744073709551615, 1, 261, 2), - (13, 1024, 436, 692, 18446744073709551615, 1, 261, 2), - (13, 1024, 435, 691, 18446744073709551615, 1, 261, 2), - (13, 1024, 434, 690, 18446744073709551615, 1, 261, 2), - (13, 1024, 433, 689, 18446744073709551615, 1, 261, 2), - (13, 1024, 432, 688, 18446744073709551615, 1, 261, 2), - (13, 1024, 431, 687, 18446744073709551615, 1, 261, 2), - (13, 1024, 430, 686, 18446744073709551615, 1, 261, 2), - (13, 1024, 429, 685, 18446744073709551615, 1, 261, 2), - (13, 1024, 428, 684, 18446744073709551615, 1, 261, 2), - (13, 1024, 427, 683, 18446744073709551615, 1, 261, 2), - (13, 1024, 426, 682, 18446744073709551615, 1, 261, 2), - (13, 1024, 425, 681, 18446744073709551615, 1, 261, 2), - (13, 1024, 424, 680, 18446744073709551615, 1, 261, 2), - (13, 1024, 423, 679, 18446744073709551615, 1, 261, 2), - (13, 1024, 422, 678, 18446744073709551615, 1, 261, 2), - (13, 1024, 421, 677, 18446744073709551615, 1, 261, 2), - (13, 1024, 420, 676, 18446744073709551615, 1, 261, 2), - (13, 1024, 419, 675, 18446744073709551615, 1, 261, 2), - (13, 1024, 418, 674, 18446744073709551615, 1, 261, 2), - (13, 1024, 417, 673, 18446744073709551615, 1, 261, 2), - (13, 1024, 416, 672, 18446744073709551615, 1, 261, 2), - (13, 1024, 415, 671, 18446744073709551615, 1, 261, 2), - (13, 1024, 414, 670, 18446744073709551615, 1, 261, 2), - (13, 1024, 413, 669, 18446744073709551615, 1, 261, 2), - (13, 1024, 412, 668, 18446744073709551615, 1, 261, 2), - (13, 1024, 411, 667, 18446744073709551615, 1, 261, 2), - (13, 1024, 410, 666, 18446744073709551615, 1, 261, 2), - (13, 1024, 409, 665, 18446744073709551615, 1, 261, 2), - (13, 1024, 408, 664, 18446744073709551615, 1, 261, 2), - (13, 1024, 407, 663, 18446744073709551615, 1, 261, 2), - (13, 1024, 406, 662, 18446744073709551615, 1, 261, 2), - (13, 1024, 405, 661, 18446744073709551615, 1, 261, 2), - (13, 1024, 404, 660, 18446744073709551615, 1, 261, 2), - (13, 1024, 403, 659, 18446744073709551615, 1, 261, 2), - (13, 1024, 402, 658, 18446744073709551615, 1, 261, 2), - (13, 1024, 401, 657, 18446744073709551615, 1, 261, 2), - (13, 1024, 400, 656, 18446744073709551615, 1, 261, 2), - (13, 1024, 399, 655, 18446744073709551615, 1, 261, 2), - (13, 1024, 398, 654, 18446744073709551615, 1, 261, 2), - (13, 1024, 397, 653, 18446744073709551615, 1, 261, 2), - (13, 1024, 396, 652, 18446744073709551615, 1, 261, 2), - (13, 1024, 395, 651, 18446744073709551615, 1, 261, 2), - (13, 1024, 394, 650, 18446744073709551615, 1, 261, 2), - (13, 1024, 393, 649, 18446744073709551615, 1, 261, 2), - (13, 1024, 392, 648, 18446744073709551615, 1, 261, 2), - (13, 1024, 391, 647, 18446744073709551615, 1, 261, 2), - (13, 1024, 390, 646, 18446744073709551615, 1, 261, 2), - (13, 1024, 389, 645, 18446744073709551615, 1, 261, 2), - (13, 1024, 388, 644, 18446744073709551615, 1, 261, 2), - (13, 1024, 387, 643, 18446744073709551615, 1, 261, 2), - (13, 1024, 386, 642, 18446744073709551615, 1, 261, 2), - (13, 512, 256, 1028, 18446744073709551615, 0, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 1, 11, 1), - (13, 543, 1058, 1059, 18446744073709551615, 0, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 2, 11, 1), - (13, 542, 1060, 1061, 18446744073709551615, 0, 1, 2), - (13, 543, 1061, 1062, 18446744073709551615, 0, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 3, 11, 1), - (14, 1024, 255, 1023, 18446744073709551615, 4, 11, 1), - (13, 542, 1064, 1065, 18446744073709551615, 1, 2, 2), - (13, 543, 1065, 1066, 18446744073709551615, 1, 2, 2), - (14, 1024, 255, 1023, 18446744073709551615, 5, 11, 1), - (13, 543, 1069, 1070, 18446744073709551615, 0, 1, 2), - (13, 542, 1067, 1068, 18446744073709551615, 0, 1, 2), - (13, 543, 1068, 1069, 18446744073709551615, 0, 1, 2), - (14, 1024, 255, 1023, 18446744073709551615, 6, 11, 2), - (13, 543, 1071, 1072, 18446744073709551615, 0, 1, 2), - (13, 543, 1076, 1077, 18446744073709551615, 0, 1, 2), - (13, 542, 1074, 1075, 18446744073709551615, 0, 1, 2), - (13, 543, 1080, 1081, 18446744073709551615, 0, 3, 2), - (13, 542, 1079, 1080, 18446744073709551615, 1, 3, 2), - (13, 1028, 1021, 253, 18446744073709551615, 11, 12, 2), - (13, 542, 1080, 1081, 18446744073709551615, 1, 5, 2), - (13, 543, 1081, 1082, 18446744073709551615, 1, 5, 2), - (13, 542, 1079, 1080, 18446744073709551615, 2, 3, 2), - (13, 543, 1080, 1081, 18446744073709551615, 2, 3, 2), - (13, 1028, 1019, 251, 18446744073709551615, 13, 14, 2), - (13, 543, 1083, 1084, 18446744073709551615, 0, 6, 2), - (13, 542, 1081, 1082, 18446744073709551615, 2, 6, 2), - (13, 1028, 1017, 249, 18446744073709551615, 15, 16, 2), - (13, 1028, 1016, 248, 18446744073709551615, 16, 17, 2), - (13, 542, 1081, 1082, 18446744073709551615, 4, 6, 2), - (13, 543, 1082, 1083, 18446744073709551615, 4, 6, 2), - (13, 1028, 1015, 247, 18446744073709551615, 17, 18, 2), - (13, 1028, 1014, 246, 18446744073709551615, 18, 19, 2), - (13, 543, 1083, 1084, 18446744073709551615, 4, 6, 2), - (13, 543, 1083, 1084, 18446744073709551615, 5, 6, 2), - (13, 543, 1084, 1085, 18446744073709551615, 4, 6, 2), - (13, 1028, 1008, 240, 18446744073709551615, 24, 25, 2), - (13, 542, 1083, 1084, 18446744073709551615, 5, 6, 2), - (13, 543, 1084, 1085, 18446744073709551615, 5, 6, 2), - (13, 1028, 1006, 238, 18446744073709551615, 26, 27, 2), - (14, 1024, 238, 1006, 18446744073709551615, 0, 1, 2), - (13, 542, 1085, 1086, 18446744073709551615, 2, 6, 2), - (13, 542, 1086, 1087, 18446744073709551615, 2, 6, 2), - (13, 543, 1087, 1088, 18446744073709551615, 2, 6, 2), - (13, 543, 1087, 1088, 18446744073709551615, 4, 6, 2), - (13, 542, 1086, 1087, 18446744073709551615, 5, 6, 2), - (13, 543, 1087, 1088, 18446744073709551615, 5, 6, 2), - (13, 543, 1088, 1089, 18446744073709551615, 4, 6, 2), - (14, 1024, 229, 997, 18446744073709551615, 0, 1, 2), - (13, 542, 1088, 1089, 18446744073709551615, 2, 6, 2), - (13, 543, 1089, 1090, 18446744073709551615, 2, 6, 2), - (13, 542, 1087, 1088, 18446744073709551615, 5, 6, 2), - (13, 543, 1088, 1089, 18446744073709551615, 5, 6, 2), - (13, 543, 1089, 1090, 18446744073709551615, 4, 6, 2), - (13, 543, 1090, 1091, 18446744073709551615, 2, 6, 2), - (13, 543, 1091, 1092, 18446744073709551615, 1, 6, 2), - (13, 543, 1092, 1093, 18446744073709551615, 1, 6, 2), - (13, 542, 1090, 1091, 18446744073709551615, 4, 6, 2), - (13, 542, 1091, 1092, 18446744073709551615, 2, 6, 2), - (14, 1024, 218, 986, 18446744073709551615, 0, 1, 2), - (13, 542, 1092, 1093, 18446744073709551615, 2, 6, 2), - (13, 543, 1093, 1094, 18446744073709551615, 2, 6, 2), - (13, 543, 1092, 1093, 18446744073709551615, 5, 6, 2), - (14, 1024, 214, 982, 18446744073709551615, 0, 1, 2), - (14, 1024, 213, 981, 18446744073709551615, 0, 1, 2), - (13, 542, 1092, 1093, 18446744073709551615, 5, 6, 2), - (13, 542, 1093, 1094, 18446744073709551615, 4, 6, 2), - (13, 543, 1094, 1095, 18446744073709551615, 4, 6, 2), - (13, 543, 1095, 1096, 18446744073709551615, 2, 6, 2), - (14, 1024, 210, 978, 18446744073709551615, 0, 1, 2), - (13, 543, 1095, 1096, 18446744073709551615, 3, 6, 2), - (13, 543, 1094, 1095, 18446744073709551615, 5, 6, 2), - (14, 1024, 209, 977, 18446744073709551615, 0, 1, 2), - (14, 1024, 208, 976, 18446744073709551615, 0, 1, 2), - (13, 542, 1095, 1096, 18446744073709551615, 2, 6, 2), - (14, 1024, 207, 975, 18446744073709551615, 0, 1, 2), - (13, 543, 1095, 1096, 18446744073709551615, 5, 6, 2), - (14, 1024, 206, 974, 18446744073709551615, 0, 1, 2), - (14, 1024, 204, 972, 18446744073709551615, 0, 1, 2), - (14, 1024, 203, 971, 18446744073709551615, 1, 2, 2), - (13, 542, 1096, 1097, 18446744073709551615, 4, 6, 2), - (13, 543, 1097, 1098, 18446744073709551615, 4, 6, 2), - (14, 1024, 202, 970, 18446744073709551615, 0, 1, 2), - (14, 1024, 201, 969, 18446744073709551615, 2, 3, 2), - (13, 542, 1097, 1098, 18446744073709551615, 4, 6, 2), - (13, 543, 1098, 1099, 18446744073709551615, 4, 6, 2), - (14, 1024, 199, 967, 18446744073709551615, 3, 4, 2), - (13, 542, 1098, 1099, 18446744073709551615, 2, 6, 2), - (13, 543, 1099, 1100, 18446744073709551615, 2, 6, 2), - (14, 1024, 198, 966, 18446744073709551615, 0, 1, 2), - (13, 542, 1097, 1098, 18446744073709551615, 5, 6, 2), - (14, 1024, 197, 965, 18446744073709551615, 3, 4, 2), - (13, 543, 1099, 1100, 18446744073709551615, 4, 6, 2), - (13, 542, 1098, 1099, 18446744073709551615, 5, 6, 2), - (13, 543, 1100, 1101, 18446744073709551615, 4, 6, 2), - (14, 1024, 193, 961, 18446744073709551615, 3, 4, 2), - (13, 542, 1100, 1101, 18446744073709551615, 2, 6, 2), - (13, 543, 1100, 1101, 18446744073709551615, 5, 6, 2), - (14, 1024, 191, 959, 18446744073709551615, 3, 4, 2), - (14, 1024, 190, 958, 18446744073709551615, 0, 1, 2), - (13, 542, 1101, 1102, 18446744073709551615, 2, 6, 2), - (13, 543, 1102, 1103, 18446744073709551615, 2, 6, 2), - (14, 1024, 189, 957, 18446744073709551615, 3, 4, 1), - (14, 1024, 188, 956, 18446744073709551615, 0, 1, 2), - (14, 1024, 187, 955, 18446744073709551615, 3, 4, 2), - (13, 542, 1102, 1103, 18446744073709551615, 2, 6, 2), - (13, 543, 1103, 1104, 18446744073709551615, 2, 6, 2), - (14, 1024, 186, 954, 18446744073709551615, 0, 1, 2), - (14, 1024, 185, 953, 18446744073709551615, 3, 4, 2), - (14, 1024, 184, 952, 18446744073709551615, 0, 1, 1), - (13, 542, 1103, 1104, 18446744073709551615, 2, 6, 2), - (14, 1024, 183, 951, 18446744073709551615, 3, 4, 2), - (13, 542, 1102, 1103, 18446744073709551615, 5, 6, 2), - (14, 1024, 182, 950, 18446744073709551615, 0, 1, 1), - (13, 543, 1104, 1105, 18446744073709551615, 4, 6, 2), - (13, 543, 1105, 1106, 18446744073709551615, 2, 6, 2), - (13, 542, 1103, 1104, 18446744073709551615, 5, 6, 2), - (14, 1024, 179, 947, 18446744073709551615, 3, 4, 2), - (13, 543, 1105, 1106, 18446744073709551615, 4, 6, 2), - (14, 1024, 178, 946, 18446744073709551615, 0, 1, 1), - (13, 542, 1104, 1105, 18446744073709551615, 5, 6, 2), - (14, 1024, 176, 944, 18446744073709551615, 0, 1, 1), - (14, 1024, 175, 943, 18446744073709551615, 3, 4, 1), - (13, 542, 1106, 1107, 18446744073709551615, 2, 7, 2), - (13, 543, 1107, 1108, 18446744073709551615, 2, 7, 2), - (14, 1024, 174, 942, 18446744073709551615, 0, 1, 1), - (14, 1024, 173, 941, 18446744073709551615, 3, 4, 2), - (13, 542, 1106, 1107, 18446744073709551615, 4, 7, 2), - (14, 1024, 172, 940, 18446744073709551615, 0, 2, 1), - (13, 542, 1107, 1108, 18446744073709551615, 2, 9, 2), - (13, 1028, 940, 172, 18446744073709551615, 93, 94, 2), - (13, 1028, 939, 171, 18446744073709551615, 94, 95, 2), - (14, 1024, 169, 937, 18446744073709551615, 3, 4, 1), - (13, 542, 1108, 1109, 18446744073709551615, 2, 10, 2), - (14, 1024, 168, 936, 18446744073709551615, 0, 1, 1), - (13, 543, 1108, 1109, 18446744073709551615, 3, 9, 2), - (14, 1024, 167, 935, 18446744073709551615, 3, 4, 1), - (14, 1024, 166, 934, 18446744073709551615, 0, 1, 1), - (13, 542, 1109, 1110, 18446744073709551615, 4, 9, 2), - (14, 1024, 165, 933, 18446744073709551615, 3, 4, 1), - (13, 542, 1108, 1109, 18446744073709551615, 5, 10, 2), - (13, 543, 1109, 1110, 18446744073709551615, 5, 10, 2), - (14, 1024, 163, 931, 18446744073709551615, 3, 4, 1), - (13, 543, 1108, 1109, 18446744073709551615, 4, 9, 2), - (14, 1024, 161, 929, 18446744073709551615, 3, 5, 1), - (13, 542, 1106, 1107, 18446744073709551615, 5, 7, 2), - (14, 1024, 161, 929, 18446744073709551615, 4, 5, 2), - (13, 542, 1107, 1108, 18446744073709551615, 6, 9, 2), - (14, 1024, 160, 928, 18446744073709551615, 0, 1, 2), - (13, 543, 1109, 1110, 18446744073709551615, 8, 10, 2), - (14, 1024, 159, 927, 18446744073709551615, 3, 4, 2), - (13, 542, 1109, 1110, 18446744073709551615, 7, 9, 2), - (14, 1024, 157, 925, 18446744073709551615, 3, 5, 1), - (13, 543, 1108, 1109, 18446744073709551615, 7, 9, 2), - (13, 543, 1107, 1108, 18446744073709551615, 6, 7, 2), - (14, 1024, 157, 925, 18446744073709551615, 4, 5, 2), - (13, 543, 1110, 1111, 18446744073709551615, 8, 9, 2), - (14, 1024, 156, 924, 18446744073709551615, 0, 1, 2), - (13, 542, 1110, 1111, 18446744073709551615, 4, 8, 2), - (13, 543, 1111, 1112, 18446744073709551615, 4, 8, 2), - (14, 1024, 154, 922, 18446744073709551615, 0, 2, 1), - (13, 542, 1107, 1108, 18446744073709551615, 8, 9, 2), - (14, 1024, 154, 922, 18446744073709551615, 1, 2, 1), - (14, 1024, 153, 921, 18446744073709551615, 3, 4, 2), - (13, 543, 1112, 1113, 18446744073709551615, 2, 10, 2), - (14, 1024, 152, 920, 18446744073709551615, 0, 1, 2), - (13, 543, 1111, 1112, 18446744073709551615, 6, 8, 2), - (14, 1024, 151, 919, 18446744073709551615, 3, 4, 2), - (13, 542, 1111, 1112, 18446744073709551615, 4, 10, 2), - (14, 1024, 150, 918, 18446744073709551615, 0, 1, 2), - (13, 542, 1112, 1113, 18446744073709551615, 2, 9, 2), - (14, 1024, 149, 917, 18446744073709551615, 3, 4, 2), - (13, 543, 1113, 1114, 18446744073709551615, 3, 9, 2), - (14, 1024, 148, 916, 18446744073709551615, 0, 1, 2), - (14, 1024, 146, 914, 18446744073709551615, 0, 1, 1), - (13, 542, 1111, 1112, 18446744073709551615, 6, 10, 2), - (13, 543, 1112, 1113, 18446744073709551615, 6, 10, 2), - (14, 1024, 145, 913, 18446744073709551615, 5, 6, 1), - (13, 543, 1111, 1112, 18446744073709551615, 7, 8, 2), - (14, 1024, 144, 912, 18446744073709551615, 0, 1, 1), - (13, 542, 1111, 1112, 18446744073709551615, 8, 10, 2), - (13, 543, 1112, 1113, 18446744073709551615, 8, 10, 2), - (14, 1024, 143, 911, 18446744073709551615, 5, 6, 1), - (14, 1024, 142, 910, 18446744073709551615, 0, 2, 1), - (14, 1024, 142, 910, 18446744073709551615, 1, 2, 2), - (14, 1024, 141, 909, 18446744073709551615, 4, 5, 2), - (13, 542, 1115, 1116, 18446744073709551615, 1, 4, 2), - (14, 1024, 140, 908, 18446744073709551615, 0, 1, 2), - (13, 542, 1114, 1115, 18446744073709551615, 1, 6, 2), - (14, 1024, 138, 906, 18446744073709551615, 0, 2, 1), - (13, 542, 1113, 1114, 18446744073709551615, 3, 9, 2), - (13, 543, 1114, 1115, 18446744073709551615, 3, 4, 2), - (14, 1024, 138, 906, 18446744073709551615, 1, 2, 2), - (13, 543, 1117, 1118, 18446744073709551615, 1, 6, 2), - (14, 1024, 137, 905, 18446744073709551615, 6, 7, 2), - (13, 543, 1116, 1117, 18446744073709551615, 3, 4, 2), - (14, 1024, 136, 904, 18446744073709551615, 0, 1, 2), - (13, 542, 1116, 1117, 18446744073709551615, 3, 7, 2), - (14, 1024, 135, 903, 18446744073709551615, 3, 4, 2), - (14, 1024, 134, 902, 18446744073709551615, 0, 1, 2), - (14, 1024, 133, 901, 18446744073709551615, 1, 2, 2), - (13, 542, 1117, 1118, 18446744073709551615, 4, 10, 2), - (14, 1024, 132, 900, 18446744073709551615, 0, 1, 2), - (13, 543, 1120, 1121, 18446744073709551615, 0, 4, 2), - (13, 542, 1118, 1119, 18446744073709551615, 2, 11, 2), - (14, 1024, 131, 899, 18446744073709551615, 2, 3, 2), - (13, 542, 1117, 1118, 18446744073709551615, 5, 10, 2), - (13, 543, 1118, 1119, 18446744073709551615, 5, 10, 2), - (14, 1024, 130, 898, 18446744073709551615, 0, 1, 2), - (13, 542, 1118, 1119, 18446744073709551615, 4, 11, 2), - (14, 1024, 128, 896, 18446744073709551615, 0, 1, 2), - (13, 543, 1118, 1119, 18446744073709551615, 6, 10, 2), - (14, 1024, 127, 895, 18446744073709551615, 3, 4, 1), - (13, 543, 1117, 1118, 18446744073709551615, 5, 6, 2), - (13, 126, 894, 895, 18446744073709551615, 0, 1, 2), - (14, 1024, 126, 894, 18446744073709551615, 0, 1, 2), - (14, 1024, 125, 893, 18446744073709551615, 6, 7, 2), - (14, 1024, 124, 892, 18446744073709551615, 0, 1, 1), - (13, 542, 1117, 1118, 18446744073709551615, 9, 10, 2), - (14, 1024, 123, 891, 18446744073709551615, 4, 6, 1), - (13, 543, 1120, 1121, 18446744073709551615, 3, 4, 2), - (14, 1024, 123, 891, 18446744073709551615, 5, 6, 2), - (14, 1024, 122, 890, 18446744073709551615, 0, 1, 2), - (13, 542, 1120, 1121, 18446744073709551615, 0, 4, 2), - (13, 543, 1121, 1122, 18446744073709551615, 0, 4, 2), - (14, 1024, 121, 889, 18446744073709551615, 0, 1, 2), - (13, 542, 1121, 1122, 18446744073709551615, 2, 10, 2), - (14, 1024, 119, 887, 18446744073709551615, 1, 3, 1), - (13, 543, 1122, 1123, 18446744073709551615, 3, 10, 2), - (13, 543, 1121, 1122, 18446744073709551615, 1, 4, 2), - (14, 1024, 119, 887, 18446744073709551615, 2, 3, 2), - (14, 1024, 117, 885, 18446744073709551615, 4, 5, 1), - (13, 543, 1121, 1122, 18446744073709551615, 2, 4, 2), - (14, 1024, 116, 884, 18446744073709551615, 1, 2, 1), - (13, 542, 1121, 1122, 18446744073709551615, 6, 10, 2), - (13, 543, 1122, 1123, 18446744073709551615, 6, 10, 2), - (14, 1024, 115, 883, 18446744073709551615, 0, 1, 1), - (14, 1024, 114, 882, 18446744073709551615, 0, 1, 1), - (13, 542, 1121, 1122, 18446744073709551615, 8, 10, 2), - (13, 543, 1122, 1123, 18446744073709551615, 8, 10, 2), - (14, 1024, 113, 881, 18446744073709551615, 1, 2, 1), - (13, 542, 1122, 1123, 18446744073709551615, 5, 9, 2), - (13, 543, 1123, 1124, 18446744073709551615, 5, 9, 2), - (14, 1024, 112, 880, 18446744073709551615, 0, 1, 1), - (13, 543, 1122, 1123, 18446744073709551615, 9, 10, 2), - (14, 1024, 111, 879, 18446744073709551615, 0, 1, 1), - (13, 542, 1122, 1123, 18446744073709551615, 7, 9, 2), - (13, 543, 1123, 1124, 18446744073709551615, 7, 9, 2), - (14, 1024, 110, 878, 18446744073709551615, 1, 2, 1), - (13, 543, 1125, 1126, 18446744073709551615, 0, 6, 2), - (14, 1024, 109, 877, 18446744073709551615, 1, 2, 1), - (14, 1024, 108, 876, 18446744073709551615, 0, 1, 1), - (14, 1024, 107, 875, 18446744073709551615, 0, 1, 1), - (13, 542, 1124, 1125, 18446744073709551615, 2, 6, 2), - (13, 543, 1125, 1126, 18446744073709551615, 2, 6, 2), - (14, 1024, 106, 874, 18446744073709551615, 1, 2, 1), - (14, 1024, 105, 873, 18446744073709551615, 0, 1, 1), - (13, 542, 1124, 1125, 18446744073709551615, 4, 6, 2), - (14, 1024, 104, 872, 18446744073709551615, 0, 1, 1), - (13, 542, 1125, 1126, 18446744073709551615, 2, 6, 2), - (14, 1024, 103, 871, 18446744073709551615, 1, 2, 1), - (13, 542, 1124, 1125, 18446744073709551615, 5, 6, 2), - (14, 1024, 102, 870, 18446744073709551615, 1, 2, 1), - (14, 1024, 101, 869, 18446744073709551615, 2, 3, 1), - (13, 542, 1126, 1127, 18446744073709551615, 2, 6, 2), - (14, 1024, 100, 868, 18446744073709551615, 3, 4, 1), - (13, 542, 1125, 1126, 18446744073709551615, 5, 6, 2), - (14, 1024, 99, 867, 18446744073709551615, 3, 4, 1), - (13, 543, 1128, 1129, 18446744073709551615, 1, 6, 2), - (13, 542, 1126, 1127, 18446744073709551615, 4, 6, 2), - (13, 543, 1127, 1128, 18446744073709551615, 4, 6, 2), - (14, 1024, 98, 866, 18446744073709551615, 3, 4, 1), - (13, 542, 1127, 1128, 18446744073709551615, 2, 6, 2), - (13, 543, 1128, 1129, 18446744073709551615, 2, 6, 2), - (14, 1024, 97, 865, 18446744073709551615, 3, 4, 1), - (13, 542, 1126, 1127, 18446744073709551615, 5, 6, 2), - (13, 543, 1127, 1128, 18446744073709551615, 5, 6, 2), - (14, 1024, 96, 864, 18446744073709551615, 3, 4, 1), - (13, 543, 1128, 1129, 18446744073709551615, 4, 6, 2), - (14, 1024, 95, 863, 18446744073709551615, 3, 4, 1), - (14, 1024, 94, 862, 18446744073709551615, 3, 4, 1), - (13, 542, 1127, 1128, 18446744073709551615, 5, 6, 2), - (14, 1024, 93, 861, 18446744073709551615, 3, 4, 1), - (13, 543, 1129, 1130, 18446744073709551615, 4, 6, 2), - (14, 1024, 92, 860, 18446744073709551615, 3, 4, 1), - (14, 1024, 91, 859, 18446744073709551615, 3, 4, 1), - (14, 1024, 90, 858, 18446744073709551615, 3, 4, 1), - (13, 542, 1129, 1130, 18446744073709551615, 4, 6, 2), - (13, 543, 1130, 1131, 18446744073709551615, 4, 6, 2), - (14, 1024, 89, 857, 18446744073709551615, 3, 4, 1), - (13, 542, 1130, 1131, 18446744073709551615, 2, 6, 2), - (14, 1024, 88, 856, 18446744073709551615, 3, 4, 1), - (13, 542, 1129, 1130, 18446744073709551615, 5, 6, 2), - (14, 1024, 87, 855, 18446744073709551615, 3, 4, 1), - (13, 543, 1131, 1132, 18446744073709551615, 4, 6, 2), - (14, 1024, 86, 854, 18446744073709551615, 3, 4, 1), - (13, 542, 1131, 1132, 18446744073709551615, 2, 6, 2), - (14, 1024, 85, 853, 18446744073709551615, 3, 4, 1), - (13, 543, 1132, 1133, 18446744073709551615, 3, 6, 2), - (13, 542, 1130, 1131, 18446744073709551615, 5, 6, 2), - (14, 1024, 84, 852, 18446744073709551615, 3, 4, 1), - (13, 543, 1132, 1133, 18446744073709551615, 4, 6, 2), - (14, 1024, 83, 851, 18446744073709551615, 3, 4, 1), - (14, 1024, 82, 850, 18446744073709551615, 3, 4, 1), - (13, 542, 1131, 1132, 18446744073709551615, 5, 6, 2), - (14, 1024, 81, 849, 18446744073709551615, 3, 4, 1), - (13, 543, 1133, 1134, 18446744073709551615, 4, 6, 2), - (14, 1024, 80, 848, 18446744073709551615, 3, 4, 1), - (13, 542, 1133, 1134, 18446744073709551615, 2, 6, 2), - (14, 1024, 79, 847, 18446744073709551615, 3, 4, 1), - (13, 542, 1132, 1133, 18446744073709551615, 5, 6, 2), - (13, 543, 1133, 1134, 18446744073709551615, 5, 6, 2), - (14, 1024, 78, 846, 18446744073709551615, 3, 4, 1), - (13, 542, 1133, 1134, 18446744073709551615, 4, 6, 2), - (14, 1024, 77, 845, 18446744073709551615, 3, 4, 1), - (14, 1024, 76, 844, 18446744073709551615, 3, 4, 1), - (14, 1024, 75, 843, 18446744073709551615, 3, 4, 1), - (14, 1024, 74, 842, 18446744073709551615, 4, 5, 1), - (13, 542, 1135, 1136, 18446744073709551615, 2, 6, 2), - (13, 543, 1136, 1137, 18446744073709551615, 2, 6, 2), - (13, 543, 1135, 1136, 18446744073709551615, 5, 6, 2), - (13, 542, 1135, 1136, 18446744073709551615, 4, 6, 2), - (13, 543, 1137, 1138, 18446744073709551615, 2, 6, 2), - (13, 542, 1135, 1136, 18446744073709551615, 5, 6, 2), - (13, 543, 1136, 1137, 18446744073709551615, 5, 6, 2), - (13, 543, 1137, 1138, 18446744073709551615, 4, 6, 2), - (13, 543, 1138, 1139, 18446744073709551615, 2, 6, 2), - (13, 543, 1137, 1138, 18446744073709551615, 5, 6, 2), - (13, 543, 1138, 1139, 18446744073709551615, 4, 6, 2), - (13, 542, 1138, 1139, 18446744073709551615, 0, 3, 2), - (13, 542, 1137, 1138, 18446744073709551615, 5, 6, 2), - (13, 542, 1138, 1139, 18446744073709551615, 1, 3, 2), - (13, 543, 1140, 1141, 18446744073709551615, 0, 3, 2), - (13, 543, 1139, 1140, 18446744073709551615, 2, 3, 2), - (13, 542, 1139, 1140, 18446744073709551615, 1, 3, 2), - (13, 543, 1140, 1141, 18446744073709551615, 1, 3, 2), - (13, 542, 1118, 1115, 18446744073709551615, 1, 6, 2), - (13, 542, 1139, 1140, 18446744073709551615, 2, 3, 2), - (13, 542, 1140, 1141, 18446744073709551615, 1, 3, 2), - (13, 543, 1141, 1142, 18446744073709551615, 1, 3, 2), - (13, 543, 1122, 1125, 18446744073709551615, 0, 1, 2), - (13, 543, 1141, 1142, 18446744073709551615, 2, 3, 2), - (13, 542, 1113, 1114, 18446744073709551615, 5, 9, 2), - (13, 542, 1142, 1143, 18446744073709551615, 0, 3, 2), - (13, 543, 1143, 1144, 18446744073709551615, 0, 3, 2), - (13, 542, 1141, 1142, 18446744073709551615, 2, 3, 2), - (13, 543, 1142, 1143, 18446744073709551615, 2, 3, 2), - (13, 542, 1142, 1143, 18446744073709551615, 1, 3, 2), - (13, 543, 1143, 1144, 18446744073709551615, 1, 3, 2), - (13, 543, 1144, 1145, 18446744073709551615, 0, 3, 2), - (13, 542, 1142, 1143, 18446744073709551615, 2, 3, 2), - (13, 543, 1143, 1144, 18446744073709551615, 2, 3, 2), - (13, 542, 1118, 1115, 18446744073709551615, 2, 6, 2), - (13, 543, 1114, 840, 18446744073709551615, 1, 3, 2), - (13, 544, 1147, 1148, 18446744073709551615, 0, 8, 1), - (13, 542, 1143, 1144, 18446744073709551615, 2, 3, 2), - (13, 543, 1144, 1145, 18446744073709551615, 2, 3, 2), - (13, 542, 1144, 1145, 18446744073709551615, 1, 3, 2), - (13, 544, 1147, 1148, 18446744073709551615, 1, 8, 1), - (13, 542, 1145, 1146, 18446744073709551615, 0, 3, 2), - (13, 543, 1147, 1148, 18446744073709551615, 0, 5, 1), - (13, 544, 1148, 1149, 18446744073709551615, 1, 8, 1), - (13, 542, 1144, 1145, 18446744073709551615, 2, 3, 2), - (13, 544, 1147, 1148, 18446744073709551615, 2, 8, 1), - (13, 543, 1147, 1148, 18446744073709551615, 1, 5, 1), - (13, 544, 1148, 1149, 18446744073709551615, 3, 8, 1), - (13, 542, 1118, 1115, 18446744073709551615, 3, 6, 2), - (13, 543, 1147, 1148, 18446744073709551615, 2, 5, 2), - (13, 542, 0, 1147, 18446744073709551615, 0, 1, 1), - (13, 543, 1147, 1148, 18446744073709551615, 3, 5, 1), - (13, 544, 1148, 1149, 18446744073709551615, 5, 8, 1), - (13, 543, 1146, 1148, 18446744073709551615, 2, 3, 2), - (13, 543, 1147, 1148, 18446744073709551615, 4, 5, 1), - (13, 544, 1148, 1149, 18446744073709551615, 7, 8, 1), - (13, 541, 1146, 1147, 18446744073709551615, 0, 4, 1), - (13, 542, 1147, 1148, 18446744073709551615, 1, 9, 1), - (13, 543, 1148, 1149, 18446744073709551615, 1, 10, 1), - (13, 544, 1149, 1150, 18446744073709551615, 1, 8, 1), - (13, 541, 1147, 1148, 18446744073709551615, 1, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 1, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 1, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 1, 20, 1), - (13, 542, 1147, 1148, 18446744073709551615, 2, 9, 2), - (13, 541, 1146, 1147, 18446744073709551615, 1, 4, 1), - (13, 542, 1147, 1148, 18446744073709551615, 3, 9, 1), - (13, 543, 1148, 1149, 18446744073709551615, 3, 10, 1), - (13, 544, 1149, 1150, 18446744073709551615, 3, 8, 1), - (13, 541, 1147, 1148, 18446744073709551615, 3, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 3, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 3, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 3, 20, 1), - (13, 541, 1147, 1148, 18446744073709551615, 5, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 5, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 5, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 5, 20, 1), - (13, 541, 1147, 1148, 18446744073709551615, 7, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 7, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 7, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 7, 20, 1), - (13, 542, 1115, 1113, 18446744073709551615, 3, 5, 2), - (13, 541, 1147, 1148, 18446744073709551615, 9, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 9, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 9, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 9, 20, 1), - (13, 541, 1148, 1149, 18446744073709551615, 1, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 1, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 1, 12, 1), - (13, 544, 1152, 1151, 18446744073709551615, 1, 12, 1), - (13, 541, 1147, 1148, 18446744073709551615, 11, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 11, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 11, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 11, 20, 1), - (13, 541, 1148, 1149, 18446744073709551615, 3, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 3, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 3, 12, 1), - (13, 544, 1152, 1151, 18446744073709551615, 3, 12, 1), - (13, 542, 1113, 1114, 18446744073709551615, 8, 9, 2), - (13, 544, 1147, 1148, 18446744073709551615, 3, 8, 1), - (13, 541, 1150, 1152, 18446744073709551615, 1, 6, 1), - (13, 542, 1152, 1151, 18446744073709551615, 1, 6, 1), - (13, 542, 1116, 1131, 18446744073709551615, 0, 1, 2), - (13, 541, 1148, 1149, 18446744073709551615, 5, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 5, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 5, 12, 1), - (13, 544, 1152, 1151, 18446744073709551615, 5, 12, 1), - (13, 543, 1118, 1114, 18446744073709551615, 2, 3, 2), - (13, 544, 1147, 1148, 18446744073709551615, 4, 8, 1), - (13, 542, 1152, 1151, 18446744073709551615, 3, 6, 1), - (13, 543, 1113, 1116, 18446744073709551615, 2, 3, 2), - (13, 544, 1147, 1148, 18446744073709551615, 5, 8, 1), - (13, 541, 1152, 1151, 18446744073709551615, 1, 4, 1), - (13, 542, 1151, 1153, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 25, 18446744073709551615, 0, 1, 1), - (13, 542, 1135, 1115, 18446744073709551615, 0, 1, 2), - (13, 541, 1146, 1147, 18446744073709551615, 2, 4, 1), - (13, 542, 1147, 1148, 18446744073709551615, 5, 9, 1), - (13, 543, 1148, 1149, 18446744073709551615, 5, 10, 1), - (13, 544, 1149, 1150, 18446744073709551615, 5, 8, 1), - (13, 0, 768, 791, 18446744073709551615, 0, 1, 1), - (13, 543, 1118, 793, 18446744073709551615, 0, 1, 2), - (13, 542, 1113, 1118, 18446744073709551615, 3, 4, 2), - (13, 541, 1147, 1148, 18446744073709551615, 13, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 13, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 13, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 13, 20, 1), - (13, 0, 768, 790, 18446744073709551615, 0, 1, 1), - (13, 543, 27, 1135, 18446744073709551615, 0, 1, 2), - (13, 562, 1152, 1151, 18446744073709551615, 35, 40, 1), - (13, 540, 1147, 1148, 18446744073709551615, 7, 12, 1), - (13, 541, 1148, 1149, 18446744073709551615, 7, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 7, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 7, 12, 1), - (13, 544, 1152, 1151, 18446744073709551615, 7, 12, 1), - (13, 0, 768, 789, 18446744073709551615, 0, 1, 1), - (13, 542, 1113, 840, 18446744073709551615, 0, 1, 2), - (13, 542, 793, 840, 18446744073709551615, 0, 1, 2), - (13, 540, 1146, 1147, 18446744073709551615, 7, 10, 1), - (13, 541, 1147, 1148, 18446744073709551615, 15, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 15, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 15, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 15, 20, 1), - (13, 0, 768, 788, 18446744073709551615, 0, 1, 1), - (13, 542, 794, 1113, 18446744073709551615, 0, 1, 2), - (13, 543, 1113, 27, 18446744073709551615, 0, 1, 2), - (13, 542, 1135, 1113, 18446744073709551615, 0, 1, 2), - (13, 562, 1152, 1151, 18446744073709551615, 37, 40, 1), - (13, 540, 1147, 1148, 18446744073709551615, 9, 12, 1), - (13, 541, 1148, 1149, 18446744073709551615, 9, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 9, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 9, 12, 1), - (13, 0, 768, 787, 18446744073709551615, 0, 1, 1), - (13, 543, 794, 793, 18446744073709551615, 0, 1, 2), - (13, 541, 1114, 1118, 18446744073709551615, 0, 1, 2), - (13, 562, 1150, 1152, 18446744073709551615, 7, 9, 1), - (13, 544, 1146, 1147, 18446744073709551615, 0, 3, 1), - (13, 540, 1148, 1149, 18446744073709551615, 1, 6, 1), - (13, 541, 1149, 1150, 18446744073709551615, 1, 6, 1), - (13, 542, 1150, 1152, 18446744073709551615, 1, 6, 1), - (13, 0, 768, 792, 18446744073709551615, 0, 1, 1), - (13, 541, 1116, 27, 18446744073709551615, 0, 1, 2), - (13, 543, 1132, 1135, 18446744073709551615, 0, 2, 2), - (13, 541, 1134, 836, 18446744073709551615, 0, 1, 2), - (13, 544, 1146, 1147, 18446744073709551615, 1, 3, 1), - (13, 539, 1148, 1149, 18446744073709551615, 5, 6, 1), - (13, 540, 1149, 1150, 18446744073709551615, 5, 6, 1), - (13, 541, 1150, 1152, 18446744073709551615, 5, 6, 1), - (13, 542, 1152, 1151, 18446744073709551615, 5, 6, 1), - (13, 0, 768, 786, 18446744073709551615, 0, 1, 1), - (13, 541, 1114, 793, 18446744073709551615, 0, 1, 2), - (13, 543, 1146, 1147, 18446744073709551615, 0, 1, 1), - (13, 544, 1147, 1148, 18446744073709551615, 7, 8, 1), - (13, 539, 1149, 1150, 18446744073709551615, 3, 6, 1), - (13, 540, 1150, 1152, 18446744073709551615, 3, 4, 1), - (13, 541, 1152, 1151, 18446744073709551615, 3, 4, 1), - (13, 0, 768, 27, 18446744073709551615, 2, 3, 1), - (13, 1028, 785, 17, 18446744073709551615, 245, 246, 2), - (13, 542, 1114, 1136, 18446744073709551615, 0, 1, 2), - (13, 542, 1137, 1136, 18446744073709551615, 0, 1, 2), - (13, 560, 1152, 1151, 18446744073709551615, 45, 48, 1), - (13, 540, 1146, 1147, 18446744073709551615, 8, 10, 1), - (13, 541, 1147, 1148, 18446744073709551615, 17, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 17, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 17, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 17, 20, 1), - (13, 538, 1152, 1151, 18446744073709551615, 1, 4, 1), - (13, 0, 768, 785, 18446744073709551615, 0, 1, 1), - (13, 1028, 784, 16, 18446744073709551615, 246, 247, 2), - (13, 540, 1113, 1118, 18446744073709551615, 0, 1, 2), - (13, 541, 1118, 836, 18446744073709551615, 0, 1, 2), - (13, 542, 836, 1134, 18446744073709551615, 0, 1, 2), - (13, 543, 1134, 1135, 18446744073709551615, 6, 7, 2), - (13, 541, 1132, 1114, 18446744073709551615, 0, 1, 2), - (13, 542, 1114, 1134, 18446744073709551615, 0, 1, 2), - (13, 560, 1150, 1152, 18446744073709551615, 29, 34, 1), - (13, 561, 1152, 1151, 18446744073709551615, 21, 24, 1), - (13, 541, 1146, 1147, 18446744073709551615, 3, 4, 1), - (13, 542, 1147, 1148, 18446744073709551615, 7, 9, 1), - (13, 543, 1148, 1149, 18446744073709551615, 7, 10, 1), - (13, 544, 1149, 1150, 18446744073709551615, 7, 8, 1), - (13, 538, 1150, 1152, 18446744073709551615, 1, 2, 1), - (13, 539, 1152, 1151, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 784, 18446744073709551615, 0, 1, 1), - (13, 1028, 783, 15, 18446744073709551615, 247, 248, 2), - (13, 540, 1114, 1138, 18446744073709551615, 0, 1, 2), - (13, 541, 1138, 836, 18446744073709551615, 0, 1, 2), - (13, 542, 836, 17, 18446744073709551615, 0, 1, 2), - (13, 540, 1136, 793, 18446744073709551615, 0, 1, 2), - (13, 541, 793, 1118, 18446744073709551615, 0, 1, 2), - (13, 542, 1118, 17, 18446744073709551615, 0, 1, 2), - (13, 559, 1150, 1152, 18446744073709551615, 41, 42, 1), - (13, 560, 1152, 1151, 18446744073709551615, 47, 48, 1), - (13, 540, 1146, 1147, 18446744073709551615, 9, 10, 1), - (13, 541, 1147, 1148, 18446744073709551615, 19, 20, 1), - (13, 542, 1148, 1149, 18446744073709551615, 19, 20, 1), - (13, 543, 1149, 1150, 18446744073709551615, 19, 20, 1), - (13, 544, 1150, 1152, 18446744073709551615, 19, 20, 1), - (13, 537, 1150, 1152, 18446744073709551615, 3, 4, 1), - (13, 538, 1152, 1151, 18446744073709551615, 3, 4, 1), - (13, 0, 768, 783, 18446744073709551615, 0, 3, 1), - (13, 1028, 782, 14, 18446744073709551615, 248, 250, 2), - (13, 541, 1137, 836, 18446744073709551615, 0, 1, 2), - (13, 542, 836, 16, 18446744073709551615, 0, 1, 2), - (13, 561, 1150, 1152, 18446744073709551615, 19, 20, 1), - (13, 562, 1152, 1151, 18446744073709551615, 39, 40, 1), - (13, 558, 1150, 1152, 18446744073709551615, 27, 28, 1), - (13, 559, 1152, 1151, 18446744073709551615, 27, 29, 1), - (13, 539, 1146, 1147, 18446744073709551615, 5, 6, 1), - (13, 540, 1147, 1148, 18446744073709551615, 11, 12, 1), - (13, 541, 1148, 1149, 18446744073709551615, 11, 13, 1), - (13, 542, 1149, 1150, 18446744073709551615, 11, 12, 1), - (13, 543, 1150, 1152, 18446744073709551615, 11, 12, 1), - (13, 544, 1152, 1151, 18446744073709551615, 11, 12, 1), - (13, 537, 1152, 1151, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 1114, 18446744073709551615, 0, 1, 1), - (13, 1028, 782, 14, 18446744073709551615, 249, 250, 2), - (13, 562, 1150, 1152, 18446744073709551615, 8, 9, 1), - (13, 559, 1149, 1150, 18446744073709551615, 20, 23, 1), - (13, 560, 1150, 1152, 18446744073709551615, 31, 34, 1), - (13, 544, 1146, 1147, 18446744073709551615, 2, 3, 1), - (13, 537, 1145, 1146, 18446744073709551615, 1, 3, 1), - (13, 538, 1146, 1147, 18446744073709551615, 3, 6, 1), - (13, 539, 1147, 1148, 18446744073709551615, 3, 6, 1), - (13, 540, 1148, 1149, 18446744073709551615, 3, 6, 1), - (13, 541, 1149, 1150, 18446744073709551615, 3, 6, 1), - (13, 542, 1150, 1152, 18446744073709551615, 3, 6, 1), - (13, 0, 768, 782, 18446744073709551615, 0, 1, 1), - (13, 1028, 781, 13, 18446744073709551615, 250, 253, 2), - (13, 538, 793, 836, 18446744073709551615, 0, 1, 2), - (13, 538, 783, 1141, 18446744073709551615, 0, 1, 2), - (13, 558, 1148, 1149, 18446744073709551615, 6, 7, 1), - (13, 559, 1149, 1150, 18446744073709551615, 22, 23, 1), - (13, 560, 1150, 1152, 18446744073709551615, 33, 34, 1), - (13, 561, 1152, 1151, 18446744073709551615, 23, 24, 1), - (13, 537, 1145, 1146, 18446744073709551615, 2, 3, 1), - (13, 538, 1146, 1147, 18446744073709551615, 5, 6, 1), - (13, 539, 1147, 1148, 18446744073709551615, 5, 6, 1), - (13, 540, 1148, 1149, 18446744073709551615, 5, 6, 1), - (13, 541, 1149, 1150, 18446744073709551615, 5, 6, 1), - (13, 542, 1150, 1152, 18446744073709551615, 5, 6, 1), - (13, 543, 1152, 1151, 18446744073709551615, 1, 2, 1), - (13, 535, 1152, 1151, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 1141, 18446744073709551615, 0, 9, 1), - (13, 537, 1151, 1152, 18446744073709551615, 0, 1, 2), - (13, 535, 1147, 1148, 18446744073709551615, 2, 4, 2), - (13, 560, 1152, 1150, 18446744073709551615, 0, 1, 1), - (13, 561, 1150, 1151, 18446744073709551615, 7, 8, 1), - (13, 562, 1151, 0, 18446744073709551615, 1, 2, 1), - (13, 557, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 558, 1151, 0, 18446744073709551615, 2, 3, 1), - (13, 542, 1147, 1148, 18446744073709551615, 8, 9, 1), - (13, 543, 1148, 1149, 18446744073709551615, 9, 10, 1), - (13, 544, 1149, 1152, 18446744073709551615, 1, 2, 1), - (13, 535, 1147, 1148, 18446744073709551615, 3, 4, 1), - (13, 536, 1148, 1149, 18446744073709551615, 3, 4, 1), - (13, 537, 1149, 1152, 18446744073709551615, 1, 2, 1), - (13, 538, 1152, 1150, 18446744073709551615, 1, 2, 1), - (13, 539, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 540, 1151, 0, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 15, 18446744073709551615, 2, 3, 1), - (13, 559, 1150, 1151, 18446744073709551615, 3, 4, 1), - (13, 560, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 561, 1132, 0, 18446744073709551615, 1, 2, 1), - (13, 556, 1151, 1132, 18446744073709551615, 1, 3, 1), - (13, 557, 1132, 0, 18446744073709551615, 1, 2, 1), - (13, 541, 1148, 1149, 18446744073709551615, 12, 13, 1), - (13, 542, 1149, 1152, 18446744073709551615, 1, 3, 1), - (13, 543, 1152, 1150, 18446744073709551615, 1, 4, 1), - (13, 544, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 534, 1148, 1149, 18446744073709551615, 3, 5, 1), - (13, 535, 1149, 1152, 18446744073709551615, 1, 4, 1), - (13, 536, 1152, 1150, 18446744073709551615, 1, 4, 1), - (13, 537, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 538, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 539, 1132, 0, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 13, 18446744073709551615, 0, 1, 1), - (13, 534, 1147, 1149, 18446744073709551615, 0, 1, 2), - (13, 535, 1149, 1152, 18446744073709551615, 2, 4, 2), - (13, 537, 1150, 1132, 18446744073709551615, 0, 2, 2), - (13, 560, 1132, 1151, 18446744073709551615, 1, 2, 1), - (13, 561, 1151, 1141, 18446744073709551615, 1, 2, 1), - (13, 562, 1141, 0, 18446744073709551615, 1, 2, 1), - (13, 555, 1150, 1132, 18446744073709551615, 0, 1, 1), - (13, 556, 1132, 1151, 18446744073709551615, 2, 3, 1), - (13, 557, 1151, 1141, 18446744073709551615, 1, 2, 1), - (13, 558, 1141, 0, 18446744073709551615, 1, 2, 1), - (13, 542, 1149, 1152, 18446744073709551615, 2, 3, 1), - (13, 543, 1152, 1150, 18446744073709551615, 3, 4, 1), - (13, 544, 1150, 1132, 18446744073709551615, 1, 2, 1), - (13, 534, 1148, 1149, 18446744073709551615, 4, 5, 1), - (13, 535, 1149, 1152, 18446744073709551615, 3, 4, 1), - (13, 536, 1152, 1150, 18446744073709551615, 3, 4, 1), - (13, 537, 1150, 1132, 18446744073709551615, 1, 2, 1), - (13, 538, 1132, 1151, 18446744073709551615, 2, 3, 1), - (13, 539, 1151, 1141, 18446744073709551615, 1, 2, 1), - (13, 540, 1141, 0, 18446744073709551615, 1, 2, 1), - (13, 532, 1141, 0, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 14, 18446744073709551615, 6, 7, 1), - (13, 537, 12, 1147, 18446744073709551615, 0, 1, 2), - (13, 538, 1147, 1149, 18446744073709551615, 0, 1, 2), - (13, 543, 1141, 12, 18446744073709551615, 0, 2, 2), - (13, 557, 1132, 1141, 18446744073709551615, 0, 2, 2), - (13, 560, 1132, 1141, 18446744073709551615, 0, 2, 1), - (13, 561, 1141, 12, 18446744073709551615, 1, 2, 1), - (13, 556, 1151, 1132, 18446744073709551615, 2, 3, 1), - (13, 557, 1132, 1141, 18446744073709551615, 1, 2, 1), - (13, 558, 1141, 12, 18446744073709551615, 1, 2, 1), - (13, 554, 1141, 12, 18446744073709551615, 1, 2, 1), - (13, 538, 1148, 1149, 18446744073709551615, 4, 5, 1), - (13, 539, 1149, 1150, 18446744073709551615, 5, 6, 1), - (13, 540, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 541, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 542, 1132, 1141, 18446744073709551615, 1, 2, 1), - (13, 543, 1141, 12, 18446744073709551615, 1, 2, 1), - (13, 532, 1149, 1150, 18446744073709551615, 1, 2, 1), - (13, 533, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 534, 1151, 1132, 18446744073709551615, 1, 3, 1), - (13, 535, 1132, 1141, 18446744073709551615, 1, 2, 1), - (13, 536, 1141, 12, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 11, 18446744073709551615, 0, 1, 1), - (13, 532, 1139, 0, 18446744073709551615, 0, 2, 2), - (13, 538, 12, 1141, 18446744073709551615, 0, 3, 2), - (13, 560, 12, 1141, 18446744073709551615, 0, 1, 1), - (13, 561, 1141, 1139, 18446744073709551615, 7, 8, 1), - (13, 562, 1139, 0, 18446744073709551615, 1, 2, 1), - (13, 555, 1132, 12, 18446744073709551615, 0, 1, 1), - (13, 556, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 557, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 558, 1139, 0, 18446744073709551615, 1, 2, 1), - (13, 553, 1139, 0, 18446744073709551615, 1, 2, 1), - (13, 542, 1150, 1151, 18446744073709551615, 0, 1, 1), - (13, 543, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 544, 1132, 12, 18446744073709551615, 1, 2, 1), - (13, 534, 1149, 1150, 18446744073709551615, 2, 3, 1), - (13, 535, 1150, 1151, 18446744073709551615, 1, 2, 1), - (13, 536, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 537, 1132, 12, 18446744073709551615, 1, 2, 1), - (13, 538, 12, 1141, 18446744073709551615, 1, 3, 1), - (13, 539, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 540, 1139, 0, 18446744073709551615, 1, 2, 1), - (13, 531, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 532, 1139, 0, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 777, 18446744073709551615, 0, 1, 1), - (13, 534, 1150, 1132, 18446744073709551615, 0, 1, 2), - (13, 536, 12, 1141, 18446744073709551615, 0, 2, 2), - (13, 552, 10, 0, 18446744073709551615, 0, 2, 2), - (13, 553, 0, 1153, 18446744073709551615, 0, 2, 2), - (13, 560, 1139, 10, 18446744073709551615, 0, 1, 1), - (13, 561, 10, 0, 18446744073709551615, 1, 2, 1), - (13, 562, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 555, 1141, 1139, 18446744073709551615, 0, 1, 1), - (13, 556, 1139, 10, 18446744073709551615, 1, 3, 1), - (13, 557, 10, 0, 18446744073709551615, 1, 2, 1), - (13, 558, 0, 1153, 18446744073709551615, 1, 4, 1), - (13, 551, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 552, 10, 0, 18446744073709551615, 1, 2, 1), - (13, 553, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 542, 1132, 12, 18446744073709551615, 0, 1, 1), - (13, 543, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 544, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 534, 1151, 1132, 18446744073709551615, 2, 3, 1), - (13, 535, 1132, 12, 18446744073709551615, 1, 2, 1), - (13, 536, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 537, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 538, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 539, 10, 0, 18446744073709551615, 1, 2, 1), - (13, 540, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 529, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 530, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 531, 10, 0, 18446744073709551615, 1, 2, 1), - (13, 532, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 1147, 18446744073709551615, 4, 5, 1), - (13, 530, 1150, 1132, 18446744073709551615, 0, 1, 2), - (13, 532, 12, 1141, 18446744073709551615, 0, 2, 2), - (13, 543, 9, 0, 18446744073709551615, 0, 2, 2), - (13, 551, 12, 1139, 18446744073709551615, 0, 1, 2), - (13, 555, 0, 1141, 18446744073709551615, 0, 1, 2), - (13, 559, 0, 1139, 18446744073709551615, 0, 1, 2), - (13, 560, 10, 9, 18446744073709551615, 0, 1, 1), - (13, 561, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 556, 1139, 10, 18446744073709551615, 2, 3, 1), - (13, 557, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 558, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 551, 1141, 1139, 18446744073709551615, 0, 1, 1), - (13, 552, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 553, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 554, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 538, 1132, 12, 18446744073709551615, 0, 1, 1), - (13, 539, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 540, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 541, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 542, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 543, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 530, 1151, 1132, 18446744073709551615, 2, 3, 1), - (13, 531, 1132, 12, 18446744073709551615, 1, 2, 1), - (13, 532, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 533, 1141, 1139, 18446744073709551615, 1, 2, 1), - (13, 534, 1139, 10, 18446744073709551615, 1, 2, 1), - (13, 535, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 536, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 781, 18446744073709551615, 0, 1, 1), - (13, 527, 9, 0, 18446744073709551615, 0, 2, 2), - (13, 529, 1153, 1151, 18446744073709551615, 0, 1, 2), - (13, 532, 1141, 10, 18446744073709551615, 0, 2, 2), - (13, 535, 9, 0, 18446744073709551615, 0, 2, 2), - (13, 549, 0, 1153, 18446744073709551615, 0, 2, 2), - (13, 560, 9, 0, 18446744073709551615, 0, 1, 1), - (13, 561, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 556, 793, 9, 18446744073709551615, 0, 1, 1), - (13, 557, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 558, 0, 1153, 18446744073709551615, 3, 4, 1), - (13, 551, 10, 793, 18446744073709551615, 0, 1, 1), - (13, 552, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 553, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 554, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 549, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 538, 12, 1141, 18446744073709551615, 2, 3, 1), - (13, 539, 1141, 10, 18446744073709551615, 1, 2, 1), - (13, 540, 10, 793, 18446744073709551615, 1, 2, 1), - (13, 541, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 542, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 543, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 530, 1132, 12, 18446744073709551615, 0, 1, 1), - (13, 531, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 532, 1141, 10, 18446744073709551615, 1, 2, 1), - (13, 533, 10, 793, 18446744073709551615, 1, 2, 1), - (13, 534, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 535, 9, 0, 18446744073709551615, 1, 2, 1), - (13, 536, 0, 1153, 18446744073709551615, 1, 2, 1), - (13, 0, 768, 1144, 18446744073709551615, 16, 17, 1), - (13, 1028, 769, 1, 18446744073709551615, 259, 260, 1), - (13, 1, 769, 768, 18446744073709551615, 224, 225, 2), - (13, 1152, 1144, 1149, 18446744073709551615, 0, 1, 2), - (13, 1152, 1144, 746, 18446744073709551615, 0, 1, 2), - (13, 755, 767, 1143, 18446744073709551615, 0, 1, 1), - (13, 755, 767, 1152, 18446744073709551615, 0, 1, 1), - (13, 752, 761, 1146, 18446744073709551615, 0, 3, 2), - (13, 766, 761, 752, 18446744073709551615, 1, 261, 2), - (13, 755, 767, 1146, 18446744073709551615, 0, 1, 1), - (13, 750, 759, 1148, 18446744073709551615, 0, 1, 2), - (13, 766, 759, 750, 18446744073709551615, 2, 261, 2), - (13, 765, 758, 749, 18446744073709551615, 2, 259, 2), - (13, 755, 767, 14, 18446744073709551615, 0, 1, 1), - (13, 749, 758, 1148, 18446744073709551615, 0, 1, 2), - (13, 766, 758, 749, 18446744073709551615, 3, 261, 2), - (13, 765, 756, 747, 18446744073709551615, 3, 259, 2), - (13, 755, 767, 778, 18446744073709551615, 0, 1, 1), - (13, 748, 757, 781, 18446744073709551615, 1, 4, 2), - (13, 747, 756, 1143, 18446744073709551615, 1, 4, 2), - (13, 766, 756, 747, 18446744073709551615, 4, 261, 2), - (13, 755, 767, 836, 18446744073709551615, 0, 1, 1), - (13, 747, 756, 746, 18446744073709551615, 0, 3, 2), - (13, 11, 779, 781, 18446744073709551615, 0, 3, 2), - (13, 766, 779, 11, 18446744073709551615, 1, 257, 2), - (13, 765, 779, 11, 18446744073709551615, 1, 255, 2), - (13, 755, 767, 780, 18446744073709551615, 0, 1, 1), - (13, 765, 778, 777, 18446744073709551615, 2, 255, 2), - (13, 755, 767, 1136, 18446744073709551615, 0, 1, 1), - (13, 765, 1148, 13, 18446744073709551615, 1, 253, 2), - (13, 765, 780, 1145, 18446744073709551615, 1, 253, 2), - (13, 755, 767, 783, 18446744073709551615, 0, 1, 1), - (13, 765, 1148, 13, 18446744073709551615, 2, 253, 2), - (13, 765, 780, 1145, 18446744073709551615, 2, 253, 2), - (13, 755, 767, 1137, 18446744073709551615, 0, 1, 1), - (13, 765, 780, 1145, 18446744073709551615, 3, 253, 2), - (13, 755, 767, 1138, 18446744073709551615, 0, 1, 1), - (13, 765, 1140, 1137, 18446744073709551615, 1, 250, 2), - (13, 755, 767, 17, 18446744073709551615, 0, 1, 1), - (13, 755, 767, 1134, 18446744073709551615, 0, 1, 1), - (13, 17, 1118, 746, 18446744073709551615, 0, 3, 2), - (13, 766, 1118, 17, 18446744073709551615, 1, 250, 2), - (13, 755, 767, 27, 18446744073709551615, 0, 1, 1), - (13, 1134, 16, 781, 18446744073709551615, 0, 2, 2), - (13, 766, 16, 1134, 18446744073709551615, 1, 249, 2), - (13, 755, 767, 1116, 18446744073709551615, 0, 1, 1), - (13, 766, 1113, 27, 18446744073709551615, 1, 248, 2), - (13, 765, 1113, 27, 18446744073709551615, 1, 246, 2), - (13, 755, 767, 786, 18446744073709551615, 0, 1, 1), - (13, 766, 785, 786, 18446744073709551615, 0, 246, 2), - (13, 765, 785, 786, 18446744073709551615, 0, 244, 2), - (13, 755, 767, 792, 18446744073709551615, 0, 1, 1), - (13, 765, 785, 786, 18446744073709551615, 1, 244, 2), - (13, 755, 767, 787, 18446744073709551615, 0, 1, 1), - (13, 766, 840, 787, 18446744073709551615, 0, 244, 2), - (13, 765, 840, 787, 18446744073709551615, 0, 242, 2), - (13, 755, 767, 788, 18446744073709551615, 0, 1, 1), - (13, 766, 794, 788, 18446744073709551615, 0, 243, 2), - (13, 765, 794, 788, 18446744073709551615, 0, 241, 2), - (13, 755, 767, 789, 18446744073709551615, 0, 1, 1), - (13, 766, 22, 789, 18446744073709551615, 0, 242, 2), - (13, 765, 22, 789, 18446744073709551615, 0, 240, 2), - (13, 755, 767, 790, 18446744073709551615, 0, 1, 1), - (13, 766, 1115, 790, 18446744073709551615, 0, 241, 2), - (13, 765, 1115, 790, 18446744073709551615, 0, 239, 2), - (13, 755, 767, 791, 18446744073709551615, 0, 1, 1), - (13, 766, 21, 791, 18446744073709551615, 0, 240, 2), - (13, 765, 21, 791, 18446744073709551615, 0, 238, 2), - (13, 755, 767, 25, 18446744073709551615, 0, 1, 1), - (13, 23, 26, 743, 18446744073709551615, 0, 4, 1), - (13, 20, 25, 743, 18446744073709551615, 0, 5, 2), - (13, 18, 24, 742, 18446744073709551615, 0, 5, 2), - (13, 766, 24, 18, 18446744073709551615, 1, 239, 2), - (13, 18, 24, 743, 18446744073709551615, 0, 6, 2), - (13, 795, 1131, 742, 18446744073709551615, 0, 6, 2), - (13, 766, 1131, 795, 18446744073709551615, 1, 238, 2), - (13, 796, 792, 740, 18446744073709551615, 0, 4, 2), - (13, 766, 30, 797, 18446744073709551615, 0, 236, 2), - (13, 766, 792, 796, 18446744073709551615, 1, 237, 2), - (13, 765, 30, 797, 18446744073709551615, 0, 234, 2), - (13, 797, 30, 740, 18446744073709551615, 0, 5, 2), - (13, 766, 1130, 798, 18446744073709551615, 0, 235, 2), - (13, 766, 30, 797, 18446744073709551615, 1, 236, 2), - (13, 765, 1130, 798, 18446744073709551615, 0, 233, 2), - (13, 798, 1130, 740, 18446744073709551615, 0, 6, 2), - (13, 766, 29, 799, 18446744073709551615, 0, 234, 2), - (13, 766, 1130, 798, 18446744073709551615, 1, 235, 2), - (13, 765, 29, 799, 18446744073709551615, 0, 232, 2), - (13, 799, 29, 738, 18446744073709551615, 0, 4, 2), - (13, 766, 33, 800, 18446744073709551615, 0, 233, 2), - (13, 766, 29, 799, 18446744073709551615, 1, 234, 2), - (13, 765, 33, 800, 18446744073709551615, 0, 231, 2), - (13, 800, 33, 738, 18446744073709551615, 0, 5, 2), - (13, 766, 33, 800, 18446744073709551615, 1, 233, 2), - (13, 801, 1129, 738, 18446744073709551615, 0, 6, 2), - (13, 766, 32, 802, 18446744073709551615, 0, 231, 2), - (13, 766, 1129, 801, 18446744073709551615, 1, 232, 2), - (13, 765, 32, 802, 18446744073709551615, 0, 229, 2), - (13, 802, 32, 736, 18446744073709551615, 0, 4, 2), - (13, 766, 32, 802, 18446744073709551615, 1, 231, 2), - (13, 803, 36, 736, 18446744073709551615, 0, 5, 2), - (13, 766, 1128, 804, 18446744073709551615, 0, 229, 2), - (13, 766, 36, 803, 18446744073709551615, 1, 230, 2), - (13, 765, 1128, 804, 18446744073709551615, 0, 227, 2), - (13, 804, 1128, 736, 18446744073709551615, 0, 4, 2), - (13, 766, 35, 805, 18446744073709551615, 0, 228, 2), - (13, 766, 1128, 804, 18446744073709551615, 1, 229, 2), - (13, 765, 35, 805, 18446744073709551615, 0, 226, 2), - (13, 805, 35, 734, 18446744073709551615, 0, 4, 2), - (13, 766, 39, 806, 18446744073709551615, 0, 227, 2), - (13, 766, 35, 805, 18446744073709551615, 1, 228, 2), - (13, 765, 39, 806, 18446744073709551615, 0, 225, 2), - (13, 806, 39, 734, 18446744073709551615, 0, 3, 2), - (13, 766, 1127, 807, 18446744073709551615, 0, 226, 2), - (13, 766, 39, 806, 18446744073709551615, 1, 227, 2), - (13, 765, 1127, 807, 18446744073709551615, 0, 224, 2), - (13, 807, 1127, 734, 18446744073709551615, 0, 5, 2), - (13, 766, 38, 808, 18446744073709551615, 0, 225, 2), - (13, 766, 1127, 807, 18446744073709551615, 1, 226, 2), - (13, 765, 38, 808, 18446744073709551615, 0, 223, 2), - (13, 808, 38, 732, 18446744073709551615, 0, 2, 2), - (13, 766, 42, 809, 18446744073709551615, 0, 224, 2), - (13, 766, 38, 808, 18446744073709551615, 1, 225, 2), - (13, 765, 42, 809, 18446744073709551615, 0, 222, 2), - (13, 809, 42, 732, 18446744073709551615, 0, 4, 2), - (13, 766, 1126, 810, 18446744073709551615, 0, 223, 2), - (13, 766, 42, 809, 18446744073709551615, 1, 224, 2), - (13, 765, 1126, 810, 18446744073709551615, 0, 221, 2), - (13, 810, 1126, 732, 18446744073709551615, 0, 6, 2), - (13, 766, 41, 811, 18446744073709551615, 0, 222, 2), - (13, 765, 41, 811, 18446744073709551615, 0, 220, 2), - (13, 811, 41, 730, 18446744073709551615, 0, 3, 2), - (13, 766, 1125, 813, 18446744073709551615, 0, 220, 2), - (13, 766, 44, 814, 18446744073709551615, 0, 219, 2), - (13, 766, 48, 815, 18446744073709551615, 0, 218, 2), - (13, 766, 44, 814, 18446744073709551615, 1, 219, 2), - (13, 766, 1124, 816, 18446744073709551615, 0, 217, 2), - (13, 766, 47, 817, 18446744073709551615, 0, 216, 2), - (13, 766, 51, 818, 18446744073709551615, 0, 215, 2), - (13, 818, 51, 726, 18446744073709551615, 0, 3, 2), - (13, 766, 1123, 819, 18446744073709551615, 0, 214, 2), - (13, 819, 1123, 726, 18446744073709551615, 0, 4, 2), - (13, 766, 50, 820, 18446744073709551615, 0, 213, 2), - (13, 820, 50, 724, 18446744073709551615, 1, 2, 2), - (13, 766, 54, 821, 18446744073709551615, 0, 212, 2), - (13, 765, 54, 821, 18446744073709551615, 0, 210, 2), - (13, 766, 1122, 822, 18446744073709551615, 0, 211, 2), - (13, 766, 53, 823, 18446744073709551615, 0, 210, 2), - (13, 766, 57, 824, 18446744073709551615, 0, 209, 2), - (13, 765, 57, 824, 18446744073709551615, 0, 207, 2), - (13, 766, 1121, 825, 18446744073709551615, 0, 208, 2), - (13, 766, 56, 826, 18446744073709551615, 0, 207, 2), - (13, 766, 60, 827, 18446744073709551615, 0, 206, 2), - (13, 765, 60, 827, 18446744073709551615, 0, 204, 2), - (13, 766, 1120, 828, 18446744073709551615, 0, 205, 2), - (13, 765, 1120, 828, 18446744073709551615, 0, 203, 2), - (13, 766, 59, 829, 18446744073709551615, 0, 204, 2), - (13, 766, 63, 830, 18446744073709551615, 0, 203, 2), - (13, 766, 1117, 831, 18446744073709551615, 0, 202, 2), - (13, 766, 62, 832, 18446744073709551615, 0, 201, 2), - (13, 766, 66, 833, 18446744073709551615, 0, 200, 2), - (13, 766, 1119, 834, 18446744073709551615, 0, 199, 2), - (13, 766, 65, 835, 18446744073709551615, 0, 198, 2), - (13, 766, 1112, 69, 18446744073709551615, 0, 197, 2), - (13, 766, 838, 837, 18446744073709551615, 0, 196, 2), - (13, 766, 68, 839, 18446744073709551615, 0, 195, 2), - (13, 766, 1111, 72, 18446744073709551615, 0, 194, 2), - (13, 766, 843, 841, 18446744073709551615, 0, 193, 2), - (13, 766, 71, 842, 18446744073709551615, 0, 192, 2), - (13, 766, 1110, 75, 18446744073709551615, 0, 191, 2), - (13, 766, 846, 844, 18446744073709551615, 0, 190, 2), - (13, 766, 74, 845, 18446744073709551615, 0, 189, 2), - (13, 766, 1109, 78, 18446744073709551615, 0, 188, 2), - (13, 766, 849, 847, 18446744073709551615, 0, 187, 2), - (13, 766, 77, 848, 18446744073709551615, 0, 186, 2), - (13, 766, 1108, 81, 18446744073709551615, 0, 185, 2), - (13, 766, 852, 850, 18446744073709551615, 0, 184, 2), - (13, 766, 80, 851, 18446744073709551615, 0, 183, 2), - (13, 766, 1107, 84, 18446744073709551615, 0, 182, 2), - (13, 766, 855, 853, 18446744073709551615, 0, 181, 2), - (13, 766, 83, 854, 18446744073709551615, 0, 180, 2), - (13, 766, 1106, 87, 18446744073709551615, 0, 179, 2), - (13, 766, 858, 856, 18446744073709551615, 0, 178, 2), - (13, 766, 86, 857, 18446744073709551615, 0, 177, 2), - (13, 766, 1105, 90, 18446744073709551615, 0, 176, 2), - (13, 765, 1105, 90, 18446744073709551615, 0, 174, 2), - (13, 766, 861, 859, 18446744073709551615, 0, 175, 2), - (13, 765, 861, 859, 18446744073709551615, 0, 173, 2), - (13, 766, 89, 860, 18446744073709551615, 0, 174, 2), - (13, 766, 1104, 93, 18446744073709551615, 0, 173, 2), - (13, 766, 864, 862, 18446744073709551615, 0, 172, 2), - (13, 766, 92, 863, 18446744073709551615, 0, 171, 2), - (13, 766, 1103, 96, 18446744073709551615, 0, 170, 2), - (13, 766, 867, 865, 18446744073709551615, 0, 169, 2), - (13, 766, 95, 866, 18446744073709551615, 0, 168, 2), - (13, 766, 1102, 99, 18446744073709551615, 0, 167, 2), - (13, 766, 870, 868, 18446744073709551615, 0, 166, 2), - (13, 766, 98, 869, 18446744073709551615, 0, 165, 2), - (13, 766, 1101, 102, 18446744073709551615, 0, 164, 2), - (13, 766, 873, 871, 18446744073709551615, 0, 163, 2), - (13, 765, 873, 871, 18446744073709551615, 0, 161, 2), - (13, 766, 101, 872, 18446744073709551615, 0, 162, 2), - (13, 766, 1100, 105, 18446744073709551615, 0, 161, 2), - (13, 766, 876, 874, 18446744073709551615, 0, 160, 2), - (13, 765, 876, 874, 18446744073709551615, 0, 158, 2), - (13, 766, 104, 875, 18446744073709551615, 0, 159, 2), - (13, 766, 1099, 108, 18446744073709551615, 0, 158, 2), - (13, 766, 879, 877, 18446744073709551615, 0, 157, 2), - (13, 765, 879, 877, 18446744073709551615, 0, 155, 2), - (13, 766, 107, 878, 18446744073709551615, 0, 156, 2), - (13, 766, 1098, 111, 18446744073709551615, 0, 155, 2), - (13, 765, 1098, 111, 18446744073709551615, 0, 153, 2), - (13, 766, 882, 880, 18446744073709551615, 0, 154, 2), - (13, 766, 110, 881, 18446744073709551615, 0, 153, 2), - (13, 766, 894, 114, 18446744073709551615, 0, 152, 2), - (13, 765, 894, 114, 18446744073709551615, 0, 150, 2), - (13, 766, 885, 883, 18446744073709551615, 0, 151, 2), - (13, 766, 113, 884, 18446744073709551615, 0, 150, 2), - (13, 766, 887, 117, 18446744073709551615, 0, 149, 2), - (13, 766, 1097, 119, 18446744073709551615, 0, 148, 2), - (13, 118, 116, 679, 18446744073709551615, 0, 3, 1), - (13, 766, 116, 118, 18446744073709551615, 0, 147, 2), - (13, 766, 886, 115, 18446744073709551615, 1, 147, 2), - (13, 890, 889, 677, 18446744073709551615, 0, 2, 1), - (13, 766, 889, 890, 18446744073709551615, 0, 145, 2), - (13, 1116, 888, 677, 18446744073709551615, 0, 1, 2), - (13, 766, 121, 891, 18446744073709551615, 0, 144, 2), - (13, 766, 888, 1116, 18446744073709551615, 1, 145, 2), - (13, 891, 121, 675, 18446744073709551615, 0, 1, 2), - (13, 766, 901, 892, 18446744073709551615, 0, 143, 2), - (13, 766, 121, 891, 18446744073709551615, 1, 144, 2), - (13, 766, 901, 892, 18446744073709551615, 1, 143, 2), - (13, 766, 123, 893, 18446744073709551615, 0, 141, 2), - (13, 766, 899, 126, 18446744073709551615, 0, 140, 2), - (13, 766, 130, 895, 18446744073709551615, 0, 139, 2), - (13, 766, 125, 896, 18446744073709551615, 0, 138, 2), - (13, 766, 1094, 129, 18446744073709551615, 0, 137, 2), - (13, 765, 1094, 129, 18446744073709551615, 0, 135, 2), - (13, 127, 898, 671, 18446744073709551615, 0, 2, 1), - (13, 766, 898, 127, 18446744073709551615, 0, 136, 2), - (13, 1095, 897, 671, 18446744073709551615, 0, 3, 2), - (13, 766, 128, 900, 18446744073709551615, 0, 135, 2), - (13, 766, 897, 1095, 18446744073709551615, 1, 136, 2), - (13, 900, 128, 669, 18446744073709551615, 0, 1, 2), - (13, 766, 1093, 133, 18446744073709551615, 0, 134, 2), - (13, 133, 1093, 669, 18446744073709551615, 0, 2, 2), - (13, 766, 904, 902, 18446744073709551615, 0, 133, 2), - (13, 766, 132, 903, 18446744073709551615, 0, 132, 2), - (13, 766, 1092, 136, 18446744073709551615, 0, 131, 2), - (13, 766, 909, 905, 18446744073709551615, 0, 130, 2), - (13, 766, 135, 906, 18446744073709551615, 0, 129, 2), - (13, 766, 908, 140, 18446744073709551615, 0, 128, 2), - (13, 139, 138, 665, 18446744073709551615, 0, 2, 1), - (13, 766, 1089, 142, 18446744073709551615, 0, 125, 2), - (13, 766, 1090, 919, 18446744073709551615, 0, 124, 2), - (13, 765, 1090, 919, 18446744073709551615, 0, 122, 2), - (13, 766, 143, 914, 18446744073709551615, 0, 120, 2), - (13, 766, 1088, 147, 18446744073709551615, 0, 119, 2), - (13, 145, 916, 659, 18446744073709551615, 0, 2, 1), - (13, 911, 915, 659, 18446744073709551615, 0, 3, 2), - (13, 766, 146, 918, 18446744073709551615, 0, 117, 2), - (13, 766, 915, 911, 18446744073709551615, 1, 118, 2), - (13, 918, 146, 657, 18446744073709551615, 0, 1, 2), - (13, 766, 1087, 151, 18446744073709551615, 0, 116, 2), - (13, 151, 1087, 657, 18446744073709551615, 0, 2, 2), - (13, 766, 922, 920, 18446744073709551615, 0, 115, 2), - (13, 766, 150, 921, 18446744073709551615, 0, 114, 2), - (13, 766, 1086, 154, 18446744073709551615, 0, 113, 2), - (13, 766, 925, 157, 18446744073709551615, 0, 112, 2), - (13, 155, 924, 653, 18446744073709551615, 0, 1, 1), - (13, 153, 923, 653, 18446744073709551615, 0, 4, 2), - (13, 766, 928, 160, 18446744073709551615, 0, 109, 2), - (13, 765, 928, 160, 18446744073709551615, 0, 107, 2), - (13, 158, 927, 651, 18446744073709551615, 0, 3, 1), - (13, 766, 1085, 929, 18446744073709551615, 0, 106, 2), - (13, 765, 1085, 929, 18446744073709551615, 0, 104, 2), - (13, 766, 934, 933, 18446744073709551615, 0, 105, 2), - (13, 165, 931, 649, 18446744073709551615, 0, 3, 1), - (13, 164, 163, 646, 18446744073709551615, 0, 4, 1), - (13, 766, 163, 164, 18446744073709551615, 0, 102, 2), - (13, 162, 932, 644, 18446744073709551615, 0, 2, 2), - (13, 766, 940, 167, 18446744073709551615, 0, 101, 2), - (13, 766, 932, 162, 18446744073709551615, 1, 102, 2), - (13, 167, 940, 644, 18446744073709551615, 0, 3, 2), - (13, 766, 171, 936, 18446744073709551615, 0, 100, 2), - (13, 766, 940, 167, 18446744073709551615, 1, 101, 2), - (13, 936, 171, 644, 18446744073709551615, 0, 2, 2), - (13, 766, 166, 937, 18446744073709551615, 0, 99, 2), - (13, 766, 171, 936, 18446744073709551615, 1, 100, 2), - (13, 766, 1084, 170, 18446744073709551615, 0, 98, 2), - (13, 766, 166, 937, 18446744073709551615, 1, 99, 2), - (13, 168, 939, 639, 18446744073709551615, 0, 1, 1), - (13, 766, 939, 168, 18446744073709551615, 0, 97, 2), - (13, 168, 939, 640, 18446744073709551615, 0, 1, 2), - (13, 156, 938, 639, 18446744073709551615, 0, 1, 2), - (13, 766, 169, 1082, 18446744073709551615, 0, 96, 2), - (13, 766, 938, 156, 18446744073709551615, 1, 97, 2), - (13, 766, 939, 168, 18446744073709551615, 1, 97, 2), - (13, 766, 169, 1082, 18446744073709551615, 1, 96, 2), - (13, 766, 944, 942, 18446744073709551615, 0, 94, 2), - (13, 766, 941, 943, 18446744073709551615, 0, 93, 2), - (13, 766, 1081, 176, 18446744073709551615, 0, 92, 2), - (13, 766, 947, 945, 18446744073709551615, 0, 91, 2), - (13, 765, 947, 945, 18446744073709551615, 0, 89, 2), - (13, 766, 175, 946, 18446744073709551615, 0, 90, 2), - (13, 766, 1080, 179, 18446744073709551615, 0, 89, 2), - (13, 766, 950, 948, 18446744073709551615, 0, 88, 2), - (13, 765, 950, 948, 18446744073709551615, 0, 86, 2), - (13, 766, 178, 949, 18446744073709551615, 0, 87, 2), - (13, 766, 1079, 182, 18446744073709551615, 0, 86, 2), - (13, 766, 953, 951, 18446744073709551615, 0, 85, 2), - (13, 765, 953, 951, 18446744073709551615, 0, 83, 2), - (13, 766, 181, 952, 18446744073709551615, 0, 84, 2), - (13, 766, 1078, 185, 18446744073709551615, 0, 83, 2), - (13, 766, 956, 954, 18446744073709551615, 0, 82, 2), - (13, 766, 184, 955, 18446744073709551615, 0, 81, 2), - (13, 766, 1077, 188, 18446744073709551615, 0, 80, 2), - (13, 766, 959, 957, 18446744073709551615, 0, 79, 2), - (13, 766, 187, 958, 18446744073709551615, 0, 78, 2), - (13, 765, 187, 958, 18446744073709551615, 0, 76, 2), - (13, 766, 1076, 191, 18446744073709551615, 0, 77, 2), - (13, 766, 962, 960, 18446744073709551615, 0, 76, 2), - (13, 766, 190, 961, 18446744073709551615, 0, 75, 2), - (13, 765, 190, 961, 18446744073709551615, 0, 73, 2), - (13, 766, 1075, 194, 18446744073709551615, 0, 74, 2), - (13, 766, 965, 963, 18446744073709551615, 0, 73, 2), - (13, 766, 193, 964, 18446744073709551615, 0, 72, 2), - (13, 766, 1074, 197, 18446744073709551615, 0, 71, 2), - (13, 766, 968, 966, 18446744073709551615, 0, 70, 2), - (13, 766, 196, 967, 18446744073709551615, 0, 69, 2), - (13, 766, 1073, 200, 18446744073709551615, 0, 68, 2), - (13, 766, 971, 969, 18446744073709551615, 0, 67, 2), - (13, 766, 199, 970, 18446744073709551615, 0, 66, 2), - (13, 765, 199, 970, 18446744073709551615, 0, 64, 2), - (13, 766, 1072, 203, 18446744073709551615, 0, 65, 2), - (13, 766, 974, 972, 18446744073709551615, 0, 64, 2), - (13, 766, 202, 973, 18446744073709551615, 0, 63, 2), - (13, 766, 1071, 206, 18446744073709551615, 0, 62, 2), - (13, 766, 977, 975, 18446744073709551615, 0, 61, 2), - (13, 766, 205, 976, 18446744073709551615, 0, 60, 2), - (13, 766, 1070, 209, 18446744073709551615, 0, 59, 2), - (13, 766, 980, 978, 18446744073709551615, 0, 58, 2), - (13, 765, 980, 978, 18446744073709551615, 0, 56, 2), - (13, 766, 208, 979, 18446744073709551615, 0, 57, 2), - (13, 766, 1069, 212, 18446744073709551615, 0, 56, 2), - (13, 766, 983, 981, 18446744073709551615, 0, 55, 2), - (13, 766, 211, 982, 18446744073709551615, 0, 54, 2), - (13, 766, 1068, 215, 18446744073709551615, 0, 53, 2), - (13, 766, 986, 984, 18446744073709551615, 0, 52, 2), - (13, 766, 214, 985, 18446744073709551615, 0, 51, 2), - (13, 766, 1067, 218, 18446744073709551615, 0, 50, 2), - (13, 766, 989, 987, 18446744073709551615, 0, 49, 2), - (13, 766, 217, 988, 18446744073709551615, 0, 48, 2), - (13, 766, 1066, 221, 18446744073709551615, 0, 47, 2), - (13, 766, 992, 990, 18446744073709551615, 0, 46, 2), - (13, 766, 220, 991, 18446744073709551615, 0, 45, 2), - (13, 766, 1065, 224, 18446744073709551615, 0, 44, 2), - (13, 766, 995, 993, 18446744073709551615, 0, 43, 2), - (13, 766, 223, 994, 18446744073709551615, 0, 42, 2), - (13, 766, 1064, 227, 18446744073709551615, 0, 41, 2), - (13, 766, 998, 996, 18446744073709551615, 0, 40, 2), - (13, 765, 998, 996, 18446744073709551615, 0, 38, 2), - (13, 766, 226, 997, 18446744073709551615, 0, 39, 2), - (13, 766, 1063, 230, 18446744073709551615, 0, 38, 2), - (13, 766, 1001, 999, 18446744073709551615, 0, 37, 2), - (13, 765, 1001, 999, 18446744073709551615, 0, 35, 2), - (13, 766, 229, 1000, 18446744073709551615, 0, 36, 2), - (13, 766, 1062, 233, 18446744073709551615, 0, 35, 2), - (13, 766, 1004, 1002, 18446744073709551615, 0, 34, 2), - (13, 766, 232, 1003, 18446744073709551615, 0, 33, 2), - (13, 766, 1061, 236, 18446744073709551615, 0, 32, 2), - (13, 765, 1061, 236, 18446744073709551615, 0, 30, 2), - (13, 766, 1007, 1005, 18446744073709551615, 0, 31, 2), - (13, 766, 235, 1006, 18446744073709551615, 0, 30, 2), - (13, 766, 1060, 239, 18446744073709551615, 0, 29, 2), - (13, 765, 1060, 239, 18446744073709551615, 0, 27, 2), - (13, 766, 1010, 1008, 18446744073709551615, 0, 28, 2), - (13, 766, 238, 1009, 18446744073709551615, 0, 27, 2), - (13, 766, 1059, 242, 18446744073709551615, 0, 26, 2), - (13, 765, 1059, 242, 18446744073709551615, 0, 24, 2), - (13, 766, 1013, 1011, 18446744073709551615, 0, 25, 2), - (13, 766, 241, 1012, 18446744073709551615, 0, 24, 2), - (13, 766, 1058, 245, 18446744073709551615, 0, 23, 2), - (13, 766, 1016, 1014, 18446744073709551615, 0, 22, 2), - (13, 765, 1016, 1014, 18446744073709551615, 0, 20, 2), - (13, 766, 244, 1015, 18446744073709551615, 0, 21, 2), - (13, 766, 1057, 248, 18446744073709551615, 0, 20, 2), - (13, 766, 1019, 1017, 18446744073709551615, 0, 19, 2), - (13, 765, 1019, 1017, 18446744073709551615, 0, 17, 2), - (13, 766, 247, 1018, 18446744073709551615, 0, 18, 2), - (13, 765, 247, 1018, 18446744073709551615, 0, 16, 2), - (13, 766, 1056, 251, 18446744073709551615, 0, 17, 2), - (13, 766, 1022, 1020, 18446744073709551615, 0, 16, 2), - (13, 766, 250, 1021, 18446744073709551615, 0, 15, 2), - (13, 766, 1054, 254, 18446744073709551615, 0, 14, 2), - (13, 766, 1055, 1023, 18446744073709551615, 0, 13, 2), - (13, 766, 253, 1049, 18446744073709551615, 0, 12, 2), - (13, 21, 1086, 1042, 18446744073709551615, 0, 2, 2), - (13, 26, 925, 1052, 18446744073709551615, 0, 2, 2), - (13, 25, 924, 1051, 18446744073709551615, 0, 2, 1), - (13, 24, 923, 1053, 18446744073709551615, 0, 2, 1), - (13, 1131, 928, 255, 18446744073709551615, 0, 2, 1), - (13, 792, 927, 1047, 18446744073709551615, 0, 2, 1), - (13, 30, 926, 252, 18446744073709551615, 0, 2, 2), - (13, 1130, 1085, 172, 18446744073709551615, 0, 2, 1), - (13, 29, 934, 249, 18446744073709551615, 0, 2, 1), - (13, 33, 931, 246, 18446744073709551615, 0, 2, 1), - (13, 1129, 930, 243, 18446744073709551615, 0, 2, 1), - (13, 32, 163, 240, 18446744073709551615, 0, 2, 1), - (13, 36, 932, 237, 18446744073709551615, 0, 2, 1), - (13, 1128, 940, 234, 18446744073709551615, 0, 2, 1), - (13, 35, 171, 231, 18446744073709551615, 0, 2, 1), - (13, 39, 166, 228, 18446744073709551615, 0, 2, 1), - (13, 1127, 1084, 225, 18446744073709551615, 0, 2, 1), - (13, 38, 939, 222, 18446744073709551615, 0, 2, 1), - (13, 42, 938, 219, 18446744073709551615, 0, 2, 1), - (13, 1126, 169, 216, 18446744073709551615, 0, 2, 1), - (13, 41, 944, 213, 18446744073709551615, 0, 2, 1), - (13, 45, 941, 210, 18446744073709551615, 0, 2, 1), - (13, 1125, 1081, 207, 18446744073709551615, 0, 2, 1), - (13, 44, 947, 204, 18446744073709551615, 0, 2, 1), - (13, 48, 175, 201, 18446744073709551615, 0, 2, 1), - (13, 1124, 1080, 198, 18446744073709551615, 0, 2, 1), - (13, 47, 950, 195, 18446744073709551615, 0, 2, 1), - (13, 51, 178, 192, 18446744073709551615, 0, 2, 1), - (13, 1123, 1079, 189, 18446744073709551615, 0, 2, 1), - (13, 50, 953, 186, 18446744073709551615, 0, 2, 1), - (13, 54, 181, 183, 18446744073709551615, 0, 2, 1), - (13, 1122, 1078, 180, 18446744073709551615, 0, 2, 1), - (13, 53, 956, 177, 18446744073709551615, 0, 2, 1), - (13, 57, 184, 174, 18446744073709551615, 0, 2, 1), - (13, 1121, 1077, 1083, 18446744073709551615, 0, 2, 1), - (13, 56, 959, 173, 18446744073709551615, 0, 2, 1), - (13, 60, 187, 159, 18446744073709551615, 0, 2, 1), - (13, 1120, 1076, 912, 18446744073709551615, 0, 2, 1), - (13, 59, 962, 152, 18446744073709551615, 0, 2, 1), - (13, 63, 190, 149, 18446744073709551615, 0, 2, 1), - (13, 1117, 1075, 141, 18446744073709551615, 0, 2, 1), - (13, 62, 965, 1091, 18446744073709551615, 0, 2, 1), - (13, 66, 193, 1096, 18446744073709551615, 0, 2, 1), - (13, 1119, 1074, 137, 18446744073709551615, 0, 2, 1), - (13, 65, 968, 134, 18446744073709551615, 0, 2, 1), - (13, 1112, 196, 131, 18446744073709551615, 0, 2, 1), - (13, 838, 1073, 124, 18446744073709551615, 0, 2, 1), - (13, 68, 971, 122, 18446744073709551615, 0, 2, 1), - (13, 1111, 199, 112, 18446744073709551615, 0, 2, 1), - (13, 843, 1072, 120, 18446744073709551615, 0, 2, 1), - (13, 71, 974, 109, 18446744073709551615, 0, 2, 1), - (13, 1110, 202, 106, 18446744073709551615, 0, 2, 1), - (13, 846, 1071, 103, 18446744073709551615, 0, 2, 1), - (13, 74, 977, 100, 18446744073709551615, 0, 2, 1), - (13, 1109, 205, 97, 18446744073709551615, 0, 2, 1), - (13, 849, 1070, 94, 18446744073709551615, 0, 2, 1), - (13, 77, 980, 91, 18446744073709551615, 0, 2, 1), - (13, 1108, 208, 88, 18446744073709551615, 0, 2, 1), - (13, 852, 1069, 85, 18446744073709551615, 0, 2, 1), - (13, 80, 983, 82, 18446744073709551615, 0, 2, 1), - (13, 1107, 211, 79, 18446744073709551615, 0, 2, 1), - (13, 855, 1068, 76, 18446744073709551615, 0, 2, 1), - (13, 83, 986, 73, 18446744073709551615, 0, 2, 1), - (13, 1106, 214, 70, 18446744073709551615, 0, 2, 1), - (13, 858, 1067, 67, 18446744073709551615, 0, 2, 1), - (13, 86, 989, 64, 18446744073709551615, 0, 2, 1), - (13, 1105, 217, 61, 18446744073709551615, 0, 2, 1), - (13, 861, 1066, 58, 18446744073709551615, 0, 2, 1), - (13, 89, 992, 55, 18446744073709551615, 0, 2, 1), - (13, 1104, 220, 52, 18446744073709551615, 0, 2, 1), - (13, 864, 1065, 49, 18446744073709551615, 0, 2, 1), - (13, 92, 995, 46, 18446744073709551615, 0, 2, 1), - (13, 1103, 223, 43, 18446744073709551615, 0, 2, 1), - (13, 867, 1064, 40, 18446744073709551615, 0, 2, 1), - (13, 95, 998, 37, 18446744073709551615, 0, 2, 1), - (13, 1102, 226, 34, 18446744073709551615, 0, 2, 1), - (13, 870, 1063, 31, 18446744073709551615, 0, 2, 1), - (13, 98, 1001, 28, 18446744073709551615, 0, 2, 1), - (13, 1101, 229, 19, 18446744073709551615, 0, 2, 1), - (13, 873, 1062, 1133, 18446744073709551615, 0, 2, 1), - (13, 101, 1004, 784, 18446744073709551615, 0, 2, 1), - (13, 1100, 232, 782, 18446744073709551615, 0, 2, 1), - (13, 876, 1061, 1138, 18446744073709551615, 0, 2, 1), - (13, 104, 1007, 1114, 18446744073709551615, 0, 2, 1), - (13, 1099, 235, 1135, 18446744073709551615, 0, 2, 1), - (13, 879, 1060, 783, 18446744073709551615, 0, 2, 1), - (13, 107, 1010, 1136, 18446744073709551615, 0, 2, 1), - (13, 1098, 238, 836, 18446744073709551615, 0, 2, 1), - (13, 882, 1059, 15, 18446744073709551615, 0, 2, 1), - (13, 110, 1013, 1146, 18446744073709551615, 0, 2, 1), - (13, 894, 241, 746, 18446744073709551615, 0, 2, 1), - (13, 885, 1058, 1152, 18446744073709551615, 0, 2, 1), - (13, 113, 1016, 781, 18446744073709551615, 0, 2, 1), - (13, 887, 244, 1143, 18446744073709551615, 0, 2, 1), - (13, 1097, 1057, 1144, 18446744073709551615, 0, 2, 1), - (13, 116, 1019, 745, 18446744073709551615, 0, 2, 1), - (13, 886, 247, 744, 18446744073709551615, 0, 2, 1), - (13, 889, 1056, 743, 18446744073709551615, 0, 2, 1), - (13, 888, 1022, 742, 18446744073709551615, 0, 2, 1), - (13, 121, 250, 741, 18446744073709551615, 0, 2, 1), - (13, 901, 1054, 740, 18446744073709551615, 0, 2, 1), - (13, 123, 1055, 739, 18446744073709551615, 0, 2, 1), - (13, 899, 253, 738, 18446744073709551615, 0, 2, 1), - (13, 130, 766, 737, 18446744073709551615, 0, 2, 1), - (13, 125, 764, 736, 18446744073709551615, 0, 2, 1), - (13, 1094, 763, 735, 18446744073709551615, 0, 2, 1), - (13, 898, 767, 734, 18446744073709551615, 0, 2, 1), - (13, 625, 1048, 626, 18446744073709551615, 0, 1, 1), - (13, 629, 1053, 630, 18446744073709551615, 0, 1, 1), - (13, 920, 627, 628, 18446744073709551615, 0, 2, 2), - (13, 920, 627, 628, 18446744073709551615, 1, 2, 2), - (13, 818, 558, 557, 18446744073709551615, 0, 5, 1), - (13, 815, 559, 558, 18446744073709551615, 0, 5, 1), - (13, 816, 558, 557, 18446744073709551615, 1, 10, 1), - (13, 157, 711, 710, 18446744073709551615, 0, 2, 2), - (13, 935, 706, 705, 18446744073709551615, 0, 2, 2), - (13, 929, 705, 704, 18446744073709551615, 0, 2, 2), - (13, 929, 705, 704, 18446744073709551615, 1, 2, 2), - (13, 935, 706, 705, 18446744073709551615, 1, 2, 2), - (13, 157, 711, 710, 18446744073709551615, 1, 2, 2), - (13, 818, 562, 561, 18446744073709551615, 0, 3, 1), - (13, 815, 563, 562, 18446744073709551615, 0, 3, 1), - (13, 816, 562, 561, 18446744073709551615, 1, 6, 1), - (13, 153, 630, 631, 18446744073709551615, 0, 2, 2), - (13, 929, 634, 635, 18446744073709551615, 0, 2, 2), - (13, 929, 634, 635, 18446744073709551615, 1, 2, 2), - (13, 153, 630, 631, 18446744073709551615, 1, 2, 2), - (13, 818, 564, 563, 18446744073709551615, 0, 3, 1), - (13, 815, 565, 564, 18446744073709551615, 0, 3, 1), - (13, 816, 564, 563, 18446744073709551615, 1, 6, 1), - (13, 161, 706, 705, 18446744073709551615, 0, 2, 2), - (13, 161, 706, 705, 18446744073709551615, 1, 2, 2), - (13, 818, 568, 567, 18446744073709551615, 0, 3, 1), - (13, 815, 569, 568, 18446744073709551615, 0, 3, 1), - (13, 816, 568, 567, 18446744073709551615, 1, 6, 1), - (13, 185, 636, 12, 18446744073709551615, 0, 1, 2), - (13, 954, 637, 1141, 18446744073709551615, 0, 1, 2), - (13, 957, 640, 9, 18446744073709551615, 0, 1, 2), - (13, 818, 590, 589, 18446744073709551615, 0, 3, 1), - (13, 815, 591, 590, 18446744073709551615, 0, 3, 1), - (13, 816, 590, 589, 18446744073709551615, 1, 6, 1), - (13, 687, 1048, 686, 18446744073709551615, 0, 1, 1), - (13, 683, 1053, 682, 18446744073709551615, 0, 1, 1), - (13, 21, 1086, 1042, 18446744073709551615, 1, 2, 2), - (13, 26, 925, 1052, 18446744073709551615, 1, 2, 2), - (13, 25, 924, 1051, 18446744073709551615, 1, 2, 1), - (13, 24, 923, 1053, 18446744073709551615, 1, 2, 1), - (13, 1131, 928, 255, 18446744073709551615, 1, 2, 1), - (13, 792, 927, 1047, 18446744073709551615, 1, 2, 1), - (13, 30, 926, 252, 18446744073709551615, 1, 2, 2), - (13, 1130, 1085, 172, 18446744073709551615, 1, 2, 1), - (13, 29, 934, 249, 18446744073709551615, 1, 2, 1), - (13, 33, 931, 246, 18446744073709551615, 1, 2, 1), - (13, 1129, 930, 243, 18446744073709551615, 1, 2, 1), - (13, 32, 163, 240, 18446744073709551615, 1, 2, 1), - (13, 36, 932, 237, 18446744073709551615, 1, 2, 1), - (13, 1128, 940, 234, 18446744073709551615, 1, 2, 1), - (13, 35, 171, 231, 18446744073709551615, 1, 2, 1), - (13, 39, 166, 228, 18446744073709551615, 1, 2, 1), - (13, 1127, 1084, 225, 18446744073709551615, 1, 2, 1), - (13, 38, 939, 222, 18446744073709551615, 1, 2, 1), - (13, 42, 938, 219, 18446744073709551615, 1, 2, 1), - (13, 1126, 169, 216, 18446744073709551615, 1, 2, 1), - (13, 41, 944, 213, 18446744073709551615, 1, 2, 1), - (13, 45, 941, 210, 18446744073709551615, 1, 2, 1), - (13, 1125, 1081, 207, 18446744073709551615, 1, 2, 1), - (13, 44, 947, 204, 18446744073709551615, 1, 2, 1), - (13, 48, 175, 201, 18446744073709551615, 1, 2, 1), - (13, 1124, 1080, 198, 18446744073709551615, 1, 2, 1), - (13, 47, 950, 195, 18446744073709551615, 1, 2, 1), - (13, 51, 178, 192, 18446744073709551615, 1, 2, 1), - (13, 1123, 1079, 189, 18446744073709551615, 1, 2, 1), - (13, 50, 953, 186, 18446744073709551615, 1, 2, 1), - (13, 54, 181, 183, 18446744073709551615, 1, 2, 1), - (13, 1122, 1078, 180, 18446744073709551615, 1, 2, 1), - (13, 53, 956, 177, 18446744073709551615, 1, 2, 1), - (13, 57, 184, 174, 18446744073709551615, 1, 2, 1), - (13, 1121, 1077, 1083, 18446744073709551615, 1, 2, 1), - (13, 56, 959, 173, 18446744073709551615, 1, 2, 1), - (13, 60, 187, 159, 18446744073709551615, 1, 2, 1), - (13, 1120, 1076, 912, 18446744073709551615, 1, 2, 1), - (13, 59, 962, 152, 18446744073709551615, 1, 2, 1), - (13, 63, 190, 149, 18446744073709551615, 1, 2, 1), - (13, 1117, 1075, 141, 18446744073709551615, 1, 2, 1), - (13, 62, 965, 1091, 18446744073709551615, 1, 2, 1), - (13, 66, 193, 1096, 18446744073709551615, 1, 2, 1), - (13, 1119, 1074, 137, 18446744073709551615, 1, 2, 1), - (13, 65, 968, 134, 18446744073709551615, 1, 2, 1), - (13, 1112, 196, 131, 18446744073709551615, 1, 2, 1), - (13, 838, 1073, 124, 18446744073709551615, 1, 2, 1), - (13, 68, 971, 122, 18446744073709551615, 1, 2, 1), - (13, 1111, 199, 112, 18446744073709551615, 1, 2, 1), - (13, 843, 1072, 120, 18446744073709551615, 1, 2, 1), - (13, 71, 974, 109, 18446744073709551615, 1, 2, 1), - (13, 1110, 202, 106, 18446744073709551615, 1, 2, 1), - (13, 846, 1071, 103, 18446744073709551615, 1, 2, 1), - (13, 74, 977, 100, 18446744073709551615, 1, 2, 1), - (13, 1109, 205, 97, 18446744073709551615, 1, 2, 1), - (13, 849, 1070, 94, 18446744073709551615, 1, 2, 1), - (13, 77, 980, 91, 18446744073709551615, 1, 2, 1), - (13, 1108, 208, 88, 18446744073709551615, 1, 2, 1), - (13, 852, 1069, 85, 18446744073709551615, 1, 2, 1), - (13, 80, 983, 82, 18446744073709551615, 1, 2, 1), - (13, 1107, 211, 79, 18446744073709551615, 1, 2, 1), - (13, 855, 1068, 76, 18446744073709551615, 1, 2, 1), - (13, 83, 986, 73, 18446744073709551615, 1, 2, 1), - (13, 1106, 214, 70, 18446744073709551615, 1, 2, 1), - (13, 858, 1067, 67, 18446744073709551615, 1, 2, 1), - (13, 86, 989, 64, 18446744073709551615, 1, 2, 1), - (13, 1105, 217, 61, 18446744073709551615, 1, 2, 1), - (13, 861, 1066, 58, 18446744073709551615, 1, 2, 1), - (13, 89, 992, 55, 18446744073709551615, 1, 2, 1), - (13, 1104, 220, 52, 18446744073709551615, 1, 2, 1), - (13, 864, 1065, 49, 18446744073709551615, 1, 2, 1), - (13, 92, 995, 46, 18446744073709551615, 1, 2, 1), - (13, 1103, 223, 43, 18446744073709551615, 1, 2, 1), - (13, 867, 1064, 40, 18446744073709551615, 1, 2, 1), - (13, 95, 998, 37, 18446744073709551615, 1, 2, 1), - (13, 1102, 226, 34, 18446744073709551615, 1, 2, 1), - (13, 870, 1063, 31, 18446744073709551615, 1, 2, 1), - (13, 98, 1001, 28, 18446744073709551615, 1, 2, 1), - (13, 1101, 229, 19, 18446744073709551615, 1, 2, 1), - (13, 873, 1062, 1133, 18446744073709551615, 1, 2, 1), - (13, 101, 1004, 784, 18446744073709551615, 1, 2, 1), - (13, 1100, 232, 782, 18446744073709551615, 1, 2, 1), - (13, 876, 1061, 1138, 18446744073709551615, 1, 2, 1), - (13, 104, 1007, 1114, 18446744073709551615, 1, 2, 1), - (13, 1099, 235, 1135, 18446744073709551615, 1, 2, 1), - (13, 879, 1060, 783, 18446744073709551615, 1, 2, 1), - (13, 107, 1010, 1136, 18446744073709551615, 1, 2, 1), - (13, 1098, 238, 836, 18446744073709551615, 1, 2, 1), - (13, 882, 1059, 15, 18446744073709551615, 1, 2, 1), - (13, 110, 1013, 1146, 18446744073709551615, 1, 2, 1), - (13, 894, 241, 746, 18446744073709551615, 1, 2, 1), - (13, 885, 1058, 1152, 18446744073709551615, 1, 2, 1), - (13, 113, 1016, 781, 18446744073709551615, 1, 2, 1), - (13, 887, 244, 1143, 18446744073709551615, 1, 2, 1), - (13, 1097, 1057, 1144, 18446744073709551615, 1, 2, 1), - (13, 116, 1019, 745, 18446744073709551615, 1, 2, 1), - (13, 886, 247, 744, 18446744073709551615, 1, 2, 1), - (13, 889, 1056, 743, 18446744073709551615, 1, 2, 1), - (13, 888, 1022, 742, 18446744073709551615, 1, 2, 1), - (13, 121, 250, 741, 18446744073709551615, 1, 2, 1), - (13, 901, 1054, 740, 18446744073709551615, 1, 2, 1), - (13, 123, 1055, 739, 18446744073709551615, 1, 2, 1), - (13, 899, 253, 738, 18446744073709551615, 1, 2, 1), - (13, 130, 766, 737, 18446744073709551615, 1, 2, 1), - (13, 125, 764, 736, 18446744073709551615, 1, 2, 1), - (13, 1094, 763, 735, 18446744073709551615, 1, 2, 1), - (13, 898, 767, 734, 18446744073709551615, 1, 2, 1), - (13, 276, 783, 1010, 18446744073709551615, 0, 2, 2), - (13, 277, 1135, 1060, 18446744073709551615, 0, 2, 2), - (13, 278, 1114, 235, 18446744073709551615, 0, 2, 1), - (13, 279, 1138, 1007, 18446744073709551615, 0, 2, 2), - (13, 280, 782, 1061, 18446744073709551615, 0, 2, 2), - (13, 281, 784, 232, 18446744073709551615, 0, 2, 2), - (13, 282, 1133, 1004, 18446744073709551615, 0, 2, 1), - (13, 283, 19, 1062, 18446744073709551615, 0, 2, 1), - (13, 284, 28, 229, 18446744073709551615, 0, 2, 1), - (13, 285, 31, 1001, 18446744073709551615, 0, 2, 1), - (13, 286, 34, 1063, 18446744073709551615, 0, 2, 1), - (13, 287, 37, 226, 18446744073709551615, 0, 2, 1), - (13, 288, 40, 998, 18446744073709551615, 0, 2, 1), - (13, 289, 43, 1064, 18446744073709551615, 0, 2, 1), - (13, 290, 46, 223, 18446744073709551615, 0, 2, 1), - (13, 291, 49, 995, 18446744073709551615, 0, 2, 1), - (13, 292, 52, 1065, 18446744073709551615, 0, 2, 1), - (13, 293, 55, 220, 18446744073709551615, 0, 2, 1), - (13, 294, 58, 992, 18446744073709551615, 0, 2, 1), - (13, 295, 61, 1066, 18446744073709551615, 0, 2, 1), - (13, 296, 64, 217, 18446744073709551615, 0, 2, 1), - (13, 297, 67, 989, 18446744073709551615, 0, 2, 1), - (13, 298, 70, 1067, 18446744073709551615, 0, 2, 1), - (13, 299, 73, 214, 18446744073709551615, 0, 2, 1), - (13, 300, 76, 986, 18446744073709551615, 0, 2, 1), - (13, 301, 79, 1068, 18446744073709551615, 0, 2, 1), - (13, 302, 82, 211, 18446744073709551615, 0, 2, 1), - (13, 303, 85, 983, 18446744073709551615, 0, 2, 1), - (13, 304, 88, 1069, 18446744073709551615, 0, 2, 1), - (13, 305, 91, 208, 18446744073709551615, 0, 2, 1), - (13, 306, 94, 980, 18446744073709551615, 0, 2, 1), - (13, 307, 97, 1070, 18446744073709551615, 0, 2, 1), - (13, 308, 100, 205, 18446744073709551615, 0, 2, 1), - (13, 309, 103, 977, 18446744073709551615, 0, 2, 1), - (13, 310, 106, 1071, 18446744073709551615, 0, 2, 1), - (13, 311, 109, 202, 18446744073709551615, 0, 2, 1), - (13, 312, 120, 974, 18446744073709551615, 0, 2, 1), - (13, 313, 112, 1072, 18446744073709551615, 0, 2, 1), - (13, 314, 122, 199, 18446744073709551615, 0, 2, 1), - (13, 315, 124, 971, 18446744073709551615, 0, 2, 1), - (13, 316, 131, 1073, 18446744073709551615, 0, 2, 1), - (13, 317, 134, 196, 18446744073709551615, 0, 2, 1), - (13, 318, 137, 968, 18446744073709551615, 0, 2, 1), - (13, 319, 1096, 1074, 18446744073709551615, 0, 2, 1), - (13, 320, 1091, 193, 18446744073709551615, 0, 2, 1), - (13, 321, 141, 965, 18446744073709551615, 0, 2, 1), - (13, 322, 149, 1075, 18446744073709551615, 0, 2, 1), - (13, 323, 152, 190, 18446744073709551615, 0, 2, 1), - (13, 324, 912, 962, 18446744073709551615, 0, 2, 1), - (13, 325, 159, 1076, 18446744073709551615, 0, 2, 1), - (13, 326, 173, 187, 18446744073709551615, 0, 2, 1), - (13, 327, 1083, 959, 18446744073709551615, 0, 2, 1), - (13, 328, 174, 1077, 18446744073709551615, 0, 2, 1), - (13, 329, 177, 184, 18446744073709551615, 0, 2, 1), - (13, 330, 180, 956, 18446744073709551615, 0, 2, 1), - (13, 331, 183, 1078, 18446744073709551615, 0, 2, 1), - (13, 332, 186, 181, 18446744073709551615, 0, 2, 1), - (13, 333, 189, 953, 18446744073709551615, 0, 2, 1), - (13, 334, 192, 1079, 18446744073709551615, 0, 2, 1), - (13, 335, 195, 178, 18446744073709551615, 0, 2, 1), - (13, 336, 198, 950, 18446744073709551615, 0, 2, 1), - (13, 337, 201, 1080, 18446744073709551615, 0, 2, 1), - (13, 338, 204, 175, 18446744073709551615, 0, 2, 1), - (13, 339, 207, 947, 18446744073709551615, 0, 2, 1), - (13, 340, 210, 1081, 18446744073709551615, 0, 2, 1), - (13, 341, 213, 941, 18446744073709551615, 0, 2, 1), - (13, 342, 216, 944, 18446744073709551615, 0, 2, 1), - (13, 343, 219, 169, 18446744073709551615, 0, 2, 1), - (13, 344, 222, 938, 18446744073709551615, 0, 2, 1), - (13, 345, 225, 939, 18446744073709551615, 0, 2, 1), - (13, 346, 228, 1084, 18446744073709551615, 0, 2, 1), - (13, 347, 231, 166, 18446744073709551615, 0, 2, 1), - (13, 348, 234, 171, 18446744073709551615, 0, 2, 1), - (13, 349, 237, 940, 18446744073709551615, 0, 2, 1), - (13, 350, 240, 932, 18446744073709551615, 0, 2, 1), - (13, 351, 243, 163, 18446744073709551615, 0, 2, 1), - (13, 352, 246, 930, 18446744073709551615, 0, 2, 1), - (13, 353, 249, 931, 18446744073709551615, 0, 2, 1), - (13, 354, 172, 934, 18446744073709551615, 0, 2, 1), - (13, 355, 252, 1085, 18446744073709551615, 0, 2, 1), - (13, 356, 1047, 926, 18446744073709551615, 0, 2, 1), - (13, 357, 255, 927, 18446744073709551615, 0, 2, 1), - (13, 358, 1053, 928, 18446744073709551615, 0, 2, 1), - (13, 359, 1051, 923, 18446744073709551615, 0, 2, 1), - (13, 360, 1052, 924, 18446744073709551615, 0, 2, 1), - (13, 361, 1042, 925, 18446744073709551615, 0, 2, 1), - (13, 362, 1048, 1086, 18446744073709551615, 0, 2, 1), - (13, 363, 1040, 150, 18446744073709551615, 0, 2, 1), - (13, 364, 1050, 922, 18446744073709551615, 0, 2, 1), - (13, 365, 1046, 1087, 18446744073709551615, 0, 2, 1), - (13, 366, 1044, 146, 18446744073709551615, 0, 2, 1), - (13, 367, 1045, 915, 18446744073709551615, 0, 2, 1), - (13, 368, 1035, 916, 18446744073709551615, 0, 2, 1), - (13, 369, 1041, 1088, 18446744073709551615, 0, 2, 1), - (13, 370, 1033, 143, 18446744073709551615, 0, 2, 1), - (13, 371, 1043, 148, 18446744073709551615, 0, 2, 1), - (13, 372, 1039, 917, 18446744073709551615, 0, 2, 1), - (13, 373, 1037, 1090, 18446744073709551615, 0, 2, 1), - (13, 374, 1038, 1089, 18446744073709551615, 0, 2, 1), - (13, 375, 1030, 907, 18446744073709551615, 0, 2, 1), - (13, 376, 1034, 138, 18446744073709551615, 0, 2, 1), - (13, 377, 1036, 908, 18446744073709551615, 0, 2, 1), - (13, 378, 1027, 135, 18446744073709551615, 0, 2, 1), - (13, 379, 1031, 909, 18446744073709551615, 0, 2, 1), - (13, 380, 765, 1092, 18446744073709551615, 0, 2, 1), - (13, 381, 1032, 132, 18446744073709551615, 0, 2, 1), - (13, 382, 1029, 904, 18446744073709551615, 0, 2, 1), - (13, 719, 1010, 718, 18446744073709551615, 0, 1, 1), - (13, 718, 1060, 717, 18446744073709551615, 0, 1, 1), - (13, 715, 1061, 714, 18446744073709551615, 0, 1, 1), - (13, 714, 232, 713, 18446744073709551615, 0, 1, 1), - (13, 713, 1004, 712, 18446744073709551615, 0, 1, 1), - (13, 711, 229, 710, 18446744073709551615, 0, 1, 1), - (13, 799, 678, 677, 18446744073709551615, 0, 1, 2), - (13, 799, 576, 575, 18446744073709551615, 1, 5, 2), - (13, 918, 718, 717, 18446744073709551615, 0, 2, 2), - (13, 154, 714, 713, 18446744073709551615, 0, 2, 2), - (13, 157, 713, 712, 18446744073709551615, 0, 2, 2), - (13, 157, 713, 712, 18446744073709551615, 1, 2, 2), - (13, 154, 714, 713, 18446744073709551615, 1, 2, 2), - (13, 918, 718, 717, 18446744073709551615, 1, 2, 2), - (13, 818, 558, 557, 18446744073709551615, 2, 5, 1), - (13, 815, 559, 558, 18446744073709551615, 2, 5, 1), - (13, 816, 558, 557, 18446744073709551615, 5, 10, 1), - (13, 921, 689, 688, 18446744073709551615, 0, 2, 2), - (13, 157, 687, 686, 18446744073709551615, 0, 2, 2), - (13, 155, 686, 685, 18446744073709551615, 0, 2, 2), - (13, 158, 683, 682, 18446744073709551615, 0, 2, 2), - (13, 158, 683, 682, 18446744073709551615, 1, 2, 2), - (13, 155, 686, 685, 18446744073709551615, 1, 2, 2), - (13, 157, 687, 686, 18446744073709551615, 1, 2, 2), - (13, 921, 689, 688, 18446744073709551615, 1, 2, 2), - (13, 818, 562, 561, 18446744073709551615, 1, 3, 1), - (13, 815, 563, 562, 18446744073709551615, 1, 3, 1), - (13, 816, 562, 561, 18446744073709551615, 3, 6, 1), - (13, 157, 715, 714, 18446744073709551615, 2, 4, 2), - (13, 155, 714, 713, 18446744073709551615, 2, 4, 2), - (13, 158, 711, 710, 18446744073709551615, 2, 4, 2), - (13, 929, 709, 708, 18446744073709551615, 2, 4, 2), - (13, 929, 709, 708, 18446744073709551615, 3, 4, 2), - (13, 158, 711, 710, 18446744073709551615, 3, 4, 2), - (13, 155, 714, 713, 18446744073709551615, 3, 4, 2), - (13, 157, 715, 714, 18446744073709551615, 3, 4, 2), - (13, 818, 564, 563, 18446744073709551615, 1, 3, 1), - (13, 815, 565, 564, 18446744073709551615, 1, 3, 1), - (13, 816, 564, 563, 18446744073709551615, 3, 6, 1), - (13, 935, 686, 685, 18446744073709551615, 0, 2, 2), - (13, 933, 684, 683, 18446744073709551615, 0, 2, 2), - (13, 165, 683, 682, 18446744073709551615, 0, 2, 2), - (13, 161, 682, 681, 18446744073709551615, 0, 2, 2), - (13, 161, 682, 681, 18446744073709551615, 1, 2, 2), - (13, 165, 683, 682, 18446744073709551615, 1, 2, 2), - (13, 933, 684, 683, 18446744073709551615, 1, 2, 2), - (13, 935, 686, 685, 18446744073709551615, 1, 2, 2), - (13, 818, 568, 567, 18446744073709551615, 1, 3, 1), - (13, 815, 569, 568, 18446744073709551615, 1, 3, 1), - (13, 816, 568, 567, 18446744073709551615, 3, 6, 1), - (13, 182, 710, 1150, 18446744073709551615, 0, 1, 2), - (13, 951, 709, 1151, 18446744073709551615, 0, 1, 2), - (13, 185, 614, 12, 18446744073709551615, 0, 1, 2), - (13, 818, 590, 589, 18446744073709551615, 1, 3, 1), - (13, 815, 591, 590, 18446744073709551615, 1, 3, 1), - (13, 816, 590, 589, 18446744073709551615, 3, 6, 1), - (13, 665, 1010, 664, 18446744073709551615, 0, 1, 1), - (13, 664, 1060, 663, 18446744073709551615, 0, 1, 1), - (13, 661, 1061, 660, 18446744073709551615, 0, 1, 1), - (13, 660, 232, 659, 18446744073709551615, 0, 1, 1), - (13, 659, 1004, 658, 18446744073709551615, 0, 1, 1), - (13, 657, 229, 656, 18446744073709551615, 0, 1, 1), - (13, 276, 783, 1010, 18446744073709551615, 1, 2, 2), - (13, 277, 1135, 1060, 18446744073709551615, 1, 2, 2), - (13, 278, 1114, 235, 18446744073709551615, 1, 2, 1), - (13, 279, 1138, 1007, 18446744073709551615, 1, 2, 2), - (13, 280, 782, 1061, 18446744073709551615, 1, 2, 2), - (13, 281, 784, 232, 18446744073709551615, 1, 2, 2), - (13, 282, 1133, 1004, 18446744073709551615, 1, 2, 1), - (13, 283, 19, 1062, 18446744073709551615, 1, 2, 1), - (13, 284, 28, 229, 18446744073709551615, 1, 2, 1), - (13, 285, 31, 1001, 18446744073709551615, 1, 2, 1), - (13, 286, 34, 1063, 18446744073709551615, 1, 2, 1), - (13, 287, 37, 226, 18446744073709551615, 1, 2, 1), - (13, 288, 40, 998, 18446744073709551615, 1, 2, 1), - (13, 289, 43, 1064, 18446744073709551615, 1, 2, 1), - (13, 290, 46, 223, 18446744073709551615, 1, 2, 1), - (13, 291, 49, 995, 18446744073709551615, 1, 2, 1), - (13, 292, 52, 1065, 18446744073709551615, 1, 2, 1), - (13, 293, 55, 220, 18446744073709551615, 1, 2, 1), - (13, 294, 58, 992, 18446744073709551615, 1, 2, 1), - (13, 295, 61, 1066, 18446744073709551615, 1, 2, 1), - (13, 296, 64, 217, 18446744073709551615, 1, 2, 1), - (13, 297, 67, 989, 18446744073709551615, 1, 2, 1), - (13, 298, 70, 1067, 18446744073709551615, 1, 2, 1), - (13, 299, 73, 214, 18446744073709551615, 1, 2, 1), - (13, 300, 76, 986, 18446744073709551615, 1, 2, 1), - (13, 301, 79, 1068, 18446744073709551615, 1, 2, 1), - (13, 302, 82, 211, 18446744073709551615, 1, 2, 1), - (13, 303, 85, 983, 18446744073709551615, 1, 2, 1), - (13, 304, 88, 1069, 18446744073709551615, 1, 2, 1), - (13, 305, 91, 208, 18446744073709551615, 1, 2, 1), - (13, 306, 94, 980, 18446744073709551615, 1, 2, 1), - (13, 307, 97, 1070, 18446744073709551615, 1, 2, 1), - (13, 308, 100, 205, 18446744073709551615, 1, 2, 1), - (13, 309, 103, 977, 18446744073709551615, 1, 2, 1), - (13, 310, 106, 1071, 18446744073709551615, 1, 2, 1), - (13, 311, 109, 202, 18446744073709551615, 1, 2, 1), - (13, 312, 120, 974, 18446744073709551615, 1, 2, 1), - (13, 313, 112, 1072, 18446744073709551615, 1, 2, 1), - (13, 314, 122, 199, 18446744073709551615, 1, 2, 1), - (13, 315, 124, 971, 18446744073709551615, 1, 2, 1), - (13, 316, 131, 1073, 18446744073709551615, 1, 2, 1), - (13, 317, 134, 196, 18446744073709551615, 1, 2, 1), - (13, 318, 137, 968, 18446744073709551615, 1, 2, 1), - (13, 319, 1096, 1074, 18446744073709551615, 1, 2, 1), - (13, 320, 1091, 193, 18446744073709551615, 1, 2, 1), - (13, 321, 141, 965, 18446744073709551615, 1, 2, 1), - (13, 322, 149, 1075, 18446744073709551615, 1, 2, 1), - (13, 323, 152, 190, 18446744073709551615, 1, 2, 1), - (13, 324, 912, 962, 18446744073709551615, 1, 2, 1), - (13, 325, 159, 1076, 18446744073709551615, 1, 2, 1), - (13, 326, 173, 187, 18446744073709551615, 1, 2, 1), - (13, 327, 1083, 959, 18446744073709551615, 1, 2, 1), - (13, 328, 174, 1077, 18446744073709551615, 1, 2, 1), - (13, 329, 177, 184, 18446744073709551615, 1, 2, 1), - (13, 330, 180, 956, 18446744073709551615, 1, 2, 1), - (13, 331, 183, 1078, 18446744073709551615, 1, 2, 1), - (13, 332, 186, 181, 18446744073709551615, 1, 2, 1), - (13, 333, 189, 953, 18446744073709551615, 1, 2, 1), - (13, 334, 192, 1079, 18446744073709551615, 1, 2, 1), - (13, 335, 195, 178, 18446744073709551615, 1, 2, 1), - (13, 336, 198, 950, 18446744073709551615, 1, 2, 1), - (13, 337, 201, 1080, 18446744073709551615, 1, 2, 1), - (13, 338, 204, 175, 18446744073709551615, 1, 2, 1), - (13, 339, 207, 947, 18446744073709551615, 1, 2, 1), - (13, 340, 210, 1081, 18446744073709551615, 1, 2, 1), - (13, 341, 213, 941, 18446744073709551615, 1, 2, 1), - (13, 342, 216, 944, 18446744073709551615, 1, 2, 1), - (13, 343, 219, 169, 18446744073709551615, 1, 2, 1), - (13, 344, 222, 938, 18446744073709551615, 1, 2, 1), - (13, 345, 225, 939, 18446744073709551615, 1, 2, 1), - (13, 346, 228, 1084, 18446744073709551615, 1, 2, 1), - (13, 347, 231, 166, 18446744073709551615, 1, 2, 1), - (13, 348, 234, 171, 18446744073709551615, 1, 2, 1), - (13, 349, 237, 940, 18446744073709551615, 1, 2, 1), - (13, 350, 240, 932, 18446744073709551615, 1, 2, 1), - (13, 351, 243, 163, 18446744073709551615, 1, 2, 1), - (13, 352, 246, 930, 18446744073709551615, 1, 2, 1), - (13, 353, 249, 931, 18446744073709551615, 1, 2, 1), - (13, 354, 172, 934, 18446744073709551615, 1, 2, 1), - (13, 355, 252, 1085, 18446744073709551615, 1, 2, 1), - (13, 356, 1047, 926, 18446744073709551615, 1, 2, 1), - (13, 357, 255, 927, 18446744073709551615, 1, 2, 1), - (13, 358, 1053, 928, 18446744073709551615, 1, 2, 1), - (13, 359, 1051, 923, 18446744073709551615, 1, 2, 1), - (13, 360, 1052, 924, 18446744073709551615, 1, 2, 1), - (13, 361, 1042, 925, 18446744073709551615, 1, 2, 1), - (13, 362, 1048, 1086, 18446744073709551615, 1, 2, 1), - (13, 363, 1040, 150, 18446744073709551615, 1, 2, 1), - (13, 364, 1050, 922, 18446744073709551615, 1, 2, 1), - (13, 365, 1046, 1087, 18446744073709551615, 1, 2, 1), - (13, 366, 1044, 146, 18446744073709551615, 1, 2, 1), - (13, 367, 1045, 915, 18446744073709551615, 1, 2, 1), - (13, 368, 1035, 916, 18446744073709551615, 1, 2, 1), - (13, 369, 1041, 1088, 18446744073709551615, 1, 2, 1), - (13, 370, 1033, 143, 18446744073709551615, 1, 2, 1), - (13, 371, 1043, 148, 18446744073709551615, 1, 2, 1), - (13, 372, 1039, 917, 18446744073709551615, 1, 2, 1), - (13, 373, 1037, 1090, 18446744073709551615, 1, 2, 1), - (13, 374, 1038, 1089, 18446744073709551615, 1, 2, 1), - (13, 375, 1030, 907, 18446744073709551615, 1, 2, 1), - (13, 376, 1034, 138, 18446744073709551615, 1, 2, 1), - (13, 377, 1036, 908, 18446744073709551615, 1, 2, 1), - (13, 378, 1027, 135, 18446744073709551615, 1, 2, 1), - (13, 379, 1031, 909, 18446744073709551615, 1, 2, 1), - (13, 380, 765, 1092, 18446744073709551615, 1, 2, 1), - (13, 381, 1032, 132, 18446744073709551615, 1, 2, 1), - (13, 382, 1029, 904, 18446744073709551615, 1, 2, 1), - (13, 405, 924, 1052, 18446744073709551615, 0, 2, 2), - (13, 406, 923, 1051, 18446744073709551615, 0, 2, 1), - (13, 407, 928, 1053, 18446744073709551615, 0, 2, 1), - (13, 408, 927, 255, 18446744073709551615, 0, 2, 1), - (13, 409, 926, 1047, 18446744073709551615, 0, 2, 1), - (13, 410, 1085, 252, 18446744073709551615, 0, 2, 1), - (13, 411, 934, 172, 18446744073709551615, 0, 2, 1), - (13, 412, 931, 249, 18446744073709551615, 0, 2, 1), - (13, 413, 930, 246, 18446744073709551615, 0, 2, 1), - (13, 414, 163, 243, 18446744073709551615, 0, 2, 1), - (13, 415, 932, 240, 18446744073709551615, 0, 2, 1), - (13, 416, 940, 237, 18446744073709551615, 0, 2, 1), - (13, 417, 171, 234, 18446744073709551615, 0, 2, 1), - (13, 418, 166, 231, 18446744073709551615, 0, 2, 2), - (13, 419, 1084, 228, 18446744073709551615, 0, 2, 1), - (13, 420, 939, 225, 18446744073709551615, 0, 2, 1), - (13, 421, 938, 222, 18446744073709551615, 0, 2, 1), - (13, 422, 169, 219, 18446744073709551615, 0, 2, 1), - (13, 423, 944, 216, 18446744073709551615, 0, 2, 1), - (13, 424, 941, 213, 18446744073709551615, 0, 2, 1), - (13, 425, 1081, 210, 18446744073709551615, 0, 2, 1), - (13, 426, 947, 207, 18446744073709551615, 0, 2, 1), - (13, 427, 175, 204, 18446744073709551615, 0, 2, 1), - (13, 428, 1080, 201, 18446744073709551615, 0, 2, 1), - (13, 429, 950, 198, 18446744073709551615, 0, 2, 1), - (13, 430, 178, 195, 18446744073709551615, 0, 2, 1), - (13, 431, 1079, 192, 18446744073709551615, 0, 2, 1), - (13, 432, 953, 189, 18446744073709551615, 0, 2, 1), - (13, 433, 181, 186, 18446744073709551615, 0, 2, 1), - (13, 434, 1078, 183, 18446744073709551615, 0, 2, 1), - (13, 435, 956, 180, 18446744073709551615, 0, 2, 1), - (13, 436, 184, 177, 18446744073709551615, 0, 2, 1), - (13, 437, 1077, 174, 18446744073709551615, 0, 2, 1), - (13, 438, 959, 1083, 18446744073709551615, 0, 2, 1), - (13, 439, 187, 173, 18446744073709551615, 0, 2, 1), - (13, 440, 1076, 159, 18446744073709551615, 0, 2, 1), - (13, 441, 962, 912, 18446744073709551615, 0, 2, 1), - (13, 442, 190, 152, 18446744073709551615, 0, 2, 1), - (13, 443, 1075, 149, 18446744073709551615, 0, 2, 1), - (13, 444, 965, 141, 18446744073709551615, 0, 2, 1), - (13, 445, 193, 1091, 18446744073709551615, 0, 2, 1), - (13, 446, 1074, 1096, 18446744073709551615, 0, 2, 1), - (13, 447, 968, 137, 18446744073709551615, 0, 2, 1), - (13, 448, 196, 134, 18446744073709551615, 0, 2, 1), - (13, 449, 1073, 131, 18446744073709551615, 0, 2, 1), - (13, 450, 971, 124, 18446744073709551615, 0, 2, 1), - (13, 451, 199, 122, 18446744073709551615, 0, 2, 1), - (13, 452, 1072, 112, 18446744073709551615, 0, 2, 1), - (13, 453, 974, 120, 18446744073709551615, 0, 2, 1), - (13, 454, 202, 109, 18446744073709551615, 0, 2, 1), - (13, 455, 1071, 106, 18446744073709551615, 0, 2, 1), - (13, 456, 977, 103, 18446744073709551615, 0, 2, 1), - (13, 457, 205, 100, 18446744073709551615, 0, 2, 1), - (13, 458, 1070, 97, 18446744073709551615, 0, 2, 1), - (13, 459, 980, 94, 18446744073709551615, 0, 2, 1), - (13, 460, 208, 91, 18446744073709551615, 0, 2, 1), - (13, 461, 1069, 88, 18446744073709551615, 0, 2, 1), - (13, 462, 983, 85, 18446744073709551615, 0, 2, 1), - (13, 463, 211, 82, 18446744073709551615, 0, 2, 1), - (13, 464, 1068, 79, 18446744073709551615, 0, 2, 1), - (13, 465, 986, 76, 18446744073709551615, 0, 2, 1), - (13, 466, 214, 73, 18446744073709551615, 0, 2, 1), - (13, 467, 1067, 70, 18446744073709551615, 0, 2, 1), - (13, 468, 989, 67, 18446744073709551615, 0, 2, 1), - (13, 469, 217, 64, 18446744073709551615, 0, 2, 1), - (13, 470, 1066, 61, 18446744073709551615, 0, 2, 1), - (13, 471, 992, 58, 18446744073709551615, 0, 2, 1), - (13, 472, 220, 55, 18446744073709551615, 0, 2, 1), - (13, 473, 1065, 52, 18446744073709551615, 0, 2, 1), - (13, 474, 995, 49, 18446744073709551615, 0, 2, 1), - (13, 475, 223, 46, 18446744073709551615, 0, 2, 1), - (13, 476, 1064, 43, 18446744073709551615, 0, 2, 1), - (13, 477, 998, 40, 18446744073709551615, 0, 2, 1), - (13, 478, 226, 37, 18446744073709551615, 0, 2, 1), - (13, 479, 1063, 34, 18446744073709551615, 0, 2, 1), - (13, 480, 1001, 31, 18446744073709551615, 0, 2, 1), - (13, 481, 229, 28, 18446744073709551615, 0, 2, 1), - (13, 482, 1062, 19, 18446744073709551615, 0, 2, 1), - (13, 483, 1004, 1133, 18446744073709551615, 0, 2, 1), - (13, 484, 232, 784, 18446744073709551615, 0, 2, 1), - (13, 485, 1061, 782, 18446744073709551615, 0, 2, 1), - (13, 486, 1007, 1138, 18446744073709551615, 0, 2, 1), - (13, 487, 235, 1114, 18446744073709551615, 0, 2, 1), - (13, 488, 1060, 1135, 18446744073709551615, 0, 2, 1), - (13, 489, 1010, 783, 18446744073709551615, 0, 2, 1), - (13, 490, 238, 1136, 18446744073709551615, 0, 2, 1), - (13, 491, 1059, 836, 18446744073709551615, 0, 2, 1), - (13, 492, 1013, 15, 18446744073709551615, 0, 2, 1), - (13, 493, 241, 1146, 18446744073709551615, 0, 2, 1), - (13, 494, 1058, 746, 18446744073709551615, 0, 2, 1), - (13, 495, 1016, 1152, 18446744073709551615, 0, 2, 1), - (13, 496, 244, 781, 18446744073709551615, 0, 2, 1), - (13, 497, 1057, 1143, 18446744073709551615, 0, 2, 1), - (13, 498, 1019, 1144, 18446744073709551615, 0, 2, 1), - (13, 499, 247, 745, 18446744073709551615, 0, 2, 1), - (13, 500, 1056, 744, 18446744073709551615, 0, 2, 1), - (13, 501, 1022, 743, 18446744073709551615, 0, 2, 1), - (13, 502, 250, 742, 18446744073709551615, 0, 2, 1), - (13, 503, 1054, 741, 18446744073709551615, 0, 2, 1), - (13, 504, 1055, 740, 18446744073709551615, 0, 2, 1), - (13, 505, 253, 739, 18446744073709551615, 0, 2, 1), - (13, 506, 766, 738, 18446744073709551615, 0, 2, 1), - (13, 507, 764, 737, 18446744073709551615, 0, 2, 1), - (13, 508, 763, 736, 18446744073709551615, 0, 2, 1), - (13, 509, 767, 735, 18446744073709551615, 0, 2, 1), - (13, 510, 1026, 734, 18446744073709551615, 0, 2, 1), - (13, 918, 696, 695, 18446744073709551615, 2, 4, 2), - (13, 921, 693, 692, 18446744073709551615, 2, 4, 2), - (13, 154, 692, 691, 18446744073709551615, 2, 4, 2), - (13, 154, 692, 691, 18446744073709551615, 3, 4, 2), - (13, 921, 693, 692, 18446744073709551615, 3, 4, 2), - (13, 918, 696, 695, 18446744073709551615, 3, 4, 2), - (13, 818, 558, 557, 18446744073709551615, 4, 5, 1), - (13, 815, 559, 558, 18446744073709551615, 4, 5, 1), - (13, 816, 558, 557, 18446744073709551615, 9, 10, 1), - (13, 921, 665, 664, 18446744073709551615, 0, 2, 2), - (13, 154, 664, 663, 18446744073709551615, 0, 2, 2), - (13, 160, 660, 659, 18446744073709551615, 0, 2, 2), - (13, 158, 659, 658, 18446744073709551615, 0, 2, 2), - (13, 158, 659, 658, 18446744073709551615, 1, 2, 2), - (13, 160, 660, 659, 18446744073709551615, 1, 2, 2), - (13, 154, 664, 663, 18446744073709551615, 1, 2, 2), - (13, 921, 665, 664, 18446744073709551615, 1, 2, 2), - (13, 818, 562, 561, 18446744073709551615, 2, 3, 1), - (13, 815, 563, 562, 18446744073709551615, 2, 3, 1), - (13, 816, 562, 561, 18446744073709551615, 5, 6, 1), - (13, 157, 693, 692, 18446744073709551615, 0, 2, 2), - (13, 153, 691, 690, 18446744073709551615, 0, 2, 2), - (13, 160, 690, 689, 18446744073709551615, 0, 2, 2), - (13, 158, 689, 688, 18446744073709551615, 0, 2, 2), - (13, 933, 686, 612, 18446744073709551615, 0, 2, 2), - (13, 165, 612, 613, 18446744073709551615, 0, 2, 2), - (13, 165, 612, 613, 18446744073709551615, 1, 2, 2), - (13, 933, 686, 612, 18446744073709551615, 1, 2, 2), - (13, 158, 689, 688, 18446744073709551615, 1, 2, 2), - (13, 160, 690, 689, 18446744073709551615, 1, 2, 2), - (13, 153, 691, 690, 18446744073709551615, 1, 2, 2), - (13, 157, 693, 692, 18446744073709551615, 1, 2, 2), - (13, 818, 564, 563, 18446744073709551615, 2, 3, 1), - (13, 815, 565, 564, 18446744073709551615, 2, 3, 1), - (13, 816, 564, 563, 18446744073709551615, 5, 6, 1), - (13, 158, 663, 662, 18446744073709551615, 0, 2, 2), - (13, 929, 661, 660, 18446744073709551615, 0, 2, 2), - (13, 929, 661, 660, 18446744073709551615, 1, 2, 2), - (13, 158, 663, 662, 18446744073709551615, 1, 2, 2), - (13, 818, 568, 567, 18446744073709551615, 2, 3, 1), - (13, 815, 569, 568, 18446744073709551615, 2, 3, 1), - (13, 816, 568, 567, 18446744073709551615, 5, 6, 1), - (13, 949, 689, 1139, 18446744073709551615, 0, 1, 2), - (13, 951, 687, 1151, 18446744073709551615, 0, 1, 2), - (13, 818, 590, 589, 18446744073709551615, 2, 3, 1), - (13, 815, 591, 590, 18446744073709551615, 2, 3, 1), - (13, 816, 590, 589, 18446744073709551615, 5, 6, 1), - (13, 798, 631, 630, 18446744073709551615, 0, 5, 2), - (13, 799, 630, 629, 18446744073709551615, 1, 5, 2), - (13, 800, 631, 630, 18446744073709551615, 0, 4, 2), - (13, 800, 632, 631, 18446744073709551615, 0, 4, 2), - (13, 801, 631, 630, 18446744073709551615, 0, 4, 2), - (13, 801, 632, 631, 18446744073709551615, 0, 4, 2), - (13, 799, 631, 630, 18446744073709551615, 1, 4, 2), - (13, 800, 631, 630, 18446744073709551615, 1, 4, 2), - (13, 800, 632, 631, 18446744073709551615, 1, 4, 2), - (13, 801, 631, 630, 18446744073709551615, 1, 4, 2), - (13, 801, 632, 631, 18446744073709551615, 1, 4, 2), - (13, 803, 632, 631, 18446744073709551615, 0, 3, 2), - (13, 799, 630, 629, 18446744073709551615, 3, 5, 2), - (13, 800, 632, 631, 18446744073709551615, 2, 4, 2), - (13, 801, 631, 630, 18446744073709551615, 2, 4, 2), - (13, 802, 631, 630, 18446744073709551615, 2, 4, 2), - (13, 803, 631, 630, 18446744073709551615, 1, 3, 2), - (13, 804, 632, 631, 18446744073709551615, 0, 2, 2), - (13, 806, 631, 630, 18446744073709551615, 0, 2, 2), - (13, 807, 631, 630, 18446744073709551615, 0, 2, 2), - (13, 798, 632, 631, 18446744073709551615, 3, 4, 2), - (13, 799, 631, 630, 18446744073709551615, 3, 4, 2), - (13, 801, 631, 630, 18446744073709551615, 3, 4, 2), - (13, 802, 631, 630, 18446744073709551615, 3, 4, 2), - (13, 803, 631, 630, 18446744073709551615, 2, 3, 2), - (13, 805, 631, 630, 18446744073709551615, 1, 2, 2), - (13, 806, 631, 630, 18446744073709551615, 1, 2, 2), - (13, 807, 631, 630, 18446744073709551615, 1, 2, 2), - (13, 807, 632, 631, 18446744073709551615, 1, 2, 2), - (13, 808, 631, 630, 18446744073709551615, 1, 2, 2), - (13, 811, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 813, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 816, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 817, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 818, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 820, 632, 631, 18446744073709551615, 0, 1, 2), - (13, 822, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 823, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 825, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 826, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 827, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 827, 632, 631, 18446744073709551615, 0, 1, 2), - (13, 828, 632, 631, 18446744073709551615, 0, 1, 2), - (13, 829, 632, 631, 18446744073709551615, 0, 1, 2), - (13, 830, 631, 630, 18446744073709551615, 0, 1, 2), - (13, 405, 924, 1052, 18446744073709551615, 1, 2, 2), - (13, 406, 923, 1051, 18446744073709551615, 1, 2, 1), - (13, 407, 928, 1053, 18446744073709551615, 1, 2, 1), - (13, 408, 927, 255, 18446744073709551615, 1, 2, 1), - (13, 409, 926, 1047, 18446744073709551615, 1, 2, 1), - (13, 410, 1085, 252, 18446744073709551615, 1, 2, 1), - (13, 411, 934, 172, 18446744073709551615, 1, 2, 1), - (13, 412, 931, 249, 18446744073709551615, 1, 2, 1), - (13, 413, 930, 246, 18446744073709551615, 1, 2, 1), - (13, 414, 163, 243, 18446744073709551615, 1, 2, 1), - (13, 415, 932, 240, 18446744073709551615, 1, 2, 1), - (13, 416, 940, 237, 18446744073709551615, 1, 2, 1), - (13, 417, 171, 234, 18446744073709551615, 1, 2, 1), - (13, 418, 166, 231, 18446744073709551615, 1, 2, 2), - (13, 419, 1084, 228, 18446744073709551615, 1, 2, 1), - (13, 420, 939, 225, 18446744073709551615, 1, 2, 1), - (13, 421, 938, 222, 18446744073709551615, 1, 2, 1), - (13, 422, 169, 219, 18446744073709551615, 1, 2, 1), - (13, 423, 944, 216, 18446744073709551615, 1, 2, 1), - (13, 424, 941, 213, 18446744073709551615, 1, 2, 1), - (13, 425, 1081, 210, 18446744073709551615, 1, 2, 1), - (13, 426, 947, 207, 18446744073709551615, 1, 2, 1), - (13, 427, 175, 204, 18446744073709551615, 1, 2, 1), - (13, 428, 1080, 201, 18446744073709551615, 1, 2, 1), - (13, 429, 950, 198, 18446744073709551615, 1, 2, 1), - (13, 430, 178, 195, 18446744073709551615, 1, 2, 1), - (13, 431, 1079, 192, 18446744073709551615, 1, 2, 1), - (13, 432, 953, 189, 18446744073709551615, 1, 2, 1), - (13, 433, 181, 186, 18446744073709551615, 1, 2, 1), - (13, 434, 1078, 183, 18446744073709551615, 1, 2, 1), - (13, 435, 956, 180, 18446744073709551615, 1, 2, 1), - (13, 436, 184, 177, 18446744073709551615, 1, 2, 1), - (13, 437, 1077, 174, 18446744073709551615, 1, 2, 1), - (13, 438, 959, 1083, 18446744073709551615, 1, 2, 1), - (13, 439, 187, 173, 18446744073709551615, 1, 2, 1), - (13, 440, 1076, 159, 18446744073709551615, 1, 2, 1), - (13, 441, 962, 912, 18446744073709551615, 1, 2, 1), - (13, 442, 190, 152, 18446744073709551615, 1, 2, 1), - (13, 443, 1075, 149, 18446744073709551615, 1, 2, 1), - (13, 444, 965, 141, 18446744073709551615, 1, 2, 1), - (13, 445, 193, 1091, 18446744073709551615, 1, 2, 1), - (13, 446, 1074, 1096, 18446744073709551615, 1, 2, 1), - (13, 447, 968, 137, 18446744073709551615, 1, 2, 1), - (13, 448, 196, 134, 18446744073709551615, 1, 2, 1), - (13, 449, 1073, 131, 18446744073709551615, 1, 2, 1), - (13, 450, 971, 124, 18446744073709551615, 1, 2, 1), - (13, 451, 199, 122, 18446744073709551615, 1, 2, 1), - (13, 452, 1072, 112, 18446744073709551615, 1, 2, 1), - (13, 453, 974, 120, 18446744073709551615, 1, 2, 1), - (13, 454, 202, 109, 18446744073709551615, 1, 2, 1), - (13, 455, 1071, 106, 18446744073709551615, 1, 2, 1), - (13, 456, 977, 103, 18446744073709551615, 1, 2, 1), - (13, 457, 205, 100, 18446744073709551615, 1, 2, 1), - (13, 458, 1070, 97, 18446744073709551615, 1, 2, 1), - (13, 459, 980, 94, 18446744073709551615, 1, 2, 1), - (13, 460, 208, 91, 18446744073709551615, 1, 2, 1), - (13, 461, 1069, 88, 18446744073709551615, 1, 2, 1), - (13, 462, 983, 85, 18446744073709551615, 1, 2, 1), - (13, 463, 211, 82, 18446744073709551615, 1, 2, 1), - (13, 464, 1068, 79, 18446744073709551615, 1, 2, 1), - (13, 465, 986, 76, 18446744073709551615, 1, 2, 1), - (13, 466, 214, 73, 18446744073709551615, 1, 2, 1), - (13, 467, 1067, 70, 18446744073709551615, 1, 2, 1), - (13, 468, 989, 67, 18446744073709551615, 1, 2, 1), - (13, 469, 217, 64, 18446744073709551615, 1, 2, 1), - (13, 470, 1066, 61, 18446744073709551615, 1, 2, 1), - (13, 471, 992, 58, 18446744073709551615, 1, 2, 1), - (13, 472, 220, 55, 18446744073709551615, 1, 2, 1), - (13, 473, 1065, 52, 18446744073709551615, 1, 2, 1), - (13, 474, 995, 49, 18446744073709551615, 1, 2, 1), - (13, 475, 223, 46, 18446744073709551615, 1, 2, 1), - (13, 476, 1064, 43, 18446744073709551615, 1, 2, 1), - (13, 477, 998, 40, 18446744073709551615, 1, 2, 1), - (13, 478, 226, 37, 18446744073709551615, 1, 2, 1), - (13, 479, 1063, 34, 18446744073709551615, 1, 2, 1), - (13, 480, 1001, 31, 18446744073709551615, 1, 2, 1), - (13, 481, 229, 28, 18446744073709551615, 1, 2, 1), - (13, 482, 1062, 19, 18446744073709551615, 1, 2, 1), - (13, 483, 1004, 1133, 18446744073709551615, 1, 2, 1), - (13, 484, 232, 784, 18446744073709551615, 1, 2, 1), - (13, 485, 1061, 782, 18446744073709551615, 1, 2, 1), - (13, 486, 1007, 1138, 18446744073709551615, 1, 2, 1), - (13, 487, 235, 1114, 18446744073709551615, 1, 2, 1), - (13, 488, 1060, 1135, 18446744073709551615, 1, 2, 1), - (13, 489, 1010, 783, 18446744073709551615, 1, 2, 1), - (13, 490, 238, 1136, 18446744073709551615, 1, 2, 1), - (13, 491, 1059, 836, 18446744073709551615, 1, 2, 1), - (13, 492, 1013, 15, 18446744073709551615, 1, 2, 1), - (13, 493, 241, 1146, 18446744073709551615, 1, 2, 1), - (13, 494, 1058, 746, 18446744073709551615, 1, 2, 1), - (13, 495, 1016, 1152, 18446744073709551615, 1, 2, 1), - (13, 496, 244, 781, 18446744073709551615, 1, 2, 1), - (13, 497, 1057, 1143, 18446744073709551615, 1, 2, 1), - (13, 498, 1019, 1144, 18446744073709551615, 1, 2, 1), - (13, 499, 247, 745, 18446744073709551615, 1, 2, 1), - (13, 500, 1056, 744, 18446744073709551615, 1, 2, 1), - (13, 501, 1022, 743, 18446744073709551615, 1, 2, 1), - (13, 502, 250, 742, 18446744073709551615, 1, 2, 1), - (13, 503, 1054, 741, 18446744073709551615, 1, 2, 1), - (13, 504, 1055, 740, 18446744073709551615, 1, 2, 1), - (13, 505, 253, 739, 18446744073709551615, 1, 2, 1), - (13, 506, 766, 738, 18446744073709551615, 1, 2, 1), - (13, 507, 764, 737, 18446744073709551615, 1, 2, 1), - (13, 508, 763, 736, 18446744073709551615, 1, 2, 1), - (13, 509, 767, 735, 18446744073709551615, 1, 2, 1), - (13, 510, 1026, 734, 18446744073709551615, 1, 2, 1), - (13, 754, 898, 897, 18446744073709551615, 0, 261, 1), - (13, 1029, 1032, 1049, 18446744073709551615, 1, 12, 2), - (13, 1029, 765, 1023, 18446744073709551615, 1, 13, 2), - (13, 1029, 1031, 254, 18446744073709551615, 1, 14, 2), - (13, 1029, 1027, 1021, 18446744073709551615, 1, 15, 2), - (13, 1029, 1036, 1020, 18446744073709551615, 1, 16, 2), - (13, 1029, 1034, 251, 18446744073709551615, 1, 17, 2), - (13, 1029, 1030, 1018, 18446744073709551615, 1, 18, 2), - (13, 1029, 1038, 1017, 18446744073709551615, 1, 19, 2), - (13, 1029, 1037, 248, 18446744073709551615, 1, 20, 2), - (13, 1029, 1039, 1015, 18446744073709551615, 1, 21, 2), - (13, 1029, 1043, 1014, 18446744073709551615, 1, 22, 2), - (13, 1029, 1033, 245, 18446744073709551615, 1, 23, 2), - (13, 1029, 1041, 1012, 18446744073709551615, 1, 24, 2), - (13, 1029, 1035, 1011, 18446744073709551615, 1, 25, 2), - (13, 1029, 1045, 242, 18446744073709551615, 1, 26, 2), - (13, 1029, 1044, 1009, 18446744073709551615, 1, 27, 2), - (13, 1029, 1046, 1008, 18446744073709551615, 1, 28, 2), - (13, 1029, 1050, 239, 18446744073709551615, 1, 29, 2), - (13, 1029, 1040, 1006, 18446744073709551615, 1, 30, 2), - (13, 1029, 1048, 1005, 18446744073709551615, 1, 31, 2), - (13, 1029, 1042, 236, 18446744073709551615, 1, 32, 2), - (13, 1029, 1052, 1003, 18446744073709551615, 1, 33, 2), - (13, 1029, 1051, 1002, 18446744073709551615, 1, 34, 2), - (13, 1029, 1053, 233, 18446744073709551615, 1, 35, 2), - (13, 1029, 255, 1000, 18446744073709551615, 1, 36, 2), - (13, 1029, 1047, 999, 18446744073709551615, 1, 37, 2), - (13, 1029, 252, 230, 18446744073709551615, 1, 38, 2), - (13, 1029, 172, 997, 18446744073709551615, 1, 39, 2), - (13, 1029, 249, 996, 18446744073709551615, 1, 40, 2), - (13, 1029, 246, 227, 18446744073709551615, 1, 41, 2), - (13, 1029, 243, 994, 18446744073709551615, 1, 42, 2), - (13, 1029, 240, 993, 18446744073709551615, 1, 43, 2), - (13, 1029, 237, 224, 18446744073709551615, 1, 44, 2), - (13, 1029, 234, 991, 18446744073709551615, 1, 45, 2), - (13, 1029, 231, 990, 18446744073709551615, 1, 46, 2), - (13, 1029, 228, 221, 18446744073709551615, 1, 47, 2), - (13, 1029, 225, 988, 18446744073709551615, 1, 48, 2), - (13, 1029, 222, 987, 18446744073709551615, 1, 49, 2), - (13, 1029, 219, 218, 18446744073709551615, 1, 50, 2), - (13, 1029, 216, 985, 18446744073709551615, 1, 51, 2), - (13, 1029, 213, 984, 18446744073709551615, 1, 52, 2), - (13, 1029, 210, 215, 18446744073709551615, 1, 53, 2), - (13, 1029, 207, 982, 18446744073709551615, 1, 54, 2), - (13, 1029, 204, 981, 18446744073709551615, 1, 55, 2), - (13, 1029, 201, 212, 18446744073709551615, 1, 56, 2), - (13, 1029, 198, 979, 18446744073709551615, 1, 57, 2), - (13, 1029, 195, 978, 18446744073709551615, 1, 58, 2), - (13, 1029, 192, 209, 18446744073709551615, 1, 59, 2), - (13, 1029, 189, 976, 18446744073709551615, 1, 60, 2), - (13, 1029, 186, 975, 18446744073709551615, 1, 61, 2), - (13, 1029, 183, 206, 18446744073709551615, 1, 62, 2), - (13, 1029, 180, 973, 18446744073709551615, 1, 63, 2), - (13, 1029, 177, 972, 18446744073709551615, 1, 64, 2), - (13, 1029, 174, 203, 18446744073709551615, 1, 65, 2), - (13, 1029, 1083, 970, 18446744073709551615, 1, 66, 2), - (13, 1029, 173, 969, 18446744073709551615, 1, 67, 2), - (13, 1029, 159, 200, 18446744073709551615, 1, 68, 2), - (13, 1029, 912, 967, 18446744073709551615, 1, 69, 2), - (13, 1029, 152, 966, 18446744073709551615, 1, 70, 2), - (13, 1029, 149, 197, 18446744073709551615, 1, 71, 2), - (13, 1029, 141, 964, 18446744073709551615, 1, 72, 2), - (13, 1029, 1091, 963, 18446744073709551615, 1, 73, 2), - (13, 1029, 1096, 194, 18446744073709551615, 1, 74, 2), - (13, 1029, 137, 961, 18446744073709551615, 1, 75, 2), - (13, 1029, 134, 960, 18446744073709551615, 1, 76, 2), - (13, 1029, 131, 191, 18446744073709551615, 1, 77, 2), - (13, 1029, 124, 958, 18446744073709551615, 1, 78, 2), - (13, 1029, 122, 957, 18446744073709551615, 1, 79, 2), - (13, 1029, 112, 188, 18446744073709551615, 1, 80, 2), - (13, 1029, 120, 955, 18446744073709551615, 1, 81, 2), - (13, 1029, 109, 954, 18446744073709551615, 1, 82, 2), - (13, 1029, 106, 185, 18446744073709551615, 1, 83, 2), - (13, 1029, 103, 952, 18446744073709551615, 1, 84, 2), - (13, 1029, 100, 951, 18446744073709551615, 1, 85, 2), - (13, 1029, 97, 182, 18446744073709551615, 1, 86, 2), - (13, 1029, 94, 949, 18446744073709551615, 1, 87, 2), - (13, 1029, 91, 948, 18446744073709551615, 1, 88, 2), - (13, 1029, 88, 179, 18446744073709551615, 1, 89, 2), - (13, 1029, 85, 946, 18446744073709551615, 1, 90, 2), - (13, 1029, 82, 945, 18446744073709551615, 1, 91, 2), - (13, 1029, 79, 176, 18446744073709551615, 1, 92, 2), - (13, 1029, 76, 943, 18446744073709551615, 1, 93, 2), - (13, 1029, 73, 942, 18446744073709551615, 1, 94, 2), - (13, 1029, 70, 1082, 18446744073709551615, 1, 96, 2), - (13, 1029, 67, 156, 18446744073709551615, 1, 97, 2), - (13, 1029, 64, 168, 18446744073709551615, 1, 97, 2), - (13, 1029, 61, 170, 18446744073709551615, 1, 98, 2), - (13, 1029, 58, 937, 18446744073709551615, 1, 99, 2), - (13, 1029, 55, 936, 18446744073709551615, 1, 100, 2), - (13, 1029, 52, 167, 18446744073709551615, 1, 101, 2), - (13, 1029, 49, 162, 18446744073709551615, 1, 102, 2), - (13, 1029, 46, 164, 18446744073709551615, 1, 102, 2), - (13, 1029, 43, 161, 18446744073709551615, 1, 103, 2), - (13, 1029, 40, 165, 18446744073709551615, 1, 103, 2), - (13, 1029, 37, 933, 18446744073709551615, 1, 105, 2), - (13, 1029, 34, 929, 18446744073709551615, 1, 106, 2), - (13, 1029, 31, 935, 18446744073709551615, 1, 107, 2), - (13, 1029, 28, 158, 18446744073709551615, 1, 107, 2), - (13, 1029, 19, 160, 18446744073709551615, 1, 109, 2), - (13, 1029, 1133, 153, 18446744073709551615, 1, 110, 2), - (13, 1029, 784, 155, 18446744073709551615, 1, 110, 2), - (13, 1029, 782, 157, 18446744073709551615, 1, 112, 2), - (13, 1029, 1138, 154, 18446744073709551615, 1, 113, 2), - (13, 1029, 1114, 921, 18446744073709551615, 1, 114, 2), - (13, 1029, 1135, 920, 18446744073709551615, 1, 115, 2), - (13, 1029, 783, 151, 18446744073709551615, 1, 116, 2), - (13, 1029, 1136, 918, 18446744073709551615, 1, 117, 2), - (13, 1029, 836, 911, 18446744073709551615, 1, 118, 2), - (13, 1029, 15, 145, 18446744073709551615, 1, 118, 2), - (13, 1029, 1146, 147, 18446744073709551615, 1, 119, 2), - (13, 1029, 746, 914, 18446744073709551615, 1, 120, 2), - (13, 1029, 1152, 913, 18446744073709551615, 1, 121, 2), - (13, 1029, 781, 144, 18446744073709551615, 1, 122, 2), - (13, 1029, 1143, 919, 18446744073709551615, 1, 124, 2), - (13, 1029, 1144, 142, 18446744073709551615, 1, 125, 2), - (13, 1029, 745, 910, 18446744073709551615, 1, 126, 2), - (13, 1029, 744, 139, 18446744073709551615, 1, 126, 2), - (13, 1029, 743, 140, 18446744073709551615, 1, 128, 2), - (13, 1029, 742, 906, 18446744073709551615, 1, 129, 2), - (13, 1029, 741, 905, 18446744073709551615, 1, 130, 2), - (13, 1029, 740, 136, 18446744073709551615, 1, 131, 2), - (13, 1029, 739, 903, 18446744073709551615, 1, 132, 2), - (13, 1029, 738, 902, 18446744073709551615, 1, 133, 2), - (13, 1029, 737, 133, 18446744073709551615, 1, 134, 2), - (13, 1029, 736, 900, 18446744073709551615, 1, 135, 2), - (13, 1029, 735, 1095, 18446744073709551615, 1, 136, 2), - (13, 1029, 734, 127, 18446744073709551615, 1, 136, 2), - (13, 1029, 762, 129, 18446744073709551615, 1, 137, 2), - (13, 1029, 761, 896, 18446744073709551615, 1, 138, 2), - (13, 1029, 760, 895, 18446744073709551615, 1, 139, 2), - (13, 1029, 759, 126, 18446744073709551615, 1, 140, 2), - (13, 1029, 758, 893, 18446744073709551615, 1, 141, 2), - (13, 1029, 757, 892, 18446744073709551615, 1, 143, 2), - (13, 1029, 756, 891, 18446744073709551615, 1, 144, 2), - (13, 1029, 1142, 1116, 18446744073709551615, 1, 145, 2), - (13, 1029, 779, 890, 18446744073709551615, 1, 145, 2), - (13, 1029, 778, 115, 18446744073709551615, 1, 147, 2), - (13, 1029, 1148, 118, 18446744073709551615, 1, 147, 2), - (13, 1029, 780, 119, 18446744073709551615, 1, 148, 2), - (13, 1029, 1140, 117, 18446744073709551615, 1, 149, 2), - (13, 1029, 1118, 884, 18446744073709551615, 1, 150, 2), - (13, 1029, 16, 883, 18446744073709551615, 1, 151, 2), - (13, 1029, 1113, 114, 18446744073709551615, 1, 152, 2), - (13, 1029, 785, 881, 18446744073709551615, 1, 153, 2), - (13, 1029, 840, 880, 18446744073709551615, 1, 154, 2), - (13, 1029, 794, 111, 18446744073709551615, 1, 155, 2), - (13, 1029, 22, 878, 18446744073709551615, 1, 156, 2), - (13, 1029, 1115, 877, 18446744073709551615, 1, 157, 2), - (13, 1029, 21, 108, 18446744073709551615, 1, 158, 2), - (13, 1029, 26, 875, 18446744073709551615, 1, 159, 2), - (13, 1029, 25, 874, 18446744073709551615, 1, 160, 2), - (13, 1029, 24, 105, 18446744073709551615, 1, 161, 2), - (13, 1029, 1131, 872, 18446744073709551615, 1, 162, 2), - (13, 1029, 792, 871, 18446744073709551615, 1, 163, 2), - (13, 1029, 30, 102, 18446744073709551615, 1, 164, 2), - (13, 1029, 1130, 869, 18446744073709551615, 1, 165, 2), - (13, 1029, 29, 868, 18446744073709551615, 1, 166, 2), - (13, 1029, 33, 99, 18446744073709551615, 1, 167, 2), - (13, 1029, 1129, 866, 18446744073709551615, 1, 168, 2), - (13, 1029, 32, 865, 18446744073709551615, 1, 169, 2), - (13, 1029, 36, 96, 18446744073709551615, 1, 170, 2), - (13, 1029, 1128, 863, 18446744073709551615, 1, 171, 2), - (13, 1029, 35, 862, 18446744073709551615, 1, 172, 2), - (13, 1029, 39, 93, 18446744073709551615, 1, 173, 2), - (13, 1029, 1127, 860, 18446744073709551615, 1, 174, 2), - (13, 1029, 38, 859, 18446744073709551615, 1, 175, 2), - (13, 1029, 42, 90, 18446744073709551615, 1, 176, 2), - (13, 1029, 1126, 857, 18446744073709551615, 1, 177, 2), - (13, 1029, 41, 856, 18446744073709551615, 1, 178, 2), - (13, 1029, 45, 87, 18446744073709551615, 1, 179, 2), - (13, 1029, 1125, 854, 18446744073709551615, 1, 180, 2), - (13, 1029, 44, 853, 18446744073709551615, 1, 181, 2), - (13, 1029, 48, 84, 18446744073709551615, 1, 182, 2), - (13, 1029, 1124, 851, 18446744073709551615, 1, 183, 2), - (13, 1029, 47, 850, 18446744073709551615, 1, 184, 2), - (13, 1029, 51, 81, 18446744073709551615, 1, 185, 2), - (13, 1029, 1123, 848, 18446744073709551615, 1, 186, 2), - (13, 1029, 50, 847, 18446744073709551615, 1, 187, 2), - (13, 1029, 54, 78, 18446744073709551615, 1, 188, 2), - (13, 1029, 1122, 845, 18446744073709551615, 1, 189, 2), - (13, 1029, 53, 844, 18446744073709551615, 1, 190, 2), - (13, 1029, 57, 75, 18446744073709551615, 1, 191, 2), - (13, 1029, 1121, 842, 18446744073709551615, 1, 192, 2), - (13, 1029, 56, 841, 18446744073709551615, 1, 193, 2), - (13, 1029, 60, 72, 18446744073709551615, 1, 194, 2), - (13, 1029, 1120, 839, 18446744073709551615, 1, 195, 2), - (13, 1029, 59, 837, 18446744073709551615, 1, 196, 2), - (13, 1029, 63, 69, 18446744073709551615, 1, 197, 2), - (13, 1029, 1117, 835, 18446744073709551615, 1, 198, 2), - (13, 1029, 62, 834, 18446744073709551615, 1, 199, 2), - (13, 1029, 66, 833, 18446744073709551615, 1, 200, 2), - (13, 1029, 1119, 832, 18446744073709551615, 1, 201, 2), - (13, 1029, 65, 831, 18446744073709551615, 1, 202, 2), - (13, 1029, 1112, 830, 18446744073709551615, 1, 203, 2), - (13, 1029, 838, 829, 18446744073709551615, 1, 204, 2), - (13, 1029, 68, 828, 18446744073709551615, 1, 205, 2), - (13, 1029, 1111, 827, 18446744073709551615, 1, 206, 2), - (13, 1029, 843, 826, 18446744073709551615, 1, 207, 2), - (13, 1029, 71, 825, 18446744073709551615, 1, 208, 2), - (13, 1029, 1110, 824, 18446744073709551615, 1, 209, 2), - (13, 1029, 846, 823, 18446744073709551615, 1, 210, 2), - (13, 1029, 74, 822, 18446744073709551615, 1, 211, 2), - (13, 1029, 1109, 821, 18446744073709551615, 1, 212, 2), - (13, 1029, 849, 820, 18446744073709551615, 1, 213, 2), - (13, 1029, 77, 819, 18446744073709551615, 1, 214, 2), - (13, 1029, 870, 799, 18446744073709551615, 1, 234, 2), - (13, 1029, 98, 798, 18446744073709551615, 1, 235, 2), - (13, 764, 1031, 254, 18446744073709551615, 11, 12, 2), - (13, 764, 1036, 1020, 18446744073709551615, 13, 14, 2), - (13, 764, 1030, 1018, 18446744073709551615, 15, 16, 2), - (13, 764, 1038, 1017, 18446744073709551615, 16, 17, 2), - (13, 764, 1037, 248, 18446744073709551615, 17, 18, 2), - (13, 764, 70, 1082, 18446744073709551615, 93, 94, 2), - (13, 764, 67, 156, 18446744073709551615, 94, 95, 2), - (13, 764, 894, 27, 18446744073709551615, 245, 246, 2), - (13, 764, 885, 1134, 18446744073709551615, 246, 247, 2), - (13, 764, 113, 17, 18446744073709551615, 247, 248, 2), - (13, 764, 887, 1137, 18446744073709551615, 248, 250, 2), - (13, 764, 887, 1137, 18446744073709551615, 249, 250, 2), - (13, 764, 1097, 1145, 18446744073709551615, 250, 253, 2), - (13, 764, 898, 754, 18446744073709551615, 259, 260, 1), - (13, 754, 898, 897, 18446744073709551615, 260, 261, 2), - (13, 886, 916, 917, 18446744073709551615, 0, 1, 2), - (13, 886, 916, 1149, 18446744073709551615, 0, 1, 2), - (13, 0, 1025, 148, 18446744073709551615, 0, 1, 1), - (13, 303, 10, 793, 18446744073709551615, 0, 7, 1), - (13, 304, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 305, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 306, 1147, 1025, 18446744073709551615, 1, 2, 1), - (13, 297, 1141, 10, 18446744073709551615, 0, 1, 1), - (13, 298, 10, 793, 18446744073709551615, 1, 8, 1), - (13, 299, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 300, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 301, 1147, 1025, 18446744073709551615, 1, 2, 1), - (13, 290, 12, 1141, 18446744073709551615, 0, 4, 1), - (13, 291, 1141, 10, 18446744073709551615, 1, 2, 1), - (13, 292, 10, 793, 18446744073709551615, 1, 8, 1), - (13, 293, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 294, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 295, 1147, 1025, 18446744073709551615, 1, 2, 1), - (13, 282, 1132, 12, 18446744073709551615, 0, 1, 1), - (13, 283, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 284, 1141, 10, 18446744073709551615, 1, 2, 1), - (13, 285, 10, 793, 18446744073709551615, 1, 6, 1), - (13, 286, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 287, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 288, 1147, 1025, 18446744073709551615, 1, 2, 1), - (13, 273, 1151, 1132, 18446744073709551615, 0, 2, 1), - (13, 274, 1132, 12, 18446744073709551615, 1, 4, 1), - (13, 275, 12, 1141, 18446744073709551615, 1, 4, 1), - (13, 276, 1141, 10, 18446744073709551615, 1, 4, 1), - (13, 277, 10, 793, 18446744073709551615, 1, 3, 1), - (13, 278, 793, 9, 18446744073709551615, 1, 2, 1), - (13, 279, 9, 1147, 18446744073709551615, 1, 4, 1), - (13, 280, 1147, 1025, 18446744073709551615, 1, 2, 1), - (13, 263, 1150, 1151, 18446744073709551615, 0, 2, 1), - (13, 273, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 274, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 276, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 278, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 279, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 295, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 296, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 297, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 298, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 299, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 0, 1025, 1097, 18446744073709551615, 0, 2, 1), - (13, 274, 1132, 12, 18446744073709551615, 2, 4, 2), - (13, 275, 12, 1141, 18446744073709551615, 2, 4, 2), - (13, 276, 1141, 10, 18446744073709551615, 2, 4, 2), - (13, 282, 12, 1141, 18446744073709551615, 0, 4, 2), - (13, 296, 9, 143, 18446744073709551615, 0, 2, 2), - (13, 299, 1141, 9, 18446744073709551615, 0, 1, 2), - (13, 300, 9, 143, 18446744073709551615, 0, 3, 2), - (13, 306, 143, 1147, 18446744073709551615, 0, 1, 1), - (13, 303, 9, 143, 18446744073709551615, 0, 1, 1), - (13, 304, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 299, 10, 9, 18446744073709551615, 0, 2, 1), - (13, 300, 9, 143, 18446744073709551615, 1, 3, 1), - (13, 301, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 294, 1141, 10, 18446744073709551615, 0, 1, 1), - (13, 295, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 296, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 297, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 288, 12, 1141, 18446744073709551615, 0, 3, 1), - (13, 281, 1132, 12, 18446744073709551615, 0, 2, 1), - (13, 282, 12, 1141, 18446744073709551615, 1, 4, 1), - (13, 283, 1141, 10, 18446744073709551615, 1, 2, 1), - (13, 284, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 285, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 286, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 273, 1151, 1132, 18446744073709551615, 1, 2, 1), - (13, 274, 1132, 12, 18446744073709551615, 3, 4, 1), - (13, 275, 12, 1141, 18446744073709551615, 3, 4, 1), - (13, 276, 1141, 10, 18446744073709551615, 3, 4, 1), - (13, 277, 10, 9, 18446744073709551615, 1, 2, 1), - (13, 278, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 279, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 276, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 278, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 279, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 281, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 298, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 302, 1153, 1025, 18446744073709551615, 0, 1, 2), - (13, 307, 1153, 1147, 18446744073709551615, 0, 1, 2), - (13, 3, 773, 1097, 18446744073709551615, 1, 2, 2), - (13, 1028, 773, 3, 18446744073709551615, 1, 261, 2), - (13, 0, 1025, 1097, 18446744073709551615, 1, 2, 1), - (13, 274, 1147, 1088, 18446744073709551615, 0, 4, 2), - (13, 278, 12, 1141, 18446744073709551615, 0, 5, 2), - (13, 281, 143, 1147, 18446744073709551615, 0, 4, 2), - (13, 297, 12, 9, 18446744073709551615, 0, 2, 2), - (13, 298, 9, 143, 18446744073709551615, 0, 4, 2), - (13, 301, 1088, 1141, 18446744073709551615, 0, 2, 2), - (13, 302, 1141, 143, 18446744073709551615, 0, 2, 2), - (13, 302, 9, 143, 18446744073709551615, 0, 2, 1), - (13, 303, 143, 1147, 18446744073709551615, 1, 4, 1), - (13, 304, 1147, 1088, 18446744073709551615, 1, 8, 1), - (13, 297, 1141, 9, 18446744073709551615, 0, 2, 1), - (13, 298, 9, 143, 18446744073709551615, 1, 4, 1), - (13, 299, 143, 1147, 18446744073709551615, 1, 4, 1), - (13, 300, 1147, 1088, 18446744073709551615, 1, 8, 1), - (13, 295, 1147, 1088, 18446744073709551615, 1, 10, 1), - (13, 284, 1132, 12, 18446744073709551615, 0, 2, 1), - (13, 285, 12, 1141, 18446744073709551615, 1, 6, 1), - (13, 286, 1141, 9, 18446744073709551615, 1, 5, 1), - (13, 287, 9, 143, 18446744073709551615, 1, 4, 1), - (13, 288, 143, 1147, 18446744073709551615, 1, 4, 1), - (13, 276, 1151, 1132, 18446744073709551615, 0, 1, 1), - (13, 277, 1132, 12, 18446744073709551615, 1, 2, 1), - (13, 278, 12, 1141, 18446744073709551615, 1, 5, 1), - (13, 279, 1141, 9, 18446744073709551615, 1, 4, 1), - (13, 280, 9, 143, 18446744073709551615, 1, 4, 1), - (13, 281, 143, 1147, 18446744073709551615, 1, 4, 1), - (13, 282, 1147, 1088, 18446744073709551615, 1, 4, 1), - (13, 273, 143, 1147, 18446744073709551615, 1, 5, 1), - (13, 274, 1147, 1088, 18446744073709551615, 1, 4, 1), - (13, 276, 1025, 1088, 18446744073709551615, 0, 2, 2), - (13, 277, 1025, 1147, 18446744073709551615, 0, 1, 2), - (13, 278, 1025, 1088, 18446744073709551615, 0, 2, 2), - (13, 280, 1025, 1088, 18446744073709551615, 0, 2, 2), - (13, 281, 1025, 1147, 18446744073709551615, 0, 1, 2), - (13, 299, 1025, 1147, 18446744073709551615, 0, 1, 2), - (13, 300, 1025, 1088, 18446744073709551615, 0, 2, 2), - (13, 301, 1025, 1147, 18446744073709551615, 0, 1, 2), - (13, 302, 1025, 1088, 18446744073709551615, 0, 2, 2), - (13, 303, 1025, 1147, 18446744073709551615, 0, 1, 2), - (13, 4, 772, 116, 18446744073709551615, 0, 2, 2), - (13, 5, 771, 1097, 18446744073709551615, 0, 2, 2), - (13, 1028, 771, 5, 18446744073709551615, 2, 261, 2), - (13, 0, 1025, 14, 18446744073709551615, 0, 1, 1), - (13, 275, 1088, 10, 18446744073709551615, 0, 1, 2), - (13, 276, 10, 1151, 18446744073709551615, 0, 1, 2), - (13, 278, 12, 1141, 18446744073709551615, 2, 5, 2), - (13, 281, 143, 1147, 18446744073709551615, 2, 4, 2), - (13, 298, 9, 143, 18446744073709551615, 2, 4, 2), - (13, 300, 1147, 1088, 18446744073709551615, 2, 8, 2), - (13, 305, 1088, 9, 18446744073709551615, 1, 2, 2), - (13, 302, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 303, 143, 1147, 18446744073709551615, 3, 4, 1), - (13, 304, 1147, 1088, 18446744073709551615, 3, 8, 1), - (13, 297, 1141, 9, 18446744073709551615, 1, 2, 1), - (13, 298, 9, 143, 18446744073709551615, 3, 4, 1), - (13, 299, 143, 1147, 18446744073709551615, 3, 4, 1), - (13, 300, 1147, 1088, 18446744073709551615, 3, 8, 1), - (13, 284, 1151, 12, 18446744073709551615, 1, 2, 1), - (13, 285, 12, 1141, 18446744073709551615, 3, 6, 1), - (13, 286, 1141, 9, 18446744073709551615, 3, 5, 1), - (13, 287, 9, 143, 18446744073709551615, 3, 4, 1), - (13, 288, 143, 1147, 18446744073709551615, 3, 4, 1), - (13, 276, 793, 1151, 18446744073709551615, 0, 1, 1), - (13, 277, 1151, 12, 18446744073709551615, 1, 2, 1), - (13, 278, 12, 1141, 18446744073709551615, 3, 5, 1), - (13, 279, 1141, 9, 18446744073709551615, 3, 4, 1), - (13, 280, 9, 143, 18446744073709551615, 3, 4, 1), - (13, 281, 143, 1147, 18446744073709551615, 3, 4, 1), - (13, 282, 1147, 1088, 18446744073709551615, 3, 4, 1), - (13, 274, 1147, 1088, 18446744073709551615, 3, 4, 1), - (13, 277, 1025, 886, 18446744073709551615, 0, 1, 2), - (13, 280, 1025, 1088, 18446744073709551615, 1, 2, 2), - (13, 281, 1025, 886, 18446744073709551615, 0, 1, 2), - (13, 284, 1025, 1088, 18446744073709551615, 1, 2, 2), - (13, 299, 1025, 886, 18446744073709551615, 0, 1, 2), - (13, 300, 1025, 1088, 18446744073709551615, 1, 2, 2), - (13, 301, 1025, 886, 18446744073709551615, 0, 1, 2), - (13, 302, 1025, 1088, 18446744073709551615, 1, 2, 2), - (13, 303, 1025, 886, 18446744073709551615, 0, 2, 2), - (13, 6, 770, 148, 18446744073709551615, 1, 2, 2), - (13, 1028, 770, 6, 18446744073709551615, 4, 262, 2), - (13, 0, 1025, 11, 18446744073709551615, 0, 1, 1), - (13, 276, 9, 143, 18446744073709551615, 0, 2, 2), - (13, 277, 143, 1147, 18446744073709551615, 0, 2, 2), - (13, 280, 1088, 889, 18446744073709551615, 0, 2, 2), - (13, 282, 12, 9, 18446744073709551615, 0, 1, 2), - (13, 300, 143, 886, 18446744073709551615, 0, 1, 2), - (13, 302, 1088, 889, 18446744073709551615, 0, 5, 2), - (13, 305, 1088, 889, 18446744073709551615, 0, 7, 2), - (13, 304, 886, 1088, 18446744073709551615, 0, 15, 1), - (13, 305, 1088, 889, 18446744073709551615, 1, 7, 1), - (13, 300, 1147, 886, 18446744073709551615, 0, 7, 1), - (13, 301, 886, 1088, 18446744073709551615, 1, 16, 1), - (13, 302, 1088, 889, 18446744073709551615, 1, 5, 1), - (13, 298, 1088, 889, 18446744073709551615, 1, 2, 1), - (13, 282, 1141, 9, 18446744073709551615, 0, 1, 1), - (13, 283, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 284, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 285, 1147, 886, 18446744073709551615, 1, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 1, 12, 1), - (13, 287, 1088, 889, 18446744073709551615, 1, 2, 1), - (13, 276, 9, 143, 18446744073709551615, 1, 2, 1), - (13, 277, 143, 1147, 18446744073709551615, 1, 2, 1), - (13, 278, 1147, 886, 18446744073709551615, 1, 6, 1), - (13, 279, 886, 1088, 18446744073709551615, 1, 6, 1), - (13, 280, 1088, 889, 18446744073709551615, 1, 2, 1), - (13, 280, 1025, 889, 18446744073709551615, 0, 2, 2), - (13, 282, 1025, 889, 18446744073709551615, 0, 2, 2), - (13, 301, 1025, 1088, 18446744073709551615, 0, 1, 2), - (13, 303, 1025, 1088, 18446744073709551615, 0, 1, 2), - (13, 304, 1025, 889, 18446744073709551615, 0, 2, 2), - (13, 305, 1025, 1088, 18446744073709551615, 0, 1, 2), - (13, 7, 769, 1139, 18446744073709551615, 3, 6, 2), - (13, 8, 768, 1150, 18446744073709551615, 1, 6, 2), - (13, 1028, 768, 8, 18446744073709551615, 5, 262, 2), - (13, 1028, 769, 7, 18446744073709551615, 5, 262, 2), - (13, 1024, 888, 14, 18446744073709551615, 1, 256, 2), - (13, 0, 1025, 1149, 18446744073709551615, 0, 1, 1), - (13, 278, 1141, 9, 18446744073709551615, 0, 2, 2), - (13, 279, 9, 1147, 18446744073709551615, 2, 4, 2), - (13, 281, 886, 143, 18446744073709551615, 0, 1, 2), - (13, 285, 1141, 9, 18446744073709551615, 0, 2, 2), - (13, 299, 886, 12, 18446744073709551615, 0, 1, 2), - (13, 300, 12, 9, 18446744073709551615, 0, 1, 2), - (13, 301, 9, 1147, 18446744073709551615, 0, 2, 2), - (13, 303, 886, 1141, 18446744073709551615, 0, 1, 2), - (13, 304, 1141, 1147, 18446744073709551615, 0, 1, 2), - (13, 304, 9, 1147, 18446744073709551615, 0, 1, 1), - (13, 305, 1147, 886, 18446744073709551615, 1, 5, 1), - (13, 300, 1141, 9, 18446744073709551615, 0, 1, 1), - (13, 301, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 302, 1147, 886, 18446744073709551615, 1, 8, 1), - (13, 282, 10, 793, 18446744073709551615, 0, 5, 1), - (13, 283, 793, 12, 18446744073709551615, 1, 2, 1), - (13, 284, 12, 1141, 18446744073709551615, 1, 3, 1), - (13, 285, 1141, 9, 18446744073709551615, 1, 2, 1), - (13, 286, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 287, 1147, 886, 18446744073709551615, 1, 7, 1), - (13, 277, 12, 1141, 18446744073709551615, 1, 2, 1), - (13, 278, 1141, 9, 18446744073709551615, 1, 2, 1), - (13, 279, 9, 1147, 18446744073709551615, 3, 4, 1), - (13, 280, 1147, 886, 18446744073709551615, 1, 6, 1), - (13, 283, 1025, 915, 18446744073709551615, 0, 1, 2), - (13, 301, 1025, 915, 18446744073709551615, 0, 1, 2), - (13, 305, 1025, 915, 18446744073709551615, 0, 1, 2), - (13, 8, 768, 1132, 18446744073709551615, 1, 8, 2), - (13, 1028, 768, 8, 18446744073709551615, 6, 262, 2), - (13, 0, 1025, 13, 18446744073709551615, 0, 1, 1), - (13, 279, 886, 1088, 18446744073709551615, 2, 6, 2), - (13, 285, 1147, 886, 18446744073709551615, 2, 9, 2), - (13, 286, 886, 1088, 18446744073709551615, 2, 12, 2), - (13, 300, 889, 148, 18446744073709551615, 0, 4, 2), - (13, 302, 886, 915, 18446744073709551615, 0, 5, 2), - (13, 305, 148, 1088, 18446744073709551615, 0, 2, 2), - (13, 307, 915, 889, 18446744073709551615, 0, 18, 2), - (13, 302, 1088, 915, 18446744073709551615, 0, 24, 1), - (13, 303, 915, 889, 18446744073709551615, 1, 30, 1), - (13, 304, 889, 148, 18446744073709551615, 1, 4, 1), - (13, 299, 915, 889, 18446744073709551615, 1, 30, 1), - (13, 300, 889, 148, 18446744073709551615, 1, 4, 1), - (13, 284, 9, 1147, 18446744073709551615, 0, 1, 1), - (13, 285, 1147, 886, 18446744073709551615, 3, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 3, 12, 1), - (13, 287, 1088, 915, 18446744073709551615, 1, 10, 1), - (13, 288, 915, 889, 18446744073709551615, 1, 10, 1), - (13, 277, 9, 1147, 18446744073709551615, 1, 2, 1), - (13, 278, 1147, 886, 18446744073709551615, 3, 6, 1), - (13, 279, 886, 1088, 18446744073709551615, 3, 6, 1), - (13, 280, 1088, 915, 18446744073709551615, 1, 4, 1), - (13, 281, 915, 889, 18446744073709551615, 1, 4, 1), - (13, 282, 889, 148, 18446744073709551615, 1, 4, 1), - (13, 280, 1025, 148, 18446744073709551615, 0, 2, 2), - (13, 283, 1025, 889, 18446744073709551615, 0, 1, 2), - (13, 285, 1025, 889, 18446744073709551615, 0, 1, 2), - (13, 303, 1025, 889, 18446744073709551615, 0, 1, 2), - (13, 307, 1025, 889, 18446744073709551615, 0, 1, 2), - (13, 1024, 11, 1097, 18446744073709551615, 2, 255, 2), - (13, 0, 1025, 1086, 18446744073709551615, 0, 4, 1), - (13, 283, 148, 793, 18446744073709551615, 0, 1, 2), - (13, 284, 793, 1147, 18446744073709551615, 0, 1, 2), - (13, 303, 915, 889, 18446744073709551615, 2, 30, 2), - (13, 304, 889, 148, 18446744073709551615, 2, 4, 2), - (13, 305, 148, 1088, 18446744073709551615, 1, 2, 2), - (13, 306, 1088, 915, 18446744073709551615, 1, 20, 2), - (13, 302, 1088, 915, 18446744073709551615, 1, 24, 1), - (13, 303, 915, 889, 18446744073709551615, 3, 30, 1), - (13, 304, 889, 148, 18446744073709551615, 3, 4, 1), - (13, 300, 889, 148, 18446744073709551615, 3, 4, 1), - (13, 284, 1141, 1147, 18446744073709551615, 1, 2, 1), - (13, 285, 1147, 886, 18446744073709551615, 5, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 5, 12, 1), - (13, 287, 1088, 915, 18446744073709551615, 3, 10, 1), - (13, 288, 915, 889, 18446744073709551615, 3, 10, 1), - (13, 278, 1147, 886, 18446744073709551615, 5, 6, 1), - (13, 279, 886, 1088, 18446744073709551615, 5, 6, 1), - (13, 280, 1088, 915, 18446744073709551615, 3, 4, 1), - (13, 281, 915, 889, 18446744073709551615, 3, 4, 1), - (13, 282, 889, 148, 18446744073709551615, 3, 4, 1), - (13, 283, 1025, 146, 18446744073709551615, 0, 1, 2), - (13, 284, 1025, 148, 18446744073709551615, 1, 2, 2), - (13, 286, 1025, 148, 18446744073709551615, 1, 2, 2), - (13, 304, 1025, 148, 18446744073709551615, 1, 2, 2), - (13, 306, 1025, 148, 18446744073709551615, 1, 2, 2), - (13, 307, 1025, 146, 18446744073709551615, 0, 1, 2), - (13, 1024, 1145, 1087, 18446744073709551615, 1, 253, 2), - (13, 1024, 13, 1149, 18446744073709551615, 1, 253, 2), - (13, 0, 1025, 1086, 18446744073709551615, 1, 4, 1), - (13, 280, 1025, 1147, 18446744073709551615, 0, 2, 2), - (13, 283, 1088, 915, 18446744073709551615, 0, 10, 2), - (13, 284, 915, 143, 18446744073709551615, 0, 1, 2), - (13, 286, 793, 1025, 18446744073709551615, 0, 2, 2), - (13, 304, 886, 1088, 18446744073709551615, 1, 15, 2), - (13, 305, 1088, 915, 18446744073709551615, 0, 17, 2), - (13, 303, 1147, 886, 18446744073709551615, 0, 7, 1), - (13, 304, 886, 1088, 18446744073709551615, 2, 15, 1), - (13, 305, 1088, 915, 18446744073709551615, 1, 17, 1), - (13, 301, 1088, 915, 18446744073709551615, 1, 24, 1), - (13, 285, 10, 793, 18446744073709551615, 2, 6, 1), - (13, 286, 793, 1025, 18446744073709551615, 1, 2, 1), - (13, 287, 1025, 1147, 18446744073709551615, 2, 3, 1), - (13, 288, 1147, 886, 18446744073709551615, 1, 8, 1), - (13, 279, 793, 1025, 18446744073709551615, 1, 2, 1), - (13, 280, 1025, 1147, 18446744073709551615, 1, 2, 1), - (13, 281, 1147, 886, 18446744073709551615, 1, 7, 1), - (13, 282, 886, 1088, 18446744073709551615, 1, 10, 1), - (13, 283, 1088, 915, 18446744073709551615, 1, 10, 1), - (13, 282, 1139, 1141, 18446744073709551615, 0, 2, 2), - (13, 286, 1141, 9, 18446744073709551615, 4, 5, 2), - (13, 304, 1150, 10, 18446744073709551615, 0, 1, 2), - (13, 304, 143, 10, 18446744073709551615, 0, 1, 2), - (13, 281, 12, 143, 18446744073709551615, 0, 3, 2), - (13, 282, 143, 1150, 18446744073709551615, 0, 1, 2), - (13, 1024, 1145, 1087, 18446744073709551615, 2, 253, 2), - (13, 1024, 13, 1149, 18446744073709551615, 2, 253, 2), - (13, 0, 1025, 1137, 18446744073709551615, 0, 1, 1), - (13, 281, 923, 1147, 18446744073709551615, 0, 5, 2), - (13, 303, 915, 889, 18446744073709551615, 4, 30, 2), - (13, 304, 889, 146, 18446744073709551615, 0, 30, 2), - (13, 306, 886, 1088, 18446744073709551615, 0, 11, 2), - (13, 302, 1088, 915, 18446744073709551615, 3, 24, 1), - (13, 303, 915, 889, 18446744073709551615, 5, 30, 1), - (13, 304, 889, 146, 18446744073709551615, 1, 30, 1), - (13, 288, 923, 1147, 18446744073709551615, 0, 2, 1), - (13, 280, 793, 923, 18446744073709551615, 0, 5, 1), - (13, 281, 923, 1147, 18446744073709551615, 1, 5, 1), - (13, 282, 1147, 886, 18446744073709551615, 1, 9, 1), - (13, 283, 886, 1088, 18446744073709551615, 1, 12, 1), - (13, 284, 1088, 915, 18446744073709551615, 1, 12, 1), - (13, 285, 915, 889, 18446744073709551615, 1, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 1, 12, 1), - (13, 283, 1151, 1086, 18446744073709551615, 0, 1, 2), - (13, 285, 916, 1151, 18446744073709551615, 0, 1, 2), - (13, 307, 793, 1139, 18446744073709551615, 0, 1, 2), - (13, 304, 1139, 1025, 18446744073709551615, 0, 1, 2), - (13, 305, 1025, 10, 18446744073709551615, 1, 2, 2), - (13, 285, 1139, 1141, 18446744073709551615, 1, 2, 2), - (13, 281, 12, 1139, 18446744073709551615, 1, 2, 2), - (13, 1024, 13, 1149, 18446744073709551615, 3, 253, 2), - (13, 0, 1025, 17, 18446744073709551615, 0, 2, 1), - (13, 281, 10, 923, 18446744073709551615, 0, 1, 2), - (13, 282, 923, 1147, 18446744073709551615, 0, 5, 2), - (13, 283, 1147, 886, 18446744073709551615, 0, 11, 2), - (13, 284, 886, 1088, 18446744073709551615, 0, 15, 2), - (13, 286, 915, 889, 18446744073709551615, 0, 16, 2), - (13, 303, 1088, 915, 18446744073709551615, 0, 25, 2), - (13, 307, 886, 1088, 18446744073709551615, 1, 14, 2), - (13, 302, 886, 1088, 18446744073709551615, 0, 15, 1), - (13, 303, 1088, 915, 18446744073709551615, 1, 25, 1), - (13, 304, 915, 889, 18446744073709551615, 1, 32, 1), - (13, 305, 889, 146, 18446744073709551615, 1, 32, 1), - (13, 281, 793, 923, 18446744073709551615, 0, 4, 1), - (13, 282, 923, 1147, 18446744073709551615, 1, 5, 1), - (13, 283, 1147, 886, 18446744073709551615, 1, 11, 1), - (13, 284, 886, 1088, 18446744073709551615, 1, 15, 1), - (13, 285, 1088, 915, 18446744073709551615, 1, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 1, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 1, 16, 1), - (13, 284, 150, 9, 18446744073709551615, 0, 1, 2), - (13, 285, 9, 1150, 18446744073709551615, 0, 1, 2), - (13, 305, 916, 925, 18446744073709551615, 0, 6, 2), - (13, 305, 916, 925, 18446744073709551615, 1, 6, 2), - (13, 284, 12, 1025, 18446744073709551615, 0, 1, 2), - (13, 285, 1025, 1151, 18446744073709551615, 0, 1, 2), - (13, 282, 1025, 1151, 18446744073709551615, 0, 1, 2), - (13, 1028, 887, 1137, 18446744073709551615, 1, 252, 2), - (13, 1024, 887, 1137, 18446744073709551615, 1, 250, 2), - (13, 0, 1025, 17, 18446744073709551615, 1, 2, 1), - (13, 283, 1147, 886, 18446744073709551615, 2, 11, 2), - (13, 285, 1088, 915, 18446744073709551615, 2, 16, 2), - (13, 286, 915, 889, 18446744073709551615, 2, 16, 2), - (13, 287, 889, 146, 18446744073709551615, 2, 16, 2), - (13, 304, 915, 889, 18446744073709551615, 2, 32, 1), - (13, 305, 889, 146, 18446744073709551615, 3, 32, 1), - (13, 282, 923, 1147, 18446744073709551615, 2, 5, 1), - (13, 283, 1147, 886, 18446744073709551615, 3, 11, 1), - (13, 284, 886, 1088, 18446744073709551615, 3, 15, 1), - (13, 285, 1088, 915, 18446744073709551615, 3, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 3, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 3, 16, 1), - (13, 285, 1132, 1141, 18446744073709551615, 0, 3, 2), - (13, 286, 1141, 1139, 18446744073709551615, 0, 1, 2), - (13, 287, 1139, 12, 18446744073709551615, 0, 1, 2), - (13, 306, 916, 925, 18446744073709551615, 0, 10, 2), - (13, 307, 925, 1150, 18446744073709551615, 0, 1, 2), - (13, 308, 1150, 9, 18446744073709551615, 0, 1, 2), - (13, 286, 1025, 1139, 18446744073709551615, 0, 1, 2), - (13, 0, 1025, 1134, 18446744073709551615, 0, 1, 1), - (13, 285, 886, 1088, 18446744073709551615, 0, 10, 2), - (13, 286, 1088, 915, 18446744073709551615, 0, 10, 2), - (13, 306, 889, 146, 18446744073709551615, 0, 27, 2), - (13, 307, 146, 915, 18446744073709551615, 0, 5, 2), - (13, 305, 915, 889, 18446744073709551615, 0, 29, 1), - (13, 306, 889, 146, 18446744073709551615, 1, 27, 1), - (13, 283, 923, 1147, 18446744073709551615, 0, 2, 1), - (13, 284, 1147, 886, 18446744073709551615, 1, 7, 1), - (13, 285, 886, 1088, 18446744073709551615, 1, 10, 1), - (13, 286, 1088, 915, 18446744073709551615, 1, 10, 1), - (13, 287, 915, 889, 18446744073709551615, 1, 10, 1), - (13, 288, 889, 146, 18446744073709551615, 1, 10, 1), - (13, 281, 889, 146, 18446744073709551615, 1, 2, 1), - (13, 284, 150, 143, 18446744073709551615, 0, 1, 2), - (13, 285, 143, 1151, 18446744073709551615, 0, 1, 2), - (13, 286, 1151, 924, 18446744073709551615, 0, 1, 2), - (13, 306, 9, 916, 18446744073709551615, 0, 10, 2), - (13, 307, 916, 1141, 18446744073709551615, 0, 1, 2), - (13, 308, 1141, 1132, 18446744073709551615, 0, 2, 2), - (13, 305, 1132, 9, 18446744073709551615, 1, 2, 2), - (13, 306, 9, 916, 18446744073709551615, 1, 10, 2), - (13, 284, 12, 1141, 18446744073709551615, 2, 3, 2), - (13, 285, 1141, 1025, 18446744073709551615, 0, 1, 2), - (13, 286, 1025, 924, 18446744073709551615, 0, 1, 2), - (13, 17, 113, 1132, 18446744073709551615, 0, 3, 2), - (13, 1028, 113, 17, 18446744073709551615, 1, 250, 2), - (13, 0, 1025, 27, 18446744073709551615, 0, 1, 1), - (13, 284, 1147, 1088, 18446744073709551615, 0, 1, 2), - (13, 285, 1088, 915, 18446744073709551615, 4, 16, 2), - (13, 287, 889, 146, 18446744073709551615, 4, 16, 2), - (13, 306, 889, 146, 18446744073709551615, 2, 27, 2), - (13, 304, 148, 922, 18446744073709551615, 1, 6, 1), - (13, 284, 886, 1088, 18446744073709551615, 4, 15, 1), - (13, 285, 1088, 915, 18446744073709551615, 5, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 5, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 5, 16, 1), - (13, 288, 146, 148, 18446744073709551615, 1, 8, 1), - (13, 282, 148, 922, 18446744073709551615, 1, 2, 1), - (13, 285, 1150, 1151, 18446744073709551615, 0, 1, 2), - (13, 307, 925, 1132, 18446744073709551615, 0, 1, 2), - (13, 308, 1132, 9, 18446744073709551615, 0, 1, 2), - (13, 306, 916, 925, 18446744073709551615, 3, 10, 2), - (13, 285, 1132, 1025, 18446744073709551615, 0, 1, 2), - (13, 286, 1025, 143, 18446744073709551615, 0, 1, 2), - (13, 1134, 885, 916, 18446744073709551615, 3, 5, 2), - (13, 1028, 885, 1134, 18446744073709551615, 1, 249, 2), - (13, 0, 1025, 150, 18446744073709551615, 0, 1, 1), - (13, 284, 793, 923, 18446744073709551615, 0, 5, 2), - (13, 286, 1147, 886, 18446744073709551615, 0, 5, 2), - (13, 307, 915, 886, 18446744073709551615, 0, 4, 2), - (13, 305, 886, 1088, 18446744073709551615, 0, 8, 1), - (13, 306, 1088, 915, 18446744073709551615, 3, 20, 1), - (13, 283, 10, 793, 18446744073709551615, 0, 4, 1), - (13, 284, 793, 923, 18446744073709551615, 1, 5, 1), - (13, 285, 923, 1147, 18446744073709551615, 1, 2, 1), - (13, 286, 1147, 886, 18446744073709551615, 1, 5, 1), - (13, 287, 886, 1088, 18446744073709551615, 1, 9, 1), - (13, 288, 1088, 915, 18446744073709551615, 1, 10, 1), - (13, 287, 1100, 143, 18446744073709551615, 0, 1, 2), - (13, 307, 1150, 12, 18446744073709551615, 0, 1, 2), - (13, 284, 143, 12, 18446744073709551615, 0, 1, 2), - (13, 1028, 894, 27, 18446744073709551615, 1, 248, 2), - (13, 1024, 894, 27, 18446744073709551615, 1, 246, 2), - (13, 0, 1025, 110, 18446744073709551615, 0, 1, 1), - (13, 305, 915, 889, 18446744073709551615, 2, 29, 1), - (13, 306, 889, 146, 18446744073709551615, 4, 27, 1), - (13, 286, 923, 1147, 18446744073709551615, 0, 1, 1), - (13, 287, 1147, 886, 18446744073709551615, 3, 7, 1), - (13, 288, 886, 1088, 18446744073709551615, 1, 13, 1), - (13, 283, 915, 889, 18446744073709551615, 1, 6, 1), - (13, 284, 889, 146, 18446744073709551615, 1, 6, 1), - (13, 286, 150, 927, 18446744073709551615, 0, 1, 2), - (13, 286, 924, 927, 18446744073709551615, 0, 2, 2), - (13, 1028, 1086, 110, 18446744073709551615, 0, 246, 2), - (13, 1024, 1086, 110, 18446744073709551615, 0, 244, 2), - (13, 0, 1025, 104, 18446744073709551615, 0, 1, 1), - (13, 284, 915, 889, 18446744073709551615, 0, 8, 2), - (13, 286, 146, 793, 18446744073709551615, 0, 1, 2), - (13, 306, 1088, 915, 18446744073709551615, 4, 20, 2), - (13, 307, 915, 889, 18446744073709551615, 3, 18, 2), - (13, 287, 923, 1147, 18446744073709551615, 0, 1, 1), - (13, 288, 1147, 886, 18446744073709551615, 3, 8, 1), - (13, 283, 1088, 915, 18446744073709551615, 3, 10, 1), - (13, 284, 915, 889, 18446744073709551615, 1, 8, 1), - (13, 285, 889, 146, 18446744073709551615, 1, 8, 1), - (13, 286, 1142, 1100, 18446744073709551615, 0, 1, 2), - (13, 287, 1100, 1132, 18446744073709551615, 0, 1, 2), - (13, 308, 150, 143, 18446744073709551615, 0, 1, 2), - (13, 286, 1141, 1100, 18446744073709551615, 1, 3, 2), - (13, 1028, 1086, 110, 18446744073709551615, 1, 246, 2), - (13, 1024, 1086, 110, 18446744073709551615, 1, 244, 2), - (13, 0, 1025, 882, 18446744073709551615, 0, 1, 1), - (13, 284, 1088, 915, 18446744073709551615, 2, 12, 2), - (13, 285, 915, 889, 18446744073709551615, 2, 12, 2), - (13, 286, 889, 146, 18446744073709551615, 2, 12, 2), - (13, 287, 146, 793, 18446744073709551615, 1, 2, 2), - (13, 307, 1088, 915, 18446744073709551615, 1, 14, 2), - (13, 288, 923, 1147, 18446744073709551615, 1, 2, 1), - (13, 284, 1088, 915, 18446744073709551615, 3, 12, 1), - (13, 285, 915, 889, 18446744073709551615, 3, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 3, 12, 1), - (13, 287, 927, 150, 18446744073709551615, 0, 1, 2), - (13, 308, 1142, 12, 18446744073709551615, 0, 1, 2), - (13, 1028, 795, 882, 18446744073709551615, 0, 244, 2), - (13, 1024, 795, 882, 18446744073709551615, 0, 242, 2), - (13, 0, 1025, 1098, 18446744073709551615, 0, 1, 1), - (13, 285, 1088, 915, 18446744073709551615, 6, 16, 2), - (13, 307, 915, 889, 18446744073709551615, 4, 18, 2), - (13, 284, 886, 1088, 18446744073709551615, 6, 15, 1), - (13, 285, 1088, 915, 18446744073709551615, 7, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 7, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 7, 16, 1), - (13, 1028, 1148, 1098, 18446744073709551615, 0, 243, 2), - (13, 1024, 1148, 1098, 18446744073709551615, 0, 241, 2), - (13, 0, 1025, 107, 18446744073709551615, 0, 1, 1), - (13, 285, 915, 889, 18446744073709551615, 4, 12, 2), - (13, 286, 889, 146, 18446744073709551615, 4, 12, 2), - (13, 307, 146, 889, 18446744073709551615, 0, 4, 2), - (13, 288, 1147, 886, 18446744073709551615, 4, 8, 1), - (13, 284, 1088, 915, 18446744073709551615, 5, 12, 1), - (13, 285, 915, 889, 18446744073709551615, 5, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 5, 12, 1), - (13, 286, 150, 786, 18446744073709551615, 0, 2, 2), - (13, 1028, 790, 107, 18446744073709551615, 0, 242, 2), - (13, 1024, 790, 107, 18446744073709551615, 0, 240, 2), - (13, 0, 1025, 879, 18446744073709551615, 0, 1, 1), - (13, 307, 915, 889, 18446744073709551615, 5, 18, 2), - (13, 284, 886, 1088, 18446744073709551615, 8, 15, 1), - (13, 285, 1088, 915, 18446744073709551615, 9, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 9, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 9, 16, 1), - (13, 1028, 876, 879, 18446744073709551615, 0, 241, 2), - (13, 1024, 876, 879, 18446744073709551615, 0, 239, 2), - (13, 0, 1025, 1099, 18446744073709551615, 0, 1, 1), - (13, 285, 886, 1088, 18446744073709551615, 2, 10, 2), - (13, 285, 886, 1088, 18446744073709551615, 3, 10, 1), - (13, 286, 1088, 915, 18446744073709551615, 3, 10, 1), - (13, 287, 915, 889, 18446744073709551615, 3, 10, 1), - (13, 288, 889, 146, 18446744073709551615, 3, 10, 1), - (13, 286, 150, 786, 18446744073709551615, 1, 2, 2), - (13, 1028, 789, 1099, 18446744073709551615, 0, 240, 2), - (13, 1024, 789, 1099, 18446744073709551615, 0, 238, 2), - (13, 0, 1025, 20, 18446744073709551615, 0, 1, 1), - (13, 286, 922, 1147, 18446744073709551615, 0, 1, 2), - (13, 287, 1147, 1088, 18446744073709551615, 0, 1, 2), - (13, 287, 886, 1088, 18446744073709551615, 2, 9, 1), - (13, 288, 1088, 915, 18446744073709551615, 3, 10, 1), - (13, 285, 148, 922, 18446744073709551615, 1, 2, 1), - (13, 286, 143, 12, 18446744073709551615, 0, 2, 2), - (13, 791, 18, 1147, 18446744073709551615, 0, 4, 1), - (13, 287, 922, 1147, 18446744073709551615, 0, 2, 2), - (13, 288, 886, 1088, 18446744073709551615, 2, 13, 1), - (13, 285, 146, 148, 18446744073709551615, 1, 4, 1), - (13, 286, 148, 922, 18446744073709551615, 1, 4, 1), - (13, 786, 20, 1147, 18446744073709551615, 0, 4, 2), - (13, 150, 23, 886, 18446744073709551615, 0, 4, 2), - (13, 1028, 23, 150, 18446744073709551615, 1, 239, 2), - (13, 1024, 23, 150, 18446744073709551615, 1, 237, 2), - (13, 286, 146, 148, 18446744073709551615, 0, 6, 2), - (13, 287, 148, 1147, 18446744073709551615, 0, 3, 2), - (13, 288, 886, 1088, 18446744073709551615, 3, 13, 1), - (13, 285, 889, 146, 18446744073709551615, 3, 8, 1), - (13, 286, 146, 148, 18446744073709551615, 1, 6, 1), - (13, 287, 12, 927, 18446744073709551615, 0, 1, 2), - (13, 150, 23, 1147, 18446744073709551615, 0, 4, 2), - (13, 101, 926, 886, 18446744073709551615, 0, 4, 2), - (13, 1028, 926, 101, 18446744073709551615, 1, 238, 2), - (13, 286, 148, 922, 18446744073709551615, 2, 4, 2), - (13, 288, 886, 1088, 18446744073709551615, 4, 13, 1), - (13, 285, 146, 148, 18446744073709551615, 3, 4, 1), - (13, 286, 148, 922, 18446744073709551615, 3, 4, 1), - (13, 287, 787, 924, 18446744073709551615, 0, 1, 2), - (13, 873, 1100, 915, 18446744073709551615, 0, 3, 2), - (13, 1028, 1100, 873, 18446744073709551615, 1, 237, 2), - (13, 287, 148, 1147, 18446744073709551615, 1, 3, 2), - (13, 288, 886, 1088, 18446744073709551615, 5, 13, 1), - (13, 286, 146, 148, 18446744073709551615, 3, 6, 1), - (13, 287, 788, 1132, 18446744073709551615, 0, 1, 2), - (13, 1101, 798, 915, 18446744073709551615, 0, 3, 2), - (13, 1028, 1085, 98, 18446744073709551615, 0, 235, 2), - (13, 1028, 798, 1101, 18446744073709551615, 1, 236, 2), - (13, 1024, 1085, 98, 18446744073709551615, 0, 233, 2), - (13, 286, 889, 146, 18446744073709551615, 6, 12, 2), - (13, 287, 146, 148, 18446744073709551615, 0, 6, 2), - (13, 285, 915, 889, 18446744073709551615, 7, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 7, 12, 1), - (13, 287, 146, 148, 18446744073709551615, 1, 6, 1), - (13, 286, 928, 787, 18446744073709551615, 1, 2, 2), - (13, 98, 1085, 915, 18446744073709551615, 0, 4, 2), - (13, 1028, 1085, 98, 18446744073709551615, 1, 235, 2), - (13, 288, 886, 1088, 18446744073709551615, 6, 13, 1), - (13, 285, 889, 146, 18446744073709551615, 7, 8, 1), - (13, 286, 146, 148, 18446744073709551615, 5, 6, 1), - (13, 870, 797, 146, 18446744073709551615, 0, 2, 2), - (13, 1028, 801, 1102, 18446744073709551615, 0, 233, 2), - (13, 1028, 797, 870, 18446744073709551615, 1, 234, 2), - (13, 1024, 801, 1102, 18446744073709551615, 0, 231, 2), - (13, 285, 915, 889, 18446744073709551615, 9, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 9, 12, 1), - (13, 287, 146, 148, 18446744073709551615, 3, 6, 1), - (13, 1102, 801, 146, 18446744073709551615, 0, 3, 2), - (13, 1028, 934, 95, 18446744073709551615, 0, 232, 2), - (13, 1028, 801, 1102, 18446744073709551615, 1, 233, 2), - (13, 1024, 934, 95, 18446744073709551615, 0, 230, 2), - (13, 286, 915, 889, 18446744073709551615, 10, 16, 2), - (13, 286, 915, 889, 18446744073709551615, 11, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 11, 16, 1), - (13, 288, 146, 148, 18446744073709551615, 3, 8, 1), - (13, 287, 143, 927, 18446744073709551615, 0, 1, 2), - (13, 95, 934, 146, 18446744073709551615, 0, 3, 2), - (13, 1028, 934, 95, 18446744073709551615, 1, 232, 2), - (13, 286, 889, 146, 18446744073709551615, 10, 12, 2), - (13, 287, 146, 148, 18446744073709551615, 4, 6, 2), - (13, 285, 915, 889, 18446744073709551615, 11, 12, 1), - (13, 286, 889, 146, 18446744073709551615, 11, 12, 1), - (13, 287, 146, 148, 18446744073709551615, 5, 6, 1), - (13, 867, 800, 922, 18446744073709551615, 0, 2, 2), - (13, 1028, 804, 1103, 18446744073709551615, 0, 230, 2), - (13, 1028, 800, 867, 18446744073709551615, 1, 231, 2), - (13, 1024, 804, 1103, 18446744073709551615, 0, 228, 2), - (13, 287, 889, 146, 18446744073709551615, 12, 16, 2), - (13, 285, 1088, 915, 18446744073709551615, 13, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 13, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 13, 16, 1), - (13, 288, 146, 148, 18446744073709551615, 5, 8, 1), - (13, 1103, 804, 922, 18446744073709551615, 0, 2, 2), - (13, 1028, 931, 92, 18446744073709551615, 0, 229, 2), - (13, 1028, 804, 1103, 18446744073709551615, 1, 230, 2), - (13, 1024, 931, 92, 18446744073709551615, 0, 227, 2), - (13, 286, 1088, 915, 18446744073709551615, 4, 10, 2), - (13, 285, 886, 1088, 18446744073709551615, 5, 10, 1), - (13, 286, 1088, 915, 18446744073709551615, 5, 10, 1), - (13, 287, 915, 889, 18446744073709551615, 5, 10, 1), - (13, 288, 889, 146, 18446744073709551615, 5, 10, 1), - (13, 92, 931, 922, 18446744073709551615, 0, 3, 2), - (13, 1028, 803, 864, 18446744073709551615, 0, 228, 2), - (13, 1028, 931, 92, 18446744073709551615, 1, 229, 2), - (13, 1024, 803, 864, 18446744073709551615, 0, 226, 2), - (13, 287, 889, 146, 18446744073709551615, 14, 16, 2), - (13, 285, 1088, 915, 18446744073709551615, 15, 16, 1), - (13, 286, 915, 889, 18446744073709551615, 15, 16, 1), - (13, 287, 889, 146, 18446744073709551615, 15, 16, 1), - (13, 288, 146, 148, 18446744073709551615, 7, 8, 1), - (13, 286, 796, 1132, 18446744073709551615, 0, 2, 2), - (13, 864, 803, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 807, 1104, 18446744073709551615, 0, 227, 2), - (13, 1028, 803, 864, 18446744073709551615, 1, 228, 2), - (13, 1024, 807, 1104, 18446744073709551615, 0, 225, 2), - (13, 285, 886, 1088, 18446744073709551615, 7, 10, 1), - (13, 286, 1088, 915, 18446744073709551615, 7, 10, 1), - (13, 287, 915, 889, 18446744073709551615, 7, 10, 1), - (13, 288, 889, 146, 18446744073709551615, 7, 10, 1), - (13, 1104, 807, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 930, 89, 18446744073709551615, 0, 226, 2), - (13, 1028, 807, 1104, 18446744073709551615, 1, 227, 2), - (13, 1024, 930, 89, 18446744073709551615, 0, 224, 2), - (13, 286, 886, 1088, 18446744073709551615, 6, 12, 2), - (13, 287, 1088, 915, 18446744073709551615, 4, 10, 2), - (13, 285, 1147, 886, 18446744073709551615, 6, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 7, 12, 1), - (13, 287, 1088, 915, 18446744073709551615, 5, 10, 1), - (13, 288, 915, 889, 18446744073709551615, 5, 10, 1), - (13, 287, 1132, 927, 18446744073709551615, 0, 1, 2), - (13, 89, 930, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 806, 861, 18446744073709551615, 0, 225, 2), - (13, 1028, 930, 89, 18446744073709551615, 1, 226, 2), - (13, 1024, 806, 861, 18446744073709551615, 0, 223, 2), - (13, 286, 1088, 915, 18446744073709551615, 8, 10, 2), - (13, 287, 915, 889, 18446744073709551615, 8, 10, 2), - (13, 285, 886, 1088, 18446744073709551615, 9, 10, 1), - (13, 286, 1088, 915, 18446744073709551615, 9, 10, 1), - (13, 287, 915, 889, 18446744073709551615, 9, 10, 1), - (13, 288, 889, 146, 18446744073709551615, 9, 10, 1), - (13, 861, 806, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 810, 1105, 18446744073709551615, 0, 224, 2), - (13, 1028, 806, 861, 18446744073709551615, 1, 225, 2), - (13, 1024, 810, 1105, 18446744073709551615, 0, 222, 2), - (13, 286, 886, 1088, 18446744073709551615, 8, 12, 2), - (13, 285, 1147, 886, 18446744073709551615, 7, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 9, 12, 1), - (13, 287, 1088, 915, 18446744073709551615, 7, 10, 1), - (13, 288, 915, 889, 18446744073709551615, 7, 10, 1), - (13, 1105, 810, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 163, 86, 18446744073709551615, 0, 223, 2), - (13, 1028, 810, 1105, 18446744073709551615, 1, 224, 2), - (13, 1024, 163, 86, 18446744073709551615, 0, 221, 2), - (13, 287, 886, 1088, 18446744073709551615, 3, 9, 2), - (13, 286, 1147, 886, 18446744073709551615, 2, 5, 1), - (13, 287, 886, 1088, 18446744073709551615, 4, 9, 1), - (13, 288, 1088, 915, 18446744073709551615, 5, 10, 1), - (13, 86, 163, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 809, 858, 18446744073709551615, 0, 222, 2), - (13, 1024, 809, 858, 18446744073709551615, 0, 220, 2), - (13, 286, 886, 1088, 18446744073709551615, 10, 12, 2), - (13, 285, 1147, 886, 18446744073709551615, 8, 9, 1), - (13, 286, 886, 1088, 18446744073709551615, 11, 12, 1), - (13, 287, 1088, 915, 18446744073709551615, 9, 10, 1), - (13, 288, 915, 889, 18446744073709551615, 9, 10, 1), - (13, 858, 809, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 813, 1106, 18446744073709551615, 0, 221, 2), - (13, 1024, 813, 1106, 18446744073709551615, 0, 219, 2), - (13, 286, 923, 886, 18446744073709551615, 1, 3, 2), - (13, 286, 1147, 886, 18446744073709551615, 3, 5, 1), - (13, 287, 886, 1088, 18446744073709551615, 6, 9, 1), - (13, 288, 1088, 915, 18446744073709551615, 7, 10, 1), - (13, 1028, 932, 83, 18446744073709551615, 0, 220, 2), - (13, 287, 1147, 886, 18446744073709551615, 4, 7, 1), - (13, 288, 886, 1088, 18446744073709551615, 8, 13, 1), - (13, 1028, 812, 855, 18446744073709551615, 0, 219, 2), - (13, 286, 923, 886, 18446744073709551615, 2, 3, 2), - (13, 286, 1147, 886, 18446744073709551615, 4, 5, 1), - (13, 287, 886, 1088, 18446744073709551615, 8, 9, 1), - (13, 288, 1088, 915, 18446744073709551615, 9, 10, 1), - (13, 1028, 816, 1107, 18446744073709551615, 0, 218, 2), - (13, 1028, 812, 855, 18446744073709551615, 1, 219, 2), - (13, 286, 793, 923, 18446744073709551615, 1, 3, 2), - (13, 287, 923, 886, 18446744073709551615, 1, 3, 2), - (13, 287, 1147, 886, 18446744073709551615, 5, 7, 1), - (13, 288, 886, 1088, 18446744073709551615, 10, 13, 1), - (13, 1028, 940, 80, 18446744073709551615, 0, 217, 2), - (13, 288, 1147, 886, 18446744073709551615, 5, 8, 1), - (13, 1028, 815, 852, 18446744073709551615, 0, 216, 2), - (13, 286, 793, 923, 18446744073709551615, 2, 3, 2), - (13, 287, 1147, 886, 18446744073709551615, 6, 7, 1), - (13, 288, 886, 1088, 18446744073709551615, 12, 13, 1), - (13, 287, 802, 814, 18446744073709551615, 0, 1, 2), - (13, 286, 808, 802, 18446744073709551615, 0, 2, 2), - (13, 1028, 819, 1108, 18446744073709551615, 0, 215, 2), - (13, 288, 1147, 886, 18446744073709551615, 6, 8, 1), - (13, 1108, 819, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 171, 77, 18446744073709551615, 0, 214, 2), - (13, 1028, 818, 849, 18446744073709551615, 0, 213, 2), - (13, 288, 1147, 886, 18446744073709551615, 7, 8, 1), - (13, 849, 818, 1153, 18446744073709551615, 1, 2, 2), - (13, 1028, 822, 1109, 18446744073709551615, 0, 212, 2), - (13, 1024, 822, 1109, 18446744073709551615, 0, 210, 2), - (13, 287, 10, 793, 18446744073709551615, 1, 3, 2), - (13, 1028, 166, 74, 18446744073709551615, 0, 211, 2), - (13, 1024, 166, 74, 18446744073709551615, 0, 209, 2), - (13, 286, 916, 925, 18446744073709551615, 0, 3, 2), - (13, 287, 925, 10, 18446744073709551615, 0, 3, 2), - (13, 1028, 821, 846, 18446744073709551615, 0, 210, 2), - (13, 1024, 821, 846, 18446744073709551615, 0, 208, 2), - (13, 1028, 825, 1110, 18446744073709551615, 0, 209, 2), - (13, 286, 916, 925, 18446744073709551615, 1, 3, 2), - (13, 287, 802, 817, 18446744073709551615, 0, 1, 2), - (13, 1028, 1084, 71, 18446744073709551615, 0, 208, 2), - (13, 1024, 1084, 71, 18446744073709551615, 0, 206, 2), - (13, 286, 9, 916, 18446744073709551615, 0, 3, 2), - (13, 286, 814, 808, 18446744073709551615, 1, 2, 2), - (13, 1028, 824, 843, 18446744073709551615, 0, 207, 2), - (13, 1024, 824, 843, 18446744073709551615, 0, 205, 2), - (13, 286, 916, 925, 18446744073709551615, 2, 3, 2), - (13, 287, 925, 10, 18446744073709551615, 2, 3, 2), - (13, 1028, 828, 1111, 18446744073709551615, 0, 206, 2), - (13, 286, 9, 916, 18446744073709551615, 1, 3, 2), - (13, 287, 916, 925, 18446744073709551615, 1, 3, 2), - (13, 287, 805, 820, 18446744073709551615, 0, 1, 2), - (13, 1028, 939, 68, 18446744073709551615, 0, 205, 2), - (13, 1024, 939, 68, 18446744073709551615, 0, 203, 2), - (13, 1028, 827, 838, 18446744073709551615, 0, 204, 2), - (13, 1028, 831, 1112, 18446744073709551615, 0, 203, 2), - (13, 287, 9, 916, 18446744073709551615, 1, 3, 2), - (13, 1028, 938, 65, 18446744073709551615, 0, 202, 2), - (13, 1024, 938, 65, 18446744073709551615, 0, 200, 2), - (13, 287, 1150, 9, 18446744073709551615, 0, 6, 2), - (13, 1028, 830, 1119, 18446744073709551615, 0, 201, 2), - (13, 287, 9, 916, 18446744073709551615, 2, 3, 2), - (13, 1028, 834, 66, 18446744073709551615, 197, 397, 2), - (13, 1028, 169, 62, 18446744073709551615, 0, 199, 2), - (13, 286, 1139, 1151, 18446744073709551615, 0, 6, 2), - (13, 287, 1151, 1150, 18446744073709551615, 0, 6, 2), - (13, 1028, 833, 1117, 18446744073709551615, 0, 198, 2), - (13, 287, 1150, 9, 18446744073709551615, 3, 6, 2), - (13, 1028, 837, 69, 18446744073709551615, 194, 391, 2), - (13, 1028, 944, 59, 18446744073709551615, 0, 196, 2), - (13, 286, 104, 1139, 18446744073709551615, 0, 6, 2), - (13, 287, 1139, 1151, 18446744073709551615, 0, 6, 2), - (13, 1028, 835, 839, 18446744073709551615, 0, 195, 2), - (13, 286, 1139, 1151, 18446744073709551615, 3, 6, 2), - (13, 287, 1151, 1150, 18446744073709551615, 3, 6, 2), - (13, 287, 1150, 9, 18446744073709551615, 5, 6, 2), - (13, 1028, 841, 72, 18446744073709551615, 0, 194, 2), - (13, 286, 104, 1139, 18446744073709551615, 1, 6, 2), - (13, 1028, 941, 60, 18446744073709551615, 0, 193, 2), - (13, 287, 104, 1139, 18446744073709551615, 0, 6, 2), - (13, 1028, 63, 842, 18446744073709551615, 0, 192, 2), - (13, 286, 104, 1139, 18446744073709551615, 3, 6, 2), - (13, 75, 844, 104, 18446744073709551615, 0, 4, 1), - (13, 1028, 844, 75, 18446744073709551615, 0, 191, 2), - (14, 1028, 75, 844, 18446744073709551615, 0, 5, 1), - (13, 286, 1142, 104, 18446744073709551615, 1, 6, 2), - (13, 57, 1081, 1142, 18446744073709551615, 0, 7, 1), - (13, 1028, 1081, 57, 18446744073709551615, 0, 190, 2), - (14, 1028, 57, 1081, 18446744073709551615, 0, 4, 1), - (13, 845, 811, 788, 18446744073709551615, 0, 6, 1), - (13, 1028, 811, 845, 18446744073709551615, 0, 189, 2), - (14, 1028, 845, 811, 18446744073709551615, 0, 4, 1), - (13, 287, 104, 1139, 18446744073709551615, 3, 6, 2), - (13, 78, 847, 1139, 18446744073709551615, 0, 6, 1), - (13, 1028, 847, 78, 18446744073709551615, 0, 188, 2), - (14, 1028, 78, 847, 18446744073709551615, 0, 4, 1), - (13, 1024, 847, 78, 18446744073709551615, 0, 186, 2), - (13, 286, 788, 1142, 18446744073709551615, 2, 7, 2), - (13, 54, 947, 104, 18446744073709551615, 0, 5, 1), - (13, 1028, 947, 54, 18446744073709551615, 0, 187, 2), - (14, 1028, 54, 947, 18446744073709551615, 0, 4, 1), - (13, 848, 56, 1142, 18446744073709551615, 0, 8, 1), - (13, 1028, 56, 848, 18446744073709551615, 0, 186, 2), - (14, 1028, 848, 56, 18446744073709551615, 0, 4, 1), - (13, 81, 850, 1151, 18446744073709551615, 0, 4, 1), - (13, 1028, 850, 81, 18446744073709551615, 0, 185, 2), - (14, 1028, 81, 850, 18446744073709551615, 0, 4, 1), - (13, 51, 175, 1139, 18446744073709551615, 0, 7, 1), - (13, 1028, 175, 51, 18446744073709551615, 0, 184, 2), - (14, 1028, 51, 175, 18446744073709551615, 0, 4, 1), - (13, 286, 787, 12, 18446744073709551615, 2, 8, 2), - (13, 287, 12, 788, 18446744073709551615, 0, 6, 2), - (13, 851, 53, 104, 18446744073709551615, 0, 7, 1), - (13, 1028, 53, 851, 18446744073709551615, 0, 183, 2), - (14, 1028, 851, 53, 18446744073709551615, 0, 4, 1), - (13, 286, 12, 788, 18446744073709551615, 4, 7, 2), - (13, 84, 853, 1150, 18446744073709551615, 0, 6, 1), - (13, 1028, 853, 84, 18446744073709551615, 0, 182, 2), - (14, 1028, 84, 853, 18446744073709551615, 0, 4, 1), - (13, 286, 787, 12, 18446744073709551615, 3, 8, 2), - (13, 48, 1080, 1151, 18446744073709551615, 0, 6, 1), - (13, 1028, 1080, 48, 18446744073709551615, 0, 181, 2), - (14, 1028, 48, 1080, 18446744073709551615, 0, 4, 1), - (13, 287, 787, 12, 18446744073709551615, 0, 6, 2), - (13, 854, 50, 1139, 18446744073709551615, 0, 6, 1), - (13, 1028, 50, 854, 18446744073709551615, 0, 180, 2), - (14, 1028, 854, 50, 18446744073709551615, 0, 4, 1), - (13, 286, 787, 12, 18446744073709551615, 5, 8, 2), - (13, 287, 12, 788, 18446744073709551615, 3, 6, 2), - (13, 87, 856, 9, 18446744073709551615, 0, 5, 1), - (13, 1028, 856, 87, 18446744073709551615, 0, 179, 2), - (14, 1028, 87, 856, 18446744073709551615, 0, 4, 1), - (13, 45, 950, 1150, 18446744073709551615, 0, 5, 1), - (13, 1028, 950, 45, 18446744073709551615, 0, 178, 2), - (14, 1028, 45, 950, 18446744073709551615, 0, 4, 1), - (13, 1024, 950, 45, 18446744073709551615, 0, 176, 2), - (13, 286, 928, 143, 18446744073709551615, 2, 8, 2), - (13, 857, 47, 1151, 18446744073709551615, 0, 6, 1), - (13, 1028, 47, 857, 18446744073709551615, 0, 177, 2), - (14, 1028, 857, 47, 18446744073709551615, 0, 4, 1), - (13, 287, 787, 12, 18446744073709551615, 3, 6, 2), - (13, 90, 859, 916, 18446744073709551615, 0, 4, 1), - (13, 1028, 859, 90, 18446744073709551615, 0, 176, 2), - (14, 1028, 90, 859, 18446744073709551615, 0, 4, 1), - (13, 287, 787, 12, 18446744073709551615, 4, 6, 2), - (13, 42, 178, 9, 18446744073709551615, 0, 5, 1), - (13, 1028, 178, 42, 18446744073709551615, 0, 175, 2), - (14, 1028, 42, 178, 18446744073709551615, 0, 4, 1), - (13, 860, 44, 1150, 18446744073709551615, 0, 4, 1), - (13, 1028, 44, 860, 18446744073709551615, 0, 174, 2), - (14, 1028, 860, 44, 18446744073709551615, 0, 4, 1), - (13, 1024, 44, 860, 18446744073709551615, 0, 172, 2), - (13, 93, 862, 925, 18446744073709551615, 0, 4, 1), - (13, 1028, 862, 93, 18446744073709551615, 0, 173, 2), - (14, 1028, 93, 862, 18446744073709551615, 0, 4, 1), - (13, 286, 1132, 928, 18446744073709551615, 3, 8, 2), - (13, 39, 1079, 916, 18446744073709551615, 0, 3, 1), - (13, 1028, 1079, 39, 18446744073709551615, 0, 172, 2), - (14, 1028, 39, 1079, 18446744073709551615, 0, 4, 1), - (13, 286, 924, 1132, 18446744073709551615, 2, 8, 2), - (13, 863, 41, 9, 18446744073709551615, 0, 3, 1), - (13, 1028, 41, 863, 18446744073709551615, 0, 171, 2), - (14, 1028, 863, 41, 18446744073709551615, 0, 4, 1), - (13, 96, 865, 10, 18446744073709551615, 0, 2, 1), - (13, 1028, 865, 96, 18446744073709551615, 0, 170, 2), - (14, 1028, 96, 865, 18446744073709551615, 0, 4, 1), - (13, 286, 924, 1132, 18446744073709551615, 3, 8, 2), - (13, 36, 953, 925, 18446744073709551615, 0, 2, 1), - (13, 1028, 953, 36, 18446744073709551615, 0, 169, 2), - (14, 1028, 36, 953, 18446744073709551615, 0, 4, 1), - (13, 286, 796, 924, 18446744073709551615, 2, 8, 2), - (13, 866, 38, 916, 18446744073709551615, 0, 3, 1), - (13, 1028, 38, 866, 18446744073709551615, 0, 168, 2), - (14, 1028, 866, 38, 18446744073709551615, 0, 4, 1), - (13, 287, 1132, 928, 18446744073709551615, 3, 6, 2), - (13, 99, 868, 793, 18446744073709551615, 0, 1, 1), - (13, 1028, 868, 99, 18446744073709551615, 0, 167, 2), - (14, 1028, 99, 868, 18446744073709551615, 0, 4, 1), - (13, 33, 181, 10, 18446744073709551615, 0, 2, 1), - (13, 1028, 181, 33, 18446744073709551615, 0, 166, 2), - (14, 1028, 33, 181, 18446744073709551615, 0, 4, 1), - (13, 869, 35, 925, 18446744073709551615, 0, 5, 1), - (13, 1028, 35, 869, 18446744073709551615, 0, 165, 2), - (14, 1028, 869, 35, 18446744073709551615, 0, 4, 1), - (13, 287, 924, 1132, 18446744073709551615, 3, 6, 2), - (13, 102, 871, 923, 18446744073709551615, 0, 1, 1), - (13, 1028, 871, 102, 18446744073709551615, 0, 164, 2), - (14, 1028, 102, 871, 18446744073709551615, 0, 3, 1), - (13, 30, 1078, 793, 18446744073709551615, 0, 4, 1), - (13, 1028, 1078, 30, 18446744073709551615, 0, 163, 2), - (14, 1028, 30, 1078, 18446744073709551615, 0, 2, 1), - (13, 1024, 1078, 30, 18446744073709551615, 0, 161, 2), - (13, 286, 802, 799, 18446744073709551615, 2, 8, 2), - (13, 872, 32, 10, 18446744073709551615, 0, 3, 1), - (13, 1028, 32, 872, 18446744073709551615, 0, 162, 2), - (14, 1028, 872, 32, 18446744073709551615, 0, 2, 1), - (13, 286, 799, 796, 18446744073709551615, 5, 8, 2), - (13, 105, 874, 1147, 18446744073709551615, 0, 2, 1), - (13, 1028, 874, 105, 18446744073709551615, 0, 161, 2), - (14, 1028, 105, 874, 18446744073709551615, 0, 1, 1), - (13, 286, 802, 799, 18446744073709551615, 3, 8, 2), - (13, 24, 956, 923, 18446744073709551615, 0, 2, 1), - (13, 1028, 956, 24, 18446744073709551615, 0, 160, 2), - (14, 1028, 24, 956, 18446744073709551615, 0, 1, 1), - (13, 286, 805, 802, 18446744073709551615, 2, 8, 2), - (13, 875, 29, 793, 18446744073709551615, 0, 4, 1), - (13, 1028, 29, 875, 18446744073709551615, 0, 159, 2), - (14, 1028, 875, 29, 18446744073709551615, 0, 2, 1), - (13, 287, 796, 924, 18446744073709551615, 5, 6, 2), - (13, 108, 877, 886, 18446744073709551615, 0, 1, 1), - (13, 1028, 877, 108, 18446744073709551615, 0, 158, 2), - (14, 1028, 108, 877, 18446744073709551615, 0, 1, 1), - (13, 21, 184, 1147, 18446744073709551615, 0, 3, 1), - (13, 1028, 184, 21, 18446744073709551615, 0, 157, 2), - (14, 1028, 21, 184, 18446744073709551615, 0, 1, 1), - (13, 286, 808, 805, 18446744073709551615, 2, 11, 2), - (13, 878, 792, 923, 18446744073709551615, 0, 3, 1), - (13, 1028, 792, 878, 18446744073709551615, 0, 156, 2), - (14, 1028, 878, 792, 18446744073709551615, 0, 2, 1), - (13, 286, 805, 802, 18446744073709551615, 5, 8, 2), - (13, 287, 802, 799, 18446744073709551615, 3, 6, 2), - (13, 111, 880, 1088, 18446744073709551615, 0, 2, 1), - (13, 1028, 880, 111, 18446744073709551615, 0, 155, 2), - (14, 1028, 111, 880, 18446744073709551615, 0, 2, 1), - (13, 286, 808, 805, 18446744073709551615, 3, 11, 2), - (13, 794, 1077, 886, 18446744073709551615, 0, 2, 1), - (13, 1028, 1077, 794, 18446744073709551615, 0, 154, 2), - (14, 1028, 794, 1077, 18446744073709551615, 0, 1, 1), - (13, 881, 25, 1147, 18446744073709551615, 0, 7, 1), - (13, 1028, 25, 881, 18446744073709551615, 0, 153, 2), - (14, 1028, 881, 25, 18446744073709551615, 0, 1, 1), - (13, 1024, 25, 881, 18446744073709551615, 0, 151, 2), - (13, 286, 808, 805, 18446744073709551615, 5, 11, 2), - (13, 114, 883, 915, 18446744073709551615, 0, 1, 1), - (13, 1028, 883, 114, 18446744073709551615, 0, 152, 2), - (14, 1028, 114, 883, 18446744073709551615, 0, 2, 1), - (13, 1024, 883, 114, 18446744073709551615, 0, 150, 2), - (13, 1113, 187, 1088, 18446744073709551615, 0, 6, 1), - (13, 1028, 187, 1113, 18446744073709551615, 0, 151, 2), - (14, 1028, 1113, 187, 18446744073709551615, 0, 1, 1), - (13, 287, 820, 808, 18446744073709551615, 0, 4, 2), - (13, 884, 1115, 886, 18446744073709551615, 0, 4, 1), - (13, 1028, 1115, 884, 18446744073709551615, 0, 150, 2), - (14, 1028, 884, 1115, 18446744073709551615, 0, 1, 1), - (13, 1024, 1115, 884, 18446744073709551615, 0, 148, 2), - (13, 286, 820, 808, 18446744073709551615, 3, 10, 2), - (13, 117, 119, 889, 18446744073709551615, 0, 5, 1), - (13, 1028, 119, 117, 18446744073709551615, 0, 149, 2), - (14, 1028, 117, 119, 18446744073709551615, 0, 2, 1), - (13, 1024, 119, 117, 18446744073709551615, 0, 147, 2), - (13, 286, 817, 820, 18446744073709551615, 1, 4, 2), - (13, 287, 820, 808, 18446744073709551615, 1, 4, 2), - (13, 1140, 778, 915, 18446744073709551615, 0, 3, 1), - (13, 1028, 778, 1140, 18446744073709551615, 0, 148, 2), - (14, 1028, 1140, 778, 18446744073709551615, 0, 5, 1), - (13, 1028, 146, 1025, 18446744073709551615, 0, 150, 2), - (13, 16, 840, 890, 18446744073709551615, 0, 2, 1), - (13, 1028, 840, 16, 18446744073709551615, 0, 147, 2), - (13, 16, 840, 890, 18446744073709551615, 1, 2, 2), - (14, 1028, 1140, 778, 18446744073709551615, 1, 5, 2), - (13, 115, 118, 146, 18446744073709551615, 0, 2, 2), - (13, 1028, 146, 1025, 18446744073709551615, 1, 150, 2), - (13, 1028, 118, 115, 18446744073709551615, 1, 147, 2), - (14, 1028, 115, 118, 18446744073709551615, 1, 3, 1), - (13, 744, 779, 756, 18446744073709551615, 0, 5, 1), - (13, 1028, 779, 744, 18446744073709551615, 0, 145, 2), - (13, 286, 817, 820, 18446744073709551615, 3, 4, 2), - (13, 287, 820, 808, 18446744073709551615, 3, 4, 2), - (13, 1116, 890, 780, 18446744073709551615, 0, 2, 2), - (13, 891, 959, 757, 18446744073709551615, 0, 1, 1), - (13, 1028, 959, 891, 18446744073709551615, 0, 144, 2), - (13, 1028, 890, 1116, 18446744073709551615, 1, 145, 2), - (13, 1028, 779, 744, 18446744073709551615, 1, 145, 2), - (13, 1116, 890, 780, 18446744073709551615, 1, 2, 2), - (14, 1028, 891, 959, 18446744073709551615, 0, 1, 1), - (13, 287, 805, 802, 18446744073709551615, 8, 9, 2), - (13, 891, 959, 785, 18446744073709551615, 0, 4, 2), - (13, 892, 193, 22, 18446744073709551615, 0, 3, 1), - (13, 1028, 193, 892, 18446744073709551615, 0, 143, 2), - (13, 1028, 959, 891, 18446744073709551615, 1, 144, 2), - (14, 1028, 892, 193, 18446744073709551615, 0, 6, 1), - (13, 286, 927, 1141, 18446744073709551615, 0, 10, 2), - (13, 1028, 146, 1025, 18446744073709551615, 5, 150, 2), - (13, 1028, 193, 892, 18446744073709551615, 1, 143, 2), - (14, 1028, 892, 193, 18446744073709551615, 1, 6, 2), - (13, 286, 832, 927, 18446744073709551615, 0, 10, 2), - (13, 893, 780, 889, 18446744073709551615, 0, 7, 1), - (13, 1028, 780, 893, 18446744073709551615, 0, 141, 2), - (14, 1028, 893, 780, 18446744073709551615, 0, 1, 1), - (13, 286, 927, 1141, 18446744073709551615, 2, 10, 2), - (13, 126, 895, 757, 18446744073709551615, 0, 1, 1), - (13, 1028, 895, 126, 18446744073709551615, 0, 140, 2), - (13, 1028, 780, 893, 18446744073709551615, 1, 141, 2), - (14, 1028, 126, 895, 18446744073709551615, 0, 7, 1), - (13, 286, 832, 927, 18446744073709551615, 1, 10, 2), - (13, 1028, 146, 1025, 18446744073709551615, 7, 150, 2), - (13, 759, 962, 896, 18446744073709551615, 0, 1, 1), - (13, 1028, 962, 759, 18446744073709551615, 0, 139, 2), - (14, 1028, 759, 962, 18446744073709551615, 0, 1, 1), - (14, 1028, 126, 895, 18446744073709551615, 1, 7, 2), - (13, 286, 826, 832, 18446744073709551615, 0, 6, 2), - (13, 287, 832, 927, 18446744073709551615, 0, 6, 2), - (13, 896, 1076, 146, 18446744073709551615, 0, 4, 1), - (13, 1028, 1076, 896, 18446744073709551615, 0, 138, 2), - (14, 1028, 896, 1076, 18446744073709551615, 0, 4, 1), - (13, 287, 927, 1141, 18446744073709551615, 3, 10, 2), - (13, 129, 127, 1095, 18446744073709551615, 0, 1, 1), - (13, 1028, 127, 129, 18446744073709551615, 0, 137, 2), - (14, 1028, 129, 127, 18446744073709551615, 0, 1, 1), - (13, 287, 1141, 817, 18446744073709551615, 5, 10, 2), - (13, 760, 734, 735, 18446744073709551615, 0, 8, 1), - (13, 1028, 734, 760, 18446744073709551615, 0, 136, 2), - (13, 1095, 762, 758, 18446744073709551615, 0, 2, 2), - (13, 900, 757, 1118, 18446744073709551615, 0, 5, 1), - (13, 1028, 757, 900, 18446744073709551615, 0, 135, 2), - (13, 1028, 762, 1095, 18446744073709551615, 1, 136, 2), - (14, 1028, 900, 757, 18446744073709551615, 0, 3, 1), - (13, 287, 1141, 817, 18446744073709551615, 7, 10, 2), - (13, 900, 757, 785, 18446744073709551615, 0, 6, 2), - (13, 133, 902, 22, 18446744073709551615, 0, 5, 1), - (13, 1028, 902, 133, 18446744073709551615, 0, 134, 2), - (13, 1028, 757, 900, 18446744073709551615, 1, 135, 2), - (14, 1028, 133, 902, 18446744073709551615, 0, 1, 1), - (13, 287, 927, 1141, 18446744073709551615, 5, 10, 2), - (13, 287, 1141, 817, 18446744073709551615, 8, 10, 2), - (13, 737, 190, 756, 18446744073709551615, 0, 3, 1), - (13, 1028, 190, 737, 18446744073709551615, 0, 133, 2), - (13, 1028, 902, 133, 18446744073709551615, 1, 134, 2), - (14, 1028, 737, 190, 18446744073709551615, 0, 2, 1), - (13, 903, 761, 1118, 18446744073709551615, 0, 9, 1), - (13, 1028, 761, 903, 18446744073709551615, 0, 132, 2), - (14, 1028, 903, 761, 18446744073709551615, 0, 1, 1), - (13, 286, 832, 927, 18446744073709551615, 7, 10, 2), - (13, 136, 905, 22, 18446744073709551615, 0, 1, 1), - (13, 1028, 905, 136, 18446744073709551615, 0, 131, 2), - (14, 1028, 136, 905, 18446744073709551615, 0, 4, 1), - (13, 740, 1075, 756, 18446744073709551615, 0, 7, 1), - (13, 1028, 1075, 740, 18446744073709551615, 0, 130, 2), - (14, 1028, 740, 1075, 18446744073709551615, 0, 1, 1), - (13, 287, 832, 927, 18446744073709551615, 3, 6, 2), - (13, 906, 758, 1118, 18446744073709551615, 0, 3, 1), - (13, 1028, 758, 906, 18446744073709551615, 0, 129, 2), - (14, 1028, 906, 758, 18446744073709551615, 0, 7, 1), - (13, 287, 832, 927, 18446744073709551615, 4, 6, 2), - (13, 140, 745, 22, 18446744073709551615, 0, 5, 1), - (13, 1028, 745, 140, 18446744073709551615, 0, 128, 2), - (14, 1028, 140, 745, 18446744073709551615, 0, 2, 1), - (13, 287, 814, 829, 18446744073709551615, 0, 4, 2), - (13, 1028, 741, 738, 18446744073709551615, 0, 1, 2), - (14, 1028, 140, 745, 18446744073709551615, 1, 2, 2), - (13, 965, 738, 736, 18446744073709551615, 0, 8, 1), - (13, 287, 826, 832, 18446744073709551615, 2, 4, 2), - (13, 142, 919, 22, 18446744073709551615, 0, 1, 1), - (13, 1028, 919, 142, 18446744073709551615, 0, 125, 2), - (14, 1028, 142, 919, 18446744073709551615, 0, 5, 1), - (13, 287, 829, 826, 18446744073709551615, 2, 3, 2), - (13, 1144, 1074, 756, 18446744073709551615, 0, 5, 1), - (13, 1028, 1074, 1144, 18446744073709551615, 0, 124, 2), - (14, 1028, 1144, 1074, 18446744073709551615, 0, 2, 1), - (13, 1028, 836, 913, 18446744073709551615, 0, 1, 2), - (14, 1028, 1144, 1074, 18446744073709551615, 1, 2, 2), - (13, 144, 913, 742, 18446744073709551615, 0, 7, 1), - (14, 1028, 144, 913, 18446744073709551615, 0, 6, 1), - (13, 781, 968, 1143, 18446744073709551615, 0, 10, 1), - (13, 1028, 968, 781, 18446744073709551615, 0, 121, 2), - (14, 1028, 781, 968, 18446744073709551615, 0, 1, 1), - (13, 286, 1122, 1121, 18446744073709551615, 0, 8, 2), - (13, 914, 743, 43, 18446744073709551615, 0, 1, 1), - (13, 1028, 743, 914, 18446744073709551615, 0, 120, 2), - (14, 1028, 914, 743, 18446744073709551615, 0, 6, 1), - (13, 286, 1121, 1120, 18446744073709551615, 3, 10, 2), - (13, 287, 1120, 823, 18446744073709551615, 3, 10, 2), - (13, 147, 145, 742, 18446744073709551615, 0, 8, 1), - (13, 1028, 145, 147, 18446744073709551615, 0, 119, 2), - (14, 1028, 147, 145, 18446744073709551615, 0, 1, 1), - (13, 287, 823, 814, 18446744073709551615, 4, 9, 2), - (13, 1152, 15, 735, 18446744073709551615, 0, 6, 1), - (13, 1028, 15, 1152, 18446744073709551615, 0, 118, 2), - (13, 911, 1146, 736, 18446744073709551615, 0, 7, 2), - (13, 918, 836, 1118, 18446744073709551615, 0, 6, 1), - (13, 1028, 836, 918, 18446744073709551615, 0, 117, 2), - (13, 1028, 1146, 911, 18446744073709551615, 1, 118, 2), - (14, 1028, 918, 836, 18446744073709551615, 0, 4, 1), - (13, 918, 836, 785, 18446744073709551615, 0, 4, 2), - (13, 151, 920, 22, 18446744073709551615, 0, 3, 1), - (13, 1028, 920, 151, 18446744073709551615, 0, 116, 2), - (14, 1028, 151, 920, 18446744073709551615, 0, 1, 1), - (13, 783, 196, 756, 18446744073709551615, 0, 4, 1), - (13, 1028, 196, 783, 18446744073709551615, 0, 115, 2), - (14, 1028, 783, 196, 18446744073709551615, 0, 4, 1), - (13, 921, 746, 1118, 18446744073709551615, 0, 7, 1), - (13, 1028, 746, 921, 18446744073709551615, 0, 114, 2), - (14, 1028, 921, 746, 18446744073709551615, 0, 1, 1), - (13, 287, 1120, 823, 18446744073709551615, 7, 10, 2), - (13, 154, 157, 22, 18446744073709551615, 0, 2, 1), - (13, 1028, 157, 154, 18446744073709551615, 0, 113, 2), - (14, 1028, 154, 157, 18446744073709551615, 0, 4, 1), - (13, 1138, 1073, 756, 18446744073709551615, 0, 5, 1), - (13, 1028, 1073, 1138, 18446744073709551615, 0, 112, 2), - (14, 1028, 1138, 1073, 18446744073709551615, 0, 2, 1), - (13, 287, 1124, 1123, 18446744073709551615, 0, 9, 2), - (13, 1028, 1136, 784, 18446744073709551615, 0, 1, 2), - (14, 1028, 1138, 1073, 18446744073709551615, 1, 2, 2), - (13, 43, 784, 785, 18446744073709551615, 0, 4, 1), - (13, 1135, 67, 756, 18446744073709551615, 0, 5, 1), - (13, 1028, 67, 1135, 18446744073709551615, 0, 109, 2), - (14, 1028, 1135, 67, 18446744073709551615, 0, 5, 1), - (13, 286, 1126, 1125, 18446744073709551615, 0, 7, 2), - (13, 1028, 1136, 28, 18446744073709551615, 0, 1, 2), - (14, 1028, 1135, 67, 18446744073709551615, 1, 5, 2), - (13, 286, 1123, 1122, 18446744073709551615, 1, 9, 2), - (13, 287, 1122, 1121, 18446744073709551615, 1, 9, 2), - (13, 1133, 28, 785, 18446744073709551615, 0, 4, 1), - (13, 286, 1124, 1123, 18446744073709551615, 1, 10, 2), - (13, 782, 1001, 756, 18446744073709551615, 0, 6, 1), - (13, 1028, 1001, 782, 18446744073709551615, 0, 106, 2), - (14, 1028, 782, 1001, 18446744073709551615, 0, 1, 1), - (13, 1024, 1001, 782, 18446744073709551615, 0, 104, 2), - (13, 287, 1124, 1123, 18446744073709551615, 2, 9, 2), - (13, 933, 31, 1118, 18446744073709551615, 0, 9, 1), - (13, 1028, 31, 933, 18446744073709551615, 0, 105, 2), - (14, 1028, 933, 31, 18446744073709551615, 0, 5, 1), - (13, 1024, 31, 933, 18446744073709551615, 0, 103, 2), - (13, 286, 1126, 1125, 18446744073709551615, 1, 7, 2), - (13, 1028, 742, 40, 18446744073709551615, 0, 1, 2), - (14, 1028, 933, 31, 18446744073709551615, 1, 5, 2), - (13, 286, 1125, 1124, 18446744073709551615, 4, 9, 2), - (13, 46, 40, 735, 18446744073709551615, 0, 8, 1), - (13, 286, 1124, 1123, 18446744073709551615, 4, 10, 2), - (13, 287, 1122, 1121, 18446744073709551615, 3, 9, 2), - (13, 19, 49, 1131, 18446744073709551615, 0, 5, 1), - (13, 1028, 49, 19, 18446744073709551615, 0, 102, 2), - (13, 286, 1123, 1122, 18446744073709551615, 4, 9, 2), - (13, 162, 164, 1127, 18446744073709551615, 0, 2, 2), - (13, 167, 936, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 936, 167, 18446744073709551615, 0, 101, 2), - (13, 1028, 164, 162, 18446744073709551615, 1, 102, 2), - (14, 1028, 167, 936, 18446744073709551615, 0, 1, 1), - (13, 167, 936, 1129, 18446744073709551615, 0, 4, 2), - (13, 52, 199, 1128, 18446744073709551615, 0, 4, 1), - (13, 1028, 199, 52, 18446744073709551615, 0, 100, 2), - (13, 1028, 936, 167, 18446744073709551615, 1, 101, 2), - (14, 1028, 52, 199, 18446744073709551615, 0, 4, 1), - (13, 287, 1123, 1122, 18446744073709551615, 6, 10, 2), - (13, 52, 199, 1131, 18446744073709551615, 0, 5, 2), - (13, 937, 37, 1130, 18446744073709551615, 0, 5, 1), - (13, 1028, 37, 937, 18446744073709551615, 0, 99, 2), - (13, 1028, 199, 52, 18446744073709551615, 1, 100, 2), - (14, 1028, 937, 37, 18446744073709551615, 0, 1, 1), - (13, 937, 37, 1127, 18446744073709551615, 0, 3, 2), - (13, 170, 168, 1126, 18446744073709551615, 0, 3, 1), - (13, 1028, 168, 170, 18446744073709551615, 0, 98, 2), - (13, 1028, 37, 937, 18446744073709551615, 1, 99, 2), - (14, 1028, 170, 168, 18446744073709551615, 0, 4, 1), - (13, 286, 1123, 1122, 18446744073709551615, 7, 9, 2), - (13, 287, 1122, 1121, 18446744073709551615, 7, 9, 2), - (13, 55, 64, 1122, 18446744073709551615, 0, 1, 1), - (13, 1028, 64, 55, 18446744073709551615, 0, 97, 2), - (13, 1028, 168, 170, 18446744073709551615, 1, 98, 2), - (13, 286, 1124, 1123, 18446744073709551615, 8, 10, 2), - (13, 287, 1123, 1122, 18446744073709551615, 8, 10, 2), - (13, 156, 61, 1124, 18446744073709551615, 0, 2, 2), - (13, 1082, 929, 1123, 18446744073709551615, 0, 2, 1), - (13, 1028, 929, 1082, 18446744073709551615, 0, 96, 2), - (13, 1028, 61, 156, 18446744073709551615, 1, 97, 2), - (13, 1028, 64, 55, 18446744073709551615, 1, 97, 2), - (14, 1028, 1082, 929, 18446744073709551615, 0, 2, 1), - (13, 1082, 929, 1126, 18446744073709551615, 0, 4, 2), - (13, 1028, 1126, 974, 18446744073709551615, 0, 1, 2), - (13, 1028, 929, 1082, 18446744073709551615, 1, 96, 2), - (14, 1028, 1082, 929, 18446744073709551615, 1, 2, 1), - (13, 286, 1126, 1125, 18446744073709551615, 2, 7, 2), - (13, 942, 974, 1128, 18446744073709551615, 0, 5, 1), - (13, 1028, 974, 942, 18446744073709551615, 0, 94, 2), - (14, 1028, 942, 974, 18446744073709551615, 0, 4, 1), - (13, 286, 1127, 1126, 18446744073709551615, 0, 6, 2), - (13, 943, 1072, 1130, 18446744073709551615, 0, 4, 1), - (13, 1028, 1072, 943, 18446744073709551615, 0, 93, 2), - (14, 1028, 943, 1072, 18446744073709551615, 0, 1, 1), - (13, 176, 945, 1126, 18446744073709551615, 0, 4, 1), - (13, 1028, 945, 176, 18446744073709551615, 0, 92, 2), - (14, 1028, 176, 945, 18446744073709551615, 0, 4, 1), - (13, 1024, 945, 176, 18446744073709551615, 0, 90, 2), - (13, 287, 1126, 1125, 18446744073709551615, 1, 6, 2), - (13, 79, 202, 1128, 18446744073709551615, 0, 3, 1), - (13, 1028, 202, 79, 18446744073709551615, 0, 91, 2), - (14, 1028, 79, 202, 18446744073709551615, 0, 1, 1), - (13, 286, 1128, 1127, 18446744073709551615, 0, 6, 2), - (13, 287, 1127, 1126, 18446744073709551615, 0, 6, 2), - (13, 946, 1004, 1130, 18446744073709551615, 0, 5, 1), - (13, 1028, 1004, 946, 18446744073709551615, 0, 90, 2), - (14, 1028, 946, 1004, 18446744073709551615, 0, 4, 1), - (13, 286, 1127, 1126, 18446744073709551615, 3, 6, 2), - (13, 179, 948, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 948, 179, 18446744073709551615, 0, 89, 2), - (14, 1028, 179, 948, 18446744073709551615, 0, 1, 1), - (13, 287, 1127, 1126, 18446744073709551615, 1, 6, 2), - (13, 88, 1071, 1128, 18446744073709551615, 0, 4, 1), - (13, 1028, 1071, 88, 18446744073709551615, 0, 88, 2), - (14, 1028, 88, 1071, 18446744073709551615, 0, 4, 1), - (13, 286, 1129, 1128, 18446744073709551615, 0, 6, 2), - (13, 287, 1128, 1127, 18446744073709551615, 0, 6, 2), - (13, 949, 73, 1130, 18446744073709551615, 0, 4, 1), - (13, 1028, 73, 949, 18446744073709551615, 0, 87, 2), - (14, 1028, 949, 73, 18446744073709551615, 0, 1, 1), - (13, 287, 1127, 1126, 18446744073709551615, 3, 6, 2), - (13, 182, 951, 1126, 18446744073709551615, 0, 3, 1), - (13, 1028, 951, 182, 18446744073709551615, 0, 86, 2), - (14, 1028, 182, 951, 18446744073709551615, 0, 4, 1), - (13, 97, 977, 1128, 18446744073709551615, 0, 3, 1), - (13, 1028, 977, 97, 18446744073709551615, 0, 85, 2), - (14, 1028, 97, 977, 18446744073709551615, 0, 1, 1), - (13, 952, 82, 1130, 18446744073709551615, 0, 4, 1), - (13, 1028, 82, 952, 18446744073709551615, 0, 84, 2), - (14, 1028, 952, 82, 18446744073709551615, 0, 4, 1), - (13, 1024, 82, 952, 18446744073709551615, 0, 82, 2), - (13, 287, 1128, 1127, 18446744073709551615, 3, 6, 2), - (13, 185, 954, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 954, 185, 18446744073709551615, 0, 83, 2), - (14, 1028, 185, 954, 18446744073709551615, 0, 1, 1), - (13, 287, 1128, 1127, 18446744073709551615, 4, 6, 2), - (13, 106, 205, 1128, 18446744073709551615, 0, 3, 1), - (13, 1028, 205, 106, 18446744073709551615, 0, 82, 2), - (14, 1028, 106, 205, 18446744073709551615, 0, 4, 1), - (13, 286, 1131, 1130, 18446744073709551615, 0, 6, 2), - (13, 287, 1130, 1129, 18446744073709551615, 0, 6, 2), - (13, 955, 91, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 91, 955, 18446744073709551615, 0, 81, 2), - (14, 1028, 955, 91, 18446744073709551615, 0, 1, 1), - (13, 1024, 91, 955, 18446744073709551615, 0, 79, 2), - (13, 188, 957, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 957, 188, 18446744073709551615, 0, 80, 2), - (14, 1028, 188, 957, 18446744073709551615, 0, 4, 1), - (13, 287, 1130, 1129, 18446744073709551615, 1, 6, 2), - (13, 112, 1070, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1070, 112, 18446744073709551615, 0, 79, 2), - (14, 1028, 112, 1070, 18446744073709551615, 0, 1, 1), - (13, 286, 26, 1131, 18446744073709551615, 0, 6, 2), - (13, 287, 1131, 1130, 18446744073709551615, 0, 6, 2), - (13, 287, 1130, 1129, 18446744073709551615, 2, 6, 2), - (13, 958, 100, 1130, 18446744073709551615, 0, 5, 1), - (13, 1028, 100, 958, 18446744073709551615, 0, 78, 2), - (14, 1028, 958, 100, 18446744073709551615, 0, 4, 1), - (13, 1024, 100, 958, 18446744073709551615, 0, 76, 2), - (13, 286, 1131, 1130, 18446744073709551615, 3, 6, 2), - (13, 191, 960, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 960, 191, 18446744073709551615, 0, 77, 2), - (14, 1028, 191, 960, 18446744073709551615, 0, 1, 1), - (13, 131, 980, 1128, 18446744073709551615, 0, 4, 1), - (13, 1028, 980, 131, 18446744073709551615, 0, 76, 2), - (14, 1028, 131, 980, 18446744073709551615, 0, 4, 1), - (13, 1024, 980, 131, 18446744073709551615, 0, 74, 2), - (13, 286, 22, 26, 18446744073709551615, 0, 6, 2), - (13, 287, 26, 1131, 18446744073709551615, 0, 6, 2), - (13, 961, 109, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 109, 961, 18446744073709551615, 0, 75, 2), - (14, 1028, 961, 109, 18446744073709551615, 0, 1, 1), - (13, 1024, 109, 961, 18446744073709551615, 0, 73, 2), - (13, 286, 26, 1131, 18446744073709551615, 3, 6, 2), - (13, 287, 1131, 1130, 18446744073709551615, 3, 6, 2), - (13, 194, 963, 1126, 18446744073709551615, 0, 3, 1), - (13, 1028, 963, 194, 18446744073709551615, 0, 74, 2), - (14, 1028, 194, 963, 18446744073709551615, 0, 4, 1), - (13, 287, 26, 1131, 18446744073709551615, 1, 6, 2), - (13, 1096, 208, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 208, 1096, 18446744073709551615, 0, 73, 2), - (14, 1028, 1096, 208, 18446744073709551615, 0, 1, 1), - (13, 286, 785, 22, 18446744073709551615, 0, 6, 2), - (13, 287, 22, 26, 18446744073709551615, 0, 6, 2), - (13, 287, 26, 1131, 18446744073709551615, 2, 6, 2), - (13, 964, 122, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 122, 964, 18446744073709551615, 0, 72, 2), - (14, 1028, 964, 122, 18446744073709551615, 0, 4, 1), - (13, 1024, 122, 964, 18446744073709551615, 0, 70, 2), - (13, 286, 22, 26, 18446744073709551615, 3, 6, 2), - (13, 197, 966, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 966, 197, 18446744073709551615, 0, 71, 2), - (14, 1028, 197, 966, 18446744073709551615, 0, 1, 1), - (13, 149, 1069, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1069, 149, 18446744073709551615, 0, 70, 2), - (14, 1028, 149, 1069, 18446744073709551615, 0, 4, 1), - (13, 286, 756, 785, 18446744073709551615, 0, 6, 2), - (13, 967, 134, 1130, 18446744073709551615, 0, 5, 1), - (13, 1028, 134, 967, 18446744073709551615, 0, 69, 2), - (14, 1028, 967, 134, 18446744073709551615, 0, 1, 1), - (13, 287, 22, 26, 18446744073709551615, 3, 6, 2), - (13, 200, 969, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 969, 200, 18446744073709551615, 0, 68, 2), - (14, 1028, 200, 969, 18446744073709551615, 0, 4, 1), - (13, 159, 983, 1128, 18446744073709551615, 0, 4, 1), - (13, 1028, 983, 159, 18446744073709551615, 0, 67, 2), - (14, 1028, 159, 983, 18446744073709551615, 0, 1, 1), - (13, 1024, 983, 159, 18446744073709551615, 0, 65, 2), - (13, 970, 1091, 1130, 18446744073709551615, 0, 4, 1), - (13, 1028, 1091, 970, 18446744073709551615, 0, 66, 2), - (14, 1028, 970, 1091, 18446744073709551615, 0, 3, 1), - (13, 286, 756, 785, 18446744073709551615, 3, 6, 2), - (13, 287, 785, 22, 18446744073709551615, 3, 6, 2), - (13, 203, 972, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 972, 203, 18446744073709551615, 0, 65, 2), - (14, 1028, 203, 972, 18446744073709551615, 0, 1, 1), - (13, 1024, 972, 203, 18446744073709551615, 0, 63, 2), - (13, 286, 735, 756, 18446744073709551615, 1, 6, 2), - (13, 174, 211, 1128, 18446744073709551615, 0, 3, 1), - (13, 1028, 211, 174, 18446744073709551615, 0, 64, 2), - (14, 1028, 174, 211, 18446744073709551615, 0, 2, 1), - (13, 286, 1118, 735, 18446744073709551615, 0, 6, 2), - (13, 287, 735, 756, 18446744073709551615, 0, 6, 2), - (13, 973, 152, 1130, 18446744073709551615, 0, 4, 1), - (13, 1028, 152, 973, 18446744073709551615, 0, 63, 2), - (14, 1028, 973, 152, 18446744073709551615, 0, 1, 1), - (13, 286, 735, 756, 18446744073709551615, 3, 6, 2), - (13, 206, 975, 1126, 18446744073709551615, 0, 2, 1), - (13, 1028, 975, 206, 18446744073709551615, 0, 62, 2), - (14, 1028, 206, 975, 18446744073709551615, 0, 2, 1), - (13, 287, 735, 756, 18446744073709551615, 1, 6, 2), - (13, 183, 1068, 1128, 18446744073709551615, 0, 3, 1), - (13, 1028, 1068, 183, 18446744073709551615, 0, 61, 2), - (14, 1028, 183, 1068, 18446744073709551615, 0, 1, 1), - (13, 287, 1118, 735, 18446744073709551615, 0, 6, 2), - (13, 976, 173, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 173, 976, 18446744073709551615, 0, 60, 2), - (14, 1028, 976, 173, 18446744073709551615, 0, 1, 1), - (13, 1024, 173, 976, 18446744073709551615, 0, 58, 2), - (13, 286, 1118, 735, 18446744073709551615, 3, 6, 2), - (13, 287, 735, 756, 18446744073709551615, 3, 6, 2), - (13, 209, 978, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 978, 209, 18446744073709551615, 0, 59, 2), - (14, 1028, 209, 978, 18446744073709551615, 0, 1, 1), - (13, 287, 1118, 735, 18446744073709551615, 1, 6, 2), - (13, 192, 986, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 986, 192, 18446744073709551615, 0, 58, 2), - (14, 1028, 192, 986, 18446744073709551615, 0, 1, 1), - (13, 287, 1118, 735, 18446744073709551615, 2, 6, 2), - (13, 979, 177, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 177, 979, 18446744073709551615, 0, 57, 2), - (14, 1028, 979, 177, 18446744073709551615, 0, 1, 1), - (13, 287, 1118, 735, 18446744073709551615, 3, 6, 2), - (13, 212, 981, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 981, 212, 18446744073709551615, 0, 56, 2), - (14, 1028, 212, 981, 18446744073709551615, 0, 2, 1), - (13, 201, 214, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 214, 201, 18446744073709551615, 0, 55, 2), - (14, 1028, 201, 214, 18446744073709551615, 0, 1, 1), - (13, 982, 186, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 186, 982, 18446744073709551615, 0, 54, 2), - (14, 1028, 982, 186, 18446744073709551615, 0, 1, 1), - (13, 286, 739, 736, 18446744073709551615, 3, 6, 2), - (13, 215, 984, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 984, 215, 18446744073709551615, 0, 53, 2), - (14, 1028, 215, 984, 18446744073709551615, 0, 1, 1), - (13, 286, 742, 739, 18446744073709551615, 1, 6, 2), - (13, 287, 739, 736, 18446744073709551615, 1, 6, 2), - (13, 210, 1067, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1067, 210, 18446744073709551615, 0, 52, 2), - (14, 1028, 210, 1067, 18446744073709551615, 0, 1, 1), - (13, 287, 742, 739, 18446744073709551615, 0, 6, 2), - (13, 985, 195, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 195, 985, 18446744073709551615, 0, 51, 2), - (14, 1028, 985, 195, 18446744073709551615, 0, 1, 1), - (13, 286, 742, 739, 18446744073709551615, 3, 6, 2), - (13, 287, 739, 736, 18446744073709551615, 3, 6, 2), - (13, 218, 987, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 987, 218, 18446744073709551615, 0, 50, 2), - (14, 1028, 218, 987, 18446744073709551615, 0, 2, 1), - (13, 287, 742, 739, 18446744073709551615, 1, 6, 2), - (13, 219, 989, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 989, 219, 18446744073709551615, 0, 49, 2), - (14, 1028, 219, 989, 18446744073709551615, 0, 1, 1), - (13, 287, 741, 742, 18446744073709551615, 0, 6, 2), - (13, 988, 204, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 204, 988, 18446744073709551615, 0, 48, 2), - (14, 1028, 988, 204, 18446744073709551615, 0, 2, 1), - (13, 287, 739, 736, 18446744073709551615, 5, 6, 2), - (13, 221, 990, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 990, 221, 18446744073709551615, 0, 47, 2), - (14, 1028, 221, 990, 18446744073709551615, 0, 1, 1), - (13, 1024, 990, 221, 18446744073709551615, 0, 45, 2), - (13, 228, 217, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 217, 228, 18446744073709551615, 0, 46, 2), - (14, 1028, 228, 217, 18446744073709551615, 0, 1, 1), - (13, 991, 213, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 213, 991, 18446744073709551615, 0, 45, 2), - (14, 1028, 991, 213, 18446744073709551615, 0, 1, 1), - (13, 286, 1143, 741, 18446744073709551615, 3, 6, 2), - (13, 224, 993, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 993, 224, 18446744073709551615, 0, 44, 2), - (14, 1028, 224, 993, 18446744073709551615, 0, 1, 1), - (13, 287, 1143, 741, 18446744073709551615, 1, 6, 2), - (13, 237, 1066, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1066, 237, 18446744073709551615, 0, 43, 2), - (14, 1028, 237, 1066, 18446744073709551615, 0, 1, 1), - (13, 286, 1136, 971, 18446744073709551615, 0, 6, 2), - (13, 994, 222, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 222, 994, 18446744073709551615, 0, 42, 2), - (14, 1028, 994, 222, 18446744073709551615, 0, 2, 1), - (13, 286, 971, 1143, 18446744073709551615, 3, 6, 2), - (13, 287, 1143, 741, 18446744073709551615, 3, 6, 2), - (13, 227, 996, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 996, 227, 18446744073709551615, 0, 41, 2), - (14, 1028, 227, 996, 18446744073709551615, 0, 1, 1), - (13, 1024, 996, 227, 18446744073709551615, 0, 39, 2), - (13, 246, 992, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 992, 246, 18446744073709551615, 0, 40, 2), - (14, 1028, 246, 992, 18446744073709551615, 0, 1, 1), - (13, 286, 1114, 1136, 18446744073709551615, 0, 6, 2), - (13, 287, 1136, 971, 18446744073709551615, 0, 6, 2), - (13, 997, 231, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 231, 997, 18446744073709551615, 0, 39, 2), - (14, 1028, 997, 231, 18446744073709551615, 0, 1, 1), - (13, 1024, 231, 997, 18446744073709551615, 0, 37, 2), - (13, 230, 999, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 999, 230, 18446744073709551615, 0, 38, 2), - (14, 1028, 230, 999, 18446744073709551615, 0, 1, 1), - (13, 1024, 999, 230, 18446744073709551615, 0, 36, 2), - (13, 252, 220, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 220, 252, 18446744073709551615, 0, 37, 2), - (14, 1028, 252, 220, 18446744073709551615, 0, 1, 1), - (13, 287, 1114, 1136, 18446744073709551615, 0, 6, 2), - (13, 1000, 240, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 240, 1000, 18446744073709551615, 0, 36, 2), - (14, 1028, 1000, 240, 18446744073709551615, 0, 2, 1), - (13, 286, 1114, 1136, 18446744073709551615, 3, 6, 2), - (13, 233, 1002, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1002, 233, 18446744073709551615, 0, 35, 2), - (14, 1028, 233, 1002, 18446744073709551615, 0, 1, 1), - (13, 1053, 1065, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1065, 1053, 18446744073709551615, 0, 34, 2), - (14, 1028, 1053, 1065, 18446744073709551615, 0, 2, 1), - (13, 287, 160, 1114, 18446744073709551615, 0, 6, 2), - (13, 1003, 249, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 249, 1003, 18446744073709551615, 0, 33, 2), - (14, 1028, 1003, 249, 18446744073709551615, 0, 1, 1), - (13, 286, 160, 1114, 18446744073709551615, 3, 6, 2), - (13, 287, 1114, 1136, 18446744073709551615, 3, 6, 2), - (13, 236, 1005, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1005, 236, 18446744073709551615, 0, 32, 2), - (14, 1028, 236, 1005, 18446744073709551615, 0, 1, 1), - (13, 287, 1114, 1136, 18446744073709551615, 4, 6, 2), - (13, 1042, 995, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 995, 1042, 18446744073709551615, 0, 31, 2), - (14, 1028, 1042, 995, 18446744073709551615, 0, 1, 1), - (13, 286, 70, 34, 18446744073709551615, 0, 6, 2), - (13, 1006, 1047, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 1047, 1006, 18446744073709551615, 0, 30, 2), - (14, 1028, 1006, 1047, 18446744073709551615, 0, 1, 1), - (13, 287, 160, 1114, 18446744073709551615, 3, 6, 2), - (13, 239, 1008, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1008, 239, 18446744073709551615, 0, 29, 2), - (14, 1028, 239, 1008, 18446744073709551615, 0, 1, 1), - (13, 1024, 1008, 239, 18446744073709551615, 0, 27, 2), - (13, 286, 70, 34, 18446744073709551615, 1, 6, 2), - (13, 1050, 223, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 223, 1050, 18446744073709551615, 0, 28, 2), - (14, 1028, 1050, 223, 18446744073709551615, 0, 2, 1), - (13, 1009, 1051, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 1051, 1009, 18446744073709551615, 0, 27, 2), - (14, 1028, 1009, 1051, 18446744073709551615, 0, 1, 1), - (13, 286, 70, 34, 18446744073709551615, 3, 6, 2), - (13, 287, 34, 160, 18446744073709551615, 3, 6, 2), - (13, 242, 1011, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1011, 242, 18446744073709551615, 0, 26, 2), - (14, 1028, 242, 1011, 18446744073709551615, 0, 1, 1), - (13, 1024, 1011, 242, 18446744073709551615, 0, 24, 2), - (13, 286, 58, 70, 18446744073709551615, 1, 6, 2), - (13, 287, 70, 34, 18446744073709551615, 1, 6, 2), - (13, 1045, 1064, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1064, 1045, 18446744073709551615, 0, 25, 2), - (14, 1028, 1045, 1064, 18446744073709551615, 0, 1, 1), - (13, 1024, 1064, 1045, 18446744073709551615, 0, 23, 2), - (13, 287, 58, 70, 18446744073709551615, 0, 6, 2), - (13, 1012, 1048, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 1048, 1012, 18446744073709551615, 0, 24, 2), - (14, 1028, 1012, 1048, 18446744073709551615, 0, 1, 1), - (13, 287, 70, 34, 18446744073709551615, 3, 6, 2), - (13, 245, 1014, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1014, 245, 18446744073709551615, 0, 23, 2), - (14, 1028, 245, 1014, 18446744073709551615, 0, 1, 1), - (13, 1033, 998, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 998, 1033, 18446744073709551615, 0, 22, 2), - (14, 1028, 1033, 998, 18446744073709551615, 0, 2, 1), - (13, 1024, 998, 1033, 18446744073709551615, 0, 20, 2), - (13, 287, 76, 58, 18446744073709551615, 0, 6, 2), - (13, 1015, 1046, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 1046, 1015, 18446744073709551615, 0, 21, 2), - (14, 1028, 1015, 1046, 18446744073709551615, 0, 1, 1), - (13, 1024, 1046, 1015, 18446744073709551615, 0, 19, 2), - (13, 287, 58, 70, 18446744073709551615, 3, 6, 2), - (13, 287, 70, 34, 18446744073709551615, 5, 6, 2), - (13, 248, 1017, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1017, 248, 18446744073709551615, 0, 20, 2), - (14, 1028, 248, 1017, 18446744073709551615, 0, 1, 1), - (13, 286, 85, 76, 18446744073709551615, 1, 6, 2), - (13, 287, 76, 58, 18446744073709551615, 1, 6, 2), - (13, 1037, 226, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 226, 1037, 18446744073709551615, 0, 19, 2), - (14, 1028, 1037, 226, 18446744073709551615, 0, 1, 1), - (13, 286, 94, 85, 18446744073709551615, 0, 5, 2), - (13, 1018, 1035, 1130, 18446744073709551615, 0, 3, 1), - (13, 1028, 1035, 1018, 18446744073709551615, 0, 18, 2), - (14, 1028, 1018, 1035, 18446744073709551615, 0, 2, 1), - (13, 287, 76, 58, 18446744073709551615, 3, 6, 2), - (13, 251, 1020, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1020, 251, 18446744073709551615, 0, 17, 2), - (14, 1028, 251, 1020, 18446744073709551615, 0, 1, 1), - (13, 287, 85, 76, 18446744073709551615, 1, 5, 2), - (13, 1034, 1063, 1128, 18446744073709551615, 0, 2, 1), - (13, 1028, 1063, 1034, 18446744073709551615, 0, 16, 2), - (14, 1028, 1034, 1063, 18446744073709551615, 0, 1, 1), - (13, 286, 103, 94, 18446744073709551615, 0, 3, 2), - (13, 1021, 1043, 1130, 18446744073709551615, 0, 2, 1), - (13, 1028, 1043, 1021, 18446744073709551615, 0, 15, 2), - (14, 1028, 1021, 1043, 18446744073709551615, 0, 1, 1), - (13, 287, 85, 76, 18446744073709551615, 3, 5, 2), - (13, 254, 1023, 1126, 18446744073709551615, 0, 1, 1), - (13, 1028, 1023, 254, 18446744073709551615, 0, 14, 2), - (14, 1028, 254, 1023, 18446744073709551615, 0, 1, 1), - (13, 1024, 1023, 254, 18446744073709551615, 0, 12, 2), - (13, 286, 103, 94, 18446744073709551615, 1, 3, 2), - (13, 1031, 229, 1128, 18446744073709551615, 0, 1, 1), - (13, 1028, 229, 1031, 18446744073709551615, 0, 13, 2), - (14, 1028, 1031, 229, 18446744073709551615, 0, 1, 1), - (13, 1049, 1038, 1130, 18446744073709551615, 0, 1, 1), - (13, 1028, 1038, 1049, 18446744073709551615, 0, 12, 2), - (14, 1028, 1049, 1038, 18446744073709551615, 0, 11, 1), - (13, 1024, 1038, 1049, 18446744073709551615, 0, 10, 2), - (13, 287, 120, 103, 18446744073709551615, 0, 1, 2), - (13, 1028, 22, 232, 18446744073709551615, 0, 1, 2), - (14, 1028, 1049, 1038, 18446744073709551615, 1, 11, 2), - (13, 286, 912, 141, 18446744073709551615, 0, 1, 2), - (13, 287, 137, 124, 18446744073709551615, 0, 1, 2), - (14, 1028, 1049, 1038, 18446744073709551615, 2, 11, 2), - (13, 287, 180, 1083, 18446744073709551615, 0, 2, 2), - (13, 287, 1083, 912, 18446744073709551615, 0, 1, 2), - (13, 286, 198, 189, 18446744073709551615, 0, 1, 2), - (13, 286, 172, 243, 18446744073709551615, 0, 2, 2), - (13, 287, 243, 234, 18446744073709551615, 0, 2, 2), - (13, 286, 1030, 1039, 18446744073709551615, 0, 1, 2), - (13, 287, 1039, 1041, 18446744073709551615, 0, 1, 2), - (13, 276, 1013, 1062, 18446744073709551615, 0, 3, 2), - (13, 278, 238, 232, 18446744073709551615, 0, 3, 2), - (13, 281, 1007, 235, 18446744073709551615, 0, 3, 2), - (13, 282, 235, 1061, 18446744073709551615, 0, 3, 2), - (13, 299, 216, 207, 18446744073709551615, 0, 3, 2), - (13, 301, 198, 189, 18446744073709551615, 0, 3, 2), - (13, 306, 912, 141, 18446744073709551615, 0, 3, 1), - (13, 303, 1083, 912, 18446744073709551615, 0, 3, 1), - (13, 304, 912, 141, 18446744073709551615, 1, 6, 1), - (13, 286, 765, 1027, 18446744073709551615, 1, 3, 2), - (13, 287, 1027, 1030, 18446744073709551615, 1, 3, 2), - (13, 286, 765, 1027, 18446744073709551615, 2, 3, 2), - (13, 306, 912, 141, 18446744073709551615, 2, 3, 1), - (13, 287, 996, 222, 18446744073709551615, 0, 1, 2), -]; diff --git a/src/point_add/dirtyscan.rs b/src/point_add/dirtyscan.rs deleted file mode 100644 index 13cf18cc..00000000 --- a/src/point_add/dirtyscan.rs +++ /dev/null @@ -1,354 +0,0 @@ -//! DIAGNOSTIC ONLY (`TLM_DIRTY_SCAN=1`). Never runs in a scoring build. -//! -//! Every phase failure in this circuit is a qubit that still held 1 when it was -//! measured away: `sim.rs:140-155` makes `R`/`Hmr` flip that shot's phase with -//! probability 1/2 and then force-zeroes the qubit, discarding the outcome. So a -//! systematic `phase-garbage` rate is a *deterministic dirty free*, and a single -//! 64-lane batch localises it exactly. -//! -//! This module re-implements `Simulator::apply_iter` verbatim (same order, same -//! xof consumption) with one extra observation per `R`/`Hmr`: the mask of live -//! lanes whose target qubit is 1 at that instant. It then asserts its own final -//! (qubits, bits, phase) against the frozen `crate::sim::Simulator` driven from -//! an identical xof, so the mirror is proved faithful on every run rather than -//! assumed. -//! -//! Attribution needs a 1:1 op-index mapping, so run it with -//! `CONSTPROP_DISABLE=1 SINGLE_CCX_FANOUT_DISABLE=1 TRACE_OP_SITES=1`. - -use crate::circuit::{Op, OperationType, QubitOrBit, NO_BIT}; -use crate::sim::Simulator; -use alloy_primitives::U256; -use sha3::{ - digest::{ExtendableOutput, Update, XofReader}, - Shake256, -}; - -const TRAIL: usize = 6; - -struct Hit { - op_index: usize, - qubit: u64, - kind: OperationType, - lanes: u32, - /// Op indices of the last `TRAIL` gates that could have written this qubit, - /// oldest first. Names the routine that left it dirty. - trail: Vec, -} - -/// Classical mirror of `Simulator::apply_iter`, instrumented at the reset sites. -fn mirrored_run( - ops: &[Op], - q0: &[u64], - b0: &[u64], - xof: &mut impl XofReader, - hits: &mut Vec, - max_hits: usize, -) -> (Vec, Vec, u64) { - let include_hmr = std::env::var_os("TLM_DIRTY_SCAN_HMR").is_some(); - let mut qubits = q0.to_vec(); - let mut bits = b0.to_vec(); - let mut phase = 0u64; - let mut condition_stack: Vec = Vec::new(); - let mut base = u64::MAX; - // Ring of the last TRAIL writers per qubit. - let mut writers: Vec<[usize; TRAIL]> = vec![[usize::MAX; TRAIL]; q0.len()]; - let mut wpos: Vec = vec![0; q0.len()]; - let mut note = |writers: &mut Vec<[usize; TRAIL]>, wpos: &mut Vec, q: u64, index: usize| { - let q = q as usize; - let p = wpos[q] as usize; - writers[q][p] = index; - wpos[q] = ((p + 1) % TRAIL) as u8; - }; - - for (index, op) in ops.iter().enumerate() { - let mut cond = base; - if op.c_condition != NO_BIT { - cond &= bits[op.c_condition.0 as usize]; - } - match op.kind { - OperationType::CCX => { - let v = cond - & qubits[op.q_control1.0 as usize] - & qubits[op.q_control2.0 as usize]; - qubits[op.q_target.0 as usize] ^= v; - note(&mut writers, &mut wpos, op.q_target.0, index); - } - OperationType::CX => { - let v = cond & qubits[op.q_control1.0 as usize]; - qubits[op.q_target.0 as usize] ^= v; - note(&mut writers, &mut wpos, op.q_target.0, index); - } - OperationType::Swap => { - let mut a = qubits[op.q_control1.0 as usize]; - let mut t = qubits[op.q_target.0 as usize]; - a ^= t; - t ^= cond & a; - a ^= t; - qubits[op.q_control1.0 as usize] = a; - qubits[op.q_target.0 as usize] = t; - note(&mut writers, &mut wpos, op.q_control1.0, index); - note(&mut writers, &mut wpos, op.q_target.0, index); - } - OperationType::X => { - qubits[op.q_target.0 as usize] ^= cond; - note(&mut writers, &mut wpos, op.q_target.0, index); - } - OperationType::CCZ => { - phase ^= cond - & qubits[op.q_target.0 as usize] - & qubits[op.q_control1.0 as usize] - & qubits[op.q_control2.0 as usize]; - } - OperationType::CZ => { - phase ^= cond - & qubits[op.q_target.0 as usize] - & qubits[op.q_control1.0 as usize]; - } - OperationType::Z => phase ^= cond & qubits[op.q_target.0 as usize], - OperationType::Neg => phase ^= cond, - OperationType::Hmr | OperationType::R => { - let mut buf = [0u8; 8]; - xof.read(&mut buf); - let rng = u64::from_le_bytes(buf); - // Hmr dirtiness is BY DESIGN (Gidney uncompute: the kickback - // `qubit & rng` is cancelled by the bit-conditioned CZ fixup that - // follows). Only `R` is unrecoverable: its outcome is discarded, so - // any lane holding 1 at an `R` leaks phase with no possible fixup. - let dirty = qubits[op.q_target.0 as usize] & cond; - if dirty != 0 && hits.len() < max_hits && (op.kind == OperationType::R || include_hmr) - { - let q = op.q_target.0 as usize; - let p = wpos[q] as usize; - let trail = (0..TRAIL) - .map(|k| writers[q][(p + k) % TRAIL]) - .filter(|&x| x != usize::MAX) - .collect(); - hits.push(Hit { - op_index: index, - qubit: op.q_target.0, - kind: op.kind, - lanes: dirty.count_ones(), - trail, - }); - } - if op.kind == OperationType::Hmr { - bits[op.c_target.0 as usize] &= !cond; - bits[op.c_target.0 as usize] ^= rng & cond; - } - phase ^= qubits[op.q_target.0 as usize] & rng & cond; - qubits[op.q_target.0 as usize] &= !cond; - } - OperationType::BitInvert => bits[op.c_target.0 as usize] ^= cond, - OperationType::BitStore0 => bits[op.c_target.0 as usize] &= !cond, - OperationType::BitStore1 => bits[op.c_target.0 as usize] |= cond, - OperationType::AppendToRegister - | OperationType::Register - | OperationType::DebugPrint => {} - OperationType::PushCondition => { - condition_stack.push(base); - base &= bits[op.c_condition.0 as usize]; - } - OperationType::PopCondition => { - if let Some(v) = condition_stack.pop() { - base = v; - } - } - } - } - (qubits, bits, phase) -} - -fn measure_xof() -> impl XofReader { - let mut h = Shake256::default(); - h.update(b"tlm-dirty-scan-measure"); - h.finalize_xof() -} - -/// Seed one 64-lane batch of valid secp256k1 addition inputs, exactly the way -/// `eval_circuit::run_tests` does, and return the reference sums. -fn seed_lanes( - sim: &mut Simulator<'_, impl XofReader>, - regs: &[Vec], - seed: u64, -) -> Vec<(U256, U256)> { - let curve = crate::point_add::secp256k1_curve(); - let mut h = Shake256::default(); - h.update(b"tlm-dirty-scan-inputs"); - h.update(&seed.to_le_bytes()); - let mut inputs = h.finalize_xof(); - - let mut expected = Vec::with_capacity(64); - while expected.len() < 64 { - let mut rb = [[0u8; 32]; 2]; - inputs.read(&mut rb[0]); - inputs.read(&mut rb[1]); - let t = curve.mul(curve.gx, curve.gy, U256::from_le_bytes(rb[0])); - let o = curve.mul(curve.gx, curve.gy, U256::from_le_bytes(rb[1])); - if t.0 == o.0 || (t.0.is_zero() && t.1.is_zero()) || (o.0.is_zero() && o.1.is_zero()) { - continue; - } - let shot = expected.len(); - sim.set_register(®s[0], t.0, shot); - sim.set_register(®s[1], t.1, shot); - sim.set_register(®s[2], o.0, shot); - sim.set_register(®s[3], o.1, shot); - expected.push(curve.add(t.0, t.1, o.0, o.1)); - } - expected -} - -pub(crate) fn scan(ops: &[Op], transitions: &[(usize, &'static str)]) { - let max_hits: usize = std::env::var("TLM_DIRTY_SCAN_MAX") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(400); - - let (num_q, num_b, _nregs, regs) = crate::circuit::analyze_ops(ops.iter()); - if regs.len() != 4 { - eprintln!("DIRTY_SCAN: expected 4 registers, got {}", regs.len()); - return; - } - - let rounds: u64 = std::env::var("TLM_DIRTY_SCAN_ROUNDS") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(1); - - let mut hits: Vec = Vec::new(); - let mut classical = 0usize; - let mut phase_shots = 0usize; - let mut any_fault = 0usize; - let mut phase_bad = 0usize; - let mut ancilla_bad = 0usize; - let mut last_phase = 0u64; - for round in 0..rounds { - let mut seed_xof = measure_xof(); - let mut seeder = Simulator::new(num_q as usize, num_b as usize, &mut seed_xof); - let expected = seed_lanes(&mut seeder, ®s, round); - let q0 = seeder.qubits.clone(); - let b0 = seeder.bits.clone(); - drop(seeder); - - let mut mirror_xof = measure_xof(); - let (mq, mb, mphase) = - mirrored_run(ops, &q0, &b0, &mut mirror_xof, &mut hits, max_hits); - - // Prove the mirror against the frozen simulator on the same xof stream. - let mut ref_xof = measure_xof(); - let mut sim = Simulator::new(num_q as usize, num_b as usize, &mut ref_xof); - sim.qubits.copy_from_slice(&q0); - sim.bits.copy_from_slice(&b0); - sim.apply_iter(ops.iter()); - assert!( - sim.qubits == mq && sim.bits == mb && sim.phase == mphase, - "dirty-scan mirror diverged from crate::sim::Simulator" - ); - last_phase = sim.phase; - if sim.phase != 0 { - phase_bad += 1; - } - // A nonce is only ground when a shot has NO fault of any kind, so the - // grind exponent is the per-shot UNION, not `classical + phase`: the two - // marginals share a large "both" cell (a divstep truncation corrupts a - // value AND dirties a qubit) and adding them double-counts it. - let mut classical_mask = 0u64; - for (shot, want) in expected.iter().enumerate() { - let gx = sim.get_register(®s[0], shot); - let gy = sim.get_register(®s[1], shot); - if (gx, gy) != *want { - classical += 1; - classical_mask |= 1u64 << shot; - } - } - phase_shots += sim.phase.count_ones() as usize; - any_fault += (classical_mask | sim.phase).count_ones() as usize; - // Same rule as eval_circuit: register members are cleared first, then - // every remaining qubit must be |0> on every live shot. - for register in ®s { - for qb in register { - if let QubitOrBit::Qubit(q) = *qb { - *sim.qubit_mut(q) = 0; - } - } - } - if sim.qubits.iter().any(|&v| v != 0) { - ancilla_bad += 1; - } - if round == 0 { - eprintln!("DIRTY_SCAN mirror_check -> FAITHFUL (qubits, bits and phase all agree)"); - } - } - let lanes = 64 * rounds; - - let sites = crate::point_add::take_last_op_sites(); - let attributable = sites.len() == ops.len(); - let phase_at = |op: usize| -> &'static str { - let mut lo = 0usize; - let mut hi = transitions.len(); - let mut ans = "init"; - while lo < hi { - let mid = (lo + hi) / 2; - if transitions[mid].0 <= op { - ans = transitions[mid].1; - lo = mid + 1; - } else { - hi = mid; - } - } - ans - }; - - // Scale the per-shot fault rate to the harness's 9024-shot eval, which is the - // unit the nonce grind is priced in: P(ground nonce) = exp(-lambda_total). - let lambda = 9024.0 * any_fault as f64 / lanes as f64; - eprintln!( - "DIRTY_SCAN rounds={rounds} lanes={lanes} ops={} classical={classical} phase_shots={phase_shots} any_fault_shots={any_fault} lambda_total_per_9024={lambda:.2} phase_bad_rounds={phase_bad}/{rounds} ancilla_bad_rounds={ancilla_bad}/{rounds} dirty_free_events={} (cap {max_hits}) attributable={attributable} last_phase={last_phase:#018x}", - ops.len(), - hits.len(), - ); - let show: usize = std::env::var("TLM_DIRTY_SCAN_SHOW") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(40); - for h in hits.iter().take(show) { - let site = if attributable { - let (f, l, c) = sites[h.op_index]; - format!("{f}:{l} ctx={c:#010x}") - } else { - "-".to_string() - }; - eprintln!( - "DIRTY_FREE op={} kind={:?} q={} lanes={}/64 phase_region={} site={site}", - h.op_index, - h.kind, - h.qubit, - h.lanes, - phase_at(h.op_index), - ); - for &w in &h.trail { - let (f, l, c) = if attributable { - sites[w] - } else { - ("-", 0, 0) - }; - eprintln!( - " DIRTY_TRAIL wrote op={w} kind={:?} {f}:{l} ctx={c:#010x} phase={}", - ops[w].kind, - phase_at(w), - ); - } - } - // Also report which qubit ids repeat, so a single leaking lane is obvious. - let mut by_q: std::collections::BTreeMap = std::collections::BTreeMap::new(); - for h in &hits { - let e = by_q.entry(h.qubit).or_insert((0, 0)); - e.0 += 1; - e.1 = e.1.max(h.lanes); - } - let mut rows: Vec<_> = by_q.into_iter().collect(); - rows.sort_by(|a, b| b.1 .0.cmp(&a.1 .0)); - for (q, (n, mx)) in rows.into_iter().take(20) { - eprintln!("DIRTY_FREE_Q qubit={q} events={n} max_lanes={mx}"); - } -} diff --git a/src/point_add/emit.rs b/src/point_add/emit.rs index 7c035997..4f977170 100644 --- a/src/point_add/emit.rs +++ b/src/point_add/emit.rs @@ -1,57 +1,57 @@ -use super::*; - -pub(crate) fn emit_inverse(b: &mut B, f: F) { - if b.count_only { - let snap = b.count_snapshot(); - f(b); - let delta = b.count_delta_since(snap); - b.restore_count_snapshot(snap); - add_inverse_count_delta(b, &delta); - return; - } - let start = b.ops.len(); - f(b); - let end = b.ops.len(); - - let fwd: Vec<_> = b.ops[start..end].to_vec(); - b.ops.truncate(start); - emit_inverse_ops_allowing_clean_resets(b, &fwd, "emit_inverse"); -} - -pub(crate) fn add_inverse_count_delta(b: &mut B, delta: &[usize; 18]) { - for kind in [ - OperationType::X, - OperationType::Z, - OperationType::CX, - OperationType::CZ, - OperationType::CCX, - OperationType::CCZ, - OperationType::Swap, - ] { - b.add_counted_kind(kind, delta[kind as usize]); - } -} - -pub(crate) fn emit_inverse_ops_allowing_clean_resets(b: &mut B, fwd: &[Op], context: &'static str) { - for op in fwd.iter().rev().copied() { - match op.kind { - OperationType::X - | OperationType::Z - | OperationType::CX - | OperationType::CZ - | OperationType::CCX - | OperationType::CCZ - | OperationType::Swap => b.push_op(op), - - OperationType::R => {} - - OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - _ => panic!( - "{context}: non-invertible op kind {:?} inside forward block", - op.kind - ), - } - } -} +use super::*; + +pub(crate) fn emit_inverse(b: &mut B, f: F) { + if b.count_only { + let snap = b.count_snapshot(); + f(b); + let delta = b.count_delta_since(snap); + b.restore_count_snapshot(snap); + add_inverse_count_delta(b, &delta); + return; + } + let start = b.ops.len(); + f(b); + let end = b.ops.len(); + + let fwd: Vec<_> = b.ops[start..end].to_vec(); + b.ops.truncate(start); + emit_inverse_ops_allowing_clean_resets(b, &fwd, "emit_inverse"); +} + +pub(crate) fn add_inverse_count_delta(b: &mut B, delta: &[usize; 18]) { + for kind in [ + OperationType::X, + OperationType::Z, + OperationType::CX, + OperationType::CZ, + OperationType::CCX, + OperationType::CCZ, + OperationType::Swap, + ] { + b.add_counted_kind(kind, delta[kind as usize]); + } +} + +pub(crate) fn emit_inverse_ops_allowing_clean_resets(b: &mut B, fwd: &[Op], context: &'static str) { + for op in fwd.iter().rev().copied() { + match op.kind { + OperationType::X + | OperationType::Z + | OperationType::CX + | OperationType::CZ + | OperationType::CCX + | OperationType::CCZ + | OperationType::Swap => b.push_op(op), + + OperationType::R => {} + + OperationType::Register + | OperationType::AppendToRegister + | OperationType::DebugPrint => {} + _ => panic!( + "{context}: non-invertible op kind {:?} inside forward block", + op.kind + ), + } + } +} diff --git a/src/point_add/m60_dead_t10.rs b/src/point_add/m60_dead_t10.rs deleted file mode 100644 index 23fa3438..00000000 --- a/src/point_add/m60_dead_t10.rs +++ /dev/null @@ -1,182 +0,0 @@ -// AUTO-GENERATED — M-60 dead-CCX skip set (dead_t10, 2101 gates). -// Indices into point_add::build()'s POST-fanout op stream (nonce 9000624727621). -// These CCX gates are census-verified never-firing (both controls never simultaneously 1) -// over 1e8 faithful-RNG inputs; removing them is bit-exact. Source: repo-c2b/dead_t10.txt. -pub(crate) const M60_DEAD_T10: [usize; 2101] = [ - 20425, 21846, 296956, 377983, 377992, 378001, 716134, 843456, 1125675, 1202838, 1657109, 1659982, - 1821881, 1824633, 1824653, 1824968, 1866481, 1869210, 1869219, 1984396, 1986970, 1986990, 2089967, 2101714, - 2104185, 2104475, 2145196, 2147656, 2147665, 2202652, 2205031, 2260122, 2288810, 2291127, 2361954, 2499921, - 2529896, 2599031, 2719900, 2721421, 2721430, 3115134, 3167140, 3183210, 3341485, 3396020, 3396678, 3435889, - 3436488, 3436499, 3501624, 3551809, 3591647, 3602906, 3605195, 3628374, 3640539, 3653283, 3665375, 3667150, - 3667663, 3699254, 3699257, 3709930, 3719202, 3728720, 3729027, 3753136, 3753472, 3754489, 3757169, 3757637, - 3757648, 3757990, 3761353, 3761968, 3761990, 3761999, 3762421, 3762426, 3764376, 3773148, 3774431, 3777595, - 3778255, 3778988, 3782744, 3785965, 3789157, 3790963, 3802821, 3807733, 3821984, 3830516, 3832809, 3848623, - 3853398, 3858063, 3870369, 3875445, 3884325, 3889622, 3901659, 3945868, 3950606, 3967483, 3973711, 3985087, - 3989892, 3991652, 3994883, 4030654, 4036034, 4041274, 4052054, 4054030, 4057614, 4064995, 4074161, 4081753, - 4083828, 4085492, 4095280, 4095699, 4100786, 4104766, 4106900, 4107319, 4108616, 4122613, 4123023, 4138544, - 4158998, 4167331, 4179886, 4188245, 4198692, 4201092, 4222907, 4265213, 4274428, 4277017, 4290946, 4300386, - 4314615, 4333779, 4358255, 4378085, 4383048, 4393188, 4398202, 4441719, 4460523, 4465943, 4484268, 4487346, - 4492704, 4509037, 4525546, 4536696, 4559053, 4692818, 4693943, 4695057, 4696160, 4697252, 4698333, 4699403, - 4700462, 4701510, 4702547, 4703573, 4704588, 4705592, 4706585, 4707567, 4708538, 4709498, 4710447, 4711385, - 4712312, 4713228, 4714133, 4715027, 4715910, 4716782, 4717643, 4718493, 4719332, 4720160, 4720977, 4721783, - 4722578, 4723362, 4724135, 4724897, 4725648, 4726388, 4727117, 4727835, 4728542, 4729238, 4729923, 4730597, - 4731260, 4731912, 4732553, 4733183, 4733802, 4734410, 4735007, 4735593, 4736168, 4736732, 4737285, 4737827, - 4738358, 4738878, 4739387, 4739885, 4740372, 4740848, 4741313, 4741767, 4742210, 4742642, 4743063, 4743473, - 4743872, 4744260, 4744637, 4745003, 4745358, 4745702, 4746035, 4746357, 4746668, 4746968, 4751677, 4752580, - 4753033, 4753036, 4753039, 4753042, 4753045, 4753048, 4753051, 4753054, 4753057, 4753060, 4753063, 4753066, - 4753069, 4753072, 4753075, 4753078, 4753081, 4753084, 4753087, 4753090, 4753093, 4753096, 4753099, 4753102, - 4753105, 4753108, 4753111, 4753114, 4753117, 4753120, 4753123, 4753126, 4753129, 4753132, 4753135, 4753138, - 4753141, 4753144, 4753147, 4753150, 4753153, 4753156, 4753159, 4753162, 4753165, 4753168, 4753171, 4753174, - 4753177, 4753180, 4753183, 4753186, 4753189, 4753192, 4753195, 4753198, 4753201, 4753204, 4753207, 4753210, - 4753213, 4753216, 4753219, 4753222, 4753225, 4753228, 4753231, 4753234, 4753237, 4753240, 4753243, 4753246, - 4753249, 4753252, 4753255, 4753258, 4753261, 4753264, 4753267, 4753270, 4753273, 4753276, 4753279, 4753282, - 4753285, 4753288, 4753291, 4753294, 4753297, 4753300, 4753303, 4753306, 4753309, 4753312, 4753315, 4753318, - 4753321, 4753324, 4753327, 4753330, 4753333, 4753336, 4753339, 4753342, 4753345, 4753350, 4753353, 4753356, - 4753359, 4753362, 4753365, 4753368, 4753371, 4753374, 4753377, 4753380, 4753383, 4753386, 4753389, 4753392, - 4753395, 4753398, 4753401, 4753404, 4753407, 4753410, 4753413, 4753416, 4753419, 4753422, 4753425, 4753428, - 4753431, 4753434, 4753437, 4753440, 4753443, 4753446, 4753449, 4753452, 4753455, 4753458, 4753461, 4753464, - 4753467, 4753470, 4753473, 4753476, 4753479, 4753482, 4753485, 4753488, 4753491, 4753494, 4753497, 4753500, - 4753503, 4753506, 4753509, 4753512, 4753515, 4753518, 4753521, 4753524, 4753527, 4753530, 4753533, 4753536, - 4753539, 4753542, 4753545, 4753548, 4753551, 4753554, 4753557, 4753560, 4753563, 4753566, 4753569, 4753572, - 4753575, 4753578, 4753581, 4753584, 4753587, 4753590, 4753593, 4753596, 4753599, 4753602, 4753605, 4753608, - 4753611, 4753614, 4753617, 4753620, 4753623, 4753626, 4753629, 4753632, 4753635, 4753638, 4753641, 4753644, - 4753647, 4753650, 4753653, 4753656, 4753659, 4753662, 4753665, 4754118, 4761807, 4765676, 4767531, 4768988, - 4772756, 4776552, 4778275, 4778728, 4778731, 4778734, 4778737, 4778740, 4778743, 4778746, 4778749, 4778752, - 4778755, 4778758, 4778761, 4778764, 4778767, 4778770, 4778773, 4778776, 4778779, 4778782, 4778785, 4778788, - 4778791, 4778794, 4778797, 4778800, 4778803, 4778806, 4778809, 4778812, 4778815, 4778818, 4778821, 4778824, - 4778827, 4778830, 4778833, 4778836, 4778839, 4778842, 4778845, 4778848, 4778851, 4778854, 4778857, 4778860, - 4778863, 4778866, 4778869, 4778872, 4778875, 4778878, 4778881, 4778884, 4778887, 4778890, 4778893, 4778896, - 4778899, 4778902, 4778905, 4778908, 4778911, 4778914, 4778917, 4778920, 4778923, 4778926, 4778929, 4778932, - 4778935, 4778938, 4778941, 4778944, 4778947, 4778950, 4778953, 4778956, 4778959, 4778962, 4778965, 4778968, - 4778971, 4778974, 4778977, 4778980, 4778983, 4778986, 4778989, 4778992, 4778995, 4778998, 4779001, 4779004, - 4779007, 4779010, 4779013, 4779016, 4779019, 4779022, 4779025, 4779028, 4779031, 4779034, 4779037, 4779040, - 4779044, 4779048, 4779051, 4779054, 4779057, 4779060, 4779063, 4779066, 4779069, 4779072, 4779075, 4779078, - 4779081, 4779084, 4779087, 4779090, 4779093, 4779096, 4779099, 4779102, 4779105, 4779108, 4779111, 4779114, - 4779117, 4779120, 4779123, 4779126, 4779129, 4779132, 4779135, 4779138, 4779141, 4779144, 4779147, 4779150, - 4779153, 4779156, 4779159, 4779162, 4779165, 4779168, 4779171, 4779174, 4779177, 4779180, 4779183, 4779186, - 4779189, 4779192, 4779195, 4779198, 4779201, 4779204, 4779207, 4779210, 4779213, 4779216, 4779219, 4779222, - 4779225, 4779228, 4779231, 4779234, 4779237, 4779240, 4779243, 4779246, 4779249, 4779252, 4779255, 4779258, - 4779261, 4779264, 4779267, 4779270, 4779273, 4779276, 4779279, 4779282, 4779285, 4779288, 4779291, 4779294, - 4779297, 4779300, 4779303, 4779306, 4779309, 4779312, 4779315, 4779318, 4779321, 4779324, 4779327, 4779330, - 4779333, 4779336, 4779339, 4779342, 4779345, 4779348, 4779351, 4779354, 4779357, 4779360, 4779813, 4780717, - 4785522, 4785821, 4786131, 4786452, 4786784, 4787127, 4787481, 4787846, 4788222, 4788609, 4789007, 4789416, - 4789836, 4790267, 4790709, 4791162, 4791626, 4792101, 4792587, 4793084, 4793592, 4794111, 4794641, 4795182, - 4795734, 4796297, 4796871, 4797456, 4798052, 4798659, 4799277, 4799906, 4800546, 4801197, 4801859, 4802532, - 4803216, 4803911, 4804617, 4805334, 4806062, 4806801, 4807551, 4808312, 4809084, 4809867, 4810661, 4811466, - 4812282, 4813109, 4813947, 4814796, 4815656, 4816527, 4817409, 4818302, 4819206, 4820121, 4821047, 4821984, - 4822932, 4823891, 4824861, 4825842, 4826834, 4827837, 4828851, 4829876, 4830912, 4831959, 4833017, 4834086, - 4835166, 4836257, 4837359, 4838472, 4839596, 4906050, 4907175, 4908289, 4909392, 4910484, 4911565, 4912635, - 4913694, 4914742, 4915779, 4916805, 4917820, 4918824, 4919817, 4920799, 4921770, 4922730, 4923679, 4924617, - 4925544, 4926460, 4927365, 4928259, 4929142, 4930014, 4930875, 4931725, 4932564, 4933392, 4934209, 4935015, - 4935810, 4936594, 4937367, 4938129, 4938880, 4939620, 4940349, 4941067, 4941774, 4942470, 4943155, 4943829, - 4944492, 4945144, 4945785, 4946415, 4947034, 4947642, 4948239, 4948825, 4949400, 4949964, 4950517, 4951059, - 4951590, 4952110, 4952619, 4953117, 4953604, 4954080, 4954545, 4954999, 4955442, 4955874, 4956295, 4956705, - 4957104, 4957492, 4957869, 4958235, 4958590, 4958934, 4959267, 4959589, 4959900, 4960200, 4960489, 4964903, - 4965799, 4966249, 4966252, 4966255, 4966258, 4966261, 4966264, 4966267, 4966270, 4966273, 4966276, 4966279, - 4966282, 4966285, 4966288, 4966291, 4966294, 4966297, 4966300, 4966303, 4966306, 4966309, 4966312, 4966315, - 4966318, 4966321, 4966324, 4966327, 4966330, 4966333, 4966336, 4966339, 4966342, 4966345, 4966348, 4966351, - 4966354, 4966357, 4966360, 4966363, 4966366, 4966369, 4966372, 4966375, 4966378, 4966381, 4966384, 4966387, - 4966390, 4966393, 4966396, 4966399, 4966402, 4966405, 4966408, 4966411, 4966414, 4966417, 4966420, 4966423, - 4966426, 4966429, 4966432, 4966435, 4966438, 4966441, 4966444, 4966447, 4966450, 4966453, 4966456, 4966459, - 4966462, 4966465, 4966468, 4966471, 4966474, 4966477, 4966480, 4966483, 4966486, 4966489, 4966492, 4966495, - 4966498, 4966501, 4966504, 4966507, 4966510, 4966513, 4966516, 4966519, 4966522, 4966525, 4966528, 4966531, - 4966534, 4966537, 4966540, 4966543, 4966546, 4966549, 4966552, 4966555, 4966558, 4966563, 4966566, 4966569, - 4966572, 4966575, 4966578, 4966581, 4966584, 4966587, 4966590, 4966593, 4966596, 4966599, 4966602, 4966605, - 4966608, 4966611, 4966614, 4966617, 4966620, 4966623, 4966626, 4966629, 4966632, 4966635, 4966638, 4966641, - 4966644, 4966647, 4966650, 4966653, 4966656, 4966659, 4966662, 4966665, 4966668, 4966671, 4966674, 4966677, - 4966680, 4966683, 4966686, 4966689, 4966692, 4966695, 4966698, 4966701, 4966704, 4966707, 4966710, 4966713, - 4966716, 4966719, 4966722, 4966725, 4966728, 4966731, 4966734, 4966737, 4966740, 4966743, 4966746, 4966749, - 4966752, 4966755, 4966758, 4966761, 4966764, 4966767, 4966770, 4966773, 4966776, 4966779, 4966782, 4966785, - 4966788, 4966791, 4966794, 4966797, 4966800, 4966803, 4966806, 4966809, 4966812, 4966815, 4966818, 4966821, - 4966824, 4966827, 4966830, 4966833, 4966836, 4966839, 4966842, 4966845, 4966848, 4966851, 4966854, 4966857, - 4966860, 4966863, 4966866, 4966869, 4966872, 4966875, 4967325, 4978588, 4981805, 4985571, 4988881, 4990506, - 4992081, 4993709, 4994159, 4994162, 4994165, 4994168, 4994171, 4994174, 4994177, 4994180, 4994183, 4994186, - 4994189, 4994192, 4994195, 4994198, 4994201, 4994204, 4994207, 4994210, 4994213, 4994216, 4994219, 4994222, - 4994225, 4994228, 4994231, 4994234, 4994237, 4994240, 4994243, 4994246, 4994249, 4994252, 4994255, 4994258, - 4994261, 4994264, 4994267, 4994270, 4994273, 4994276, 4994279, 4994282, 4994285, 4994288, 4994291, 4994294, - 4994297, 4994300, 4994303, 4994306, 4994309, 4994312, 4994315, 4994318, 4994321, 4994324, 4994327, 4994330, - 4994333, 4994336, 4994339, 4994342, 4994345, 4994348, 4994351, 4994354, 4994357, 4994360, 4994363, 4994366, - 4994369, 4994372, 4994375, 4994378, 4994381, 4994384, 4994387, 4994390, 4994393, 4994396, 4994399, 4994402, - 4994405, 4994408, 4994411, 4994414, 4994417, 4994420, 4994423, 4994426, 4994429, 4994432, 4994435, 4994438, - 4994441, 4994444, 4994447, 4994450, 4994453, 4994456, 4994459, 4994462, 4994465, 4994468, 4994472, 4994476, - 4994479, 4994482, 4994485, 4994488, 4994491, 4994494, 4994497, 4994500, 4994503, 4994506, 4994509, 4994512, - 4994515, 4994518, 4994521, 4994524, 4994527, 4994530, 4994533, 4994536, 4994539, 4994542, 4994545, 4994548, - 4994551, 4994554, 4994557, 4994560, 4994563, 4994566, 4994569, 4994572, 4994575, 4994578, 4994581, 4994584, - 4994587, 4994590, 4994593, 4994596, 4994599, 4994602, 4994605, 4994608, 4994611, 4994614, 4994617, 4994620, - 4994623, 4994626, 4994629, 4994632, 4994635, 4994638, 4994641, 4994644, 4994647, 4994650, 4994653, 4994656, - 4994659, 4994662, 4994665, 4994668, 4994671, 4994674, 4994677, 4994680, 4994683, 4994686, 4994689, 4994692, - 4994695, 4994698, 4994701, 4994704, 4994707, 4994710, 4994713, 4994716, 4994719, 4994722, 4994725, 4994728, - 4994731, 4994734, 4994737, 4994740, 4994743, 4994746, 4994749, 4994752, 4994755, 4994758, 4994761, 4994764, - 4994767, 4994770, 4994773, 4994776, 4994779, 4994782, 4994785, 4995235, 4996132, 5000642, 5000930, 5001229, - 5001539, 5001860, 5002192, 5002535, 5002889, 5003254, 5003630, 5004017, 5004415, 5004824, 5005244, 5005675, - 5006117, 5006570, 5007034, 5007509, 5007995, 5008492, 5009000, 5009519, 5010049, 5010590, 5011142, 5011705, - 5012279, 5012864, 5013460, 5014067, 5014685, 5015314, 5015954, 5016605, 5017267, 5017940, 5018624, 5019319, - 5020025, 5020742, 5021470, 5022209, 5022959, 5023720, 5024492, 5025275, 5026069, 5026874, 5027690, 5028517, - 5029355, 5030204, 5031064, 5031935, 5032817, 5033710, 5034614, 5035529, 5036455, 5037392, 5038340, 5039299, - 5040269, 5041250, 5042242, 5043245, 5044259, 5045284, 5046320, 5047367, 5048425, 5049494, 5050574, 5051665, - 5052767, 5053880, 5055004, 5122279, 5123382, 5124474, 5125555, 5126625, 5127684, 5128732, 5129769, 5130795, - 5131810, 5132814, 5133807, 5134789, 5135760, 5136720, 5137669, 5138607, 5139534, 5140450, 5141355, 5142249, - 5143132, 5144004, 5144865, 5145715, 5146554, 5147382, 5148199, 5149005, 5149800, 5150584, 5151357, 5152119, - 5152870, 5153610, 5154339, 5155057, 5155764, 5156460, 5157145, 5157819, 5158482, 5159134, 5159775, 5160405, - 5161024, 5161632, 5162229, 5162815, 5163390, 5163954, 5164507, 5165049, 5165580, 5166100, 5166609, 5167107, - 5167594, 5168070, 5168535, 5168989, 5169432, 5169864, 5170285, 5170695, 5171094, 5171482, 5171859, 5172225, - 5172580, 5172924, 5173257, 5173579, 5173890, 5174190, 5174479, 5178893, 5179789, 5180239, 5180242, 5180245, - 5180248, 5180251, 5180254, 5180257, 5180260, 5180263, 5180266, 5180269, 5180272, 5180275, 5180278, 5180281, - 5180284, 5180287, 5180290, 5180293, 5180296, 5180299, 5180302, 5180305, 5180308, 5180311, 5180314, 5180317, - 5180320, 5180323, 5180326, 5180329, 5180332, 5180335, 5180338, 5180341, 5180344, 5180347, 5180350, 5180353, - 5180356, 5180359, 5180362, 5180365, 5180368, 5180371, 5180374, 5180377, 5180380, 5180383, 5180386, 5180389, - 5180392, 5180395, 5180398, 5180401, 5180404, 5180407, 5180410, 5180413, 5180416, 5180419, 5180422, 5180425, - 5180428, 5180431, 5180434, 5180437, 5180440, 5180443, 5180446, 5180449, 5180452, 5180455, 5180458, 5180461, - 5180464, 5180467, 5180470, 5180473, 5180476, 5180479, 5180482, 5180485, 5180488, 5180491, 5180494, 5180497, - 5180500, 5180503, 5180506, 5180509, 5180512, 5180515, 5180518, 5180521, 5180524, 5180527, 5180530, 5180533, - 5180536, 5180539, 5180542, 5180545, 5180548, 5180553, 5180556, 5180559, 5180562, 5180565, 5180568, 5180571, - 5180574, 5180577, 5180580, 5180583, 5180586, 5180589, 5180592, 5180595, 5180598, 5180601, 5180604, 5180607, - 5180610, 5180613, 5180616, 5180619, 5180622, 5180625, 5180628, 5180631, 5180634, 5180637, 5180640, 5180643, - 5180646, 5180649, 5180652, 5180655, 5180658, 5180661, 5180664, 5180667, 5180670, 5180673, 5180676, 5180679, - 5180682, 5180685, 5180688, 5180691, 5180694, 5180697, 5180700, 5180703, 5180706, 5180709, 5180712, 5180715, - 5180718, 5180721, 5180724, 5180727, 5180730, 5180733, 5180736, 5180739, 5180742, 5180745, 5180748, 5180751, - 5180754, 5180757, 5180760, 5180763, 5180766, 5180769, 5180772, 5180775, 5180778, 5180781, 5180784, 5180787, - 5180790, 5180793, 5180796, 5180799, 5180802, 5180805, 5180808, 5180811, 5180814, 5180817, 5180820, 5180823, - 5180826, 5180829, 5180832, 5180835, 5180838, 5180841, 5180844, 5180847, 5180850, 5180853, 5180856, 5180859, - 5180862, 5180865, 5181315, 5187784, 5191003, 5194771, 5198079, 5201271, 5259036, 5259486, 5259489, 5259492, - 5259495, 5259498, 5259501, 5259504, 5259507, 5259510, 5259513, 5259516, 5259519, 5259522, 5259525, 5259528, - 5259531, 5259534, 5259537, 5259540, 5259543, 5259546, 5259549, 5259552, 5259555, 5259558, 5259561, 5259564, - 5259567, 5259570, 5259573, 5259576, 5259579, 5259582, 5259585, 5259588, 5259591, 5259594, 5259597, 5259600, - 5259603, 5259606, 5259609, 5259612, 5259615, 5259618, 5259621, 5259624, 5259627, 5259630, 5259633, 5259636, - 5259639, 5259642, 5259645, 5259648, 5259651, 5259654, 5259657, 5259660, 5259663, 5259666, 5259669, 5259672, - 5259675, 5259678, 5259681, 5259684, 5259687, 5259690, 5259693, 5259696, 5259699, 5259702, 5259705, 5259708, - 5259711, 5259714, 5259717, 5259720, 5259723, 5259726, 5259729, 5259732, 5259735, 5259738, 5259741, 5259744, - 5259747, 5259750, 5259753, 5259756, 5259759, 5259762, 5259765, 5259768, 5259771, 5259774, 5259777, 5259780, - 5259783, 5259786, 5259789, 5259792, 5259795, 5259799, 5259803, 5259806, 5259809, 5259812, 5259815, 5259818, - 5259821, 5259824, 5259827, 5259830, 5259833, 5259836, 5259839, 5259842, 5259845, 5259848, 5259851, 5259854, - 5259857, 5259860, 5259863, 5259866, 5259869, 5259872, 5259875, 5259878, 5259881, 5259884, 5259887, 5259890, - 5259893, 5259896, 5259899, 5259902, 5259905, 5259908, 5259911, 5259914, 5259917, 5259920, 5259923, 5259926, - 5259929, 5259932, 5259935, 5259938, 5259941, 5259944, 5259947, 5259950, 5259953, 5259956, 5259959, 5259962, - 5259965, 5259968, 5259971, 5259974, 5259977, 5259980, 5259983, 5259986, 5259989, 5259992, 5259995, 5259998, - 5260001, 5260004, 5260007, 5260010, 5260013, 5260016, 5260019, 5260022, 5260025, 5260028, 5260031, 5260034, - 5260037, 5260040, 5260043, 5260046, 5260049, 5260052, 5260055, 5260058, 5260061, 5260064, 5260067, 5260070, - 5260073, 5260076, 5260079, 5260082, 5260085, 5260088, 5260091, 5260094, 5260097, 5260100, 5260103, 5260106, - 5260109, 5260112, 5260562, 5261459, 5265969, 5266257, 5266556, 5266866, 5267187, 5267519, 5267862, 5268216, - 5268581, 5268957, 5269344, 5269742, 5270151, 5270571, 5271002, 5271444, 5271897, 5272361, 5272836, 5273322, - 5273819, 5274327, 5274846, 5275376, 5275917, 5276469, 5277032, 5277606, 5278191, 5278787, 5279394, 5280012, - 5280641, 5281281, 5281932, 5282594, 5283267, 5283951, 5284646, 5285352, 5286069, 5286797, 5287536, 5288286, - 5289047, 5289819, 5290602, 5291396, 5292201, 5293017, 5293844, 5294682, 5295531, 5296391, 5297262, 5298144, - 5299037, 5299941, 5300856, 5301782, 5302719, 5303667, 5304626, 5305596, 5306577, 5307569, 5308572, 5309586, - 5310611, 5311647, 5312694, 5313752, 5314821, 5315901, 5316992, 5318094, 5470876, 5473168, 5473190, 5508538, - 5508547, 5624358, 5626461, 5626472, 5735373, 5786891, 5788755, 5812342, 5907991, 5909693, 5941216, 5942863, - 5942874, 6030578, 6050099, 6051520, 6083398, 6127830, 6143842, 6145043, 6260958, 6261661, 6261672, 6266791, - 6267426, 6267437, 6272213, 6272780, 6272791, 6280875, 6283457, 6283814, 6289701, 6290398, 6290401, 6290463, - 6290923, 6298244, 6298615, 6300832, 6323102, 6323105, 6341818, 6344840, 6344867, 6345910, 6352203, 6355109, - 6355297, 6363262, 6366334, 6389343, 6397815, 6400676, 6401190, 6401195, 6437660, 6437758, 6492758, 6521732, - 6546581, 6571123, 6582771, 6582793, 6583360, 6669822, 6670849, 6943620, 6949197, 6962470, 7027427, 7089178, - 7090523, 7101588, 7101597, 7102945, 7114211, 7240246, 7240255, 7241347, 7266786, 7278320, 7278329, 7279454, - 7290979, 7290988, 7292090, 7304990, 7356098, 7537487, 7562208, 7563527, 7589857, 7616206, 7682235, 7762490, - 7776008, 7801167, 7801176, 7802683, 7830187, 7937118, 7937127, 7950763, 7966058, 7978486, 7991841, 7991845, - 7991854, 7991863, 7992169, 8005569, 8021068, 8034748, 8048417, 8074623, 8076049, 8143636, 8143645, 8145445, - 8157475, 8157495, 8187111, 8199175, 8199184, 8199544, 8200996, 8227450, 8228904, 8241371, 8254937, 8284784, - 8285194, 8312813, 8324950, 8326768, 8340728, 8354864, 8411161, 8423367, 8425205, 8439433, 8453506, 8467586, - 8481860, 8495979, 8524403, 8609896, 8622203, 8638383, 8681415, 8695890, 8739060, 8767794, 8811147, 8881745, - 8883771, 8927494, 8942015, 8954676, 8983794, 8985845, 9042463, 9057111, 9057120, 9059206, 9101249, 9103354, - 9160209, 9160218, 9368654, 9400912, 9461040, 9473817, 9473826, 9506320, 9564559, 9566824, 9612397, 9755957, - 9757276, -]; diff --git a/src/point_add/memory/01-architecture.md b/src/point_add/memory/01-architecture.md deleted file mode 100644 index 26bd8079..00000000 --- a/src/point_add/memory/01-architecture.md +++ /dev/null @@ -1,101 +0,0 @@ -# Architecture, from first principles - -Everything here is measured against the shipped circuit unless marked [INFERENCE]. - -## Layer 1 — the algorithm. Two inversions is a hard floor. - -`trailmix_ludicrous/ec_add.rs::ec_add` is Roetteler-style in-place affine addition: - -``` -x -= x0 ; y -= y0 -lambda <- y/x ModDiv (Direction::Inverse) -x += 3*x0 -x -= lambda^2 modular square -y <- lambda * x ModDiv reversed (Direction::Forward) -y -= y0 ; x <- x0 - x -``` - -The second "multiply" is a **division circuit run backwards**. In-place multiplication by a *quantum* value -`|λ⟩|x⟩ → |λx⟩|x⟩` is a permutation only because x ≠ 0, and realising it requires the division machinery — you cannot -erase λ without dividing. And you cannot avoid erasing it: after `(t_x,t_y)` are overwritten by `(R_x,R_y)`, recovering -`dx` needs to invert `R_x − Q_x`. - -Priced alternatives, all losing: - -| approach | cost | why dead | -|---|---|---| -| Fermat, `x^(p-2)` | ~134M CCX | 255 squarings + ~15 muls | -| Jacobian coordinates | ~5.5M CCX | no peak reduction either, and affine in/out forces a final inversion | -| Montgomery batch-invert both | n/a | data-dependent: `c = Qx − Rx` only exists AFTER Rx, which needs the first inverse | -| one-inversion point-add | n/a | `ONE_INV_DX3_AFFINE_PA_BLOCKER` — needs a second inversion to recover dx | -| Kim inversion drop-in | 2,530,240 T @ 4,102 q | dead for a ~1200q target | - -## Layer 2 — the inversion - -**Jump-2 binary extended Euclid (Stein/Kaliski), NOT Bernstein–Yang.** `schedule.rs`: `ITERS=258`, `JUMP=2`. - -Per iteration (`gcd.rs:1162-1305`): truncate u,v to `SCHED_J2[i]`; right-shift v (unconditional for i>0, conditional on -`t1` at i=0); `s2 = (v now even)` and if so shift again; `subtracted = v[0]`; `swp = subtracted AND -truncated_lt(v,u,cmp_window(i))`; if swp swap u,v; if subtracted `v -= u`. A 3-bit symbol `(subtracted, swp, s2)` goes -to the dialog tape. - -**Only 5 of 8 symbols are reachable**, and the constraint is structural: `s2=0 ⇒ subtracted=1` (if no second halving -happened, v[0] was 1), and `subtracted=0 ⇒ swp=0` (swp is ANDed with subtracted). - -The preserved invariant is bilinear: -``` -u*X + v*Y == num*den (mod p) -seed (u,v,X,Y) = (p, den, 0, num) final (1, 0, R, 0) -``` -The walk applies `M = L·S·D` with `D = diag(1, 2^-(1+s2))`; the apply applies `M^-T`, whose `D^-T = diag(1, 2^(1+s2))` -IS the 1+s2 doublings. **So the s2 conditionality is load-bearing on both sides** — drop it on either and the pairing -slips by a data-dependent `2^-z`. - -Bernstein–Yang would be *worse*: its proven 256-bit bounds are 590 (hddivstep) / 741 (divstep) against the 516 -divsteps here. The gap to the literature is negative. - -## Layer 3 — the qubit budget - -``` -peak = 512 (Bezout pair) + tape(i) + u(i) + v(i) + ~22 ancilla -``` -Measured with the built-in B0 owner map (`B0_WIN_LO`/`B0_WIN_HI`, mod.rs:392-419) at the binding op 25841, divstep i=0: - -| n | site | role | -|---|---|---| -| 256 | `trailmix_ludicrous/mod.rs:363` `y2` | Bezout accumulator X | -| 256 | `gcd.rs:1842` `tmp` | Bezout numerator Y | -| 255 | `mod.rs:362` `v` | divstep g — 255 because `v[0]≡0` is parked+loaned | -| 255 | `gcd.rs:1138` `u` | divstep f — 255 because `u[0]≡1` is parked+loaned | -| 124 | `gidney.rs:1186` `inner` | clean-carry ladder, BORROWED, fills to the cap | -| 2 | `gidney.rs:1546` `cy` | chunk-boundary carries | -| 4 | gcd.rs:1146/1148/1149/1203 | subtracted, s2, t1, swap_flag | -| **1152** | | | - -**Why the peak is a flat plateau, not a spike**: `u+v` shrink at 2 qubits/step (SCHED_J2) while the tape grows at -2.333 bits/step. Net +0.33/step. The two curves nearly cancel, which is exactly what makes this circuit hard to -improve — there is no single fat moment to attack. - -Tape = `dialog_tape_qubits(85,258)` = 2 + 7·85 + 5 = **602** (codec.rs:304-311, 444-474). - -## Layer 4 — the Toffoli budget by primitive - -Total emitted at the old head: 1,394,540 CCX + 5,341 CCZ. - -| bucket | CCX | % | -|---|---|---| -| adders (GCD 300,164 + apply register 365,491) | 665,655 | 47.7 | -| controlled permutation (apply cswap 131,328 + apply fold 132,612 + GCD cswap 140,780 + GCD cond shift 141,249) | 545,969 | 39.2 | -| modular reductions | ~70,490 | 5.1 | -| square | 60,545 | 4.3 | -| comparators | ~41,500 | 3.0 | -| codec | 6,304 | 0.5 | - -**The emitted→executed discount is NOT uniform.** Measured with a purpose-built profiler (`TRACE_TLM_TOF=1`): -apply register phases 13.7%, `mod_add_clean` exactly 50%, and **0.000%** on swap / gcd_forward_compare / -gcd_forward_shift / square_*_build. Anything inside a `push_condition(hmr_bit)` executes on half the shots. -Never compare an emitted delta against the executed baseline. - -## Layer 5 — λ, the axis that isn't in the score - -See `notes/02-lambda.md`. This is the one that actually decides what ships. diff --git a/src/point_add/memory/02-lambda.md b/src/point_add/memory/02-lambda.md deleted file mode 100644 index 79ed03f0..00000000 --- a/src/point_add/memory/02-lambda.md +++ /dev/null @@ -1,98 +0,0 @@ -# λ — the hidden third axis - -## The setup - -`apply_tail_nonce` (mod.rs:1714-1726) asserts the last 96 ops are all `X` and rewrites **only `q_target`** on 48 -adjacent `X;X` identity pairs. So the circuit FUNCTION is provably identical for all 2^48 nonces. Only the SHAKE256 -Fiat–Shamir seed moves, and with it the 9024 test inputs. - -That makes the nonce a clean experimental handle: vary it and you resample the test set from the same circuit. - -## The measurement (n=700, full 9024 shots each) - -| statistic | classical | phase-garbage batches | -|---|---|---| -| mean | 18.127 | 12.636 | -| variance | 18.094 | 11.054 | -| var/mean | **0.998** | — | -| range | 8..30 | 4..23 | -| runs with zero | **0 / 700** | **0 / 700** | - -var/mean = 0.998 is textbook Poisson with zero overdispersion, which independently proves the per-shot failure -probability is identical at every nonce — i.e. the circuit really is nonce-invariant, and this is intrinsic error, not -overfitting. - -Pearson ρ(cm,pg) = 0.5205. Fitting on conditional means `E[pg|cm]` in bins cm=11..23 (20–69 nonces per bin, no -extrapolation) discriminates decisively between two generative models: - -- **A** "phase ⊂ classical" (forces pg=0 when cm=0): SSE **13.37**, residuals systematically curved, and cannot reach - the observed ρ at any parameter (best fit 0.835 vs observed 0.5205). -- **B** "phase-only failures exist": SSE **2.44**. Fitted λ_classical_only 10.05, λ_both 8.08, λ_phase_only 5.16. - -$$\lambda_{\text{total}} = 23.29 \quad\Rightarrow\quad P(\text{clean seed}) = e^{-23.29} = 7.7\times10^{-11}$$ - -**The phase channel alone costs 175×** and almost every estimate in circulation quotes `e^-(classical mean)`. - -## What this means - -The old head computes a **wrong point addition roughly once per 1,100 inversions**. It ships because a lucky seed was -found once and carried forward, with each subsequent submission accepted only if it kept that seed clean. - -So the real objective is: - -> **minimise score subject to λ small enough to grind** - -and λ is exponentially leveraged: every 1.0 removed multiplies grind yield by *e*. - -## Where λ comes from (classical channel, modelled to 88%) - -Exact classical emulation of the whole ModDiv incl. the Bezout apply, 6e6 samples, per 9024 shots: - -| source | mm | -|---|---| -| divstep convergence tail (ITERS=258 vs ~270 needed) | 5.73 | -| i=257 apply skips (ADD_SKIP_LASTK / S2_ZERO / FWD_CSWAP) | 5.30 | -| SCHED_J2 drops a nonzero bit, walk still terminates | 2.80 | -| LSBS=53 fold-window carry escapes | 2.18 | -| **model total** | **16.01** | -| observed (n=700) | 18.13 | - -Residual ~2.1 is the square / non-ModDiv point arithmetic. - -ITERS tail curve (1e6-sample convergence distribution), mm per 9024: -`258→5.228, 259→2.453, 260→1.114, 261→0.483, 262→0.200, 265→0.014`. Steep — the first extra iteration is worth a lot -and the seventh is worth nothing. Cost ≈ 2,930 emitted CCX per iteration, dominated by the apply side (256-bit, -width-independent, so it does NOT get cheaper at the tail). - -## Traps - -- **`ancilla-garbage = 0` is guaranteed by construction, not evidence.** `B::free` (mod.rs:495) emits an unconditional - `R`; per sim.rs:149-154 an `R` on a non-|0⟩ qubit flips that shot's phase with p=½ and force-zeroes the qubit with the - outcome DISCARDED. So no qubit can be dirty at the end and that channel cannot fire. Every would-be ancilla failure - is laundered into half a phase failure. -- **"Every phase failure is a dirty free" is FALSE.** A census-dropped CCZ that no longer cancels gives phase garbage - on every batch with ZERO dirty resets. Audit the phase word directly. -- **Don't price a truncation site by `2^-w` alone.** MSBS=19 looks like `9024 × 516 × 2^-19 = 8.9` mismatches; measured - effect of switching the site fully off (w=48) is **zero**. Three factor-of-two discounts: a top-w tie only means the - low bits decide (½), the correction is gated on `subtracted` (¾), and the block sits inside `push_condition(hmr_bit)` - (½). It is also an hmr-uncompute feeding a CZ, so it can only ever produce a *phase* error. - -## Triage rule (use this constantly) - -| full-9024 result | meaning | -|---|---| -| ~9024 classical | positional desync — a sequentially-addressed table shifted | -| thousands but not 9024 | a repointed gate-DROP table | -| low tens (10–30) | **the intrinsic band. Expected. Not a bug.** | -| saturated 141/141 phase, normal classical | bad phase-correction predicate, or a deleted live gate | -| 0/0/0 | you are on a ground seed | - -## Statistics discipline - -Per-nonce sd is 4.25. **n=1 cannot distinguish Δλ=+7 from Δλ=0.** A reserve retune measured at n=1 as -"cm 19, intrinsic, safe" was **+7.24 λ at n=12** (individual draws 19,21,22,23,23,24,25,27,28,29,31,32 — the first two -sit inside the baseline range). Use n≥12, paired on the same nonce set, and quote a sigma. - -Also: avg-executed-Toffoli varies across nonces with sd 13.4 (n=700, span 86). So a single-nonce Toffoli comparison -gates at ~40, not 20. This does NOT gate qubit work (1 qubit = 1152 ppm ≈ 2600× the noise) nor deterministic gate -deletion (verify those by gate count). diff --git a/src/point_add/memory/03-proven-floors.md b/src/point_add/memory/03-proven-floors.md deleted file mode 100644 index 80fb8b24..00000000 --- a/src/point_add/memory/03-proven-floors.md +++ /dev/null @@ -1,109 +0,0 @@ -# Proven floors — where the headroom is NOT - -Each of these is a proof or an exact enumeration, not a failed search. Do not re-mine them. - -## Controlled-permutation bucket — 545,969 CCX (39.2%) — CLOSED - -Every item in the bucket is a **controlled GF(2)-linear map**: cswap ladders, cyclic shifts, conditional doubling -(shift + Solinas fold). Track, per wire, the bilinear `c(x)·v` component of its polynomial. CNOT/X move it linearly, -CCZ is diagonal so contributes nothing, and **each Toffoli adds at most ONE new vector to the span**. Therefore - -$$\#\text{Toffoli} \;\ge\; \operatorname{rank}(M \oplus I)$$ - -over the reachable subspace. Ancillas — clean or dirty — do not lower the bound. - -| item | floor | emitted | -|---|---|---| -| apply cswap | 256 | 256 | -| GCD cswap | n−1 | n−1 | -| GCD conditional shift | n−2 | **n−1** ← the only slack | -| apply conditional double | 256 | 256 | - -Exactly **68 gates** in the whole bucket were removable (conditioned on ctrl=1 both `v[0]` and `v[w-1]` are zero, so -the last Fredkin swaps two zeros). Taken. That is the entire prize. - -Related: the free-vs-conditional asymmetry is not an implementation artefact. An unconditional right shift is pure -SWAP relabelling and SWAP is Clifford, hence free in this cost model; a controlled n-cycle provably costs n−1 Toffoli. -That is the price of conditionality on a linear map and it is unavoidable. - -## Adder bucket — 665,655 CCX (47.7%) — at best-known - -Multiplicative complexity: each Toffoli contributes at most one AND to the ANF, so #CCX ≥ MC. - -1. **Uncontrolled n-bit add**: `deg(c_{n-1}) = n`, so MC ≥ n−1. Achieved by `MAJ(x,y,c) = c ⊕ (x⊕c)(y⊕c)`, one AND per - carry, Gidney temporary-AND erasure free. **Floor n−1, TIGHT, 1.00 CCX/bit.** -2. **Controlled add** `y += t·x`: two independent bounds both give n (degree, and a bilinear-rank argument on the - restriction y=0 where the function becomes the n-fold fan-out `t·x_i`). Best known is **2n** — Gidney 2018, - *Halving the cost of quantum addition*, 8n+O(1) T. Both natural decompositions land on 2n−1 and neither improves, - because the carry-recursion gates all have zero degree-2 contribution and are necessarily disjoint from the n gates - the rank bound forces. **Proven floor n, achieved 2n, factor-2 gap OPEN — that is a publishable result, not an - engineering task.** -3. **Controlled modular add mod p**: for a CLASSICAL addend the required degree-2 forms are linear, so the rank bound - gives zero and only the carry recursion is nonlinear → floor ~n−1, half the quantum-addend case. This is why the - Solinas fold is cheap. - -Measured: GCD body **1.971 CCX/bit** = 2n, already at it. The apply register phase ran 2.767 CCX/bit because it took -the chunked path; that gap is what we took. - -**Why 2n is unreachable at k **Standing rule: a null result is only a result if `md5 ops.bin` changed.** Pristine head md5 was -> `7c79628f5d19664ebead263860b04ce1`. Six seconds, and it would have caught two of my own runs. - -## 2. Positional addressing, at two levels - -**Level 1 — the eight schedule vectors.** `load_schedule` (trailmix_ludicrous/mod.rs:261-306) loads flat vectors and -every consumer pulls the next value with `step()` (mod.rs:127-131) — a bare sequential pop. Values are addressed **by -position in the dynamic consumption order**, not by call identity. - -Exact position formulas, verified against 5,807 traced consumptions, zero exceptions: -``` -ord(pass,i) = i for passes 0,2 (forward) ; 257-i for passes 1,3 (reverse) -pass order = 0 inverse-fwd, 1 inverse-rev, 2 multiply-fwd, 3 multiply-rev -GCD_SUB_K[1032] = GCD_BRANCH[1032] = pass*258 + ord -CMP_K[1028] = pass*257 + (i-1 even | 257-i odd) -APPLY_COUT_K[516] = dir*258 + ord -FOLD_SCHED[514] = dir*257 + (i-1 | 257-i) -FFG_G[516] = dir==0 ? i : 257+(257-i) # stride 257; slot 515 never read -HYB_V[1558] = NOT a (pass,i) function; 1170 reads, passes 0 and 3 only, i<=201 -SQ_ROW_K[512] = zero reads under the shipped knob set (TLM_SQUARE_ADDSUB_SKIP_C=1 revives it) -``` - -**Level 2 — the ~30 gate-DROPPING predicates**, keyed by bare incrementing call counters plus ordinal-keyed strips. -This is the dangerous one: a desynced *schedule* value gives a wrong width, but a desynced *drop* table **silently -deletes a live Toffoli**. Deleted live gate → qubit dirty at its `free()` → unconditional `R` → phase flip with p=½, -outcome discarded, uncorrectable. Hence saturated 141/141 phase-garbage with a normal-looking classical count. - -The **occupancy tripwire** now in `deep_strip_keys.rs` fixes the ordinal-keyed strip: each key records how often its -operand tuple occurred at census time, and any key whose occupancy moved is discarded with a warning instead of -applied. Build log line to watch: `"... ; N stale keys skipped"`. N > 0 means re-mine. - -## 3. Inert knobs worth knowing (measured, all byte-identical) - -- `HYB_V` values touch **no gate**. With `TLM_DIRECT_VARCHUNK=1` (shipped) `gidney.rs:1780-1795` passes `hi - lo` to - the adder and the fit value only feeds a trace. All 1170 reads set to 0, and to 999, both give emitted CCX 1394540 - exactly. What IS lethal is the varchunk **segment count**, which drives the threaded-add call counter. -- `GCD_BRANCH` is read 1032 times and **ignored** — `TLM_GCD_RESELECT_LAYOUT=1` (mod.rs:2163) diverts first. -- `COUT_K` has zero slack: all 514 calls have effective == headroom exactly, local_peak == 1152 exactly. -- `GCD_SUB_K` is 100% clamped by live headroom — `TLM_GCD_K_ADJUST` in {0,40,120} gives a byte-identical ops.bin. -- Three drop flags are exact no-ops at 0 CCX: `TLM_ADD_CONST_SKIP_STRUCTURAL_DEAD_CARRIES`, - `TLM_GCD_SKIP_EXACT_FORWARD_CSWAPS`, `TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ`. -- `gidney.rs:1052` never fires; `square.rs:84 add_into` unreachable under the shipped knob set. - -## 4. The nonce-screen trap - -If you write your own screen: **draw all 9024 test pairs BEFORE simulating.** Drawing them lazily one pass at a time -from the same XOF the simulator consumes means that after the first pass your input draw reads bytes the simulator -already advanced past. The resulting points are still valid curve points, just not the harness's — and the circuit -computes valid inputs *correctly*, so they never mismatch and your screen reports false `classical=0`. Cost me a -1,344-vCPU grind. - -Also: classical outcomes ARE insensitive to both the value and the consumption order of the Hmr/R stream (measured -identical at W=1024 and W=1 on four nonces). **Phase and avgT are NOT** — avgT counts `cond.count_ones()` and `cond` -depends on Hmr-derived bits, so avgT must only ever be read from a W=64 harness-order run. - -## 5. Tree divergence - -`ecbox:~/ec-NAME` can silently diverge from `/tmp/ec-NAME`. An `ecwork build` rsyncs local→remote with `--delete`, so -it will happily overwrite a remote-generated artifact (e.g. a freshly mined census table) with a stale local copy and -break the circuit in a way that looks like a logic bug. Always re-check `md5 ops.bin` on the box after a sync. - -## 6. Validation gates, ranked - -| gate | strength | needs a nonce? | -|---|---|---| -| `eval_circuit`'s printed qubit count (a max-ID scan, circuit.rs:348-363, printed BEFORE the tests) | weak but always available — even a 9024/9024 run reports it | no | -| byte-identical `ops.bin` vs pristine | proves nothing desynced | no | -| `TLM_STRADDLE_VERIFY=n` — runs pre/post streams side by side off ONE shared Shake256, comparing every qubit, every classical bit AND the phase word | proves a rewrite is bit-exact | no | -| `dirtyscan` — one 64-lane batch, flags every `R` on a non-|0⟩ target, self-asserts against the frozen simulator | deterministic phase audit, ~45 s | no | -| full 9024 `eval_circuit` | the only thing that ships | yes | - -**Per-phase CCX equality is NOT a soundness certificate.** Two circuits can agree on every phase total and differ in -gate identity — same count, different operands, or an index-keyed drop table deleting a different set of the same size. diff --git a/src/point_add/memory/05-qubit-reduction.md b/src/point_add/memory/05-qubit-reduction.md deleted file mode 100644 index 973ec38a..00000000 --- a/src/point_add/memory/05-qubit-reduction.md +++ /dev/null @@ -1,132 +0,0 @@ -# Reducing peak qubits — measured, session 2 - -Goal: 2–3 qubits from first principles. Baseline is the promoted head `02146ca`: -**1153 qubits × 1,309,147 executed Toffoli = 1,509,446,491**. - -Break-even: 1 qubit = 1,309,147 / 1153 = **1,135 executed Toffoli** ≈ **1,188 emitted** (executed/emitted = 0.9556). - -## Step 1 — locate the peak exactly - -The 1153 peak is a **spike, not a plateau**, confined to three fold phases; everything else is ≤1152: - -``` -tlm_apply_inverse_mod_sub_fold 782 samples peak op 3454853 -tlm_apply_inverse_fold 227 -tlm_apply_forward_fold 117 -``` - -B0 owner census at op 3454853 (sums to exactly 1153): - -| n | site | role | -|---|---|---| -| 599 | gcd.rs:1353 | dialog tape slots | -| 256 | mod.rs:459 | `y2` — Bezout X | -| 256 | gcd.rs:1902 | `tmp` — Bezout Y | -| 10 | mod.rs:458 | `v` (11 allocated − 1 parked) | -| 10 | gcd.rs:1189 | `u` (11 allocated − 1 parked) | -| 9 | arith.rs:981 | graduated-staircase intermediates | -| 7 | arith.rs:1197 | `add_f_window_hybrid` clean carries | -| 1 | arith.rs:1169 | staircase cout | -| 1 | gcd.rs:1830 | `controlled_mod_sub_vented` cout | -| 1,1,1 | gcd.rs:1197/1199/1260 | subtracted, s2, swap_flag | - -## Step 2 — ideas killed - -**`t1` is not a wasted qubit.** I expected it to be a scalar held from i=0 to the end for one use. -`compress_step0_with_t1` (codec.rs:415-427) **consumes** it — it frees `sub` and `swap` and returns `vec![t1, s2]`, -so t1 *becomes* a tape bit. Its census attribution just stays with its original alloc site. Nothing to reclaim. - -**The graduated staircase is already minimal.** `controlled_add_const_chunked_graduated_off` builds chunks of width -`k-3-j`, so peak contribution is a constant `k-3` — a genuinely clever design. `graduated_const_kmin(n)` needs -`(k-3)(k-2)/2 ≥ n`; at n = LSBS = 53 that gives k=13 and a 10-qubit contribution. k=12 only covers 45 < 53. To shrink -it you must shrink LSBS, which directly raises λ (the fold-window carry escape is ~f/2^LSBS and already contributes -2.18 mismatches). - -**ITERS is pinned at 261.** Each step down is worth ~3,357 emitted CCX (−0.245% score), which looked like a far better -lever than qubits. But ITERS **must be ≡ 0 mod 3** or `jump_dialog_regions` grows a ragged Pair/Raw tail. Measured at -n=12: ITERS=260 → 4,906 classical mismatches, ITERS=259 → 7,348. Both destroyed. 258 reverts to `BAKED_ITERS` and is -candidate A at λ≈17. So 261 is the only usable value in the neighbourhood. - -## Step 3 — the exchange-rate trap, confirmed empirically - -Narrowing the SCHED_J2 tail frees u,v qubits — and the peak **does not move**: - -| narrowed tail entries | peak | -|---|---| -| 4, 12, 24, 48 | 1153 (unchanged) | - -Because the vent pool (`headroom = TLM_TARGET_Q − active`) simply expands to absorb whatever you free. -**A persistent-set reduction only pays if you lower the cap by the same amount.** This is the single most important -operational fact about this circuit and it has now bitten three separate workstreams. - -## Step 4 — the dial alone loses - -Both caps moved together, final-stream Toffoli-family counts (not `TLM_CCX_TOTAL`, which is measured *before* the -post-passes and is structurally blind to the strip): - -| q | peak | final tof | Δtof | Δq | -|---|---|---|---|---| -| 1152 | 1153 | 1,369,934 | — | — | -| 1151 | 1152 | 1,375,722 | +5,788 | −1 | -| 1150 | 1151 | 1,378,439 | +8,505 | −2 | -| 1149 | 1150 | 1,381,262 | +11,328 | −3 | - -Roughly half of each Δ is **lost strips** (3,198–3,805 census keys go stale — the tripwire correctly discards them); -the rest is genuine adder cost, ~2,590/qubit after accounting. Against a 1,188 break-even that still loses by ~2.2×. -**The dial is not the answer.** - -## Step 5 — what actually worked: narrow the tail AND lower the cap together - -Narrowing SCHED_J2's tail is not just a lifetime change — it shrinks the GCD registers, so the walk's adders, -comparators and cswaps all get *cheaper*. Combined with a matching cap reduction it improves **both** axes at once. -(GAP_J2 narrowed in lockstep, preserving `s = SCHED_J2[i] − cmp_window(i) = −1`, per the coupling result: the error -depends only on `s`, and moving one without the other takes the divstep channel from 8.36 to 4,646 mismatches.) - -Strip-off, so the numbers are pure (baseline = 1153 × 1,381,252 = 1.5926e9): - -| N narrowed | q | peak | tof | peak×tof | vs base | -|---|---|---|---|---|---| -| 0 | 1152 | 1153 | 1,381,252 | 1.59258e9 | — | -| 96 | 1151 | 1152 | 1,378,319 | 1.58782e9 | −0.30% | -| 160 | 1151 | 1152 | 1,375,689 | 1.58479e9 | **−0.49%** | -| 224 | 1151 | 1152 | 1,374,133 | 1.58300e9 | −0.60% | -| 258 | 1151 | 1152 | 1,373,437 | 1.58220e9 | −0.65% | -| 160 | 1150 | 1151 | 1,378,056 | 1.58614e9 | −0.41% | - -λ is the gate (n=12 per arm, strip off, q=1151): - -| N | classical | phase | -|---|---|---| -| 0 (base @1152) | 6.08 | 5.33 | -| 96 | 8.33 | 6.92 | -| 128 | 8.33 | 7.33 | -| **160** | **9.67** | **8.08** | -| 192 | 10.50 | 8.58 | -| 224 | 13.67 | 10.00 | -| 258 | **1386.83** | 140.58 ← destroyed | - -N=258 breaks because the *early* SCHED_J2 entries are a genuinely tight magnitude bound on f,g. The tail is where the -slack is. - -**Chosen point: N=160, q=1151.** −0.49% proxy at λ_classical 9.67, which is ~22× harder to grind than the shipped -λ≈7.25 but still on the order of an hour. - -## Step 6 — shipped-state measurement - -`ec-FINAL` = head + narrow-160 + caps at 1151, with the *existing* (now partly stale) census table: -``` -peak_qubits=1152 final tof 1,370,612 removed 4389/9268 dead, downgraded 688/2050, 6241 stale keys -``` -Estimated executed ≈ 1,370,612 × 0.9556 = 1,309,797 → score ≈ **1,508,886,144 (−0.037%)**. -A win already, and that is *with* 6,241 census keys discarded by the tripwire. A re-mine against this stream should -recover ~6,241 gates and take it to roughly **1.502e9 (−0.49%)**. - -Blocker on the re-mine: the census tooling lived in `/tmp` and `/dev/shm` on the box and did **not** survive the -stop/start. Only the `~/ec-*` trees are on real disk. Rebuilding it is the obvious next task — and the mined tables -themselves should be committed to git, not left on a VM. - -## Next -1. Grind a clean nonce for `ec-FINAL` and submit the −0.037%. -2. Rebuild the census tool, re-mine against the FINAL stream, take the remaining ~0.45%. -3. Re-test the qubit programme end to end now that the tripwire exists — every pre-tripwire "impossible" verdict is - suspect (the `TLM_TARGET_Q` weld already reversed). diff --git a/src/point_add/memory/06-research-status.md b/src/point_add/memory/06-research-status.md deleted file mode 100644 index 62791095..00000000 --- a/src/point_add/memory/06-research-status.md +++ /dev/null @@ -1,205 +0,0 @@ -# Research status — what is proved, what failed, what remains open - -This is the handoff for the verifier-centered research performed against promoted source -`cf5aa02147d4e1a698bbf84c10d33920d4356489`. The repository has been reset to that official source. Experimental -production edits, raw solver traces, generated CNFs, ledgers, and controller infrastructure were deliberately removed. -The small programs in `repro/` are the retained executable knowledge. - -## Official frontier and evidence standard - -| field | certified value | -|---|---:| -| promoted submission | `0c5b1b7b-561a-48a0-abc6-5fefaffdc0ad` | -| score | `1,490,805,286` | -| average executed Toffoli | `1,291,859.302` (`1,291,859` rounded) | -| total executed Toffoli | `11,657,738,337` over `9,024` shots | -| qubits | `1,154` | -| emitted operations | `9,062,420` | -| compressed `ops.bin` SHA-256 | `7333b19de3f3171a70d1b5132e867b7fb28cd5d77b34668175b391c420eed8c9` | -| canonical decompressed-operation SHA-256 | `ec90afeadf8d294819e1e2128764c9da8d0742730c09d4ac1ae19d3b1a99dfba` | -| official result | `9,024/9,024`; zero classical, phase, and end-of-forward ancilla failures | - -The trusted scorer is - -\[ -S(T,Q)=\min(\lfloor T+0.5\rfloor Q,2^{64}-1). -\] - -`T` is the verifier's average executed Toffoli count and `Q` is `max referenced qubit id + 1`; neither emitted gate -count nor live-qubit count substitutes for these values. Only a byte-identical artifact or a complete `ecdsafail run` -is transfer evidence. See `repro/exact_scorer.py` and `04-traps.md`. - -The verifier accepts exactly four 256-bit registers typed quantum/quantum/classical/classical, all affine outputs -correct, zero residual phase, and zero non-output qubits after the forward pass. The operation cap is four billion. -The ABI alone gives `Q >= 512`; no nontrivial global Toffoli lower bound was proved. - -## Status vocabulary - -- **Established:** proof, exact enumeration, or exhaustive replay within the stated scope. -- **Observed:** measured on named artifacts/seeds; not a theorem. -- **Refuted:** a preregistered prediction received a concrete counterexample. -- **Unresolved:** neither a witness nor a lower-bound certificate exists. Timeout is not evidence of UNSAT. -- **Relaxation:** an oracle or assumption used only to price headroom, not an implementation. - -## Established scoped results - -### 1. The standalone five-wire pair normalizer needs exactly six CCX in the tested class - -`compress_2sym_fast` feeds `NORMALIZER_OPS` 25 distinct five-wire states, not five raw three-bit symbols. On those 25 -states the normalizer maps bijectively to canonical values `0..24`. - -For the class **no ancilla, arbitrary affine gates, and affine-conjugated CCX gates on those five wires**, every CCX is -one reversible generalized shear. Exhaustive quotient search produced: - -- input depth-two frontier: `913,220` states; -- output depth-two frontier: `908,804` states; -- exactly one shared rank-five hyperplane pair; -- all `420` admissible independent affine-control products on that hyperplane rejected as a bridge; -- no path of five or fewer generalized shears; -- the shipped six-shear reference independently replayed through pinned Kissat and CaDiCaL SAT witnesses. - -Therefore the exact minimum is **six CCX in this class**. This is not a global normalizer bound: ancillas, non-affine -intermediate representations, or absorbing surrounding compressor logic are outside scope. Do not rerun a standalone -at-most-five search unless the gate/representation class changes. - -Reproducer sources: `repro/y5_pair25_quotient.py`, `repro/hyperplane_mitm.cpp`, -`repro/y5_normalizer_synth.py`. - -### 2. Two one-shear neighborhoods of the joint six-wire codec are closed - -The useful broader map combines `compress_2sym_fast` with `NORMALIZER_OPS`. Its verified reference costs eight CCX -forward and nine CCX in the reversible cleanup. It replays all 64 six-wire states, including all 25 reachable inputs, -and has an explicitly invertible affine output map. - -For exact-eight synthesis: - -- all `8/8` branches replacing one adjacent pair of the nine reference shears by one arbitrary shear are UNSAT; -- all `288/288` branches retaining seven reference shears and inserting one arbitrary shear are UNSAT; the sole initial - timeout was independently settled UNSAT by Kissat and CaDiCaL. - -These are class results around the shipped reference, not a global eight-CCX lower bound. Reproducers: -`repro/y5_joint_codec_neighborhood.py` and `repro/y5_joint_codec_two_rebase.py`. - -### 3. Small-width composite controlled arithmetic did not expose a gain - -For the restricted `n=3` GCD cswap-plus-controlled-subtract map (`u` odd, `v0=t`, `s=>t`), exact XOR/AND synthesis -settled multiplicative complexity at five: bounds zero through four were UNSAT and five was SAT in both Kissat and -CaDiCaL. That equals the reference. This refutes this small branch as an immediate optimization surface; it does not -prove the large-width optimum. Reproducer: `repro/y1_composite_synth.py`. - -### 4. Whole-dialog information slack exists, but no usable streaming codec is known - -With fixed initial `u=p`, the exact complete dialog and terminal state identify one input `x`; all `p-1` inputs give -distinct dialogs. The exact information rank is 256 bits versus the current 609-bit representation, a 353-bit -information gap. This is only an information bound. No reversible streaming rank/unrank construction was found that -keeps the apply traversal below the current peak. The naive endpoint construction regenerates the full tape and saves -zero peak qubits. Reproducer: `repro/y3_global_codec.py`. - -### 5. One source-level implication is exact but already represented empirically - -Before `controlled_clean_add_threaded` call 0, bit 0, in the no-carry branch, the source state implies the redundant -control. Two solvers proved the violating assignment UNSAT before and after an identity perturbation. Replacing that -specific CCX with CX is sound, but it merely reproduced one existing empirical downgrade: the emitted artifact and -score stayed byte-identical. The important reusable result is methodological: source-indexed certificates survive -same-tuple ordinal shifts that invalidate persistent census keys. Further work must find *new* source implications, not -re-encode existing table entries. - -## Refuted or exhausted approaches - -| approach | decisive result | implication | -|---|---|---| -| Five raw-symbol normalizer restriction | After rebasing its stale key, the official verifier failed `9,024/9,024` classical shots and all `141` phase batches. | The true domain is the 25 post-compressor five-wire states. | -| Direct terminal-carry reuse | Isolated miter passed 2,736 cases and predicted one CCX saved per call; production official run failed 24 classical shots and 15 phase batches. Individual GCD, less-than, and carry surfaces also produced trusted counterexamples. | The isolated phase/value abstraction was not compositional. | -| Four-bit terminal dialog codec | Tape bits fell 609→605, but peak qubits stayed 1,154 and final CCX rose by 8,038; break-even was 4,493. Support-miss rate was about `3e-4`. | Statically product-negative and not exact. | -| Final CCX self-inverse cancellation | Exact strict-clean and net-restore analyzers both found zero pairs in 9,073,163 pre-strip operations. | Do not rerun these same-tuple pair classes. | -| Deep-strip localization | On a committed root, full and completely unstripped streams had the identical 13 classical failure shots; restoring all final empirical transforms cost 12,803.278 executed Toffoli. | Transfer failures originate upstream, not in the final deep-strip table. | -| Coordinate ports | No tested ABI-compatible representation cleared its qubit-specific Toffoli cap. The strongest local `Q=835` case already required 6,443,568 Toffoli for two inversions before shell cost, versus a cap of 1,785,395. | A new representation needs a complete four-register-compatible cost, not a qubit claim alone. | -| Perfect coordinate-shell oracle | Granting the measured shell zero cost would save about 1,600 executed Toffoli and lower score by 1,846,400 (`1,488,958,886`). | Headroom exists, but the oracle supplies no reversible implementation. | -| More nonce grinding | The current artifact's pooled nonce Toffoli SD was 8.694 over 384 disjoint draws; correctness success remains exponentially rare on ordinary seeds. | Nonce outcomes select artifacts but do not create transferable structural gain. | - -The coordinate-shell score delta is exactly `1,846,400`: `1,490,805,286 - 1,488,958,886`. The displayed oracle is a -relaxation, not a candidate. - -## Open problems — do not overstate the stop - -### Unrestricted exact-eight joint synthesis remains open - -The exact-eight CNF had 11,416 variables and 54,051 clauses. Kissat, CaDiCaL, and diversified CryptoMiniSat runs timed -out or exited indeterminate. No witness was found, but there is **no UNSAT proof**. All seven branches replacing a -contiguous reference triple by at most two arbitrary shears also remain unresolved. - -The run stopped at its preregistered two-local-CPU-hour cap (`7,113.268` conservatively charged seconds), not because a -theoretical ceiling or abstraction impossibility was demonstrated. Repeating the same CNF and solver portfolio had low -expected return. Reopen with one of: - -1. a machine-checkable symmetry reduction; -2. a materially stronger exact encoding; -3. a distinct synthesis representation or gate class; -4. a compiled exact-eight witness that replays all 25 forward/inverse pairs. - -Do not describe the generalized-shear abstraction as globally saturated: only the two named neighborhoods and the -standalone five-wire class are closed. - -### Other high-leverage uncertainties - -1. Controlled quantum addition has a proven `n` lower bound and a roughly `2n` construction; the factor-two gap remains. -2. A streaming exact dialog ranker could exploit a large information gap only if its rank/unrank logic and live set beat - the current product. -3. New source-state implications can outperform ordinal census keys only when they remove gates not already downgraded. -4. Any low-qubit representation must price both inversions, affine-output cleanup, four-register ABI compatibility, and - executed—not emitted—Toffoli. -5. The current representation's oracle floor `(T,Q)=(132,864,1,022)` and score `135,787,008` is a deliberately impossible - relaxation: it grants perfect arithmetic outside retained swaps and releases 132 peak owners. It maps headroom; it - is not an attainable design. - -## Re-entry commands - -Run all lightweight retained checks first: - -```sh -python3 -m unittest discover -s src/point_add/memory/repro -p 'test_*.py' -v -python3 src/point_add/memory/repro/exact_scorer.py --backtest results.tsv -``` - -Regenerate the pair25 depth-two frontiers only when auditing the exact-six proof; this is intentionally expensive and -creates transient `.autoresearch/` output: - -```sh -python3 src/point_add/memory/repro/y5_pair25_quotient.py \ - --output .autoresearch/measurements/pair25/report.json \ - --frontier-dir .autoresearch/measurements/pair25 -clang++ -std=c++20 -O3 -DNDEBUG src/point_add/memory/repro/hyperplane_mitm.cpp \ - -o .autoresearch/measurements/pair25/hyperplane_mitm -.autoresearch/measurements/pair25/hyperplane_mitm \ - .autoresearch/measurements/pair25/x-depth2.bin \ - .autoresearch/measurements/pair25/y-depth2.bin -``` - -For a genuinely improved joint encoding, start from `repro/y5_joint_codec_synth.py`; the three neighboring scripts -encode the already-tested subclasses. Any SAT witness must be compiled, replayed forward and inverse on all 25 valid -pairs, then passed to the untouched official court: - -```sh -ecdsafail run -``` - -Never submit from a proxy result. Never treat a timeout as a lower bound. Re-run `ecdsafail benchmark` and -`ecdsafail sync` before new work because the promoted frontier can move. - -## Retained files - -| file | purpose | -|---|---| -| `repro/exact_scorer.py` | exact score arithmetic and historical backtest | -| `repro/y1_composite_synth.py` | reusable XOR/AND CNF support plus the scoped `n=3` experiment | -| `repro/y3_global_codec.py` | exact dialog-rank and bounded suffix experiments | -| `repro/y5_normalizer_synth.py` | five-wire generalized-shear encoding and reference compiler | -| `repro/y5_pair25_quotient.py` | exact depth-two affine-quotient frontier generator | -| `repro/hyperplane_mitm.cpp` | exact fifth-edge bridge checker for the pair25 proof | -| `repro/y5_joint_codec_synth.py` | unrestricted joint six-wire exact synthesis encoding | -| `repro/y5_joint_codec_{neighborhood,two_rebase,triple_fusion}.py` | closed and unresolved local subclasses | -| `repro/y6_source_invariant.py`, `repro/artifact_io.py` | source-indexed invariant proof utility | -| `repro/test_*.py` | fast contracts for the retained machinery | - -Everything else from the research harness was operational scaffolding or bulky evidence. It was removed after these -scoped conclusions, counterexamples, hashes, and reproducers were retained. \ No newline at end of file diff --git a/src/point_add/memory/CEILING.md b/src/point_add/memory/CEILING.md deleted file mode 100644 index a0b89969..00000000 --- a/src/point_add/memory/CEILING.md +++ /dev/null @@ -1,96 +0,0 @@ -# Verifier ceiling — ECDSA Fail - -## Exact scorer - -The trusted path is `src/bin/eval_circuit.rs::write_score` plus -`src/sim.rs::Simulator::apply_iter`; the executable model is -[`repro/exact_scorer.py`](repro/exact_scorer.py), and the pinned bound checker is -[`repro/verifier_ceiling.py`](repro/verifier_ceiling.py). - -For `N = 9,024` accepted shots, - -\[ -T=\frac{\text{total executed CCX/CCZ}}{N},\qquad -S=\min(\lfloor T+0.5\rfloor Q,2^{64}-1). -\] - -`Q` is `max referenced qubit id + 1`. Only CCX and CCZ are charged, and only on -shots satisfying their classical condition stack. - -Pinned trusted hashes are emitted by `verifier_ceiling.py`; any mismatch makes the -bound model red. - -## Bounds - -| bound | value | argument | class | -|---|---:|---|---| -| Absolute score floor | **0** | Both rounded executed Toffoli and qubit width are non-negative. | Hard | -| Zero-score threshold | **total executed Toffoli <= 4,511 over 9,024 shots** | `4,511 / 9,024 < 0.5`; `4,512 / 9,024 = 0.5` and rounds to one. | Hard | -| Intended output width floor | **512 qubits** | Two distinct 256-bit quantum output registers. The loader does not itself reject duplicate register members, so this is an intended-computation bound, not the proof of the score floor. | Scoped hard | -| Universal zero-Toffoli circuit | **impossible for generic point translation** | With classical offset fixed and no CCX/CCZ, computational-basis quantum values remain affine in the quantum input; elliptic-curve translation is not affine. | Scoped hard | -| Finite-verifier zero-Toffoli lookup | **3,042,193 ops, 512 qubits, score 0 on a frozen draw** | A 27-bit classical-offset prefix uniquely selects each of the current 9,024 pairs; condition stacks and X corrections are uncharged. | Relaxation | -| Fiat-Shamir replay of that lookup | **9,024/9,024 failures** | The lookup's semantic stream changes the SHAKE256 draw; none of the new prefixes hit its frozen table. | Observed refutation | -| Reduced self-seeded lookup census | **5 fixed points in 1,149,296 exact toy states; 0–2 per scope** | Exact verifier-field serialization and SHAKE256 coupling at one-row widths 1–5 and two-row widths 1–2; production lookup family has approximately `2^4,758,375` states. | Observed scaling | -| Nontrivial global Toffoli floor | **unknown** | The verifier checks a self-seeded finite sample, not universal point addition. No exact multiplicative-complexity lower bound is known for all accepted op streams. | Open | -| Best witness upper bound | **1,489,216,228** | Promoted `705b36a`: `1,290,482 × 1,154`, exact 9,024-shot pass. | Official | -| Prior arithmetic oracle floor | `135,787,008` | Grants perfect arithmetic and removes peak owners; explicitly not an implementation. | Relaxation | - -The verifier's absolute numerical ceiling for a lower-is-better score is therefore -**0**. It is not yet an exact *attainable* circuit minimum: that equality requires an -official score-zero witness. Until then the certified interval is -`[0, 1,489,216,228]`. - -## Baseline and headroom - -Current promoted artifact: - -- submission `705b36a4-7571-4c4a-85e4-3b79d9dec0f7`; -- source `7fa872d08f121648554d9a8869ac032624f20472`; -- compressed artifact hash - `e1f6f50af54b7d67e3812faf5cccd13f6c16ed68e500d122b5779c5ccc76f333`; -- canonical operation hash - `ddea3e8d298073281223e5a9ff4995e08efce2b6e7408f6774a38a5701767ce7`; -- exact average `1,290,481.644947`, width `1,154`, score `1,489,216,228`. - -The multiplicative headroom ratio to zero is undefined. The additive score gap is -exactly `1,489,216,228`; reaching the floor requires crossing the rounding boundary, -not merely improving the existing product by a constant factor. - -## Headroom ledger - -`TRACE_TLM_TOF=1` on the pinned initial `cf5aa02` artifact measured this pre-postpass -executed-Toffoli model: - -| niche | term | expected executed Toffoli | evidence / route | -|---|---|---:|---| -| `H1-gcd-apply` | two GCD/apply traversals, swaps, compares, shifts, folds, codecs | `1,235,398.5` | Exact phase census under the profiler model; controlled-add/composite arithmetic and a representation removing one traversal. | -| `H2-square` | reversible modular square | `67,988.0` | Exact phase census under the profiler model; alternative square or representation. | -| `H3-coordinate-shell` | classical-offset coordinate shell | `1,600.0` | Exact phase census under the profiler model; source-indexed invariants. | -| `H4-postpasses` | constprop, fanout, deep strip, and execution-model residual | `-13,127.198` | Calibrated credit required to reproduce the trusted average exactly. Re-mine on every geometry change. | -| **sum** | | **`1,291,859.302`** | Matches the official average; residual `0`. | - -Width is a separate conserved resource: - -| niche | term | current | hard/scoped floor | route | -|---|---|---:|---:|---| -| `H5-width` | peak referenced qubit id | `1,154` | `512` intended distinct outputs | schedule/cap geometry or complete alternative representation; lower caps must be priced with executed Toffoli. | - -`H0-zero-rounding` is the second court rather than an additive component: exploit-free -verifier-specific constructions may replace the entire arithmetic ledger only if they -remain correct after their own semantic stream determines the Fiat-Shamir draw. The direct -frozen lookup failed this test. - -## Verdict - -1. **Absolute target:** score `0`, equivalently at most `4,511` total executed Toffoli - over the official 9,024 shots. -2. **What is proved:** the scorer floor and rounding threshold, trusted source identity, - complete pinned-baseline cost reconciliation, failure of direct frozen-dataset lookup, - and inverse-density scaling of the canonical lookup fixed-point family. -3. **What is not proved:** existence of a score-zero artifact or any positive global - Toffoli lower bound for self-seeded finite verification. -4. **Search discipline:** keep `H0` as a reframe court; maintain live candidates in - `H1`–`H5`; predict artifact/hash invalidations before every experiment; only an exact - trusted result updates the frontier. -5. **Stop:** official promotion at score zero, or the bounded 500-iteration return with a - content-addressed evidence checkpoint. diff --git a/src/point_add/memory/README.md b/src/point_add/memory/README.md deleted file mode 100644 index d00e5fce..00000000 --- a/src/point_add/memory/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Memory - -Start with `06-research-status.md` for the current frontier, proved scope, failed approaches, open problems, and exact -re-entry commands. These notes live under `src/point_add` so they travel with submissions. - -| file | contents | -|---|---| -| `01-architecture.md` | first-principles decomposition: the algorithm, the inversion, the qubit budget, the Toffoli budget | -| `02-lambda.md` | the intrinsic error rate — the hidden third score axis, and the reason the leaderboard stalls | -| `03-proven-floors.md` | where the headroom is NOT, with proofs (rank bound, multiplicative complexity, exact codec enumeration) | -| `04-traps.md` | four ways an env knob silently no-ops, positional addressing, validation gates | -| `05-qubit-reduction.md` | the measured qubit programme, including the exchange-rate trap | -| `06-research-status.md` | latest research handoff: certified baseline, scoped results, counterexamples, unresolved work, re-entry conditions | -| `repro/` | compact tested programs retained to reproduce or extend the durable claims | -| [`repro/world_model.py`](repro/world_model.py) | executable evidence, invalidation, history-replay, and promotion-gate model | - -The single most important operational fact: **a persistent-set reduction only pays if you lower `TLM_TARGET_Q` by the -same amount**, because the vent pool expands to fill whatever you free. The second most important: **only a -byte-identical `ops.bin` or a full 9024-shot run is evidence.** A healthy peak/Toffoli probe proves nothing. diff --git a/src/point_add/memory/RIG.md b/src/point_add/memory/RIG.md deleted file mode 100644 index 43bd03fc..00000000 --- a/src/point_add/memory/RIG.md +++ /dev/null @@ -1,112 +0,0 @@ -# ECDSA Fail research rig - -Companion to [`CEILING.md`](CEILING.md). This rig instruments the current trusted -verifier; it never substitutes for `ecdsafail run`. - -## Contract - -| field | pinned value | -|---|---| -| objective | minimize `round(avg executed CCX/CCZ) × max referenced qubit id + 1` | -| official regime | 9,024 SHAKE256-of-semantic-stream shots; zero classical, phase, and ancilla failures | -| frontier | `1,489,216,228 = 1,290,482 × 1,154`, submission `705b36a`, source `7fa872d` | -| artifact | compressed `e1f6f50a…c76f333`, canonical `ddea3e8d…1767ce7` | -| absolute scorer floor | `0`; requires at most `4,511` total executed Toffoli | -| iteration cap | 500; checkpoint every 10 completed iterations | -| editable | `src/point_add/**`, durable memory/reproducers, ignored `.autoresearch/**` | -| frozen | trusted evaluator/simulator/circuit, benchmark scripts/config, toolchain, retained tests/history | - -Literal registration: - -```sh -python3 src/point_add/memory/repro/verifier_ceiling.py --verify --json -python3 src/point_add/memory/repro/schema_harness.py init -python3 src/point_add/memory/repro/schema_harness.py backtest -``` - -## Instruments - -| tier | instrument | authority | -|---|---|---| -| Hash | `artifact_io.py::fingerprint` | Exact artifact identity, width, and static operation census. First check after every build. | -| Rank | retained exact synthesis/proof reproducers and source-level models | Refutes scoped mechanisms and ranks hypotheses; cannot update frontier. | -| Gate | paired fixed-randomness differential, exact stream census, `dirtyscan`, `TRACE_TLM_TOF` | Allocates trusted-run spend. Any surprise invalidates affected calibrations. | -| Certify | `ecdsafail run` | Sole correctness and score authority for an exact artifact. | -| Promote | `world_model.py::promotion_gate` followed by `ecdsafail submit` | Requires refreshed frontier, exact hash, 9,024-shot pass, and strict score beat. Official promotion is ground truth. | - -No `.opencode` controller is installed. `schema_harness.py` is the single thin -content-addressed recorder/backtester, while the active goal session remains the only -controller. This preserves the prior deletion of unmeasured controller infrastructure. - -## Niches - -The harness accepts exactly the `CEILING.md` terms: - -| niche | mechanism | initial champion | exhausted? | -|---|---|---|---| -| `H0-zero-rounding` | seed-independent or fixed-point verifier-specific construction | none; frozen lookup and direct fixed-point census retired | no | -| `H1-gcd-apply` | controlled arithmetic, composite synthesis, or one-traversal representation | promoted frontier | no | -| `H2-square` | modular-square structure | promoted frontier | no | -| `H3-coordinate-shell` | source-indexed invariants and coordinate shell | promoted frontier | no | -| `H4-postpasses` | exact transforms, strip provenance, cost calibration | promoted frontier | locally mature, not globally exhausted | -| `H5-width` | schedule/cap geometry or complete alternative representation | promoted frontier | no | - -`schema_harness.py select` samples the least-attempted niche; proposals may branch from -any live candidate. A globally dominated candidate remains live when it is the best witness -for an unclosed mechanism. - -## Gates - -1. **Backtest before action.** A broken hash chain, invalidation mismatch, missing prior - observation, unresolved surprise without a reframe, or missing tenth-iteration checkpoint - makes the rig red. Measurement remains legal; optimization edits do not. -2. **Prediction before experiment.** Every prediction names niche, parent candidate and - artifact, action class, mechanism, `ΔQ`, mean/SD of `ΔT`, correctness risk, invalidations, - and full-run budget. -3. **Hash before spend.** A byte-identical semantic artifact is `no_effect` and cannot receive - a full verification allocation. -4. **Evidence hardness.** Exact proof channels hard-block only their scope. Statistical - proxies are calibrated bets and never certify a circuit. -5. **Mismatch abort.** `prediction_match=false` requires a reframe with a compression claim - and forward prediction before the next iteration. -6. **Full run.** Stage `full` requires the exact artifact hash, trusted evidence kind, - 9,024 shots, all failure channels, qubits, average Toffoli, and score. -7. **Promotion.** Refresh frontier, require exact passing artifact and strict score beat, - then submit. Record rejected, failed, accepted, and promotion outcomes without omission. - -## Court - -The initial ontology change is `H0-zero-rounding`: the numerical floor is zero, so arithmetic -constant-factor grinding cannot establish the absolute optimum. Its first forward prediction -was tested by `zero_score_lookup.py`: a frozen 27-bit-prefix table fit all 9,024 points at -zero Toffoli in 3,042,193 operations, but its own semantic stream reseeded the draw and failed -9,024/9,024 with zero table hits. Iteration 28 then exhaustively enumerated 1,149,296 reduced -self-seeded lookup states with exact field serialization and SHAKE256 coupling. The seven -scopes had 0–2 fixed points each, while the analogous production table family has -approximately `2^4,758,375` states. The compressed model is: artifact identity and verifier -draw are one endogenous state, and direct canonical fixed-point search has inverse-density -cost. Further H0 proposals must be seed-independent or generically transform the quantum -input; fitting a draw or searching the direct table map is retired. - -## Acceptance - -| instrument gate | observed acceptance | -|---|---| -| scorer replay | `exact_scorer.py` green on 7 retained rows and exact current totals | -| public frontier replay | `world_model.py` green on all 416 promoted rows in strict order | -| trusted pin | `verifier_ceiling.py --verify --json` green on all six trusted hashes and both rounding boundaries | -| baseline identity | `artifact_io.fingerprint(ops.bin)` reproduces both promoted hashes, 9,062,420 ops, and 1,154 qubits | -| no-op safety | `TRACE_TLM_TOF=1` rebuild preserved compressed hash `7333b19d…e890b8c9` | -| seeded bad discriminator | zero-score lookup self-reseed produced 9,024 classical failures; q1145 trusted counterexample remains denied by tests | -| reduced fixed-point census | `h0_fixed_point_census.py` exhaustively checked 1,149,296 states; instrument SHA-256 `9e2ce86a…a8c0edc`; 0–2 fixed points per scope | -| latest official witness | submission `705b36a` promoted at score `1,489,216,228`, exact 9,024-shot pass; this updates only the upper bound | -| phase cost model | profiler terms sum `1,304,986.5`; calibrated postpass credit `-13,127.198` reproduces official `1,291,859.302` exactly | -| harness contracts | full retained, ceiling, Schema, world-model, and fixed-point contract suite green | -| live ledger | `.autoresearch/measurements.jsonl` backtest green through iteration 28; tail `87b2cf73…72cbaa` | - -## Source - -Pinned instrument identity: -`db5c1340408626b17fb37eebc18b3bdc1be42bbb141e34e8f70a2af328ddccbd`. -Recompile this rig if a trusted hash, scorer, world-model invalidation contract, ceiling term, -or calibrated proxy turns red. diff --git a/src/point_add/memory/niche_portfolio.json b/src/point_add/memory/niche_portfolio.json deleted file mode 100644 index 4880cd2e..00000000 --- a/src/point_add/memory/niche_portfolio.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "schema_version": 1, - "frontier": { - "source_ref": "7fa872d08f121648554d9a8869ac032624f20472", - "score": 1489216228, - "rounded_average_toffoli": 1290482, - "measured_average_toffoli": 1290481.644947, - "qubits": 1154 - }, - "objective": { - "exact": "round(average_executed_toffoli) * qubits", - "absolute_floor": 0, - "zero_score_condition": "total executed Toffoli across 9024 shots <= 4511", - "abi_qubit_floor": 512, - "status": "floor proved; attainability open" - }, - "strict_improvement_thresholds": [ - {"qubits": 512, "maximum_rounded_toffoli": 2908625}, - {"qubits": 768, "maximum_rounded_toffoli": 1939083}, - {"qubits": 1024, "maximum_rounded_toffoli": 1454312}, - {"qubits": 1100, "maximum_rounded_toffoli": 1353832}, - {"qubits": 1145, "maximum_rounded_toffoli": 1300625}, - {"qubits": 1154, "maximum_rounded_toffoli": 1290481} - ], - "profile": { - "pre_postpass_expected_toffoli": 1304986.5, - "calibrated_postpass_credit": -13127.198, - "official_average_toffoli": 1291859.302, - "profile_rows": 40 - }, - "niches": [ - { - "id": "H0-zero-rounding", - "role": "orthogonal verifier construction", - "current_expected_toffoli": null, - "first_principle_constraint": "A candidate semantic stream determines its own SHAKE256 test draw; a finite table fit to another stream is not a candidate.", - "champion": null, - "prior_evidence": "A 27-bit frozen lookup fit 9024/9024 samples in 3042193 zero-Toffoli ops, then had 0 self-seeded hits and 9024 classical failures. An exact census of 1149296 reduced self-seeded states found 0-2 fixed points per scope and extrapolated a direct production search space of about 2^4758375 states.", - "stepping_stones": [ - { - "id": "H0.1-seed-invariant-semantics", - "claim": "Find a non-byte-identical semantic change that preserves the verifier seed or prove the serialized ABI makes this impossible without a SHAKE256 collision.", - "cheapest_discriminator": "canonical operation-stream hash derivation and exact source proof", - "exit": "machine proof or explicit collision obligation" - }, - { - "id": "H0.2-fixed-point-map", - "claim": "The direct canonical table map has O(1) fixed points but inverse-density search cost.", - "cheapest_discriminator": "closed by h0_fixed_point_census.py over 1149296 exact reduced states", - "exit": "retired as a scalable route; reopen only with a construction that removes inverse-density search" - }, - { - "id": "H0.3-generic-input-extraction", - "claim": "Determine whether the verifier's free classical condition stack can reveal quantum register contents without measured or Toffoli-mediated transfer.", - "cheapest_discriminator": "operation semantics proof over Simulator::qubit, phase, conditions, and register readback", - "exit": "generic extraction primitive or impossibility within the ABI" - }, - { - "id": "H0.4-seed-independent-translation", - "claim": "Construct a generic zero-Toffoli affine translation or prove that nonlinear secp256k1 addition forces a nonlinear reversible primitive.", - "cheapest_discriminator": "algebraic-degree argument followed by a reduced-width exhaustive circuit census", - "exit": "scalable construction or explicit lower-bound premise" - } - ] - }, - { - "id": "H1-gcd-apply", - "role": "dominant Toffoli kernel", - "current_expected_toffoli": 1235398.5, - "emitted_profile_ops": 1291549, - "first_principle_constraint": "This term contains most executed nonlinear work; local suffix savings matter only when multiplied by their measured invocation count and surviving postpasses.", - "champion": "cf5aa02 promoted frontier", - "prior_evidence": "Known suffix, composite, cap, and traversal searches are documented in 06-research-status.md; no global lower bound exists.", - "stepping_stones": [ - { - "id": "H1.1-exact-call-census", - "claim": "Attribute every emitted and expected Toffoli to a source kernel, call count, control regime, and postpass fate.", - "cheapest_discriminator": "TRACE_TLM_TOF profile plus source-indexed transition replay", - "exit": "cost ledger closes exactly to 1235398.5 before postpass credit" - }, - { - "id": "H1.2-controlled-composition", - "claim": "Synthesize controlled add/apply composites across call boundaries instead of optimizing isolated primitives.", - "cheapest_discriminator": "exact reduced-domain miter and weighted invocation model", - "exit": "positive full-stream predicted saving with no unproved composition edge" - }, - { - "id": "H1.3-one-traversal-representation", - "claim": "Replace paired forward/reverse affine-inversion work with a representation that needs one inversion traversal.", - "cheapest_discriminator": "symbolic dataflow and liveness proof before circuit construction", - "exit": "closed reversible schedule with ancilla cleanup and lower modeled product" - }, - { - "id": "H1.4-unrestricted-joint-codec", - "claim": "Resolve the exact-eight joint codec without restricting to the exhausted local shear family.", - "cheapest_discriminator": "SAT/SMT synthesis with exact semantic replay", - "exit": "witness below retained reference or a scoped UNSAT certificate" - } - ] - }, - { - "id": "H2-square", - "role": "specialized nonlinear kernel", - "current_expected_toffoli": 67988.0, - "emitted_profile_ops": 68406, - "first_principle_constraint": "Squaring is not free in the prime-field bit basis, but it has symmetry absent from generic multiplication and the modulus is pseudo-Mersenne.", - "champion": "cf5aa02 promoted frontier", - "prior_evidence": "The present profile isolates square cost, but no square-specific global optimum certificate exists.", - "stepping_stones": [ - { - "id": "H2.1-bilinear-symmetry", - "claim": "Separate diagonal, doubled cross-term, and modular-fold costs in the exact reversible representation.", - "cheapest_discriminator": "symbolic carry/cross-term census on reduced widths", - "exit": "closed formula reproducing current 256-bit cost" - }, - { - "id": "H2.2-pseudo-mersenne-fold", - "claim": "Exploit p = 2^256 - 2^32 - 977 with a square-specific reduction schedule.", - "cheapest_discriminator": "classical exact arithmetic model plus reversible liveness bound", - "exit": "candidate schedule with lower T and bounded peak Q" - }, - { - "id": "H2.3-joint-square-reduction", - "claim": "Fuse production of high square limbs with modular reduction so temporary products never fully materialize.", - "cheapest_discriminator": "dependency DAG and peak-live interval solver", - "exit": "end-to-end square miter with positive score delta" - } - ] - }, - { - "id": "H3-coordinate-shell", - "role": "small direct Toffoli shell and correctness invariants", - "current_expected_toffoli": 1600.0, - "emitted_profile_ops": 1660, - "first_principle_constraint": "Its direct cost is small, but source-indexed invariants here can delete or constrain much larger controlled arithmetic upstream.", - "champion": "cf5aa02 promoted frontier", - "prior_evidence": "The q1145 local-miter counterexample proved that primitive equivalence does not imply full-circuit equivalence.", - "stepping_stones": [ - { - "id": "H3.1-source-indexed-invariants", - "claim": "Mine exact value, phase, cleanliness, and reachability facts at each callsite rather than assuming a primitive-wide domain.", - "cheapest_discriminator": "trusted-source lane census and exact callsite miter", - "exit": "machine-checkable invariant keyed to source and operation hashes" - }, - { - "id": "H3.2-offset-shell-fusion", - "claim": "Fuse offset injection and output shell corrections into adjacent controlled arithmetic.", - "cheapest_discriminator": "local symbolic composition plus full-stream op diff", - "exit": "non-no-op artifact with transferred full-circuit proof obligations explicit" - }, - { - "id": "H3.3-composition-counterexamples", - "claim": "Continuously replay retained q1145 and HMR/phase counterexamples against every new local proof scope.", - "cheapest_discriminator": "exact retained counterexample suite", - "exit": "zero unexplained counterexamples at the candidate scope" - } - ] - }, - { - "id": "H4-postpasses", - "role": "negative calibrated correction and proof-preserving transforms", - "current_expected_toffoli": -13127.198, - "first_principle_constraint": "A raw source saving is not real until the exact final stream survives strip, cap, cancellation, and density recalibration; the correction is artifact-bound, not additive folklore.", - "champion": "cf5aa02 postpass chain", - "prior_evidence": "Current profile removes 10743/10743 dead ops and downgrades 3088/3088, with 13127.198 expected Toffoli credit beyond pre-postpass terms.", - "stepping_stones": [ - { - "id": "H4.1-provenance-replay", - "claim": "Associate every removed/downgraded operation with an exact source and proof witness.", - "cheapest_discriminator": "content-addressed strip-key replay", - "exit": "zero stale/unattributed transformations" - }, - { - "id": "H4.2-contextual-identities", - "claim": "Search exact commuting/conjugation identities unavailable to local adjacency passes.", - "cheapest_discriminator": "bounded window canonicalization with exact phase-aware miter", - "exit": "strict semantic op reduction outside the known pass family" - }, - { - "id": "H4.3-density-calibration", - "claim": "Predict executed/static Toffoli conversion for the exact changed stream without reusing stale density.", - "cheapest_discriminator": "paired fixed-randomness differential", - "exit": "historically backtested error band narrow enough to gate a full run" - } - ] - }, - { - "id": "H5-width", - "role": "multiplicative qubit term and representation geometry", - "current_qubits": 1154, - "abi_qubit_floor": 512, - "first_principle_constraint": "Reducing peak Q helps only if added executed Toffoli stays below the exact break-even threshold; no nontrivial global Q lower bound beyond the 512 output wires is proved.", - "champion": "cf5aa02 promoted frontier", - "prior_evidence": "A q1145 artifact passed local miters but failed trusted full verification; width changes invalidate seed, cap, strip, density, and correctness evidence.", - "stepping_stones": [ - { - "id": "H5.1-live-interval-proof", - "claim": "Derive the exact source-indexed peak liveness witness and the minimum schedule under the current representation.", - "cheapest_discriminator": "interval graph / dependency schedule with operation replay", - "exit": "machine-checkable current-representation Q bound or lower schedule" - }, - { - "id": "H5.2-cap-break-even", - "claim": "For each proposed width, price recomputation and cap changes against the strict Toffoli threshold table.", - "cheapest_discriminator": "exact static rebuild plus calibrated executed-cost interval", - "exit": "score interval strictly below frontier before full spend" - }, - { - "id": "H5.3-alternative-representation", - "claim": "Evaluate projective, batch-inversion, or streaming representations end to end rather than importing published gate counts.", - "cheapest_discriminator": "full reversible dataflow model including conversion, cleanup, and peak liveness", - "exit": "complete candidate whose modeled QxT dominates the current frontier" - } - ] - } - ], - "aggregation_rule": "A candidate is promotable only after rebuilding every invalidated dependency, trusted 9024-shot certification, refreshed-frontier comparison, and exact artifact submission." -} diff --git a/src/point_add/memory/reframe_log.md b/src/point_add/memory/reframe_log.md deleted file mode 100644 index da623295..00000000 --- a/src/point_add/memory/reframe_log.md +++ /dev/null @@ -1,21 +0,0 @@ -# Reframe court - -Raw observations live in the hash-chained `.autoresearch/measurements.jsonl`; this file keeps -only durable ontology changes and forward predictions. - -## RF-001 — artifact and Fiat–Shamir draw are one state - -- **Previous ontology:** the zero scorer floor might be attained by encoding the finite 9,024 - verifier inputs as a free-classical lookup. -- **Why incomplete:** the table artifact changes the complete semantic operation stream, which - is the Fiat–Shamir seed; the dataset cannot be held fixed independently of the candidate. -- **Discriminator:** exact frozen-dataset construction followed by an exact self-seeded 9,024-pair - census in `repro/zero_score_lookup.py`. -- **Observation:** 27 prefix bits uniquely selected all frozen inputs; 3,042,193 X/condition ops - fit the cap and had zero frozen failures, but the candidate stream had zero table hits and - 9,024 self-seeded classical failures. -- **Compression:** artifact identity and verifier draw are one endogenous, content-addressed state. -- **Forward prediction:** a table derived from another stream will have negligible overlap after - reseeding. An attainable `H0-zero-rounding` construction must instead be seed-independent, - solve a semantic-stream fixed point, or generically extract/transform the quantum inputs. -- **Status:** previous ontology refuted; prediction retained for the next H0 discriminator. diff --git a/src/point_add/memory/repro/__pycache__/artifact_io.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/artifact_io.cpython-313.pyc deleted file mode 100644 index a5e83ca4..00000000 Binary files a/src/point_add/memory/repro/__pycache__/artifact_io.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/exact_scorer.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/exact_scorer.cpython-313.pyc deleted file mode 100644 index c20ac02b..00000000 Binary files a/src/point_add/memory/repro/__pycache__/exact_scorer.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/schema_harness.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/schema_harness.cpython-313.pyc deleted file mode 100644 index 69fbfe9f..00000000 Binary files a/src/point_add/memory/repro/__pycache__/schema_harness.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/test_exact_scorer.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/test_exact_scorer.cpython-313.pyc deleted file mode 100644 index 2131b68e..00000000 Binary files a/src/point_add/memory/repro/__pycache__/test_exact_scorer.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/test_repro_contracts.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/test_repro_contracts.cpython-313.pyc deleted file mode 100644 index 59e0947c..00000000 Binary files a/src/point_add/memory/repro/__pycache__/test_repro_contracts.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/test_schema_harness.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/test_schema_harness.cpython-313.pyc deleted file mode 100644 index 75f40eeb..00000000 Binary files a/src/point_add/memory/repro/__pycache__/test_schema_harness.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/test_world_model.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/test_world_model.cpython-313.pyc deleted file mode 100644 index 5fd577a5..00000000 Binary files a/src/point_add/memory/repro/__pycache__/test_world_model.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/world_model.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/world_model.cpython-313.pyc deleted file mode 100644 index 894f93bd..00000000 Binary files a/src/point_add/memory/repro/__pycache__/world_model.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y1_composite_synth.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y1_composite_synth.cpython-313.pyc deleted file mode 100644 index 6c13f0ef..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y1_composite_synth.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_joint_codec_neighborhood.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_joint_codec_neighborhood.cpython-313.pyc deleted file mode 100644 index 0ef745cd..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_joint_codec_neighborhood.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_joint_codec_stochastic.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_joint_codec_stochastic.cpython-313.pyc deleted file mode 100644 index 35e25c52..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_joint_codec_stochastic.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_joint_codec_synth.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_joint_codec_synth.cpython-313.pyc deleted file mode 100644 index 6d72570d..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_joint_codec_synth.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_joint_codec_triple_fusion.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_joint_codec_triple_fusion.cpython-313.pyc deleted file mode 100644 index 3ae7d9f4..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_joint_codec_triple_fusion.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_joint_codec_two_rebase.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_joint_codec_two_rebase.cpython-313.pyc deleted file mode 100644 index 52934589..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_joint_codec_two_rebase.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_normalizer_synth.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_normalizer_synth.cpython-313.pyc deleted file mode 100644 index 4c19d038..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_normalizer_synth.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/__pycache__/y5_pair25_quotient.cpython-313.pyc b/src/point_add/memory/repro/__pycache__/y5_pair25_quotient.cpython-313.pyc deleted file mode 100644 index cf57e3e8..00000000 Binary files a/src/point_add/memory/repro/__pycache__/y5_pair25_quotient.cpython-313.pyc and /dev/null differ diff --git a/src/point_add/memory/repro/artifact_io.py b/src/point_add/memory/repro/artifact_io.py deleted file mode 100755 index 98fd8f36..00000000 --- a/src/point_add/memory/repro/artifact_io.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -"""Canonical hashing and bounded record I/O for QECCOPSZ artifacts.""" - -from __future__ import annotations - -import hashlib -import shutil -import struct -import subprocess -from pathlib import Path -from typing import Any, BinaryIO - -try: - import numpy as _numpy -except ImportError: - _numpy = None - -MAGIC = b"QECCOPSZ" -HEADER_BYTES = 16 -RECORD_BYTES = 56 -CANONICAL_RECORD_BYTES = 49 -MAX_OPS = 4_000_000_000 -NO_QUBIT = (1 << 64) - 1 -X_KIND = 6 -TAIL_RECORDS = 96 - - -def _zstd() -> str: - executable = shutil.which("zstd") - if executable is None: - raise RuntimeError("zstd executable not found") - return executable - - -def read_header(source: BinaryIO) -> tuple[bytes, int]: - header = source.read(HEADER_BYTES) - if len(header) != HEADER_BYTES: - raise ValueError("ops artifact is too short for its header") - if header[: len(MAGIC)] != MAGIC: - raise ValueError("ops artifact has invalid magic") - count = struct.unpack(" MAX_OPS: - raise ValueError(f"op count {count} exceeds cap {MAX_OPS}") - return header, count - - -def fingerprint(path: Path) -> dict[str, Any]: - compressed_hasher = hashlib.sha256() - with path.open("rb") as source: - header, count = read_header(source) - compressed_hasher.update(header) - while chunk := source.read(8 * 1024 * 1024): - compressed_hasher.update(chunk) - - canonical_hasher = hashlib.sha256(struct.pack("= len(kind_counts)) - if invalid_kinds.size: - index = int(invalid_kinds[0]) - raise ValueError( - f"unknown kind {int(kinds[index])} at op {decoded_records + index}" - ) - invalid_padding = _numpy.flatnonzero(_numpy.any(raw[:, 4:8] != 0, axis=1)) - if invalid_padding.size: - raise ValueError( - f"nonzero reserved padding at op {decoded_records + int(invalid_padding[0])}" - ) - counts = _numpy.bincount(kinds, minlength=len(kind_counts)) - kind_counts = [ - current + int(delta) for current, delta in zip(kind_counts, counts) - ] - canonical = _numpy.empty( - (len(kinds), CANONICAL_RECORD_BYTES), dtype=_numpy.uint8 - ) - canonical[:, 0] = kinds - canonical[:, 1:] = raw[:, 8:RECORD_BYTES] - canonical_hasher.update(canonical) - qubits = raw[:, 8:32].copy().view("= len(kind_counts): - raise ValueError(f"unknown kind {kind} at op {decoded_records}") - if records[offset + 4 : offset + 8].tobytes() != b"\0\0\0\0": - raise ValueError(f"nonzero reserved padding at op {decoded_records}") - kind_counts[kind] += 1 - canonical[canonical_offset] = kind - canonical[ - canonical_offset + 1 : canonical_offset + CANONICAL_RECORD_BYTES - ] = records[offset + 8 : offset + RECORD_BYTES] - for operand_offset in (offset + 8, offset + 16, offset + 24): - qubit = struct.unpack_from(" max_qubit_id: - max_qubit_id = qubit - canonical_offset += CANONICAL_RECORD_BYTES - decoded_records += 1 - canonical_hasher.update(canonical) - remainder = records[complete:].tobytes() - decoder.stdout.close() - stderr = decoder.stderr.read().decode("utf-8", errors="replace") if decoder.stderr else "" - if decoder.stderr: - decoder.stderr.close() - returncode = decoder.wait() - if returncode != 0: - raise RuntimeError(f"zstd decoder failed: {stderr.strip()}") - if remainder: - raise ValueError(f"decompressed body has {len(remainder)} trailing partial-record bytes") - if decoded_records != count: - raise ValueError(f"decoded {decoded_records} records, expected {count}") - return { - "emitted_ops": count, - "canonical_semantic_sha256": canonical_hasher.hexdigest(), - "compressed_ops_sha256": compressed_hasher.hexdigest(), - "max_referenced_qubit_id": max_qubit_id, - "qubits": max_qubit_id + 1, - "operation_kind_counts": kind_counts, - } - - -def decompress_record_body(source_path: Path, destination_path: Path) -> dict[str, Any]: - raw_hasher = hashlib.sha256() - with source_path.open("rb", buffering=0) as source: - _, count = read_header(source) - source.seek(HEADER_BYTES) - decoder = subprocess.Popen( - [_zstd(), "-d", "-q", "-c"], - stdin=source, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - assert decoder.stdout is not None - size = 0 - with destination_path.open("wb") as destination: - while chunk := decoder.stdout.read(8 * 1024 * 1024): - destination.write(chunk) - raw_hasher.update(chunk) - size += len(chunk) - decoder.stdout.close() - stderr = decoder.stderr.read().decode("utf-8", errors="replace") if decoder.stderr else "" - if decoder.stderr: - decoder.stderr.close() - returncode = decoder.wait() - expected_size = count * RECORD_BYTES - if returncode != 0: - raise RuntimeError(f"zstd decoder failed: {stderr.strip()}") - if size != expected_size: - raise ValueError(f"decompressed body has {size} bytes, expected {expected_size}") - return {"emitted_ops": count, "raw_bytes": size, "raw_sha256": raw_hasher.hexdigest()} - - -def write_nonce_artifact( - raw_records_path: Path, - destination_path: Path, - emitted_ops: int, - nonce: int, -) -> None: - if nonce < 0 or nonce >= 1 << 48: - raise ValueError("nonce must be a 48-bit unsigned integer") - expected_size = emitted_ops * RECORD_BYTES - if raw_records_path.stat().st_size != expected_size: - raise ValueError("raw record body size does not match emitted op count") - tail_bytes = TAIL_RECORDS * RECORD_BYTES - prefix_bytes = expected_size - tail_bytes - if prefix_bytes < 0: - raise ValueError("artifact is shorter than the protected nonce tail") - - destination_path.parent.mkdir(parents=True, exist_ok=True) - with raw_records_path.open("rb") as raw, destination_path.open("wb", buffering=0) as destination: - destination.write(MAGIC) - destination.write(struct.pack("> bit & 1 else 0 - for pair_offset in (2 * bit, 2 * bit + 1): - struct.pack_into(" int: - return score(self.average_toffoli, self.qubits) - - -@dataclass(frozen=True, slots=True) -class ArchiveNode: - candidate_id: str - parent_candidate_id: str | None - niche: str - iteration: int - status: str - frontier_submission_id: str - source_ref: str | None - artifact_ops_sha256: str | None - canonical_artifact_sha256: str | None - actual_score: int | None - average_toffoli: float | None - qubits: int | None - emitted_ops: int | None - predicted_score: float - prediction_standard_deviation: float - conservative_score: float - functioning: bool - reproducible: bool - functioning_children: int = 0 - emitter: str | None = None - evidence: str | None = None - - def to_mapping(self) -> dict[str, Any]: - return asdict(self) - - -@dataclass(frozen=True, slots=True) -class ParentChoice: - node: ArchiveNode - niche: str - iteration: int - ledger_tail_sha256: str - seed: int - rank_percentile: float - quality: float - weight: float - probability: float - - def to_mapping(self) -> dict[str, Any]: - result = asdict(self) - result["node"] = self.node.to_mapping() - return result - - -@dataclass(frozen=True, slots=True) -class StageResult: - stage: str - passed: bool - conclusion: str - evidence_kind: str - artifact_ops_sha256: str | None - canonical_artifact_sha256: str | None - measurement: dict[str, Any] | None - - -@dataclass(frozen=True, slots=True) -class PublicFrontier: - submission_id: str - source_ref: str - score: int - qubits: int - rounded_toffoli: int - - -_ANSI_ESCAPE = re.compile(r"\x1b\[[0-9;]*m") -_PUBLIC_ROW = re.compile( - r"^([0-9a-f]{7})\s+.*?\s+promoted\s+([0-9]+)\s+" - r'\{"qubits":([0-9]+),"toffoli":([0-9]+)\}.*?\s+' - r"([0-9a-f]{7,40})\s+[0-9]+/[0-9]+/[0-9]+", -) - - -def repo_root() -> Path: - return Path(__file__).resolve().parents[4] - - -def _records_of_type( - records: Sequence[Mapping[str, Any]], record_type: str -) -> list[Mapping[str, Any]]: - return [record for record in records if record.get("type") == record_type] - - -def _latest_by( - records: Iterable[Mapping[str, Any]], key: str -) -> dict[Any, Mapping[str, Any]]: - latest: dict[Any, Mapping[str, Any]] = {} - for record in records: - value = record.get(key) - if value is not None: - latest[value] = record - return latest - - -def _frontier_id(frontier: Mapping[str, Any]) -> str: - return f"{str(frontier['source_ref'])[:7]}-frontier" - - -def _clean_full_observation(record: Mapping[str, Any]) -> bool: - if ( - record.get("type") != "observation" - or record.get("stage") != "full" - or record.get("verdict") != "pass" - ): - return False - measurement = record.get("measurement") - if not isinstance(measurement, Mapping): - return False - try: - exact_score = score( - float(measurement["average_toffoli"]), - int(measurement["qubits"]), - ) - except (KeyError, TypeError, ValueError): - return False - return ( - measurement.get("shots") == FULL_SHOTS - and measurement.get("score") == exact_score - and all( - measurement.get(key) == 0 - for key in ( - "classical_failures", - "phase_garbage_batches", - "ancilla_garbage_batches", - ) - ) - ) - - -def _full_observations( - records: Sequence[Mapping[str, Any]], -) -> dict[int, Mapping[str, Any]]: - result: dict[int, Mapping[str, Any]] = {} - for record in records: - if record.get("type") == "observation" and record.get("stage") == "full": - result[int(record["iteration"])] = record - return result - - -def _submission_by_iteration( - records: Sequence[Mapping[str, Any]], -) -> dict[int, Mapping[str, Any]]: - result: dict[int, Mapping[str, Any]] = {} - for record in _records_of_type(records, "submission"): - if record.get("status") == "promoted": - result[int(record["iteration"])] = record - return result - - -def build_archive( - records: Sequence[Mapping[str, Any]], - *, - repo: Path | None = None, -) -> tuple[ArchiveNode, ...]: - """Rebuild the complete stepping-stone archive from ledger records.""" - if not records or records[0].get("type") != "frontier": - raise ValueError("archive requires a ledger beginning with frontier") - frontier = records[0] - root_id = _frontier_id(frontier) - root_metrics = Metrics( - average_toffoli=float(frontier["rounded_toffoli"]), - qubits=int(frontier["qubits"]), - ) - latest_candidates = _latest_by( - _records_of_type(records, "candidate"), "candidate_id" - ) - predictions = _latest_by( - _records_of_type(records, "prediction"), "candidate_id" - ) - predictions_by_iteration = { - int(record["iteration"]): record - for record in _records_of_type(records, "prediction") - } - candidate_ids_by_iteration: dict[int, set[str]] = {} - for candidate_id, candidate in latest_candidates.items(): - candidate_ids_by_iteration.setdefault(int(candidate["iteration"]), set()).add( - str(candidate_id) - ) - observations = _full_observations(records) - submissions = _submission_by_iteration(records) - - candidate_ids = set(predictions) | set(latest_candidates) - parent_ids = { - str(record.get("parent_candidate_id")) - for record in (*predictions.values(), *latest_candidates.values()) - if record.get("parent_candidate_id") - } - unresolved_parent_ids = sorted(parent_ids - candidate_ids - {root_id}) - root = ArchiveNode( - candidate_id=root_id, - parent_candidate_id=None, - niche=_FRONTIER_NICHE, - iteration=0, - status="promoted", - frontier_submission_id=str(frontier["submission_id"]), - source_ref=str(frontier["source_ref"]), - artifact_ops_sha256=str(frontier["ops_sha256"]), - canonical_artifact_sha256=str(frontier["canonical_ops_sha256"]), - actual_score=int(frontier["score"]), - average_toffoli=root_metrics.average_toffoli, - qubits=root_metrics.qubits, - emitted_ops=None, - predicted_score=float(frontier["score"]), - prediction_standard_deviation=0.0, - conservative_score=float(frontier["score"]), - functioning=True, - reproducible=( - repo is None or _ref_commit(repo, str(frontier["source_ref"])) is not None - ), - evidence="initial trusted frontier", - ) - metrics: dict[str, Metrics] = {root_id: root_metrics} - nodes: dict[str, ArchiveNode] = {root_id: root} - for alias in unresolved_parent_ids: - nodes[alias] = ArchiveNode( - candidate_id=alias, - parent_candidate_id=None, - niche=_FRONTIER_NICHE, - iteration=0, - status="retired", - frontier_submission_id=str(frontier["submission_id"]), - source_ref=None, - artifact_ops_sha256=None, - canonical_artifact_sha256=None, - actual_score=None, - average_toffoli=None, - qubits=None, - emitted_ops=None, - predicted_score=WORST_SCORE, - prediction_standard_deviation=WORST_SCORE, - conservative_score=WORST_SCORE, - functioning=False, - reproducible=False, - evidence="unresolved external parent placeholder", - ) - - unresolved = set(candidate_ids) - while unresolved: - progressed = False - for candidate_id in sorted(unresolved): - prediction = predictions.get(candidate_id) - candidate = latest_candidates.get(candidate_id) - inherited_prediction = ( - predictions_by_iteration.get(int(candidate["iteration"])) - if candidate is not None - else None - ) - model_prediction = prediction or inherited_prediction - source = candidate or prediction - if source is None: - unresolved.remove(candidate_id) - progressed = True - continue - parent_id = str(source.get("parent_candidate_id") or root_id) - parent_metrics = metrics.get(parent_id) - if parent_metrics is None and parent_id in unresolved: - continue - if parent_metrics is None: - parent_metrics = root_metrics - - iteration = int( - source.get( - "iteration", - model_prediction.get("iteration", 0) if model_prediction else 0, - ) - ) - retained_ids = candidate_ids_by_iteration.get(iteration, set()) - owns_iteration_evidence = candidate is not None or not retained_ids - full = observations.get(iteration) if owns_iteration_evidence else None - submission = submissions.get(iteration) if owns_iteration_evidence else None - actual_metrics: Metrics | None = None - actual_score: int | None = None - if full is not None and isinstance(full.get("measurement"), Mapping): - measurement = full["measurement"] - if "average_toffoli" in measurement and "qubits" in measurement: - actual_metrics = Metrics( - float(measurement["average_toffoli"]), - int(measurement["qubits"]), - ) - actual_score = int(measurement.get("score", actual_metrics.score)) - if candidate is not None and all( - key in candidate - for key in ("actual_average_toffoli", "actual_qubits", "actual_score") - ): - actual_metrics = Metrics( - float(candidate["actual_average_toffoli"]), - int(candidate["actual_qubits"]), - ) - actual_score = int(candidate["actual_score"]) - if submission is not None: - actual_score = int(submission["official_score"]) - - predicted_metrics = parent_metrics - conservative = float(parent_metrics.score) - predicted_score = float(parent_metrics.score) - predicted_sigma = 0.0 - if model_prediction is not None: - predicted_metrics = Metrics( - max( - 0.0, - parent_metrics.average_toffoli - + float(model_prediction["delta_toffoli_mean"]), - ), - max( - 0, - parent_metrics.qubits - + int(model_prediction["delta_qubits"]), - ), - ) - upper_metrics = Metrics( - max( - 0.0, - predicted_metrics.average_toffoli - + 2.0 - * float( - model_prediction["delta_toffoli_standard_deviation"] - ), - ), - predicted_metrics.qubits, - ) - predicted_score = float(predicted_metrics.score) - conservative = float(upper_metrics.score) - predicted_sigma = max(0.0, (conservative - predicted_score) / 2.0) - if actual_metrics is not None: - metrics[candidate_id] = actual_metrics - predicted_score = float(actual_score if actual_score is not None else actual_metrics.score) - conservative = predicted_score - predicted_sigma = 0.0 - else: - metrics[candidate_id] = predicted_metrics - - status = str(candidate.get("status", "retired") if candidate else "retired") - functioning = ( - status == "promoted" - or (full is not None and _clean_full_observation(full)) - or submission is not None - ) - source_ref = None - if candidate is not None and candidate.get("source_ref"): - source_ref = str(candidate["source_ref"]) - elif submission is not None and submission.get("source_ref"): - source_ref = str(submission["source_ref"]) - archived_ref = candidate_ref(str(candidate_id)) - reproducible = bool( - repo is not None - and ( - _ref_commit(repo, archived_ref) - or (source_ref and _ref_commit(repo, source_ref)) - ) - ) - if repo is None: - reproducible = bool(source_ref) - node = ArchiveNode( - candidate_id=str(candidate_id), - parent_candidate_id=parent_id, - niche=str(source.get("niche", _FRONTIER_NICHE)), - iteration=iteration, - status=status, - frontier_submission_id=( - str(submission["submission_id"]) - if submission is not None - else ( - str(candidate["official_submission_id"]) - if candidate is not None - and candidate.get("official_submission_id") - else ( - str(candidate["parent_frontier_submission_id"]) - if candidate is not None - and candidate.get("parent_frontier_submission_id") - else nodes.get(parent_id, root).frontier_submission_id - ) - ) - ), - source_ref=source_ref, - artifact_ops_sha256=( - str(candidate["artifact_ops_sha256"]) - if candidate is not None and candidate.get("artifact_ops_sha256") - else ( - str(full["artifact_ops_sha256"]) - if full is not None and full.get("artifact_ops_sha256") - else None - ) - ), - canonical_artifact_sha256=( - str(candidate["canonical_artifact_sha256"]) - if candidate is not None - and candidate.get("canonical_artifact_sha256") - else None - ), - actual_score=actual_score, - average_toffoli=metrics[candidate_id].average_toffoli, - qubits=metrics[candidate_id].qubits, - emitted_ops=( - int(candidate["emitted_ops"]) - if candidate is not None and candidate.get("emitted_ops") is not None - else None - ), - predicted_score=predicted_score, - prediction_standard_deviation=predicted_sigma, - conservative_score=conservative, - functioning=functioning, - reproducible=reproducible, - emitter=( - str(candidate["emitter"]) - if candidate is not None and candidate.get("emitter") - else None - ), - evidence=( - str(candidate["evidence"]) - if candidate is not None and candidate.get("evidence") - else None - ), - ) - nodes[candidate_id] = node - unresolved.remove(candidate_id) - progressed = True - if not progressed: - # A malformed lineage must remain inspectable rather than hanging. - for candidate_id in sorted(unresolved): - prediction = predictions.get(candidate_id) - candidate = latest_candidates.get(candidate_id) - source = candidate or prediction or {} - nodes[candidate_id] = ArchiveNode( - candidate_id=str(candidate_id), - parent_candidate_id=( - str(source["parent_candidate_id"]) - if source.get("parent_candidate_id") - else root_id - ), - niche=str(source.get("niche", _FRONTIER_NICHE)), - iteration=int(source.get("iteration", 0)), - status=str(source.get("status", "retired")), - frontier_submission_id=root.frontier_submission_id, - source_ref=None, - artifact_ops_sha256=None, - canonical_artifact_sha256=None, - actual_score=None, - average_toffoli=None, - qubits=None, - emitted_ops=None, - predicted_score=float(frontier["score"]), - prediction_standard_deviation=0.0, - conservative_score=float(frontier["score"]), - functioning=False, - reproducible=False, - evidence="unresolved lineage", - ) - break - - child_counts: dict[str, int] = {} - for node in nodes.values(): - if node.functioning and node.reproducible and node.parent_candidate_id is not None: - child_counts[node.parent_candidate_id] = ( - child_counts.get(node.parent_candidate_id, 0) + 1 - ) - return tuple( - replace(node, functioning_children=child_counts.get(node.candidate_id, 0)) - for node in sorted(nodes.values(), key=lambda item: (item.iteration, item.candidate_id)) - ) - - -def selection_seed(iteration: int, ledger_tail_sha256: str) -> int: - material = f"dgm-search-v1:{iteration}:{ledger_tail_sha256}".encode() - return int.from_bytes(hashlib.sha256(material).digest()[:16], "big") - - -def select_emitter( - records: Sequence[Mapping[str, Any]], - *, - iteration: int, - ledger_tail_sha256: str, -) -> dict[str, Any]: - if iteration == 63: - return {"emitter": "literature", "reason": "first post-62 transfer"} - last_observation = next( - ( - record - for record in reversed(records) - if record.get("type") == "observation" - ), - None, - ) - if last_observation is not None and last_observation.get("prediction_match") is False: - return {"emitter": "abductor", "reason": "latest result mismatched prediction"} - attempts = {emitter: 0 for emitter in EMITTERS} - contributions = {emitter: 0 for emitter in EMITTERS} - for record in _records_of_type(records, "candidate"): - emitter = record.get("emitter") - if emitter not in attempts: - continue - attempts[str(emitter)] += 1 - contributions[str(emitter)] += int( - record.get("archive_contribution") is True - ) - total = sum(attempts.values()) - scores: dict[str, float] = {} - for emitter in EMITTERS: - count = attempts[emitter] - scores[emitter] = ( - math.inf - if count == 0 - else contributions[emitter] / count - + math.sqrt(2.0 * math.log(total + 1.0) / count) - ) - best = max(scores.values()) - tied = sorted(emitter for emitter, value in scores.items() if value == best) - index = selection_seed(iteration, ledger_tail_sha256) % len(tied) - return { - "emitter": tied[index], - "reason": "UCB on archive-cell contribution", - "attempts": attempts, - "contributions": contributions, - "ucb": { - emitter: (None if math.isinf(value) else value) - for emitter, value in scores.items() - }, - } - - -def parent_distribution( - nodes: Sequence[ArchiveNode], - niche: str, -) -> tuple[tuple[ArchiveNode, float, float, float, float], ...]: - """Return node, rank percentile, quality, weight, probability.""" - if niche not in NICHES: - raise ValueError(f"unknown niche {niche}") - # The portfolio chooses the problem niche; it does not erase useful - # stepping stones from other cells. This also permits recombination from a - # distant lineage while keeping the proposed mechanism targeted at `niche`. - eligible = [ - node for node in nodes if node.functioning and node.reproducible - ] - if not eligible: - raise ValueError(f"no functioning parent for niche {niche}") - ranked = sorted(eligible, key=lambda node: (node.conservative_score, node.candidate_id)) - weighted: list[tuple[ArchiveNode, float, float, float]] = [] - denominator = max(1, len(ranked) - 1) - for rank, node in enumerate(ranked): - percentile = rank / denominator if len(ranked) > 1 else 0.0 - quality = math.exp(-2.0 * percentile) - weight = (0.05 + quality) / (1.0 + node.functioning_children) - weighted.append((node, percentile, quality, weight)) - total = sum(item[3] for item in weighted) - return tuple((*item, item[3] / total) for item in weighted) - - -def choose_parent( - nodes: Sequence[ArchiveNode], - *, - niche: str, - iteration: int, - ledger_tail_sha256: str, -) -> ParentChoice: - distribution = parent_distribution(nodes, niche) - seed = selection_seed(iteration, ledger_tail_sha256) - draw = random.Random(seed).random() - cumulative = 0.0 - selected = distribution[-1] - for item in distribution: - cumulative += item[4] - if draw < cumulative: - selected = item - break - node, percentile, quality, weight, probability = selected - return ParentChoice( - node=node, - niche=niche, - iteration=iteration, - ledger_tail_sha256=ledger_tail_sha256, - seed=seed, - rank_percentile=percentile, - quality=quality, - weight=weight, - probability=probability, - ) - - -def candidate_ref(candidate_id: str) -> str: - if not _CANDIDATE_ID.fullmatch(candidate_id) or ".." in candidate_id: - raise ValueError(f"candidate id is not safe for a Git ref: {candidate_id!r}") - reference = f"{CANDIDATE_REF_PREFIX}/{candidate_id}" - if subprocess.run( - ["git", "check-ref-format", reference], - capture_output=True, - ).returncode: - raise ValueError(f"candidate id is not a valid Git ref: {candidate_id!r}") - return reference - - -def sanitized_environment( - source: Mapping[str, str] | None = None, -) -> dict[str, str]: - """Strip credentials and process-injection variables from child agents.""" - environment = dict(os.environ if source is None else source) - for key in tuple(environment): - upper = key.upper() - if ( - key in _DANGEROUS_ENV - or upper in _PROXY_ENV - or any(marker in upper for marker in _SECRET_MARKERS) - ): - environment.pop(key, None) - environment["CARGO_NET_OFFLINE"] = "true" - return environment - - -def validate_mutation_paths(paths: Iterable[str]) -> tuple[str, ...]: - """Reject every mutation outside Rust implementation files in point_add.""" - accepted: list[str] = [] - for raw in paths: - path = Path(raw) - if path.is_absolute() or ".." in path.parts: - raise ValueError(f"unsafe mutation path: {raw}") - if ( - not path.is_relative_to(ALLOWED_MUTATION_ROOT) - or path.suffix not in ALLOWED_MUTATION_SUFFIXES - or "memory" in path.parts - ): - raise ValueError(f"mutation escaped editable Rust surface: {raw}") - accepted.append(path.as_posix()) - if not accepted: - raise ValueError("mutation produced no editable Rust changes") - return tuple(sorted(set(accepted))) - - -def validate_mutation_tree(worktree: Path, paths: Iterable[str]) -> tuple[str, ...]: - accepted = validate_mutation_paths(paths) - for raw in accepted: - path = worktree / raw - if path.is_symlink(): - raise ValueError(f"mutation created a symlink: {raw}") - if path.exists() and not path.is_file(): - raise ValueError(f"mutation created a non-file path: {raw}") - summary = _git_output(worktree, "diff", "--summary") - if any( - marker in summary - for marker in ("mode change", "create mode 120000", "Subproject commit") - ): - raise ValueError(f"mutation changed file type or mode: {summary}") - return accepted - - -def semantic_noop( - artifact: Mapping[str, Any], - *, - parent_compressed_sha256: str, - parent_canonical_sha256: str | None, -) -> bool: - if parent_canonical_sha256: - return artifact.get("canonical_semantic_sha256") == parent_canonical_sha256 - return artifact.get("compressed_ops_sha256") == parent_compressed_sha256 - - -def validate_and_apply_patch(worktree: Path, patch: str) -> tuple[str, ...]: - if len(patch.encode("utf-8")) > 2 * 1024 * 1024: - raise ValueError("mutation patch exceeds 2 MiB") - forbidden = ( - "GIT binary patch", - "Binary files ", - "old mode ", - "new mode ", - "similarity index ", - "rename from ", - "rename to ", - "Subproject commit ", - ) - if any(marker in patch for marker in forbidden): - raise ValueError("mutation patch contains binary, mode, rename, or submodule data") - headers = re.findall(r"^diff --git a/(\S+) b/(\S+)$", patch, flags=re.MULTILINE) - if not headers: - raise ValueError("mutation output is not a Git unified diff") - header_paths: list[str] = [] - for before, after in headers: - if before != after: - raise ValueError("mutation patch may not rename files") - header_paths.append(after) - validate_mutation_paths(header_paths) - for arguments in (("--check", "--whitespace=error-all"), ()): - completed = subprocess.run( - ["git", "-C", str(worktree), "apply", *arguments, "-"], - input=patch, - capture_output=True, - text=True, - ) - if completed.returncode: - raise ValueError(f"git apply failed: {completed.stderr.strip()}") - changed = _changed_paths(worktree) - return validate_mutation_tree(worktree, changed) - - -def verify_upstream_clone(repo: Path) -> dict[str, Any]: - clone = repo / ".autoresearch/upstream/dgm" - if not clone.is_dir(): - raise ValueError(f"missing pinned DGM clone: {clone}") - head = _git_output(clone, "rev-parse", "HEAD") - origin = _git_output(clone, "remote", "get-url", "origin") - if head != DGM_UPSTREAM_REVISION: - raise ValueError(f"DGM revision mismatch: {head}") - if origin.rstrip("/") != DGM_UPSTREAM_URL.rstrip("/"): - raise ValueError(f"DGM origin mismatch: {origin}") - return {"path": str(clone), "origin": origin, "revision": head, "verdict": "green"} - - -def _git_output(repo: Path, *arguments: str) -> str: - completed = subprocess.run( - ["git", "-C", str(repo), *arguments], - check=True, - capture_output=True, - text=True, - ) - return completed.stdout.strip() - - -def _ref_commit(repo: Path, reference: str) -> str | None: - completed = subprocess.run( - ["git", "-C", str(repo), "rev-parse", "--verify", "--quiet", f"{reference}^{{commit}}"], - capture_output=True, - text=True, - ) - return completed.stdout.strip() or None - - -def resolve_parent_ref(repo: Path, node: ArchiveNode) -> str: - archived = candidate_ref(node.candidate_id) - if _ref_commit(repo, archived): - return archived - if node.source_ref and _ref_commit(repo, node.source_ref): - return node.source_ref - raise ValueError( - f"parent {node.candidate_id} has no local candidate ref or resolvable source ref" - ) - - -def _best_score(records: Sequence[Mapping[str, Any]]) -> int: - scores = [int(records[0]["score"])] - scores.extend( - int(record["official_score"]) - for record in _records_of_type(records, "submission") - if record.get("status") == "promoted" - ) - scores.extend( - int(record["actual_score"]) - for record in _records_of_type(records, "candidate") - if record.get("status") == "promoted" - and record.get("official_submission_id") - and record.get("actual_score") is not None - ) - for record in records: - if _clean_full_observation(record): - measurement = record.get("measurement") - if isinstance(measurement, Mapping) and "score" in measurement: - scores.append(int(measurement["score"])) - return min(scores) - - -def parse_public_frontier_table(output: str) -> PublicFrontier: - rows: list[PublicFrontier] = [] - for raw in output.splitlines(): - line = _ANSI_ESCAPE.sub("", raw) - match = _PUBLIC_ROW.match(line) - if match is None: - continue - submission, raw_score, raw_qubits, raw_toffoli, source = match.groups() - rows.append( - PublicFrontier( - submission_id=submission, - source_ref=source, - score=int(raw_score), - qubits=int(raw_qubits), - rounded_toffoli=int(raw_toffoli), - ) - ) - if not rows: - raise ValueError("could not parse any promoted public frontier rows") - return min(rows, key=lambda row: (row.score, row.submission_id)) - - -def refresh_public_frontier(repo: Path, *, timeout: int = 120) -> PublicFrontier: - completed = _run_with_timeout( - ["ecdsafail", "submissions", "--all"], - cwd=repo, - environment=sanitized_environment(), - timeout=timeout, - ) - if completed.returncode: - raise RuntimeError(f"public frontier refresh failed: {completed.stderr[-1000:]}") - short = parse_public_frontier_table(completed.stdout) - main_rows = _git_ls_remote(repo, "refs/heads/main") - if len(main_rows) != 1 or not main_rows[0][0].startswith(short.source_ref): - raise RuntimeError("public table and origin/main advanced inconsistently; retry") - submission_rows = _git_ls_remote( - repo, f"refs/heads/submissions/{short.submission_id}*" - ) - if len(submission_rows) != 1: - raise RuntimeError( - f"could not resolve public submission {short.submission_id} to one full id" - ) - full_submission_id = submission_rows[0][1].rsplit("/", 1)[-1] - return replace( - short, - submission_id=full_submission_id, - source_ref=main_rows[0][0], - ) - - -def _git_ls_remote(repo: Path, pattern: str) -> list[tuple[str, str]]: - completed = subprocess.run( - ["git", "-C", str(repo), "ls-remote", "origin", pattern], - check=True, - capture_output=True, - text=True, - ) - rows: list[tuple[str, str]] = [] - for line in completed.stdout.splitlines(): - if not line.strip(): - continue - commit, reference = line.split("\t", 1) - rows.append((commit, reference)) - return rows - - -def ensure_ready(records: Sequence[Mapping[str, Any]]) -> dict[str, Any]: - report = backtest(tuple(dict(record) for record in records)) - if report["verdict"] != "green": - raise ValueError(f"schema harness is red: {report['failures']}") - if report["pending_iteration"] is not None: - raise ValueError(f"iteration {report['pending_iteration']} is still pending") - if report["iterations_started"] >= MAX_ITERATIONS: - raise ValueError(f"iteration cap {MAX_ITERATIONS} reached") - if _best_score(records) == 0: - raise ValueError("certified score-zero stop condition reached") - return report - - -def pending_dgm_prediction( - records: Sequence[Mapping[str, Any]], -) -> Mapping[str, Any] | None: - report = backtest(tuple(dict(record) for record in records)) - pending = report.get("pending_iteration") - if pending is None: - return None - for record in reversed(records): - if ( - record.get("type") == "prediction" - and record.get("iteration") == pending - and str(record.get("candidate_id", "")).startswith("dgm-i") - ): - return record - return None - - -def recover_pending_infrastructure_error( - ledger: Path, - *, - conclusion: str, -) -> dict[str, Any]: - """Close only a DGM-owned pending iteration after an infrastructure crash.""" - records = load_ledger(ledger) - prediction = pending_dgm_prediction(records) - if prediction is None: - raise ValueError("there is no pending DGM iteration to recover") - observation = { - "type": "observation", - "iteration": int(prediction["iteration"]), - "observation_id": f"{prediction['candidate_id']}-infrastructure-error", - "stage": "hash", - "evidence_kind": EvidenceKind.NARRATIVE.value, - "verdict": "error", - "artifact_ops_sha256": None, - "prediction_match": None, - "measurement": None, - "conclusion": conclusion, - } - return append_payload(ledger, observation) - - -def archive_report( - records: Sequence[Mapping[str, Any]], - *, - repo: Path | None = None, -) -> dict[str, Any]: - report = backtest(tuple(dict(record) for record in records)) - nodes = build_archive(records, repo=repo) - next_iteration = int(report["iterations_started"]) + 1 - niche = str(report["portfolio"]["selected_niche"]) - choice = choose_parent( - nodes, - niche=niche, - iteration=next_iteration, - ledger_tail_sha256=str(report["tail_sha256"]), - ) - mapping: dict[str, Any] = { - "schema_version": 1, - "derived_from_tail_sha256": report["tail_sha256"], - "iterations_started": report["iterations_started"], - "best_score": _best_score(records), - "next_niche": niche, - "next_emitter": select_emitter( - records, - iteration=next_iteration, - ledger_tail_sha256=str(report["tail_sha256"]), - ), - "nodes": [node.to_mapping() for node in nodes], - "next_parent": choice.to_mapping(), - } - if repo is not None: - mapping["next_parent"]["resolvable_ref"] = ( - resolve_parent_ref(repo, choice.node) - if ( - _ref_commit(repo, candidate_ref(choice.node.candidate_id)) - or (choice.node.source_ref and _ref_commit(repo, choice.node.source_ref)) - ) - else None - ) - return mapping - - -def _atomic_json(path: Path, value: Mapping[str, Any]) -> None: - path.parent.mkdir(parents=True, exist_ok=True) - encoded = json.dumps(value, sort_keys=True, indent=2) + "\n" - with tempfile.NamedTemporaryFile( - "w", encoding="utf-8", dir=path.parent, delete=False - ) as destination: - destination.write(encoded) - temporary = Path(destination.name) - os.replace(temporary, path) - - -@contextmanager -def controller_lock(path: Path) -> Iterable[None]: - path.parent.mkdir(parents=True, exist_ok=True) - with path.open("a+", encoding="utf-8") as lock: - try: - fcntl.flock(lock.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) - except BlockingIOError as error: - raise RuntimeError(f"another DGM controller holds {path}") from error - try: - yield - finally: - fcntl.flock(lock.fileno(), fcntl.LOCK_UN) - - -def _slug(value: str) -> str: - slug = re.sub(r"[^A-Za-z0-9._-]+", "-", value.strip()).strip(".-") - slug = re.sub(r"-+", "-", slug)[:48] - return slug or "candidate" - - -def _proposal_to_prediction( - proposal: Mapping[str, Any], - *, - iteration: int, - niche: str, - parent: ArchiveNode, -) -> dict[str, Any]: - action_kind = ActionKind(str(proposal["action_kind"])) - if action_kind in {ActionKind.NO_EFFECT, ActionKind.PROMOTION}: - raise ValueError(f"invalid mutation action kind: {action_kind.value}") - candidate_id = f"dgm-i{iteration:03d}-{_slug(str(proposal['candidate_id']))}" - candidate_ref(candidate_id) - parent_hash = parent.artifact_ops_sha256 - if parent_hash is None: - raise ValueError(f"parent {parent.candidate_id} has no exact artifact hash") - return { - "type": "prediction", - "iteration": iteration, - "niche": niche, - "action_kind": action_kind.value, - "candidate_id": candidate_id, - "parent_candidate_id": parent.candidate_id, - "parent_frontier_submission_id": parent.frontier_submission_id, - "parent_ops_sha256": parent_hash, - "parent_canonical_artifact_sha256": parent.canonical_artifact_sha256, - "parent_average_toffoli": parent.average_toffoli, - "parent_qubits": parent.qubits, - "mechanism": str(proposal["mechanism"]), - "delta_qubits": int(proposal["delta_qubits"]), - "delta_toffoli_mean": float(proposal["delta_toffoli_mean"]), - "delta_toffoli_standard_deviation": float( - proposal["delta_toffoli_standard_deviation"] - ), - "correctness_risk": str(proposal["correctness_risk"]), - "full_verification_budget": int(proposal["full_verification_budget"]), - "expected_invalidations": sorted( - dependency.value for dependency in action_impact(action_kind).invalidated - ), - "falsifier": str(proposal["falsifier"]), - } - - -def diagnosis_prompt( - *, - choice: ParentChoice, - records: Sequence[Mapping[str, Any]], - first_literature_transfer: bool, - emitter: str, -) -> str: - mode = ( - "This is the first DGM iteration after iteration 62. Start with a filtered " - "literature transfer from both briefs below." - if first_literature_transfer - else "Use literature only when it directly attacks the selected niche." - ) - emitter_job = { - "refiner": "Improve the selected parent locally.", - "recombiner": "Import a mechanism from a distant archive lineage into the selected parent.", - "literature": "Transfer one unused external technique through the verifier contract.", - "cold-start": "Reason independently from the verifier/ceiling contract, without prior attempt history.", - "abductor": "Explain the latest mismatch and propose its strongest discriminating successor.", - }[emitter] - context_instruction = ( - "Do not read measurements.jsonl or prior research memory; use only the " - "verifier contract and source code." - if emitter == "cold-start" - else ( - "Read the complete copied ledger at " - ".autoresearch/context/measurements.jsonl and grep raw local " - "memory/code as needed." - ) - ) - return f"""You are the read-only diagnosis phase of a verifier-first circuit search. - -Goal: minimize the exact ECDSA Fail score toward the proved floor 0. Reality and -the trusted verifier outrank every model. Propose exactly one falsifiable mutation; -do not edit files in this phase. - -Iteration: {choice.iteration} -Emitter: {emitter} -Emitter job: {emitter_job} -Selected niche: {choice.niche} — {NICHES[choice.niche]} -Parent: {json.dumps(choice.node.to_mapping(), sort_keys=True)} -Ledger tail: {choice.ledger_tail_sha256} -Best certified score: {_best_score(records)} -Selection seed: {choice.seed} - -{mode} -Literature briefs: -{json.dumps(LITERATURE_TRANSFERS, indent=2)} - -{context_instruction} -Do not use hidden tests, benchmark-private -answers, leaderboard guesses, or an LLM judge. Approximate arithmetic is not -evidence. Preserve the exact ABI, reversibility, phase, ancilla cleanup, and the -self-seeded Fiat-Shamir draw. - -Your JSON prediction must estimate delta executed Toffoli (mean and standard -deviation), delta qubits, name the dominant correctness risk, give a concrete -falsifier, and provide implementation instructions restricted to Rust files -under src/point_add (never memory/, verifier, simulator, benchmark, config, or -tests). A full-verification budget of 1 is allowed only when the conservative -prediction can strictly beat the certified frontier. -""" - - -def mutation_prompt( - prediction: Mapping[str, Any], - mutation_instructions: str, -) -> str: - return f"""Produce a patch for the preregistered ECDSA Fail candidate. - -Prediction (already committed to the external hash-chained ledger): -{json.dumps(dict(prediction), sort_keys=True, indent=2)} - -Mutation instructions: -{mutation_instructions} - -You are read-only. Return one Git unified diff; the controller validates and -applies it. The patch may touch only existing or new *.rs files under src/point_add, excluding -src/point_add/memory. Do not edit the verifier, simulator, Cargo files, -benchmark scripts, tests, memory, configuration, Git metadata, or .autoresearch. -Do not run benchmark.sh, eval_circuit, ecdsafail, or any full verifier. Do not -access the network or credentials. Do not emit binary patches, mode changes, -renames, symlinks, or submodules. Keep the diff minimal and describe it in the -summary field. The controller owns all mutation, build, and verification. -""" - - -def _prepare_context( - worktree: Path, - ledger: Path, - source_repo: Path, - *, - include_history: bool, -) -> None: - context = worktree / ".autoresearch/context" - context.mkdir(parents=True, exist_ok=True) - if include_history: - shutil.copy2(ledger, context / "measurements.jsonl") - memory = source_repo / "src/point_add/memory" - for name in ( - "CEILING.md", - "RIG.md", - "06-research-status.md", - "reframe_log.md", - "niche_portfolio.json", - ): - source = memory / name - if include_history and source.is_file(): - shutil.copy2(source, context / name) - - -def _run_with_timeout( - command: Sequence[str], - *, - cwd: Path, - environment: Mapping[str, str], - timeout: int, - stdin: str | None = None, -) -> subprocess.CompletedProcess[str]: - process = subprocess.Popen( - list(command), - cwd=cwd, - env=dict(environment), - stdin=subprocess.PIPE if stdin is not None else None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - start_new_session=True, - ) - try: - stdout, stderr = process.communicate(stdin, timeout=timeout) - except subprocess.TimeoutExpired: - os.killpg(process.pid, signal.SIGKILL) - stdout, stderr = process.communicate() - raise TimeoutError(f"command timed out after {timeout}s: {command[0]}") from None - return subprocess.CompletedProcess(command, process.returncode, stdout, stderr) - - -def _run_codex( - *, - worktree: Path, - attempt: Path, - phase: str, - prompt: str, - schema: Mapping[str, Any] | None, - sandbox: str, - timeout: int, -) -> Mapping[str, Any] | str: - trace = attempt / "trace" - trace.mkdir(parents=True, exist_ok=True) - schema_path = attempt / f"{phase}-schema.json" - final_path = attempt / f"{phase}-final.txt" - command = [ - "codex", - "exec", - "--ephemeral", - "--ignore-user-config", - "--sandbox", - sandbox, - "-c", - "sandbox_workspace_write.network_access=false", - "-c", - "sandbox_workspace_write.exclude_slash_tmp=true", - "-c", - "sandbox_workspace_write.exclude_tmpdir_env_var=true", - "-c", - "shell_environment_policy.inherit=none", - "-c", - "approval_policy=never", - "-C", - str(worktree), - "--json", - "--color", - "never", - "-o", - str(final_path), - ] - if schema is not None: - _atomic_json(schema_path, schema) - command.extend(["--output-schema", str(schema_path)]) - command.append("-") - completed = _run_with_timeout( - command, - cwd=worktree, - environment=sanitized_environment(), - timeout=timeout, - stdin=prompt, - ) - (trace / f"{phase}.jsonl").write_text(completed.stdout, encoding="utf-8") - (trace / f"{phase}.stderr.log").write_text(completed.stderr, encoding="utf-8") - if completed.returncode: - raise RuntimeError( - f"Codex {phase} failed ({completed.returncode}): {completed.stderr[-1000:]}" - ) - final = final_path.read_text(encoding="utf-8") - if schema is None: - return final - value = json.loads(final) - if not isinstance(value, Mapping): - raise ValueError(f"Codex {phase} output was not an object") - return value - - -def _add_worktree(repo: Path, root: Path, iteration: int, parent_ref: str) -> Path: - root.mkdir(parents=True, exist_ok=True) - path = Path(tempfile.mkdtemp(prefix=f"i{iteration:03d}-", dir=root)) - path.rmdir() - subprocess.run( - ["git", "-C", str(repo), "worktree", "add", "--detach", str(path), parent_ref], - check=True, - capture_output=True, - text=True, - ) - return path - - -def _remove_worktree(repo: Path, root: Path, worktree: Path) -> None: - resolved_root = root.resolve() - resolved = worktree.resolve() - if not resolved.is_relative_to(resolved_root): - raise ValueError(f"refusing to remove unmanaged worktree: {resolved}") - subprocess.run( - ["git", "-C", str(repo), "worktree", "remove", "--force", str(worktree)], - check=True, - capture_output=True, - text=True, - ) - - -def _changed_paths(worktree: Path) -> tuple[str, ...]: - completed = subprocess.run( - ["git", "-C", str(worktree), "status", "--porcelain", "-z"], - check=True, - capture_output=True, - text=True, - ) - output = completed.stdout - if not output: - return () - paths: list[str] = [] - fields = output.split("\0") - index = 0 - while index < len(fields): - field = fields[index] - if not field: - break - status = field[:2] - path = field[3:] - if status[0] in {"R", "C"} or status[1] in {"R", "C"}: - index += 1 - if index < len(fields): - path = fields[index] - paths.append(path) - index += 1 - return tuple(paths) - - -def _commit_candidate( - repo: Path, - worktree: Path, - prediction: Mapping[str, Any], - paths: Sequence[str], -) -> str: - message = f"feat(point-add): test {prediction['candidate_id']}" - subprocess.run( - ["committer", message, *paths], - cwd=worktree, - check=True, - capture_output=True, - text=True, - env=sanitized_environment(), - ) - commit = _git_output(worktree, "rev-parse", "HEAD") - reference = candidate_ref(str(prediction["candidate_id"])) - existing = _ref_commit(repo, reference) - if existing is not None and existing != commit: - raise RuntimeError(f"candidate ref already exists at a different commit: {reference}") - subprocess.run( - [ - "git", - "-C", - str(repo), - "update-ref", - reference, - commit, - existing or ("0" * 40), - ], - check=True, - capture_output=True, - text=True, - ) - return commit - - -def _sandbox_command( - command: Sequence[str], - *, - cwd: Path, - writable: Sequence[Path], - timeout: int, - environment: Mapping[str, str], -) -> subprocess.CompletedProcess[str]: - system = os.uname().sysname - if system == "Darwin" and shutil.which("sandbox-exec"): - grants = "".join( - f'(allow file-write* (subpath "{path.resolve()}"))' for path in writable - ) - profile = f"(version 1)(allow default)(deny network*)(deny file-write*){grants}" - wrapped = ["sandbox-exec", "-p", profile, *command] - elif shutil.which("bwrap"): - wrapped = [ - "bwrap", - "--ro-bind", - "/", - "/", - "--dev", - "/dev", - "--proc", - "/proc", - "--unshare-net", - "--die-with-parent", - ] - for path in writable: - wrapped.extend(["--bind", str(path.resolve()), str(path.resolve())]) - wrapped.extend(["--chdir", str(cwd.resolve()), "--", *command]) - else: - raise RuntimeError("no fail-closed sandbox (sandbox-exec or bwrap) is available") - return _run_with_timeout( - wrapped, - cwd=cwd, - environment=environment, - timeout=timeout, - ) - - -def _build_artifact( - worktree: Path, - attempt: Path, - *, - timeout: int, -) -> dict[str, Any]: - trace = attempt / "trace" - target = attempt / "target" - scratch = attempt / "build-scratch" - target.mkdir(parents=True, exist_ok=True) - scratch.mkdir(parents=True, exist_ok=True) - environment = sanitized_environment() - environment["CARGO_TARGET_DIR"] = str(target) - build = _run_with_timeout( - [ - "cargo", - "build", - "--release", - "--locked", - "--offline", - "--bin", - "build_circuit", - "--bin", - "eval_circuit", - ], - cwd=worktree, - environment=environment, - timeout=timeout, - ) - (trace / "build.log").write_text(build.stdout + build.stderr, encoding="utf-8") - if build.returncode: - raise RuntimeError(f"candidate build failed: {build.stderr[-1000:]}") - run = _sandbox_command( - [str(target / "release/build_circuit")], - cwd=scratch, - writable=(scratch,), - timeout=timeout, - environment={**environment, "TMPDIR": str(scratch)}, - ) - (trace / "build-circuit.log").write_text( - run.stdout + run.stderr, encoding="utf-8" - ) - if run.returncode: - raise RuntimeError(f"build_circuit failed: {run.stderr[-1000:]}") - generated = scratch / "ops.bin" - if not generated.is_file(): - raise RuntimeError("sandboxed build_circuit did not produce ops.bin") - shutil.copy2(generated, worktree / "ops.bin") - return fingerprint(worktree / "ops.bin") - - -def verify_instrument_pins( - worktree: Path, - controller_repo: Path, - frontier_record: Mapping[str, Any], -) -> dict[str, str]: - instruments = InstrumentSet.from_files( - worktree / "src/bin/eval_circuit.rs", - worktree / "src/sim.rs", - controller_repo / "src/point_add/memory/repro/exact_scorer.py", - ) - actual = { - "verifier_sha256": instruments.verifier_sha256, - "simulator_sha256": instruments.simulator_sha256, - "scorer_sha256": instruments.scorer_sha256, - "identity_sha256": instruments.identity_sha256, - } - expected = frontier_record.get("instruments") - if not isinstance(expected, Mapping): - raise ValueError("frontier record has no instrument pin set") - mismatches = { - key: {"expected": expected.get(key), "actual": value} - for key, value in actual.items() - if expected.get(key) != value - } - if mismatches: - raise RuntimeError(f"trusted instrument mismatch: {mismatches}") - return actual - - -def _build_eval_variant( - worktree: Path, - attempt: Path, - shots: int, - expected_verifier_sha256: str, - *, - timeout: int, -) -> Path: - source = worktree / "src/bin/eval_circuit.rs" - if hashlib.sha256(source.read_bytes()).hexdigest() != expected_verifier_sha256: - raise RuntimeError("trusted evaluator hash differs from ledger pin") - variant_name = f"autoresearch_eval_{shots}" - variant = worktree / f"src/bin/{variant_name}.rs" - original = source.read_text(encoding="utf-8") - needle = "const NUM_TESTS: usize = 9024;" - if original.count(needle) != 1: - raise RuntimeError("trusted evaluator shot constant changed unexpectedly") - variant.write_text( - original.replace(needle, f"const NUM_TESTS: usize = {shots};"), - encoding="utf-8", - ) - environment = sanitized_environment() - environment["CARGO_TARGET_DIR"] = str(attempt / "target") - try: - build = _run_with_timeout( - [ - "cargo", - "build", - "--release", - "--locked", - "--offline", - "--bin", - variant_name, - ], - cwd=worktree, - environment=environment, - timeout=timeout, - ) - finally: - variant.unlink(missing_ok=True) - (attempt / "trace" / f"eval-{shots}-build.log").write_text( - build.stdout + build.stderr, encoding="utf-8" - ) - if build.returncode: - raise RuntimeError(f"{shots}-shot evaluator build failed: {build.stderr[-1000:]}") - return attempt / "target/release" / variant_name - - -def _parse_evaluator_output(output: str) -> dict[str, Any]: - patterns = { - "shots": r"tested shots\s*:\s*([0-9]+)", - "classical_failures": r"classical mismatches\s*:\s*([0-9]+)", - "phase_garbage_batches": r"phase-garbage batches\s*:\s*([0-9]+)", - "ancilla_garbage_batches": r"ancilla-garbage batches\s*:\s*([0-9]+)", - "qubits": r"qubits\s*:\s*([0-9]+)", - "average_toffoli": r"avg executed Toffoli\s*:\s*([0-9.]+)", - "total_toffoli": r"total Toffoli \(sum\)\s*:\s*([0-9]+)", - } - values: dict[str, Any] = {} - for key, pattern in patterns.items(): - matches = re.findall(pattern, output) - if matches: - values[key] = float(matches[-1]) if key == "average_toffoli" else int(matches[-1]) - required = { - "shots", - "classical_failures", - "phase_garbage_batches", - "ancilla_garbage_batches", - "qubits", - "average_toffoli", - } - missing = sorted(required - values.keys()) - if missing: - raise ValueError(f"evaluator output missing fields: {missing}") - values["score"] = score(values["average_toffoli"], values["qubits"]) - return values - - -def _last_results_measurement( - worktree: Path, - *, - shots: int, - partial: Mapping[str, Any], -) -> dict[str, Any]: - with (worktree / "results.tsv").open( - newline="", encoding="utf-8" - ) as source: - rows = list(csv.DictReader(source, delimiter="\t")) - if not rows: - raise ValueError("evaluator produced no results.tsv row") - row = rows[-1] - average = float(row["toffoli"]) - qubits = int(row["qubits"]) - return { - "shots": shots, - "classical_failures": int(partial.get("classical_failures", shots)), - "phase_garbage_batches": int(partial.get("phase_garbage_batches", 0)), - "ancilla_garbage_batches": int( - partial.get("ancilla_garbage_batches", 0) - ), - "qubits": qubits, - "average_toffoli": average, - "score": score(average, qubits), - } - - -def _parse_evaluator_with_results( - output: str, - worktree: Path, - *, - shots: int, -) -> dict[str, Any]: - try: - return _parse_evaluator_output(output) - except ValueError: - partial: dict[str, Any] = {} - for key, pattern in { - "classical_failures": r"classical mismatches\s*:\s*([0-9]+)", - "phase_garbage_batches": r"phase-garbage batches\s*:\s*([0-9]+)", - "ancilla_garbage_batches": r"ancilla-garbage batches\s*:\s*([0-9]+)", - }.items(): - matches = re.findall(pattern, output) - if matches: - partial[key] = int(matches[-1]) - return _last_results_measurement(worktree, shots=shots, partial=partial) - - -def _run_eval_stage( - worktree: Path, - attempt: Path, - *, - shots: int, - expected_verifier_sha256: str, - timeout: int, -) -> StageResult: - if shots == FULL_SHOTS: - executable = attempt / "target/release/eval_circuit" - else: - executable = _build_eval_variant( - worktree, - attempt, - shots, - expected_verifier_sha256, - timeout=timeout, - ) - completed = _run_with_timeout( - [str(executable), "--note", f"dgm staged gate {shots}"], - cwd=worktree, - environment=sanitized_environment(), - timeout=timeout, - ) - output = completed.stdout + completed.stderr - (attempt / "trace" / f"eval-{shots}.log").write_text(output, encoding="utf-8") - measurement = _parse_evaluator_with_results(output, worktree, shots=shots) - passed = ( - completed.returncode == 0 - and measurement["shots"] == shots - and measurement["classical_failures"] == 0 - and measurement["phase_garbage_batches"] == 0 - and measurement["ancilla_garbage_batches"] == 0 - ) - artifact = fingerprint(worktree / "ops.bin") - return StageResult( - stage="full" if shots == FULL_SHOTS else "proxy", - passed=passed, - conclusion=( - f"exact {shots}-shot verifier stage passed" - if passed - else f"exact {shots}-shot verifier stage failed" - ), - evidence_kind=( - EvidenceKind.TRUSTED_FULL.value - if shots == FULL_SHOTS - else EvidenceKind.LOW_SHOT_SCREEN.value - ), - artifact_ops_sha256=artifact["compressed_ops_sha256"], - canonical_artifact_sha256=artifact["canonical_semantic_sha256"], - measurement=measurement, - ) - - -def _run_official_full( - worktree: Path, - attempt: Path, - *, - expected_artifact: Mapping[str, Any], - timeout: int, -) -> StageResult: - completed = _run_with_timeout( - ["ecdsafail", "run"], - cwd=worktree, - environment=sanitized_environment(), - timeout=timeout, - ) - output = completed.stdout + completed.stderr - (attempt / "trace" / "ecdsafail-run-9024.log").write_text( - output, encoding="utf-8" - ) - measurement = _parse_evaluator_with_results( - output, worktree, shots=FULL_SHOTS - ) - rebuilt = fingerprint(worktree / "ops.bin") - identity_match = ( - rebuilt["canonical_semantic_sha256"] - == expected_artifact["canonical_semantic_sha256"] - ) - passed = ( - completed.returncode == 0 - and identity_match - and measurement["shots"] == FULL_SHOTS - and measurement["classical_failures"] == 0 - and measurement["phase_garbage_batches"] == 0 - and measurement["ancilla_garbage_batches"] == 0 - ) - measurement["staged_artifact_identity_match"] = identity_match - return StageResult( - stage="full", - passed=passed, - conclusion=( - "ecdsafail run certified the exact staged artifact" - if passed - else "ecdsafail run failed or rebuilt a different semantic artifact" - ), - evidence_kind=EvidenceKind.TRUSTED_FULL.value, - artifact_ops_sha256=rebuilt["compressed_ops_sha256"], - canonical_artifact_sha256=rebuilt["canonical_semantic_sha256"], - measurement=measurement, - ) - - -def _conservative_prediction_score( - prediction: Mapping[str, Any], - parent: ArchiveNode, -) -> float: - if parent.average_toffoli is None or parent.qubits is None: - return WORST_SCORE - width = max(0, parent.qubits + int(prediction["delta_qubits"])) - upper_toffoli = max( - 0.0, - parent.average_toffoli - + float(prediction["delta_toffoli_mean"]) - + 2.0 * float(prediction["delta_toffoli_standard_deviation"]), - ) - return float(score(upper_toffoli, width)) - - -def full_gate_reasons( - prediction: Mapping[str, Any], - *, - artifact_ops_sha256: str, - supporting_evidence: Iterable[EvidenceKind], -) -> tuple[str, ...]: - model_prediction = Prediction( - prediction_id=str(prediction["candidate_id"]), - mechanism=str(prediction["mechanism"]), - delta_qubits=int(prediction["delta_qubits"]), - delta_toffoli_mean=float(prediction["delta_toffoli_mean"]), - delta_toffoli_standard_deviation=float( - prediction["delta_toffoli_standard_deviation"] - ), - correctness_risk=str(prediction["correctness_risk"]), - full_verification_budget=int(prediction["full_verification_budget"]), - expected_invalidations=frozenset( - Dependency(value) for value in prediction["expected_invalidations"] - ), - ) - action = Action( - kind=ActionKind(str(prediction["action_kind"])), - before_ops_sha256=str(prediction["parent_ops_sha256"]), - after_ops_sha256=artifact_ops_sha256, - prediction=model_prediction, - supporting_evidence=frozenset(supporting_evidence), - ) - return full_verification_gate(action).reasons - - -def frontier_from_archive( - public: PublicFrontier, - nodes: Sequence[ArchiveNode], -) -> Frontier: - matches = [ - node - for node in nodes - if node.frontier_submission_id == public.submission_id - and node.status == "promoted" - and node.reproducible - ] - if not matches: - raise ValueError("refreshed public frontier is not bootstrapped in the archive") - node = min(matches, key=lambda item: (item.actual_score or WORST_SCORE, item.candidate_id)) - if ( - node.actual_score != public.score - or node.qubits != public.qubits - or node.artifact_ops_sha256 is None - or node.canonical_artifact_sha256 is None - ): - raise ValueError("bootstrapped public frontier metadata is incomplete or stale") - return Frontier( - submission_id=public.submission_id, - source_ref=public.source_ref, - score=public.score, - qubits=public.qubits, - rounded_toffoli=public.rounded_toffoli, - ops_sha256=node.artifact_ops_sha256, - canonical_ops_sha256=node.canonical_artifact_sha256, - emitted_ops=node.emitted_ops or 0, - ) - - -def promotion_report( - prediction: Mapping[str, Any], - *, - candidate_source_ref: str, - artifact: Mapping[str, Any], - result: StageResult, - refreshed_frontier: Frontier, -) -> dict[str, Any]: - measurement = result.measurement or {} - verification = Verification( - evidence_kind=EvidenceKind(result.evidence_kind), - ops_sha256=result.artifact_ops_sha256, - shots=int(measurement.get("shots", 0)), - qubits=( - int(measurement["qubits"]) if measurement.get("qubits") is not None else None - ), - total_toffoli=( - int(measurement["total_toffoli"]) - if measurement.get("total_toffoli") is not None - else None - ), - average_toffoli=( - float(measurement["average_toffoli"]) - if measurement.get("average_toffoli") is not None - else None - ), - classical_failures=int(measurement.get("classical_failures", 0)), - phase_garbage_batches=int(measurement.get("phase_garbage_batches", 0)), - ancilla_garbage_batches=int( - measurement.get("ancilla_garbage_batches", 0) - ), - ) - candidate = Candidate( - candidate_id=str(prediction["candidate_id"]), - parent_submission_id=str(prediction["parent_frontier_submission_id"]), - source_ref=candidate_source_ref, - ops_sha256=result.artifact_ops_sha256, - canonical_ops_sha256=result.canonical_artifact_sha256, - qubits=int(artifact["qubits"]), - emitted_ops=int(artifact["emitted_ops"]), - ) - decision = promotion_gate(candidate, verification, refreshed_frontier) - return { - "allowed": decision.allowed, - "reasons": list(decision.reasons), - "candidate_score": decision.candidate_score, - "refreshed_frontier": { - "submission_id": refreshed_frontier.submission_id, - "source_ref": refreshed_frontier.source_ref, - "score": refreshed_frontier.score, - }, - } - - -def _submit_candidate( - *, - worktree: Path, - attempt: Path, - prediction: Mapping[str, Any], - result: StageResult, - candidate_ref_name: str, - model: str, - timeout: int, -) -> dict[str, Any]: - measurement = result.measurement or {} - claimed_score = int(measurement["score"]) - note_path = attempt / "submission-note.md" - note_path.write_text( - "\n".join( - ( - f"## {prediction['candidate_id']}", - "", - str(prediction["mechanism"]), - "", - f"Preregistered falsifier: {prediction.get('falsifier', 'n/a')}", - "", - ( - f"Exact `ecdsafail run`: {measurement['shots']} shots, " - f"score {claimed_score}, zero classical/phase/ancilla failures." - ), - "", - f"Candidate lineage: `{candidate_ref_name}`.", - ) - ) - + "\n", - encoding="utf-8", - ) - completed = _run_with_timeout( - [ - "ecdsafail", - "submit", - "--claimed-score", - str(claimed_score), - "--note-file", - str(note_path), - "--model", - model, - ], - cwd=worktree, - environment=sanitized_environment(), - timeout=timeout, - ) - output = completed.stdout + completed.stderr - (attempt / "trace" / "ecdsafail-submit.log").write_text( - output, encoding="utf-8" - ) - if completed.returncode: - raise RuntimeError(f"ecdsafail submit failed: {output[-1000:]}") - clean = _ANSI_ESCAPE.sub("", output) - submission = re.search( - r"submission\s+([0-9a-f]{8}-[0-9a-f-]{27,})", clean - ) - status = re.search(r"status\s+([A-Za-z_-]+)", clean) - if submission is None or status is None: - raise ValueError("could not parse ecdsafail submit receipt") - return { - "submission_id": submission.group(1), - "status": status.group(1).lower(), - "claimed_score": claimed_score, - "outcome": "submitted exact clean beat; official judge pending", - } - - -def _observation_payload( - prediction: Mapping[str, Any], - result: StageResult, - *, - prediction_match: bool, -) -> dict[str, Any]: - return { - "type": "observation", - "iteration": int(prediction["iteration"]), - "observation_id": f"{prediction['candidate_id']}-{result.stage}", - "stage": result.stage, - "evidence_kind": result.evidence_kind, - "verdict": "pass" if result.passed else "fail", - "artifact_ops_sha256": result.artifact_ops_sha256, - "prediction_match": prediction_match, - "measurement": result.measurement, - "conclusion": result.conclusion, - } - - -def _candidate_payload( - prediction: Mapping[str, Any], - *, - status: str, - artifact_hash: str | None, - canonical_artifact_hash: str | None, - emitted_ops: int | None, - source_ref: str | None, - emitter: str, - evidence: str, - archive_contribution: bool, -) -> dict[str, Any]: - payload = { - "type": "candidate", - "iteration": int(prediction["iteration"]), - "candidate_id": str(prediction["candidate_id"]), - "niche": str(prediction["niche"]), - "status": status, - "parent_candidate_id": str(prediction["parent_candidate_id"]), - "parent_frontier_submission_id": str( - prediction["parent_frontier_submission_id"] - ), - "evidence": evidence, - "artifact_ops_sha256": artifact_hash, - "canonical_artifact_sha256": canonical_artifact_hash, - "emitted_ops": emitted_ops, - "emitter": emitter, - "archive_contribution": archive_contribution, - } - if source_ref is not None: - payload["source_ref"] = source_ref - return payload - - -def _automatic_reframe( - *, - worktree: Path, - attempt: Path, - prediction: Mapping[str, Any], - observation: Mapping[str, Any], - timeout: int, -) -> Mapping[str, Any]: - prompt = f"""A preregistered ECDSA Fail prediction mismatched reality. -Deliberate from the raw trace files under {attempt / 'trace'} and return a -minimal evidence-bound reframe. Do not edit files and do not rescue the old -hypothesis with unobserved claims. - -Prediction: -{json.dumps(dict(prediction), indent=2, sort_keys=True)} - -Observation: -{json.dumps(dict(observation), indent=2, sort_keys=True)} - -State one falsified claim, the smallest compression supported by this result, -and one forward prediction that would discriminate the revised mechanism. -""" - try: - result = _run_codex( - worktree=worktree, - attempt=attempt, - phase="reframe", - prompt=prompt, - schema=_REFRAME_SCHEMA, - sandbox="read-only", - timeout=timeout, - ) - assert isinstance(result, Mapping) - return result - except (OSError, ValueError, RuntimeError, TimeoutError, json.JSONDecodeError): - return { - "claim": f"{prediction['mechanism']} did not survive {observation['stage']}", - "compression": str(observation["conclusion"]), - "forward_prediction": ( - "A revised candidate must change the named mechanism and pass " - "the same failed gate before receiving more verifier budget." - ), - } - - -def bootstrap_public_frontier( - *, - repo: Path, - ledger: Path, - attempts_root: Path, - worktrees_root: Path, - stage_timeout: int, -) -> dict[str, Any]: - """Import the exact current promoted source as a reproducible archive seed.""" - records = load_ledger(ledger) - ensure_ready(records) - public = refresh_public_frontier(repo) - candidate_id = f"public-{public.submission_id[:8]}" - ref = candidate_ref(candidate_id) - existing = next( - ( - record - for record in records - if record.get("type") == "candidate" - and record.get("official_submission_id") == public.submission_id - ), - None, - ) - if existing is not None and _ref_commit(repo, ref): - return { - "verdict": "green", - "status": "already_bootstrapped", - "candidate_id": candidate_id, - "candidate_ref": ref, - "public_score": public.score, - } - - subprocess.run( - ["git", "-C", str(repo), "fetch", "--no-tags", "origin", "main"], - check=True, - capture_output=True, - text=True, - ) - if _ref_commit(repo, public.source_ref) is None: - raise RuntimeError(f"fetched public source is unresolved: {public.source_ref}") - attempt = attempts_root / f"bootstrap-{candidate_id}-{public.source_ref[:12]}" - if attempt.exists(): - attempt = Path( - tempfile.mkdtemp(prefix=f"bootstrap-{candidate_id}-", dir=attempts_root) - ) - else: - attempt.mkdir(parents=True) - (attempt / "trace").mkdir(exist_ok=True) - worktree = _add_worktree(repo, worktrees_root, 0, public.source_ref) - try: - artifact = _build_artifact(worktree, attempt, timeout=stage_timeout) - finally: - if worktree.exists(): - _remove_worktree(repo, worktrees_root, worktree) - if int(artifact["qubits"]) != public.qubits: - raise RuntimeError( - "public source build width differs from its official frontier metrics" - ) - existing_ref_commit = _ref_commit(repo, ref) - if existing_ref_commit is not None and existing_ref_commit != public.source_ref: - raise RuntimeError(f"ref {ref} already points at a different commit") - subprocess.run( - [ - "git", - "-C", - str(repo), - "update-ref", - ref, - public.source_ref, - existing_ref_commit or ("0" * 40), - ], - check=True, - capture_output=True, - text=True, - ) - latest_records = load_ledger(ledger) - if latest_records[-1]["record_sha256"] != records[-1]["record_sha256"]: - raise RuntimeError("ledger advanced during public frontier bootstrap") - root_id = _frontier_id(records[0]) - appended = append_payload( - ledger, - { - "type": "candidate", - "iteration": 0, - "candidate_id": candidate_id, - "niche": "H4-postpasses", - "status": "promoted", - "parent_candidate_id": root_id, - "evidence": ( - "official public promotion refreshed from ecdsafail submissions " - "and rebuilt from origin/main" - ), - "artifact_ops_sha256": artifact["compressed_ops_sha256"], - "canonical_artifact_sha256": artifact[ - "canonical_semantic_sha256" - ], - "source_ref": ref, - "official_submission_id": public.submission_id, - "actual_score": public.score, - "actual_average_toffoli": float(public.rounded_toffoli), - "actual_qubits": public.qubits, - "emitted_ops": artifact["emitted_ops"], - "emitter": "external-frontier", - }, - ) - return { - "verdict": "green", - "status": "bootstrapped", - "candidate_id": candidate_id, - "candidate_ref": ref, - "public_score": public.score, - "source_ref": public.source_ref, - "artifact": artifact, - "record_sha256": appended["record_sha256"], - } - - -def _run_once_locked( - *, - repo: Path, - ledger: Path, - archive_path: Path, - attempts_root: Path, - worktrees_root: Path, - agent_timeout: int, - stage_timeout: int, - proposal_path: Path | None = None, - submit: bool = False, - model: str = "GPT-5.6 Codex", -) -> dict[str, Any]: - """Run one diagnose/predict/mutate/verify iteration.""" - verify_upstream_clone(repo) - records = load_ledger(ledger) - ensure_ready(records) - bootstrap_public_frontier( - repo=repo, - ledger=ledger, - attempts_root=attempts_root, - worktrees_root=worktrees_root, - stage_timeout=stage_timeout, - ) - records = load_ledger(ledger) - status = ensure_ready(records) - iteration = int(status["iterations_started"]) + 1 - niche = str(status["portfolio"]["selected_niche"]) - nodes = build_archive(records, repo=repo) - choice = choose_parent( - nodes, - niche=niche, - iteration=iteration, - ledger_tail_sha256=str(status["tail_sha256"]), - ) - emitter_plan = select_emitter( - records, - iteration=iteration, - ledger_tail_sha256=str(status["tail_sha256"]), - ) - emitter = str(emitter_plan["emitter"]) - parent_ref = resolve_parent_ref(repo, choice.node) - archive = archive_report(records, repo=repo) - _atomic_json(archive_path, archive) - - attempt = attempts_root / ( - f"i{iteration:03d}-{status['tail_sha256'][:12]}-{choice.node.candidate_id}" - ) - if attempt.exists(): - raise ValueError(f"attempt directory already exists: {attempt}") - attempt.mkdir(parents=True) - _atomic_json(attempt / "selection.json", choice.to_mapping()) - _atomic_json(attempt / "emitter.json", emitter_plan) - _atomic_json( - attempt / "meta.json", - { - "controller": "dgm_search.py", - "dgm_upstream_revision": DGM_UPSTREAM_REVISION, - "codex_version": subprocess.run( - ["codex", "--version"], - check=True, - capture_output=True, - text=True, - ).stdout.strip(), - "model": model, - "iteration": iteration, - "ledger_tail_sha256": status["tail_sha256"], - "selection_seed": choice.seed, - "agent_timeout_seconds": agent_timeout, - "stage_timeout_seconds": stage_timeout, - }, - ) - worktree = _add_worktree(repo, worktrees_root, iteration, parent_ref) - try: - _prepare_context( - worktree, - ledger, - repo, - include_history=emitter != "cold-start", - ) - if proposal_path is None: - proposal = _run_codex( - worktree=worktree, - attempt=attempt, - phase="diagnose", - prompt=diagnosis_prompt( - choice=choice, - records=records, - first_literature_transfer=iteration == 63, - emitter=emitter, - ), - schema=_PROPOSAL_SCHEMA, - sandbox="read-only", - timeout=agent_timeout, - ) - assert isinstance(proposal, Mapping) - else: - proposal_value = json.loads(proposal_path.read_text(encoding="utf-8")) - if not isinstance(proposal_value, Mapping): - raise ValueError("proposal file must contain an object") - proposal = proposal_value - - prediction = _proposal_to_prediction( - proposal, - iteration=iteration, - niche=niche, - parent=choice.node, - ) - current = load_ledger(ledger) - current_status = ensure_ready(current) - if current_status["tail_sha256"] != status["tail_sha256"]: - raise RuntimeError("ledger advanced during diagnosis; retry from the new tail") - append_payload(ledger, prediction) - _atomic_json(attempt / "prediction.json", prediction) - - patch_result = _run_codex( - worktree=worktree, - attempt=attempt, - phase="mutate", - prompt=mutation_prompt(prediction, str(proposal["mutation_instructions"])), - schema=_PATCH_SCHEMA, - sandbox="read-only", - timeout=agent_timeout, - ) - assert isinstance(patch_result, Mapping) - paths = validate_and_apply_patch(worktree, str(patch_result["patch"])) - ref: str | None = None - commit: str | None = None - - artifact: Mapping[str, Any] | None = None - try: - artifact = _build_artifact(worktree, attempt, timeout=stage_timeout) - except (OSError, RuntimeError, TimeoutError) as error: - result = StageResult( - stage="hash", - passed=False, - conclusion=str(error), - evidence_kind=EvidenceKind.NARRATIVE.value, - artifact_ops_sha256=None, - canonical_artifact_sha256=None, - measurement=None, - ) - else: - commit = _commit_candidate(repo, worktree, prediction, paths) - ref = candidate_ref(str(prediction["candidate_id"])) - artifact_hash = str(artifact["compressed_ops_sha256"]) - canonical_hash = str(artifact["canonical_semantic_sha256"]) - is_noop = semantic_noop( - artifact, - parent_compressed_sha256=str(prediction["parent_ops_sha256"]), - parent_canonical_sha256=( - str(prediction["parent_canonical_artifact_sha256"]) - if prediction.get("parent_canonical_artifact_sha256") - else None - ), - ) - if is_noop: - result = StageResult( - stage="hash", - passed=False, - conclusion="candidate is byte-identical to its parent artifact", - evidence_kind=EvidenceKind.BYTE_IDENTICAL.value, - artifact_ops_sha256=artifact_hash, - canonical_artifact_sha256=canonical_hash, - measurement={"fingerprint": artifact}, - ) - else: - result = StageResult( - stage="proxy", - passed=True, - conclusion="artifact hash changed; beginning fixed-draw screens", - evidence_kind=EvidenceKind.NARRATIVE.value, - artifact_ops_sha256=artifact_hash, - canonical_artifact_sha256=canonical_hash, - measurement={"fingerprint": artifact}, - ) - instrument_report = verify_instrument_pins( - worktree, repo, current[0] - ) - _atomic_json( - attempt / "instrument-pins.json", - {"verdict": "green", **instrument_report}, - ) - verifier_hash = str(current[0]["instruments"]["verifier_sha256"]) - for shots in SHOT_LADDER[:-1]: - result = _run_eval_stage( - worktree, - attempt, - shots=shots, - expected_verifier_sha256=verifier_hash, - timeout=stage_timeout, - ) - if not result.passed: - break - if result.passed: - public_before_full = refresh_public_frontier(repo) - best = public_before_full.score - conservative = _conservative_prediction_score( - prediction, choice.node - ) - evidence_reasons = full_gate_reasons( - prediction, - artifact_ops_sha256=artifact_hash, - supporting_evidence={EvidenceKind.LOW_SHOT_SCREEN}, - ) - if ( - int(prediction["full_verification_budget"]) == 0 - or conservative >= best - or evidence_reasons - ): - denial = [] - if int(prediction["full_verification_budget"]) == 0: - denial.append("prediction allocated no full-run budget") - if conservative >= best: - denial.append( - f"conservative predicted score {int(conservative)} " - f"does not beat {best}" - ) - denial.extend(evidence_reasons) - result = replace( - result, - conclusion=( - f"{SHOT_LADDER[-2]}-shot screen passed; full " - f"verifier denied: {', '.join(denial)}" - ), - measurement={ - **(result.measurement or {}), - "conservative_predicted_score": int(conservative), - "best_score": best, - "full_gate_reasons": list(evidence_reasons), - }, - ) - else: - result = _run_official_full( - worktree, - attempt, - expected_artifact=artifact, - timeout=stage_timeout, - ) - - measurement = result.measurement or {} - predicted_delta = float(prediction["delta_toffoli_mean"]) - predicted_sd = float(prediction["delta_toffoli_standard_deviation"]) - observed_delta: float | None = None - if "average_toffoli" in measurement: - parent_average = choice.node.average_toffoli - if parent_average is not None: - observed_delta = float(measurement["average_toffoli"]) - parent_average - prediction_match = bool( - result.passed - and ( - observed_delta is None - or abs(observed_delta - predicted_delta) <= 2.0 * predicted_sd - or predicted_sd == 0.0 - and observed_delta == predicted_delta - ) - ) - observation = _observation_payload( - prediction, result, prediction_match=prediction_match - ) - append_payload(ledger, observation) - clean_full = result.stage == "full" and result.passed - promotion: dict[str, Any] | None = None - submission_receipt: dict[str, Any] | None = None - if ( - clean_full - and ref is not None - and isinstance(artifact, Mapping) - ): - public_after_full = refresh_public_frontier(repo) - try: - refreshed_frontier = frontier_from_archive( - public_after_full, - build_archive(current, repo=repo), - ) - except ValueError as error: - promotion = { - "allowed": False, - "reasons": [str(error)], - "candidate_score": measurement.get("score"), - "refreshed_frontier": asdict(public_after_full), - } - else: - promotion = promotion_report( - prediction, - candidate_source_ref=ref, - artifact=artifact, - result=result, - refreshed_frontier=refreshed_frontier, - ) - if submit and promotion["allowed"]: - submission_receipt = _submit_candidate( - worktree=worktree, - attempt=attempt, - prediction=prediction, - result=result, - candidate_ref_name=ref, - model=model, - timeout=stage_timeout, - ) - _atomic_json(attempt / "promotion.json", promotion) - append_payload( - ledger, - _candidate_payload( - prediction, - status=( - "promoted" - if submission_receipt is not None - and submission_receipt["status"] == "promoted" - else ("live" if clean_full else "retired") - ), - artifact_hash=result.artifact_ops_sha256, - canonical_artifact_hash=result.canonical_artifact_sha256, - emitted_ops=( - int(artifact["emitted_ops"]) - if isinstance(artifact, Mapping) - else None - ), - source_ref=ref, - emitter=emitter, - evidence=result.conclusion, - archive_contribution=( - clean_full - and not any( - node.functioning and node.niche == niche - for node in build_archive(current, repo=repo) - ) - ), - ), - ) - if submission_receipt is not None: - append_payload( - ledger, - { - "type": "submission", - "iteration": iteration, - "submission_id": submission_receipt["submission_id"], - "source_ref": ref, - "artifact_ops_sha256": result.artifact_ops_sha256, - "status": submission_receipt["status"], - "official_score": submission_receipt["claimed_score"], - "outcome": submission_receipt["outcome"], - }, - ) - if not prediction_match: - reframe = _automatic_reframe( - worktree=worktree, - attempt=attempt, - prediction=prediction, - observation=observation, - timeout=agent_timeout, - ) - append_payload( - ledger, - { - "type": "reframe", - "iteration": iteration, - "claim": str(reframe["claim"]), - "compression": str(reframe["compression"]), - "forward_prediction": str(reframe["forward_prediction"]), - }, - ) - - refreshed = archive_report(load_ledger(ledger), repo=repo) - _atomic_json(archive_path, refreshed) - final_report = { - "verdict": "green" if clean_full else "retired", - "iteration": iteration, - "candidate_id": prediction["candidate_id"], - "candidate_ref": ref, - "commit": commit, - "stage": result.stage, - "passed": result.passed, - "prediction_match": prediction_match, - "conclusion": result.conclusion, - "attempt": str(attempt), - "promotion": promotion, - "submission": submission_receipt, - } - _atomic_json(attempt / "result.json", final_report) - return final_report - finally: - if worktree.exists(): - _remove_worktree(repo, worktrees_root, worktree) - - -def run_once( - *, - repo: Path, - ledger: Path, - archive_path: Path, - attempts_root: Path, - worktrees_root: Path, - agent_timeout: int, - stage_timeout: int, - proposal_path: Path | None = None, - submit: bool = False, - model: str = "GPT-5.6 Codex", -) -> dict[str, Any]: - """Hold the controller transaction lock for one complete iteration.""" - with controller_lock(repo / ".autoresearch/dgm.lock"): - try: - return _run_once_locked( - repo=repo, - ledger=ledger, - archive_path=archive_path, - attempts_root=attempts_root, - worktrees_root=worktrees_root, - agent_timeout=agent_timeout, - stage_timeout=stage_timeout, - proposal_path=proposal_path, - submit=submit, - model=model, - ) - except Exception as error: - # Once prediction is preregistered, never leave an ordinary Python, - # tool, or timeout failure masquerading as a scientific result. - # SIGKILL/power loss is handled by the explicit recover-pending CLI. - records = load_ledger(ledger) - if pending_dgm_prediction(records) is not None: - recover_pending_infrastructure_error( - ledger, - conclusion=f"controller infrastructure error: {type(error).__name__}: {error}", - ) - raise - - -def dry_run( - *, - repo: Path, - ledger: Path, - archive_path: Path, -) -> dict[str, Any]: - upstream = verify_upstream_clone(repo) - records = load_ledger(ledger) - status = backtest(records) - archive = archive_report(records, repo=repo) - _atomic_json(archive_path, archive) - ready = status["verdict"] == "green" and status["pending_iteration"] is None - return { - "verdict": "green" if ready else "waiting", - "upstream": upstream, - "harness": status, - "archive_path": str(archive_path), - "next_parent": archive["next_parent"], - "stop": { - "score_zero": _best_score(records) == 0, - "iteration_cap": status["iterations_started"] >= MAX_ITERATIONS, - }, - } - - -def _absolute(repo: Path, path: Path) -> Path: - return path if path.is_absolute() else repo / path - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--repo", type=Path, default=repo_root()) - parser.add_argument("--ledger", type=Path, default=DEFAULT_LEDGER) - parser.add_argument("--archive", type=Path, default=DEFAULT_ARCHIVE) - subparsers = parser.add_subparsers(dest="command", required=True) - subparsers.add_parser("upstream") - subparsers.add_parser("archive") - subparsers.add_parser("select") - subparsers.add_parser("dry-run") - bootstrap_parser = subparsers.add_parser("bootstrap-public") - bootstrap_parser.add_argument("--attempts", type=Path, default=DEFAULT_ATTEMPTS) - bootstrap_parser.add_argument("--worktrees", type=Path, default=DEFAULT_WORKTREES) - bootstrap_parser.add_argument("--stage-timeout", type=int, default=7_200) - recover_parser = subparsers.add_parser("recover-pending") - recover_parser.add_argument( - "--conclusion", - required=True, - help="evidence-bound infrastructure failure description", - ) - run_parser = subparsers.add_parser("run-once") - run_parser.add_argument("--attempts", type=Path, default=DEFAULT_ATTEMPTS) - run_parser.add_argument("--worktrees", type=Path, default=DEFAULT_WORKTREES) - run_parser.add_argument("--agent-timeout", type=int, default=1_800) - run_parser.add_argument("--stage-timeout", type=int, default=7_200) - run_parser.add_argument("--proposal", type=Path) - run_parser.add_argument( - "--submit", - action="store_true", - help="submit only when refreshed world-model promotion gates pass", - ) - run_parser.add_argument("--model", default="GPT-5.6 Codex") - args = parser.parse_args() - - repo = args.repo.resolve() - ledger = _absolute(repo, args.ledger) - archive_path = _absolute(repo, args.archive) - try: - if args.command == "upstream": - output = verify_upstream_clone(repo) - elif args.command == "archive": - output = archive_report(load_ledger(ledger), repo=repo) - _atomic_json(archive_path, output) - elif args.command == "select": - records = load_ledger(ledger) - status = ensure_ready(records) - nodes = build_archive(records, repo=repo) - output = choose_parent( - nodes, - niche=str(status["portfolio"]["selected_niche"]), - iteration=int(status["iterations_started"]) + 1, - ledger_tail_sha256=str(status["tail_sha256"]), - ).to_mapping() - elif args.command == "dry-run": - output = dry_run(repo=repo, ledger=ledger, archive_path=archive_path) - elif args.command == "recover-pending": - with controller_lock(repo / ".autoresearch/dgm.lock"): - output = recover_pending_infrastructure_error( - ledger, - conclusion=args.conclusion, - ) - elif args.command == "bootstrap-public": - with controller_lock(repo / ".autoresearch/dgm.lock"): - output = bootstrap_public_frontier( - repo=repo, - ledger=ledger, - attempts_root=_absolute(repo, args.attempts), - worktrees_root=_absolute(repo, args.worktrees), - stage_timeout=args.stage_timeout, - ) - else: - output = run_once( - repo=repo, - ledger=ledger, - archive_path=archive_path, - attempts_root=_absolute(repo, args.attempts), - worktrees_root=_absolute(repo, args.worktrees), - agent_timeout=args.agent_timeout, - stage_timeout=args.stage_timeout, - proposal_path=( - _absolute(repo, args.proposal) if args.proposal is not None else None - ), - submit=args.submit, - model=args.model, - ) - except ( - OSError, - ValueError, - RuntimeError, - TimeoutError, - subprocess.CalledProcessError, - json.JSONDecodeError, - ) as error: - print(json.dumps({"verdict": "red", "error": str(error)}, sort_keys=True)) - return 1 - print(json.dumps(output, sort_keys=True)) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/exact_scorer.py b/src/point_add/memory/repro/exact_scorer.py deleted file mode 100755 index 1321b9aa..00000000 --- a/src/point_add/memory/repro/exact_scorer.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python3 -"""Exact model of eval_circuit.rs::write_score; not a replacement verifier.""" - -from __future__ import annotations - -import argparse -import csv -import json -import math -from decimal import Decimal, ROUND_FLOOR -from pathlib import Path -from typing import Any - -U64_MAX = (1 << 64) - 1 -_U64_LIMIT_AS_FLOAT = float(1 << 64) -_LIVE_FRONTIER = { - "average_toffoli": 1_291_859.302, - "total_toffoli": 11_657_738_337, - "shots": 9_024, - "qubits": 1_154, - "score": 1_490_805_286, -} - - -def _require_u64(name: str, value: int) -> int: - if type(value) is not int: - raise TypeError(f"{name} must be an int") - if value < 0 or value > U64_MAX: - raise ValueError(f"{name} must be in [0, 2**64 - 1]") - return value - - -def _require_verifier_float(name: str, value: float) -> float: - if isinstance(value, bool) or not isinstance(value, (int, float)): - raise TypeError(f"{name} must be a real number") - result = float(value) - if not math.isfinite(result) or result < 0.0 or result >= _U64_LIMIT_AS_FLOAT: - raise ValueError(f"{name} must be finite and in [0, 2**64 - 1]") - return result - - -def score(avg_toffoli: float, qubits: int) -> int: - """Return Rust's rounded-Toffoli × qubits score with u64 saturation.""" - average = _require_verifier_float("avg_toffoli", avg_toffoli) - width = _require_u64("qubits", qubits) - rounded_toffoli = math.floor(average + 0.5) - return min(rounded_toffoli * width, U64_MAX) - - -def score_from_totals(total_toffoli: int, shots: int, qubits: int) -> int: - """Compute the score after the verifier's IEEE-754 totals/shots division.""" - total = _require_u64("total_toffoli", total_toffoli) - sample_count = _require_u64("shots", shots) - width = _require_u64("qubits", qubits) - if sample_count == 0: - raise ValueError("shots must be greater than zero") - average = float(total) / float(sample_count) - return score(average, width) - - -def backtest_results(path: Path) -> dict[str, Any]: - """Replay every accepted results.tsv row against a decimal-text oracle.""" - checked: list[dict[str, Any]] = [] - failures: list[dict[str, Any]] = [] - with path.open(newline="", encoding="utf-8") as source: - for line_number, row in enumerate(csv.DictReader(source, delimiter="\t"), start=2): - if row["correct"] != "OK": - continue - average_text = row["toffoli"] - qubits = int(row["qubits"]) - decimal_rounded = int( - (Decimal(average_text) + Decimal("0.5")).to_integral_value(rounding=ROUND_FLOOR) - ) - expected = min(decimal_rounded * qubits, U64_MAX) - actual = score(float(average_text), qubits) - result = { - "line": line_number, - "commit": row["commit"], - "average_toffoli": average_text, - "qubits": qubits, - "expected": expected, - "actual": actual, - } - checked.append(result) - if actual != expected: - failures.append(result) - - live_average_score = score( - _LIVE_FRONTIER["average_toffoli"], _LIVE_FRONTIER["qubits"] - ) - live_totals_score = score_from_totals( - _LIVE_FRONTIER["total_toffoli"], - _LIVE_FRONTIER["shots"], - _LIVE_FRONTIER["qubits"], - ) - if live_average_score != _LIVE_FRONTIER["score"] or live_totals_score != _LIVE_FRONTIER["score"]: - failures.append( - { - "case": "live-frontier", - "expected": _LIVE_FRONTIER["score"], - "from_average": live_average_score, - "from_totals": live_totals_score, - } - ) - - return { - "model": "eval_circuit.rs::write_score", - "results_path": str(path), - "ok_rows_checked": len(checked), - "live_frontier": { - **_LIVE_FRONTIER, - "score_from_average": live_average_score, - "score_from_totals": live_totals_score, - }, - "failures": failures, - "rows": checked, - "verdict": "green" if not failures else "red", - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--backtest", type=Path, required=True, metavar="RESULTS_TSV") - parser.add_argument("--json", action="store_true", help="emit compact JSON") - args = parser.parse_args() - report = backtest_results(args.backtest) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_classical_independence.py b/src/point_add/memory/repro/h0_classical_independence.py deleted file mode 100755 index 68f77175..00000000 --- a/src/point_add/memory/repro/h0_classical_independence.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -"""Prove that free classical controls cannot read initial quantum inputs. - -The proof is an induction over the pinned Simulator::apply_iter transition table. -Classical state starts from the two classical input registers. Every subsequent -classical writer depends only on prior classical state, condition bits, and XOF -randomness. HMR moves quantum dependence into phase, never into c_target. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -from enum import IntFlag -from pathlib import Path -from typing import Any - -try: - from verifier_ceiling import PINNED_TRUSTED_SHA256 -except ModuleNotFoundError: - from .verifier_ceiling import PINNED_TRUSTED_SHA256 - - -class Dependency(IntFlag): - NONE = 0 - INITIAL_QUANTUM = 1 - INITIAL_CLASSICAL = 2 - XOF_RANDOMNESS = 4 - - -CLASSICAL_WRITERS = ( - "Hmr", - "BitInvert", - "BitStore0", - "BitStore1", -) -NON_WRITERS = ( - "Neg", - "Register", - "AppendToRegister", - "X", - "Z", - "CX", - "CZ", - "Swap", - "R", - "CCX", - "CCZ", - "PushCondition", - "PopCondition", - "DebugPrint", -) -ALL_OPERATION_TYPES = CLASSICAL_WRITERS + NON_WRITERS - - -def _sha256(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - for chunk in iter(lambda: source.read(1024 * 1024), b""): - digest.update(chunk) - return digest.hexdigest() - - -def classical_write_dependency( - kind: str, - *, - old_target: Dependency, - condition: Dependency, - hmr_leaks_quantum: bool = False, -) -> Dependency | None: - """Return the dependencies of c_target after one abstract transition.""" - if kind == "Hmr": - result = old_target | condition | Dependency.XOF_RANDOMNESS - if hmr_leaks_quantum: - result |= Dependency.INITIAL_QUANTUM - return result - if kind == "BitInvert": - return old_target | condition - if kind in {"BitStore0", "BitStore1"}: - return old_target | condition - if kind in NON_WRITERS: - return None - raise ValueError(f"unknown operation type {kind}") - - -def verify_independence(*, hmr_leaks_quantum: bool = False) -> dict[str, Any]: - # Induction hypothesis: every existing bit and every condition expression is - # independent of the initial quantum registers. XOF randomness is also - # independent of those registers for a fixed semantic artifact. - prior = Dependency.INITIAL_CLASSICAL | Dependency.XOF_RANDOMNESS - condition = prior - failures: list[str] = [] - transitions: dict[str, list[str] | None] = {} - for kind in ALL_OPERATION_TYPES: - dependency = classical_write_dependency( - kind, - old_target=prior, - condition=condition, - hmr_leaks_quantum=hmr_leaks_quantum, - ) - if dependency is None: - transitions[kind] = None - continue - names = [member.name for member in Dependency if member and member & dependency] - transitions[kind] = names - if dependency & Dependency.INITIAL_QUANTUM: - failures.append(f"{kind}:classical_target_depends_on_initial_quantum") - return { - "verdict": "green" if not failures else "red", - "failures": failures, - "operation_types_checked": len(ALL_OPERATION_TYPES), - "classical_writers_checked": len(CLASSICAL_WRITERS), - "transitions": transitions, - "conclusion": ( - "classical condition stacks cannot distinguish initial quantum target values" - if not failures - else "classical independence is violated" - ), - } - - -def verify(repo: Path) -> dict[str, Any]: - simulator = repo / "src/sim.rs" - actual_hash = _sha256(simulator) - pinned_hash = PINNED_TRUSTED_SHA256["src/sim.rs"] - proof = verify_independence() - failures = list(proof["failures"]) - if actual_hash != pinned_hash: - failures.append("simulator_hash_mismatch") - countermodel = verify_independence(hmr_leaks_quantum=True) - if countermodel["verdict"] != "red": - failures.append("proof_does_not_reject_quantum_leaking_hmr") - return { - "model": "classical-state dependency induction over Simulator::apply_iter", - "scope": "pinned operation semantics; initial quantum-to-classical extraction only", - "simulator_sha256": actual_hash, - "pinned_simulator_sha256": pinned_hash, - "transition_proof": proof, - "negative_control": { - "mutation": "Hmr c_target also depends on q_target", - "verdict": countermodel["verdict"], - "failures": countermodel["failures"], - }, - "failures": failures, - "verdict": "green" if not failures else "red", - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--repo", type=Path, default=Path(__file__).resolve().parents[4]) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - report = verify(args.repo.resolve()) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_debug_payload_census.py b/src/point_add/memory/repro/h0_debug_payload_census.py deleted file mode 100755 index 659f9b7d..00000000 --- a/src/point_add/memory/repro/h0_debug_payload_census.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python3 -"""Exact reduced census of DebugPrint no-op payload freedom. - -The trusted parser accepts DebugPrint records without enforcing per-kind field -shape, while resource analysis still observes every field and the simulator does -nothing for the operation. This instrument enumerates only payload values that -stay inside already declared resource ranges (plus each sentinel), so each -record changes the Fiat-Shamir seed without changing the reduced lookup's -function or resource counts. -""" - -from __future__ import annotations - -import argparse -import itertools -import json -import math -import time -from typing import Any, Iterator - -try: - from h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _correction_encodings, - _decode_draw, - _row_encodings, - _semantic_reader, - ) - from zero_score_lookup import NO_FIELD, _record -except ModuleNotFoundError: - from .h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _correction_encodings, - _decode_draw, - _row_encodings, - _semantic_reader, - ) - from .zero_score_lookup import NO_FIELD, _record - -DEBUG_PRINT = 17 - - -def _payload_records(half_width: int) -> Iterator[bytes]: - resource_ids = (*range(2 * half_width), NO_FIELD) - register_ids = (0, 1, 2, 3, NO_FIELD) - for q2, q1, qt, ct, cc, rt in itertools.product( - resource_ids, - resource_ids, - resource_ids, - resource_ids, - resource_ids, - register_ids, - ): - yield _record(DEBUG_PRINT, q2=q2, q1=q1, qt=qt, ct=ct, cc=cc, rt=rt) - - -def payload_state_count(half_width: int) -> int: - if half_width <= 0: - raise ValueError("half_width must be positive") - return (2 * half_width + 1) ** 5 * 5 - - -def census(scope: Scope) -> dict[str, Any]: - if scope.rows != 1: - raise ValueError("DebugPrint payload census currently requires one row") - base = _base_records(scope.half_width) - row_encodings = _row_encodings(scope.key_bits) - correction_encodings = _correction_encodings(scope.key_bits) - payloads = tuple(_payload_records(scope.half_width)) - successful_pairs = 0 - successful_tables: set[tuple[tuple[int, int], ...]] = set() - checked = 0 - started = time.monotonic() - - for rows, payload in itertools.product(_candidate_rows(scope), payloads): - shake, _, _ = _semantic_reader( - scope, - rows, - base, - row_encodings, - correction_encodings, - payload, - ) - checked += 1 - state_bytes = (2 * scope.key_bits + 7) // 8 - if _decode_draw(shake.digest(state_bytes), scope) == rows: - successful_pairs += 1 - successful_tables.add(rows) - - payload_states = payload_state_count(scope.half_width) - expected = float(payload_states) - sigma = math.sqrt(expected * (1.0 - 1.0 / scope.candidate_count)) - return { - "half_width": scope.half_width, - "rows": scope.rows, - "table_states": scope.candidate_count, - "payload_states": payload_states, - "checked_pairs": checked, - "successful_pairs": successful_pairs, - "successful_tables": len(successful_tables), - "expected_successful_pairs": expected, - "success_sigma": sigma, - "z_score": (successful_pairs - expected) / sigma if sigma else 0.0, - "pair_success_density": successful_pairs / checked, - "expected_pair_success_density": 1.0 / scope.candidate_count, - "complete": checked == scope.candidate_count * payload_states, - "elapsed_seconds": time.monotonic() - started, - } - - -def run(max_width: int) -> dict[str, Any]: - if max_width <= 0: - raise ValueError("max_width must be positive") - scopes = [census(Scope(width, 1)) for width in range(1, max_width + 1)] - minimum_production_payload_states = 513**5 * 5 - return { - "experiment": "DebugPrint no-op payload fixed-point census", - "scopes": scopes, - "all_scopes_complete": all(scope["complete"] for scope in scopes), - "all_scopes_within_four_sigma": all( - abs(scope["z_score"]) <= 4.0 for scope in scopes - ), - "production_extrapolation": { - "minimum_qubit_field_states": 513, - "minimum_bit_field_states": 513, - "register_field_states": 5, - "payload_states_per_record": minimum_production_payload_states, - "payload_entropy_bits_per_record": math.log2( - minimum_production_payload_states - ), - "note": "Payload freedom multiplies independent seed trials but does not change fixed-point density per table/payload pair.", - }, - "verdict": "green", - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--max-width", type=int, default=2) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - report = run(args.max_width) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["all_scopes_complete"] else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_fixed_point_census.py b/src/point_add/memory/repro/h0_fixed_point_census.py deleted file mode 100755 index 73494134..00000000 --- a/src/point_add/memory/repro/h0_fixed_point_census.py +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/env python3 -"""Exact reduced-domain census for self-seeded zero-Toffoli lookup tables. - -The production lookup route is a fixed-point problem: the table determines the -semantic operation stream, the stream determines the verifier SHAKE256 draw, -and that draw must reproduce the same table. The production state is too large -to enumerate, so this program preserves the verifier's domain separator, field -serialization, condition-stack construction, and SHAKE256 coupling while -reducing register widths and table rows to finite exhaustive models. - -A green report means every declared reduced state was enumerated exactly. It is -mechanism evidence, not a production circuit certificate. -""" - -from __future__ import annotations - -import argparse -import hashlib -import itertools -import json -import math -import struct -import time -from dataclasses import dataclass -from typing import Any, Iterable, Iterator - -try: - from zero_score_lookup import ( - APPEND_TO_REGISTER, - BIT_INVERT, - CANONICAL_RECORD_BYTES, - DOMAIN, - NO_FIELD, - POP_CONDITION, - PUSH_CONDITION, - REGISTER, - X, - _record, - ) -except ModuleNotFoundError: - from .zero_score_lookup import ( - APPEND_TO_REGISTER, - BIT_INVERT, - CANONICAL_RECORD_BYTES, - DOMAIN, - NO_FIELD, - POP_CONDITION, - PUSH_CONDITION, - REGISTER, - X, - _record, - ) - - -@dataclass(frozen=True, slots=True) -class RowEncoding: - key: int - before: bytes - after: bytes - fixed_op_count: int - - -@dataclass(frozen=True, slots=True) -class Scope: - half_width: int - rows: int - - def __post_init__(self) -> None: - if self.half_width <= 0: - raise ValueError("half_width must be positive") - if self.rows not in (1, 2): - raise ValueError("only one-row and two-row exact scopes are supported") - - @property - def key_bits(self) -> int: - return 2 * self.half_width - - @property - def key_states(self) -> int: - return 1 << self.key_bits - - @property - def correction_states(self) -> int: - return 1 << self.key_bits - - @property - def candidate_count(self) -> int: - return ( - math.comb(self.key_states, self.rows) - * self.correction_states**self.rows - ) - - @property - def valid_draw_probability(self) -> float: - numerator = math.prod(self.key_states - index for index in range(self.rows)) - return numerator / self.key_states**self.rows - - -def _base_records(half_width: int) -> bytes: - records = bytearray() - for register in range(4): - records.extend(_record(REGISTER, rt=register)) - for qubit in range(half_width): - records.extend(_record(APPEND_TO_REGISTER, qt=qubit, rt=0)) - for qubit in range(half_width, 2 * half_width): - records.extend(_record(APPEND_TO_REGISTER, qt=qubit, rt=1)) - for bit in range(half_width): - records.extend(_record(APPEND_TO_REGISTER, ct=bit, rt=2)) - for bit in range(half_width, 2 * half_width): - records.extend(_record(APPEND_TO_REGISTER, ct=bit, rt=3)) - return bytes(records) - - -def _row_encodings(key_bits: int) -> tuple[RowEncoding, ...]: - encodings: list[RowEncoding] = [] - for key in range(1 << key_bits): - zero_positions = [bit for bit in range(key_bits) if not (key >> bit) & 1] - before = bytearray() - after = bytearray() - for bit in zero_positions: - before.extend(_record(BIT_INVERT, ct=bit)) - for bit in range(key_bits): - before.extend(_record(PUSH_CONDITION, cc=bit)) - for _ in range(key_bits): - after.extend(_record(POP_CONDITION)) - for bit in zero_positions: - after.extend(_record(BIT_INVERT, ct=bit)) - encodings.append( - RowEncoding( - key=key, - before=bytes(before), - after=bytes(after), - fixed_op_count=2 * len(zero_positions) + 2 * key_bits, - ) - ) - return tuple(encodings) - - -def _correction_encodings(key_bits: int) -> tuple[tuple[bytes, int], ...]: - encodings: list[tuple[bytes, int]] = [] - for correction in range(1 << key_bits): - records = bytearray() - for bit in range(key_bits): - if (correction >> bit) & 1: - records.extend(_record(X, qt=bit)) - encodings.append((bytes(records), correction.bit_count())) - return tuple(encodings) - - -def _decode_draw(payload: bytes, scope: Scope) -> tuple[tuple[int, int], ...] | None: - state_bits = 2 * scope.key_bits - state_bytes = (state_bits + 7) // 8 - expected_bytes = state_bytes * scope.rows - if len(payload) != expected_bytes: - raise ValueError(f"draw has {len(payload)} bytes, expected {expected_bytes}") - mask = (1 << scope.key_bits) - 1 - rows: list[tuple[int, int]] = [] - for index in range(scope.rows): - start = index * state_bytes - value = int.from_bytes(payload[start : start + state_bytes], "little") - value &= (1 << state_bits) - 1 - rows.append((value & mask, (value >> scope.key_bits) & mask)) - rows.sort() - if len({key for key, _ in rows}) != scope.rows: - return None - return tuple(rows) - - -def _candidate_rows(scope: Scope) -> Iterator[tuple[tuple[int, int], ...]]: - corrections = range(scope.correction_states) - for keys in itertools.combinations(range(scope.key_states), scope.rows): - for values in itertools.product(corrections, repeat=scope.rows): - yield tuple(zip(keys, values, strict=True)) - - -def _semantic_reader( - scope: Scope, - rows: tuple[tuple[int, int], ...], - base: bytes, - row_encodings: tuple[RowEncoding, ...], - correction_encodings: tuple[tuple[bytes, int], ...], - tail: bytes = b"", -) -> tuple[Any, int, str]: - base_count = 4 + 4 * scope.half_width - op_count = base_count - for key, correction in rows: - op_count += row_encodings[key].fixed_op_count - op_count += correction_encodings[correction][1] - if len(tail) % CANONICAL_RECORD_BYTES: - raise ValueError("tail must contain complete canonical operation records") - op_count += len(tail) // CANONICAL_RECORD_BYTES - - shake = hashlib.shake_256() - semantic = hashlib.sha256() - prefix = DOMAIN + struct.pack(" dict[str, Any]: - base = _base_records(scope.half_width) - row_encodings = _row_encodings(scope.key_bits) - correction_encodings = _correction_encodings(scope.key_bits) - fixed_points = 0 - fixed_samples: list[dict[str, Any]] = [] - minimum_ops: int | None = None - maximum_ops = 0 - checked = 0 - started = time.monotonic() - - for rows in _candidate_rows(scope): - shake, op_count, semantic_sha = _semantic_reader( - scope, - rows, - base, - row_encodings, - correction_encodings, - ) - checked += 1 - minimum_ops = op_count if minimum_ops is None else min(minimum_ops, op_count) - maximum_ops = max(maximum_ops, op_count) - state_bytes = (2 * scope.key_bits + 7) // 8 - draw = shake.digest(state_bytes * scope.rows) - if _decode_draw(draw, scope) == rows: - fixed_points += 1 - if len(fixed_samples) < keep_fixed: - fixed_samples.append( - { - "rows": [[key, correction] for key, correction in rows], - "emitted_ops": op_count, - "semantic_sha256": semantic_sha, - } - ) - - elapsed = time.monotonic() - started - expected = scope.valid_draw_probability - return { - "half_width": scope.half_width, - "rows": scope.rows, - "key_bits": scope.key_bits, - "candidate_count": scope.candidate_count, - "checked": checked, - "fixed_points": fixed_points, - "fixed_point_density": fixed_points / checked, - "random_map_expected_fixed_points": expected, - "expected_density": expected / checked, - "minimum_emitted_ops": minimum_ops, - "maximum_emitted_ops": maximum_ops, - "fixed_samples": fixed_samples, - "elapsed_seconds": elapsed, - "complete": checked == scope.candidate_count, - } - - -def default_scopes(max_one_row_width: int, max_two_row_width: int) -> tuple[Scope, ...]: - if max_one_row_width <= 0 or max_two_row_width <= 0: - raise ValueError("maximum widths must be positive") - return tuple( - [Scope(width, 1) for width in range(1, max_one_row_width + 1)] - + [Scope(width, 2) for width in range(1, max_two_row_width + 1)] - ) - - -def _log2_candidate_states(key_bits: int, correction_bits: int, rows: int) -> float: - key_states = 1 << key_bits - key_term = sum( - math.log2(key_states - index) - math.log2(index + 1) - for index in range(rows) - ) - return key_term + correction_bits * rows - - -def run(max_one_row_width: int = 5, max_two_row_width: int = 2) -> dict[str, Any]: - reports = [ - census(scope) - for scope in default_scopes(max_one_row_width, max_two_row_width) - ] - complete = all(report["complete"] for report in reports) - total_candidates = sum(report["candidate_count"] for report in reports) - total_fixed_points = sum(report["fixed_points"] for report in reports) - production_rows = 9_024 - production_key_bits = 27 - production_correction_bits = 512 - production_log2_states = _log2_candidate_states( - production_key_bits, - production_correction_bits, - production_rows, - ) - return { - "experiment": "reduced self-seeded lookup fixed-point census", - "verdict": "green" if complete else "red", - "scopes": reports, - "total_candidates": total_candidates, - "total_fixed_points": total_fixed_points, - "all_scopes_complete": complete, - "production_extrapolation": { - "rows": production_rows, - "key_bits": production_key_bits, - "correction_bits_per_row": production_correction_bits, - "state_bits_before_key_order_quotient": ( - production_rows - * (production_key_bits + production_correction_bits) - ), - "log2_candidate_states": production_log2_states, - "random_map_expected_fixed_points": 1.0, - "random_map_fixed_point_density_log2": -production_log2_states, - "note": ( - "The production family has one random-map fixed point in expectation, " - "but an inverse-density search scale. Toy fixed points do not provide " - "a scalable preimage method." - ), - }, - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--max-one-row-width", type=int, default=5) - parser.add_argument("--max-two-row-width", type=int, default=2) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - report = run(args.max_one_row_width, args.max_two_row_width) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_fixed_point_dynamics.py b/src/point_add/memory/repro/h0_fixed_point_dynamics.py deleted file mode 100755 index 05b3351e..00000000 --- a/src/point_add/memory/repro/h0_fixed_point_dynamics.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python3 -"""Exact functional-graph census for canonical self-seeded lookup tables.""" - -from __future__ import annotations - -import hashlib -import json -import math -import struct -import time -from array import array - -try: - from h0_fixed_point_census import ( - DOMAIN, - Scope, - _base_records, - _correction_encodings, - _decode_draw, - _row_encodings, - ) -except ModuleNotFoundError: - from .h0_fixed_point_census import ( - DOMAIN, - Scope, - _base_records, - _correction_encodings, - _decode_draw, - _row_encodings, - ) - - -def successor_map(half_width: int) -> array: - scope = Scope(half_width=half_width, rows=1) - states = scope.key_states * scope.correction_states - base = _base_records(half_width) - rows = _row_encodings(scope.key_bits) - corrections = _correction_encodings(scope.key_bits) - base_count = 4 + 4 * half_width - state_bytes = (2 * scope.key_bits + 7) // 8 - successors = array("I") - for key in range(scope.key_states): - row = rows[key] - for correction in range(scope.correction_states): - correction_bytes, correction_ops = corrections[correction] - op_count = base_count + row.fixed_op_count + correction_ops - shake = hashlib.shake_256() - shake.update(DOMAIN) - shake.update(struct.pack(" dict[str, object]: - started = time.monotonic() - successors = successor_map(half_width) - states = len(successors) - unresolved = -2 - nonfixed_cycle = -1 - attractor = array("i", [unresolved]) * states - fixed = [index for index, target in enumerate(successors) if index == target] - basin_sizes = {index: 1 for index in fixed} - for index in fixed: - attractor[index] = index - - cycle_lengths: list[int] = [] - max_tail = 0 - for start in range(states): - if attractor[start] != unresolved: - continue - path: list[int] = [] - positions: dict[int, int] = {} - node = start - while attractor[node] == unresolved and node not in positions: - positions[node] = len(path) - path.append(node) - node = successors[node] - if attractor[node] != unresolved: - destination = attractor[node] - prefix = path - else: - cycle_start = positions[node] - cycle = path[cycle_start:] - cycle_lengths.append(len(cycle)) - for member in cycle: - attractor[member] = nonfixed_cycle - destination = nonfixed_cycle - prefix = path[:cycle_start] - max_tail = max(max_tail, len(prefix)) - for member in reversed(prefix): - attractor[member] = destination - if destination >= 0: - basin_sizes[destination] += len(prefix) - - fixed_basin_sizes = sorted(basin_sizes.values(), reverse=True) - fixed_basin_total = sum(fixed_basin_sizes) - basin_bound = math.ceil(8.0 * math.sqrt(states)) - return { - "half_width": half_width, - "states": states, - "fixed_points": len(fixed), - "fixed_point_basin_sizes": fixed_basin_sizes, - "fixed_point_basin_total": fixed_basin_total, - "fixed_point_basin_fraction": fixed_basin_total / states, - "predicted_basin_bound": basin_bound, - "basin_bound_pass": not fixed_basin_sizes - or max(fixed_basin_sizes) <= basin_bound, - "nonfixed_cycles": len(cycle_lengths), - "maximum_nonfixed_cycle_length": max(cycle_lengths, default=0), - "maximum_tail_length": max_tail, - "elapsed_seconds": time.monotonic() - started, - "complete": all(value != unresolved for value in attractor), - } - - -def run(max_half_width: int = 5) -> dict[str, object]: - if max_half_width < 1: - raise ValueError("max_half_width must be positive") - scopes = [graph_report(width) for width in range(1, max_half_width + 1)] - return { - "experiment": "one-row self-seeded lookup functional graph", - "scopes": scopes, - "all_complete": all(scope["complete"] for scope in scopes), - "all_basin_bounds_pass": all( - scope["basin_bound_pass"] for scope in scopes - ), - } - - -def main() -> int: - report = run() - print(json.dumps(report, sort_keys=True)) - return 0 if report["all_complete"] and report["all_basin_bounds_pass"] else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_nonce_fixed_point_census.py b/src/point_add/memory/repro/h0_nonce_fixed_point_census.py deleted file mode 100755 index 9479d5c1..00000000 --- a/src/point_add/memory/repro/h0_nonce_fixed_point_census.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python3 -"""Exact reduced census of no-op nonce freedom in lookup fixed points. - -A semantic nonce can sample many verifier seeds without changing the lookup -function. This instrument enumerates every table and every nonce in reduced -one-row domains, showing whether nonce bits change fixed-point density or only -multiply the number of independent trials. -""" - -from __future__ import annotations - -import argparse -import itertools -import json -import math -import time -from typing import Any - -try: - from h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _correction_encodings, - _decode_draw, - _record, - _row_encodings, - _semantic_reader, - ) - from zero_score_lookup import X -except ModuleNotFoundError: - from .h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _correction_encodings, - _decode_draw, - _record, - _row_encodings, - _semantic_reader, - ) - from .zero_score_lookup import X - - -def _nonce_tail(nonce: int, bits: int) -> bytes: - if bits < 0: - raise ValueError("nonce bits must be nonnegative") - if nonce < 0 or nonce >= 1 << bits: - raise ValueError("nonce is outside the declared bit width") - records = bytearray() - for bit in range(bits): - target = 1 if (nonce >> bit) & 1 else 0 - record = _record(X, qt=target) - records.extend(record) - records.extend(record) - return bytes(records) - - -def census(scope: Scope, nonce_bits: int) -> dict[str, Any]: - if scope.rows != 1: - raise ValueError("nonce census currently requires a one-row scope") - base = _base_records(scope.half_width) - row_encodings = _row_encodings(scope.key_bits) - correction_encodings = _correction_encodings(scope.key_bits) - tails = tuple(_nonce_tail(nonce, nonce_bits) for nonce in range(1 << nonce_bits)) - successes = 0 - checked = 0 - successful_tables: set[tuple[tuple[int, int], ...]] = set() - started = time.monotonic() - - for rows, tail in itertools.product(_candidate_rows(scope), tails): - shake, _, _ = _semantic_reader( - scope, - rows, - base, - row_encodings, - correction_encodings, - tail, - ) - checked += 1 - state_bytes = (2 * scope.key_bits + 7) // 8 - if _decode_draw(shake.digest(state_bytes), scope) == rows: - successes += 1 - successful_tables.add(rows) - - expected = float(1 << nonce_bits) - sigma = math.sqrt(expected * (1.0 - 1.0 / scope.candidate_count)) - return { - "half_width": scope.half_width, - "rows": scope.rows, - "nonce_bits": nonce_bits, - "table_states": scope.candidate_count, - "nonce_states": 1 << nonce_bits, - "checked_pairs": checked, - "successful_pairs": successes, - "successful_tables": len(successful_tables), - "expected_successful_pairs": expected, - "success_sigma": sigma, - "z_score": (successes - expected) / sigma if sigma else 0.0, - "pair_success_density": successes / checked, - "expected_pair_success_density": 1.0 / scope.candidate_count, - "complete": checked == scope.candidate_count * (1 << nonce_bits), - "elapsed_seconds": time.monotonic() - started, - } - - -def run(max_width: int, max_nonce_bits: int) -> dict[str, Any]: - if max_width <= 0: - raise ValueError("max width must be positive") - if max_nonce_bits < 0: - raise ValueError("max nonce bits must be nonnegative") - scopes = [ - census(Scope(width, 1), nonce_bits) - for width in range(1, max_width + 1) - for nonce_bits in range(max_nonce_bits + 1) - ] - production_table_log2 = 4_758_375.235490617 - production_nonce_bits = 48 - return { - "experiment": "no-op nonce lookup fixed-point census", - "scopes": scopes, - "all_scopes_complete": all(scope["complete"] for scope in scopes), - "all_scopes_within_four_sigma": all(abs(scope["z_score"]) <= 4.0 for scope in scopes), - "production_extrapolation": { - "table_log2_states": production_table_log2, - "nonce_bits": production_nonce_bits, - "fixed_table_exhaustive_success_log2": production_nonce_bits - production_table_log2, - "global_pair_success_density_log2": -production_table_log2, - "note": "Nonce bits multiply independent trials but do not change success density per table/nonce pair.", - }, - "verdict": "green", - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--max-width", type=int, default=2) - parser.add_argument("--max-nonce-bits", type=int, default=8) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - report = run(args.max_width, args.max_nonce_bits) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["all_scopes_complete"] else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h0_permutation_fixed_point_census.py b/src/point_add/memory/repro/h0_permutation_fixed_point_census.py deleted file mode 100755 index 0b224daa..00000000 --- a/src/point_add/memory/repro/h0_permutation_fixed_point_census.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/env python3 -"""Census semantic-order freedom in reduced zero-Toffoli lookup fixed points. - -The zero-score lookup has far more seed freedom than an appended nonce: condition -pushes, classical inversions, correction X gates, and complete lookup rows can be -reordered without changing the circuit function. This program enumerates every -such stream in finite reduced scopes and measures whether the extra streams -change fixed-point density or merely multiply random-map trials. - -A green report certifies only the declared reduced censuses and the ordering -entropy of the supplied frozen dataset. It is not a production fixed point. -""" - -from __future__ import annotations - -import argparse -import hashlib -import itertools -import json -import math -import struct -import time -from collections.abc import Iterator -from pathlib import Path -from typing import Any - -try: - from h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _decode_draw, - ) - from zero_score_lookup import ( - BIT_INVERT, - DOMAIN, - POP_CONDITION, - PUSH_CONDITION, - X, - _artifact_seed, - _draw_dataset, - _fixed_base_table, - _lookup_rows, - _minimum_unique_prefix, - _record, - ) -except ModuleNotFoundError: - from .h0_fixed_point_census import ( - Scope, - _base_records, - _candidate_rows, - _decode_draw, - ) - from .zero_score_lookup import ( - BIT_INVERT, - DOMAIN, - POP_CONDITION, - PUSH_CONDITION, - X, - _artifact_seed, - _draw_dataset, - _fixed_base_table, - _lookup_rows, - _minimum_unique_prefix, - _record, - ) - - -def _records(kind: int, values: tuple[int, ...], field: str) -> bytes: - output = bytearray() - for value in values: - if field == "ct": - output.extend(_record(kind, ct=value)) - elif field == "cc": - output.extend(_record(kind, cc=value)) - elif field == "qt": - output.extend(_record(kind, qt=value)) - else: - raise ValueError(f"unknown operation field {field}") - return bytes(output) - - -def _row_variants(key: int, correction: int, key_bits: int) -> Iterator[bytes]: - zeros = tuple(bit for bit in range(key_bits) if not (key >> bit) & 1) - ones = tuple(bit for bit in range(key_bits) if (correction >> bit) & 1) - pops = b"".join(_record(POP_CONDITION) for _ in range(key_bits)) - for before_order in itertools.permutations(zeros): - before = _records(BIT_INVERT, before_order, "ct") - for push_order in itertools.permutations(range(key_bits)): - pushes = _records(PUSH_CONDITION, push_order, "cc") - for correction_order in itertools.permutations(ones): - corrections = _records(X, correction_order, "qt") - for after_order in itertools.permutations(zeros): - after = _records(BIT_INVERT, after_order, "ct") - yield before + pushes + corrections + pops + after - - -def _row_variant_count(key: int, correction: int, key_bits: int) -> int: - zeros = key_bits - key.bit_count() - ones = correction.bit_count() - return ( - math.factorial(zeros) - * math.factorial(key_bits) - * math.factorial(ones) - * math.factorial(zeros) - ) - - -def _table_body_variants( - rows: tuple[tuple[int, int], ...], key_bits: int -) -> Iterator[bytes]: - if not rows: - yield b"" - return - key, correction = rows[0] - for first in _row_variants(key, correction, key_bits): - for remainder in _table_body_variants(rows[1:], key_bits): - yield first + remainder - - -def _operation_count(scope: Scope, rows: tuple[tuple[int, int], ...]) -> int: - count = 4 + 4 * scope.half_width - for key, correction in rows: - zeros = scope.key_bits - key.bit_count() - count += 2 * zeros + 2 * scope.key_bits + correction.bit_count() - return count - - -def census(scope: Scope) -> dict[str, Any]: - """Enumerate all declared semantic orderings for one reduced scope.""" - base = _base_records(scope.half_width) - state_bytes = (2 * scope.key_bits + 7) // 8 - total = 0 - successes = 0 - successful_tables: set[tuple[tuple[int, int], ...]] = set() - semantic_hashes: set[bytes] = set() - semantic_collisions = 0 - declared = 0 - started = time.monotonic() - - for table in _candidate_rows(scope): - row_orders = (table,) if scope.rows == 1 else (table, tuple(reversed(table))) - table_declared = math.factorial(scope.rows) - for key, correction in table: - table_declared *= _row_variant_count(key, correction, scope.key_bits) - declared += table_declared - count = _operation_count(scope, table) - shake_prefix = DOMAIN + struct.pack(" dict[str, Any]: - """Count a conservative subset of distinct streams for one frozen draw.""" - shake, semantic_sha, emitted_ops = _artifact_seed(ops_path) - dataset = _draw_dataset(shake, shots, _fixed_base_table()) - prefix_width = _minimum_unique_prefix(dataset) - table = _lookup_rows(dataset, prefix_width) - - # Complete rows commute. Within each row, condition pushes, pre/post - # inversions, and correction X gates independently commute. - log2_variants = math.lgamma(shots + 1) / math.log(2) - correction_weights: list[int] = [] - for key, (mask_x, mask_y) in table.items(): - zeros = prefix_width - key.bit_count() - weight = mask_x.bit_count() + mask_y.bit_count() - correction_weights.append(weight) - log2_variants += ( - math.lgamma(prefix_width + 1) - + 2 * math.lgamma(zeros + 1) - + math.lgamma(weight + 1) - ) / math.log(2) - - return { - "source_ops_semantic_sha256": semantic_sha, - "source_emitted_ops": emitted_ops, - "shots": shots, - "prefix_width": prefix_width, - "table_entries": len(table), - "minimum_correction_weight": min(correction_weights), - "maximum_correction_weight": max(correction_weights), - "mean_correction_weight": sum(correction_weights) / len(correction_weights), - "log2_distinct_semantics_preserving_streams_lower_bound": log2_variants, - } - - -def run(ops_path: Path, shots: int) -> dict[str, Any]: - scopes = (Scope(1, 1), Scope(1, 2), Scope(2, 1)) - reports = [census(scope) for scope in scopes] - production = production_order_entropy(ops_path, shots) - green = all( - report["declared_semantic_variants"] - == report["checked_semantic_variants"] - and report["semantic_sha256_collisions"] == 0 - and abs(report["z_score"]) <= 4.0 - for report in reports - ) - return { - "experiment": "semantics-preserving zero-score lookup permutation census", - "verdict": "green" if green else "red", - "scopes": reports, - "production_entropy": production, - "conclusion": ( - "Permutation freedom creates many distinct streams and fixed variants in reduced " - "models, but per-stream fixed-point density remains random-map scale. Entropy is " - "abundant; no efficient production search follows." - ), - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--ops", type=Path, default=Path("ops.bin")) - parser.add_argument("--shots", type=int, default=9_024) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - if args.shots <= 0: - parser.error("--shots must be positive") - report = run(args.ops, args.shots) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/h3_affine_shell_rank.py b/src/point_add/memory/repro/h3_affine_shell_rank.py deleted file mode 100755 index 940ed9a1..00000000 --- a/src/point_add/memory/repro/h3_affine_shell_rank.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python3 -"""Exact GF(2) rank test for zero-Toffoli affine point-add output bits. - -For a pinned verifier operation stream, the first 9,024 SHAKE256-derived point -pairs are the complete correctness domain. This instrument asks whether each -of the 512 required output-correction bits lies in the affine span of the 1,024 -input bits. A positive result is only finite-seed evidence because changing -the circuit changes the verifier seed; a negative result closes the direct -Clifford/affine shell on that pinned draw. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -from pathlib import Path -from typing import Any - -try: - from world_model import FULL_VERIFICATION_SHOTS - from zero_score_lookup import _artifact_seed, _draw_dataset, _fixed_base_table -except ModuleNotFoundError: - from .world_model import FULL_VERIFICATION_SHOTS - from .zero_score_lookup import _artifact_seed, _draw_dataset, _fixed_base_table - -COORDINATE_BITS = 256 -FEATURE_BITS = 1 + 4 * COORDINATE_BITS -OUTPUT_BITS = 2 * COORDINATE_BITS -FEATURE_MASK = (1 << FEATURE_BITS) - 1 - - -def _sha256(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb", buffering=0) as stream: - while chunk := stream.read(8 * 1024 * 1024): - digest.update(chunk) - return digest.hexdigest() - - -def _packed_row(row: tuple[int, int, int, int, int, int]) -> int: - target_x, target_y, offset_x, offset_y, result_x, result_y = row - features = 1 - features |= target_x << 1 - features |= target_y << (1 + COORDINATE_BITS) - features |= offset_x << (1 + 2 * COORDINATE_BITS) - features |= offset_y << (1 + 3 * COORDINATE_BITS) - correction = (result_x ^ target_x) | ((result_y ^ target_y) << COORDINATE_BITS) - return features | (correction << FEATURE_BITS) - - -def reduce_dataset( - dataset: list[tuple[int, int, int, int, int, int]], -) -> dict[str, Any]: - basis: list[int | None] = [None] * FEATURE_BITS - feature_rank = 0 - inconsistent_outputs = 0 - dependency_rows = 0 - - for dataset_row in dataset: - packed = _packed_row(dataset_row) - while True: - features = packed & FEATURE_MASK - if features == 0: - dependency_rows += 1 - inconsistent_outputs |= packed >> FEATURE_BITS - break - pivot = features.bit_length() - 1 - basis_row = basis[pivot] - if basis_row is None: - basis[pivot] = packed - feature_rank += 1 - break - packed ^= basis_row - - inconsistent_indices = [ - index for index in range(OUTPUT_BITS) if (inconsistent_outputs >> index) & 1 - ] - exact_indices = [ - index for index in range(OUTPUT_BITS) if not (inconsistent_outputs >> index) & 1 - ] - return { - "rows": len(dataset), - "feature_columns": FEATURE_BITS, - "feature_rank": feature_rank, - "dependency_rows": dependency_rows, - "inconsistent_output_bits": len(inconsistent_indices), - "exact_affine_output_bits": len(exact_indices), - "exact_affine_output_indices": exact_indices, - } - - -def inspect_artifact(path: Path, shots: int, powers: tuple[tuple[int, int], ...]) -> dict[str, Any]: - shake, semantic_sha256, emitted_ops = _artifact_seed(path) - dataset = _draw_dataset(shake, shots, powers) - report = reduce_dataset(dataset) - report.update( - { - "path": str(path), - "artifact_sha256": _sha256(path), - "canonical_semantic_sha256": semantic_sha256, - "emitted_ops": emitted_ops, - } - ) - return report - - -def run(paths: list[Path], shots: int) -> dict[str, Any]: - if shots <= 0: - raise ValueError("shots must be positive") - if not paths: - raise ValueError("at least one ops artifact is required") - powers = _fixed_base_table() - artifacts = [inspect_artifact(path, shots, powers) for path in paths] - return { - "experiment": "affine output-correction rank", - "shots_per_artifact": shots, - "artifacts": artifacts, - "all_output_bits_non_affine": all( - artifact["exact_affine_output_bits"] == 0 for artifact in artifacts - ), - "verdict": "green", - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--ops", type=Path, action="append", required=True) - parser.add_argument("--shots", type=int, default=FULL_VERIFICATION_SHOTS) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - report = run(args.ops, args.shots) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/hyperplane_mitm.cpp b/src/point_add/memory/repro/hyperplane_mitm.cpp deleted file mode 100644 index 0365d1a8..00000000 --- a/src/point_add/memory/repro/hyperplane_mitm.cpp +++ /dev/null @@ -1,429 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - -constexpr std::uint32_t kConstant = 0x01ffffffU; -constexpr std::size_t kStateWords = 6; -constexpr std::size_t kHyperplaneWords = 5; -constexpr std::uint32_t kNormals = 31; - -using State = std::array; -using Hyperplane = std::array; -using Coordinates = std::array; - -struct HashRef { - std::uint64_t hash; - std::uint32_t ref; -}; - -struct Basis { - std::array rows{}; - int rank = 0; - - bool insert(std::uint32_t value) { - for (int pivot = 31; pivot >= 0; --pivot) { - if (((value >> pivot) & 1U) != 0 && rows[pivot] != 0) { - value ^= rows[pivot]; - } - } - if (value == 0) { - return false; - } - const int pivot = 31 - std::countl_zero(value); - for (int other = 0; other < 32; ++other) { - if (rows[other] != 0 && ((rows[other] >> pivot) & 1U) != 0) { - rows[other] ^= value; - } - } - rows[pivot] = value; - ++rank; - return true; - } - - bool contains(std::uint32_t value) const { - for (int pivot = 31; pivot >= 0; --pivot) { - if (((value >> pivot) & 1U) != 0 && rows[pivot] != 0) { - value ^= rows[pivot]; - } - } - return value == 0; - } -}; - -std::vector read_states(const std::string& path) { - std::ifstream input(path, std::ios::binary | std::ios::ate); - if (!input) { - throw std::runtime_error("cannot open " + path); - } - const auto bytes = input.tellg(); - constexpr std::streamoff record_bytes = static_cast(sizeof(State)); - if (bytes < 0 || bytes % record_bytes != 0) { - throw std::runtime_error("invalid frontier byte length for " + path); - } - std::vector states(static_cast(bytes / record_bytes)); - input.seekg(0); - input.read(reinterpret_cast(states.data()), bytes); - if (!input) { - throw std::runtime_error("short read from " + path); - } - return states; -} - -Coordinates state_coordinates(const State& state) { - Basis basis; - if (!basis.insert(kConstant)) { - throw std::runtime_error("constant basis insertion failed"); - } - Coordinates coordinates{}; - std::size_t count = 0; - for (const auto row : state) { - if (basis.insert(row)) { - if (count >= coordinates.size()) { - throw std::runtime_error("state rank exceeds six"); - } - coordinates[count++] = row; - } - } - if (count != coordinates.size() || basis.rank != 6) { - throw std::runtime_error("frontier state does not have affine rank six"); - } - return coordinates; -} - -std::array, kNormals> invariant_bases() { - std::array, kNormals> result{}; - for (std::uint32_t normal = 1; normal <= kNormals; ++normal) { - Basis basis; - std::size_t count = 0; - for (std::uint32_t form = 1; form <= kNormals && count < 4; ++form) { - if ((std::popcount(form & normal) & 1) != 0) { - continue; - } - if (basis.insert(form)) { - result[normal - 1][count++] = static_cast(form); - } - } - if (count != 4) { - throw std::runtime_error("failed to construct invariant hyperplane basis"); - } - } - return result; -} - -std::uint32_t linear_mask(const Coordinates& coordinates, std::uint32_t form) { - std::uint32_t value = 0; - for (std::size_t index = 0; index < coordinates.size(); ++index) { - if (((form >> index) & 1U) != 0) { - value ^= coordinates[index]; - } - } - return value; -} - -Hyperplane canonical_hyperplane(const Coordinates& coordinates, - const std::array& forms) { - Basis basis; - basis.insert(kConstant); - for (const auto form : forms) { - basis.insert(linear_mask(coordinates, form)); - } - if (basis.rank != 5) { - throw std::runtime_error("hyperplane rank is not five"); - } - Hyperplane result{}; - std::size_t index = 0; - for (int pivot = 31; pivot >= 0; --pivot) { - if (basis.rows[pivot] != 0) { - result[index++] = basis.rows[pivot]; - } - } - if (index != result.size()) { - throw std::runtime_error("canonical hyperplane has wrong size"); - } - return result; -} - -std::uint64_t mix64(std::uint64_t value) { - value ^= value >> 30; - value *= 0xbf58476d1ce4e5b9ULL; - value ^= value >> 27; - value *= 0x94d049bb133111ebULL; - value ^= value >> 31; - return value; -} - -std::uint64_t hash_hyperplane(const Hyperplane& hyperplane) { - std::uint64_t hash = 0x243f6a8885a308d3ULL; - for (std::size_t index = 0; index < hyperplane.size(); ++index) { - hash ^= mix64(static_cast(hyperplane[index]) + - 0x9e3779b97f4a7c15ULL * (index + 1)); - hash = std::rotl(hash, 17); - hash *= 0x9ddfea08eb382d69ULL; - } - return mix64(hash); -} - -Hyperplane hyperplane_for_ref(const std::vector& states, - const std::array, kNormals>& forms, - std::uint32_t ref) { - const std::uint32_t state_index = ref / kNormals; - const std::uint32_t normal_index = ref % kNormals; - if (state_index >= states.size()) { - throw std::runtime_error("hyperplane reference is out of range"); - } - return canonical_hyperplane(state_coordinates(states[state_index]), forms[normal_index]); -} - -std::vector enumerate_hyperplanes( - const std::vector& states, - const std::array, kNormals>& forms, - const char* label) { - if (states.size() > UINT32_MAX / kNormals) { - throw std::runtime_error("frontier is too large for 32-bit references"); - } - std::vector records; - records.reserve(states.size() * kNormals); - const auto started = std::chrono::steady_clock::now(); - for (std::uint32_t state_index = 0; state_index < states.size(); ++state_index) { - const auto coordinates = state_coordinates(states[state_index]); - for (std::uint32_t normal_index = 0; normal_index < kNormals; ++normal_index) { - const auto hyperplane = canonical_hyperplane(coordinates, forms[normal_index]); - records.push_back({hash_hyperplane(hyperplane), state_index * kNormals + normal_index}); - } - if ((state_index + 1) % 100000 == 0) { - const auto seconds = std::chrono::duration( - std::chrono::steady_clock::now() - started).count(); - std::cerr << label << " generated " << (state_index + 1) << "/" << states.size() - << " states in " << seconds << " s\n"; - } - } - return records; -} - -Basis basis_for_hyperplane(const Hyperplane& hyperplane) { - Basis basis; - for (const auto row : hyperplane) { - basis.insert(row); - } - if (basis.rank != 5 || !basis.contains(kConstant)) { - throw std::runtime_error("invalid shared hyperplane"); - } - return basis; -} - -Coordinates hyperplane_linear_coordinates(const Hyperplane& hyperplane) { - Basis basis; - basis.insert(kConstant); - Coordinates result{}; - std::size_t count = 0; - for (const auto row : hyperplane) { - if (basis.insert(row)) { - result[count++] = row; - } - } - if (count != 4) { - throw std::runtime_error("shared hyperplane does not have four linear coordinates"); - } - return result; -} - -std::uint32_t outside_row(const State& state, const Basis& hyperplane_basis) { - for (const auto row : state) { - if (!hyperplane_basis.contains(row)) { - return row; - } - } - throw std::runtime_error("state is contained in a rank-five hyperplane"); -} - -struct AdjacencyWitness { - std::uint8_t left = 0; - std::uint8_t right = 0; - std::uint8_t left_constant = 0; - std::uint8_t right_constant = 0; - std::uint32_t source_outside = 0; - std::uint32_t target_outside = 0; -}; - -bool adjacent(const State& source, const State& target, const Hyperplane& hyperplane, - AdjacencyWitness& witness) { - const auto hyperplane_basis = basis_for_hyperplane(hyperplane); - const auto source_outside = outside_row(source, hyperplane_basis); - const auto target_outside = outside_row(target, hyperplane_basis); - const auto delta = source_outside ^ target_outside; - const auto coordinates = hyperplane_linear_coordinates(hyperplane); - - std::array linear{}; - for (std::uint32_t form = 1; form < linear.size(); ++form) { - for (std::size_t index = 0; index < 4; ++index) { - if (((form >> index) & 1U) != 0) { - linear[form] ^= coordinates[index]; - } - } - } - for (std::uint32_t left = 1; left < 16; ++left) { - for (std::uint32_t right = left + 1; right < 16; ++right) { - for (std::uint32_t left_constant = 0; left_constant < 2; ++left_constant) { - const auto left_mask = linear[left] ^ (left_constant ? kConstant : 0U); - for (std::uint32_t right_constant = 0; right_constant < 2; ++right_constant) { - const auto right_mask = linear[right] ^ (right_constant ? kConstant : 0U); - const auto residual = delta ^ (left_mask & right_mask); - if (hyperplane_basis.contains(residual)) { - witness.left = static_cast(left); - witness.right = static_cast(right); - witness.left_constant = static_cast(left_constant); - witness.right_constant = static_cast(right_constant); - witness.source_outside = source_outside; - witness.target_outside = target_outside; - return true; - } - } - } - } - } - return false; -} - -void print_words(const char* name, const auto& words) { - std::cout << '\"' << name << "\":["; - for (std::size_t index = 0; index < words.size(); ++index) { - if (index != 0) { - std::cout << ','; - } - std::cout << words[index]; - } - std::cout << ']'; -} - -} // namespace - -int main(int argc, char** argv) { - try { - if (argc != 3) { - std::cerr << "usage: hyperplane_mitm X_DEPTH2.bin Y_DEPTH2.bin\n"; - return 2; - } - const auto started = std::chrono::steady_clock::now(); - const auto x_states = read_states(argv[1]); - const auto y_states = read_states(argv[2]); - const auto forms = invariant_bases(); - std::cerr << "loaded x=" << x_states.size() << " y=" << y_states.size() << " states\n"; - - auto x_records = enumerate_hyperplanes(x_states, forms, "x"); - auto y_records = enumerate_hyperplanes(y_states, forms, "y"); - const auto by_hash = [](const HashRef& left, const HashRef& right) { - return left.hash < right.hash; - }; - std::cerr << "sorting x records=" << x_records.size() << "\n"; - std::sort(x_records.begin(), x_records.end(), by_hash); - std::cerr << "sorting y records=" << y_records.size() << "\n"; - std::sort(y_records.begin(), y_records.end(), by_hash); - - std::size_t xi = 0; - std::size_t yi = 0; - std::uint64_t common_hashes = 0; - std::uint64_t exact_hyperplane_pairs = 0; - std::uint64_t tested_pairs = 0; - std::uint32_t first_x_ref = UINT32_MAX; - std::uint32_t first_y_ref = UINT32_MAX; - Hyperplane first_shared_hyperplane{}; - while (xi < x_records.size() && yi < y_records.size()) { - if (x_records[xi].hash < y_records[yi].hash) { - ++xi; - continue; - } - if (y_records[yi].hash < x_records[xi].hash) { - ++yi; - continue; - } - const auto hash = x_records[xi].hash; - const auto x_begin = xi; - const auto y_begin = yi; - while (xi < x_records.size() && x_records[xi].hash == hash) { - ++xi; - } - while (yi < y_records.size() && y_records[yi].hash == hash) { - ++yi; - } - ++common_hashes; - for (std::size_t x_index = x_begin; x_index < xi; ++x_index) { - const auto x_ref = x_records[x_index].ref; - const auto x_hyperplane = hyperplane_for_ref(x_states, forms, x_ref); - for (std::size_t y_index = y_begin; y_index < yi; ++y_index) { - const auto y_ref = y_records[y_index].ref; - const auto y_hyperplane = hyperplane_for_ref(y_states, forms, y_ref); - if (x_hyperplane != y_hyperplane) { - continue; - } - ++exact_hyperplane_pairs; - if (first_x_ref == UINT32_MAX) { - first_x_ref = x_ref; - first_y_ref = y_ref; - first_shared_hyperplane = x_hyperplane; - } - AdjacencyWitness witness; - ++tested_pairs; - const auto& x_state = x_states[x_ref / kNormals]; - const auto& y_state = y_states[y_ref / kNormals]; - if (!adjacent(x_state, y_state, x_hyperplane, witness)) { - continue; - } - const auto seconds = std::chrono::duration( - std::chrono::steady_clock::now() - started).count(); - std::cout << '{'; - std::cout << "\"verdict\":\"sat\",\"x_ref\":" << x_ref - << ",\"y_ref\":" << y_ref - << ",\"x_state_index\":" << x_ref / kNormals - << ",\"y_state_index\":" << y_ref / kNormals << ','; - print_words("x_state", x_state); - std::cout << ','; - print_words("y_state", y_state); - std::cout << ','; - print_words("shared_hyperplane", x_hyperplane); - std::cout << ",\"left\":" << static_cast(witness.left) - << ",\"right\":" << static_cast(witness.right) - << ",\"left_constant\":" << static_cast(witness.left_constant) - << ",\"right_constant\":" << static_cast(witness.right_constant) - << ",\"source_outside\":" << witness.source_outside - << ",\"target_outside\":" << witness.target_outside - << ",\"common_hashes\":" << common_hashes - << ",\"exact_hyperplane_pairs\":" << exact_hyperplane_pairs - << ",\"tested_pairs\":" << tested_pairs - << ",\"wall_seconds\":" << seconds << "}\n"; - return 0; - } - } - } - const auto seconds = std::chrono::duration( - std::chrono::steady_clock::now() - started).count(); - std::cout << "{\"verdict\":\"unsat\",\"common_hashes\":" << common_hashes - << ",\"exact_hyperplane_pairs\":" << exact_hyperplane_pairs - << ",\"tested_pairs\":" << tested_pairs; - if (first_x_ref != UINT32_MAX) { - std::cout << ",\"first_x_ref\":" << first_x_ref - << ",\"first_y_ref\":" << first_y_ref - << ",\"first_x_state_index\":" << first_x_ref / kNormals - << ",\"first_y_state_index\":" << first_y_ref / kNormals << ','; - print_words("first_x_state", x_states[first_x_ref / kNormals]); - std::cout << ','; - print_words("first_y_state", y_states[first_y_ref / kNormals]); - std::cout << ','; - print_words("first_shared_hyperplane", first_shared_hyperplane); - } - std::cout << ",\"wall_seconds\":" << seconds << "}\n"; - return 1; - } catch (const std::exception& error) { - std::cerr << "error: " << error.what() << '\n'; - return 2; - } -} diff --git a/src/point_add/memory/repro/schema_harness.py b/src/point_add/memory/repro/schema_harness.py deleted file mode 100755 index 59795ca2..00000000 --- a/src/point_add/memory/repro/schema_harness.py +++ /dev/null @@ -1,648 +0,0 @@ -#!/usr/bin/env python3 -"""Content-addressed predict/observe loop for ECDSA Fail research. - -The harness records reality; it does not edit source or certify circuits. Every -research iteration starts with one preregistered prediction and must receive an -observation before another iteration can begin. Hash-chain backtesting, niche -portfolio selection, mismatch reframing, and ten-iteration checkpoints keep the -loop auditable without installing a second controller. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import math -import os -from collections import Counter -from collections.abc import Mapping -from datetime import datetime, timezone -from pathlib import Path -from typing import Any - -try: - from artifact_io import fingerprint - from exact_scorer import score - from world_model import ( - CURRENT_FRONTIER, - ActionKind, - EvidenceKind, - InstrumentSet, - action_impact, - ) -except ModuleNotFoundError: - from .artifact_io import fingerprint - from .exact_scorer import score - from .world_model import ( - CURRENT_FRONTIER, - ActionKind, - EvidenceKind, - InstrumentSet, - action_impact, - ) - -SCHEMA_VERSION = 1 -MAX_ITERATIONS = 500 -ZERO_HASH = "0" * 64 -NICHES = { - "H0-zero-rounding": "verifier-specific construction crossing the zero-score rounding boundary", - "H1-gcd-apply": "GCD/apply traversal and controlled arithmetic", - "H2-square": "reversible modular square", - "H3-coordinate-shell": "classical-offset coordinate shell and source invariants", - "H4-postpasses": "exact postpasses, strip provenance, and calibration", - "H5-width": "peak-qubit schedule, cap, or complete alternative representation", -} -_RECORD_TYPES = { - "frontier", - "prediction", - "observation", - "candidate", - "reframe", - "submission", - "checkpoint", -} -_OBSERVATION_VERDICTS = {"pass", "fail", "no_effect", "inconclusive", "error"} -_CANDIDATE_STATUSES = {"live", "promoted", "retired"} - - -def _canonical_json(value: Mapping[str, Any]) -> bytes: - return json.dumps( - value, - sort_keys=True, - separators=(",", ":"), - allow_nan=False, - ).encode("utf-8") - - -def _hash_record(record: Mapping[str, Any]) -> str: - material = {key: value for key, value in record.items() if key != "record_sha256"} - return hashlib.sha256(_canonical_json(material)).hexdigest() - - -def _require_text(row: Mapping[str, Any], key: str) -> str: - value = row.get(key) - if not isinstance(value, str) or not value.strip(): - raise ValueError(f"{key} must be a non-empty string") - return value - - -def _require_int(row: Mapping[str, Any], key: str, *, minimum: int = 0) -> int: - value = row.get(key) - if type(value) is not int or value < minimum: - raise ValueError(f"{key} must be an integer >= {minimum}") - return value - - -def _require_number(row: Mapping[str, Any], key: str, *, nonnegative: bool = False) -> float: - value = row.get(key) - if isinstance(value, bool) or not isinstance(value, (int, float)): - raise ValueError(f"{key} must be a finite number") - result = float(value) - if not math.isfinite(result) or (nonnegative and result < 0.0): - raise ValueError(f"{key} must be {'non-negative and ' if nonnegative else ''}finite") - return result - - -def _require_sha256(row: Mapping[str, Any], key: str, *, optional: bool = False) -> str | None: - value = row.get(key) - if value is None and optional: - return None - if not isinstance(value, str) or len(value) != 64: - raise ValueError(f"{key} must be a SHA-256 digest") - try: - bytes.fromhex(value) - except ValueError as error: - raise ValueError(f"{key} must be hexadecimal") from error - return value.lower() - - -def _payload(record: Mapping[str, Any]) -> dict[str, Any]: - metadata = { - "schema_version", - "sequence", - "recorded_at", - "previous_sha256", - "record_sha256", - } - return {key: value for key, value in record.items() if key not in metadata} - - -def load_ledger(path: Path) -> tuple[dict[str, Any], ...]: - if not path.exists(): - return () - records: list[dict[str, Any]] = [] - previous = ZERO_HASH - with path.open(encoding="utf-8") as source: - for line_number, line in enumerate(source, start=1): - if not line.strip(): - continue - row = json.loads(line) - if not isinstance(row, dict): - raise ValueError(f"line {line_number}: record must be an object") - if row.get("schema_version") != SCHEMA_VERSION: - raise ValueError(f"line {line_number}: unsupported schema version") - if row.get("sequence") != len(records): - raise ValueError(f"line {line_number}: non-contiguous sequence") - if row.get("previous_sha256") != previous: - raise ValueError(f"line {line_number}: broken previous hash") - actual = _hash_record(row) - if row.get("record_sha256") != actual: - raise ValueError(f"line {line_number}: record hash mismatch") - records.append(row) - previous = actual - return tuple(records) - - -def _predictions(records: tuple[dict[str, Any], ...]) -> list[dict[str, Any]]: - return [record for record in records if record.get("type") == "prediction"] - - -def _observations_for(records: tuple[dict[str, Any], ...], iteration: int) -> list[dict[str, Any]]: - return [ - record - for record in records - if record.get("type") == "observation" and record.get("iteration") == iteration - ] - - -def _last_mismatch_is_reframed(records: tuple[dict[str, Any], ...]) -> bool: - mismatch_sequence = max( - ( - record["sequence"] - for record in records - if record.get("type") == "observation" and record.get("prediction_match") is False - ), - default=-1, - ) - if mismatch_sequence < 0: - return True - return any( - record.get("type") == "reframe" and record["sequence"] > mismatch_sequence - for record in records - ) - - -def _validate_frontier(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - if records: - raise ValueError("frontier can only initialize an empty ledger") - if _require_int(payload, "iteration") != 0: - raise ValueError("frontier iteration must be zero") - _require_text(payload, "submission_id") - _require_text(payload, "source_ref") - _require_sha256(payload, "ops_sha256") - _require_sha256(payload, "canonical_ops_sha256") - _require_int(payload, "score") - qubits = _require_int(payload, "qubits") - rounded_toffoli = _require_int(payload, "rounded_toffoli") - if score(float(rounded_toffoli), qubits) != payload["score"]: - raise ValueError("frontier metrics do not reproduce its score") - if _require_int(payload, "ceiling_score") != 0: - raise ValueError("pinned verifier ceiling must be zero") - if _require_int(payload, "max_iterations", minimum=1) != MAX_ITERATIONS: - raise ValueError(f"max_iterations must be {MAX_ITERATIONS}") - instruments = payload.get("instruments") - if not isinstance(instruments, Mapping): - raise ValueError("frontier requires instrument hashes") - for key in ("verifier_sha256", "simulator_sha256", "scorer_sha256", "identity_sha256"): - _require_sha256(instruments, key) - - -def _validate_prediction(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - predictions = _predictions(records) - iteration = _require_int(payload, "iteration", minimum=1) - expected_iteration = len(predictions) + 1 - if iteration != expected_iteration: - raise ValueError(f"prediction iteration must be {expected_iteration}") - if iteration > MAX_ITERATIONS: - raise ValueError(f"iteration cap {MAX_ITERATIONS} reached") - if predictions and not _observations_for(records, iteration - 1): - raise ValueError("previous prediction has no observation") - if not _last_mismatch_is_reframed(records): - raise ValueError("prediction mismatch requires a reframe before continuing") - if iteration > 10 and (iteration - 1) // 10 > 0: - checkpoint_iteration = ((iteration - 1) // 10) * 10 - if not any( - record.get("type") == "checkpoint" - and record.get("iteration") == checkpoint_iteration - for record in records - ): - raise ValueError(f"missing checkpoint at iteration {checkpoint_iteration}") - niche = _require_text(payload, "niche") - if niche not in NICHES: - raise ValueError(f"unknown niche {niche}") - action_kind = ActionKind(_require_text(payload, "action_kind")) - if action_kind is ActionKind.PROMOTION: - raise ValueError("promotion cannot be a research prediction") - _require_text(payload, "candidate_id") - _require_text(payload, "parent_candidate_id") - _require_sha256(payload, "parent_ops_sha256") - _require_text(payload, "mechanism") - delta_qubits = payload.get("delta_qubits") - if type(delta_qubits) is not int: - raise ValueError("delta_qubits must be an integer") - delta_toffoli = _require_number(payload, "delta_toffoli_mean") - _require_number(payload, "delta_toffoli_standard_deviation", nonnegative=True) - _require_text(payload, "correctness_risk") - full_verification_budget = _require_int(payload, "full_verification_budget") - if action_kind is ActionKind.NO_EFFECT and ( - delta_qubits != 0 or delta_toffoli != 0.0 or full_verification_budget != 0 - ): - raise ValueError("measurement-only predictions require zero deltas and zero full-run budget") - expected_invalidations = payload.get("expected_invalidations") - if not isinstance(expected_invalidations, list) or any( - not isinstance(value, str) for value in expected_invalidations - ): - raise ValueError("expected_invalidations must be a string list") - canonical = sorted(dependency.value for dependency in action_impact(action_kind).invalidated) - if sorted(expected_invalidations) != canonical: - raise ValueError( - "prediction invalidations differ from the world model: " - f"expected={canonical}:actual={sorted(expected_invalidations)}" - ) - - -def _prediction_for( - records: tuple[dict[str, Any], ...], iteration: int -) -> dict[str, Any] | None: - return next( - ( - record - for record in records - if record.get("type") == "prediction" and record.get("iteration") == iteration - ), - None, - ) - - -def _validate_observation(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - iteration = _require_int(payload, "iteration", minimum=1) - prediction = _prediction_for(records, iteration) - if prediction is None: - raise ValueError(f"observation has no prediction for iteration {iteration}") - observation_id = _require_text(payload, "observation_id") - if any( - record.get("type") == "observation" and record.get("observation_id") == observation_id - for record in records - ): - raise ValueError(f"duplicate observation_id {observation_id}") - stage = _require_text(payload, "stage") - if stage not in {"hash", "proxy", "proof", "full", "submission"}: - raise ValueError(f"unknown observation stage {stage}") - EvidenceKind(_require_text(payload, "evidence_kind")) - verdict = _require_text(payload, "verdict") - if verdict not in _OBSERVATION_VERDICTS: - raise ValueError(f"unknown observation verdict {verdict}") - _require_text(payload, "conclusion") - artifact_hash = _require_sha256(payload, "artifact_ops_sha256", optional=True) - prediction_match = payload.get("prediction_match") - if prediction_match is not None and type(prediction_match) is not bool: - raise ValueError("prediction_match must be boolean or null") - measurement = payload.get("measurement") - if measurement is not None and not isinstance(measurement, Mapping): - raise ValueError("measurement must be an object or null") - if stage == "full": - if artifact_hash is None: - raise ValueError("full observation requires exact artifact hash") - if payload["evidence_kind"] != EvidenceKind.TRUSTED_FULL.value: - raise ValueError("full observation requires trusted full evidence") - if not isinstance(measurement, Mapping): - raise ValueError("full observation requires measurement") - if _require_int(measurement, "shots") != 9_024: - raise ValueError("full observation must contain 9,024 shots") - for key in ( - "classical_failures", - "phase_garbage_batches", - "ancilla_garbage_batches", - ): - _require_int(measurement, key) - _require_int(measurement, "qubits") - _require_number(measurement, "average_toffoli", nonnegative=True) - _require_int(measurement, "score") - if artifact_hash == prediction["parent_ops_sha256"]: - raise ValueError("full verification denied for byte-identical parent artifact") - - -def _validate_candidate(payload: Mapping[str, Any]) -> None: - _require_int(payload, "iteration") - _require_text(payload, "candidate_id") - niche = _require_text(payload, "niche") - if niche not in NICHES: - raise ValueError(f"unknown niche {niche}") - status = _require_text(payload, "status") - if status not in _CANDIDATE_STATUSES: - raise ValueError(f"unknown candidate status {status}") - _require_text(payload, "parent_candidate_id") - _require_text(payload, "evidence") - _require_sha256(payload, "artifact_ops_sha256", optional=True) - - -def _validate_reframe(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - iteration = _require_int(payload, "iteration", minimum=1) - if _prediction_for(records, iteration) is None: - raise ValueError("reframe requires an existing iteration") - _require_text(payload, "claim") - _require_text(payload, "compression") - _require_text(payload, "forward_prediction") - - -def _validate_submission(payload: Mapping[str, Any]) -> None: - _require_int(payload, "iteration", minimum=1) - _require_text(payload, "submission_id") - _require_text(payload, "source_ref") - _require_sha256(payload, "artifact_ops_sha256") - _require_text(payload, "status") - _require_int(payload, "official_score") - _require_text(payload, "outcome") - - -def _validate_checkpoint(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - iteration = _require_int(payload, "iteration", minimum=10) - if iteration % 10: - raise ValueError("checkpoint iteration must be divisible by ten") - _require_sha256(payload, "segment_tail_sha256") - _require_sha256(payload, "summary_sha256") - _require_text(payload, "summary_path") - if not records or payload["segment_tail_sha256"] != records[-1]["record_sha256"]: - raise ValueError("checkpoint tail hash does not match the ledger") - - -def validate_payload(payload: Mapping[str, Any], records: tuple[dict[str, Any], ...]) -> None: - record_type = _require_text(payload, "type") - if record_type not in _RECORD_TYPES: - raise ValueError(f"unknown record type {record_type}") - if record_type == "frontier": - _validate_frontier(payload, records) - elif not records or records[0].get("type") != "frontier": - raise ValueError("ledger must start with a frontier record") - elif record_type == "prediction": - _validate_prediction(payload, records) - elif record_type == "observation": - _validate_observation(payload, records) - elif record_type == "candidate": - _validate_candidate(payload) - elif record_type == "reframe": - _validate_reframe(payload, records) - elif record_type == "submission": - _validate_submission(payload) - elif record_type == "checkpoint": - _validate_checkpoint(payload, records) - - -def append_payload( - path: Path, - payload: Mapping[str, Any], - *, - recorded_at: str | None = None, -) -> dict[str, Any]: - records = load_ledger(path) - validate_payload(payload, records) - record = { - "schema_version": SCHEMA_VERSION, - "sequence": len(records), - "recorded_at": recorded_at - or datetime.now(timezone.utc).isoformat(timespec="seconds").replace("+00:00", "Z"), - "previous_sha256": records[-1]["record_sha256"] if records else ZERO_HASH, - **payload, - } - record["record_sha256"] = _hash_record(record) - path.parent.mkdir(parents=True, exist_ok=True) - with path.open("a", encoding="utf-8") as destination: - destination.write(_canonical_json(record).decode("utf-8")) - destination.write("\n") - destination.flush() - os.fsync(destination.fileno()) - return record - - -def initialize_ledger(path: Path, repo: Path) -> dict[str, Any]: - if path.exists() and path.stat().st_size: - raise ValueError(f"ledger already initialized: {path}") - instruments = InstrumentSet.from_files( - repo / "src/bin/eval_circuit.rs", - repo / "src/sim.rs", - repo / "src/point_add/memory/repro/exact_scorer.py", - ) - artifact = fingerprint(repo / "ops.bin") - if artifact["compressed_ops_sha256"] != CURRENT_FRONTIER.ops_sha256: - raise ValueError("current ops.bin does not match the pinned frontier") - return append_payload( - path, - { - "type": "frontier", - "iteration": 0, - "submission_id": CURRENT_FRONTIER.submission_id, - "source_ref": CURRENT_FRONTIER.source_ref, - "ops_sha256": CURRENT_FRONTIER.ops_sha256, - "canonical_ops_sha256": CURRENT_FRONTIER.canonical_ops_sha256, - "score": CURRENT_FRONTIER.score, - "qubits": CURRENT_FRONTIER.qubits, - "rounded_toffoli": CURRENT_FRONTIER.rounded_toffoli, - "ceiling_score": 0, - "max_iterations": MAX_ITERATIONS, - "instruments": { - "verifier_sha256": instruments.verifier_sha256, - "simulator_sha256": instruments.simulator_sha256, - "scorer_sha256": instruments.scorer_sha256, - "identity_sha256": instruments.identity_sha256, - }, - }, - ) - - -def select_niche(records: tuple[dict[str, Any], ...]) -> dict[str, Any]: - counts = Counter( - record["niche"] for record in records if record.get("type") == "prediction" - ) - last_sequence = { - niche: max( - ( - record["sequence"] - for record in records - if record.get("type") == "prediction" and record.get("niche") == niche - ), - default=-1, - ) - for niche in NICHES - } - selected = min(NICHES, key=lambda niche: (counts[niche], last_sequence[niche], niche)) - return { - "selected_niche": selected, - "description": NICHES[selected], - "prediction_counts": dict(sorted((niche, counts[niche]) for niche in NICHES)), - } - - -def backtest(records: tuple[dict[str, Any], ...]) -> dict[str, Any]: - failures: list[str] = [] - if not records: - failures.append("empty_ledger") - elif records[0].get("type") != "frontier": - failures.append("missing_initial_frontier") - predictions = _predictions(records) - for expected, prediction in enumerate(predictions, start=1): - if prediction.get("iteration") != expected: - failures.append(f"noncontiguous_prediction:{prediction.get('iteration')}") - try: - action_kind = ActionKind(prediction["action_kind"]) - canonical = sorted( - dependency.value for dependency in action_impact(action_kind).invalidated - ) - if sorted(prediction.get("expected_invalidations", [])) != canonical: - failures.append(f"invalidation_mismatch:{expected}") - except (KeyError, ValueError): - failures.append(f"invalid_action_kind:{expected}") - observations = _observations_for(records, expected) - if expected < len(predictions) and not observations: - failures.append(f"missing_observation:{expected}") - completed = max( - (iteration for iteration in range(1, len(predictions) + 1) if _observations_for(records, iteration)), - default=0, - ) - for checkpoint_iteration in range(10, completed + 1, 10): - if not any( - record.get("type") == "checkpoint" - and record.get("iteration") == checkpoint_iteration - for record in records - ): - failures.append(f"missing_checkpoint:{checkpoint_iteration}") - if len(predictions) > MAX_ITERATIONS: - failures.append("iteration_cap_exceeded") - for record in records: - if record.get("type") == "candidate" and record.get("niche") not in NICHES: - failures.append(f"unknown_candidate_niche:{record.get('candidate_id')}") - return { - "model": "ECDSA Schema evidence loop", - "verdict": "green" if not failures else "red", - "records": len(records), - "iterations_started": len(predictions), - "iterations_completed": completed, - "remaining_iterations": MAX_ITERATIONS - len(predictions), - "tail_sha256": records[-1]["record_sha256"] if records else ZERO_HASH, - "pending_iteration": ( - predictions[-1]["iteration"] - if predictions and not _observations_for(records, predictions[-1]["iteration"]) - else None - ), - "failures": failures, - "portfolio": select_niche(records), - } - - -def checkpoint(path: Path, checkpoint_dir: Path, iteration: int) -> dict[str, Any]: - records = load_ledger(path) - if iteration % 10 or iteration < 10: - raise ValueError("checkpoint iteration must be a positive multiple of ten") - if any( - record.get("type") == "checkpoint" and record.get("iteration") == iteration - for record in records - ): - raise ValueError(f"checkpoint {iteration} already exists") - completed = { - record["iteration"] - for record in records - if record.get("type") == "observation" - } - if any(value not in completed for value in range(1, iteration + 1)): - raise ValueError(f"cannot checkpoint before iterations 1..{iteration} are observed") - verdicts = Counter( - record["verdict"] for record in records if record.get("type") == "observation" - ) - niches = Counter( - record["niche"] for record in records if record.get("type") == "prediction" - ) - live_candidates: dict[str, str] = {} - for record in records: - if record.get("type") != "candidate": - continue - if record["status"] == "live": - live_candidates[record["candidate_id"]] = record["niche"] - else: - live_candidates.pop(record["candidate_id"], None) - summary = { - "schema_version": SCHEMA_VERSION, - "iteration": iteration, - "segment_tail_sha256": records[-1]["record_sha256"], - "established": verdicts["pass"], - "refuted": verdicts["fail"] + verdicts["no_effect"], - "unresolved": verdicts["inconclusive"] + verdicts["error"], - "niche_attempts": dict(sorted(niches.items())), - "live_candidates": dict(sorted(live_candidates.items())), - "next_portfolio": select_niche(records), - } - summary_bytes = _canonical_json(summary) - summary_sha = hashlib.sha256(summary_bytes).hexdigest() - checkpoint_dir.mkdir(parents=True, exist_ok=True) - summary_path = checkpoint_dir / f"iteration-{iteration:04d}-{summary_sha[:12]}.json" - if summary_path.exists(): - raise ValueError(f"checkpoint file already exists: {summary_path}") - summary_path.write_bytes(summary_bytes + b"\n") - record = append_payload( - path, - { - "type": "checkpoint", - "iteration": iteration, - "segment_tail_sha256": summary["segment_tail_sha256"], - "summary_sha256": summary_sha, - "summary_path": str(summary_path), - }, - ) - return {"record": record, "summary": summary} - - -def _read_payload(path: Path) -> Mapping[str, Any]: - payload = json.loads(path.read_text(encoding="utf-8")) - if not isinstance(payload, Mapping): - raise ValueError("record JSON must be an object") - return payload - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "--ledger", - type=Path, - default=Path(".autoresearch/measurements.jsonl"), - ) - subparsers = parser.add_subparsers(dest="command", required=True) - subparsers.add_parser("init") - append_parser = subparsers.add_parser("append") - append_parser.add_argument("record_json", type=Path) - subparsers.add_parser("backtest") - subparsers.add_parser("status") - subparsers.add_parser("select") - checkpoint_parser = subparsers.add_parser("checkpoint") - checkpoint_parser.add_argument("iteration", type=int) - checkpoint_parser.add_argument( - "--checkpoint-dir", - type=Path, - default=Path(".autoresearch/checkpoints"), - ) - args = parser.parse_args() - repo = Path(__file__).resolve().parents[4] - - try: - if args.command == "init": - output = initialize_ledger(args.ledger, repo) - elif args.command == "append": - output = append_payload(args.ledger, _read_payload(args.record_json)) - elif args.command == "backtest": - output = backtest(load_ledger(args.ledger)) - elif args.command == "status": - output = backtest(load_ledger(args.ledger)) - elif args.command == "select": - output = select_niche(load_ledger(args.ledger)) - else: - output = checkpoint(args.ledger, args.checkpoint_dir, args.iteration) - except (OSError, ValueError, KeyError, json.JSONDecodeError) as error: - print(json.dumps({"verdict": "red", "error": str(error)}, sort_keys=True)) - return 1 - - print(json.dumps(output, sort_keys=True)) - if args.command in {"backtest", "status"}: - return 0 if output["verdict"] == "green" else 1 - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/test_dgm_search.py b/src/point_add/memory/repro/test_dgm_search.py deleted file mode 100644 index ee4f8e6f..00000000 --- a/src/point_add/memory/repro/test_dgm_search.py +++ /dev/null @@ -1,507 +0,0 @@ -from __future__ import annotations - -import json -import subprocess -import tempfile -import unittest -from dataclasses import replace -from pathlib import Path - -import dgm_search as dgm -import schema_harness as harness -import test_schema_harness as schema_fixtures -import world_model as wm - - -HASH_A = "11" * 32 -HASH_B = "22" * 32 -HASH_C = "33" * 32 - - -def frontier() -> dict[str, object]: - return { - "type": "frontier", - "sequence": 0, - "submission_id": "frontier-submission", - "source_ref": "abc1234-source", - "ops_sha256": HASH_A, - "canonical_ops_sha256": HASH_B, - "score": 1_000, - "rounded_toffoli": 10, - "qubits": 100, - } - - -def prediction( - iteration: int, - candidate_id: str, - parent: str = "abc1234-frontier", - niche: str = "H1-gcd-apply", -) -> dict[str, object]: - return { - "type": "prediction", - "sequence": iteration, - "iteration": iteration, - "candidate_id": candidate_id, - "parent_candidate_id": parent, - "niche": niche, - "delta_qubits": 0, - "delta_toffoli_mean": -1.0, - "delta_toffoli_standard_deviation": 0.5, - } - - -def node(candidate_id: str, score: float, children: int = 0) -> dgm.ArchiveNode: - return dgm.ArchiveNode( - candidate_id=candidate_id, - parent_candidate_id="root", - niche="H1-gcd-apply", - iteration=1, - status="live", - frontier_submission_id="submission-root", - source_ref=f"refs/{candidate_id}", - artifact_ops_sha256=HASH_A, - canonical_artifact_sha256=HASH_B, - actual_score=int(score), - average_toffoli=score / 100, - qubits=100, - emitted_ops=10, - predicted_score=score, - prediction_standard_deviation=0.0, - conservative_score=score, - functioning=True, - reproducible=True, - functioning_children=children, - ) - - -class DgmArchiveTests(unittest.TestCase): - def test_archive_has_one_real_root_and_ineligible_external_placeholders(self) -> None: - records = [ - frontier(), - prediction(1, "candidate-a"), - prediction(2, "candidate-b", parent="external-frontier"), - ] - archive = {item.candidate_id: item for item in dgm.build_archive(records)} - - self.assertTrue(archive["abc1234-frontier"].functioning) - self.assertTrue(archive["abc1234-frontier"].reproducible) - self.assertFalse(archive["external-frontier"].functioning) - self.assertFalse(archive["external-frontier"].reproducible) - self.assertEqual( - [item.candidate_id for item in archive.values() if item.niche == "__frontier__" and item.functioning], - ["abc1234-frontier"], - ) - - def test_renamed_retained_candidate_owns_same_iteration_full_evidence(self) -> None: - records = [ - frontier(), - prediction(1, "predicted-name"), - { - "type": "observation", - "iteration": 1, - "stage": "full", - "verdict": "pass", - "artifact_ops_sha256": HASH_C, - "measurement": { - "average_toffoli": 8.0, - "qubits": 100, - "score": 800, - "classical_failures": 0, - "phase_garbage_batches": 0, - "ancilla_garbage_batches": 0, - }, - }, - { - "type": "candidate", - "iteration": 1, - "candidate_id": "retained-name", - "parent_candidate_id": "abc1234-frontier", - "niche": "H1-gcd-apply", - "status": "promoted", - "source_ref": "retained-source", - "artifact_ops_sha256": HASH_C, - "canonical_artifact_sha256": HASH_A, - "evidence": "trusted full", - }, - ] - archive = {item.candidate_id: item for item in dgm.build_archive(records)} - - self.assertFalse(archive["predicted-name"].functioning) - self.assertTrue(archive["retained-name"].functioning) - self.assertEqual(archive["retained-name"].actual_score, 800) - self.assertEqual(archive["retained-name"].predicted_score, 800) - - def test_selection_is_deterministic_and_every_eligible_node_is_nonzero(self) -> None: - nodes = (node("a", 800), node("b", 900), node("c", 1_000)) - distribution = dgm.parent_distribution(nodes, "H1-gcd-apply") - first = dgm.choose_parent( - nodes, - niche="H1-gcd-apply", - iteration=17, - ledger_tail_sha256=HASH_A, - ) - second = dgm.choose_parent( - tuple(reversed(nodes)), - niche="H1-gcd-apply", - iteration=17, - ledger_tail_sha256=HASH_A, - ) - - self.assertTrue(all(item[-1] > 0.0 for item in distribution)) - self.assertAlmostEqual(sum(item[-1] for item in distribution), 1.0) - self.assertEqual(first.to_mapping(), second.to_mapping()) - - def test_functioning_child_count_strictly_reduces_equal_quality_weight(self) -> None: - without_children = node("a", 800, children=0) - with_children = node("b", 800, children=2) - distribution = { - item[0].candidate_id: item for item in dgm.parent_distribution( - (without_children, with_children), "H1-gcd-apply" - ) - } - self.assertGreater(distribution["a"][3], distribution["b"][3]) - - def test_selected_problem_niche_keeps_cross_niche_stepping_stones(self) -> None: - other_niche = replace(node("other", 700), niche="H2-square") - distribution = dgm.parent_distribution( - (node("local", 800), other_niche), - "H1-gcd-apply", - ) - self.assertEqual( - {item[0].candidate_id for item in distribution}, - {"local", "other"}, - ) - - def test_emitter_ucb_and_mismatch_abductor_are_deterministic(self) -> None: - first = dgm.select_emitter( - [frontier()], - iteration=63, - ledger_tail_sha256=HASH_A, - ) - self.assertEqual(first["emitter"], "literature") - - records = [ - frontier(), - { - "type": "observation", - "prediction_match": False, - }, - ] - self.assertEqual( - dgm.select_emitter( - records, - iteration=64, - ledger_tail_sha256=HASH_A, - )["emitter"], - "abductor", - ) - - explored = [ - frontier(), - *[ - { - "type": "candidate", - "emitter": emitter, - "archive_contribution": emitter == "refiner", - } - for emitter in dgm.EMITTERS - ], - ] - one = dgm.select_emitter( - explored, - iteration=65, - ledger_tail_sha256=HASH_B, - ) - two = dgm.select_emitter( - explored, - iteration=65, - ledger_tail_sha256=HASH_B, - ) - self.assertEqual(one, two) - self.assertEqual(one["emitter"], "refiner") - - -class DgmBoundaryTests(unittest.TestCase): - def test_secret_and_proxy_environment_is_redacted_but_auth_paths_survive(self) -> None: - clean = dgm.sanitized_environment( - { - "PATH": "/bin", - "HOME": "/safe/home", - "CODEX_HOME": "/safe/codex", - "OPENAI_API_KEY": "secret", - "ECDSAFAIL_TOKEN": "secret", - "SSH_AUTH_SOCK": "/tmp/agent", - "HTTPS_PROXY": "http://proxy", - "LD_PRELOAD": "/bad.so", - } - ) - self.assertEqual(clean["HOME"], "/safe/home") - self.assertEqual(clean["CODEX_HOME"], "/safe/codex") - self.assertNotIn("OPENAI_API_KEY", clean) - self.assertNotIn("ECDSAFAIL_TOKEN", clean) - self.assertNotIn("SSH_AUTH_SOCK", clean) - self.assertNotIn("HTTPS_PROXY", clean) - self.assertNotIn("LD_PRELOAD", clean) - self.assertEqual(clean["CARGO_NET_OFFLINE"], "true") - - def test_candidate_refs_and_mutation_scope_fail_closed(self) -> None: - self.assertEqual( - dgm.candidate_ref("safe-id.1"), - "refs/autoresearch/candidates/safe-id.1", - ) - for unsafe in ("../escape", "has space", "-option", "a..b"): - with self.subTest(unsafe=unsafe), self.assertRaises(ValueError): - dgm.candidate_ref(unsafe) - self.assertEqual( - dgm.validate_mutation_paths(["src/point_add/mod.rs"]), - ("src/point_add/mod.rs",), - ) - for unsafe in ( - "src/bin/eval_circuit.rs", - "src/point_add/memory/RIG.md", - "src/point_add/memory/repro/dgm_search.py", - "../src/point_add/mod.rs", - ): - with self.subTest(unsafe=unsafe), self.assertRaises(ValueError): - dgm.validate_mutation_paths([unsafe]) - - def test_patch_application_rejects_escape_and_symlink_modes(self) -> None: - with tempfile.TemporaryDirectory() as directory: - root = Path(directory) - subprocess.run(["git", "init", "-q", str(root)], check=True) - source = root / "src/point_add" - source.mkdir(parents=True) - (source / "mod.rs").write_text("fn old() {}\n", encoding="utf-8") - subprocess.run(["git", "-C", str(root), "add", "src/point_add/mod.rs"], check=True) - subprocess.run( - [ - "git", - "-C", - str(root), - "-c", - "user.name=test", - "-c", - "user.email=test@example.com", - "commit", - "-qm", - "base", - ], - check=True, - ) - valid = """diff --git a/src/point_add/mod.rs b/src/point_add/mod.rs ---- a/src/point_add/mod.rs -+++ b/src/point_add/mod.rs -@@ -1 +1 @@ --fn old() {} -+fn new() {} -""" - self.assertEqual( - dgm.validate_and_apply_patch(root, valid), - ("src/point_add/mod.rs",), - ) - escape = valid.replace("src/point_add/mod.rs", "src/bin/eval_circuit.rs") - with self.assertRaises(ValueError): - dgm.validate_and_apply_patch(root, escape) - symlink = """diff --git a/src/point_add/link.rs b/src/point_add/link.rs -new file mode 120000 ---- /dev/null -+++ b/src/point_add/link.rs -@@ -0,0 +1 @@ -+../../outside -""" - with self.assertRaises(ValueError): - dgm.validate_and_apply_patch(root, symlink) - - def test_semantic_hash_outranks_compressed_encoding_hash(self) -> None: - artifact = { - "compressed_ops_sha256": HASH_C, - "canonical_semantic_sha256": HASH_B, - } - self.assertTrue( - dgm.semantic_noop( - artifact, - parent_compressed_sha256=HASH_A, - parent_canonical_sha256=HASH_B, - ) - ) - self.assertFalse( - dgm.semantic_noop( - artifact, - parent_compressed_sha256=HASH_A, - parent_canonical_sha256=HASH_A, - ) - ) - - def test_world_model_evidence_gate_blocks_unproved_exact_rewrite(self) -> None: - base = schema_fixtures.prediction_payload( - 1, action_kind=wm.ActionKind.EXACT_REWRITE - ) - base["candidate_id"] = "dgm-i001-rewrite" - reasons = dgm.full_gate_reasons( - base, - artifact_ops_sha256=HASH_B, - supporting_evidence={wm.EvidenceKind.LOW_SHOT_SCREEN}, - ) - self.assertIn( - "missing_discriminating_evidence:scoped_machine_proof", - reasons, - ) - - representation = schema_fixtures.prediction_payload( - 1, action_kind=wm.ActionKind.REPRESENTATION - ) - representation["candidate_id"] = "dgm-i001-representation" - self.assertEqual( - dgm.full_gate_reasons( - representation, - artifact_ops_sha256=HASH_B, - supporting_evidence={wm.EvidenceKind.LOW_SHOT_SCREEN}, - ), - (), - ) - - def test_promotion_report_requires_fresh_frontier_and_exact_clean_beat(self) -> None: - prediction_row = schema_fixtures.prediction_payload( - 1, action_kind=wm.ActionKind.REPRESENTATION - ) - prediction_row["candidate_id"] = "dgm-i001-beat" - prediction_row["parent_frontier_submission_id"] = "frontier-submission" - artifact = { - "qubits": 100, - "emitted_ops": 123, - } - result = dgm.StageResult( - stage="full", - passed=True, - conclusion="exact pass", - evidence_kind=wm.EvidenceKind.TRUSTED_FULL.value, - artifact_ops_sha256=HASH_B, - canonical_artifact_sha256=HASH_C, - measurement={ - "shots": 9_024, - "qubits": 100, - "average_toffoli": 8.0, - "total_toffoli": 8 * 9_024, - "score": 800, - "classical_failures": 0, - "phase_garbage_batches": 0, - "ancilla_garbage_batches": 0, - }, - ) - refreshed = wm.Frontier( - submission_id="frontier-submission", - source_ref="frontier-source", - score=1_000, - qubits=100, - rounded_toffoli=10, - ops_sha256=HASH_A, - canonical_ops_sha256=HASH_A, - emitted_ops=100, - ) - accepted = dgm.promotion_report( - prediction_row, - candidate_source_ref="refs/autoresearch/candidates/dgm-i001-beat", - artifact=artifact, - result=result, - refreshed_frontier=refreshed, - ) - self.assertTrue(accepted["allowed"]) - - stale = dict(prediction_row) - stale["parent_frontier_submission_id"] = "older-submission" - rejected = dgm.promotion_report( - stale, - candidate_source_ref="refs/autoresearch/candidates/dgm-i001-beat", - artifact=artifact, - result=result, - refreshed_frontier=refreshed, - ) - self.assertFalse(rejected["allowed"]) - self.assertIn("stale_frontier_parent", rejected["reasons"]) - - def test_evaluator_output_parser_requires_all_exact_channels(self) -> None: - output = """ - tested shots : 512 - classical mismatches : 0 - phase-garbage batches : 0 - ancilla-garbage batches : 0 - avg executed Toffoli : 8.250 - total Toffoli (sum) : 4224 over 512 shots - qubits : 100 -""" - parsed = dgm._parse_evaluator_output(output) - self.assertEqual(parsed["shots"], 512) - self.assertEqual(parsed["total_toffoli"], 4_224) - self.assertEqual(parsed["score"], 800) - with self.assertRaises(ValueError): - dgm._parse_evaluator_output("tested shots: 512") - - def test_controller_lock_is_exclusive(self) -> None: - with tempfile.TemporaryDirectory() as directory: - lock = Path(directory) / "dgm.lock" - with dgm.controller_lock(lock): - with self.assertRaises(RuntimeError): - with dgm.controller_lock(lock): - pass - - def test_pending_dgm_crash_recovery_records_error_not_hypothesis_failure(self) -> None: - with tempfile.TemporaryDirectory() as directory: - ledger = Path(directory) / "measurements.jsonl" - harness.append_payload(ledger, schema_fixtures.frontier_payload()) - pending = schema_fixtures.prediction_payload(1) - pending["candidate_id"] = "dgm-i001-test" - harness.append_payload(ledger, pending) - - recovered = dgm.recover_pending_infrastructure_error( - ledger, - conclusion="worker host restarted", - ) - status = harness.backtest(harness.load_ledger(ledger)) - - self.assertEqual(recovered["verdict"], "error") - self.assertIsNone(recovered["prediction_match"]) - self.assertIsNone(status["pending_iteration"]) - - def test_archive_snapshot_json_is_stable(self) -> None: - records = [frontier(), prediction(1, "candidate-a")] - first = json.dumps( - [item.to_mapping() for item in dgm.build_archive(records)], - sort_keys=True, - separators=(",", ":"), - ) - second = json.dumps( - [item.to_mapping() for item in dgm.build_archive(records)], - sort_keys=True, - separators=(",", ":"), - ) - self.assertEqual(first, second) - - def test_public_frontier_parser_uses_best_promoted_exact_metrics(self) -> None: - output = """ -2684231 solver-a \x1b[32mpromoted\x1b[39m 1488395734 {"qubits":1154,"toffoli":1289771} -820494 7726431 7/30/26, 4:13 AM -ce54b72 solver-b \x1b[31mrejected\x1b[39m 1488395734 {"qubits":1154,"toffoli":1289771} 0 5ac0936 7/30/26, 11:43 AM -9f99e0b solver-a \x1b[32mpromoted\x1b[39m 1488026454 {"qubits":1154,"toffoli":1289451} -369280 5265674 7/30/26, 3:58 PM -""" - frontier = dgm.parse_public_frontier_table(output) - self.assertEqual(frontier.submission_id, "9f99e0b") - self.assertEqual(frontier.source_ref, "5265674") - self.assertEqual(frontier.score, 1_488_026_454) - self.assertEqual(frontier.qubits, 1_154) - self.assertEqual(frontier.rounded_toffoli, 1_289_451) - - def test_promoted_public_seed_updates_certified_best_score(self) -> None: - records = [ - frontier(), - { - "type": "candidate", - "status": "promoted", - "official_submission_id": "new-public", - "actual_score": 700, - }, - ] - self.assertEqual(dgm._best_score(records), 700) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_exact_scorer.py b/src/point_add/memory/repro/test_exact_scorer.py deleted file mode 100755 index d5c16ae3..00000000 --- a/src/point_add/memory/repro/test_exact_scorer.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python3 - -import math -import unittest - -from exact_scorer import U64_MAX, score, score_from_totals - - -class ExactScorerTests(unittest.TestCase): - def test_rounds_nonnegative_half_up(self) -> None: - self.assertEqual(score(1.499999, 2), 2) - self.assertEqual(score(1.5, 2), 4) - - def test_saturates_product_to_u64(self) -> None: - self.assertEqual(score(float((1 << 64) - 2048), 2), U64_MAX) - - def test_live_frontier_from_average_and_totals(self) -> None: - expected = 1_490_805_286 - self.assertEqual(score(1_291_859.302, 1_154), expected) - self.assertEqual(score_from_totals(11_657_738_337, 9_024, 1_154), expected) - - def test_rejects_invalid_averages(self) -> None: - for value in (-1.0, math.inf, math.nan, float(1 << 64)): - with self.subTest(value=value), self.assertRaises(ValueError): - score(value, 1) - with self.assertRaises(TypeError): - score(True, 1) - - def test_rejects_invalid_unsigned_inputs(self) -> None: - for args in ((-1, 1, 1), (1, 0, 1), (1, 1, -1), (1 << 64, 1, 1)): - with self.subTest(args=args), self.assertRaises(ValueError): - score_from_totals(*args) - with self.assertRaises(TypeError): - score_from_totals(True, 1, 1) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_h0_debug_payload_census.py b/src/point_add/memory/repro/test_h0_debug_payload_census.py deleted file mode 100644 index 7309bc32..00000000 --- a/src/point_add/memory/repro/test_h0_debug_payload_census.py +++ /dev/null @@ -1,26 +0,0 @@ -from __future__ import annotations - -import unittest - -import h0_debug_payload_census as debug_payload -from h0_fixed_point_census import Scope - - -class DebugPrintPayloadCensusTests(unittest.TestCase): - def test_reduced_payload_domain_is_complete_and_unique(self) -> None: - records = tuple(debug_payload._payload_records(1)) - self.assertEqual(len(records), debug_payload.payload_state_count(1)) - self.assertEqual(len(records), 1_215) - self.assertEqual(len(set(records)), len(records)) - self.assertTrue(all(len(record) == 49 for record in records)) - - def test_small_exact_census_is_stable(self) -> None: - report = debug_payload.census(Scope(1, 1)) - self.assertEqual(report["checked_pairs"], 19_440) - self.assertEqual(report["successful_pairs"], 1_189) - self.assertEqual(report["successful_tables"], 16) - self.assertTrue(report["complete"]) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_h0_fixed_point_census.py b/src/point_add/memory/repro/test_h0_fixed_point_census.py deleted file mode 100644 index 65b7a5f5..00000000 --- a/src/point_add/memory/repro/test_h0_fixed_point_census.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import annotations - -import unittest - -import h0_fixed_point_census as fixed_point - - -class ReducedFixedPointCensusTests(unittest.TestCase): - def test_candidate_count_uses_distinct_canonical_keys(self) -> None: - self.assertEqual(fixed_point.Scope(1, 1).candidate_count, 16) - self.assertEqual(fixed_point.Scope(1, 2).candidate_count, 96) - self.assertEqual(fixed_point.Scope(2, 2).candidate_count, 30_720) - - def test_exact_small_censuses_have_stable_fixed_points(self) -> None: - one_row = fixed_point.census(fixed_point.Scope(1, 1)) - two_rows = fixed_point.census(fixed_point.Scope(2, 2)) - self.assertTrue(one_row["complete"]) - self.assertTrue(two_rows["complete"]) - self.assertEqual(one_row["fixed_points"], 1) - self.assertEqual(two_rows["fixed_points"], 2) - - def test_production_lookup_family_has_inverse_density_scale(self) -> None: - log2_states = fixed_point._log2_candidate_states(27, 512, 9_024) - self.assertGreater(log2_states, 4_700_000) - self.assertLess(log2_states, 4_800_000) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_h0_nonce_fixed_point_census.py b/src/point_add/memory/repro/test_h0_nonce_fixed_point_census.py deleted file mode 100644 index 0542febf..00000000 --- a/src/point_add/memory/repro/test_h0_nonce_fixed_point_census.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import annotations - -import unittest - -import h0_fixed_point_census as fixed_point -import h0_nonce_fixed_point_census as nonce_census -from zero_score_lookup import CANONICAL_RECORD_BYTES - - -class NonceFixedPointCensusTests(unittest.TestCase): - def test_nonce_tail_is_two_self_cancelling_x_gates_per_bit(self) -> None: - tail = nonce_census._nonce_tail(5, 3) - self.assertEqual(len(tail), 6 * CANONICAL_RECORD_BYTES) - - def test_exact_reduced_nonce_census_is_complete(self) -> None: - report = nonce_census.census(fixed_point.Scope(1, 1), 2) - self.assertTrue(report["complete"]) - self.assertEqual(report["checked_pairs"], 64) - self.assertEqual(report["successful_pairs"], 1) - self.assertAlmostEqual(report["expected_pair_success_density"], 1 / 16) - - def test_invalid_nonce_is_rejected(self) -> None: - with self.assertRaises(ValueError): - nonce_census._nonce_tail(4, 2) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_h0_permutation_fixed_point_census.py b/src/point_add/memory/repro/test_h0_permutation_fixed_point_census.py deleted file mode 100644 index 8b41a918..00000000 --- a/src/point_add/memory/repro/test_h0_permutation_fixed_point_census.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import annotations - -import unittest - -import h0_permutation_fixed_point_census as permutation -from h0_fixed_point_census import Scope - - -class SemanticPermutationCensusTests(unittest.TestCase): - def test_row_variant_count_matches_distinct_serialized_streams(self) -> None: - variants = list(permutation._row_variants(key=0, correction=3, key_bits=2)) - self.assertEqual(permutation._row_variant_count(0, 3, 2), 16) - self.assertEqual(len(variants), 16) - self.assertEqual(len(set(variants)), 16) - - def test_small_exact_census_is_stable(self) -> None: - report = permutation.census(Scope(half_width=1, rows=1)) - self.assertEqual(report["candidate_tables"], 16) - self.assertEqual(report["declared_semantic_variants"], 70) - self.assertEqual(report["checked_semantic_variants"], 70) - self.assertEqual(report["unique_semantic_sha256"], 70) - self.assertEqual(report["semantic_sha256_collisions"], 0) - self.assertEqual(report["fixed_variants"], 8) - self.assertEqual(report["tables_with_fixed_variant"], 6) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_h3_affine_shell_rank.py b/src/point_add/memory/repro/test_h3_affine_shell_rank.py deleted file mode 100644 index c5b92e08..00000000 --- a/src/point_add/memory/repro/test_h3_affine_shell_rank.py +++ /dev/null @@ -1,28 +0,0 @@ -from __future__ import annotations - -import unittest - -import h3_affine_shell_rank as affine_rank - - -class AffineShellRankTests(unittest.TestCase): - def test_duplicate_features_expose_inconsistent_output_bit(self) -> None: - first = (0, 0, 0, 0, 0, 0) - second = (0, 0, 0, 0, 1, 0) - report = affine_rank.reduce_dataset([first, second]) - self.assertEqual(report["feature_rank"], 1) - self.assertEqual(report["dependency_rows"], 1) - self.assertEqual(report["inconsistent_output_bits"], 1) - self.assertEqual(report["exact_affine_output_bits"], 511) - self.assertNotIn(0, report["exact_affine_output_indices"]) - - def test_independent_rows_can_fit_every_output_bit(self) -> None: - rows = [(0, 0, 0, 0, 0, 0), (1, 0, 0, 0, 1, 0)] - report = affine_rank.reduce_dataset(rows) - self.assertEqual(report["feature_rank"], 2) - self.assertEqual(report["dependency_rows"], 0) - self.assertEqual(report["exact_affine_output_bits"], 512) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_repro_contracts.py b/src/point_add/memory/repro/test_repro_contracts.py deleted file mode 100644 index 08182b39..00000000 --- a/src/point_add/memory/repro/test_repro_contracts.py +++ /dev/null @@ -1,103 +0,0 @@ -from __future__ import annotations - -import math -import tempfile -import unittest -from pathlib import Path - -import y5_joint_codec_neighborhood as neighborhood -import y5_joint_codec_synth as joint -import y5_joint_codec_stochastic as stochastic -import y5_joint_codec_triple_fusion as triple_fusion -import y5_joint_codec_two_rebase as two_rebase -import y5_normalizer_synth as normalizer -import y5_pair25_quotient as quotient - - -class RetainedReproducerContracts(unittest.TestCase): - def setUp(self) -> None: - self._width = normalizer.WIDTH - self._reference_ccx_count = normalizer.REFERENCE_CCX_COUNT - self._reference_table = normalizer.reference_table - - def tearDown(self) -> None: - normalizer.WIDTH = self._width - normalizer.REFERENCE_CCX_COUNT = self._reference_ccx_count - normalizer.reference_table = self._reference_table - - def test_pair_compressor_derives_the_exact_pair25_domain(self) -> None: - pair_states = [ - quotient.compress_pair(first, second) - for first in quotient.VALID_SYMBOLS - for second in quotient.VALID_SYMBOLS - ] - self.assertEqual(len(pair_states), 25) - self.assertEqual(len(set(pair_states)), 25) - self.assertEqual(tuple(sorted(pair_states)), normalizer.PAIR25_INPUTS) - outputs = [normalizer.reference_table()[value] for value in pair_states] - self.assertEqual(sorted(outputs), list(range(25))) - - def test_joint_reference_is_a_nine_shear_six_wire_permutation(self) -> None: - operations, table = joint.configure_problem() - self.assertEqual(len(table), 64) - self.assertEqual(len(set(table)), 64) - self.assertEqual(sorted(table[value] for value in joint.PAIR_INPUTS), list(range(25))) - - program = normalizer.reference_program(operations) - self.assertEqual(len(program["shears"]), 9) - self.assertEqual( - normalizer.verify_program(program, table, list(range(64)))["verdict"], - "green", - ) - compiled = normalizer.compile_program(program) - compiled_report = normalizer.verify_compiled(compiled, table, list(range(64))) - self.assertEqual(compiled_report["verdict"], "green") - self.assertEqual(compiled_report["ccx"], 9) - - def test_exact_eight_cnf_matches_the_recorded_problem(self) -> None: - joint.configure_problem() - with tempfile.TemporaryDirectory() as directory: - output = Path(directory) - (output / "cnf").mkdir() - cnf, variables, table, path = joint.build_cnf(8, output) - self.assertTrue(path.is_file()) - self.assertEqual(cnf.nvars, 11_416) - self.assertEqual(len(cnf.clauses), 54_051) - self.assertEqual(len(variables.shears), 8) - self.assertEqual(len(table), 64) - - def test_stochastic_codec_fitness_distinguishes_exact_noninvertible_drop(self) -> None: - operations, table = joint.configure_problem() - reference = stochastic._from_program(normalizer.reference_program(operations)) - domain = list(joint.PAIR_INPUTS) - targets = [table[value] for value in domain] - initial_columns = stochastic._columns(domain, joint.WIDTH) - target_columns = stochastic._columns(targets, joint.WIDTH) - all_rows = (1 << len(domain)) - 1 - reference_result = stochastic.evaluate_sequence( - reference, initial_columns, target_columns, all_rows - ) - dropped_result = stochastic.evaluate_sequence( - reference[:2] + reference[3:], - initial_columns, - target_columns, - all_rows, - ) - self.assertEqual(reference_result.fitness, (0, 0, 0)) - self.assertEqual(dropped_result.errors, 0) - self.assertEqual(dropped_result.output_rank, 5) - self.assertGreater(dropped_result.fitness, reference_result.fitness) - - def test_neighborhood_branch_counts_match_the_recorded_scopes(self) -> None: - self.assertEqual(joint.REFERENCE_CCX_COUNT - 1, 8) - self.assertEqual( - math.comb(joint.REFERENCE_CCX_COUNT, 2) * two_rebase.BOUND, - 288, - ) - self.assertEqual(joint.REFERENCE_CCX_COUNT - 2, 7) - self.assertEqual(neighborhood.BOUND, 8) - self.assertEqual(triple_fusion.BOUND, 8) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_schema_harness.py b/src/point_add/memory/repro/test_schema_harness.py deleted file mode 100644 index ed5a9016..00000000 --- a/src/point_add/memory/repro/test_schema_harness.py +++ /dev/null @@ -1,240 +0,0 @@ -from __future__ import annotations - -import json -import tempfile -import unittest -from pathlib import Path - -import schema_harness as harness -import world_model as wm - - -HASH_A = "11" * 32 -HASH_B = "22" * 32 -HASH_C = "33" * 32 - - -def frontier_payload() -> dict[str, object]: - return { - "type": "frontier", - "iteration": 0, - "submission_id": "frontier", - "source_ref": "source", - "ops_sha256": HASH_A, - "canonical_ops_sha256": HASH_B, - "score": 20, - "qubits": 2, - "rounded_toffoli": 10, - "ceiling_score": 0, - "max_iterations": harness.MAX_ITERATIONS, - "instruments": { - "verifier_sha256": HASH_A, - "simulator_sha256": HASH_B, - "scorer_sha256": HASH_C, - "identity_sha256": "44" * 32, - }, - } - - -def prediction_payload( - iteration: int, - *, - niche: str = "H1-gcd-apply", - action_kind: wm.ActionKind = wm.ActionKind.NONCE_ONLY, -) -> dict[str, object]: - return { - "type": "prediction", - "iteration": iteration, - "niche": niche, - "action_kind": action_kind.value, - "candidate_id": f"candidate-{iteration}", - "parent_candidate_id": "frontier" if iteration == 1 else f"candidate-{iteration - 1}", - "parent_ops_sha256": HASH_A, - "mechanism": "characterization hypothesis", - "delta_qubits": 0, - "delta_toffoli_mean": -1.0, - "delta_toffoli_standard_deviation": 0.5, - "correctness_risk": "artifact reseed", - "full_verification_budget": 0, - "expected_invalidations": sorted( - dependency.value for dependency in wm.action_impact(action_kind).invalidated - ), - } - - -def observation_payload( - iteration: int, - *, - prediction_match: bool | None = True, - verdict: str = "pass", -) -> dict[str, object]: - return { - "type": "observation", - "iteration": iteration, - "observation_id": f"observation-{iteration}", - "stage": "proxy", - "evidence_kind": wm.EvidenceKind.LOW_SHOT_SCREEN.value, - "verdict": verdict, - "artifact_ops_sha256": f"{iteration:064x}", - "prediction_match": prediction_match, - "measurement": {"samples": 64}, - "conclusion": "recorded proxy outcome", - } - - -class SchemaHarnessLedgerTests(unittest.TestCase): - def test_hash_chain_and_iteration_contract_backtest_green(self) -> None: - with tempfile.TemporaryDirectory() as directory: - ledger = Path(directory) / "measurements.jsonl" - first = harness.append_payload( - ledger, frontier_payload(), recorded_at="2026-07-30T00:00:00Z" - ) - prediction = harness.append_payload( - ledger, - prediction_payload(1), - recorded_at="2026-07-30T00:01:00Z", - ) - observation = harness.append_payload( - ledger, - observation_payload(1), - recorded_at="2026-07-30T00:02:00Z", - ) - records = harness.load_ledger(ledger) - report = harness.backtest(records) - - self.assertEqual(first["previous_sha256"], harness.ZERO_HASH) - self.assertEqual(prediction["previous_sha256"], first["record_sha256"]) - self.assertEqual(observation["previous_sha256"], prediction["record_sha256"]) - self.assertEqual(report["verdict"], "green") - self.assertEqual(report["iterations_completed"], 1) - self.assertEqual(report["remaining_iterations"], 499) - - def test_prediction_rejects_unknown_niche_and_wrong_invalidation_map(self) -> None: - with tempfile.TemporaryDirectory() as directory: - ledger = Path(directory) / "measurements.jsonl" - harness.append_payload(ledger, frontier_payload()) - unknown = prediction_payload(1) - unknown["niche"] = "unknown" - with self.assertRaisesRegex(ValueError, "unknown niche"): - harness.append_payload(ledger, unknown) - - wrong = prediction_payload(1) - wrong["expected_invalidations"] = [] - with self.assertRaisesRegex(ValueError, "prediction invalidations"): - harness.append_payload(ledger, wrong) - - def test_measurement_only_prediction_allows_no_effect_but_no_claimed_delta(self) -> None: - with tempfile.TemporaryDirectory() as directory: - root = Path(directory) - ledger = root / "measurements.jsonl" - harness.append_payload(ledger, frontier_payload()) - measurement = prediction_payload(1, action_kind=wm.ActionKind.NO_EFFECT) - measurement["delta_toffoli_mean"] = 0.0 - harness.append_payload(ledger, measurement) - - invalid_ledger = root / "invalid.jsonl" - harness.append_payload(invalid_ledger, frontier_payload()) - invalid = prediction_payload(1, action_kind=wm.ActionKind.NO_EFFECT) - with self.assertRaisesRegex(ValueError, "measurement-only"): - harness.append_payload(invalid_ledger, invalid) - - def test_next_prediction_requires_observation_and_mismatch_reframe(self) -> None: - with tempfile.TemporaryDirectory() as directory: - ledger = Path(directory) / "measurements.jsonl" - harness.append_payload(ledger, frontier_payload()) - harness.append_payload(ledger, prediction_payload(1)) - with self.assertRaisesRegex(ValueError, "no observation"): - harness.append_payload(ledger, prediction_payload(2)) - - harness.append_payload( - ledger, - observation_payload(1, prediction_match=False, verdict="fail"), - ) - with self.assertRaisesRegex(ValueError, "requires a reframe"): - harness.append_payload(ledger, prediction_payload(2)) - - harness.append_payload( - ledger, - { - "type": "reframe", - "iteration": 1, - "claim": "the original mechanism was false", - "compression": "one endogenous artifact state explains the mismatch", - "forward_prediction": "the revised discriminator will separate the routes", - }, - ) - harness.append_payload(ledger, prediction_payload(2)) - self.assertEqual(harness.backtest(harness.load_ledger(ledger))["verdict"], "green") - - def test_tenth_iteration_requires_and_builds_content_addressed_checkpoint(self) -> None: - with tempfile.TemporaryDirectory() as directory: - root = Path(directory) - ledger = root / "measurements.jsonl" - harness.append_payload(ledger, frontier_payload()) - niches = tuple(harness.NICHES) - for iteration in range(1, 11): - harness.append_payload( - ledger, - prediction_payload(iteration, niche=niches[(iteration - 1) % len(niches)]), - ) - harness.append_payload(ledger, observation_payload(iteration)) - before = harness.backtest(harness.load_ledger(ledger)) - self.assertEqual(before["verdict"], "red") - self.assertIn("missing_checkpoint:10", before["failures"]) - - result = harness.checkpoint(ledger, root / "checkpoints", 10) - after = harness.backtest(harness.load_ledger(ledger)) - summary_path = Path(result["record"]["summary_path"]) - summary_bytes = summary_path.read_bytes().strip() - - self.assertEqual(after["verdict"], "green") - self.assertEqual(result["summary"]["iteration"], 10) - self.assertEqual( - result["record"]["summary_sha256"], - harness.hashlib.sha256(summary_bytes).hexdigest(), - ) - - def test_tampering_breaks_the_hash_chain(self) -> None: - with tempfile.TemporaryDirectory() as directory: - ledger = Path(directory) / "measurements.jsonl" - harness.append_payload(ledger, frontier_payload()) - row = json.loads(ledger.read_text(encoding="utf-8")) - row["score"] = 18 - ledger.write_text(json.dumps(row) + "\n", encoding="utf-8") - with self.assertRaisesRegex(ValueError, "record hash mismatch"): - harness.load_ledger(ledger) - - def test_portfolio_selects_the_least_sampled_niche(self) -> None: - records = ( - { - "type": "prediction", - "niche": "H0-zero-rounding", - "sequence": 1, - }, - { - "type": "prediction", - "niche": "H1-gcd-apply", - "sequence": 2, - }, - ) - selected = harness.select_niche(records) - self.assertEqual(selected["selected_niche"], "H2-square") - - def test_machine_portfolio_matches_harness_niches_and_score_boundaries(self) -> None: - portfolio_path = Path(__file__).resolve().parents[1] / "niche_portfolio.json" - portfolio = json.loads(portfolio_path.read_text(encoding="utf-8")) - niche_ids = {niche["id"] for niche in portfolio["niches"]} - self.assertEqual(niche_ids, set(harness.NICHES)) - self.assertTrue( - all(niche["stepping_stones"] for niche in portfolio["niches"]) - ) - frontier_score = portfolio["frontier"]["score"] - for boundary in portfolio["strict_improvement_thresholds"]: - qubits = boundary["qubits"] - maximum_toffoli = boundary["maximum_rounded_toffoli"] - self.assertLess(maximum_toffoli * qubits, frontier_score) - self.assertGreaterEqual((maximum_toffoli + 1) * qubits, frontier_score) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_verifier_ceiling.py b/src/point_add/memory/repro/test_verifier_ceiling.py deleted file mode 100644 index 34104a42..00000000 --- a/src/point_add/memory/repro/test_verifier_ceiling.py +++ /dev/null @@ -1,89 +0,0 @@ -from __future__ import annotations - -import unittest -from pathlib import Path - -import h0_classical_independence as independence - -import verifier_ceiling as ceiling -import zero_score_lookup as lookup - - -class VerifierCeilingTests(unittest.TestCase): - def test_pinned_contract_proves_zero_floor_but_current_witness_does_not_attain_it(self) -> None: - repo = Path(__file__).resolve().parents[4] - report = ceiling.verify_bounds(repo, repo / "score.json") - self.assertEqual(report["verdict"], "green") - self.assertEqual(report["absolute_score_lower_bound"], 0) - self.assertEqual(report["best_witness_upper_bound"], 1_490_805_286) - self.assertEqual(report["open_score_gap"], 1_490_805_286) - self.assertFalse(report["attained"]) - self.assertEqual(report["achievability_status"], "lower_bound_only") - self.assertTrue(all(check["green"] for check in report["checks"])) - - def test_zero_rounding_boundary_is_exact(self) -> None: - self.assertEqual(ceiling.ZERO_SCORE_MAX_TOTAL_TOFFOLI, 4_511) - self.assertEqual( - ceiling.score_from_totals(4_511, ceiling.FULL_VERIFICATION_SHOTS, 512), - 0, - ) - self.assertEqual( - ceiling.score_from_totals(4_512, ceiling.FULL_VERIFICATION_SHOTS, 512), - 512, - ) - - -class ZeroScoreLookupTests(unittest.TestCase): - @classmethod - def setUpClass(cls) -> None: - cls.powers = lookup._fixed_base_table() - - def test_fixed_base_arithmetic_matches_generator_group(self) -> None: - infinity, generator, doubled, wrapped = lookup._fixed_base_mul_many( - [0, 1, 2, lookup.ORDER], self.powers - ) - self.assertEqual(infinity, (0, 0)) - self.assertEqual(generator, (lookup.GX, lookup.GY)) - self.assertEqual(wrapped, (0, 0)) - self.assertEqual( - doubled, - ( - 0xC6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5, - 0x1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A, - ), - ) - - def test_frozen_lookup_is_exact_on_unique_classical_prefixes(self) -> None: - rows = [ - (1, 2, 0, 0, 5, 7), - (3, 4, 1, 0, 8, 9), - (10, 11, 2, 0, 12, 13), - ] - width = lookup._minimum_unique_prefix(rows) - table = lookup._lookup_rows(rows, width) - failures, hits = lookup._lookup_failures(rows, table, width) - self.assertEqual(width, 2) - self.assertEqual(failures, 0) - self.assertEqual(hits, len(rows)) - self.assertEqual(lookup._lookup_op_count(table, width), 1_061) - - -class ClassicalIndependenceProofTests(unittest.TestCase): - def test_pinned_transition_table_blocks_quantum_to_classical_extraction(self) -> None: - repo = Path(__file__).resolve().parents[4] - report = independence.verify(repo) - self.assertEqual(report["verdict"], "green") - self.assertEqual(report["transition_proof"]["operation_types_checked"], 18) - self.assertEqual(report["transition_proof"]["classical_writers_checked"], 4) - - def test_quantum_leaking_hmr_breaks_the_inductive_invariant(self) -> None: - report = independence.verify_independence(hmr_leaks_quantum=True) - self.assertEqual(report["verdict"], "red") - self.assertEqual( - report["failures"], - ["Hmr:classical_target_depends_on_initial_quantum"], - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_world_model.py b/src/point_add/memory/repro/test_world_model.py deleted file mode 100644 index 9082c216..00000000 --- a/src/point_add/memory/repro/test_world_model.py +++ /dev/null @@ -1,400 +0,0 @@ -from __future__ import annotations - -import tempfile -import unittest -from pathlib import Path - -import world_model as wm - - -HASH_B = "ab" * 32 -HASH_C = "cd" * 32 -INSTRUMENT_HASH = "ef" * 32 - - -def prediction(kind: wm.ActionKind, prediction_id: str) -> wm.Prediction: - return wm.Prediction( - prediction_id=prediction_id, - mechanism=f"characterize {kind.value}", - delta_qubits=0, - delta_toffoli_mean=0.0, - delta_toffoli_standard_deviation=0.0, - correctness_risk="characterization fixture", - full_verification_budget=1, - expected_invalidations=wm.action_impact(kind).invalidated, - ) - - -def candidate( - *, - candidate_id: str = "candidate", - parent_submission_id: str = wm.CURRENT_FRONTIER.submission_id, - ops_sha256: str | None = HASH_B, - source_ref: str = "working-tree:candidate", - qubits: int | None = 1_154, -) -> wm.Candidate: - return wm.Candidate( - candidate_id=candidate_id, - parent_submission_id=parent_submission_id, - source_ref=source_ref, - ops_sha256=ops_sha256, - nonce=7, - nonce_policy=wm.NoncePolicy.FIXED, - qubits=qubits, - ) - - -def verification( - *, - ops_sha256: str | None = HASH_B, - shots: int = wm.FULL_VERIFICATION_SHOTS, - qubits: int = 1_154, - rounded_toffoli: int = 1_291_858, - classical_failures: int = 0, - phase_garbage_batches: int = 0, - ancilla_garbage_batches: int = 0, - evidence_kind: wm.EvidenceKind = wm.EvidenceKind.TRUSTED_FULL, -) -> wm.Verification: - return wm.Verification( - evidence_kind=evidence_kind, - ops_sha256=ops_sha256, - shots=shots, - qubits=qubits, - total_toffoli=rounded_toffoli * shots, - average_toffoli=float(rounded_toffoli), - classical_failures=classical_failures, - phase_garbage_batches=phase_garbage_batches, - ancilla_garbage_batches=ancilla_garbage_batches, - ) - - -def promoted_row( - submission_id: str, - source_ref: str, - created_at: str, - qubits: int, - rounded_toffoli: int, -) -> dict[str, object]: - return { - "id": submission_id, - "status": "accepted", - "officialScore": qubits * rounded_toffoli, - "officialMetrics": {"qubits": qubits, "toffoli": rounded_toffoli}, - "improved": True, - "promotionStatus": "promoted", - "promotedSourceRef": source_ref, - "createdAt": created_at, - } - - -class WorldModelInvalidationTests(unittest.TestCase): - def test_nonce_only_invalidates_exact_result_but_preserves_function_proof(self) -> None: - impact = wm.action_impact(wm.ActionKind.NONCE_ONLY) - self.assertEqual( - impact.invalidated, - { - wm.Dependency.FIAT_SHAMIR_SEED, - wm.Dependency.TRUSTED_VERIFICATION, - wm.Dependency.EXECUTED_TOFFOLI_DRAW, - }, - ) - self.assertIn(wm.Dependency.CIRCUIT_FUNCTION_PROOF, impact.preserved) - - action = wm.Action( - kind=wm.ActionKind.NONCE_ONLY, - before_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - after_ops_sha256=HASH_B, - prediction=prediction(wm.ActionKind.NONCE_ONLY, "nonce-only"), - ) - self.assertTrue(wm.full_verification_gate(action).allowed) - - def test_geometry_removes_artifact_bound_calibrations(self) -> None: - instruments = wm.InstrumentSet( - verifier_sha256="01" * 32, - simulator_sha256="02" * 32, - scorer_sha256="03" * 32, - ) - calibrations = tuple( - wm.Calibration( - dependency=dependency, - artifact_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - instrument_sha256=INSTRUMENT_HASH, - evidence_id=f"baseline-{dependency.value}", - samples=1, - ) - for dependency in ( - wm.Dependency.STRIP_KEYS, - wm.Dependency.CAP_OPTIMUM, - wm.Dependency.COST_CALIBRATION, - wm.Dependency.CLEAN_DENSITY, - ) - ) + ( - wm.Calibration( - dependency=wm.Dependency.SCORER_CONTRACT, - artifact_ops_sha256=None, - instrument_sha256=INSTRUMENT_HASH, - evidence_id="exact-scorer", - samples=416, - ), - ) - state = wm.WorldState( - frontier=wm.CURRENT_FRONTIER, - instruments=instruments, - calibrations=calibrations, - ) - action = wm.Action( - kind=wm.ActionKind.GEOMETRY, - before_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - after_ops_sha256=HASH_B, - prediction=prediction(wm.ActionKind.GEOMETRY, "geometry"), - ) - transitioned = wm.apply_action(state, action, candidate()) - - self.assertIs(transitioned.status, wm.PlanStatus.ACTIVE) - self.assertEqual( - {calibration.dependency for calibration in transitioned.calibrations}, - {wm.Dependency.SCORER_CONTRACT}, - ) - for dependency in ( - wm.Dependency.STRIP_KEYS, - wm.Dependency.CAP_OPTIMUM, - wm.Dependency.COST_CALIBRATION, - wm.Dependency.CLEAN_DENSITY, - ): - self.assertIn(dependency, transitioned.invalidated) - self.assertNotIn(wm.Dependency.SCORER_CONTRACT, transitioned.invalidated) - - def test_byte_identical_action_blocks_expensive_verification(self) -> None: - action = wm.Action( - kind=wm.ActionKind.NO_EFFECT, - before_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - after_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - prediction=prediction(wm.ActionKind.NO_EFFECT, "no-effect"), - ) - decision = wm.full_verification_gate(action) - self.assertFalse(decision.allowed) - self.assertIn("byte_identical_no_effect", decision.reasons) - - def test_prediction_mismatch_aborts_transition(self) -> None: - instruments = wm.InstrumentSet( - verifier_sha256="01" * 32, - simulator_sha256="02" * 32, - scorer_sha256="03" * 32, - ) - wrong_prediction = wm.Prediction( - prediction_id="wrong-invalidation-map", - mechanism="claim a geometry change is nonce-only", - delta_qubits=-1, - delta_toffoli_mean=0.0, - delta_toffoli_standard_deviation=0.0, - correctness_risk="understated", - full_verification_budget=1, - expected_invalidations=wm.action_impact(wm.ActionKind.NONCE_ONLY).invalidated, - ) - action = wm.Action( - kind=wm.ActionKind.GEOMETRY, - before_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - after_ops_sha256=HASH_B, - prediction=wrong_prediction, - ) - transitioned = wm.apply_action( - wm.WorldState(wm.CURRENT_FRONTIER, instruments), - action, - candidate(), - ) - self.assertIs(transitioned.status, wm.PlanStatus.ABORTED) - self.assertIn("preregistered prediction", transitioned.abort_reason or "") - - -class PromotionGateTests(unittest.TestCase): - def test_exact_full_fresh_strict_beat_is_allowed(self) -> None: - decision = wm.promotion_gate(candidate(), verification(), wm.CURRENT_FRONTIER) - self.assertTrue(decision.allowed) - self.assertLess(decision.candidate_score or wm.CURRENT_FRONTIER.score, wm.CURRENT_FRONTIER.score) - - def test_missing_hash_full_pass_freshness_and_score_each_deny_promotion(self) -> None: - cases = { - "missing-hash": ( - candidate(ops_sha256=None), - verification(), - "missing_candidate_ops_hash", - ), - "short-run": ( - candidate(), - verification(shots=64), - "verification_not_9024_shots", - ), - "failed-run": ( - candidate(), - verification(classical_failures=1), - "trusted_correctness_failure", - ), - "stale-frontier": ( - candidate(parent_submission_id="older-frontier"), - verification(), - "stale_frontier_parent", - ), - "non-improving": ( - candidate(), - verification(rounded_toffoli=wm.CURRENT_FRONTIER.rounded_toffoli), - "score_does_not_strictly_improve_frontier", - ), - } - for name, (test_candidate, test_verification, expected_reason) in cases.items(): - with self.subTest(name=name): - decision = wm.promotion_gate( - test_candidate, - test_verification, - wm.CURRENT_FRONTIER, - ) - self.assertFalse(decision.allowed) - self.assertIn(expected_reason, decision.reasons) - - def test_q1145_local_miter_counterexample_remains_denied(self) -> None: - instruments = wm.InstrumentSet( - verifier_sha256="01" * 32, - simulator_sha256="02" * 32, - scorer_sha256="03" * 32, - ) - local_proof = wm.EvidenceEvent( - event_id="q1145-local-miter", - kind=wm.EvidenceKind.SCOPED_MACHINE_PROOF, - observed_at="2026-07-10T13:30:00Z", - statement="isolated comparator and carry miters passed", - source_ref="422f21d:q1145-v3", - artifact_ops_sha256=HASH_C, - ) - state = wm.append_evidence(wm.WorldState(wm.CURRENT_FRONTIER, instruments), local_proof) - self.assertEqual(len(state.timeline), 1) - - q1145_candidate = candidate( - candidate_id="q1145-v3", - ops_sha256=HASH_C, - source_ref="422f21d:q1145-v3", - qubits=1_145, - ) - trusted_failure = verification( - ops_sha256=HASH_C, - qubits=1_145, - rounded_toffoli=1_300_000, - classical_failures=28, - phase_garbage_batches=20, - ) - decision = wm.promotion_gate( - q1145_candidate, - trusted_failure, - wm.CURRENT_FRONTIER, - ) - self.assertFalse(decision.allowed) - self.assertIn("trusted_correctness_failure", decision.reasons) - - def test_current_frontier_is_a_fixture_not_a_new_promotion(self) -> None: - frontier_candidate = wm.Candidate( - candidate_id="cf5aa02-characterization", - parent_submission_id=wm.CURRENT_FRONTIER.submission_id, - source_ref=wm.CURRENT_FRONTIER.source_ref, - ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - canonical_ops_sha256=wm.CURRENT_FRONTIER.canonical_ops_sha256, - nonce_policy=wm.NoncePolicy.INHERITED, - qubits=wm.CURRENT_FRONTIER.qubits, - emitted_ops=wm.CURRENT_FRONTIER.emitted_ops, - ) - decision = wm.promotion_gate( - frontier_candidate, - wm.CURRENT_FRONTIER_VERIFICATION, - wm.CURRENT_FRONTIER, - ) - self.assertFalse(decision.allowed) - self.assertEqual(decision.candidate_score, wm.CURRENT_FRONTIER.score) - self.assertIn("current_frontier_is_characterization_only", decision.reasons) - self.assertIn("score_does_not_strictly_improve_frontier", decision.reasons) - - -class EvidenceTimelineTests(unittest.TestCase): - def test_jsonl_timeline_is_append_only_and_duplicate_safe(self) -> None: - first = wm.EvidenceEvent( - event_id="first", - kind=wm.EvidenceKind.NARRATIVE, - observed_at="2026-07-29T00:00:00Z", - statement="prediction registered", - source_ref=wm.CURRENT_FRONTIER.source_ref, - prediction_id="prediction-1", - ) - second = wm.EvidenceEvent( - event_id="second", - kind=wm.EvidenceKind.BYTE_IDENTICAL, - observed_at="2026-07-29T00:01:00Z", - statement="candidate emitted the baseline operation stream", - artifact_ops_sha256=wm.CURRENT_FRONTIER.ops_sha256, - prediction_id="prediction-1", - prediction_match=False, - ) - with tempfile.TemporaryDirectory() as directory: - path = Path(directory) / "measurements.jsonl" - wm.append_evidence_jsonl(path, first) - wm.append_evidence_jsonl(path, second) - self.assertEqual(wm.load_evidence_jsonl(path), (first, second)) - with self.assertRaises(ValueError): - wm.append_evidence_jsonl(path, first) - - instruments = wm.InstrumentSet( - verifier_sha256="01" * 32, - simulator_sha256="02" * 32, - scorer_sha256="03" * 32, - ) - state = wm.append_evidence(wm.WorldState(wm.CURRENT_FRONTIER, instruments), second) - self.assertIs(state.status, wm.PlanStatus.ABORTED) - self.assertIn("second", state.abort_reason or "") - - -class PromotedHistoryBacktestTests(unittest.TestCase): - def test_known_lineage_replays_in_strict_frontier_order(self) -> None: - rows = [ - promoted_row( - "30c8dede-fa09-466a-b19d-f4d14bc1ad2a", - "6f7c159b3cc0ce57e9561cf95b35117e0b012ef6", - "2026-05-30T07:41:45.340Z", - 2_715, - 3_960_753, - ), - promoted_row( - "middle", - "1111111111111111111111111111111111111111", - "2026-06-15T00:00:00.000Z", - 1_300, - 1_200_000, - ), - promoted_row( - wm.CURRENT_FRONTIER.submission_id, - wm.CURRENT_FRONTIER.source_ref, - "2026-07-28T22:13:48.764Z", - wm.CURRENT_FRONTIER.qubits, - wm.CURRENT_FRONTIER.rounded_toffoli, - ), - ] - report = wm.backtest_promoted_history( - {"submissions": rows}, - expected_count=3, - expected_frontier=wm.CURRENT_FRONTIER, - ) - self.assertEqual(report.verdict, "green") - self.assertEqual(report.promoted_rows_checked, 3) - self.assertEqual(report.first.score if report.first else None, 10_753_444_395) - self.assertEqual(report.last.score if report.last else None, wm.CURRENT_FRONTIER.score) - - def test_history_score_corruption_is_rejected(self) -> None: - row = promoted_row( - "corrupt", - "2222222222222222222222222222222222222222", - "2026-06-01T00:00:00.000Z", - 2_000, - 2_000_000, - ) - row["officialScore"] = 1 - report = wm.backtest_promoted_history([row], expected_count=1) - self.assertEqual(report.verdict, "red") - self.assertIn("score_mismatch", report.failures[0].reason) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_y1_composite_synth.py b/src/point_add/memory/repro/test_y1_composite_synth.py deleted file mode 100644 index c4aa3297..00000000 --- a/src/point_add/memory/repro/test_y1_composite_synth.py +++ /dev/null @@ -1,109 +0,0 @@ -from __future__ import annotations - -import itertools -import unittest -import subprocess -import tempfile -from pathlib import Path -from unittest import mock - -import y1_composite_synth as synth - - -def clauses_hold(clauses: list[list[int]], assignment: dict[int, int]) -> bool: - return all( - any( - assignment[abs(literal)] == int(literal > 0) - for literal in clause - ) - for clause in clauses - ) - - -class Y1CompositeSynthesisTests(unittest.TestCase): - def test_domain_has_every_restricted_input_once(self) -> None: - rows = synth.samples() - self.assertEqual(len(rows), 48) - self.assertEqual(len({row["inputs"] for row in rows}), 48) - for row in rows: - self.assertEqual(row["u"] & 1, 1) - self.assertEqual(row["v"] & 1, row["t"]) - self.assertTrue(not row["s"] or row["t"]) - - def test_reference_map_is_injective_on_restricted_domain(self) -> None: - rows = synth.samples() - self.assertEqual(len({row["outputs"] for row in rows}), len(rows)) - - def test_and_tseitin_encoding_has_exact_truth_table(self) -> None: - cnf = synth.Cnf() - left = cnf.variable() - right = cnf.variable() - output = cnf.variable() - cnf.equivalence_and(output, left, right) - for left_value, right_value, output_value in itertools.product(range(2), repeat=3): - observed = clauses_hold( - cnf.clauses, - {left: left_value, right: right_value, output: output_value}, - ) - self.assertEqual(observed, output_value == (left_value & right_value)) - - def test_xor_tseitin_encoding_has_exact_truth_table(self) -> None: - cnf = synth.Cnf() - left = cnf.variable() - right = cnf.variable() - output = cnf.variable() - cnf.equivalence_xor(output, left, right) - for left_value, right_value, output_value in itertools.product(range(2), repeat=3): - observed = clauses_hold( - cnf.clauses, - {left: left_value, right: right_value, output: output_value}, - ) - self.assertEqual(observed, output_value == (left_value ^ right_value)) - - def test_semantic_replay_rejects_zero_program(self) -> None: - program = { - "basis": ["1", *synth.INPUT_NAMES], - "gates": [], - "outputs": [[0] * (1 + len(synth.INPUT_NAMES)) for _ in synth.OUTPUT_NAMES], - } - report = synth.verify_program(program, synth.samples()) - self.assertEqual(report["verdict"], "red") - self.assertGreater(len(report["failures"]), 0) - - def test_resume_reuses_completed_solver_log(self) -> None: - with tempfile.TemporaryDirectory(dir=synth.REPO_ROOT) as directory: - root = Path(directory) - cnf_path = root / "case.cnf" - log_path = root / "case.log" - cnf_path.write_text("p cnf 0 0\n") - log_path.write_text("s UNSATISFIABLE\n") - with mock.patch.object(synth.subprocess, "run") as run: - report = synth.run_solver( - "solver", "/solver", 4, cnf_path, log_path, 1, True - ) - run.assert_not_called() - self.assertEqual(report["status"], "unsat") - self.assertTrue(report["cached"]) - self.assertTrue(report["returncode_expected"]) - - def test_timeout_is_recorded_instead_of_raising(self) -> None: - with tempfile.TemporaryDirectory(dir=synth.REPO_ROOT) as directory: - root = Path(directory) - cnf_path = root / "case.cnf" - log_path = root / "case.log" - cnf_path.write_text("p cnf 0 0\n") - timeout = subprocess.TimeoutExpired( - ["/solver", str(cnf_path)], 1, output=b"c partial solver log\n" - ) - with mock.patch.object(synth.subprocess, "run", side_effect=timeout): - report = synth.run_solver( - "solver", "/solver", 4, cnf_path, log_path, 1, False - ) - self.assertEqual(report["status"], "timeout") - self.assertFalse(report["cached"]) - self.assertFalse(report["returncode_expected"]) - self.assertEqual(log_path.read_text(), "c partial solver log\n") - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_y3_global_codec.py b/src/point_add/memory/repro/test_y3_global_codec.py deleted file mode 100644 index 24e89b48..00000000 --- a/src/point_add/memory/repro/test_y3_global_codec.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import annotations - -import unittest - -import y3_global_codec as codec - - -class Y3GlobalCodecTests(unittest.TestCase): - def test_production_tape_sizes(self) -> None: - iters, schedule = codec.parse_schedule() - self.assertEqual(len(schedule), iters) - self.assertEqual(codec.current_tape_bits(iters, tail4=False), 609) - self.assertEqual(codec.current_tape_bits(iters, tail4=True), 605) - - def test_terminal_reverse_tree_matches_exact_recurrence(self) -> None: - _, schedule = codec.parse_schedule() - rows = codec.enumerate_terminal_tree(schedule, state_cap=1_000) - self.assertEqual([row["reachable_states"] for row in rows[:4]], [3, 13, 63, 313]) - self.assertEqual( - [row["unrestricted_states"] for row in rows[:4]], - [(5**depth + 1) // 2 for depth in range(1, 5)], - ) - - def test_implemented_tail4_decoder_is_injective(self) -> None: - support = codec.decode_tail4_support() - self.assertEqual(len(support), 32) - self.assertTrue(all(len(pattern) == 4 for pattern in support)) - - def test_small_inputs_reach_the_pinned_terminal_state(self) -> None: - _, schedule = codec.parse_schedule() - for value in range(1, 65): - dialog, outcome = codec.run_walk(value, schedule) - self.assertEqual(outcome, "terminal") - self.assertEqual(len(dialog), len(schedule)) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/test_y5_normalizer_synth.py b/src/point_add/memory/repro/test_y5_normalizer_synth.py deleted file mode 100644 index 84086f33..00000000 --- a/src/point_add/memory/repro/test_y5_normalizer_synth.py +++ /dev/null @@ -1,82 +0,0 @@ -from __future__ import annotations - -import unittest - -import y5_normalizer_synth as synth - - -class Y5NormalizerSynthesisTests(unittest.TestCase): - def test_reference_is_the_expected_five_wire_permutation(self) -> None: - operations = synth.load_reference_ops() - table = synth.reference_table(operations) - self.assertEqual(len(operations), 104) - self.assertEqual(sum(kind == "CCX" for kind, _, _, _ in operations), 6) - self.assertEqual(len(set(table)), 32) - self.assertEqual(synth.anf_report(table)["output_degrees"], [3, 4, 3, 4, 4]) - - def test_reference_decomposes_into_six_generalized_shears(self) -> None: - operations = synth.load_reference_ops() - table = synth.reference_table(operations) - program = synth.reference_program(operations) - self.assertEqual(synth.verify_program(program, table)["verdict"], "green") - self.assertEqual(len(program["shears"]), 6) - compiled = synth.compile_program(program) - report = synth.verify_compiled(compiled, table) - self.assertEqual(report["verdict"], "green") - self.assertEqual(report["ccx"], 6) - - def test_generalized_shear_compiles_to_one_ccx_without_ancilla(self) -> None: - program = { - "width": 5, - "shears": [ - { - "enabled": 1, - "left": [1, 1, 0, 1, 0, 0], - "right": [0, 0, 1, 0, 1, 0], - "direction": [0, 0, 0, 0, 1], - } - ], - "outputs": [ - [0, 1, 0, 0, 0, 0], - [0, 0, 1, 0, 0, 0], - [0, 0, 0, 1, 0, 0], - [0, 0, 0, 0, 1, 0], - [0, 0, 0, 0, 0, 1], - ], - } - table = [synth.evaluate_program(program, value) for value in range(32)] - compiled = synth.compile_program(program) - report = synth.verify_compiled(compiled, table) - self.assertEqual(report["verdict"], "green") - self.assertEqual(report["ccx"], 1) - self.assertTrue(all(max(first, second, third) < 5 for _, first, second, third in compiled)) - - def test_at_most_five_encoding_covers_every_input(self) -> None: - cnf, variables, table = synth.build_problem(5) - self.assertEqual(len(table), 32) - self.assertEqual(len(variables.shears), 5) - self.assertEqual(len(variables.outputs), 5) - self.assertGreater(cnf.nvars, 0) - self.assertGreater(len(cnf.clauses), 0) - - def test_pair25_domain_maps_bijectively_to_canonical_codes(self) -> None: - table = synth.reference_table() - outputs = [table[value] for value in synth.PAIR25_INPUTS] - self.assertEqual(len(synth.PAIR25_INPUTS), 25) - self.assertEqual(len(set(synth.PAIR25_INPUTS)), 25) - self.assertEqual(sorted(outputs), list(range(25))) - _, variables, _ = synth.build_problem(5, list(synth.PAIR25_INPUTS)) - self.assertEqual(len(variables.shears), 5) - - def test_exact_encoding_enables_every_shear(self) -> None: - cnf, variables, _ = synth.build_problem( - 5, list(synth.PAIR25_INPUTS), exact=True - ) - unit_clauses = {clause[0] for clause in cnf.clauses if len(clause) == 1} - self.assertTrue( - all(shear.enabled in unit_clauses for shear in variables.shears) - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/src/point_add/memory/repro/verifier_ceiling.py b/src/point_add/memory/repro/verifier_ceiling.py deleted file mode 100755 index 37aec469..00000000 --- a/src/point_add/memory/repro/verifier_ceiling.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python3 -"""Machine-check the absolute score floor implied by the trusted verifier. - -The scorer has a numeric floor of zero. That floor becomes the exact attainable -minimum only when an official passing artifact scores zero; until then this -program reports an open lower/upper interval instead of inventing a circuit -lower bound that the verifier does not establish. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -from pathlib import Path -from typing import Any - -try: - from exact_scorer import score, score_from_totals - from world_model import CURRENT_FRONTIER, FULL_VERIFICATION_SHOTS -except ModuleNotFoundError: - from .exact_scorer import score, score_from_totals - from .world_model import CURRENT_FRONTIER, FULL_VERIFICATION_SHOTS - -PINNED_TRUSTED_SHA256 = { - "src/bin/eval_circuit.rs": "b35314bc47a5f8eecbf60459e6c76c9b43aa034eeb9b7ec3421655d74f9e890b", - "src/sim.rs": "f0c72f2a280cd68acee1dbf8282098f72d6b3bf4311e0abf96d122fe002256d7", - "src/circuit.rs": "ac2255f6bcb6895c9da2dfe21c3a051a0ef8fc4e0af9598634fec0035dbf35c6", - "src/point_add/memory/repro/exact_scorer.py": "03895414b4b5c8fc8951747593a260292e8ba75a46a298c097d24d781e6f0b8a", - "benchmark.sh": "1f963341bfbe3d052d904c7cc5ff9d67ca9df5c98ef623092635971e18f4f941", - "benchmark.json": "8e7cd12214e6ed93932ef1a01e89f92836905d4f1ebc708a217dd7fe7f87ba0c", -} -INTENDED_OUTPUT_QUBITS = 2 * 256 -ABSOLUTE_SCORE_FLOOR = 0 -ZERO_SCORE_MAX_TOTAL_TOFFOLI = (FULL_VERIFICATION_SHOTS - 1) // 2 - - -def _sha256(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - for chunk in iter(lambda: source.read(1024 * 1024), b""): - digest.update(chunk) - return digest.hexdigest() - - -def _check(name: str, condition: bool, detail: str) -> dict[str, Any]: - return {"name": name, "green": condition, "detail": detail} - - -def verify_bounds(repo: Path, score_path: Path | None = None) -> dict[str, Any]: - checks: list[dict[str, Any]] = [] - observed_hashes: dict[str, str] = {} - for relative, expected in PINNED_TRUSTED_SHA256.items(): - actual = _sha256(repo / relative) - observed_hashes[relative] = actual - checks.append( - _check( - f"trusted_hash:{relative}", - actual == expected, - f"expected={expected}:actual={actual}", - ) - ) - - score_at_zero = score_from_totals(0, FULL_VERIFICATION_SHOTS, INTENDED_OUTPUT_QUBITS) - score_at_zero_boundary = score_from_totals( - ZERO_SCORE_MAX_TOTAL_TOFFOLI, - FULL_VERIFICATION_SHOTS, - INTENDED_OUTPUT_QUBITS, - ) - score_after_boundary = score_from_totals( - ZERO_SCORE_MAX_TOTAL_TOFFOLI + 1, - FULL_VERIFICATION_SHOTS, - INTENDED_OUTPUT_QUBITS, - ) - checks.extend( - ( - _check( - "nonnegative_product_floor", - score_at_zero == ABSOLUTE_SCORE_FLOOR, - f"score(total=0)={score_at_zero}", - ), - _check( - "rounding_zero_boundary", - score_at_zero_boundary == ABSOLUTE_SCORE_FLOOR, - ( - f"total={ZERO_SCORE_MAX_TOTAL_TOFFOLI}:" - f"score={score_at_zero_boundary}" - ), - ), - _check( - "rounding_positive_after_boundary", - score_after_boundary == INTENDED_OUTPUT_QUBITS, - ( - f"total={ZERO_SCORE_MAX_TOTAL_TOFFOLI + 1}:" - f"score={score_after_boundary}" - ), - ), - _check( - "current_frontier_score", - score( - float(CURRENT_FRONTIER.rounded_toffoli), - CURRENT_FRONTIER.qubits, - ) - == CURRENT_FRONTIER.score, - f"score={CURRENT_FRONTIER.score}", - ), - ) - ) - - candidate_score: int | None = None - if score_path is not None and score_path.exists(): - score_payload = json.loads(score_path.read_text(encoding="utf-8")) - candidate_score = score_payload.get("score") - checks.append( - _check( - "candidate_score_is_nonnegative_integer", - type(candidate_score) is int and candidate_score >= 0, - f"candidate_score={candidate_score}", - ) - ) - - mechanics_green = all(check["green"] for check in checks) - attained = mechanics_green and candidate_score == ABSOLUTE_SCORE_FLOOR - upper_bound = ( - candidate_score - if type(candidate_score) is int and candidate_score >= 0 - else CURRENT_FRONTIER.score - ) - return { - "model": "eval_circuit.rs::write_score absolute floor", - "verdict": "green" if mechanics_green else "red", - "achievability_status": "attained_by_supplied_score" if attained else "lower_bound_only", - "absolute_score_lower_bound": ABSOLUTE_SCORE_FLOOR, - "best_witness_upper_bound": upper_bound, - "open_score_gap": upper_bound - ABSOLUTE_SCORE_FLOOR, - "full_verification_shots": FULL_VERIFICATION_SHOTS, - "zero_score_condition": { - "maximum_total_executed_toffoli": ZERO_SCORE_MAX_TOTAL_TOFFOLI, - "strict_average_upper_bound": 0.5, - }, - "intended_distinct_output_qubits": INTENDED_OUTPUT_QUBITS, - "attained": attained, - "trusted_sha256": observed_hashes, - "checks": checks, - "scope_warning": ( - "The trusted verifier supplies no nontrivial global Toffoli lower bound. " - "Zero is a proved scorer floor, not an attained circuit bound without an official witness." - ), - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--verify", action="store_true", help="exit nonzero if a pinned premise fails") - parser.add_argument("--json", action="store_true", help="emit compact JSON") - parser.add_argument( - "--score-json", - type=Path, - help="optional trusted score.json witness; defaults to the repository score.json", - ) - args = parser.parse_args() - repo = Path(__file__).resolve().parents[4] - score_path = args.score_json if args.score_json is not None else repo / "score.json" - report = verify_bounds(repo, score_path) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return int(args.verify and report["verdict"] != "green") - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/world_model.py b/src/point_add/memory/repro/world_model.py deleted file mode 100755 index ca5d6e1f..00000000 --- a/src/point_add/memory/repro/world_model.py +++ /dev/null @@ -1,965 +0,0 @@ -#!/usr/bin/env python3 -"""Executable evidence and invalidation model for the fixed ECDSA Fail benchmark. - -This module models what survives a circuit change and what evidence is required -before spending a trusted 9,024-shot verification. It does not simulate circuits -and cannot certify a novel candidate; only ``eval_circuit`` can do that. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import math -import os -from collections.abc import Mapping, Sequence -from dataclasses import dataclass, replace -from enum import Enum -from pathlib import Path -from typing import Any - -try: - from exact_scorer import score as exact_score - from exact_scorer import score_from_totals -except ModuleNotFoundError: - from .exact_scorer import score as exact_score - from .exact_scorer import score_from_totals - -FULL_VERIFICATION_SHOTS = 9_024 -_SHA256_HEX_LENGTH = 64 - - -def _require_nonempty(name: str, value: str) -> str: - if not isinstance(value, str) or not value.strip(): - raise ValueError(f"{name} must be a non-empty string") - return value - - -def _require_nonnegative_int(name: str, value: int) -> int: - if type(value) is not int: - raise TypeError(f"{name} must be an int") - if value < 0: - raise ValueError(f"{name} must be non-negative") - return value - - -def _require_sha256(name: str, value: str | None) -> str | None: - if value is None: - return None - if not isinstance(value, str) or len(value) != _SHA256_HEX_LENGTH: - raise ValueError(f"{name} must be a 64-character SHA-256 hex digest") - try: - bytes.fromhex(value) - except ValueError as error: - raise ValueError(f"{name} must be hexadecimal") from error - return value.lower() - - -def _require_finite_nonnegative(name: str, value: float) -> float: - if isinstance(value, bool) or not isinstance(value, (int, float)): - raise TypeError(f"{name} must be a real number") - result = float(value) - if not math.isfinite(result) or result < 0.0: - raise ValueError(f"{name} must be finite and non-negative") - return result - - -def _sha256_file(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - for chunk in iter(lambda: source.read(1024 * 1024), b""): - digest.update(chunk) - return digest.hexdigest() - - -class ActionKind(str, Enum): - NO_EFFECT = "no_effect" - NONCE_ONLY = "nonce_only" - EXACT_REWRITE = "exact_rewrite" - GEOMETRY = "geometry" - RISK_OR_STRIP_BUDGET = "risk_or_strip_budget" - REPRESENTATION = "representation" - PROMOTION = "promotion" - - -class Dependency(str, Enum): - FIAT_SHAMIR_SEED = "fiat_shamir_seed" - TRUSTED_VERIFICATION = "trusted_verification" - EXECUTED_TOFFOLI_DRAW = "executed_toffoli_draw" - CIRCUIT_FUNCTION_PROOF = "circuit_function_proof" - STRIP_KEYS = "strip_keys" - CAP_OPTIMUM = "cap_optimum" - COST_CALIBRATION = "cost_calibration" - CLEAN_DENSITY = "clean_density" - ABI_CONTRACT = "abi_contract" - SCORER_CONTRACT = "scorer_contract" - PROVED_INVARIANTS = "proved_invariants" - - -class EvidenceKind(str, Enum): - OFFICIAL_PROMOTED = "official_promoted_result" - TRUSTED_FULL = "trusted_9024_exact_artifact_result" - BYTE_IDENTICAL = "byte_identical_operation_stream" - SCOPED_MACHINE_PROOF = "scoped_machine_proof" - PAIRED_FIXED_RANDOMNESS = "paired_fixed_randomness_differential" - EXACT_CENSUS = "exact_stream_census" - INDEPENDENT_SEED_ESTIMATE = "independent_seed_statistical_estimate" - LOW_SHOT_SCREEN = "low_shot_screen" - NARRATIVE = "narrative_claim" - - -class NoncePolicy(str, Enum): - INHERITED = "inherited_fixed_artifact" - FIXED = "fixed_before_verification" - PREREGISTERED_BRANCH = "preregistered_budgeted_branch" - NOT_APPLICABLE = "not_applicable" - - -class PlanStatus(str, Enum): - ACTIVE = "active" - ABORTED = "aborted" - - -_EVIDENCE_STRENGTH = { - EvidenceKind.OFFICIAL_PROMOTED: 1, - EvidenceKind.TRUSTED_FULL: 2, - EvidenceKind.BYTE_IDENTICAL: 3, - EvidenceKind.SCOPED_MACHINE_PROOF: 3, - EvidenceKind.PAIRED_FIXED_RANDOMNESS: 4, - EvidenceKind.EXACT_CENSUS: 4, - EvidenceKind.INDEPENDENT_SEED_ESTIMATE: 5, - EvidenceKind.LOW_SHOT_SCREEN: 6, - EvidenceKind.NARRATIVE: 7, -} - - -def evidence_strength(kind: EvidenceKind) -> int: - """Return the evidence rank; lower is stronger.""" - return _EVIDENCE_STRENGTH[kind] - - -@dataclass(frozen=True, slots=True) -class Frontier: - submission_id: str - source_ref: str - score: int - qubits: int - rounded_toffoli: int - ops_sha256: str - canonical_ops_sha256: str - emitted_ops: int - - def __post_init__(self) -> None: - _require_nonempty("submission_id", self.submission_id) - _require_nonempty("source_ref", self.source_ref) - _require_nonnegative_int("score", self.score) - _require_nonnegative_int("qubits", self.qubits) - _require_nonnegative_int("rounded_toffoli", self.rounded_toffoli) - _require_nonnegative_int("emitted_ops", self.emitted_ops) - object.__setattr__(self, "ops_sha256", _require_sha256("ops_sha256", self.ops_sha256)) - object.__setattr__( - self, - "canonical_ops_sha256", - _require_sha256("canonical_ops_sha256", self.canonical_ops_sha256), - ) - expected = exact_score(float(self.rounded_toffoli), self.qubits) - if self.score != expected: - raise ValueError(f"frontier score {self.score} does not equal exact score {expected}") - - -@dataclass(frozen=True, slots=True) -class Candidate: - candidate_id: str - parent_submission_id: str - source_ref: str - ops_sha256: str | None - canonical_ops_sha256: str | None = None - nonce: int | None = None - nonce_policy: NoncePolicy = NoncePolicy.NOT_APPLICABLE - qubits: int | None = None - emitted_ops: int | None = None - - def __post_init__(self) -> None: - _require_nonempty("candidate_id", self.candidate_id) - _require_nonempty("parent_submission_id", self.parent_submission_id) - _require_nonempty("source_ref", self.source_ref) - object.__setattr__(self, "ops_sha256", _require_sha256("ops_sha256", self.ops_sha256)) - object.__setattr__( - self, - "canonical_ops_sha256", - _require_sha256("canonical_ops_sha256", self.canonical_ops_sha256), - ) - if self.nonce is not None: - _require_nonnegative_int("nonce", self.nonce) - if self.nonce >= 1 << 48: - raise ValueError("nonce must fit the benchmark's 48-bit tail field") - if self.qubits is not None: - _require_nonnegative_int("qubits", self.qubits) - if self.emitted_ops is not None: - _require_nonnegative_int("emitted_ops", self.emitted_ops) - - -@dataclass(frozen=True, slots=True) -class InstrumentSet: - verifier_sha256: str - simulator_sha256: str - scorer_sha256: str - - def __post_init__(self) -> None: - object.__setattr__( - self, "verifier_sha256", _require_sha256("verifier_sha256", self.verifier_sha256) - ) - object.__setattr__( - self, "simulator_sha256", _require_sha256("simulator_sha256", self.simulator_sha256) - ) - object.__setattr__(self, "scorer_sha256", _require_sha256("scorer_sha256", self.scorer_sha256)) - - @classmethod - def from_files(cls, verifier: Path, simulator: Path, scorer: Path) -> InstrumentSet: - return cls( - verifier_sha256=_sha256_file(verifier), - simulator_sha256=_sha256_file(simulator), - scorer_sha256=_sha256_file(scorer), - ) - - @property - def identity_sha256(self) -> str: - digest = hashlib.sha256() - for name, value in ( - ("verifier", self.verifier_sha256), - ("simulator", self.simulator_sha256), - ("scorer", self.scorer_sha256), - ): - digest.update(name.encode("ascii")) - digest.update(b"\0") - digest.update(value.encode("ascii")) - digest.update(b"\0") - return digest.hexdigest() - - -@dataclass(frozen=True, slots=True) -class Calibration: - dependency: Dependency - artifact_ops_sha256: str | None - instrument_sha256: str - evidence_id: str - samples: int = 0 - mean: float | None = None - standard_deviation: float | None = None - - def __post_init__(self) -> None: - object.__setattr__( - self, - "artifact_ops_sha256", - _require_sha256("artifact_ops_sha256", self.artifact_ops_sha256), - ) - object.__setattr__( - self, - "instrument_sha256", - _require_sha256("instrument_sha256", self.instrument_sha256), - ) - _require_nonempty("evidence_id", self.evidence_id) - _require_nonnegative_int("samples", self.samples) - if self.mean is not None: - object.__setattr__(self, "mean", _require_finite_nonnegative("mean", self.mean)) - if self.standard_deviation is not None: - object.__setattr__( - self, - "standard_deviation", - _require_finite_nonnegative("standard_deviation", self.standard_deviation), - ) - if self.dependency in { - Dependency.STRIP_KEYS, - Dependency.CAP_OPTIMUM, - Dependency.COST_CALIBRATION, - Dependency.CLEAN_DENSITY, - } and self.artifact_ops_sha256 is None: - raise ValueError(f"{self.dependency.value} calibration requires an artifact hash") - - -@dataclass(frozen=True, slots=True) -class Prediction: - prediction_id: str - mechanism: str - delta_qubits: int - delta_toffoli_mean: float - delta_toffoli_standard_deviation: float - correctness_risk: str - full_verification_budget: int - expected_invalidations: frozenset[Dependency] - - def __post_init__(self) -> None: - _require_nonempty("prediction_id", self.prediction_id) - _require_nonempty("mechanism", self.mechanism) - if type(self.delta_qubits) is not int: - raise TypeError("delta_qubits must be an int") - if isinstance(self.delta_toffoli_mean, bool) or not isinstance( - self.delta_toffoli_mean, (int, float) - ): - raise TypeError("delta_toffoli_mean must be a real number") - if not math.isfinite(float(self.delta_toffoli_mean)): - raise ValueError("delta_toffoli_mean must be finite") - object.__setattr__( - self, - "delta_toffoli_standard_deviation", - _require_finite_nonnegative( - "delta_toffoli_standard_deviation", self.delta_toffoli_standard_deviation - ), - ) - _require_nonempty("correctness_risk", self.correctness_risk) - _require_nonnegative_int("full_verification_budget", self.full_verification_budget) - invalidations = frozenset(self.expected_invalidations) - if any(not isinstance(dependency, Dependency) for dependency in invalidations): - raise TypeError("expected_invalidations must contain Dependency values") - object.__setattr__(self, "expected_invalidations", invalidations) - - -@dataclass(frozen=True, slots=True) -class Action: - kind: ActionKind - before_ops_sha256: str - after_ops_sha256: str | None - prediction: Prediction - supporting_evidence: frozenset[EvidenceKind] = frozenset() - - def __post_init__(self) -> None: - object.__setattr__( - self, - "before_ops_sha256", - _require_sha256("before_ops_sha256", self.before_ops_sha256), - ) - object.__setattr__( - self, - "after_ops_sha256", - _require_sha256("after_ops_sha256", self.after_ops_sha256), - ) - evidence = frozenset(self.supporting_evidence) - if any(not isinstance(kind, EvidenceKind) for kind in evidence): - raise TypeError("supporting_evidence must contain EvidenceKind values") - object.__setattr__(self, "supporting_evidence", evidence) - - -@dataclass(frozen=True, slots=True) -class ActionImpact: - invalidated: frozenset[Dependency] - preserved: frozenset[Dependency] - conditionally_reusable: frozenset[Dependency] - required_evidence: frozenset[EvidenceKind] - allow_full_verification: bool - - -_ALL_DEPENDENCIES = frozenset(Dependency) - - -def _make_impact( - invalidated: set[Dependency], - *, - conditional: set[Dependency] | None = None, - required_evidence: set[EvidenceKind] | None = None, - allow_full_verification: bool = True, -) -> ActionImpact: - conditional_set = frozenset(conditional or set()) - invalidated_set = frozenset(invalidated) - return ActionImpact( - invalidated=invalidated_set, - preserved=_ALL_DEPENDENCIES - invalidated_set - conditional_set, - conditionally_reusable=conditional_set, - required_evidence=frozenset(required_evidence or set()), - allow_full_verification=allow_full_verification, - ) - - -_BASE_EMPIRICAL_INVALIDATIONS = { - Dependency.FIAT_SHAMIR_SEED, - Dependency.TRUSTED_VERIFICATION, - Dependency.EXECUTED_TOFFOLI_DRAW, -} - -_ACTION_IMPACTS = { - ActionKind.NO_EFFECT: _make_impact(set(), allow_full_verification=False), - ActionKind.NONCE_ONLY: _make_impact(set(_BASE_EMPIRICAL_INVALIDATIONS)), - ActionKind.EXACT_REWRITE: _make_impact( - _BASE_EMPIRICAL_INVALIDATIONS - | { - Dependency.STRIP_KEYS, - Dependency.COST_CALIBRATION, - Dependency.CLEAN_DENSITY, - }, - conditional={Dependency.CIRCUIT_FUNCTION_PROOF}, - required_evidence={EvidenceKind.SCOPED_MACHINE_PROOF}, - ), - ActionKind.GEOMETRY: _make_impact( - _BASE_EMPIRICAL_INVALIDATIONS - | { - Dependency.CIRCUIT_FUNCTION_PROOF, - Dependency.STRIP_KEYS, - Dependency.CAP_OPTIMUM, - Dependency.COST_CALIBRATION, - Dependency.CLEAN_DENSITY, - } - ), - ActionKind.RISK_OR_STRIP_BUDGET: _make_impact( - _BASE_EMPIRICAL_INVALIDATIONS - | { - Dependency.CIRCUIT_FUNCTION_PROOF, - Dependency.STRIP_KEYS, - Dependency.COST_CALIBRATION, - Dependency.CLEAN_DENSITY, - }, - required_evidence={ - EvidenceKind.PAIRED_FIXED_RANDOMNESS, - EvidenceKind.EXACT_CENSUS, - }, - ), - ActionKind.REPRESENTATION: _make_impact( - _ALL_DEPENDENCIES - - { - Dependency.ABI_CONTRACT, - Dependency.SCORER_CONTRACT, - Dependency.PROVED_INVARIANTS, - } - ), - ActionKind.PROMOTION: _make_impact(set(), allow_full_verification=False), -} - - -def action_impact(kind: ActionKind) -> ActionImpact: - """Return the benchmark-specific dependency invalidation contract.""" - return _ACTION_IMPACTS[kind] - - -@dataclass(frozen=True, slots=True) -class EvidenceEvent: - event_id: str - kind: EvidenceKind - observed_at: str - statement: str - source_ref: str | None = None - artifact_ops_sha256: str | None = None - prediction_id: str | None = None - prediction_match: bool | None = None - - def __post_init__(self) -> None: - _require_nonempty("event_id", self.event_id) - _require_nonempty("observed_at", self.observed_at) - _require_nonempty("statement", self.statement) - if self.source_ref is not None: - _require_nonempty("source_ref", self.source_ref) - object.__setattr__( - self, - "artifact_ops_sha256", - _require_sha256("artifact_ops_sha256", self.artifact_ops_sha256), - ) - if self.source_ref is None and self.artifact_ops_sha256 is None: - raise ValueError("evidence must name a source ref or exact artifact hash") - if self.prediction_id is not None: - _require_nonempty("prediction_id", self.prediction_id) - if self.prediction_match is not None and type(self.prediction_match) is not bool: - raise TypeError("prediction_match must be a bool or None") - - def to_mapping(self) -> dict[str, Any]: - return { - "event_id": self.event_id, - "kind": self.kind.value, - "observed_at": self.observed_at, - "statement": self.statement, - "source_ref": self.source_ref, - "artifact_ops_sha256": self.artifact_ops_sha256, - "prediction_id": self.prediction_id, - "prediction_match": self.prediction_match, - } - - @classmethod - def from_mapping(cls, row: Mapping[str, Any]) -> EvidenceEvent: - return cls( - event_id=row["event_id"], - kind=EvidenceKind(row["kind"]), - observed_at=row["observed_at"], - statement=row["statement"], - source_ref=row.get("source_ref"), - artifact_ops_sha256=row.get("artifact_ops_sha256"), - prediction_id=row.get("prediction_id"), - prediction_match=row.get("prediction_match"), - ) - - -@dataclass(frozen=True, slots=True) -class WorldState: - frontier: Frontier - instruments: InstrumentSet - candidate: Candidate | None = None - calibrations: tuple[Calibration, ...] = () - timeline: tuple[EvidenceEvent, ...] = () - invalidated: frozenset[Dependency] = frozenset() - status: PlanStatus = PlanStatus.ACTIVE - abort_reason: str | None = None - - def __post_init__(self) -> None: - invalidated = frozenset(self.invalidated) - if any(not isinstance(dependency, Dependency) for dependency in invalidated): - raise TypeError("invalidated must contain Dependency values") - object.__setattr__(self, "invalidated", invalidated) - event_ids: set[str] = set() - for event in self.timeline: - if event.event_id in event_ids: - raise ValueError(f"duplicate evidence event_id: {event.event_id}") - event_ids.add(event.event_id) - if self.status is PlanStatus.ABORTED and not self.abort_reason: - raise ValueError("an aborted plan requires abort_reason") - - -@dataclass(frozen=True, slots=True) -class GateDecision: - allowed: bool - reasons: tuple[str, ...] - candidate_score: int | None = None - - -def append_evidence(state: WorldState, event: EvidenceEvent) -> WorldState: - """Append one immutable observation and abort on a prediction mismatch.""" - if any(existing.event_id == event.event_id for existing in state.timeline): - raise ValueError(f"duplicate evidence event_id: {event.event_id}") - status = state.status - reason = state.abort_reason - if event.prediction_match is False: - status = PlanStatus.ABORTED - reason = f"prediction mismatch at evidence event {event.event_id}" - return replace( - state, - timeline=state.timeline + (event,), - status=status, - abort_reason=reason, - ) - - -def load_evidence_jsonl(path: Path) -> tuple[EvidenceEvent, ...]: - """Load and validate an append-only evidence timeline.""" - events: list[EvidenceEvent] = [] - event_ids: set[str] = set() - with path.open(encoding="utf-8") as source: - for line_number, line in enumerate(source, start=1): - if not line.strip(): - continue - row = json.loads(line) - event = EvidenceEvent.from_mapping(row) - if event.event_id in event_ids: - raise ValueError(f"duplicate event_id {event.event_id} at line {line_number}") - event_ids.add(event.event_id) - events.append(event) - return tuple(events) - - -def append_evidence_jsonl(path: Path, event: EvidenceEvent) -> None: - """Append one event without rewriting prior reality rows.""" - if path.exists(): - if any(existing.event_id == event.event_id for existing in load_evidence_jsonl(path)): - raise ValueError(f"duplicate evidence event_id: {event.event_id}") - path.parent.mkdir(parents=True, exist_ok=True) - row = json.dumps(event.to_mapping(), sort_keys=True, separators=(",", ":")) - with path.open("a", encoding="utf-8") as destination: - destination.write(row) - destination.write("\n") - destination.flush() - os.fsync(destination.fileno()) - - -def register_calibration(state: WorldState, calibration: Calibration) -> WorldState: - """Replace one active calibration after anchoring it to the current artifact.""" - active_hash = state.candidate.ops_sha256 if state.candidate is not None else state.frontier.ops_sha256 - if calibration.artifact_ops_sha256 is not None and calibration.artifact_ops_sha256 != active_hash: - raise ValueError("calibration artifact does not match the active candidate") - retained = tuple( - existing for existing in state.calibrations if existing.dependency is not calibration.dependency - ) - return replace( - state, - calibrations=retained + (calibration,), - invalidated=state.invalidated - {calibration.dependency}, - ) - - -def full_verification_gate(action: Action) -> GateDecision: - """Decide whether an expensive trusted run is justified, not whether it will pass.""" - impact = action_impact(action.kind) - reasons: list[str] = [] - if not impact.allow_full_verification: - reasons.append(f"action_class_blocks_full_verification:{action.kind.value}") - if action.after_ops_sha256 is None: - reasons.append("missing_after_ops_hash") - elif action.after_ops_sha256 == action.before_ops_sha256: - reasons.append("byte_identical_no_effect") - if action.prediction.expected_invalidations != impact.invalidated: - reasons.append("prediction_invalidation_mismatch") - for missing in sorted( - impact.required_evidence - action.supporting_evidence, - key=lambda kind: kind.value, - ): - reasons.append(f"missing_discriminating_evidence:{missing.value}") - return GateDecision(allowed=not reasons, reasons=tuple(reasons)) - - -def apply_action(state: WorldState, action: Action, candidate: Candidate) -> WorldState: - """Apply one observed candidate transition and invalidate dependent beliefs.""" - active_hash = state.candidate.ops_sha256 if state.candidate is not None else state.frontier.ops_sha256 - if action.before_ops_sha256 != active_hash: - return replace( - state, - status=PlanStatus.ABORTED, - abort_reason="action parent hash does not match active artifact", - ) - if action.after_ops_sha256 is None or candidate.ops_sha256 != action.after_ops_sha256: - return replace( - state, - status=PlanStatus.ABORTED, - abort_reason="candidate hash does not match the observed action result", - ) - if action.after_ops_sha256 == action.before_ops_sha256: - return replace( - state, - status=PlanStatus.ABORTED, - abort_reason="byte-identical operation stream; deny expensive verification", - ) - impact = action_impact(action.kind) - if action.prediction.expected_invalidations != impact.invalidated: - return replace( - state, - status=PlanStatus.ABORTED, - abort_reason="observed action invalidations differ from preregistered prediction", - ) - retained_calibrations = tuple( - calibration - for calibration in state.calibrations - if calibration.dependency not in impact.invalidated - ) - return replace( - state, - candidate=candidate, - calibrations=retained_calibrations, - invalidated=state.invalidated | impact.invalidated, - status=PlanStatus.ACTIVE, - abort_reason=None, - ) - - -@dataclass(frozen=True, slots=True) -class Verification: - evidence_kind: EvidenceKind - ops_sha256: str | None - shots: int - qubits: int | None - total_toffoli: int | None - average_toffoli: float | None - classical_failures: int - phase_garbage_batches: int - ancilla_garbage_batches: int - - def __post_init__(self) -> None: - object.__setattr__(self, "ops_sha256", _require_sha256("ops_sha256", self.ops_sha256)) - _require_nonnegative_int("shots", self.shots) - if self.qubits is not None: - _require_nonnegative_int("qubits", self.qubits) - if self.total_toffoli is not None: - _require_nonnegative_int("total_toffoli", self.total_toffoli) - if self.average_toffoli is not None: - object.__setattr__( - self, - "average_toffoli", - _require_finite_nonnegative("average_toffoli", self.average_toffoli), - ) - _require_nonnegative_int("classical_failures", self.classical_failures) - _require_nonnegative_int("phase_garbage_batches", self.phase_garbage_batches) - _require_nonnegative_int("ancilla_garbage_batches", self.ancilla_garbage_batches) - if ( - self.total_toffoli is not None - and self.average_toffoli is not None - and self.shots > 0 - and self.qubits is not None - ): - from_total = score_from_totals(self.total_toffoli, self.shots, self.qubits) - from_average = exact_score(self.average_toffoli, self.qubits) - if from_total != from_average: - raise ValueError("total and average Toffoli imply different benchmark scores") - - @property - def has_zero_failures(self) -> bool: - return ( - self.classical_failures == 0 - and self.phase_garbage_batches == 0 - and self.ancilla_garbage_batches == 0 - ) - - @property - def candidate_score(self) -> int | None: - if self.qubits is None: - return None - if self.total_toffoli is not None and self.shots > 0: - return score_from_totals(self.total_toffoli, self.shots, self.qubits) - if self.average_toffoli is not None: - return exact_score(self.average_toffoli, self.qubits) - return None - - -def promotion_gate( - candidate: Candidate, - verification: Verification, - refreshed_frontier: Frontier, -) -> GateDecision: - """Require an exact passing artifact, a fresh parent, and a strict score beat.""" - reasons: list[str] = [] - if candidate.parent_submission_id != refreshed_frontier.submission_id: - reasons.append("stale_frontier_parent") - if candidate.ops_sha256 is None: - reasons.append("missing_candidate_ops_hash") - if verification.ops_sha256 is None: - reasons.append("missing_verification_ops_hash") - elif candidate.ops_sha256 is not None and verification.ops_sha256 != candidate.ops_sha256: - reasons.append("verification_artifact_mismatch") - if candidate.ops_sha256 == refreshed_frontier.ops_sha256: - reasons.append("current_frontier_is_characterization_only") - if verification.evidence_kind not in { - EvidenceKind.OFFICIAL_PROMOTED, - EvidenceKind.TRUSTED_FULL, - }: - reasons.append("verification_not_trusted_full_result") - if verification.shots != FULL_VERIFICATION_SHOTS: - reasons.append("verification_not_9024_shots") - if not verification.has_zero_failures: - reasons.append("trusted_correctness_failure") - if candidate.qubits is not None and verification.qubits != candidate.qubits: - reasons.append("verification_qubit_mismatch") - candidate_score = verification.candidate_score - if candidate_score is None: - reasons.append("missing_candidate_score") - elif candidate_score >= refreshed_frontier.score: - reasons.append("score_does_not_strictly_improve_frontier") - return GateDecision( - allowed=not reasons, - reasons=tuple(reasons), - candidate_score=candidate_score, - ) - - -@dataclass(frozen=True, slots=True) -class HistoryAnchor: - submission_id: str - source_ref: str - score: int - created_at: str - - def to_mapping(self) -> dict[str, Any]: - return { - "submission_id": self.submission_id, - "source_ref": self.source_ref, - "score": self.score, - "created_at": self.created_at, - } - - -@dataclass(frozen=True, slots=True) -class HistoryFailure: - source_index: int - submission_id: str - reason: str - - def to_mapping(self) -> dict[str, Any]: - return { - "source_index": self.source_index, - "submission_id": self.submission_id, - "reason": self.reason, - } - - -@dataclass(frozen=True, slots=True) -class HistoryReport: - promoted_rows_checked: int - first: HistoryAnchor | None - last: HistoryAnchor | None - failures: tuple[HistoryFailure, ...] - - @property - def verdict(self) -> str: - return "green" if not self.failures else "red" - - def to_mapping(self) -> dict[str, Any]: - return { - "model": "official promoted frontier replay", - "verdict": self.verdict, - "promoted_rows_checked": self.promoted_rows_checked, - "first": self.first.to_mapping() if self.first is not None else None, - "last": self.last.to_mapping() if self.last is not None else None, - "failures": [failure.to_mapping() for failure in self.failures], - } - - -def backtest_promoted_history( - payload: Mapping[str, Any] | Sequence[Mapping[str, Any]], - *, - expected_count: int | None = None, - expected_frontier: Frontier | None = None, -) -> HistoryReport: - """Replay promoted API rows in source order through the exact scorer.""" - if isinstance(payload, Mapping): - rows = payload.get("submissions") - else: - rows = payload - if not isinstance(rows, Sequence) or isinstance(rows, (str, bytes, bytearray)): - raise TypeError("submission payload must be a sequence or contain a submissions sequence") - - failures: list[HistoryFailure] = [] - checked = 0 - first: HistoryAnchor | None = None - last: HistoryAnchor | None = None - previous_score: int | None = None - previous_created_at: str | None = None - - for source_index, row in enumerate(rows): - if not isinstance(row, Mapping): - failures.append(HistoryFailure(source_index, "", "row_is_not_a_mapping")) - continue - if row.get("promotionStatus") != "promoted": - continue - checked += 1 - submission_id = str(row.get("id") or "") - try: - if row.get("status") != "accepted": - raise ValueError("promoted_row_status_is_not_accepted") - if row.get("improved") is not True: - raise ValueError("promoted_row_not_marked_improved") - source_ref = _require_nonempty("promotedSourceRef", row.get("promotedSourceRef")) - created_at = _require_nonempty("createdAt", row.get("createdAt")) - official_score = row.get("officialScore") - _require_nonnegative_int("officialScore", official_score) - metrics = row.get("officialMetrics") - if not isinstance(metrics, Mapping): - raise ValueError("officialMetrics_missing") - qubits = metrics.get("qubits") - rounded_toffoli = metrics.get("toffoli") - _require_nonnegative_int("officialMetrics.qubits", qubits) - _require_nonnegative_int("officialMetrics.toffoli", rounded_toffoli) - replayed_score = exact_score(float(rounded_toffoli), qubits) - if replayed_score != official_score: - raise ValueError( - f"score_mismatch:official={official_score}:replayed={replayed_score}" - ) - if previous_score is not None and official_score >= previous_score: - raise ValueError( - f"frontier_not_strictly_decreasing:previous={previous_score}:current={official_score}" - ) - if previous_created_at is not None and created_at <= previous_created_at: - raise ValueError( - f"timeline_not_strictly_increasing:previous={previous_created_at}:current={created_at}" - ) - anchor = HistoryAnchor( - submission_id=submission_id, - source_ref=source_ref, - score=official_score, - created_at=created_at, - ) - if first is None: - first = anchor - last = anchor - previous_score = official_score - previous_created_at = created_at - except (TypeError, ValueError) as error: - failures.append(HistoryFailure(source_index, submission_id, str(error))) - - if expected_count is not None: - _require_nonnegative_int("expected_count", expected_count) - if checked != expected_count: - failures.append( - HistoryFailure( - -1, - "", - f"promoted_count_mismatch:expected={expected_count}:actual={checked}", - ) - ) - if expected_frontier is not None: - if last is None: - failures.append(HistoryFailure(-1, "", "missing_promoted_frontier")) - else: - if last.submission_id != expected_frontier.submission_id: - failures.append( - HistoryFailure( - -1, - last.submission_id, - "latest_submission_does_not_match_expected_frontier", - ) - ) - if last.source_ref != expected_frontier.source_ref: - failures.append( - HistoryFailure( - -1, - last.submission_id, - "latest_source_does_not_match_expected_frontier", - ) - ) - if last.score != expected_frontier.score: - failures.append( - HistoryFailure( - -1, - last.submission_id, - "latest_score_does_not_match_expected_frontier", - ) - ) - return HistoryReport( - promoted_rows_checked=checked, - first=first, - last=last, - failures=tuple(failures), - ) - - -CURRENT_FRONTIER = Frontier( - submission_id="0c5b1b7b-561a-48a0-abc6-5fefaffdc0ad", - source_ref="cf5aa02147d4e1a698bbf84c10d33920d4356489", - score=1_490_805_286, - qubits=1_154, - rounded_toffoli=1_291_859, - ops_sha256="7333b19de3f3171a70d1b5132e867b7fb28cd5d77b34668175b391c420eed8c9", - canonical_ops_sha256="ec90afeadf8d294819e1e2128764c9da8d0742730c09d4ac1ae19d3b1a99dfba", - emitted_ops=9_062_420, -) - -CURRENT_FRONTIER_VERIFICATION = Verification( - evidence_kind=EvidenceKind.OFFICIAL_PROMOTED, - ops_sha256=CURRENT_FRONTIER.ops_sha256, - shots=FULL_VERIFICATION_SHOTS, - qubits=CURRENT_FRONTIER.qubits, - total_toffoli=11_657_738_337, - average_toffoli=1_291_859.302, - classical_failures=0, - phase_garbage_batches=0, - ancilla_garbage_batches=0, -) - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "--backtest-submissions", - type=Path, - required=True, - metavar="SUBMISSIONS_JSON", - help="JSON export containing the public submissions array", - ) - parser.add_argument("--expected-promoted", type=int) - parser.add_argument( - "--require-current-frontier", - action="store_true", - help="require the replay's last row to match the pinned frontier", - ) - args = parser.parse_args() - with args.backtest_submissions.open(encoding="utf-8") as source: - payload = json.load(source) - report = backtest_promoted_history( - payload, - expected_count=args.expected_promoted, - expected_frontier=CURRENT_FRONTIER if args.require_current_frontier else None, - ) - print(json.dumps(report.to_mapping(), sort_keys=True)) - return 0 if report.verdict == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y1_composite_synth.py b/src/point_add/memory/repro/y1_composite_synth.py deleted file mode 100755 index f0db0daf..00000000 --- a/src/point_add/memory/repro/y1_composite_synth.py +++ /dev/null @@ -1,537 +0,0 @@ -#!/usr/bin/env python3 -"""Exact small-width XOR-AND synthesis for the restricted GCD cswap/subtract map.""" - -from __future__ import annotations - -import argparse -import concurrent.futures -import hashlib -import json -import os -import shutil -import subprocess -import time -from dataclasses import dataclass -from pathlib import Path -from typing import Any - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y1-composite-synth-v1" -INPUT_NAMES = ("u0", "u1", "u2", "v0", "v1", "v2", "t", "s") -OUTPUT_NAMES = INPUT_NAMES -REFERENCE_AND_COUNT = 5 - - -def canonical_json(value: Any) -> bytes: - return json.dumps(value, sort_keys=True, separators=(",", ":")).encode() - - -def sha256_file(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - while chunk := source.read(1024 * 1024): - digest.update(chunk) - return digest.hexdigest() - - -def samples() -> list[dict[str, Any]]: - rows: list[dict[str, Any]] = [] - for u in range(8): - if u & 1 == 0: - continue - for v_high in range(4): - for t in range(2): - v = (v_high << 1) | t - for s in range(t + 1): - swapped_u, swapped_v = (v, u) if s else (u, v) - result_v = (swapped_v - swapped_u) & 7 if t else swapped_v - inputs = tuple( - [(u >> bit) & 1 for bit in range(3)] - + [(v >> bit) & 1 for bit in range(3)] - + [t, s] - ) - outputs = tuple( - [(swapped_u >> bit) & 1 for bit in range(3)] - + [(result_v >> bit) & 1 for bit in range(3)] - + [t, s] - ) - rows.append( - { - "u": u, - "v": v, - "t": t, - "s": s, - "inputs": inputs, - "outputs": outputs, - } - ) - return rows - - -class Cnf: - def __init__(self) -> None: - self.nvars = 0 - self.clauses: list[list[int]] = [] - - def variable(self) -> int: - self.nvars += 1 - return self.nvars - - def clause(self, *literals: int) -> None: - self.clauses.append(list(literals)) - - def equivalence_and(self, output: int, left: int, right: int) -> None: - self.clause(-left, -right, output) - self.clause(left, -output) - self.clause(right, -output) - - def equivalence_xor(self, output: int, left: int, right: int) -> None: - self.clause(-left, -right, -output) - self.clause(-left, right, output) - self.clause(left, -right, output) - self.clause(left, right, -output) - - def constrain_xor(self, terms: list[int], expected: int) -> None: - if not terms: - if expected: - self.clauses.append([]) - return - if len(terms) == 1: - self.clause(terms[0] if expected else -terms[0]) - return - accumulator = terms[0] - for term in terms[1:]: - output = self.variable() - self.equivalence_xor(output, accumulator, term) - accumulator = output - self.clause(accumulator if expected else -accumulator) - - def write(self, path: Path, comments: list[str]) -> None: - with path.open("w", encoding="ascii") as destination: - for comment in comments: - destination.write(f"c {comment}\n") - destination.write(f"p cnf {self.nvars} {len(self.clauses)}\n") - for clause in self.clauses: - destination.write(" ".join(str(value) for value in clause)) - destination.write(" 0\n") - - -@dataclass -class ProgramVariables: - gate_coefficients: list[tuple[list[int], list[int]]] - output_coefficients: list[list[int]] - - -def selected_signal_term( - cnf: Cnf, - coefficient: int, - signal: int, - dynamic: bool, -) -> int | None: - if not dynamic: - return coefficient if signal else None - product = cnf.variable() - cnf.equivalence_and(product, coefficient, signal) - return product - - -def affine_terms_for_sample( - cnf: Cnf, - coefficients: list[int], - primary_values: tuple[int, ...], - prior_gate_values: list[int], -) -> list[int]: - basis_values = (1,) + primary_values - terms: list[int] = [] - for coefficient, value in zip(coefficients[: len(basis_values)], basis_values): - term = selected_signal_term(cnf, coefficient, value, dynamic=False) - if term is not None: - terms.append(term) - for coefficient, value in zip(coefficients[len(basis_values) :], prior_gate_values): - term = selected_signal_term(cnf, coefficient, value, dynamic=True) - if term is not None: - terms.append(term) - return terms - - -def build_problem(and_gates: int) -> tuple[Cnf, ProgramVariables, list[dict[str, Any]]]: - domain = samples() - cnf = Cnf() - affine_basis = 1 + len(INPUT_NAMES) - gate_coefficients: list[tuple[list[int], list[int]]] = [] - gate_values: list[list[int]] = [] - - for gate_index in range(and_gates): - width = affine_basis + gate_index - left_coefficients = [cnf.variable() for _ in range(width)] - right_coefficients = [cnf.variable() for _ in range(width)] - gate_coefficients.append((left_coefficients, right_coefficients)) - values_for_gate: list[int] = [] - for sample_index, row in enumerate(domain): - prior = [gate_values[index][sample_index] for index in range(gate_index)] - left_value = cnf.variable() - right_value = cnf.variable() - cnf.constrain_xor( - affine_terms_for_sample( - cnf, left_coefficients, row["inputs"], prior - ) - + [left_value], - 0, - ) - cnf.constrain_xor( - affine_terms_for_sample( - cnf, right_coefficients, row["inputs"], prior - ) - + [right_value], - 0, - ) - gate_value = cnf.variable() - cnf.equivalence_and(gate_value, left_value, right_value) - values_for_gate.append(gate_value) - gate_values.append(values_for_gate) - - output_coefficients: list[list[int]] = [] - for output_index in range(len(OUTPUT_NAMES)): - coefficients = [cnf.variable() for _ in range(affine_basis + and_gates)] - output_coefficients.append(coefficients) - for sample_index, row in enumerate(domain): - prior = [gate_values[index][sample_index] for index in range(and_gates)] - cnf.constrain_xor( - affine_terms_for_sample(cnf, coefficients, row["inputs"], prior), - row["outputs"][output_index], - ) - - return cnf, ProgramVariables(gate_coefficients, output_coefficients), domain - - -def coefficient_bits(variable_ids: list[int], true_variables: set[int]) -> list[int]: - return [int(variable in true_variables) for variable in variable_ids] - - -def evaluate_affine(coefficients: list[int], signals: list[int]) -> int: - value = 0 - for coefficient, signal in zip(coefficients, signals): - value ^= coefficient & signal - return value - - -def decode_program( - variables: ProgramVariables, true_variables: set[int] -) -> dict[str, Any]: - gates = [ - { - "left": coefficient_bits(left, true_variables), - "right": coefficient_bits(right, true_variables), - } - for left, right in variables.gate_coefficients - ] - outputs = [ - coefficient_bits(coefficients, true_variables) - for coefficients in variables.output_coefficients - ] - return {"basis": ["1", *INPUT_NAMES], "gates": gates, "outputs": outputs} - - -def verify_program(program: dict[str, Any], domain: list[dict[str, Any]]) -> dict[str, Any]: - failures: list[dict[str, Any]] = [] - for sample_index, row in enumerate(domain): - signals = [1, *row["inputs"]] - for gate in program["gates"]: - left = evaluate_affine(gate["left"], signals) - right = evaluate_affine(gate["right"], signals) - signals.append(left & right) - observed = tuple( - evaluate_affine(coefficients, signals) - for coefficients in program["outputs"] - ) - if observed != row["outputs"]: - failures.append( - { - "sample_index": sample_index, - "inputs": row["inputs"], - "expected": row["outputs"], - "observed": observed, - } - ) - return { - "samples": len(domain), - "failures": failures, - "verdict": "green" if not failures else "red", - } - - -def solver_version(binary: str) -> str: - process = subprocess.run( - [binary, "--version"], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - timeout=10, - ) - return process.stdout.strip().splitlines()[0] if process.stdout.strip() else "unknown" - - -def parse_solver_output(text: str) -> tuple[str, set[int]]: - status = "unknown" - assignment: set[int] = set() - for line in text.splitlines(): - stripped = line.strip() - if stripped in {"s SATISFIABLE", "SATISFIABLE", "SAT"}: - status = "sat" - elif stripped in {"s UNSATISFIABLE", "UNSATISFIABLE", "UNSAT"}: - status = "unsat" - if stripped.startswith("v "): - for token in stripped[2:].split(): - value = int(token) - if value > 0: - assignment.add(value) - return status, assignment - - -def run_solver( - solver_name: str, - binary: str, - and_gates: int, - cnf_path: Path, - log_path: Path, - timeout_seconds: int, - resume: bool, -) -> dict[str, Any]: - if resume and log_path.is_file(): - cached_output = log_path.read_text(encoding="utf-8") - cached_status, cached_assignment = parse_solver_output(cached_output) - if cached_status in {"sat", "unsat"}: - cached_returncode = 10 if cached_status == "sat" else 20 - return { - "solver": solver_name, - "binary": binary, - "and_gates": and_gates, - "status": cached_status, - "returncode": cached_returncode, - "returncode_expected": True, - "elapsed_seconds": None, - "cached": True, - "log_path": str(log_path.relative_to(REPO_ROOT)), - "log_sha256": sha256_file(log_path), - "true_variables": sorted(cached_assignment), - } - - started = time.monotonic() - try: - process = subprocess.run( - [binary, str(cnf_path)], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - timeout=timeout_seconds, - ) - output = process.stdout - returncode: int | None = process.returncode - timed_out = False - except subprocess.TimeoutExpired as error: - partial = error.stdout or "" - if isinstance(partial, bytes): - partial = partial.decode(errors="replace") - output = partial - returncode = None - timed_out = True - elapsed = time.monotonic() - started - log_path.write_text(output, encoding="utf-8") - status, assignment = parse_solver_output(output) - if timed_out: - status = "timeout" - expected_returncode = 10 if status == "sat" else 20 if status == "unsat" else None - return { - "solver": solver_name, - "binary": binary, - "and_gates": and_gates, - "status": status, - "returncode": returncode, - "returncode_expected": returncode == expected_returncode and expected_returncode is not None, - "elapsed_seconds": elapsed, - "cached": False, - "log_path": str(log_path.relative_to(REPO_ROOT)), - "log_sha256": sha256_file(log_path), - "true_variables": sorted(assignment), - } - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - output.mkdir(parents=True, exist_ok=True) - cnf_dir = output / "cnf" - log_dir = output / "logs" - witness_dir = output / "witnesses" - cnf_dir.mkdir(exist_ok=True) - log_dir.mkdir(exist_ok=True) - witness_dir.mkdir(exist_ok=True) - - solvers: dict[str, str] = {} - for name in ("kissat", "cadical"): - binary = shutil.which(name) - if binary is None: - raise RuntimeError(f"required solver not found: {name}") - solvers[name] = binary - - problems: dict[int, tuple[Cnf, ProgramVariables, list[dict[str, Any]]]] = {} - cnf_metadata: list[dict[str, Any]] = [] - for and_gates in range(args.max_gates + 1): - problem = build_problem(and_gates) - problems[and_gates] = problem - cnf, _, domain = problem - path = cnf_dir / f"restricted-composite-k{and_gates}.cnf" - cnf.write( - path, - [ - "restricted n=3 GCD cswap then controlled-subtract XOR-AND synthesis", - f"and_gates={and_gates}", - f"samples={len(domain)}", - "domain: u odd; v0=t; s implies t", - ], - ) - cnf_metadata.append( - { - "and_gates": and_gates, - "path": str(path.relative_to(REPO_ROOT)), - "sha256": sha256_file(path), - "variables": cnf.nvars, - "clauses": len(cnf.clauses), - } - ) - - work: list[tuple[str, str, int, Path, Path, int, bool]] = [] - for and_gates in range(args.max_gates + 1): - cnf_path = cnf_dir / f"restricted-composite-k{and_gates}.cnf" - for solver_name, binary in solvers.items(): - work.append( - ( - solver_name, - binary, - and_gates, - cnf_path, - log_dir / f"{solver_name}-k{and_gates}.log", - args.timeout_seconds, - args.resume, - ) - ) - with concurrent.futures.ThreadPoolExecutor(max_workers=len(solvers)) as executor: - solver_runs = list(executor.map(lambda item: run_solver(*item), work)) - - errors: list[str] = [] - public_runs: list[dict[str, Any]] = [] - by_solver: dict[str, dict[int, str]] = {name: {} for name in solvers} - for solver_run in solver_runs: - assignment = set(solver_run.pop("true_variables")) - and_gates = solver_run["and_gates"] - solver_name = solver_run["solver"] - by_solver[solver_name][and_gates] = solver_run["status"] - verification: dict[str, Any] | None = None - witness_path: str | None = None - witness_sha256: str | None = None - if solver_run["status"] == "sat": - _, variables, domain = problems[and_gates] - program = decode_program(variables, assignment) - verification = verify_program(program, domain) - witness = { - "schema_version": 1, - "solver": solver_name, - "and_gates": and_gates, - "program": program, - "verification": verification, - } - path = witness_dir / f"{solver_name}-k{and_gates}.json" - path.write_text(json.dumps(witness, sort_keys=True, indent=2) + "\n") - witness_path = str(path.relative_to(REPO_ROOT)) - witness_sha256 = sha256_file(path) - if verification["verdict"] != "green": - errors.append(f"{solver_name} k={and_gates}: SAT model failed semantic replay") - if solver_run["status"] not in {"sat", "unsat"}: - errors.append(f"{solver_name} k={and_gates}: unknown solver status") - if not solver_run["returncode_expected"]: - errors.append(f"{solver_name} k={and_gates}: unexpected solver return code") - public_runs.append( - { - **solver_run, - "verification": verification, - "witness_path": witness_path, - "witness_sha256": witness_sha256, - } - ) - - for and_gates in range(args.max_gates + 1): - statuses = {by_solver[name].get(and_gates) for name in solvers} - if len(statuses) != 1: - errors.append(f"solver disagreement at k={and_gates}: {sorted(statuses)}") - minimal_by_solver: dict[str, int | None] = {} - for solver_name, statuses in by_solver.items(): - sat_counts = [count for count, status in statuses.items() if status == "sat"] - minimal = min(sat_counts) if sat_counts else None - minimal_by_solver[solver_name] = minimal - if statuses.get(args.max_gates) != "sat": - errors.append(f"{solver_name}: reference upper-bound k={args.max_gates} is not SAT") - if minimal is not None: - for count in range(minimal): - if statuses.get(count) != "unsat": - errors.append(f"{solver_name}: non-monotone status below minimal k={minimal}") - for count in range(minimal, args.max_gates + 1): - if statuses.get(count) != "sat": - errors.append(f"{solver_name}: non-monotone status above minimal k={minimal}") - minima = set(minimal_by_solver.values()) - if len(minima) != 1: - errors.append(f"solvers disagree on minimum: {minimal_by_solver}") - minimum = next(iter(minima)) if len(minima) == 1 else None - - report: dict[str, Any] = { - "schema_version": 1, - "scope": "Y1 restricted n=3 cswap plus controlled-subtract multiplicative complexity", - "prediction_id": args.prediction_id, - "domain": { - "width": 3, - "inputs": list(INPUT_NAMES), - "outputs": list(OUTPUT_NAMES), - "constraints": ["u is odd", "v0 equals t", "s implies t"], - "samples": len(samples()), - }, - "reference_and_count": REFERENCE_AND_COUNT, - "max_gates": args.max_gates, - "solver_versions": {name: solver_version(binary) for name, binary in solvers.items()}, - "cnfs": cnf_metadata, - "solver_runs": sorted(public_runs, key=lambda row: (row["and_gates"], row["solver"])), - "minimal_and_count_by_solver": minimal_by_solver, - "minimal_and_count": minimum, - "candidate_found": minimum is not None and minimum < REFERENCE_AND_COUNT, - "predicted_repeated_call_saving": ( - REFERENCE_AND_COUNT - minimum if minimum is not None else None - ), - "errors": errors, - "started_unix_ns": started_unix_ns, - "recorded_unix_ns": time.time_ns(), - "wall_seconds": time.monotonic() - started, - "verdict": "green" if not errors else "red", - } - report["report_sha256"] = hashlib.sha256(canonical_json(report)).hexdigest() - report_path = output / "report.json" - report_path.write_text(json.dumps(report, sort_keys=True, indent=2) + "\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--max-gates", type=int, default=REFERENCE_AND_COUNT) - parser.add_argument("--timeout-seconds", type=int, default=600) - parser.add_argument("--prediction-id", default="PRED-Y1-COMPOSITE-N3-V1") - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - if args.max_gates < REFERENCE_AND_COUNT: - parser.error(f"--max-gates must be at least {REFERENCE_AND_COUNT}") - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y3_global_codec.py b/src/point_add/memory/repro/y3_global_codec.py deleted file mode 100755 index b4f6d8d2..00000000 --- a/src/point_add/memory/repro/y3_global_codec.py +++ /dev/null @@ -1,310 +0,0 @@ -#!/usr/bin/env python3 -"""Measure whole-dialog rank bounds and the implemented terminal-suffix codec. - -The production walk is deterministic on an input field element. Therefore a -complete dialog uniquely identifies that input when the initial modulus is -fixed, giving an exact 256-bit whole-dialog rank bound. The executable probe -also enumerates the terminal reverse tree at every tractable depth and measures -the existing 32-word tail codec on a deterministic uniform field sample. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import math -import random -import re -import time -from pathlib import Path -from typing import Any - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -GCD_SOURCE = REPO_ROOT / "src/point_add/trailmix_ludicrous/gcd.rs" -CODEC_SOURCE = REPO_ROOT / "src/point_add/trailmix_ludicrous/codec.rs" -SCHEDULE_SOURCE = REPO_ROOT / "src/point_add/trailmix_ludicrous/schedule.rs" -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y3-global-codec-v1/report.json" -FIELD_MODULUS = (1 << 256) - (1 << 32) - 977 -FIXED_SEED = 0x5933C0DEC -FULL_VERIFIER_WALKS = 2 * 9_024 - - -def sha256_file(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - while chunk := source.read(1 << 20): - digest.update(chunk) - return digest.hexdigest() - - -def parse_schedule() -> tuple[int, list[int]]: - source = SCHEDULE_SOURCE.read_text(encoding="utf-8") - iters_match = re.search(r"pub const ITERS: usize = (\d+);", source) - schedule_match = re.search(r"SCHED_J2:.*?= &\[(.*?)\];", source, re.DOTALL) - if iters_match is None or schedule_match is None: - raise ValueError("could not parse production GCD schedule") - iters = int(iters_match.group(1)) - schedule = [int(value) for value in schedule_match.group(1).split(",") if value.strip()] - if len(schedule) != iters: - raise ValueError(f"ITERS={iters}, but SCHED_J2 has {len(schedule)} entries") - return iters, schedule - - -def parse_tail4_decoder() -> tuple[int, list[int], list[list[int]]]: - source = CODEC_SOURCE.read_text(encoding="utf-8") - bits_match = re.search(r"TAIL4_TOP32_CODE_BITS: usize = (\d+);", source) - decoder_match = re.search( - r"TAIL4_TOP32_DECODER_ANF: \[&\[u16\]; 12\] = \[(.*?)\n\];", - source, - re.DOTALL, - ) - reorder_match = re.search( - r"fn tail4_reordered_raw\(.*?\{.*?\[\s*(.*?)\s*\]\s*\}", - source, - re.DOTALL, - ) - if bits_match is None or decoder_match is None or reorder_match is None: - raise ValueError("could not parse the implemented tail4 decoder") - terms = [ - [int(value) for value in body.split(",") if value.strip()] - for body in re.findall(r"&\[(.*?)\]", decoder_match.group(1), re.DOTALL) - ] - reorder = [int(value) for value in re.findall(r"raw\[(\d+)\]", reorder_match.group(1))] - if len(terms) != 12 or len(reorder) != 12 or sorted(reorder) != list(range(12)): - raise ValueError("tail4 decoder shape changed") - return int(bits_match.group(1)), reorder, terms - - -def decode_tail4_support() -> set[tuple[tuple[int, int, int], ...]]: - code_bits, reorder, decoder_terms = parse_tail4_decoder() - support: set[tuple[tuple[int, int, int], ...]] = set() - for code in range(1 << code_bits): - reordered_raw = [] - for terms in decoder_terms: - value = 0 - for mask in terms: - if code & mask == mask: - value ^= 1 - reordered_raw.append(value) - raw = [0] * 12 - for wire_index, raw_index in enumerate(reorder): - raw[raw_index] = reordered_raw[wire_index] - support.add(tuple(tuple(raw[index : index + 3]) for index in range(0, 12, 3))) - if len(support) != 1 << code_bits: - raise ValueError("tail4 decoder is not injective on code words") - return support - - -def current_tape_bits(iters: int, tail4: bool) -> int: - tail_symbols = 5 if tail4 and iters >= 6 else 0 - codec_symbols = iters - 1 - tail_symbols - triples = iters // 3 - while 3 * triples > codec_symbols: - triples -= 1 - remainder = codec_symbols - 3 * triples - bits = 2 + 7 * triples - if remainder == 3 and triples > 0: - bits += 7 - else: - bits += 5 * (remainder // 2) + 3 * (remainder % 2) - if tail_symbols: - bits += 8 - return bits - - -def run_walk(value: int, schedule: list[int]) -> tuple[list[tuple[int, int, int]], str]: - u = FIELD_MODULUS - v = value - dialog: list[tuple[int, int, int]] = [] - for index, width in enumerate(schedule): - if u.bit_length() > width or v.bit_length() > width: - return dialog, "schedule-overflow" - if index == 0: - first_shift = int(v & 1 == 0) - if first_shift: - v >>= 1 - else: - v >>= 1 - second_shift = int(v & 1 == 0) - if second_shift: - v >>= 1 - subtract = v & 1 - swap = 0 - if subtract: - swap = int(index == 0 or v < u) - if swap: - u, v = v, u - v -= u - dialog.append((subtract, swap, second_shift)) - return dialog, "terminal" if (u, v) == (1, 0) else "nonterminal" - - -def reverse_predecessors( - state: tuple[int, int], width: int -) -> list[tuple[tuple[int, int], tuple[int, int, int]]]: - u, v = state - limit = 1 << width - candidates = [ - ((u, 4 * v), (0, 0, 1)), - ((u, 2 * (u + v)), (1, 0, 0)), - ((u, 4 * (u + v)), (1, 0, 1)), - ] - if v > 0: - candidates.extend( - [ - ((u + v, 2 * u), (1, 1, 0)), - ((u + v, 4 * u), (1, 1, 1)), - ] - ) - return [(prior, symbol) for prior, symbol in candidates if max(prior) < limit] - - -def enumerate_terminal_tree(schedule: list[int], state_cap: int) -> list[dict[str, Any]]: - states = {(1, 0)} - rows = [] - for depth, index in enumerate(range(len(schedule) - 1, 0, -1), start=1): - next_states = { - prior - for state in states - for prior, _ in reverse_predecessors(state, schedule[index]) - } - unrestricted = (pow(5, depth) + 1) // 2 - rows.append( - { - "depth": depth, - "start_iteration": index, - "width": schedule[index], - "reachable_states": len(next_states), - "unrestricted_states": unrestricted, - "rank_bits": max(1, (len(next_states) - 1).bit_length()), - } - ) - states = next_states - if len(states) > state_cap: - break - return rows - - -def wilson_interval(successes: int, trials: int) -> tuple[float, float]: - if trials == 0: - return 0.0, 1.0 - z = 1.959963984540054 - probability = successes / trials - denominator = 1 + z * z / trials - centre = (probability + z * z / (2 * trials)) / denominator - radius = z * math.sqrt(probability * (1 - probability) / trials + z * z / (4 * trials * trials)) / denominator - return max(0.0, centre - radius), min(1.0, centre + radius) - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started = time.monotonic() - iters, schedule = parse_schedule() - tail4_support = decode_tail4_support() - rng = random.Random(args.seed) - suffix_counts: dict[int, dict[tuple[tuple[int, int, int], ...], int]] = { - depth: {} for depth in range(1, args.max_suffix + 1) - } - outcomes = {"terminal": 0, "schedule-overflow": 0, "nonterminal": 0} - tail4_misses = 0 - for _ in range(args.samples): - dialog, outcome = run_walk(rng.randrange(1, FIELD_MODULUS), schedule) - outcomes[outcome] += 1 - if outcome != "terminal": - continue - for depth, counts in suffix_counts.items(): - suffix = tuple(dialog[-depth:]) - counts[suffix] = counts.get(suffix, 0) + 1 - if tuple(dialog[-4:]) not in tail4_support: - tail4_misses += 1 - - terminal_samples = outcomes["terminal"] - miss_lo, miss_hi = wilson_interval(tail4_misses, terminal_samples) - miss_rate = tail4_misses / terminal_samples if terminal_samples else 1.0 - clean_seed_estimate = (1.0 - miss_rate) ** FULL_VERIFIER_WALKS - current_bits = current_tape_bits(iters, tail4=False) - tail4_bits = current_tape_bits(iters, tail4=True) - full_dialog_count = FIELD_MODULUS - 1 - report = { - "schema_version": 1, - "verdict": "green" if current_bits - tail4_bits > 2 else "red", - "scope": "Y3 whole-dialog rank bound plus production terminal-suffix probe", - "production": { - "iters": iters, - "schedule_entries": len(schedule), - "schedule_tail": schedule[-12:], - "field_modulus_hex": hex(FIELD_MODULUS), - "current_tape_bits": current_bits, - "tail4_tape_bits": tail4_bits, - "tail4_qubits_saved": current_bits - tail4_bits, - }, - "exact_whole_dialog_bound": { - "domain_elements": full_dialog_count, - "rank_bits": (full_dialog_count - 1).bit_length(), - "current_representation_bits": current_bits, - "information_slack_qubits": current_bits - (full_dialog_count - 1).bit_length(), - "proof": "With fixed initial u=p, the deterministic dialog plus terminal state reverses to exactly one input x; all x in 1..p-1 therefore give p-1 distinct complete dialogs in the exact walk.", - "scope_warning": "The production circuit deliberately truncates a small-probability tail, so this is an exact-algorithm information bound, not a proof that a cheap streaming ranker exists for the approximate verifier circuit.", - }, - "terminal_tree": enumerate_terminal_tree(schedule, args.state_cap), - "monte_carlo": { - "seed": args.seed, - "requested_samples": args.samples, - "outcomes": outcomes, - "conditional_terminal_samples": terminal_samples, - "tail4_decoder_words": len(tail4_support), - "tail4_support_misses": tail4_misses, - "tail4_support_miss_rate": miss_rate, - "tail4_support_miss_rate_wilson95": [miss_lo, miss_hi], - "estimated_clean_seed_probability_for_18048_walks": clean_seed_estimate, - "suffixes": [ - { - "depth": depth, - "observed_distinct": len(counts), - "rank_bits": max(1, (len(counts) - 1).bit_length()), - "most_frequent": [ - {"symbols": [list(symbol) for symbol in suffix], "count": count} - for suffix, count in sorted(counts.items(), key=lambda item: (-item[1], item[0]))[:8] - ], - } - for depth, counts in suffix_counts.items() - ], - "evidence_class": "deterministic Monte Carlo; ranking evidence only", - }, - "rank_unrank_price": { - "naive_endpoint_construction": "Run the existing reverse walk to map tape->x, copy x, then regenerate the tape before the apply traversal.", - "naive_endpoint_peak_reduction_qubits": 0, - "naive_endpoint_reason": "The apply traversal still requires the full tape beside the 256-bit coefficient register; regenerating it restores the binding live set and adds two GCD traversals.", - "global_streaming_ranker_status": "unimplemented-and-unpriced", - "bounded_tail4_status": "implemented reversible 12-to-5 payload codec; build-time artifact measurement must price its actual gate delta", - "decision": "Measure tail4 as the only concrete >2-qubit Y3 operator; do not implement the 256-bit global rank bound without a streaming apply construction.", - }, - "source_hashes": { - str(path.relative_to(REPO_ROOT)): sha256_file(path) - for path in (GCD_SOURCE, CODEC_SOURCE, SCHEDULE_SOURCE) - }, - "wall_seconds": time.monotonic() - started, - } - args.output.parent.mkdir(parents=True, exist_ok=True) - args.output.write_text(json.dumps(report, sort_keys=True, indent=2) + "\n", encoding="utf-8") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--samples", type=int, default=1_000_000) - parser.add_argument("--seed", type=int, default=FIXED_SEED) - parser.add_argument("--max-suffix", type=int, default=12) - parser.add_argument("--state-cap", type=int, default=1_000_000) - args = parser.parse_args() - if args.samples <= 0 or args.max_suffix < 4 or args.state_cap <= 0: - parser.error("samples/state-cap must be positive and max-suffix must be at least four") - report = run(args) - print(json.dumps(report, sort_keys=True)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_joint_codec_neighborhood.py b/src/point_add/memory/repro/y5_joint_codec_neighborhood.py deleted file mode 100755 index b4c177af..00000000 --- a/src/point_add/memory/repro/y5_joint_codec_neighborhood.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python3 -"""Search exact-eight joint codecs obtained by fusing adjacent reference shears.""" - -from __future__ import annotations - -import argparse -import json -import shutil -import time -from pathlib import Path -from typing import Any - -import y5_joint_codec_synth as joint -from y1_composite_synth import canonical_json, sha256_file, solver_version - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-joint-codec-neighborhood-v1" -BOUND = 8 - - -def pin_shear(cnf: joint.synth.Cnf, encoded: joint.synth.ShearVariables, expected: dict[str, Any]) -> None: - cnf.clause(encoded.enabled) - for variable_ids, coefficients in ( - (encoded.left, expected["left"]), - (encoded.right, expected["right"]), - (encoded.direction, expected["direction"]), - ): - for variable, value in zip(variable_ids, coefficients): - cnf.clause(variable if value else -variable) - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - for directory in (output, output / "cnf", output / "logs", output / "witnesses"): - directory.mkdir(parents=True, exist_ok=True) - - joint_ops, table = joint.configure_problem() - reference = joint.synth.reference_program(joint_ops) - if len(reference["shears"]) != joint.REFERENCE_CCX_COUNT: - raise RuntimeError("reference shear count changed") - solvers = { - name: binary - for name in ("cryptominisat5", "kissat", "cadical") - if (binary := shutil.which(name)) is not None - } - - branches: list[dict[str, Any]] = [] - candidate: dict[str, Any] | None = None - consumed = 0.0 - failures: list[str] = [] - for boundary in range(joint.REFERENCE_CCX_COUNT - 1): - if consumed >= args.max_local_seconds: - break - cnf, variables, branch_table = joint.synth.build_problem( - BOUND, list(joint.PAIR_INPUTS), exact=True - ) - template: list[dict[str, Any] | None] = [ - *reference["shears"][:boundary], - None, - *reference["shears"][boundary + 2 :], - ] - if len(template) != BOUND: - raise AssertionError("adjacent-fusion template must have eight shears") - for encoded, expected in zip(variables.shears, template): - if expected is not None: - pin_shear(cnf, encoded, expected) - - cnf_path = output / "cnf" / f"fuse-{boundary}-{boundary + 1}.cnf" - cnf.write( - cnf_path, - [ - "exact-eight joint codec with one free shear replacing an adjacent reference pair", - f"removed_reference_shears={boundary},{boundary + 1}", - "full-rank affine output map constrained by symbolic right inverse", - ], - ) - branch_runs: list[dict[str, Any]] = [] - branch_failure: str | None = None - for solver_name in ("cryptominisat5", "kissat", "cadical"): - binary = solvers.get(solver_name) - if binary is None or consumed >= args.max_local_seconds: - continue - timeout = max( - 1, - min(args.timeout_seconds, int(args.max_local_seconds - consumed)), - ) - solver_run = joint.synth.run_solver( - solver_name, - binary, - BOUND, - cnf_path, - output / "logs" / f"{solver_name}-fuse-{boundary}-{boundary + 1}.log", - timeout, - args.resume, - ) - if solver_run["elapsed_seconds"] is not None: - consumed += float(solver_run["elapsed_seconds"]) - assignment = set(solver_run.pop("true_variables")) - branch_runs.append(solver_run) - if solver_run["status"] != "sat": - continue - try: - program = joint.synth.decode_program(variables, assignment) - symbolic, compiled, compiled_verification = joint.verify_candidate( - program, branch_table, BOUND - ) - except Exception as error: - branch_failure = f"SAT witness failed to compile: {error}" - failures.append(f"branch {boundary}: {branch_failure}") - break - if symbolic["verdict"] != "green" or compiled_verification["verdict"] != "green": - branch_failure = "SAT witness failed exhaustive restricted-domain replay" - failures.append(f"branch {boundary}: {branch_failure}") - break - candidate = { - "bound": BOUND, - "fused_reference_shears": [boundary, boundary + 1], - "solver": solver_name, - "program": program, - "symbolic_verification": symbolic, - "compiled_verification": compiled_verification, - "compiled_operations": compiled, - "compiled_operation_count": len(compiled), - "compiled_ccx": sum(kind == "CCX" for kind, _, _, _ in compiled), - "rust_table": joint.synth.rust_table(compiled), - } - witness_path = output / "witnesses" / f"fuse-{boundary}-{boundary + 1}.json" - witness_path.write_bytes(canonical_json(candidate) + b"\n") - candidate["witness_path"] = str(witness_path.relative_to(REPO_ROOT)) - candidate["witness_sha256"] = sha256_file(witness_path) - break - - branches.append( - { - "fused_reference_shears": [boundary, boundary + 1], - "status": "sat" - if candidate is not None - else "instrument-failure" - if branch_failure is not None - else "unsat" - if branch_runs and all(run["status"] == "unsat" for run in branch_runs) - else "unresolved", - "failure": branch_failure, - "cnf": { - "path": str(cnf_path.relative_to(REPO_ROOT)), - "sha256": sha256_file(cnf_path), - "variables": cnf.nvars, - "clauses": len(cnf.clauses), - }, - "solver_runs": branch_runs, - } - ) - if candidate is not None or branch_failure is not None: - break - - verdict = "red" if failures else "green" if candidate is not None else "yellow" - report: dict[str, Any] = { - "schema_version": 1, - "prediction_id": args.prediction_id, - "started_unix_ns": started_unix_ns, - "wall_seconds": time.monotonic() - started, - "local_cpu_seconds": consumed, - "verdict": verdict, - "failures": failures, - "search_class": "replace each adjacent pair of the nine-shear reference by one arbitrary generalized shear", - "branches": branches, - "candidate_found": candidate is not None, - "candidate": candidate, - "solver_versions": { - name: solver_version(binary) for name, binary in solvers.items() - }, - "source_path": str(Path(__file__).resolve().relative_to(REPO_ROOT)), - "source_sha256": sha256_file(Path(__file__).resolve()), - "completeness_contract": { - "all_eight_adjacent_pairs_attempted": len(branches) == 8, - "restricted_domain_forward_inverse_replay": candidate is not None, - "output_map_explicitly_invertible": True, - "timeouts_are_not_lower_bounds": True, - }, - } - (output / "report.json").write_bytes(canonical_json(report) + b"\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--prediction-id", default="PRED-Y5-JOINT-CODEC-SYNTH-V4") - parser.add_argument("--timeout-seconds", type=int, default=30) - parser.add_argument("--max-local-seconds", type=float, default=900.0) - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 1 if report["verdict"] == "red" else 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_joint_codec_stochastic.py b/src/point_add/memory/repro/y5_joint_codec_stochastic.py deleted file mode 100755 index 68e93929..00000000 --- a/src/point_add/memory/repro/y5_joint_codec_stochastic.py +++ /dev/null @@ -1,352 +0,0 @@ -#!/usr/bin/env python3 -"""Deterministic global search for an exact eight-shear joint codec. - -This is a witness finder, not an UNSAT procedure. It searches beyond the closed -one-shear neighborhoods by evolving arbitrary valid generalized shears. For each -nonlinear prefix it solves the best final affine output map exactly over the 25 -reachable pair states. -""" - -from __future__ import annotations - -import argparse -import hashlib -import itertools -import json -import random -from dataclasses import dataclass -from pathlib import Path -from typing import Any - -import y5_joint_codec_synth as joint -import y5_normalizer_synth as synth - -Shear = tuple[int, int, int, int] -Sequence = tuple[Shear, ...] - - -@dataclass(frozen=True) -class Evaluation: - errors: int - output_rank: int - outputs: tuple[int, ...] - - @property - def fitness(self) -> tuple[int, int, int]: - rank_deficit = synth.WIDTH - self.output_rank - return self.errors + 8 * rank_deficit, self.errors, rank_deficit - - -def _sha256(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - for chunk in iter(lambda: source.read(1024 * 1024), b""): - digest.update(chunk) - return digest.hexdigest() - - -def _columns(values: list[int], width: int) -> tuple[int, ...]: - return tuple( - sum(((value >> bit) & 1) << index for index, value in enumerate(values)) - for bit in range(width) - ) - - -def _affine_mask(coefficients: int, columns: tuple[int, ...], all_rows: int) -> int: - result = all_rows if coefficients & 1 else 0 - linear = coefficients >> 1 - while linear: - bit = (linear & -linear).bit_length() - 1 - result ^= columns[bit] - linear &= linear - 1 - return result - - -def apply_sequence(sequence: Sequence, initial: tuple[int, ...], all_rows: int) -> tuple[int, ...]: - columns = list(initial) - for left, right, direction, offsets in sequence: - left_mask = _affine_mask((left << 1) | (offsets & 1), tuple(columns), all_rows) - right_mask = _affine_mask((right << 1) | ((offsets >> 1) & 1), tuple(columns), all_rows) - toggle = left_mask & right_mask - changed = direction - while changed: - bit = (changed & -changed).bit_length() - 1 - columns[bit] ^= toggle - changed &= changed - 1 - return tuple(columns) - - -def _best_affine_options( - columns: tuple[int, ...], target: int, all_rows: int -) -> tuple[int, tuple[int, ...]]: - best = len(columns) * all_rows.bit_count() + 1 - options: list[int] = [] - for coefficients in range(1 << (len(columns) + 1)): - distance = (_affine_mask(coefficients, columns, all_rows) ^ target).bit_count() - if distance < best: - best = distance - options = [coefficients] - elif distance == best: - options.append(coefficients) - return best, tuple(options) - - -def _best_ranked_outputs(options: list[tuple[int, ...]], width: int) -> tuple[int, tuple[int, ...]]: - best_rank = -1 - best: tuple[int, ...] = () - combinations = 1 - for values in options: - combinations *= len(values) - if combinations <= 100_000: - candidates = itertools.product(*options) - else: - candidates = (tuple(values[0] for values in options),) - for candidate in candidates: - rank = synth.matrix_rank([coefficients >> 1 for coefficients in candidate], width) - if rank > best_rank: - best_rank = rank - best = tuple(candidate) - if rank == width: - break - return best_rank, best - - -def evaluate_sequence( - sequence: Sequence, - initial_columns: tuple[int, ...], - target_columns: tuple[int, ...], - all_rows: int, -) -> Evaluation: - columns = apply_sequence(sequence, initial_columns, all_rows) - errors = 0 - options: list[tuple[int, ...]] = [] - for target in target_columns: - distance, coefficients = _best_affine_options(columns, target, all_rows) - errors += distance - options.append(coefficients) - rank, outputs = _best_ranked_outputs(options, len(columns)) - return Evaluation(errors=errors, output_rank=rank, outputs=outputs) - - -def _directions(left: int, right: int, width: int) -> tuple[int, ...]: - return tuple( - direction - for direction in range(1, 1 << width) - if synth.dot(left, direction) == 0 and synth.dot(right, direction) == 0 - ) - - -def random_shear(rng: random.Random, width: int) -> Shear: - left = rng.randrange(1, 1 << width) - right = rng.randrange(1, 1 << width) - while right == left: - right = rng.randrange(1, 1 << width) - offsets = rng.randrange(4) - if left > right: - left, right = right, left - offsets = ((offsets & 1) << 1) | ((offsets >> 1) & 1) - direction = rng.choice(_directions(left, right, width)) - return left, right, direction, offsets - - -def mutate(sequence: Sequence, rng: random.Random, width: int) -> Sequence: - result = list(sequence) - index = rng.randrange(len(result)) - left, right, direction, offsets = result[index] - mode = rng.randrange(10) - if mode < 4: - result[index] = random_shear(rng, width) - elif mode < 6: - choices = [value for value in range(4) if value != offsets] - result[index] = left, right, direction, rng.choice(choices) - elif mode < 8: - directions = [value for value in _directions(left, right, width) if value != direction] - result[index] = left, right, rng.choice(directions), offsets - else: - result[index] = random_shear(rng, width) - other = rng.randrange(len(result)) - result[other] = random_shear(rng, width) - if rng.random() < 0.08: - first, second = rng.sample(range(len(result)), 2) - result[first], result[second] = result[second], result[first] - return tuple(result) - - -def _from_program(program: dict[str, Any]) -> Sequence: - sequence: list[Shear] = [] - for shear in program["shears"]: - left = synth.vector(shear["left"][1:]) - right = synth.vector(shear["right"][1:]) - offsets = shear["left"][0] | (shear["right"][0] << 1) - if left > right: - left, right = right, left - offsets = ((offsets & 1) << 1) | ((offsets >> 1) & 1) - sequence.append((left, right, synth.vector(shear["direction"]), offsets)) - return tuple(sequence) - - -def _to_program(sequence: Sequence, outputs: tuple[int, ...], width: int) -> dict[str, Any]: - return { - "width": width, - "shears": [ - { - "enabled": 1, - "left": [offsets & 1, *[(left >> bit) & 1 for bit in range(width)]], - "right": [ - (offsets >> 1) & 1, - *[(right >> bit) & 1 for bit in range(width)], - ], - "direction": [(direction >> bit) & 1 for bit in range(width)], - } - for left, right, direction, offsets in sequence - ], - "outputs": [ - [coefficients & 1, *[((coefficients >> 1) >> bit) & 1 for bit in range(width)]] - for coefficients in outputs - ], - } - - -def search( - *, - evaluation_budget: int, - seed: int, - population_size: int = 256, - elite_size: int = 32, -) -> dict[str, Any]: - if evaluation_budget < population_size: - raise ValueError("evaluation budget must cover the initial population") - rng = random.Random(seed) - joint_ops, table = joint.configure_problem() - width = joint.WIDTH - domain = list(joint.PAIR_INPUTS) - targets = [table[value] for value in domain] - initial_columns = _columns(domain, width) - target_columns = _columns(targets, width) - all_rows = (1 << len(domain)) - 1 - reference = _from_program(synth.reference_program(joint_ops)) - if len(reference) != joint.REFERENCE_CCX_COUNT: - raise AssertionError("reference shear count changed") - - seeds: list[Sequence] = [reference[:index] + reference[index + 1 :] for index in range(len(reference))] - while len(seeds) < population_size: - if len(seeds) < population_size * 3 // 4: - base = rng.choice(seeds[: len(reference)]) - for _ in range(1 + rng.randrange(4)): - base = mutate(base, rng, width) - seeds.append(base) - else: - seeds.append(tuple(random_shear(rng, width) for _ in range(8))) - - cache: dict[Sequence, Evaluation] = {} - evaluated = 0 - - def measured(sequence: Sequence) -> Evaluation: - nonlocal evaluated - if sequence not in cache: - cache[sequence] = evaluate_sequence( - sequence, initial_columns, target_columns, all_rows - ) - evaluated += 1 - return cache[sequence] - - population = list(dict.fromkeys(seeds)) - history: list[dict[str, int]] = [] - best_sequence = population[0] - best_evaluation = measured(best_sequence) - generation = 0 - while evaluated < evaluation_budget: - population.sort(key=lambda sequence: measured(sequence).fitness) - current = population[0] - current_evaluation = measured(current) - if current_evaluation.fitness < best_evaluation.fitness: - best_sequence = current - best_evaluation = current_evaluation - history.append( - { - "generation": generation, - "evaluations": evaluated, - "errors": best_evaluation.errors, - "output_rank": best_evaluation.output_rank, - } - ) - if best_evaluation.errors == 0 and best_evaluation.output_rank == width: - break - exploit = population[: elite_size // 2] - explore = rng.sample(population[elite_size // 2 :], elite_size - len(exploit)) - elites = [*exploit, *explore] - next_population: list[Sequence] = list(elites) - seen = set(next_population) - while len(next_population) < population_size and evaluated < evaluation_budget: - if rng.random() < 0.20: - first, second = rng.sample(elites, 2) - cut = rng.randrange(1, len(first)) - child = first[:cut] + second[cut:] - else: - child = mutate(rng.choice(elites), rng, width) - if child in seen: - continue - seen.add(child) - next_population.append(child) - measured(child) - population = next_population - generation += 1 - - population.sort(key=lambda sequence: measured(sequence).fitness) - if measured(population[0]).fitness < best_evaluation.fitness: - best_sequence = population[0] - best_evaluation = measured(best_sequence) - program = _to_program(best_sequence, best_evaluation.outputs, width) - witness: dict[str, Any] | None = None - if best_evaluation.errors == 0 and best_evaluation.output_rank == width: - symbolic, compiled, compiled_verification = joint.verify_candidate(program, table, 8) - if symbolic["verdict"] != "green" or compiled_verification["verdict"] != "green": - raise AssertionError("zero-residual stochastic witness failed exact replay") - witness = { - "program": program, - "compiled_operations": compiled, - "symbolic_verification": symbolic, - "compiled_verification": compiled_verification, - "rust_table": synth.rust_table(compiled), - } - return { - "schema_version": 1, - "scope": "unrestricted exact-eight generalized-shear witness search", - "status": "witness" if witness is not None else "unresolved", - "seed": seed, - "evaluation_budget": evaluation_budget, - "evaluations": evaluated, - "generations": generation, - "population_size": population_size, - "elite_size": elite_size, - "reference_shears": len(reference), - "best": { - "errors": best_evaluation.errors, - "output_rank": best_evaluation.output_rank, - "program": program, - }, - "improvement_history": history, - "witness": witness, - "warning": "No witness is not evidence of UNSAT.", - "source_hashes": { - "y5_joint_codec_synth.py": _sha256(Path(joint.__file__)), - "y5_normalizer_synth.py": _sha256(Path(synth.__file__)), - }, - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--evaluations", type=int, default=200_000) - parser.add_argument("--seed", type=int, default=0xECDA5A) - parser.add_argument("--output", type=Path, required=True) - args = parser.parse_args() - report = search(evaluation_budget=args.evaluations, seed=args.seed) - args.output.parent.mkdir(parents=True, exist_ok=True) - args.output.write_text(json.dumps(report, sort_keys=True, indent=2) + "\n", encoding="utf-8") - print(json.dumps({key: value for key, value in report.items() if key != "best"}, sort_keys=True)) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_joint_codec_synth.py b/src/point_add/memory/repro/y5_joint_codec_synth.py deleted file mode 100755 index d93ef2aa..00000000 --- a/src/point_add/memory/repro/y5_joint_codec_synth.py +++ /dev/null @@ -1,374 +0,0 @@ -#!/usr/bin/env python3 -"""Exact restricted-domain synthesis for the joint pair compressor and normalizer.""" - -from __future__ import annotations - -import argparse -import json -import shutil -import time -from pathlib import Path -from typing import Any - -import y5_normalizer_synth as synth -from y1_composite_synth import canonical_json, sha256_file, solver_version - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-joint-codec-synth-v1" -VALID_SYMBOLS = (0b001, 0b011, 0b100, 0b101, 0b111) -PAIR_INPUTS = tuple(first | (second << 3) for first in VALID_SYMBOLS for second in VALID_SYMBOLS) -WIDTH = 6 -REFERENCE_CCX_COUNT = 9 -COMPRESSOR_UNITARY: tuple[synth.Gate, ...] = ( - ("X", 3, 0, 0), - ("CX", 5, 1, 0), - ("CX", 4, 0, 0), - ("X", 2, 0, 0), - ("CCX", 1, 3, 5), - ("CX", 3, 5, 0), - ("CX", 3, 0, 0), - ("CX", 1, 5, 0), - ("CX", 5, 3, 0), - ("CCX", 5, 0, 4), - ("CCX", 3, 4, 5), -) - - -def configure_problem() -> tuple[list[synth.Gate], list[int]]: - normalizer_ops = synth.load_reference_ops() - joint_ops = [*COMPRESSOR_UNITARY, *normalizer_ops] - if sum(kind == "CCX" for kind, _, _, _ in joint_ops) != REFERENCE_CCX_COUNT: - raise RuntimeError("joint reference must contain exactly nine CCX gates") - - synth.WIDTH = WIDTH - synth.REFERENCE_CCX_COUNT = REFERENCE_CCX_COUNT - table = [synth.simulate_operations(value, joint_ops) for value in range(1 << WIDTH)] - synth.reference_table = lambda operations=None: table if operations is None else [ - synth.simulate_operations(value, operations) for value in range(1 << WIDTH) - ] - - pair_outputs = [table[value] for value in PAIR_INPUTS] - if len(set(PAIR_INPUTS)) != 25 or sorted(pair_outputs) != list(range(25)): - raise RuntimeError("joint pair25 mapping must be a bijection onto canonical values 0..24") - return joint_ops, table - - -def pin_program(cnf: synth.Cnf, variables: synth.SynthesisVariables, program: dict[str, Any]) -> None: - if len(variables.shears) != len(program["shears"]): - raise ValueError("program shear count does not match CNF") - for encoded, expected in zip(variables.shears, program["shears"]): - cnf.clause(encoded.enabled if expected["enabled"] else -encoded.enabled) - for variable_ids, coefficients in ( - (encoded.left, expected["left"]), - (encoded.right, expected["right"]), - (encoded.direction, expected["direction"]), - ): - for variable, value in zip(variable_ids, coefficients): - cnf.clause(variable if value else -variable) - for variable_ids, coefficients in zip(variables.outputs, program["outputs"]): - for variable, value in zip(variable_ids, coefficients): - cnf.clause(variable if value else -variable) - - -def public_solver_run(run: dict[str, Any]) -> dict[str, Any]: - return {key: value for key, value in run.items() if key != "true_variables"} - - -def build_cnf( - bound: int, - output: Path, - pinned_program: dict[str, Any] | None = None, -) -> tuple[synth.Cnf, synth.SynthesisVariables, list[int], Path]: - cnf, variables, table = synth.build_problem(bound, list(PAIR_INPUTS), exact=True) - if pinned_program is not None: - pin_program(cnf, variables, pinned_program) - suffix = "-pinned" if pinned_program is not None else "" - path = output / "cnf" / f"joint-codec-exact-{bound}{suffix}.cnf" - cnf.write( - path, - [ - "six-wire pair compressor plus NORMALIZER_OPS restricted-domain synthesis", - f"exact_ccx={bound}; valid_inputs=25; invalid_inputs_unbound=39", - "full-rank affine output map constrained by a symbolic right inverse", - "enabled generalized shear x <- x + c*(a.x+a0)*(b.x+b0)", - ], - ) - return cnf, variables, table, path - - -def verify_candidate( - program: dict[str, Any], table: list[int], bound: int -) -> tuple[dict[str, Any], list[synth.Gate], dict[str, Any]]: - symbolic = synth.verify_program(program, table, list(PAIR_INPUTS)) - compiled = synth.compile_program(program) - compiled_verification = synth.verify_compiled(compiled, table, list(PAIR_INPUTS)) - compiled_ccx = sum(kind == "CCX" for kind, _, _, _ in compiled) - if compiled_ccx != bound: - compiled_verification = { - **compiled_verification, - "verdict": "red", - "failures": [ - *compiled_verification["failures"], - {"kind": "ccx-count", "expected": bound, "observed": compiled_ccx}, - ], - } - return symbolic, compiled, compiled_verification - - -def run_pinned_reference( - output: Path, - solvers: dict[str, str], - program: dict[str, Any], -) -> tuple[dict[str, Any], float]: - cnf, _, _, path = build_cnf(REFERENCE_CCX_COUNT, output, program) - runs: list[dict[str, Any]] = [] - elapsed_total = 0.0 - for solver_name in ("kissat", "cadical"): - binary = solvers.get(solver_name) - if binary is None: - continue - run = synth.run_solver( - solver_name, - binary, - REFERENCE_CCX_COUNT, - path, - output / "logs" / f"{solver_name}-reference-pinned.log", - 120, - False, - ) - elapsed_total += float(run["elapsed_seconds"]) - runs.append(public_solver_run(run)) - failures = [ - f"{run['solver']} pinned reference status {run['status']}" - for run in runs - if run["status"] != "sat" - ] - if not runs: - failures.append("neither Kissat nor CaDiCaL is available for the pinned reference") - return { - "verdict": "green" if not failures else "red", - "failures": failures, - "cnf": { - "path": str(path.relative_to(REPO_ROOT)), - "sha256": sha256_file(path), - "variables": cnf.nvars, - "clauses": len(cnf.clauses), - }, - "solver_runs": runs, - }, elapsed_total - - -def search_bound( - bound: int, - output: Path, - solvers: dict[str, str], - timeout_seconds: int, - remaining_seconds: float, - resume: bool, -) -> tuple[dict[str, Any], dict[str, Any] | None, float]: - cnf, variables, table, path = build_cnf(bound, output) - runs: list[dict[str, Any]] = [] - candidate: dict[str, Any] | None = None - consumed = 0.0 - failures: list[str] = [] - - for solver_name in ("cryptominisat5", "kissat", "cadical"): - binary = solvers.get(solver_name) - if binary is None or remaining_seconds - consumed <= 0: - continue - run_timeout = max(1, min(timeout_seconds, int(remaining_seconds - consumed))) - run = synth.run_solver( - solver_name, - binary, - bound, - path, - output / "logs" / f"{solver_name}-exact-{bound}.log", - run_timeout, - resume, - ) - consumed += float(run["elapsed_seconds"]) - assignment = set(run.pop("true_variables")) - runs.append(run) - if run["status"] != "sat": - continue - - try: - program = synth.decode_program(variables, assignment) - symbolic, compiled, compiled_verification = verify_candidate(program, table, bound) - except Exception as error: - failures.append(f"{solver_name} SAT witness failed to compile: {error}") - break - if symbolic["verdict"] != "green" or compiled_verification["verdict"] != "green": - failures.append(f"{solver_name} SAT witness failed exhaustive restricted-domain replay") - break - - candidate = { - "bound": bound, - "solver": solver_name, - "program": program, - "symbolic_verification": symbolic, - "compiled_verification": compiled_verification, - "compiled_operations": compiled, - "compiled_operation_count": len(compiled), - "compiled_ccx": sum(kind == "CCX" for kind, _, _, _ in compiled), - "rust_table": synth.rust_table(compiled), - } - witness_path = output / "witnesses" / f"joint-codec-exact-{bound}.json" - witness_path.write_bytes(canonical_json(candidate) + b"\n") - candidate["witness_path"] = str(witness_path.relative_to(REPO_ROOT)) - candidate["witness_sha256"] = sha256_file(witness_path) - break - - statuses = {run["solver"]: run["status"] for run in runs} - if candidate is not None: - status = "sat" - elif failures: - status = "instrument-failure" - elif runs and all(value == "unsat" for value in statuses.values()): - status = "unsat" - else: - status = "unresolved" - return { - "bound": bound, - "status": status, - "failures": failures, - "cnf": { - "path": str(path.relative_to(REPO_ROOT)), - "sha256": sha256_file(path), - "variables": cnf.nvars, - "clauses": len(cnf.clauses), - }, - "solver_runs": runs, - }, candidate, consumed - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - for directory in (output, output / "cnf", output / "logs", output / "witnesses"): - directory.mkdir(parents=True, exist_ok=True) - - joint_ops, table = configure_problem() - reference_program = synth.reference_program(joint_ops) - symbolic_reference = synth.verify_program(reference_program, table, list(range(1 << WIDTH))) - compiled_reference = synth.compile_program(reference_program) - compiled_reference_verification = synth.verify_compiled( - compiled_reference, table, list(range(1 << WIDTH)) - ) - reference_failures: list[str] = [] - if symbolic_reference["verdict"] != "green": - reference_failures.append("symbolic nine-CCX reference failed all-state replay") - if compiled_reference_verification["verdict"] != "green": - reference_failures.append("compiled nine-CCX reference failed all-state forward/inverse replay") - if sum(kind == "CCX" for kind, _, _, _ in compiled_reference) != REFERENCE_CCX_COUNT: - reference_failures.append("compiled reference CCX count changed") - - solvers = { - name: binary - for name in ("kissat", "cadical", "cryptominisat5") - if (binary := shutil.which(name)) is not None - } - pinned_reference, pinned_elapsed = run_pinned_reference(output, solvers, reference_program) - if pinned_reference["verdict"] != "green": - reference_failures.extend(pinned_reference["failures"]) - - searches: list[dict[str, Any]] = [] - best_candidate: dict[str, Any] | None = None - consumed = pinned_elapsed - if not reference_failures: - search8, candidate8, elapsed8 = search_bound( - 8, - output, - solvers, - args.timeout_seconds, - max(0.0, args.max_local_seconds - consumed), - args.resume, - ) - searches.append(search8) - consumed += elapsed8 - best_candidate = candidate8 - if candidate8 is not None and consumed < args.max_local_seconds: - search7, candidate7, elapsed7 = search_bound( - 7, - output, - solvers, - args.timeout_seconds, - args.max_local_seconds - consumed, - args.resume, - ) - searches.append(search7) - consumed += elapsed7 - if candidate7 is not None: - best_candidate = candidate7 - - failures = [*reference_failures] - failures.extend(failure for search in searches for failure in search["failures"]) - if failures: - verdict = "red" - elif best_candidate is not None: - verdict = "green" - else: - verdict = "yellow" - - report: dict[str, Any] = { - "schema_version": 1, - "prediction_id": args.prediction_id, - "started_unix_ns": started_unix_ns, - "wall_seconds": time.monotonic() - started, - "local_cpu_seconds": consumed, - "verdict": verdict, - "failures": failures, - "domain": { - "width": WIDTH, - "inputs": list(PAIR_INPUTS), - "input_count": len(PAIR_INPUTS), - "invalid_inputs_unbound": (1 << WIDTH) - len(PAIR_INPUTS), - "outputs": [table[value] for value in PAIR_INPUTS], - "outputs_clear_wire_5": all(table[value] < 1 << 5 for value in PAIR_INPUTS), - }, - "reference": { - "ccx": REFERENCE_CCX_COUNT, - "operation_count": len(joint_ops), - "symbolic_verification": symbolic_reference, - "compiled_operation_count": len(compiled_reference), - "compiled_verification": compiled_reference_verification, - "pinned_invertibility_cnf": pinned_reference, - }, - "searches": searches, - "candidate_found": best_candidate is not None, - "candidate": best_candidate, - "solver_versions": { - name: solver_version(binary) for name, binary in solvers.items() - }, - "source_path": str(Path(__file__).resolve().relative_to(REPO_ROOT)), - "source_sha256": sha256_file(Path(__file__).resolve()), - "completeness_contract": { - "reference_all_64_forward_inverse": symbolic_reference["verdict"] == "green" - and compiled_reference_verification["verdict"] == "green", - "output_map_explicitly_invertible": pinned_reference["verdict"] == "green", - "restricted_domain_forward_inverse_replay": best_candidate is not None, - "timeouts_are_not_lower_bounds": True, - }, - } - report_path = output / "report.json" - report_path.write_bytes(canonical_json(report) + b"\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--prediction-id", default="PRED-Y5-JOINT-CODEC-SYNTH-V3") - parser.add_argument("--timeout-seconds", type=int, default=600) - parser.add_argument("--max-local-seconds", type=float, default=7200.0) - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 1 if report["verdict"] == "red" else 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_joint_codec_triple_fusion.py b/src/point_add/memory/repro/y5_joint_codec_triple_fusion.py deleted file mode 100755 index cc268ebb..00000000 --- a/src/point_add/memory/repro/y5_joint_codec_triple_fusion.py +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/env python3 -"""Search exact-eight joint codecs by replacing each reference triple with two shears.""" - -from __future__ import annotations - -import argparse -import json -import shutil -import time -from pathlib import Path -from typing import Any - -import y5_joint_codec_synth as joint -from y1_composite_synth import canonical_json, sha256_file, solver_version - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-joint-codec-triple-fusion-v1" -BOUND = 8 - - -def pin_shear(cnf: joint.synth.Cnf, encoded: joint.synth.ShearVariables, expected: dict[str, Any]) -> None: - cnf.clause(encoded.enabled) - for variable_ids, coefficients in ( - (encoded.left, expected["left"]), - (encoded.right, expected["right"]), - (encoded.direction, expected["direction"]), - ): - for variable, value in zip(variable_ids, coefficients): - cnf.clause(variable if value else -variable) - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - for directory in (output, output / "cnf", output / "logs", output / "witnesses"): - directory.mkdir(parents=True, exist_ok=True) - - joint_ops, _ = joint.configure_problem() - reference = joint.synth.reference_program(joint_ops) - solvers = { - name: binary - for name in ("cryptominisat5", "kissat", "cadical") - if (binary := shutil.which(name)) is not None - } - branches: list[dict[str, Any]] = [] - candidate: dict[str, Any] | None = None - failures: list[str] = [] - consumed = 0.0 - - for start_index in range(joint.REFERENCE_CCX_COUNT - 2): - if consumed >= args.max_local_seconds: - break - template: list[dict[str, Any] | None] = [ - *reference["shears"][:start_index], - None, - None, - *reference["shears"][start_index + 3 :], - ] - cnf, variables, table = joint.synth.build_problem( - BOUND, list(joint.PAIR_INPUTS), exact=True - ) - for encoded, expected in zip(variables.shears, template): - if expected is not None: - pin_shear(cnf, encoded, expected) - branch_id = f"fuse-{start_index}-{start_index + 1}-{start_index + 2}" - cnf_path = output / "cnf" / f"{branch_id}.cnf" - cnf.write( - cnf_path, - [ - "exact-eight joint codec with two free shears replacing three adjacent reference shears", - f"removed_reference_shears={start_index},{start_index + 1},{start_index + 2}", - "full-rank affine output map constrained by symbolic right inverse", - ], - ) - solver_runs: list[dict[str, Any]] = [] - branch_failure: str | None = None - for solver_name in ("cryptominisat5", "kissat", "cadical"): - binary = solvers.get(solver_name) - if binary is None or consumed >= args.max_local_seconds: - continue - timeout = max( - 1, - min(args.timeout_seconds, int(args.max_local_seconds - consumed)), - ) - solver_run = joint.synth.run_solver( - solver_name, - binary, - BOUND, - cnf_path, - output / "logs" / f"{solver_name}-{branch_id}.log", - timeout, - args.resume, - ) - if solver_run["elapsed_seconds"] is not None: - consumed += float(solver_run["elapsed_seconds"]) - assignment = set(solver_run.pop("true_variables")) - solver_runs.append(solver_run) - if solver_run["status"] != "sat": - continue - try: - program = joint.synth.decode_program(variables, assignment) - symbolic, compiled, compiled_verification = joint.verify_candidate( - program, table, BOUND - ) - except Exception as error: - branch_failure = f"SAT witness failed to compile: {error}" - else: - if symbolic["verdict"] != "green" or compiled_verification["verdict"] != "green": - branch_failure = "SAT witness failed exhaustive restricted-domain replay" - else: - candidate = { - "bound": BOUND, - "replaced_reference_shears": [ - start_index, - start_index + 1, - start_index + 2, - ], - "solver": solver_name, - "program": program, - "symbolic_verification": symbolic, - "compiled_verification": compiled_verification, - "compiled_operations": compiled, - "compiled_operation_count": len(compiled), - "compiled_ccx": sum( - kind == "CCX" for kind, _, _, _ in compiled - ), - "rust_table": joint.synth.rust_table(compiled), - } - witness_path = output / "witnesses" / f"{branch_id}.json" - witness_path.write_bytes(canonical_json(candidate) + b"\n") - candidate["witness_path"] = str(witness_path.relative_to(REPO_ROOT)) - candidate["witness_sha256"] = sha256_file(witness_path) - break - if branch_failure is not None: - failures.append(f"{branch_id}: {branch_failure}") - statuses = {run["solver"]: run["status"] for run in solver_runs} - branches.append( - { - "id": branch_id, - "replaced_reference_shears": [ - start_index, - start_index + 1, - start_index + 2, - ], - "status": "instrument-failure" - if branch_failure is not None - else "sat" - if candidate is not None - else "unsat" - if solver_runs and all(status == "unsat" for status in statuses.values()) - else "unresolved", - "failure": branch_failure, - "cnf_path": str(cnf_path.relative_to(REPO_ROOT)), - "cnf_sha256": sha256_file(cnf_path), - "cnf_variables": cnf.nvars, - "cnf_clauses": len(cnf.clauses), - "solver_runs": solver_runs, - } - ) - if candidate is not None or branch_failure is not None: - break - - verdict = "red" if failures else "green" if candidate is not None else "yellow" - report: dict[str, Any] = { - "schema_version": 1, - "prediction_id": args.prediction_id, - "started_unix_ns": started_unix_ns, - "wall_seconds": time.monotonic() - started, - "local_cpu_seconds": consumed, - "verdict": verdict, - "failures": failures, - "search_class": "replace each contiguous three-shear block of the nine-shear reference by two arbitrary generalized shears", - "expected_branches": 7, - "branches_run": len(branches), - "branches": branches, - "candidate_found": candidate is not None, - "candidate": candidate, - "solver_versions": { - name: solver_version(binary) for name, binary in solvers.items() - }, - "source_path": str(Path(__file__).resolve().relative_to(REPO_ROOT)), - "source_sha256": sha256_file(Path(__file__).resolve()), - "completeness_contract": { - "all_seven_triples_attempted": len(branches) == 7, - "restricted_domain_forward_inverse_replay": candidate is not None, - "output_map_explicitly_invertible": True, - "timeouts_are_not_lower_bounds": True, - }, - } - (output / "report.json").write_bytes(canonical_json(report) + b"\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--prediction-id", default="PRED-Y5-JOINT-CODEC-SYNTH-V4") - parser.add_argument("--timeout-seconds", type=int, default=60) - parser.add_argument("--max-local-seconds", type=float, default=1200.0) - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 1 if report["verdict"] == "red" else 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_joint_codec_two_rebase.py b/src/point_add/memory/repro/y5_joint_codec_two_rebase.py deleted file mode 100755 index 5b9d241e..00000000 --- a/src/point_add/memory/repro/y5_joint_codec_two_rebase.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/env python3 -"""Search exact-eight joint codecs near every seven-shear reference subsequence.""" - -from __future__ import annotations - -import argparse -import itertools -import json -import shutil -import time -from pathlib import Path -from typing import Any - -import y5_joint_codec_synth as joint -from y1_composite_synth import canonical_json, sha256_file, solver_version - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-joint-codec-two-rebase-v1" -BOUND = 8 - - -def pin_shear(cnf: joint.synth.Cnf, encoded: joint.synth.ShearVariables, expected: dict[str, Any]) -> None: - cnf.clause(encoded.enabled) - for variable_ids, coefficients in ( - (encoded.left, expected["left"]), - (encoded.right, expected["right"]), - (encoded.direction, expected["direction"]), - ): - for variable, value in zip(variable_ids, coefficients): - cnf.clause(variable if value else -variable) - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - for directory in (output, output / "cnf", output / "logs", output / "witnesses"): - directory.mkdir(parents=True, exist_ok=True) - - joint_ops, _ = joint.configure_problem() - reference = joint.synth.reference_program(joint_ops) - if len(reference["shears"]) != joint.REFERENCE_CCX_COUNT: - raise RuntimeError("reference shear count changed") - solver_name = args.solver - binary = shutil.which(solver_name) - if binary is None: - raise RuntimeError(f"required solver not found: {solver_name}") - - branches: list[dict[str, Any]] = [] - candidate: dict[str, Any] | None = None - consumed = 0.0 - failures: list[str] = [] - pairs = list(itertools.combinations(range(joint.REFERENCE_CCX_COUNT), 2)) - for removed in pairs: - kept = [ - shear for index, shear in enumerate(reference["shears"]) if index not in removed - ] - for insertion in range(BOUND): - if consumed >= args.max_local_seconds: - break - template: list[dict[str, Any] | None] = [ - *kept[:insertion], None, *kept[insertion:] - ] - if len(template) != BOUND: - raise AssertionError("two-rebase template must have eight shears") - cnf, variables, table = joint.synth.build_problem( - BOUND, list(joint.PAIR_INPUTS), exact=True - ) - for encoded, expected in zip(variables.shears, template): - if expected is not None: - pin_shear(cnf, encoded, expected) - - branch_id = f"drop-{removed[0]}-{removed[1]}-insert-{insertion}" - cnf_path = output / "cnf" / f"{branch_id}.cnf" - cnf.write( - cnf_path, - [ - "exact-eight joint codec with seven pinned reference shears and one free shear", - f"removed_reference_shears={removed[0]},{removed[1]}; free_insertion={insertion}", - "full-rank affine output map constrained by symbolic right inverse", - ], - ) - timeout = max( - 1, - min(args.timeout_seconds, int(args.max_local_seconds - consumed)), - ) - solver_run = joint.synth.run_solver( - solver_name, - binary, - BOUND, - cnf_path, - output / "logs" / f"{branch_id}.log", - timeout, - args.resume, - ) - if solver_run["elapsed_seconds"] is not None: - consumed += float(solver_run["elapsed_seconds"]) - assignment = set(solver_run.pop("true_variables")) - branch_failure: str | None = None - if solver_run["status"] == "sat": - try: - program = joint.synth.decode_program(variables, assignment) - symbolic, compiled, compiled_verification = joint.verify_candidate( - program, table, BOUND - ) - except Exception as error: - branch_failure = f"SAT witness failed to compile: {error}" - else: - if ( - symbolic["verdict"] != "green" - or compiled_verification["verdict"] != "green" - ): - branch_failure = "SAT witness failed exhaustive restricted-domain replay" - else: - candidate = { - "bound": BOUND, - "removed_reference_shears": list(removed), - "free_insertion": insertion, - "solver": solver_name, - "program": program, - "symbolic_verification": symbolic, - "compiled_verification": compiled_verification, - "compiled_operations": compiled, - "compiled_operation_count": len(compiled), - "compiled_ccx": sum( - kind == "CCX" for kind, _, _, _ in compiled - ), - "rust_table": joint.synth.rust_table(compiled), - } - witness_path = output / "witnesses" / f"{branch_id}.json" - witness_path.write_bytes(canonical_json(candidate) + b"\n") - candidate["witness_path"] = str( - witness_path.relative_to(REPO_ROOT) - ) - candidate["witness_sha256"] = sha256_file(witness_path) - if branch_failure is not None: - failures.append(f"{branch_id}: {branch_failure}") - branches.append( - { - "id": branch_id, - "removed_reference_shears": list(removed), - "free_insertion": insertion, - "status": "instrument-failure" - if branch_failure is not None - else "sat" - if candidate is not None - else solver_run["status"], - "failure": branch_failure, - "cnf_path": str(cnf_path.relative_to(REPO_ROOT)), - "cnf_sha256": sha256_file(cnf_path), - "cnf_variables": cnf.nvars, - "cnf_clauses": len(cnf.clauses), - "solver_run": solver_run, - } - ) - if candidate is not None or branch_failure is not None: - break - if candidate is not None or failures or consumed >= args.max_local_seconds: - break - - total_branches = len(pairs) * BOUND - verdict = "red" if failures else "green" if candidate is not None else "yellow" - report: dict[str, Any] = { - "schema_version": 1, - "prediction_id": args.prediction_id, - "started_unix_ns": started_unix_ns, - "wall_seconds": time.monotonic() - started, - "local_cpu_seconds": consumed, - "verdict": verdict, - "failures": failures, - "search_class": "remove every pair of the nine reference shears, preserve the other seven in order, and insert one arbitrary generalized shear at every position", - "expected_branches": total_branches, - "branches_run": len(branches), - "status_counts": { - status: sum(branch["status"] == status for branch in branches) - for status in ("sat", "unsat", "timeout", "unknown", "instrument-failure") - }, - "branches": branches, - "candidate_found": candidate is not None, - "candidate": candidate, - "solver_version": solver_version(binary), - "source_path": str(Path(__file__).resolve().relative_to(REPO_ROOT)), - "source_sha256": sha256_file(Path(__file__).resolve()), - "completeness_contract": { - "all_288_rebases_settled": len(branches) == total_branches - and all(branch["status"] in {"sat", "unsat"} for branch in branches), - "restricted_domain_forward_inverse_replay": candidate is not None, - "output_map_explicitly_invertible": True, - "timeouts_are_not_lower_bounds": True, - }, - } - (output / "report.json").write_bytes(canonical_json(report) + b"\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--prediction-id", default="PRED-Y5-JOINT-CODEC-SYNTH-V4") - parser.add_argument("--solver", default="cryptominisat5") - parser.add_argument("--timeout-seconds", type=int, default=5) - parser.add_argument("--max-local-seconds", type=float, default=600.0) - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 1 if report["verdict"] == "red" else 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_normalizer_synth.py b/src/point_add/memory/repro/y5_normalizer_synth.py deleted file mode 100755 index 1c649671..00000000 --- a/src/point_add/memory/repro/y5_normalizer_synth.py +++ /dev/null @@ -1,823 +0,0 @@ -#!/usr/bin/env python3 -"""Exact no-ancilla affine/Toffoli synthesis for the five-wire dialog normalizer.""" - -from __future__ import annotations - -import argparse -import concurrent.futures -import hashlib -import json -import re -import shutil -import time -from dataclasses import dataclass -from pathlib import Path -from typing import Any - -from y1_composite_synth import ( - Cnf, - canonical_json, - run_solver, - sha256_file, - solver_version, -) - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -SOURCE_PATH = REPO_ROOT / "src/point_add/trailmix_ludicrous/codec.rs" -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-normalizer-synth-v1" -WIDTH = 5 -REFERENCE_CCX_COUNT = 6 -INVOCATIONS = 344 -WIRE_OFFSET = 6 -PAIR25_INPUTS = (0, 1, 2, 3, 5, 7, 8, 10, 11, 12, 14, 16, 17, 18, 19, 20, 22, 24, 25, 26, 27, 28, 29, 30, 31) - -Gate = tuple[str, int, int, int] - - -@dataclass -class ShearVariables: - enabled: int - left: list[int] - right: list[int] - direction: list[int] - - -@dataclass -class SynthesisVariables: - shears: list[ShearVariables] - outputs: list[list[int]] - - -def load_reference_ops(path: Path = SOURCE_PATH) -> list[Gate]: - source = path.read_text(encoding="utf-8") - match = re.search( - r"const NORMALIZER_OPS:.*?=\s*&\[(.*?)\];", - source, - flags=re.DOTALL, - ) - if match is None: - raise RuntimeError(f"NORMALIZER_OPS not found in {path}") - tuples = re.findall( - r"\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)", - match.group(1), - ) - operations: list[Gate] = [] - kinds = {0: "X", 1: "CX", 2: "CCX"} - for raw_kind, raw_a, raw_b, raw_c in tuples: - kind = int(raw_kind) - if kind not in kinds: - raise ValueError(f"unknown NORMALIZER_OPS kind {kind}") - values = [int(raw_a), int(raw_b), int(raw_c)] - for index in range(1 if kind == 0 else 2 if kind == 1 else 3): - if values[index] not in range(WIRE_OFFSET, WIRE_OFFSET + WIDTH): - raise ValueError(f"normalizer wire out of range: {values[index]}") - values[index] -= WIRE_OFFSET - operations.append((kinds[kind], values[0], values[1], values[2])) - if len(operations) != 104: - raise ValueError(f"expected 104 normalizer operations, found {len(operations)}") - if sum(kind == "CCX" for kind, _, _, _ in operations) != REFERENCE_CCX_COUNT: - raise ValueError("normalizer reference CCX count changed") - return operations - - -def simulate_operations(value: int, operations: list[Gate]) -> int: - bits = [(value >> index) & 1 for index in range(WIDTH)] - for kind, first, second, third in operations: - if kind == "X": - bits[first] ^= 1 - elif kind == "CX": - bits[second] ^= bits[first] - elif kind == "CCX": - bits[third] ^= bits[first] & bits[second] - else: - raise ValueError(f"unknown operation {kind}") - return sum(bit << index for index, bit in enumerate(bits)) - - -def reference_table(operations: list[Gate] | None = None) -> list[int]: - ops = operations if operations is not None else load_reference_ops() - table = [simulate_operations(value, ops) for value in range(1 << WIDTH)] - if len(set(table)) != len(table): - raise ValueError("NORMALIZER_OPS does not define a permutation") - return table - - -def output_anfs(table: list[int]) -> list[list[int]]: - anfs: list[list[int]] = [] - for output_index in range(WIDTH): - coefficients = [(value >> output_index) & 1 for value in table] - for bit in range(WIDTH): - for mask in range(1 << WIDTH): - if mask & (1 << bit): - coefficients[mask] ^= coefficients[mask ^ (1 << bit)] - anfs.append([mask for mask, coefficient in enumerate(coefficients) if coefficient]) - return anfs - - -def anf_report(table: list[int]) -> dict[str, Any]: - anfs = output_anfs(table) - degrees = [max((mask.bit_count() for mask in output), default=0) for output in anfs] - max_degree = max(degrees) - degree_lower_bound = 0 - reachable_degree = 1 - while reachable_degree < max_degree: - degree_lower_bound += 1 - reachable_degree *= 2 - return { - "output_monomials": anfs, - "output_degrees": degrees, - "max_degree": max_degree, - "degree_only_ccx_lower_bound": degree_lower_bound, - } - - -def xor_variable(cnf: Cnf, terms: list[int]) -> int: - if not terms: - output = cnf.variable() - cnf.clause(-output) - return output - accumulator = terms[0] - for term in terms[1:]: - output = cnf.variable() - cnf.equivalence_xor(output, accumulator, term) - accumulator = output - return accumulator - - -def affine_value(cnf: Cnf, coefficients: list[int], state: list[int]) -> int: - terms = [coefficients[0]] - for coefficient, signal in zip(coefficients[1:], state): - product = cnf.variable() - cnf.equivalence_and(product, coefficient, signal) - terms.append(product) - return xor_variable(cnf, terms) - - -def constrain_gate_shape(cnf: Cnf, shear: ShearVariables) -> None: - enabled = shear.enabled - parameters = [*shear.left, *shear.right, *shear.direction] - for parameter in parameters: - cnf.clause(enabled, -parameter) - - cnf.clause(-enabled, *shear.left[1:]) - cnf.clause(-enabled, *shear.right[1:]) - cnf.clause(-enabled, *shear.direction) - - differences: list[int] = [] - for left, right in zip(shear.left[1:], shear.right[1:]): - difference = cnf.variable() - cnf.equivalence_xor(difference, left, right) - differences.append(difference) - cnf.clause(-enabled, *differences) - - # The control product is commutative. Fix the nonconstant coefficient - # vectors in numeric order to remove the left/right SAT symmetry. - for left_value in range(1, 1 << WIDTH): - for right_value in range(1, left_value): - forbidden = [ - -variable if (value >> index) & 1 else variable - for variables, value in ( - (shear.left[1:], left_value), - (shear.right[1:], right_value), - ) - for index, variable in enumerate(variables) - ] - cnf.clause(-enabled, *forbidden) - - for coefficients in (shear.left[1:], shear.right[1:]): - products: list[int] = [] - for coefficient, direction in zip(coefficients, shear.direction): - product = cnf.variable() - cnf.equivalence_and(product, coefficient, direction) - products.append(product) - dot = xor_variable(cnf, products) - cnf.clause(-enabled, -dot) - - -def constrain_invertible_output(cnf: Cnf, outputs: list[list[int]]) -> None: - inverse = [[cnf.variable() for _ in range(WIDTH)] for _ in range(WIDTH)] - for row in range(WIDTH): - for column in range(WIDTH): - products: list[int] = [] - for inner in range(WIDTH): - product = cnf.variable() - cnf.equivalence_and(product, outputs[row][inner + 1], inverse[inner][column]) - products.append(product) - value = xor_variable(cnf, products) - cnf.clause(value if row == column else -value) - - -def build_problem( - max_ccx: int, inputs: list[int] | None = None, exact: bool = False -) -> tuple[Cnf, SynthesisVariables, list[int]]: - if max_ccx < 0: - raise ValueError("max_ccx must be non-negative") - table = reference_table() - domain = inputs if inputs is not None else list(range(1 << WIDTH)) - cnf = Cnf() - shears: list[ShearVariables] = [] - for gate_index in range(max_ccx): - shear = ShearVariables( - enabled=cnf.variable(), - left=[cnf.variable() for _ in range(WIDTH + 1)], - right=[cnf.variable() for _ in range(WIDTH + 1)], - direction=[cnf.variable() for _ in range(WIDTH)], - ) - constrain_gate_shape(cnf, shear) - if gate_index: - cnf.clause(-shear.enabled, shears[-1].enabled) - if exact: - cnf.clause(shear.enabled) - shears.append(shear) - - states: list[list[int]] = [] - for input_value in domain: - initial: list[int] = [] - for index in range(WIDTH): - signal = cnf.variable() - cnf.clause(signal if (input_value >> index) & 1 else -signal) - initial.append(signal) - states.append(initial) - - for shear in shears: - next_states: list[list[int]] = [] - for state in states: - left = affine_value(cnf, shear.left, state) - right = affine_value(cnf, shear.right, state) - product = cnf.variable() - cnf.equivalence_and(product, left, right) - next_state: list[int] = [] - for current, direction in zip(state, shear.direction): - directed = cnf.variable() - cnf.equivalence_and(directed, direction, product) - active = cnf.variable() - cnf.equivalence_and(active, shear.enabled, directed) - updated = cnf.variable() - cnf.equivalence_xor(updated, current, active) - next_state.append(updated) - next_states.append(next_state) - states = next_states - - outputs = [[cnf.variable() for _ in range(WIDTH + 1)] for _ in range(WIDTH)] - constrain_invertible_output(cnf, outputs) - for input_value, state in zip(domain, states): - expected = table[input_value] - for output_index, coefficients in enumerate(outputs): - observed = affine_value(cnf, coefficients, state) - cnf.clause(observed if (expected >> output_index) & 1 else -observed) - - return cnf, SynthesisVariables(shears=shears, outputs=outputs), table - - -def bits(variable_ids: list[int], assignment: set[int]) -> list[int]: - return [int(variable in assignment) for variable in variable_ids] - - -def decode_program(variables: SynthesisVariables, assignment: set[int]) -> dict[str, Any]: - shears = [ - { - "enabled": int(shear.enabled in assignment), - "left": bits(shear.left, assignment), - "right": bits(shear.right, assignment), - "direction": bits(shear.direction, assignment), - } - for shear in variables.shears - ] - outputs = [bits(coefficients, assignment) for coefficients in variables.outputs] - return {"width": WIDTH, "shears": shears, "outputs": outputs} - - -def affine_bit(coefficients: list[int], state: list[int]) -> int: - value = coefficients[0] - for coefficient, signal in zip(coefficients[1:], state): - value ^= coefficient & signal - return value - - -def evaluate_program(program: dict[str, Any], input_value: int) -> int: - state = [(input_value >> index) & 1 for index in range(WIDTH)] - for shear in program["shears"]: - if not shear["enabled"]: - continue - left = affine_bit(shear["left"], state) - right = affine_bit(shear["right"], state) - if left & right: - state = [ - value ^ direction - for value, direction in zip(state, shear["direction"]) - ] - output = [affine_bit(coefficients, state) for coefficients in program["outputs"]] - return sum(value << index for index, value in enumerate(output)) - - -def vector(coefficients: list[int]) -> int: - return sum(value << index for index, value in enumerate(coefficients)) - - -def dot(left: int, right: int) -> int: - return (left & right).bit_count() & 1 - - -def matrix_rank(rows: list[int], width: int | None = None) -> int: - width = WIDTH if width is None else width - work = rows.copy() - rank = 0 - for column in range(width): - pivot = next((row for row in range(rank, len(work)) if work[row] & (1 << column)), None) - if pivot is None: - continue - work[rank], work[pivot] = work[pivot], work[rank] - for row in range(len(work)): - if row != rank and work[row] & (1 << column): - work[row] ^= work[rank] - rank += 1 - return rank - - -def verify_program( - program: dict[str, Any], table: list[int], inputs: list[int] | None = None -) -> dict[str, Any]: - failures: list[dict[str, Any]] = [] - enabled_count = 0 - for index, shear in enumerate(program["shears"]): - if not shear["enabled"]: - continue - enabled_count += 1 - left = vector(shear["left"][1:]) - right = vector(shear["right"][1:]) - direction = vector(shear["direction"]) - valid = ( - left != 0 - and right != 0 - and left != right - and direction != 0 - and dot(left, direction) == 0 - and dot(right, direction) == 0 - ) - if not valid: - failures.append({"kind": "invalid-shear", "index": index}) - for index in range(1, len(program["shears"])): - if program["shears"][index]["enabled"] and not program["shears"][index - 1]["enabled"]: - failures.append({"kind": "non-prefix-enable", "index": index}) - domain = inputs if inputs is not None else list(range(len(table))) - for input_value in domain: - expected = table[input_value] - observed = evaluate_program(program, input_value) - if observed != expected: - failures.append( - { - "kind": "truth-table-mismatch", - "input": input_value, - "expected": expected, - "observed": observed, - } - ) - return { - "verdict": "green" if not failures else "red", - "failures": failures, - "inputs": len(domain), - "enabled_ccx": enabled_count, - } - - -def invert_matrix(rows: list[int], width: int | None = None) -> list[int]: - width = WIDTH if width is None else width - augmented = [row | (1 << (width + index)) for index, row in enumerate(rows)] - for column in range(width): - pivot = next((row for row in range(column, width) if augmented[row] & (1 << column)), None) - if pivot is None: - raise ValueError("matrix is singular") - augmented[column], augmented[pivot] = augmented[pivot], augmented[column] - for row in range(width): - if row != column and augmented[row] & (1 << column): - augmented[row] ^= augmented[column] - mask = (1 << width) - 1 - if [row & mask for row in augmented] != [1 << index for index in range(width)]: - raise AssertionError("matrix inversion failed") - return [(row >> width) & mask for row in augmented] - - -def apply_linear_gate(rows: list[int], operation: Gate) -> None: - kind, control, target, _ = operation - if kind != "CX": - raise ValueError("linear elimination only accepts CX") - rows[target] ^= rows[control] - - -def linear_operations(matrix: list[int]) -> list[Gate]: - if matrix_rank(matrix) != WIDTH: - raise ValueError("linear output matrix is singular") - work = matrix.copy() - elimination: list[Gate] = [] - for column in range(WIDTH): - pivot = next(row for row in range(column, WIDTH) if work[row] & (1 << column)) - if pivot != column: - swap = [ - ("CX", column, pivot, 0), - ("CX", pivot, column, 0), - ("CX", column, pivot, 0), - ] - for operation in swap: - apply_linear_gate(work, operation) - elimination.append(operation) - for row in range(WIDTH): - if row != column and work[row] & (1 << column): - operation = ("CX", column, row, 0) - apply_linear_gate(work, operation) - elimination.append(operation) - if work != [1 << index for index in range(WIDTH)]: - raise AssertionError("linear elimination did not reach identity") - return list(reversed(elimination)) - - -def affine_operations(matrix: list[int], offset: int) -> list[Gate]: - operations = linear_operations(matrix) - operations.extend( - ("X", index, 0, 0) for index in range(WIDTH) if offset & (1 << index) - ) - return operations - - -def shear_basis(left: int, right: int, direction: int) -> list[int]: - if ( - left == 0 - or right == 0 - or left == right - or direction == 0 - or dot(left, direction) - or dot(right, direction) - ): - raise ValueError("invalid generalized shear") - rows = [left, right] - target_row = next( - candidate - for candidate in range(1, 1 << WIDTH) - if dot(candidate, direction) == 1 and matrix_rank([*rows, candidate]) == 3 - ) - rows.append(target_row) - for candidate in range(1, 1 << WIDTH): - if dot(candidate, direction) == 0 and matrix_rank([*rows, candidate]) > len(rows): - rows.append(candidate) - if len(rows) == WIDTH: - break - if len(rows) != WIDTH or matrix_rank(rows) != WIDTH: - raise AssertionError("failed to complete generalized shear basis") - image = sum(dot(row, direction) << index for index, row in enumerate(rows)) - if image != 1 << 2: - raise AssertionError("generalized shear direction did not map to target wire") - return rows - - -def compile_program(program: dict[str, Any]) -> list[Gate]: - operations: list[Gate] = [] - for shear in program["shears"]: - if not shear["enabled"]: - continue - left = vector(shear["left"][1:]) - right = vector(shear["right"][1:]) - direction = vector(shear["direction"]) - matrix = shear_basis(left, right, direction) - offset = shear["left"][0] | (shear["right"][0] << 1) - transform = affine_operations(matrix, offset) - operations.extend(transform) - operations.append(("CCX", 0, 1, 2)) - operations.extend(reversed(transform)) - output_matrix = [vector(coefficients[1:]) for coefficients in program["outputs"]] - output_offset = sum( - coefficients[0] << index for index, coefficients in enumerate(program["outputs"]) - ) - operations.extend(affine_operations(output_matrix, output_offset)) - return operations - - -def verify_compiled( - operations: list[Gate], table: list[int], inputs: list[int] | None = None -) -> dict[str, Any]: - failures: list[dict[str, Any]] = [] - inverse = list(reversed(operations)) - domain = inputs if inputs is not None else list(range(len(table))) - for input_value in domain: - expected = table[input_value] - observed = simulate_operations(input_value, operations) - if observed != expected: - failures.append( - {"kind": "forward", "input": input_value, "expected": expected, "observed": observed} - ) - restored = simulate_operations(expected, inverse) - if restored != input_value: - failures.append( - {"kind": "reverse", "input": input_value, "expected": input_value, "observed": restored} - ) - return { - "verdict": "green" if not failures else "red", - "failures": failures, - "operations": len(operations), - "ccx": sum(kind == "CCX" for kind, _, _, _ in operations), - } - - -def reference_program(operations: list[Gate]) -> dict[str, Any]: - matrix = [1 << index for index in range(WIDTH)] - offset = 0 - shears: list[dict[str, Any]] = [] - for kind, first, second, third in operations: - if kind == "X": - offset ^= 1 << first - elif kind == "CX": - matrix[second] ^= matrix[first] - if offset & (1 << first): - offset ^= 1 << second - elif kind == "CCX": - inverse = invert_matrix(matrix) - direction = sum(((inverse[row] >> third) & 1) << row for row in range(WIDTH)) - left = [(offset >> first) & 1, *[(matrix[first] >> bit) & 1 for bit in range(WIDTH)]] - right = [(offset >> second) & 1, *[(matrix[second] >> bit) & 1 for bit in range(WIDTH)]] - if vector(left[1:]) > vector(right[1:]): - left, right = right, left - shears.append( - { - "enabled": 1, - "left": left, - "right": right, - "direction": [(direction >> bit) & 1 for bit in range(WIDTH)], - } - ) - else: - raise ValueError(f"unknown operation {kind}") - outputs = [ - [(offset >> row) & 1, *[(matrix[row] >> bit) & 1 for bit in range(WIDTH)]] - for row in range(WIDTH) - ] - return {"width": WIDTH, "shears": shears, "outputs": outputs} - - -def rust_table(operations: list[Gate]) -> str: - tuples: list[str] = [] - for kind, first, second, third in operations: - if kind == "X": - tuples.append(f"(0,{first + WIRE_OFFSET},0,0)") - elif kind == "CX": - tuples.append(f"(1,{first + WIRE_OFFSET},{second + WIRE_OFFSET},0)") - elif kind == "CCX": - tuples.append( - f"(2,{first + WIRE_OFFSET},{second + WIRE_OFFSET},{third + WIRE_OFFSET})" - ) - else: - raise ValueError(f"unknown operation {kind}") - lines = [", ".join(tuples[index : index + 8]) for index in range(0, len(tuples), 8)] - return "\n".join(f" {line}," for line in lines) - - -def run(args: argparse.Namespace) -> dict[str, Any]: - started_unix_ns = time.time_ns() - started = time.monotonic() - output = args.output.resolve() - cnf_dir = output / "cnf" - log_dir = output / "logs" - witness_dir = output / "witnesses" - for directory in (output, cnf_dir, log_dir, witness_dir): - directory.mkdir(parents=True, exist_ok=True) - - reference_ops = load_reference_ops() - table = reference_table(reference_ops) - synthesis_inputs = ( - list(PAIR25_INPUTS) - if args.domain == "pair25" - else list(range(1 << WIDTH)) - ) - if args.domain == "pair25": - outputs = [table[input_value] for input_value in synthesis_inputs] - if len(set(synthesis_inputs)) != 25 or sorted(outputs) != list(range(25)): - raise RuntimeError("pair25 domain must map bijectively onto canonical values 0..24") - decomposed = reference_program(reference_ops) - decomposed_verification = verify_program(decomposed, table) - compiled_reference = compile_program(decomposed) - compiled_reference_verification = verify_compiled(compiled_reference, table) - if decomposed_verification["verdict"] != "green": - raise RuntimeError("reference affine-conjugation decomposition failed") - if compiled_reference_verification["verdict"] != "green": - raise RuntimeError("reference generalized-shear recompilation failed") - - solvers: dict[str, str] = {} - for name in ("kissat", "cadical"): - binary = shutil.which(name) - if binary is None: - raise RuntimeError(f"required solver not found: {name}") - solvers[name] = binary - - bounds = [args.max_ccx, REFERENCE_CCX_COUNT] - if args.max_ccx >= REFERENCE_CCX_COUNT: - raise ValueError(f"--max-ccx must be below reference count {REFERENCE_CCX_COUNT}") - search_mode = "exact" if args.exact_ccx else "at-most" - problems: dict[int, tuple[Cnf, SynthesisVariables, list[int]]] = {} - cnf_metadata: list[dict[str, Any]] = [] - for bound in bounds: - problem = build_problem(bound, synthesis_inputs, exact=args.exact_ccx) - problems[bound] = problem - cnf, _, _ = problem - path = cnf_dir / f"normalizer-{search_mode}-{bound}-ccx.cnf" - cnf.write( - path, - [ - "five-wire NORMALIZER_OPS exact affine-conjugated Toffoli synthesis", - f"{search_mode}_ccx={bound}", - f"domain={args.domain}; inputs={len(synthesis_inputs)}; arbitrary final invertible affine map inferred from constrained mapping", - "enabled generalized shear x <- x + c*(a.x+a0)*(b.x+b0)", - ], - ) - cnf_metadata.append( - { - "at_most_ccx": bound, - "search_mode": search_mode, - "path": str(path.relative_to(REPO_ROOT)), - "sha256": sha256_file(path), - "variables": cnf.nvars, - "clauses": len(cnf.clauses), - } - ) - - work: list[tuple[str, str, int, Path, Path, int, bool]] = [] - for bound in bounds: - cnf_path = cnf_dir / f"normalizer-{search_mode}-{bound}-ccx.cnf" - for solver_name, binary in solvers.items(): - work.append( - ( - solver_name, - binary, - bound, - cnf_path, - log_dir / f"{solver_name}-{search_mode}-{bound}.log", - args.timeout_seconds, - args.resume, - ) - ) - with concurrent.futures.ThreadPoolExecutor(max_workers=len(solvers)) as executor: - solver_runs = list(executor.map(lambda item: run_solver(*item), work)) - - errors: list[str] = [] - public_runs: list[dict[str, Any]] = [] - statuses: dict[int, dict[str, str]] = {bound: {} for bound in bounds} - verified_candidates: list[dict[str, Any]] = [] - for solver_run in solver_runs: - assignment = set(solver_run.pop("true_variables")) - bound = solver_run["and_gates"] - solver_name = solver_run["solver"] - solver_run["at_most_ccx"] = solver_run.pop("and_gates") - statuses[bound][solver_name] = solver_run["status"] - verification: dict[str, Any] | None = None - compiled_verification: dict[str, Any] | None = None - witness_path: str | None = None - witness_sha256: str | None = None - if solver_run["status"] == "sat": - _, variables, target = problems[bound] - program = decode_program(variables, assignment) - verification = verify_program(program, target, synthesis_inputs) - compiled = compile_program(program) if verification["verdict"] == "green" else [] - compiled_verification = ( - verify_compiled(compiled, target, synthesis_inputs) if compiled else None - ) - witness = { - "schema_version": 1, - "solver": solver_name, - "at_most_ccx": bound, - "program": program, - "verification": verification, - "compiled_operations": compiled, - "compiled_verification": compiled_verification, - "rust_table": rust_table(compiled) if compiled else None, - } - path = witness_dir / f"{solver_name}-at-most-{bound}.json" - path.write_text(json.dumps(witness, sort_keys=True, indent=2) + "\n") - witness_path = str(path.relative_to(REPO_ROOT)) - witness_sha256 = sha256_file(path) - if verification["verdict"] != "green": - errors.append(f"{solver_name} bound {bound}: model failed exhaustive replay") - elif compiled_verification is None or compiled_verification["verdict"] != "green": - errors.append(f"{solver_name} bound {bound}: compiled circuit failed replay") - elif bound == args.max_ccx: - verified_candidates.append(witness) - if solver_run["status"] not in {"sat", "unsat"}: - errors.append(f"{solver_name} bound {bound}: {solver_run['status']}") - if not solver_run["returncode_expected"]: - errors.append(f"{solver_name} bound {bound}: unexpected solver return code") - public_runs.append( - { - **solver_run, - "verification": verification, - "compiled_verification": compiled_verification, - "witness_path": witness_path, - "witness_sha256": witness_sha256, - } - ) - - for bound in bounds: - observed = set(statuses[bound].values()) - if len(observed) != 1: - errors.append(f"solver disagreement at bound {bound}: {statuses[bound]}") - if any(statuses[REFERENCE_CCX_COUNT].get(name) != "sat" for name in solvers): - errors.append("reference six-CCX upper bound was not SAT for both solvers") - - candidate: dict[str, Any] | None = None - if verified_candidates: - candidate = min( - verified_candidates, - key=lambda witness: ( - witness["compiled_verification"]["ccx"], - witness["compiled_verification"]["operations"], - witness["solver"], - ), - ) - candidate_ccx = ( - candidate["compiled_verification"]["ccx"] if candidate is not None else None - ) - exact_minimum = ( - REFERENCE_CCX_COUNT - if all(statuses[args.max_ccx].get(name) == "unsat" for name in solvers) - else None - ) - saving_per_invocation = ( - REFERENCE_CCX_COUNT - candidate_ccx if candidate_ccx is not None else 0 - ) - - report: dict[str, Any] = { - "schema_version": 1, - "scope": "Y5 five-wire NORMALIZER_OPS exact no-ancilla affine/Toffoli synthesis", - "search_mode": search_mode, - "pair25_lower_bound": ( - { - "minimum_ccx": 5, - "proof": "exhaustive affine-span quotient search found no path of length zero through four", - } - if args.domain == "pair25" and args.exact_ccx and args.max_ccx == 5 - else None - ), - "prediction_id": args.prediction_id, - "source_path": str(SOURCE_PATH.relative_to(REPO_ROOT)), - "source_sha256": sha256_file(SOURCE_PATH), - "reference": { - "operations": len(reference_ops), - "ccx": REFERENCE_CCX_COUNT, - "truth_table": table, - "synthesis_domain": args.domain, - "synthesis_inputs": synthesis_inputs, - "synthesis_outputs": [table[input_value] for input_value in synthesis_inputs], - "anf": anf_report(table), - "generalized_shear_decomposition": decomposed_verification, - "generalized_shear_recompile": compiled_reference_verification, - }, - "completeness_contract": { - "statement": "Every same-wire affine+CCX circuit with k CCX pushes its affine gates to the output and conjugates each CCX into one encoded reversible generalized shear.", - "shear_conditions": [ - "c != 0", - "linear(a) != 0", - "linear(b) != 0", - "linear(a) != linear(b)", - "a(c) = b(c) = 0", - ], - "reference_round_trip_verified": True, - }, - "max_candidate_ccx": args.max_ccx, - "cnfs": cnf_metadata, - "solver_versions": {name: solver_version(binary) for name, binary in solvers.items()}, - "solver_runs": sorted(public_runs, key=lambda row: (row["at_most_ccx"], row["solver"])), - "statuses": statuses, - "exact_minimum_ccx": exact_minimum, - "candidate_found": candidate is not None, - "candidate_solver": candidate["solver"] if candidate is not None else None, - "candidate_ccx": candidate_ccx, - "candidate_compiled_operations": ( - candidate["compiled_verification"]["operations"] if candidate is not None else None - ), - "repeated_invocations": INVOCATIONS, - "predicted_executed_toffoli_saving": saving_per_invocation * INVOCATIONS, - "predicted_score_saving_at_q1154": saving_per_invocation * INVOCATIONS * 1154, - "errors": errors, - "started_unix_ns": started_unix_ns, - "recorded_unix_ns": time.time_ns(), - "wall_seconds": time.monotonic() - started, - "verdict": "green" if not errors else "red", - } - report["report_sha256"] = hashlib.sha256(canonical_json(report)).hexdigest() - report_path = output / "report.json" - report_path.write_text(json.dumps(report, sort_keys=True, indent=2) + "\n") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--max-ccx", type=int, default=5) - parser.add_argument("--domain", choices=("full32", "pair25"), default="full32") - parser.add_argument("--exact-ccx", action="store_true") - parser.add_argument("--timeout-seconds", type=int, default=600) - parser.add_argument("--prediction-id", default="PRED-Y5-NORMALIZER-SYNTH-V1") - parser.add_argument("--resume", action="store_true") - args = parser.parse_args() - report = run(args) - print(json.dumps(report, sort_keys=True, indent=2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y5_pair25_quotient.py b/src/point_add/memory/repro/y5_pair25_quotient.py deleted file mode 100755 index 0d95f112..00000000 --- a/src/point_add/memory/repro/y5_pair25_quotient.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python3 -"""Exhaustive affine-quotient lower bound for the pair25 normalizer domain.""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import time -from pathlib import Path -from typing import Iterable - -import y5_normalizer_synth as synth - -RESEARCH_DIR = Path(__file__).resolve().parent -REPO_ROOT = RESEARCH_DIR.parents[3] -DEFAULT_OUTPUT = REPO_ROOT / ".autoresearch/measurements/y5-pair25-quotient-v1/report.json" -VALID_SYMBOLS = (0b001, 0b011, 0b100, 0b101, 0b111) -WIDTH = 5 - - -def compress_pair(first: int, second: int) -> int: - """Classically replay compress_2sym_fast through its proven clear_and.""" - value = first | (second << 3) - - def bit(index: int) -> int: - return (value >> index) & 1 - - value ^= 1 << 3 - value ^= bit(5) << 1 - value ^= bit(4) - value ^= 1 << 2 - value ^= (bit(1) & bit(3)) << 5 - value ^= bit(3) << 5 - value ^= bit(3) - value ^= bit(1) << 5 - value ^= bit(5) << 3 - value ^= (bit(5) & bit(0)) << 4 - if bit(5) != (bit(3) & bit(4)): - raise AssertionError("compress_2sym_fast clear_and precondition failed") - value &= ~(1 << 5) - return value & ((1 << WIDTH) - 1) - - -def canonical_span(vectors: Iterable[int]) -> tuple[int, ...]: - """Canonical reduced XOR basis of sample-column bit vectors.""" - basis: dict[int, int] = {} - for raw in vectors: - value = int(raw) - for pivot in sorted(basis, reverse=True): - if (value >> pivot) & 1: - value ^= basis[pivot] - if value == 0: - continue - pivot = value.bit_length() - 1 - for other, row in list(basis.items()): - if (row >> pivot) & 1: - basis[other] = row ^ value - basis[pivot] = value - return tuple(basis[pivot] for pivot in sorted(basis, reverse=True)) - - -def coordinate_masks(key: tuple[int, ...], constant: int) -> list[int]: - chosen = [constant] - rank = 1 - for row in key: - candidate = canonical_span([*chosen, row]) - if len(candidate) > rank: - chosen.append(row) - rank += 1 - if rank == WIDTH + 1: - break - if rank != WIDTH + 1: - raise ValueError(f"expected affine rank {WIDTH + 1}, found {rank}") - return chosen[1:] - - -def neighbor_spans(key: tuple[int, ...], constant: int) -> set[tuple[int, ...]]: - """Enumerate one affine-conjugated CCX move modulo free affine output.""" - coordinates = coordinate_masks(key, constant) - linear = [0] * (1 << WIDTH) - for form in range(1, 1 << WIDTH): - value = 0 - for bit_index, coordinate in enumerate(coordinates): - if (form >> bit_index) & 1: - value ^= coordinate - linear[form] = value - - neighbors: set[tuple[int, ...]] = set() - for direction in range(1, 1 << WIDTH): - invariant_forms = [ - form - for form in range(1, 1 << WIDTH) - if (form & direction).bit_count() % 2 == 0 - ] - hyperplane_basis: list[int] = [] - for form in invariant_forms: - if synth.matrix_rank([*hyperplane_basis, form], WIDTH) > len(hyperplane_basis): - hyperplane_basis.append(form) - if len(hyperplane_basis) == WIDTH - 1: - break - transverse = next( - form - for form in range(1, 1 << WIDTH) - if (form & direction).bit_count() % 2 == 1 - ) - - products: set[int] = set() - for left_index, left in enumerate(invariant_forms): - for right in invariant_forms[left_index + 1 :]: - for left_constant in (0, 1): - left_mask = linear[left] ^ (constant if left_constant else 0) - for right_constant in (0, 1): - right_mask = linear[right] ^ (constant if right_constant else 0) - products.add(left_mask & right_mask) - - fixed = [constant, *[linear[form] for form in hyperplane_basis]] - transverse_mask = linear[transverse] - for product in products: - neighbors.add(canonical_span([*fixed, transverse_mask ^ product])) - return neighbors - - -def pack_key(key: tuple[int, ...]) -> bytes: - if len(key) != WIDTH + 1 or any(value >= 1 << 32 for value in key): - raise ValueError("pair25 span key does not fit six u32 words") - return b"".join(value.to_bytes(4, "little") for value in key) - - -def frontier_sha256(frontier: set[bytes]) -> str: - digest = hashlib.sha256() - for key in sorted(frontier): - digest.update(key) - return digest.hexdigest() - - -def write_frontier(path: Path, frontier: set[bytes]) -> None: - path.parent.mkdir(parents=True, exist_ok=True) - with path.open("wb") as output: - for key in sorted(frontier): - output.write(key) - - -def run(output: Path, frontier_dir: Path | None = None) -> dict[str, object]: - started_ns = time.time_ns() - started = time.monotonic() - pair_states = [ - compress_pair(first, second) - for first in VALID_SYMBOLS - for second in VALID_SYMBOLS - ] - if len(set(pair_states)) != 25: - raise RuntimeError("valid symbol pairs did not produce 25 distinct normalizer inputs") - if tuple(sorted(pair_states)) != synth.PAIR25_INPUTS: - raise RuntimeError("derived pair25 domain disagrees with the synthesis contract") - - table = synth.reference_table() - pair_outputs = [table[value] for value in pair_states] - if sorted(pair_outputs) != list(range(25)): - raise RuntimeError("pair25 normalizer outputs are not canonical values 0..24") - - sample_count = len(pair_states) - constant = (1 << sample_count) - 1 - input_masks = [ - sum(((value >> bit_index) & 1) << sample for sample, value in enumerate(pair_states)) - for bit_index in range(WIDTH) - ] - output_masks = [ - sum(((value >> bit_index) & 1) << sample for sample, value in enumerate(pair_outputs)) - for bit_index in range(WIDTH) - ] - input_key = canonical_span([constant, *input_masks]) - output_key = canonical_span([constant, *output_masks]) - if len(input_key) != WIDTH + 1 or len(output_key) != WIDTH + 1: - raise RuntimeError("input or output affine embedding is rank-deficient") - - input_depth1 = neighbor_spans(input_key, constant) - output_depth1 = neighbor_spans(output_key, constant) - shortest_path: int | None = 0 if input_key == output_key else None - if shortest_path is None and output_key in input_depth1: - shortest_path = 1 - if shortest_path is None and input_depth1.intersection(output_depth1): - shortest_path = 2 - - input_depth2: set[bytes] = set() - reverse_edge_failures = 0 - if shortest_path is None: - for middle in input_depth1: - neighbors = neighbor_spans(middle, constant) - if input_key not in neighbors: - reverse_edge_failures += 1 - for neighbor in neighbors: - input_depth2.add(pack_key(neighbor)) - if neighbor == output_key or neighbor in output_depth1: - shortest_path = 3 - break - if shortest_path is not None: - break - - output_depth2_edges_checked = 0 - output_depth2: set[bytes] = set() - output_reverse_edge_failures = 0 - if shortest_path is None: - for middle in output_depth1: - neighbors = neighbor_spans(middle, constant) - if output_key not in neighbors: - output_reverse_edge_failures += 1 - for neighbor in neighbors: - output_depth2_edges_checked += 1 - packed = pack_key(neighbor) - output_depth2.add(packed) - if packed in input_depth2: - shortest_path = 4 - - frontier_dir = output.parent if frontier_dir is None else frontier_dir - input_depth2_path = frontier_dir / "x-depth2.bin" - output_depth2_path = frontier_dir / "y-depth2.bin" - write_frontier(input_depth2_path, input_depth2) - write_frontier(output_depth2_path, output_depth2) - - report: dict[str, object] = { - "schema_version": 2, - "scope": "exact pair25 affine-output quotient under arbitrary affine-conjugated CCX gates", - "pair_inputs": pair_states, - "sorted_pair_inputs": sorted(pair_states), - "pair_outputs": pair_outputs, - "sorted_pair_outputs": sorted(pair_outputs), - "input_affine_rank": len(input_key), - "output_affine_rank": len(output_key), - "input_depth1_states": len(input_depth1), - "output_depth1_states": len(output_depth1), - "input_depth2_states": len(input_depth2), - "input_depth2_sha256": frontier_sha256(input_depth2), - "output_depth2_edges_checked": output_depth2_edges_checked, - "output_depth2_states": len(output_depth2), - "output_depth2_sha256": frontier_sha256(output_depth2), - "frontier_artifacts": { - "input_depth2": str(input_depth2_path.relative_to(REPO_ROOT)), - "output_depth2": str(output_depth2_path.relative_to(REPO_ROOT)), - }, - "reverse_edge_failures": reverse_edge_failures + output_reverse_edge_failures, - "shortest_path_at_most_four": shortest_path, - "minimum_ccx_lower_bound": 5 if shortest_path is None else shortest_path, - "completeness_contract": { - "state": "the six-dimensional affine function span of a labeled 25-point embedding", - "edge": "every nonzero direction, every unordered pair of independent invariant linear controls, and all four affine control constants", - "quotient": "two embeddings are identified iff related by an invertible affine output map", - "symmetry": "each generalized shear is an involution; every enumerated edge must be observed in reverse", - }, - "started_unix_ns": started_ns, - "recorded_unix_ns": time.time_ns(), - "wall_seconds": time.monotonic() - started, - "verdict": "green" if shortest_path is None and reverse_edge_failures == 0 and output_reverse_edge_failures == 0 else "red", - } - encoded = json.dumps(report, sort_keys=True, separators=(",", ":")).encode() - report["report_sha256"] = hashlib.sha256(encoded).hexdigest() - output.parent.mkdir(parents=True, exist_ok=True) - output.write_text(json.dumps(report, sort_keys=True, indent=2) + "\n", encoding="utf-8") - return report - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--output", type=Path, default=DEFAULT_OUTPUT) - parser.add_argument("--frontier-dir", type=Path) - args = parser.parse_args() - report = run( - args.output.resolve(), - None if args.frontier_dir is None else args.frontier_dir.resolve(), - ) - print(json.dumps(report, sort_keys=True, indent=2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/y6_source_invariant.py b/src/point_add/memory/repro/y6_source_invariant.py deleted file mode 100755 index b61593e5..00000000 --- a/src/point_add/memory/repro/y6_source_invariant.py +++ /dev/null @@ -1,459 +0,0 @@ -#!/usr/bin/env python3 -"""Prove one census downgrade as a source-stable Boolean invariant. - -The selected gate is the first no-carry-in gate of threaded-add call 0, bit 0. -The production stream currently identifies it through a global operand-tuple ordinal. -This instrument proves the stronger value invariant q1 => q769 for arbitrary quantum -and classical register inputs and arbitrary HMR outcomes, then repeats the proof after -an adjacent self-inverse CCX pair changes that tuple's global occupancy and ordinal. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import re -import shutil -import struct -import subprocess -import tempfile -import time -from dataclasses import dataclass -from pathlib import Path -from typing import Iterable, Sequence - -import numpy as np - -from artifact_io import HEADER_BYTES, NO_QUBIT, RECORD_BYTES, decompress_record_body, read_header - -REPO_ROOT = Path(__file__).resolve().parents[4] -TARGET = (13, 1, 769, 768, NO_QUBIT) -TARGET_ORDINAL = 0 -TARGET_OCCUPANCY = 225 -TARGET_ACTION = 1 -SYMMETRIC_ORDINAL = 224 -SYMMETRIC_ACTION = 2 -CONTEXT_RADIUS = 8 -INPUT_QUBITS = 512 -INPUT_BITS = 512 -DTYPE = np.dtype( - [ - ("kind", " None: - if self.clauses is None: - self.clauses = [] - - def new(self) -> int: - self.variables += 1 - return self.variables - - def unit(self, literal: int) -> None: - assert self.clauses is not None - self.clauses.append([literal]) - - def and_gate(self, left: int, right: int) -> int: - out = self.new() - assert self.clauses is not None - self.clauses.extend(([-left, -right, out], [left, -out], [right, -out])) - return out - - def xor_gate(self, left: int, right: int) -> int: - out = self.new() - assert self.clauses is not None - self.clauses.extend( - ( - [-left, -right, -out], - [left, right, -out], - [left, -right, out], - [-left, right, out], - ) - ) - return out - - def mux(self, select: int, when_false: int, when_true: int) -> int: - difference = self.xor_gate(when_false, when_true) - selected_difference = self.and_gate(select, difference) - return self.xor_gate(when_false, selected_difference) - - -@dataclass(frozen=True) -class EncodedPrefix: - cnf: Cnf - qubits: dict[int, int] - bits: dict[int, int] - - -def sha256_file(path: Path) -> str: - digest = hashlib.sha256() - with path.open("rb") as source: - while chunk := source.read(8 * 1024 * 1024): - digest.update(chunk) - return digest.hexdigest() - - -def operation_tuple(row: np.void) -> tuple[int, int, int, int, int]: - return ( - int(row["kind"]), - int(row["q_control2"]), - int(row["q_control1"]), - int(row["q_target"]), - int(row["c_condition"]), - ) - - -def parse_key_table(path: Path) -> tuple[list[tuple[int, ...]], list[tuple[int, ...]]]: - text = path.read_text(encoding="utf-8") - dead_match = re.search(r"pub static DEAD_KEYS.*?= &\[(.*?)\];", text, re.DOTALL) - downgrade_match = re.search(r"pub static DOWNGRADE_KEYS.*?= &\[(.*?)\];", text, re.DOTALL) - if dead_match is None or downgrade_match is None: - raise ValueError("deep-strip key table declarations not found") - - def rows(block: str, width: int) -> list[tuple[int, ...]]: - parsed: list[tuple[int, ...]] = [] - for raw in re.findall(r"\(([^()]*)\)", block): - values = tuple(int(value.strip()) for value in raw.split(",") if value.strip()) - if len(values) == width: - parsed.append(values) - return parsed - - return rows(dead_match.group(1), 7), rows(downgrade_match.group(1), 8) - - -def verify_target_keys(dead: Sequence[tuple[int, ...]], downgrade: Sequence[tuple[int, ...]]) -> dict[str, object]: - first = (*TARGET, TARGET_ORDINAL, TARGET_OCCUPANCY, TARGET_ACTION) - symmetric = (*TARGET, SYMMETRIC_ORDINAL, TARGET_OCCUPANCY, SYMMETRIC_ACTION) - if first not in downgrade: - raise ValueError(f"selected downgrade key is absent: {first}") - if symmetric not in downgrade: - raise ValueError(f"symmetric downgrade key is absent: {symmetric}") - matching_dead = [row for row in dead if row[:5] == TARGET] - matching_downgrade = [row for row in downgrade if row[:5] == TARGET] - if matching_dead or matching_downgrade != [first, symmetric]: - raise ValueError("selected operand tuple has unexpected census classifications") - return { - "dead_keys": matching_dead, - "downgrade_keys": matching_downgrade, - "migration": { - "remove": first, - "rebase_remaining": (*TARGET, SYMMETRIC_ORDINAL - 1, TARGET_OCCUPANCY - 1, SYMMETRIC_ACTION), - }, - } - - -def verify_register_layout(records: np.ndarray) -> dict[str, list[int]]: - append = records[records["kind"] == 2] - register = records[records["kind"] == 1] - if len(register) != 4 or len(append) != 1024: - raise ValueError(f"expected four 256-element registers, got {len(register)} and {len(append)} append records") - no = NO_QUBIT - expected = { - "quantum_x": list(range(0, 256)), - "quantum_y": list(range(256, 512)), - "classical_x": list(range(0, 256)), - "classical_y": list(range(256, 512)), - } - observed = {name: [] for name in expected} - for row in append: - reg = int(row["r_target"]) - q_target = int(row["q_target"]) - c_target = int(row["c_target"]) - if reg == 0 and q_target != no: - observed["quantum_x"].append(q_target) - elif reg == 1 and q_target != no: - observed["quantum_y"].append(q_target) - elif reg == 2 and c_target != no: - observed["classical_x"].append(c_target) - elif reg == 3 and c_target != no: - observed["classical_y"].append(c_target) - else: - raise ValueError(f"unexpected register record {tuple(int(row[name]) for name in DTYPE.names)}") - if observed != expected: - raise ValueError("artifact register ABI is not q0..q511 / c0..c511") - return observed - - -def encode_prefix(records: Iterable[np.void]) -> EncodedPrefix: - cnf = Cnf() - true_var = cnf.new() - false_var = cnf.new() - cnf.unit(true_var) - cnf.unit(-false_var) - qubits = {index: cnf.new() for index in range(INPUT_QUBITS)} - bits = {index: cnf.new() for index in range(INPUT_BITS)} - - def qubit(index: int) -> int: - if index not in qubits: - qubits[index] = false_var - return qubits[index] - - def bit(index: int) -> int: - if index not in bits: - bits[index] = false_var - return bits[index] - - base_condition = true_var - condition_stack: list[int] = [] - ignored = {0, 1, 2, 7, 9, 14, 17} - - for index, row in enumerate(records): - kind = int(row["kind"]) - target = int(row["q_target"]) - control1 = int(row["q_control1"]) - control2 = int(row["q_control2"]) - classical_target = int(row["c_target"]) - classical_condition = int(row["c_condition"]) - condition = ( - base_condition - if classical_condition == NO_QUBIT - else cnf.and_gate(base_condition, bit(classical_condition)) - ) - - if kind == 6: # X - qubits[target] = cnf.xor_gate(qubit(target), condition) - elif kind == 8: # CX - effect = cnf.and_gate(condition, qubit(control1)) - qubits[target] = cnf.xor_gate(qubit(target), effect) - elif kind == 13: # CCX - controls = cnf.and_gate(qubit(control1), qubit(control2)) - effect = cnf.and_gate(condition, controls) - qubits[target] = cnf.xor_gate(qubit(target), effect) - elif kind == 10: # conditional swap - old_control = qubit(control1) - old_target = qubit(target) - difference = cnf.xor_gate(old_control, old_target) - effect = cnf.and_gate(condition, difference) - qubits[control1] = cnf.xor_gate(old_control, effect) - qubits[target] = cnf.xor_gate(old_target, effect) - elif kind in (11, 12): # R / HMR reset the qubit under the condition - qubits[target] = cnf.mux(condition, qubit(target), false_var) - if kind == 12: - random_measurement = cnf.new() # arbitrary HMR outcome - bits[classical_target] = cnf.mux(condition, bit(classical_target), random_measurement) - elif kind == 3: # BIT_INVERT - bits[classical_target] = cnf.xor_gate(bit(classical_target), condition) - elif kind == 4: # BIT_STORE0 - bits[classical_target] = cnf.mux(condition, bit(classical_target), false_var) - elif kind == 5: # BIT_STORE1 - bits[classical_target] = cnf.mux(condition, bit(classical_target), true_var) - elif kind == 15: # PUSH_CONDITION - if classical_condition == NO_QUBIT: - raise ValueError(f"PUSH_CONDITION without a bit at op {index}") - condition_stack.append(base_condition) - base_condition = cnf.and_gate(base_condition, bit(classical_condition)) - elif kind == 16: # POP_CONDITION - if not condition_stack: - raise ValueError(f"condition stack underflow at op {index}") - base_condition = condition_stack.pop() - elif kind not in ignored: - raise ValueError(f"unknown operation kind {kind} at op {index}") - - if condition_stack: - raise ValueError("prefix ends inside a pushed condition") - return EncodedPrefix(cnf=cnf, qubits=qubits, bits=bits) - - -def write_query(encoded: EncodedPrefix, path: Path, survivor: int, redundant: int) -> dict[str, int]: - clauses = list(encoded.cnf.clauses or []) - clauses.append([encoded.qubits[survivor]]) - clauses.append([-encoded.qubits[redundant]]) - with path.open("w", encoding="ascii") as output: - output.write(f"p cnf {encoded.cnf.variables} {len(clauses)}\n") - for clause in clauses: - output.write(" ".join(str(literal) for literal in clause)) - output.write(" 0\n") - return {"variables": encoded.cnf.variables, "clauses": len(clauses), "bytes": path.stat().st_size} - - -def run_solver(executable: str, cnf_path: Path, log_path: Path) -> dict[str, object]: - resolved = shutil.which(executable) - if resolved is None: - raise RuntimeError(f"SAT solver not found: {executable}") - started = time.monotonic() - process = subprocess.run( - [resolved, str(cnf_path)], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - timeout=120, - check=False, - ) - elapsed = time.monotonic() - started - log_path.write_text(process.stdout, encoding="utf-8") - unsat = "s UNSATISFIABLE" in process.stdout - sat = "s SATISFIABLE" in process.stdout - if process.returncode != 20 or not unsat or sat: - raise RuntimeError( - f"{executable} did not prove UNSAT for {cnf_path.name}: " - f"returncode={process.returncode}, unsat={unsat}, sat={sat}" - ) - return { - "executable": resolved, - "returncode": process.returncode, - "result": "UNSAT", - "wall_seconds": elapsed, - "log": str(log_path.relative_to(REPO_ROOT)), - "log_sha256": sha256_file(log_path), - } - - -def context_digest(records: np.ndarray, index: int) -> str: - lo = index - CONTEXT_RADIUS - hi = index + CONTEXT_RADIUS + 1 - if lo < 0 or hi > len(records): - raise ValueError("target lacks a complete context window") - return hashlib.sha256(records[lo:hi].tobytes()).hexdigest() - - -def run(args: argparse.Namespace) -> dict[str, object]: - ops_path = args.ops.resolve() - keys_path = args.keys.resolve() - output_path = args.output.resolve() - output_path.parent.mkdir(parents=True, exist_ok=True) - dead, downgrade = parse_key_table(keys_path) - key_report = verify_target_keys(dead, downgrade) - - with ops_path.open("rb") as source: - _, op_count = read_header(source) - with tempfile.TemporaryDirectory(prefix="y6-source-invariant-") as temporary: - raw_path = Path(temporary) / "ops.raw" - raw_report = decompress_record_body(ops_path, raw_path) - records = np.memmap(raw_path, dtype=DTYPE, mode="r", shape=(op_count,)) - register_layout = verify_register_layout(records) - matches = np.flatnonzero( - (records["kind"] == TARGET[0]) - & (records["q_control2"] == TARGET[1]) - & (records["q_control1"] == TARGET[2]) - & (records["q_target"] == TARGET[3]) - & (records["c_condition"] == TARGET[4]) - ) - if len(matches) != TARGET_OCCUPANCY: - raise ValueError(f"target occupancy changed: expected {TARGET_OCCUPANCY}, got {len(matches)}") - target_index = int(matches[TARGET_ORDINAL]) - if target_index != 16278: - raise ValueError(f"source target moved: expected op 16278, got {target_index}") - - baseline_context = context_digest(records, target_index) - context_matches = [ - int(index) for index in matches if context_digest(records, int(index)) == baseline_context - ] - if context_matches != [target_index]: - raise ValueError(f"source context is not unique: {context_matches}") - - baseline_prefix = np.asarray(records[:target_index]).copy() - encoded_baseline = encode_prefix(baseline_prefix) - baseline_cnf = output_path.parent / "baseline-implied-control.cnf" - baseline_shape = write_query(encoded_baseline, baseline_cnf, TARGET[1], TARGET[2]) - - inserted = np.asarray(records[target_index : target_index + 1]).copy() - perturbed_prefix = np.concatenate((inserted, inserted, baseline_prefix)) - perturbed_target_index = target_index + 2 - encoded_perturbed = encode_prefix(perturbed_prefix) - perturbed_cnf = output_path.parent / "perturbed-implied-control.cnf" - perturbed_shape = write_query(encoded_perturbed, perturbed_cnf, TARGET[1], TARGET[2]) - perturbed_context = hashlib.sha256( - np.concatenate( - ( - perturbed_prefix[perturbed_target_index - CONTEXT_RADIUS :], - np.asarray(records[target_index : target_index + CONTEXT_RADIUS + 1]), - ) - )[: 2 * CONTEXT_RADIUS + 1].tobytes() - ).hexdigest() - if perturbed_context != baseline_context: - raise AssertionError("identity perturbation changed the target's local source context") - - solver_reports: dict[str, dict[str, object]] = {} - for label, cnf_path in (("baseline", baseline_cnf), ("perturbed", perturbed_cnf)): - solver_reports[label] = {} - for solver in (args.solver, args.second_solver): - log_path = output_path.parent / f"{label}-{Path(solver).name}.log" - solver_reports[label][Path(solver).name] = run_solver(solver, cnf_path, log_path) - - source_paths = [ - REPO_ROOT / "src/point_add/trailmix_ludicrous/gidney.rs", - REPO_ROOT / "src/point_add/trailmix_ludicrous/gcd.rs", - REPO_ROOT / "src/point_add/mod.rs", - keys_path, - ] - report: dict[str, object] = { - "schema_version": 1, - "verdict": "green", - "scope": "Y6 exact source implied-control certificate and same-tuple identity perturbation", - "artifact": { - "path": str(ops_path.relative_to(REPO_ROOT)), - "compressed_sha256": sha256_file(ops_path), - "emitted_ops": op_count, - **raw_report, - }, - "register_layout": {name: {"first": values[0], "last": values[-1], "width": len(values)} for name, values in register_layout.items()}, - "selected_gate": { - "source": "gidney.rs:controlled_clean_add_threaded call_index=0 bit=0, no carry-in branch", - "op_index": target_index, - "tuple": TARGET, - "ordinal": TARGET_ORDINAL, - "occupancy": TARGET_OCCUPANCY, - "context_radius": CONTEXT_RADIUS, - "context_sha256": baseline_context, - "unique_context_matches": context_matches, - "proof_obligation": "q_control2=1 and q_control1=0 is unreachable before the gate", - "rewrite": "CCX(q_control2,q_control1,target) == CX(q_control2,target)", - }, - "key_table": key_report, - "exact_proofs": { - "baseline": {"cnf": baseline_shape, "solvers": solver_reports["baseline"]}, - "same_tuple_identity_pair": { - "inserted_operations": 2, - "identity": "adjacent identical CCX gates are self-inverse", - "target_ordinal_before": 0, - "target_ordinal_after": 2, - "tuple_occupancy_before": TARGET_OCCUPANCY, - "tuple_occupancy_after": TARGET_OCCUPANCY + 2, - "empirical_keys_made_stale": 2, - "source_certificate_matches": 1, - "source_certificate_stale": 0, - "source_certificate_density": 1.0, - "context_sha256": perturbed_context, - "cnf": perturbed_shape, - "solvers": solver_reports["perturbed"], - }, - }, - "source_hashes": {str(path.relative_to(REPO_ROOT)): sha256_file(path) for path in source_paths}, - } - output_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") - return report - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--ops", type=Path, required=True) - parser.add_argument("--keys", type=Path, required=True) - parser.add_argument("--output", type=Path, required=True) - parser.add_argument("--solver", default="kissat") - parser.add_argument("--second-solver", default="cadical") - return parser.parse_args() - - -def main() -> int: - report = run(parse_args()) - print(json.dumps(report, sort_keys=True)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/memory/repro/zero_score_lookup.py b/src/point_add/memory/repro/zero_score_lookup.py deleted file mode 100755 index 542a3aec..00000000 --- a/src/point_add/memory/repro/zero_score_lookup.py +++ /dev/null @@ -1,415 +0,0 @@ -#!/usr/bin/env python3 -"""Test the zero-score lookup route against Fiat-Shamir self-seeding. - -For a frozen 9,024-shot dataset, free classical condition stacks can select a -unique offset prefix and apply an X-only correction to the two quantum output -registers. That circuit has zero Toffoli cost. Its semantic operation stream, -however, changes the Fiat-Shamir dataset. This reproducer builds the semantic -lookup stream, derives its new dataset, and measures the resulting failure. -""" - -from __future__ import annotations - -import argparse -import hashlib -import json -import shutil -import struct -import subprocess -from pathlib import Path -from typing import Any - -try: - import numpy as np -except ImportError as error: - raise RuntimeError("zero_score_lookup.py requires numpy") from error - -try: - from artifact_io import HEADER_BYTES, MAGIC, MAX_OPS, NO_QUBIT, RECORD_BYTES - from world_model import FULL_VERIFICATION_SHOTS -except ModuleNotFoundError: - from .artifact_io import HEADER_BYTES, MAGIC, MAX_OPS, NO_QUBIT, RECORD_BYTES - from .world_model import FULL_VERIFICATION_SHOTS - -P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F -ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 -GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 -GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 -NO_FIELD = (1 << 64) - 1 -DOMAIN = b"quantum_ecc-fiat-shamir-v2" -CANONICAL_RECORD_BYTES = 49 - -REGISTER = 1 -APPEND_TO_REGISTER = 2 -BIT_INVERT = 3 -X = 6 -PUSH_CONDITION = 15 -POP_CONDITION = 16 - -AffinePoint = tuple[int, int] -JacobianPoint = tuple[int, int, int] -DatasetRow = tuple[int, int, int, int, int, int] - - -def _artifact_seed(path: Path) -> tuple[Any, str, int]: - zstd = shutil.which("zstd") - if zstd is None: - raise RuntimeError("zstd executable is required") - with path.open("rb", buffering=0) as source: - header = source.read(HEADER_BYTES) - if len(header) != HEADER_BYTES or header[: len(MAGIC)] != MAGIC: - raise ValueError("invalid ops artifact header") - count = struct.unpack_from(" MAX_OPS: - raise ValueError(f"op count {count} exceeds verifier cap") - shake = hashlib.shake_256(DOMAIN + struct.pack(" 17): - raise ValueError("artifact contains an unknown operation kind") - if np.any(raw[:, 4:8] != 0): - raise ValueError("artifact contains nonzero reserved padding") - canonical = np.empty((len(kinds), CANONICAL_RECORD_BYTES), dtype=np.uint8) - canonical[:, 0] = kinds - canonical[:, 1:] = raw[:, 8:RECORD_BYTES] - shake.update(canonical) - canonical_sha.update(canonical) - decoded += len(kinds) - remainder = data[complete:] - decoder.stdout.close() - stderr = decoder.stderr.read().decode("utf-8", errors="replace") if decoder.stderr else "" - if decoder.stderr: - decoder.stderr.close() - returncode = decoder.wait() - if returncode != 0: - raise RuntimeError(f"zstd decoder failed: {stderr.strip()}") - if remainder or decoded != count: - raise ValueError(f"decoded {decoded} complete records for declared count {count}") - return shake, canonical_sha.hexdigest(), count - - -def _jacobian_double(point: JacobianPoint) -> JacobianPoint: - x, y, z = point - if z == 0 or y == 0: - return (0, 1, 0) - yy = y * y % P - s = 4 * x * yy % P - m = 3 * x * x % P - x3 = (m * m - 2 * s) % P - y3 = (m * (s - x3) - 8 * yy * yy) % P - z3 = 2 * y * z % P - return (x3, y3, z3) - - -def _jacobian_mixed_add(point: JacobianPoint, affine: AffinePoint) -> JacobianPoint: - x1, y1, z1 = point - x2, y2 = affine - if z1 == 0: - return (x2, y2, 1) - z1z1 = z1 * z1 % P - u2 = x2 * z1z1 % P - s2 = y2 * z1 * z1z1 % P - h = (u2 - x1) % P - r = 2 * (s2 - y1) % P - if h == 0: - return _jacobian_double(point) if r == 0 else (0, 1, 0) - hh = h * h % P - i = 4 * hh % P - j = h * i % P - v = x1 * i % P - x3 = (r * r - j - 2 * v) % P - y3 = (r * (v - x3) - 2 * y1 * j) % P - z3 = ((z1 + h) * (z1 + h) - z1z1 - hh) % P - return (x3, y3, z3) - - -def _batch_inverse(values: list[int]) -> list[int]: - if any(value == 0 for value in values): - raise ValueError("batch inversion received zero") - prefixes: list[int] = [] - product = 1 - for value in values: - prefixes.append(product) - product = product * value % P - inverse = pow(product, P - 2, P) - outputs = [0] * len(values) - for index in range(len(values) - 1, -1, -1): - outputs[index] = inverse * prefixes[index] % P - inverse = inverse * values[index] % P - return outputs - - -def _normalize_many(points: list[JacobianPoint]) -> list[AffinePoint]: - nonzero = [point[2] for point in points if point[2] != 0] - inverses = iter(_batch_inverse(nonzero)) if nonzero else iter(()) - affine: list[AffinePoint] = [] - for x, y, z in points: - if z == 0: - affine.append((0, 0)) - continue - z_inv = next(inverses) - z2 = z_inv * z_inv % P - affine.append((x * z2 % P, y * z2 * z_inv % P)) - return affine - - -def _fixed_base_table() -> tuple[AffinePoint, ...]: - powers: list[JacobianPoint] = [(GX, GY, 1)] - for _ in range(1, 256): - powers.append(_jacobian_double(powers[-1])) - return tuple(_normalize_many(powers)) - - -def _fixed_base_mul_many(scalars: list[int], powers: tuple[AffinePoint, ...]) -> list[AffinePoint]: - outputs: list[JacobianPoint] = [] - for scalar in scalars: - point = (0, 1, 0) - bit = 0 - value = scalar - while value: - if value & 1: - point = _jacobian_mixed_add(point, powers[bit]) - value >>= 1 - bit += 1 - outputs.append(point) - return _normalize_many(outputs) - - -def _add_many(first: list[AffinePoint], second: list[AffinePoint]) -> list[AffinePoint]: - denominators: list[int] = [] - for (x1, y1), (x2, y2) in zip(first, second): - if (x1, y1) == (0, 0) or (x2, y2) == (0, 0) or x1 == x2: - raise ValueError("dataset contains an exceptional addition") - denominators.append((x2 - x1) % P) - inverses = _batch_inverse(denominators) - outputs: list[AffinePoint] = [] - for ((x1, y1), (x2, y2)), inverse in zip(zip(first, second), inverses): - slope = (y2 - y1) * inverse % P - x3 = (slope * slope - x1 - x2) % P - y3 = (slope * (x1 - x3) - y1) % P - outputs.append((x3, y3)) - return outputs - - -def _draw_dataset(shake: Any, shots: int, powers: tuple[AffinePoint, ...]) -> list[DatasetRow]: - extra = 32 - raw = shake.digest((shots + extra) * 64) - scalars_t = [ - int.from_bytes(raw[offset : offset + 32], "little") - for offset in range(0, len(raw), 64) - ] - scalars_o = [ - int.from_bytes(raw[offset + 32 : offset + 64], "little") - for offset in range(0, len(raw), 64) - ] - targets = _fixed_base_mul_many(scalars_t, powers) - offsets = _fixed_base_mul_many(scalars_o, powers) - selected_t: list[AffinePoint] = [] - selected_o: list[AffinePoint] = [] - for target, offset in zip(targets, offsets): - if target == (0, 0) or offset == (0, 0) or target[0] == offset[0]: - continue - selected_t.append(target) - selected_o.append(offset) - if len(selected_t) == shots: - break - if len(selected_t) != shots: - raise RuntimeError("insufficient non-exceptional Fiat-Shamir inputs") - sums = _add_many(selected_t, selected_o) - return [ - (target[0], target[1], offset[0], offset[1], result[0], result[1]) - for target, offset, result in zip(selected_t, selected_o, sums) - ] - - -def _minimum_unique_prefix(rows: list[DatasetRow]) -> int: - combined = [offset_x | (offset_y << 256) for _, _, offset_x, offset_y, _, _ in rows] - for width in range(1, 513): - mask = (1 << width) - 1 - keys = {value & mask for value in combined} - if len(keys) == len(rows): - return width - raise ValueError("classical offsets are not unique") - - -def _lookup_rows( - dataset: list[DatasetRow], prefix_width: int -) -> dict[int, tuple[int, int]]: - mask = (1 << prefix_width) - 1 - return { - (offset_x | (offset_y << 256)) & mask: (target_x ^ result_x, target_y ^ result_y) - for target_x, target_y, offset_x, offset_y, result_x, result_y in dataset - } - - -def _lookup_op_count(table: dict[int, tuple[int, int]], prefix_width: int) -> int: - count = 4 + 4 * 256 - prefix_mask = (1 << prefix_width) - 1 - for key, (mask_x, mask_y) in table.items(): - zero_bits = prefix_width - (key & prefix_mask).bit_count() - count += 2 * zero_bits + 2 * prefix_width + mask_x.bit_count() + mask_y.bit_count() - return count - - -def _record( - kind: int, - *, - q2: int = NO_FIELD, - q1: int = NO_FIELD, - qt: int = NO_FIELD, - ct: int = NO_FIELD, - cc: int = NO_FIELD, - rt: int = NO_FIELD, -) -> bytes: - return bytes((kind,)) + struct.pack("<6Q", q2, q1, qt, ct, cc, rt) - - -def _lookup_seed( - table: dict[int, tuple[int, int]], prefix_width: int -) -> tuple[Any, str, int]: - count = _lookup_op_count(table, prefix_width) - shake = hashlib.shake_256(DOMAIN + struct.pack(" None: - buffer.extend(record) - if len(buffer) >= 4 * 1024 * 1024: - shake.update(buffer) - semantic_sha.update(buffer) - buffer.clear() - - for register in range(4): - emit(_record(REGISTER, rt=register)) - for qubit in range(256): - emit(_record(APPEND_TO_REGISTER, qt=qubit, rt=0)) - for qubit in range(256, 512): - emit(_record(APPEND_TO_REGISTER, qt=qubit, rt=1)) - for bit in range(256): - emit(_record(APPEND_TO_REGISTER, ct=bit, rt=2)) - for bit in range(256, 512): - emit(_record(APPEND_TO_REGISTER, ct=bit, rt=3)) - - prefix_mask = (1 << prefix_width) - 1 - for key, (mask_x, mask_y) in sorted(table.items()): - zero_positions = [bit for bit in range(prefix_width) if not (key >> bit) & 1] - for bit in zero_positions: - emit(_record(BIT_INVERT, ct=bit)) - for bit in range(prefix_width): - emit(_record(PUSH_CONDITION, cc=bit)) - for bit in range(256): - if (mask_x >> bit) & 1: - emit(_record(X, qt=bit)) - for bit in range(256): - if (mask_y >> bit) & 1: - emit(_record(X, qt=256 + bit)) - for _ in range(prefix_width): - emit(_record(POP_CONDITION)) - for bit in zero_positions: - emit(_record(BIT_INVERT, ct=bit)) - if buffer: - shake.update(buffer) - semantic_sha.update(buffer) - return shake, semantic_sha.hexdigest(), count - - -def _lookup_failures( - dataset: list[DatasetRow], table: dict[int, tuple[int, int]], prefix_width: int -) -> tuple[int, int]: - prefix_mask = (1 << prefix_width) - 1 - failures = 0 - table_hits = 0 - for target_x, target_y, offset_x, offset_y, result_x, result_y in dataset: - key = (offset_x | (offset_y << 256)) & prefix_mask - correction = table.get(key) - if correction is None: - output = (target_x, target_y) - else: - table_hits += 1 - output = (target_x ^ correction[0], target_y ^ correction[1]) - failures += output != (result_x, result_y) - return failures, table_hits - - -def run(ops_path: Path, shots: int) -> dict[str, Any]: - original_seed, original_semantic_sha, original_ops = _artifact_seed(ops_path) - powers = _fixed_base_table() - original_dataset = _draw_dataset(original_seed, shots, powers) - prefix_width = _minimum_unique_prefix(original_dataset) - table = _lookup_rows(original_dataset, prefix_width) - original_failures, original_hits = _lookup_failures( - original_dataset, table, prefix_width - ) - lookup_seed, lookup_semantic_sha, lookup_ops = _lookup_seed(table, prefix_width) - self_seeded_dataset = _draw_dataset(lookup_seed, shots, powers) - self_seeded_failures, self_seeded_hits = _lookup_failures( - self_seeded_dataset, table, prefix_width - ) - verdict = ( - "green" - if original_failures == 0 - and original_hits == shots - and lookup_ops <= MAX_OPS - and self_seeded_failures > 0 - else "red" - ) - return { - "experiment": "zero-Toffoli frozen-dataset lookup versus Fiat-Shamir reseed", - "verdict": verdict, - "shots": shots, - "original_artifact": { - "semantic_sha256": original_semantic_sha, - "emitted_ops": original_ops, - }, - "frozen_lookup": { - "classical_prefix_bits": prefix_width, - "table_entries": len(table), - "emitted_ops": lookup_ops, - "toffoli_ops": 0, - "qubits": 512, - "predicted_score_on_frozen_dataset": 0, - "classical_failures_on_frozen_dataset": original_failures, - "table_hits_on_frozen_dataset": original_hits, - "semantic_sha256": lookup_semantic_sha, - }, - "fiat_shamir_reseed": { - "classical_failures": self_seeded_failures, - "table_hits": self_seeded_hits, - }, - "conclusion": ( - "A zero-score lookup fits any frozen dataset within the operation cap, but changing " - "the semantic stream reseeds the verifier. The direct lookup is not a candidate." - ), - } - - -def main() -> int: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--ops", type=Path, default=Path("ops.bin")) - parser.add_argument("--shots", type=int, default=FULL_VERIFICATION_SHOTS) - parser.add_argument("--json", action="store_true") - args = parser.parse_args() - if args.shots <= 0: - parser.error("--shots must be positive") - report = run(args.ops, args.shots) - print(json.dumps(report, sort_keys=True, indent=None if args.json else 2)) - return 0 if report["verdict"] == "green" else 1 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/src/point_add/mod.rs b/src/point_add/mod.rs index 6b71acff..d0c5da45 100644 --- a/src/point_add/mod.rs +++ b/src/point_add/mod.rs @@ -1,5276 +1,4849 @@ - -use alloy_primitives::U256; -use sha3::{ - digest::{ExtendableOutput, Update, XofReader}, - Shake256, -}; - -use crate::circuit::{analyze_ops, BitId, Op, OperationType, QubitId, QubitOrBit, RegisterId}; -use crate::sim::Simulator; -use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; - -pub mod venting; - -mod emit; -pub(crate) use emit::*; - -mod arith; -pub(crate) use arith::*; - -mod rounds; -pub(crate) use rounds::*; - -pub mod trailmix_ludicrous; -mod single_ccx_fanout; -mod m60_dead_t10; -mod d2_deep_strip; -mod deep_strip_keys; -mod dirtyscan; - -thread_local! { - static D1_PHASE_CORRECTED_PRODUCT_CORE_SCOPE: std::cell::Cell = - std::cell::Cell::new(false); - static OP_SITE_TRACE: std::cell::RefCell> = - std::cell::RefCell::new(Vec::new()); - static OP_TRACE_CONTEXT: std::cell::Cell = std::cell::Cell::new(0); -} - -fn d1_phase_corrected_product_core_active() -> bool { - D1_PHASE_CORRECTED_PRODUCT_CORE_SCOPE.with(|scope| scope.get()) -} - -pub type OpSite = (&'static str, u32, u32); - -pub(crate) fn op_site_trace_enabled() -> bool { - static ENABLED: std::sync::OnceLock = std::sync::OnceLock::new(); - *ENABLED.get_or_init(|| std::env::var_os("TRACE_OP_SITES").is_some()) -} - -fn reset_op_site_trace() { - if op_site_trace_enabled() { - OP_SITE_TRACE.with(|sites| sites.borrow_mut().clear()); - } -} - -fn record_op_site(site: OpSite) { - if op_site_trace_enabled() { - OP_SITE_TRACE.with(|sites| sites.borrow_mut().push(site)); - } -} - -pub(crate) fn set_op_trace_context(context: u32) -> u32 { - if !op_site_trace_enabled() { - return 0; - } - OP_TRACE_CONTEXT.with(|slot| { - let old = slot.get(); - slot.set(context); - old - }) -} - -pub(crate) fn restore_op_trace_context(context: u32) { - if op_site_trace_enabled() { - OP_TRACE_CONTEXT.with(|slot| slot.set(context)); - } -} - -pub(crate) fn take_op_site_trace_for_constprop(expected_len: usize) -> Option> { - if !op_site_trace_enabled() { - return None; - } - OP_SITE_TRACE.with(|sites| { - let mut sites = sites.borrow_mut(); - assert_eq!( - sites.len(), - expected_len, - "op site trace length before constprop" - ); - Some(std::mem::take(&mut *sites)) - }) -} - -pub(crate) fn set_op_site_trace_from_constprop(sites: Vec) { - if op_site_trace_enabled() { - OP_SITE_TRACE.with(|slot| *slot.borrow_mut() = sites); - } -} - -pub fn take_last_op_sites() -> Vec { - OP_SITE_TRACE.with(|sites| std::mem::take(&mut *sites.borrow_mut())) -} - -pub struct B { - pub ops: Vec, - pub count_only: bool, - pub counted_ops: usize, - pub counted_kind_ops: [usize; 18], - pub counted_phase_kind_ops: [usize; 18], - pub counted_phase_start_ops: usize, - pub counted_phase_rows: Vec, - pub counted_registers: Vec>, - pub next_qubit: u32, - pub next_bit: u32, - pub next_register: u32, - pub free_qubits: Vec, - pub active_qubits: u32, - pub peak_qubits: u32, - pub peak_ops_idx: usize, - pub peak_phase: &'static str, - pub phase: &'static str, - pub peak_log: Vec<(u32, &'static str, usize)>, - pub phase_active_max: std::collections::BTreeMap<&'static str, u32>, - pub phase_active_regions: Vec<(usize, &'static str, u32)>, - pub current_phase_active_max: u32, - - pub phase_transitions: Vec<(usize, &'static str)>, - pub active_timeline: Vec<(usize, u32)>, - - pub k2_shift2_log: Vec, - - pub b0: B0Census, -} - -#[derive(Default)] -pub struct B0Census { - pub enabled: bool, - pub win_lo: usize, - pub win_hi: usize, - - pub owner: std::collections::HashMap, - - pub batch_ctx: Option<(&'static str, u32)>, - pub best_active: u32, - pub best_ops: usize, - pub best_phase: &'static str, - pub best_snapshot: Option>, - pub printed: bool, - - pub phase_filter: Option, -} - -#[derive(Clone, Copy)] -struct CountSnapshot { - ops: usize, - kind_ops: [usize; 18], - phase_kind_ops: [usize; 18], - phase_start_ops: usize, - phase_rows_len: usize, - phase: &'static str, -} - -#[derive(Clone, Debug)] -pub struct PhaseResource { - pub phase: &'static str, - pub start: usize, - pub end: usize, - pub ops: usize, - pub toffoli_ops: usize, - pub ccx_ops: usize, - pub ccz_ops: usize, - pub hmr_ops: usize, - pub r_ops: usize, -} - -impl B { - fn new() -> Self { - reset_op_site_trace(); - Self { - ops: Vec::new(), - count_only: false, - counted_ops: 0, - counted_kind_ops: [0; 18], - counted_phase_kind_ops: [0; 18], - counted_phase_start_ops: 0, - counted_phase_rows: Vec::new(), - counted_registers: Vec::new(), - next_qubit: 0, - next_bit: 0, - next_register: 0, - free_qubits: Vec::new(), - active_qubits: 0, - peak_qubits: 0, - peak_ops_idx: 0, - peak_phase: "", - phase: "init", - peak_log: Vec::new(), - phase_active_max: std::collections::BTreeMap::new(), - phase_active_regions: Vec::new(), - current_phase_active_max: 0, - phase_transitions: Vec::new(), - active_timeline: Vec::new(), - k2_shift2_log: Vec::new(), - b0: { - let lo = std::env::var("B0_WIN_LO") - .ok() - .and_then(|v| v.parse::().ok()); - let hi = std::env::var("B0_WIN_HI") - .ok() - .and_then(|v| v.parse::().ok()); - match (lo, hi) { - (Some(lo), Some(hi)) => B0Census { - enabled: true, - win_lo: lo, - win_hi: hi, - phase_filter: std::env::var("B0_PHASE").ok().filter(|s| !s.is_empty()), - ..Default::default() - }, - _ => B0Census::default(), - } - }, - } - } - fn new_count_only() -> Self { - let mut b = Self::new(); - b.count_only = true; - b - } - - pub fn new_for_test() -> Self { - Self::new() - } - pub fn take_ops(&mut self) -> Vec { - std::mem::take(&mut self.ops) - } - #[track_caller] - fn push_op(&mut self, op: Op) { - self.counted_ops += 1; - self.counted_kind_ops[op.kind as usize] += 1; - self.counted_phase_kind_ops[op.kind as usize] += 1; - if !self.count_only { - let loc = std::panic::Location::caller(); - let context = OP_TRACE_CONTEXT.with(|slot| slot.get()); - record_op_site((loc.file(), loc.line(), context)); - self.ops.push(op); - } - } - fn count_snapshot(&self) -> CountSnapshot { - CountSnapshot { - ops: self.counted_ops, - kind_ops: self.counted_kind_ops, - phase_kind_ops: self.counted_phase_kind_ops, - phase_start_ops: self.counted_phase_start_ops, - phase_rows_len: self.counted_phase_rows.len(), - phase: self.phase, - } - } - fn count_delta_since(&self, snap: CountSnapshot) -> [usize; 18] { - let mut out = [0usize; 18]; - for (idx, slot) in out.iter_mut().enumerate() { - *slot = self.counted_kind_ops[idx] - snap.kind_ops[idx]; - } - out - } - fn restore_count_snapshot(&mut self, snap: CountSnapshot) { - self.counted_ops = snap.ops; - self.counted_kind_ops = snap.kind_ops; - self.counted_phase_kind_ops = snap.phase_kind_ops; - self.counted_phase_start_ops = snap.phase_start_ops; - self.counted_phase_rows.truncate(snap.phase_rows_len); - self.phase = snap.phase; - } - fn add_counted_kind(&mut self, kind: OperationType, count: usize) { - self.counted_ops += count; - self.counted_kind_ops[kind as usize] += count; - self.counted_phase_kind_ops[kind as usize] += count; - } - fn current_ops_len(&self) -> usize { - if self.count_only { - self.counted_ops - } else { - self.ops.len() - } - } - fn close_counted_phase(&mut self) { - if !self.count_only { - return; - } - let start = self.counted_phase_start_ops; - let end = self.counted_ops; - if start < end { - let ccx_ops = self.counted_phase_kind_ops[OperationType::CCX as usize]; - let ccz_ops = self.counted_phase_kind_ops[OperationType::CCZ as usize]; - let hmr_ops = self.counted_phase_kind_ops[OperationType::Hmr as usize]; - let r_ops = self.counted_phase_kind_ops[OperationType::R as usize]; - self.counted_phase_rows.push(PhaseResource { - phase: self.phase, - start, - end, - ops: end - start, - toffoli_ops: ccx_ops + ccz_ops, - ccx_ops, - ccz_ops, - hmr_ops, - r_ops, - }); - } - self.counted_phase_start_ops = self.counted_ops; - self.counted_phase_kind_ops = [0; 18]; - } - fn set_phase(&mut self, p: &'static str) { - self.close_phase_active_region(); - self.close_counted_phase(); - self.phase = p; - if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { - self.current_phase_active_max = self.active_qubits; - } - self.phase_transitions.push((self.current_ops_len(), p)); - } - fn record_active_timeline(&mut self) { - if std::env::var("PROFILE_ACTIVE_TIMELINE").is_ok() { - self.active_timeline - .push((self.current_ops_len(), self.active_qubits)); - } - } - fn record_phase_active(&mut self) { - self.record_active_timeline(); - if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { - let entry = self.phase_active_max.entry(self.phase).or_insert(0); - if self.active_qubits > *entry { - *entry = self.active_qubits; - } - if self.active_qubits > self.current_phase_active_max { - self.current_phase_active_max = self.active_qubits; - } - } - } - fn close_phase_active_region(&mut self) { - if std::env::var("TRACE_PHASE_ACTIVE").is_ok() && self.current_phase_active_max > 0 { - self.phase_active_regions.push(( - self.current_ops_len(), - self.phase, - self.current_phase_active_max, - )); - self.current_phase_active_max = 0; - } - } - - fn b0_on_alloc(&mut self, qid: u64, file: &'static str, line: u32) { - if !self.b0.enabled || self.count_only { - return; - } - let ctx = match self.b0.batch_ctx { - Some((f, l)) => (self.phase, f, l), - None => (self.phase, file, line), - }; - self.b0.owner.insert(qid, ctx); - self.b0_sample(); - } - fn b0_on_free(&mut self, qid: u64) { - if !self.b0.enabled || self.count_only { - return; - } - self.b0.owner.remove(&qid); - self.b0_sample(); - } - fn b0_sample(&mut self) { - if self.b0.printed { - return; - } - let cur = self.current_ops_len(); - if cur > self.b0.win_hi { - self.b0_print(); - return; - } - if cur >= self.b0.win_lo && self.active_qubits > self.b0.best_active { - if let Some(f) = &self.b0.phase_filter { - if !self.phase.contains(f.as_str()) { - return; - } - } - self.b0.best_active = self.active_qubits; - self.b0.best_ops = cur; - self.b0.best_phase = self.phase; - self.b0.best_snapshot = Some(self.b0.owner.clone()); - } - } - - pub fn b0_finalize(&mut self) { - if self.b0.enabled && !self.b0.printed { - self.b0_print(); - } - } - fn b0_print(&mut self) { - self.b0.printed = true; - let snap = match self.b0.best_snapshot.take() { - Some(s) => s, - None => return, - }; - let mut hist: std::collections::HashMap<(&'static str, &'static str, u32), u32> = - std::collections::HashMap::new(); - for v in snap.values() { - *hist.entry(*v).or_insert(0) += 1; - } - let mut rows: Vec<((&'static str, &'static str, u32), u32)> = hist.into_iter().collect(); - rows.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0))); - eprintln!( - "B0_CENSUS_BEGIN best_active={} best_ops={} best_phase={} n_live={} n_groups={} win=[{},{}]", - self.b0.best_active, - self.b0.best_ops, - self.b0.best_phase, - snap.len(), - rows.len(), - self.b0.win_lo, - self.b0.win_hi - ); - for ((phase, file, line), cnt) in &rows { - eprintln!("B0_OWN count={cnt} phase={phase} caller={file}:{line}"); - } - eprintln!("B0_CENSUS_END"); - } - #[track_caller] - fn alloc_qubit(&mut self) -> QubitId { - self.active_qubits += 1; - self.record_phase_active(); - if let Ok(threshold) = std::env::var("TRACE_ALLOC_NEAR_PEAK") - .ok() - .and_then(|value| value.parse::().ok()) - .ok_or(()) - { - if self.active_qubits >= threshold { - let caller = std::panic::Location::caller(); - eprintln!( - "ALLOC_NEAR active={} next_idx={} phase='{}' ops_idx={} free_pool={} caller={}:{}", - self.active_qubits, - self.next_qubit, - self.phase, - self.current_ops_len(), - self.free_qubits.len(), - caller.file(), - caller.line(), - ); - } - } - if self.active_qubits > self.peak_qubits { - self.peak_qubits = self.active_qubits; - self.peak_ops_idx = self.current_ops_len(); - self.peak_phase = self.phase; - if std::env::var("TRACE_EACH_PEAK").is_ok() { - eprintln!( - "PEAK active={} next_idx={} phase='{}' ops_idx={}", - self.active_qubits, - self.next_qubit, - self.phase, - self.current_ops_len() - ); - } - } - if std::env::var("TRACE_PEAK").is_ok() && self.active_qubits + 10 >= self.peak_qubits { - self.peak_log - .push((self.active_qubits, self.phase, self.current_ops_len())); - } - let qid = if let Some(q) = self.free_qubits.pop() { - QubitId(q.into()) - } else { - let q = self.next_qubit; - self.next_qubit += 1; - QubitId(q.into()) - }; - if self.b0.enabled && !self.count_only { - let caller = std::panic::Location::caller(); - self.b0_on_alloc(qid.0, caller.file(), caller.line()); - } - qid - } - #[track_caller] - fn alloc_qubits(&mut self, n: usize) -> Vec { - if self.b0.enabled { - let c = std::panic::Location::caller(); - self.b0.batch_ctx = Some((c.file(), c.line())); - let out = (0..n).map(|_| self.alloc_qubit()).collect(); - self.b0.batch_ctx = None; - out - } else { - (0..n).map(|_| self.alloc_qubit()).collect() - } - } - fn alloc_bit(&mut self) -> BitId { - let b = self.next_bit; - self.next_bit += 1; - BitId(b.into()) - } - fn alloc_bits(&mut self, n: usize) -> Vec { - (0..n).map(|_| self.alloc_bit()).collect() - } - fn free(&mut self, q: QubitId) { - self.r(q); - self.free_qubits - .push(q.0.try_into().expect("qubit id fits in u32")); - if self.active_qubits > 0 { - self.active_qubits -= 1; - } - self.record_active_timeline(); - self.b0_on_free(q.0); - } - fn free_vec(&mut self, qs: &[QubitId]) { - for &q in qs { - self.free(q); - } - } - fn reacquire(&mut self, q: QubitId) { - let pos = self - .free_qubits - .iter() - .position(|&free_q| u64::from(free_q) == q.0) - .expect("reacquire qubit that is not currently free"); - self.free_qubits.swap_remove(pos); - self.active_qubits += 1; - self.record_phase_active(); - if self.active_qubits > self.peak_qubits { - self.peak_qubits = self.active_qubits; - self.peak_ops_idx = self.current_ops_len(); - self.peak_phase = self.phase; - if std::env::var("TRACE_EACH_PEAK").is_ok() { - eprintln!( - "PEAK active={} next_idx={} phase='{}' ops_idx={}", - self.active_qubits, - self.next_qubit, - self.phase, - self.current_ops_len() - ); - } - } - if std::env::var("TRACE_PEAK").is_ok() && self.active_qubits + 10 >= self.peak_qubits { - self.peak_log - .push((self.active_qubits, self.phase, self.current_ops_len())); - } - - if self.b0.enabled && !self.count_only { - self.b0_on_alloc(q.0, "reacquire", 0); - } - } - fn reacquire_vec(&mut self, qs: &[QubitId]) { - for &q in qs { - self.reacquire(q); - } - } - fn declare_qubit_register(&mut self, qs: &[QubitId]) { - let r = RegisterId(self.next_register.into()); - self.next_register += 1; - for &q in qs { - while self.counted_registers.len() <= r.0 as usize { - self.counted_registers.push(Vec::new()); - } - self.counted_registers[r.0 as usize].push(QubitOrBit::Qubit(q)); - let mut op = Op::empty(); - op.kind = OperationType::AppendToRegister; - op.q_target = q; - op.r_target = r; - self.push_op(op); - } - let mut op = Op::empty(); - op.kind = OperationType::Register; - op.r_target = r; - self.push_op(op); - } - fn declare_bit_register(&mut self, bs: &[BitId]) { - let r = RegisterId(self.next_register.into()); - self.next_register += 1; - for &b in bs { - while self.counted_registers.len() <= r.0 as usize { - self.counted_registers.push(Vec::new()); - } - self.counted_registers[r.0 as usize].push(QubitOrBit::Bit(b)); - let mut op = Op::empty(); - op.kind = OperationType::AppendToRegister; - op.c_target = b; - op.r_target = r; - self.push_op(op); - } - let mut op = Op::empty(); - op.kind = OperationType::Register; - op.r_target = r; - self.push_op(op); - } - fn x(&mut self, q: QubitId) { - let mut op = Op::empty(); - op.kind = OperationType::X; - op.q_target = q; - self.push_op(op); - } - fn cx(&mut self, ctrl: QubitId, tgt: QubitId) { - if ctrl == tgt { - panic!("invalid CX with aliased control/target {:?}", ctrl); - } - let mut op = Op::empty(); - op.kind = OperationType::CX; - op.q_control1 = ctrl; - op.q_target = tgt; - self.push_op(op); - } - #[track_caller] - fn ccx(&mut self, c1: QubitId, c2: QubitId, tgt: QubitId) { - if c1 == c2 { - if c1 != tgt { - self.cx(c1, tgt); - } - return; - } - if c1 == tgt || c2 == tgt { - panic!( - "invalid CCX with target aliased to a control: {:?}, {:?}, {:?}", - c1, c2, tgt - ); - } - let mut op = Op::empty(); - op.kind = OperationType::CCX; - op.q_control2 = c1; - op.q_control1 = c2; - op.q_target = tgt; - self.push_op(op); - } - fn cz(&mut self, a: QubitId, b: QubitId) { - if a == b { - let mut op = Op::empty(); - op.kind = OperationType::Z; - op.q_target = a; - self.push_op(op); - return; - } - let mut op = Op::empty(); - op.kind = OperationType::CZ; - op.q_control1 = a; - op.q_target = b; - self.push_op(op); - } - fn push_condition(&mut self, cond: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::PushCondition; - op.c_condition = cond; - self.push_op(op); - } - fn pop_condition(&mut self) { - let mut op = Op::empty(); - op.kind = OperationType::PopCondition; - self.push_op(op); - } - fn swap(&mut self, a: QubitId, b: QubitId) { - if a == b { - return; - } - let mut op = Op::empty(); - op.kind = OperationType::Swap; - op.q_control1 = a; - op.q_target = b; - self.push_op(op); - } - fn r(&mut self, q: QubitId) { - let mut op = Op::empty(); - op.kind = OperationType::R; - op.q_target = q; - self.push_op(op); - } - fn x_if(&mut self, q: QubitId, cond: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::X; - op.q_target = q; - op.c_condition = cond; - self.push_op(op); - } - - fn hmr(&mut self, q: QubitId, c: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::Hmr; - op.q_target = q; - op.c_target = c; - self.push_op(op); - } - - fn z_if(&mut self, q: QubitId, cond: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::Z; - op.q_target = q; - op.c_condition = cond; - self.push_op(op); - } - fn cz_if(&mut self, a: QubitId, b: QubitId, cond: BitId) { - if a == b { - self.z_if(a, cond); - return; - } - let mut op = Op::empty(); - op.kind = OperationType::CZ; - op.q_control1 = a; - op.q_target = b; - op.c_condition = cond; - self.push_op(op); - } - - fn bit_store0(&mut self, dst: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::BitStore0; - op.c_target = dst; - self.push_op(op); - } - - fn bit_store1(&mut self, dst: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::BitStore1; - op.c_target = dst; - self.push_op(op); - } - - fn bit_invert(&mut self, dst: BitId) { - let mut op = Op::empty(); - op.kind = OperationType::BitInvert; - op.c_target = dst; - self.push_op(op); - } - - fn bit_copy(&mut self, dst: BitId, a: BitId) { - self.bit_store0(dst); - self.push_condition(a); - self.bit_store1(dst); - self.pop_condition(); - } - - fn bit_xor_into(&mut self, dst: BitId, a: BitId) { - self.push_condition(a); - self.bit_invert(dst); - self.pop_condition(); - } - - fn bit_and_xor_into(&mut self, dst: BitId, a: BitId, b: BitId) { - self.push_condition(a); - self.push_condition(b); - self.bit_invert(dst); - self.pop_condition(); - self.pop_condition(); - } -} - -pub const N: usize = 256; - -pub const SECP256K1_P: U256 = U256::from_limbs([ - 0xFFFFFFFEFFFFFC2F, - 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, -]); - -pub const ONE_INV_DX3_AFFINE_PA_ENV: &str = "ONE_INV_DX3_AFFINE_PA"; -pub const ONE_INV_DX3_AFFINE_PA_BLOCKER: &str = - "ONE_INV_DX3_AFFINE_PA_BLOCKED: the dx^3 algebra gives Rx and Ry with \ - one inversion of w=dx^3, but a clean in-place Google-ABI circuit must \ - also uncompute w, dx^2, and the Kaliski input copy after tx/ty have been \ - overwritten by Rx/Ry. At that point dx is recoverable only by the inverse \ - affine add P=R-Q, whose denominator is Rx-Qx. That is a second inversion, \ - or else a retained 256-bit dx witness / dirty reset, so this path cannot \ - emit a clean one-inversion four-register PA."; - -fn direct_const_walks_enabled() -> bool { - std::env::var("KAL_DIRECT_CONST_WALKS").ok().as_deref() == Some("1") -} - -fn secp_direct_const_arith_enabled() -> bool { - std::env::var("SECP_DIRECT_CONST_ARITH").ok().as_deref() == Some("1") -} - -fn r84_lowq_enabled() -> bool { - std::env::var("R84_LOWQ").ok().as_deref() == Some("1") -} - -fn r84_lowq_cin_borrow_enabled() -> bool { - std::env::var("R84_LOWQ_CIN_BORROW").ok().as_deref() == Some("1") -} - -fn kal_vent_modadd_enabled() -> bool { - std::env::var("KAL_VENT_MODADD").ok().as_deref() == Some("1") -} - -fn kal_vent_halve_enabled() -> bool { - std::env::var("KAL_VENT_HALVE").ok().as_deref() == Some("1") -} - -const ALT_SEED_COUNT: usize = 5; -const ALT_SEED_COMMIT: usize = 24; -const ALT_SEED_SHOTS: usize = 4096; -const ALT_SEED_CLASSICAL_LIMIT: usize = 2; - -fn secp256k1_curve() -> WeierstrassEllipticCurve { - WeierstrassEllipticCurve { - modulus: U256::from_str_radix( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", - 16, - ) - .unwrap(), - a: U256::from(0), - b: U256::from(7), - gx: U256::from_str_radix( - "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", - 16, - ) - .unwrap(), - gy: U256::from_str_radix( - "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", - 16, - ) - .unwrap(), - order: U256::from_str_radix( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", - 16, - ) - .unwrap(), - } -} - -fn alt_seed_xof(ops: &[Op], tag: u64) -> sha3::Shake256Reader { - let mut hasher = Shake256::default(); - hasher.update(b"quantum_ecc-alt-seed-v1"); - hasher.update(&tag.to_le_bytes()); - hasher.update(&(ops.len() as u64).to_le_bytes()); - for op in ops { - hasher.update(&[op.kind as u8]); - hasher.update(&op.q_control2.0.to_le_bytes()); - hasher.update(&op.q_control1.0.to_le_bytes()); - hasher.update(&op.q_target.0.to_le_bytes()); - hasher.update(&op.c_target.0.to_le_bytes()); - hasher.update(&op.c_condition.0.to_le_bytes()); - hasher.update(&op.r_target.0.to_le_bytes()); - } - hasher.finalize_xof() -} - -fn run_alt_seed_checks(ops: &[Op]) { - let n_seeds = if std::env::var("ALT_SEED_COMMIT").is_ok() { - ALT_SEED_COMMIT - } else { - ALT_SEED_COUNT - }; - - let curve = secp256k1_curve(); - let (total_qubits, num_bits, _num_regs, regs) = analyze_ops(ops.iter()); - assert!(regs.len() == 4); - for (i, r) in regs.iter().enumerate() { - assert_eq!(r.len(), 256, "register {i} should be 256 wide"); - } - for q in ®s[0] { - assert!(matches!(q, QubitOrBit::Qubit(_))); - } - for q in ®s[1] { - assert!(matches!(q, QubitOrBit::Qubit(_))); - } - for q in ®s[2] { - assert!(matches!(q, QubitOrBit::Bit(_))); - } - for q in ®s[3] { - assert!(matches!(q, QubitOrBit::Bit(_))); - } - - eprintln!( - "=== alternate-seed diagnostic ({} seeds × {} shots, classical_limit={}, parallel) ===", - n_seeds, ALT_SEED_SHOTS, ALT_SEED_CLASSICAL_LIMIT, - ); - - let results: Vec<(u64, usize, usize, usize)> = std::thread::scope(|scope| { - let curve = &curve; - let regs = ®s; - let mut handles = Vec::with_capacity(n_seeds); - for tag_idx in 0..n_seeds { - let tag = (tag_idx as u64) + 1; - let handle = scope.spawn(move || { - const BATCH: usize = 64; - let mut xof = alt_seed_xof(ops, tag); - let mut targets = Vec::with_capacity(ALT_SEED_SHOTS); - let mut offsets = Vec::with_capacity(ALT_SEED_SHOTS); - let mut expected = Vec::with_capacity(ALT_SEED_SHOTS); - while targets.len() < ALT_SEED_SHOTS { - let mut rb = [[0u8; 32]; 2]; - xof.read(&mut rb[0]); - xof.read(&mut rb[1]); - let k1 = U256::from_le_bytes(rb[0]); - let k2 = U256::from_le_bytes(rb[1]); - let t = curve.mul(curve.gx, curve.gy, k1); - let o = curve.mul(curve.gx, curve.gy, k2); - if t.0 == o.0 { - continue; - } - if t.0.is_zero() && t.1.is_zero() { - continue; - } - if o.0.is_zero() && o.1.is_zero() { - continue; - } - let e = curve.add(t.0, t.1, o.0, o.1); - targets.push(t); - offsets.push(o); - expected.push(e); - } - - let mut sim = Simulator::new(total_qubits as usize, num_bits as usize, &mut xof); - let mut classical_failures = 0usize; - let mut phase_garbage_batches = 0usize; - let mut ancilla_garbage_batches = 0usize; - let num_batches = (ALT_SEED_SHOTS + BATCH - 1) / BATCH; - for batch in 0..num_batches { - let bs = BATCH.min(ALT_SEED_SHOTS - batch * BATCH); - let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; - sim.clear_for_shot(); - for shot in 0..bs { - let i = batch * BATCH + shot; - sim.set_register(®s[0], targets[i].0, shot); - sim.set_register(®s[1], targets[i].1, shot); - sim.set_register(®s[2], offsets[i].0, shot); - sim.set_register(®s[3], offsets[i].1, shot); - } - sim.apply_iter(ops.iter()); - for shot in 0..bs { - let i = batch * BATCH + shot; - let gx = sim.get_register(®s[0], shot); - let gy = sim.get_register(®s[1], shot); - if gx != expected[i].0 || gy != expected[i].1 { - classical_failures += 1; - } - } - let phase = sim.phase & cond_mask; - if phase != 0 { - phase_garbage_batches += 1; - } - for register in regs { - for qb in register { - if let QubitOrBit::Qubit(q) = *qb { - *sim.qubit_mut(q) = 0; - } - } - } - let mut garbage = false; - for q in 0..total_qubits { - if (sim.qubit(QubitId(q)) & cond_mask) != 0 { - garbage = true; - break; - } - } - if garbage { - ancilla_garbage_batches += 1; - } - } - ( - tag, - classical_failures, - phase_garbage_batches, - ancilla_garbage_batches, - ) - }); - handles.push(handle); - } - handles.into_iter().map(|h| h.join().unwrap()).collect() - }); - - let mut total_classical = 0usize; - let mut total_phase_batches = 0usize; - let mut total_ancilla_batches = 0usize; - for (tag, classical_failures, phase_garbage_batches, ancilla_garbage_batches) in &results { - total_classical += classical_failures; - total_phase_batches += phase_garbage_batches; - total_ancilla_batches += ancilla_garbage_batches; - eprintln!( - "ALT-SEED tag={} classical_mismatches={} phase_batches={} ancilla_batches={}", - tag, classical_failures, phase_garbage_batches, ancilla_garbage_batches, - ); - } - - println!("METRIC altseed_classical_total={}", total_classical); - println!("METRIC altseed_phase_batches_total={}", total_phase_batches); - println!( - "METRIC altseed_ancilla_batches_total={}", - total_ancilla_batches - ); - - let phase_limit: usize = std::env::var("ALT_SEED_PHASE_LIMIT") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(0); - assert!( - total_phase_batches <= phase_limit, - "ALT-SEED PHASE FAILURE: {} phase-garbage batches (limit {}) across {} seeds × {} shots", - total_phase_batches, - phase_limit, - n_seeds, - ALT_SEED_SHOTS, - ); - assert!( - total_ancilla_batches == 0, - "ALT-SEED ANCILLA FAILURE: {} ancilla-garbage batches across {} seeds × {} shots", - total_ancilla_batches, - n_seeds, - ALT_SEED_SHOTS, - ); - assert!( - total_classical <= ALT_SEED_CLASSICAL_LIMIT, - "ALT-SEED CLASSICAL FAILURE: {} classical mismatches exceeds limit {} across {} seeds × {} shots", - total_classical, - ALT_SEED_CLASSICAL_LIMIT, - n_seeds, - ALT_SEED_SHOTS, - ); -} - -#[cfg(test)] -mod d1_inplace_lowerer_tests { - use super::*; - - fn build_product_ops() -> Vec { - let mut b = B::new(); - let h = b.alloc_qubits(N); - b.declare_qubit_register(&h); - let n = b.alloc_qubits(N); - b.declare_qubit_register(&n); - d1_inplace_product_lowerer_with_kaliski_clean(&mut b, &h, &n, SECP256K1_P, 400); - b.ops - } - - fn build_quotient_ops() -> Vec { - let mut b = B::new(); - let h = b.alloc_qubits(N); - b.declare_qubit_register(&h); - let n = b.alloc_qubits(N); - b.declare_qubit_register(&n); - d1_inplace_quotient_lowerer_with_kaliski_clean(&mut b, &h, &n, SECP256K1_P, 400); - b.ops - } - - fn toffoli_count(ops: &[Op]) -> usize { - ops.iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count() - } - - fn assert_two_word_d1_abi(ops: &[Op]) -> (u32, u32, u32) { - let (qubits, bits, registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(registers, 2); - assert_eq!(regs.len(), 2); - for reg in regs { - assert_eq!(reg.len(), N); - assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); - } - (qubits, bits, registers) - } - - #[test] - fn d1_inplace_product_lowerer_component_stats_are_pinned() { - let ops = build_product_ops(); - let (qubits, bits, registers) = assert_two_word_d1_abi(&ops); - assert_eq!(qubits, 2475); - assert_eq!(bits, 1_141_762); - assert_eq!(registers, 2); - assert_eq!(toffoli_count(&ops), 1_919_786); - } - - #[test] - fn d1_inplace_quotient_lowerer_component_stats_are_pinned() { - let ops = build_quotient_ops(); - let (qubits, bits, registers) = assert_two_word_d1_abi(&ops); - assert_eq!(qubits, 2475); - assert_eq!(bits, 0); - assert_eq!(registers, 2); - assert_eq!(toffoli_count(&ops), 1_919_786); - assert!(ops - .iter() - .all(|op| op.c_condition == crate::circuit::NO_BIT)); - assert!(ops.iter().all(|op| { - !matches!( - op.kind, - OperationType::Hmr | OperationType::Neg | OperationType::R - ) - })); - } - - #[test] - fn round8_output_side_cleanup_hook_is_env_gated() { - let saved = std::env::var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP").ok(); - std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP"); - assert!(!round8_qtail_output_side_cleanup_enabled()); - std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP", "1"); - assert!(round8_qtail_output_side_cleanup_enabled()); - match saved { - Some(value) => std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP", value), - None => std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP"), - } - } - - #[test] - fn round8_output_side_cleanup_hook_fails_closed_until_emitter_exists() { - let mut b = B::new(); - let tx = b.alloc_qubits(N); - let ty = b.alloc_qubits(N); - let ox = b.alloc_bits(N); - let oy = b.alloc_bits(N); - let panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - round8_emit_output_side_cleanup_or_fail(&mut b, &tx, &ty, &ox, &oy, SECP256K1_P); - })) - .expect_err("output-side qtail hook must fail closed"); - let message = panic - .downcast_ref::() - .map(String::as_str) - .or_else(|| panic.downcast_ref::<&str>().copied()) - .expect("panic has message"); - assert!(message.contains("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP=1")); - assert!(message.contains("regular c=Rx-Qx inverse")); - assert!(message.contains("Round368 singular")); - assert!(message.contains("9024 Google")); - } - - #[test] - fn round8_output_side_regular_phase_repair_probe_is_separately_gated() { - let saved = std::env::var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR").ok(); - std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR"); - assert!(!round8_qtail_output_side_regular_phase_repair_enabled()); - std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR", "1"); - assert!(round8_qtail_output_side_regular_phase_repair_enabled()); - match saved { - Some(value) => { - std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR", value) - } - None => std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR"), - } - } - - #[test] - fn round8_qtail_round217_product_reuse_hook_is_env_gated() { - let saved = std::env::var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE").ok(); - std::env::remove_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE"); - assert!(!round8_qtail_round217_product_reuse_enabled()); - std::env::set_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE", "1"); - assert!(round8_qtail_round217_product_reuse_enabled()); - match saved { - Some(value) => std::env::set_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE", value), - None => std::env::remove_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE"), - } - } - - #[test] - fn round8_qtail_round217_product_reuse_hook_fails_closed_before_body() { - let plan = round218_b5_transport::round218_b5_source_live_product_lowerer_body_plan(); - assert!(!plan.body_emits_gates); - assert!(!plan.codegen_allowed_now); - assert_eq!( - plan.selected_route, - "round217_sampled_product_m2_contract_path" - ); - assert!(plan - .phase_blocks - .iter() - .any(|block| block.phase.contains("hash_history"))); - } - - #[test] - fn round218_source_live_product_lowerer_plan_rejects_full_source_alias() { - let plan = round218_b5_transport::round218_b5_source_live_product_lowerer_body_plan(); - assert!(!plan.body_emits_gates); - assert!(!plan.codegen_allowed_now); - assert!(plan - .phase_blocks - .iter() - .all(|block| !block.backend_primitive.contains("full_source_product"))); - assert!(plan - .missing_object - .contains("promotable no-history qtail/Round217 product splice")); - } -} - -fn set_default_env(name: &str, value: &str) { - if std::env::var_os(name).is_none() { - std::env::set_var(name, value); - } -} - -const Q1153_SECOND512_SUBMISSION_NONCE: &str = "193806910775884"; - -fn configure_q1153_second512_submission_defaults() { - set_default_env("DIALOG_TAIL_NONCE", Q1153_SECOND512_SUBMISSION_NONCE); - set_default_env("TLM_TARGET_Q", "1154"); - set_default_env("TLM_FOLD_CHUNK_ZERO_CIN", "1"); - set_default_env("TLM_FFG_MAX_G", "47"); - set_default_env("TLM_APPLY_ADD_SKIP_LASTK", "1"); - set_default_env("TLM_FOLD_TAIL_CINC", "1"); - set_default_env("TLM_CODEC_DIAMOND_MCX", "1"); - set_default_env("SINGLE_CCX_FANOUT_DISABLE", "0"); - - set_default_env("TLM_FFG_RELEASE_CY0_DURING_SUFFIX", "1"); - set_default_env("TLM_FFG_RELEASE_CY0_CALLS", "178,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,203,208,210,211,212,213,215,217,219,221,226,232,234,235,236,237,239"); - set_default_env("TLM_APPLY_FWD_CSWAP_SKIP_LAST", "2"); - set_default_env("TLM_COORD_RSUB_FUSED", "1"); - set_default_env("TLM_SQUARE_VENT_MARGIN", "0"); - set_default_env("TLM_COORD_ADD3X_TRUNC", "1"); - set_default_env("TLM_SQUARE_VENT_SHIFTED", "1"); - set_default_env("TLM_SQUARE_SHIFTED128_LOW_TAGS", "a,b,c"); - set_default_env("TLM_SQUARE_PEAK_CAP", "1154"); - set_default_env("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS", "1"); -} - -fn configure_ecdsafail_submission_route() { - set_default_env("DIALOG_GCD_VENTED_BODY_ODD_LOWBIT", "1"); - set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "19"); - set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1015"); - set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "18"); - set_default_env("DIALOG_GCD_FOLD_FREE_FIRST_HIGH_CARRY", "1"); - - set_default_env("DIALOG_GCD_ACTIVE_ITERATIONS", "258"); - set_default_env("DIALOG_GCD_APPLY_BOUNDARY_FREE_OWNED_DURING_REPLAY", "1"); - set_default_env("DIALOG_GCD_APPLY_BORROW_FUTURE_BOUNDARY_CARRIES", "1"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS", "20"); - set_default_env( - "DIALOG_GCD_APPLY_CHUNKED_F_CUTS", - "17,34,50,66,81,96,110,124,137,150,163,175,187,198,209,219,229,238,247", - ); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_MAX_BITS", "2"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_TARGET", "1168"); - set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "18"); - set_default_env("DIALOG_GCD_APPLY_IMPLICIT_HIGH_ZERO", "1"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_EXTRA", "3"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_MAP", "11:1,12:1,13:1"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_STEPS", "8,9,10"); - set_default_env( - "DIALOG_GCD_BODY_CARRY_BAND_TRIMS", - "0,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3", - ); - set_default_env("DIALOG_GCD_COMPARE_BITS", "46"); - set_default_env( - "DIALOG_GCD_COMPARE_STEP_BITS", - "181:48,194:48,199:48,202:48,207:48,212:48,216:48", - ); - set_default_env( - "DIALOG_GCD_FOLD_CARRY_TRUNC_STEP_WINDOWS", - "", - ); - set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "17"); - set_default_env("DIALOG_GCD_FOLD_FREED_TAIL", "1"); - set_default_env("DIALOG_GCD_FOLD_FREED_TAIL_ED", "1"); - set_default_env("DIALOG_GCD_FOLD_HOST_DERIVED_CONTROLS", "1"); - set_default_env("DIALOG_GCD_FOLD_HOST_E_TOP_CARRY", "1"); - set_default_env("DIALOG_GCD_FOLD_MAJ1", "1"); - set_default_env("DIALOG_GCD_FOLD_MAJ2", "1"); - set_default_env("DIALOG_GCD_FOLD_PARK_LOW_CARRIES", "15"); - set_default_env( - "DIALOG_GCD_FOLD_PARK_LOW_CARRIES_STEP_MAP", - "0:17,3:16,8:16,9:16,10:16,21:17,22:16,24:16,26:16,33:16,34:16,37:17,41:16,42:17,51:16,55:16,65:17,73:16,77:16,81:16,82:16,86:16,87:16,97:16,104:16,109:16,110:16,120:16,129:16,132:17,134:16,141:17,142:16,146:16,157:16,160:16,169:16,170:17,174:16,177:16,191:16,192:16,198:16,205:16,206:16,212:16,215:16,216:16,217:16,224:17,228:16", - ); - set_default_env("DIALOG_GCD_FOLD_STREAM_CONTROLS", "1"); - set_default_env("DIALOG_FUSE_C_FORM", "1"); - set_default_env("DIALOG_FUSE_X_RESTORE", "1"); - set_default_env("DIALOG_GCD_K2", "1"); - set_default_env("DIALOG_GCD_K5_CLEAN_BLOCK", "1"); - set_default_env("DIALOG_GCD_K5_FIXED_TAIL_APPLY", "0"); - set_default_env("DIALOG_GCD_K5_FREE_CLEAN_BLOCK_DURING_SHIFT", "1"); - set_default_env("DIALOG_GCD_K5_HEAD11_CODEC", "1"); - set_default_env("DIALOG_GCD_K5_HEAD11_STREAM_PAIR_APPLY", "1"); - set_default_env("DIALOG_GCD_K5_HEAD11_SPLIT_PAIR_SHIFT_APPLY", "1"); - set_default_env("DIALOG_GCD_K5_HEAD11_PAIR01_S2_PERMUTE_APPLY", "1"); - set_default_env( - "DIALOG_GCD_K5_HEAD11_PAIR23_S2_BORROW_PAIR01_APPLY", - "1", - ); - set_default_env("DIALOG_GCD_K5_PARTIAL_RAW_RELEASE", "8"); - set_default_env("DIALOG_GCD_K5_RELEASE_SCALE_BITS", "5"); - set_default_env("DIALOG_GCD_K5_STREAM_PAIR_APPLY", "1"); - set_default_env("DIALOG_GCD_K5_TAIL3_FIXED_LAST", "0"); - set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_CODEC", "1"); - set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_STREAM_APPLY", "1"); - set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_SPLIT_SLOT_APPLY", "1"); - set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_FINAL_S2_CONST_APPLY", "1"); - set_default_env("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH", "1"); - set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE", "1"); - set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN", "0"); - set_default_env("DIALOG_GCD_PERPOS_MAJ2", "1"); - set_default_env("DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL", "1"); - set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB", "0"); - set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH", "1"); - set_default_env("DIALOG_GCD_RUNWAY_PARTIAL_BLOCK", "1"); - set_default_env("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT", "1"); - set_default_env("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES", "1"); - set_default_env( - "DIALOG_GCD_SPECIAL_FOLD_CARRY_TRUNC_STEP_WINDOWS", - "10:19,11:19,21:20,63:19,74:19,100:19,107:19,110:19,118:19,135:19,136:19,137:19,188:20,204:19,227:20,241:19", - ); - set_default_env("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES", "16"); - set_default_env( - "DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES_STEP_MAP", - "", - ); - set_default_env("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH", "1"); - set_default_env( - "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", - "1:24,4:21,6:25,7:20,10:22,11:20,19:21,21:21,22:21,23:23,28:21,30:22,32:20,33:24,34:25,48:21,49:22,55:22,62:23,64:20,66:21,71:22,86:20,92:21,113:21,116:21,118:20,119:24,120:21,121:20,127:20,129:22,131:22,142:22,144:21,145:23,147:21,151:23,153:23,154:23,155:20,156:24,159:22,161:24,165:21,166:21,168:21,173:20,175:21,178:21,184:22,185:20,187:23,188:22,190:20,193:21,194:22,196:20,197:21,199:21,203:22,205:22,209:20,210:21,213:20,217:22,221:21,222:23,229:21,236:21,241:21", - ); - set_default_env( - "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", - "3:21,5:21,10:23,11:22,14:22,17:20,27:22,33:20,34:22,38:21,42:22,47:21,50:22,51:21,53:20,54:21,58:21,60:21,65:21,67:23,68:25,73:20,74:20,75:23,77:21,78:20,84:21,89:23,91:22,95:22,98:26,103:21,109:22,110:22,114:22,118:22,127:26,135:20,136:20,137:22,143:21,149:21,152:20,154:26,155:20,156:22,157:20,158:26,166:20,178:20,181:20,186:24,188:25,191:21,194:20,198:20,200:21,201:21,202:23,203:23,204:22,212:25,213:20,214:22,221:20,223:21,228:21,231:23,243:21,246:20", - ); - set_default_env("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM", "0"); - set_default_env("DIALOG_GCD_WIDTH_MARGIN", "10"); - set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1017"); - set_default_env("LUD_EXTRA_FOLD_VENTS", "1"); - set_default_env("LUD_EXTRA_FOLD_MIN_G", "24"); - set_default_env("KAL_DOUBLE_CARRY_TRUNC_W", "19"); - set_default_env("KAL_FOLD_CARRY_TRUNC_W", "18"); - set_default_env("SQUARE_ROW_MAX_SEG", "141"); - set_default_env("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS", "18"); - set_default_env( - "SQUARE_ROW_WINDOW_CLEAN_ROW_BITS", - "2:20,11:20,12:20,13:21,16:22,19:20,20:21,21:20,26:21,29:21,32:21,37:21,44:22,46:20,53:21,56:20,64:20,70:20,75:20,78:20,87:20", - ); - set_default_env( - "SQUARE_ROW_WINDOW_CLEAN_SITE_BITS", - "1:0:f:19,3:0:r:21,9:0:f:22,10:0:r:21,13:0:r:22,14:0:r:20,15:0:r:19,17:0:r:20,26:0:f:22,36:0:f:20,38:0:f:20,38:0:r:20,39:0:r:19,40:0:r:22,41:0:r:19,42:0:r:20,43:0:r:19,45:0:r:19,47:0:f:22,47:0:r:19,48:0:r:20,50:0:f:22,50:0:r:22,51:0:f:22,54:0:f:19,57:0:r:19,59:0:f:19,60:0:f:19,62:0:f:22,62:0:r:21,63:0:f:20,65:0:f:19,66:0:f:21,66:0:r:21,67:0:f:19,68:0:r:21,71:0:r:20,72:0:f:21,73:0:r:21,74:0:r:19,76:0:r:21,79:0:r:20,81:0:f:20,83:0:r:22,89:0:r:19,90:0:r:21,91:0:f:21,92:0:r:21,95:0:r:20,97:0:r:21,102:0:f:20,103:0:r:19,104:0:r:19,107:0:f:20,109:0:f:21,110:0:f:19,110:0:r:20", - ); - set_default_env("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR", "1"); - - set_default_env("SKIP_ALT_SEED_CHECKS", "1"); - set_default_env("DIALOG_GCD_COMPRESSED_SIDECAR_LOG", "1"); - - set_default_env("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS", "21"); - set_default_env("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR", "1"); - set_default_env("ROUND84_KEEP_QUOTIENT_PRODUCT", "1"); - set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "17"); - set_default_env("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT", "1"); - set_default_env("DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE", "1"); - set_default_env("DIALOG_GCD_HOST_REVERSE_RAW_BLOCK", "1"); - set_default_env("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY", "1"); - set_default_env("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY_BLOCKS", "999"); - set_default_env("DIALOG_GCD_COMPOSITE_SCRATCH", "1"); - - set_default_env("DIALOG_GCD_BORROW_CURRENT_BLOCK", "1"); - - set_default_env("DIALOG_GCD_CTRL_BODY_VENTED", "1"); - set_default_env("DIALOG_GCD_APPLY_REPLAY_SWAP_HOST", "1"); - set_default_env("SQUARE_SELFHOST_SAFE_LANE_REUSE", "1"); - set_default_env("SQUARE_SELFHOST_GATE_SUFFIX_CARRIES", "0"); - - set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE", "1"); - - set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN", "0"); - - set_default_env("KAL_DOUBLE_CARRY_TRUNC_W", "19"); - - set_default_env("KAL_FOLD_CARRY_TRUNC_W", "18"); - set_default_env("DIALOG_GCD_ROUND763_DEDUP", "1"); - set_default_env("DIALOG_GCD_ROUND763_COMPRESS_LEVER", "1"); - set_default_env("DIALOG_GCD_MEASURED_UNDERFLOW_GATE", "1"); - - set_default_env("DIALOG_GCD_COMPARE_BITS", "46"); - - set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "18"); - set_default_env("DIALOG_GCD_APPLY_BOUNDARY_CONDITIONAL_REPLAY", "1"); - set_default_env("DIALOG_GCD_SELECTED_BODY_STREAM_SUFFIX_MAP", "3:2,4:3,5:5,6:6,7:7,8:5,9:7,10:5,11:7,12:6,13:7,14:5,15:6,16:3,17:5,18:1,19:3,21:1"); - - set_default_env("DIALOG_GCD_REVERSE_BRANCH_CONDITIONAL_REPLAY", "1"); - set_default_env("DIALOG_GCD_SPECIAL_CLEAN_CONDITIONAL_REPLAY", "1"); - set_default_env("MOD_FAST_FLAG_CONDITIONAL_REPLAY", "1"); - set_default_env("DIALOG_GCD_RAW_PA", "1"); - set_default_env("DIALOG_GCD_K2", "1"); - - set_default_env("DIALOG_GCD_APPLY_FUSED_FOLD", "1"); - - set_default_env("DIALOG_GCD_K2_PAIR_COMPRESS", "1"); - - set_default_env("DIALOG_GCD_ACTIVE_ITERATIONS", "258"); - set_default_env("DIALOG_GCD_PERPOS_MAJ2", "1"); - set_default_env("DIALOG_GCD_FUSED_HCLEAR_MEASURED", "1"); - set_default_env("DIALOG_GCD_FUSED_DCLEAR_MEASURED", "1"); - set_default_env("DIALOG_GCD_FUSED_HALVE_EDCLEAR_MEASURED", "1"); - set_default_env("DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE", "1"); - set_default_env("DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL", "1"); - set_default_env("DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE", "1"); - set_default_env("DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB", "1"); - set_default_env("DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD", "1"); - set_default_env("DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN", "1"); - - set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB", "0"); - set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH", "1"); - set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES", "1"); - - set_default_env("ROUND84_XTAIL_KARATSUBA", "0"); - - set_default_env("KARA_SOL_DBL_FAST", "1"); - - set_default_env("KARA_FREE_Z1_TOPBIT", "1"); - - set_default_env("DIALOG_GCD_WIDTH_MARGIN", "10"); - - set_default_env("DIALOG_GCD_MEASURED_APPLY_SUB", "1"); - - set_default_env("DIALOG_GCD_HOST_GATED", "1"); - set_default_env("DIALOG_GCD_APPLY_WINDOW_BLOCKS", "2"); - - set_default_env("ROUND84_XTAIL_BORROW_CARRIES", "1"); - - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS", "16"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM4", "0"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM5", "0"); - - set_default_env("KARA_Z02_LOWQ", "1"); - set_default_env("KARA_Z2_SELFHOST", "1"); - set_default_env("KARA_SOL_MOD_VENT", "1"); - - set_default_env("DIALOG_GCD_BRANCH_BITS_HOST_COMPARATOR", "1"); - - set_default_env("DIALOG_GCD_BODY_HOST_CIN", "1"); - set_default_env("DIALOG_GCD_LATE_BORROW_UV_HIGH", "1"); - - set_default_env("DIALOG_GCD_BODY_CARRY_BAND_TRIMS", "0,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3"); - set_default_env("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM", "0"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_STEPS", "8,9,10"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_EXTRA", "3"); - set_default_env("DIALOG_GCD_BINDER_NOTCH_MAP", "11:1,12:1,13:1"); - set_default_env( - "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", - "113:21,131:21,142:22,187:23,205:22,210:21", - ); - set_default_env( - "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", - "42:22,91:22,118:22,149:21", - ); - set_default_env("DIALOG_GCD_FUSED_OVFCLEAR_MEASURED", "1"); - - set_default_env("DIALOG_GCD_APPLY_FINAL_LOWQ", "0"); - - set_default_env("R84_LOWQ", "1"); - set_default_env("R84_LOWQ_CIN_BORROW", "1"); - set_default_env("R84_QPROD_NAF", "1"); - - set_default_env("ROUND84_INPLACE_SOLINAS_FOLD", "1"); - set_default_env("ROUND84_INPLACE_QUOTIENT_CARRY_TRUNC_W", "21"); - - set_default_env("SQUARE_ROW_MAX_SEG", "176"); - set_default_env("DIALOG_GCD_K5_CLEAN_BLOCK", "1"); - set_default_env("DIALOG_GCD_FOLD_PARK_LOW_CARRIES", "1"); - set_default_env("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES", "1"); - set_default_env("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK", "1"); - set_default_env("DIALOG_GCD_FOLD_FREED_TAIL", "1"); - set_default_env("DIALOG_GCD_BORROW_CURRENT_S2", "1"); - set_default_env("DIALOG_GCD_BORROW_ZERO_RAW_FUTURE", "1"); - set_default_env("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT", "1"); - set_default_env("DIALOG_GCD_APPLY_BOUNDARY_SPLIT", "100"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT", "50"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT2", "100"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT3", "150"); - set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT4", "190"); - - set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1017"); - - set_default_env("DIALOG_REROLL", "4269"); - set_default_env("DIALOG_POST_SUB_REROLL", "503292"); - - set_default_env("DIALOG_GCD_SELECTED_BODY_NOCIN", "1"); - - set_default_env("ROUND84_FOLD_FAST_ADD", "0"); - set_default_env("DIALOG_GCD_FOLD_MAJ2", "1"); - set_default_env("DIALOG_GCD_FOLD_MAJ1", "1"); - set_default_env("DIALOG_GCD_APPLY_FINAL_TOPCLEAN", "0"); - set_default_env("ROUND84_QPROD_VENT_PAD", "1"); - set_default_env("DIALOG_GCD_FOLD_FREED_TAIL_ED", "1"); - set_default_env("DIALOG_GCD_APPLY_FINAL_WINDOWED_FAST_BLOCKS", "0"); - - set_default_env("DIALOG_GCD_FUSED_BRANCH_BITS", "1"); - - set_default_env("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH", "1"); -} - -pub fn build_builder() -> B { - configure_ecdsafail_submission_route(); - - let mut builder = if std::env::var("POINT_ADD_COUNT_ONLY").ok().as_deref() == Some("1") { - B::new_count_only() - } else { - B::new() - }; - let b = &mut builder; - - let tx = b.alloc_qubits(N); - b.declare_qubit_register(&tx); - - let ty = b.alloc_qubits(N); - b.declare_qubit_register(&ty); - - let ox = b.alloc_bits(N); - b.declare_bit_register(&ox); - - let oy = b.alloc_bits(N); - b.declare_bit_register(&oy); - - if let Some(k) = std::env::var("DIALOG_REROLL") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&k| k > 0) - { - b.set_phase("dialog_reroll"); - for _ in 0..k { - b.x(tx[0]); - b.x(tx[0]); - } - } - - let p = SECP256K1_P; - - mod_sub_qb(b, &tx, &ox, p); - mod_sub_qb(b, &ty, &oy, p); - if let Some(k) = std::env::var("DIALOG_POST_SUB_REROLL") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&k| k > 0) - { - b.set_phase("dialog_post_sub_reroll"); - for _ in 0..k { - b.x(tx[1]); - b.x(tx[1]); - } - } - - emit_dialog_gcd_raw_pa(b, &tx, &ty, &ox, &oy, p); - - if !b.count_only && std::env::var("SKIP_ALT_SEED_CHECKS").ok().as_deref() != Some("1") { - run_alt_seed_checks(&b.ops); - } - - if !b.count_only && std::env::var("TRACE_PEAK").is_ok() { - eprintln!( - "DEBUG peak_qubits={} at phase='{}' ops_idx={} total_ops={}", - b.peak_qubits, - b.peak_phase, - b.peak_ops_idx, - b.ops.len() - ); - let pk = b.peak_qubits; - let mut uniq: std::collections::BTreeMap<&'static str, (u32, usize)> = - std::collections::BTreeMap::new(); - for (a, ph, op) in &b.peak_log { - if *a + 5 >= pk { - let entry = uniq.entry(ph).or_insert((*a, *op)); - if *a > entry.0 { - *entry = (*a, *op); - } - } - } - for (ph, (a, op)) in uniq.iter() { - eprintln!("DEBUG near_peak active={} phase='{}' ops_idx={}", a, ph, op); - } - } - - if !b.count_only && std::env::var("DUMP_PHASE_BOUNDS").is_ok() { - for (op_idx, phase) in &b.phase_transitions { - eprintln!("PHASE_BOUND op_idx={op_idx} phase={phase}"); - } - } - - if !b.count_only && std::env::var("TRACE_PHASES").is_ok() { - - let trans = &b.phase_transitions; - let n_ops = b.ops.len(); - - let mut agg: std::collections::BTreeMap<&'static str, (u64, u64, u64)> = - std::collections::BTreeMap::new(); - - let mut regions: Vec<(&'static str, usize, u64, u64, u64)> = Vec::new(); - for i in 0..trans.len() { - let start = trans[i].0; - let end = if i + 1 < trans.len() { - trans[i + 1].0 - } else { - n_ops - }; - let phase = trans[i].1; - let mut tof: u64 = 0; - let mut cli: u64 = 0; - let mut other: u64 = 0; - for op in &b.ops[start..end] { - match op.kind { - OperationType::CCX | OperationType::CCZ => tof += 1, - OperationType::CX - | OperationType::CZ - | OperationType::Swap - | OperationType::Hmr - | OperationType::R => cli += 1, - _ => other += 1, - } - } - regions.push((phase, start, tof, cli, other)); - let e = agg.entry(phase).or_insert((0, 0, 0)); - e.0 += tof; - e.1 += cli; - e.2 += other; - } - let total_tof: u64 = agg.values().map(|v| v.0).sum(); - eprintln!("=== per-phase emitted Toffoli (classical view; executed-shot stats are in harness) ==="); - eprintln!( - "{:<40} {:>12} {:>12} {:>6}", - "phase", "ccx", "cliff", "%tof" - ); - let mut v: Vec<_> = agg.iter().collect(); - v.sort_by(|a, b| b.1 .0.cmp(&a.1 .0)); - for (ph, (t, c, _o)) in v { - let pct = if total_tof > 0 { - (*t as f64) * 100.0 / (total_tof as f64) - } else { - 0.0 - }; - eprintln!("{:<40} {:>12} {:>12} {:>5.1}%", ph, t, c, pct); - } - eprintln!("total_ccx_emitted={} total_ops={}", total_tof, n_ops); - if std::env::var("TRACE_PHASES_VERBOSE").is_ok() { - eprintln!("--- per-region (ordered) ---"); - for (ph, start, tof, cli, _o) in ®ions { - if *tof == 0 && *cli == 0 { - continue; - } - eprintln!("@{:<10} {:<40} ccx={} cli={}", start, ph, tof, cli); - } - } - } - - if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { - b.close_phase_active_region(); - eprintln!("=== per-phase active qubit maxima ==="); - eprintln!("{:<48} {:>12}", "phase", "active_q"); - let mut v: Vec<_> = b.phase_active_max.iter().collect(); - v.sort_by(|a, b| b.1.cmp(a.1).then_with(|| a.0.cmp(b.0))); - let top_n = std::env::var("TRACE_PHASE_ACTIVE_TOP") - .ok() - .and_then(|s| s.parse::().ok()); - let mut printed = 0usize; - for (phase, active) in v { - if top_n.is_some_and(|limit| printed >= limit) { - break; - } - eprintln!("{:<48} {:>12}", phase, active); - printed += 1; - } - if std::env::var("TRACE_PHASE_ACTIVE_REGIONS").is_ok() { - eprintln!("--- per-region active qubit maxima (ordered) ---"); - for (end, phase, active) in &b.phase_active_regions { - eprintln!("@{:<10} {:<48} active_q={}", end, phase, active); - } - } - } - - if let Some(nonce) = std::env::var("DIALOG_TAIL_NONCE") - .ok() - .and_then(|s| s.parse::().ok()) - { - const NONCE_BITS: u32 = 48; - b.set_phase("dialog_tail_nonce"); - for i in 0..NONCE_BITS { - let q = if (nonce >> i) & 1 == 1 { tx[1] } else { tx[0] }; - b.x(q); - b.x(q); - } - } - - builder -} - -/// M-60 (C2b): remove the census-identified dead CCX gates (dead_t10 set) from the -/// post-fanout op stream. Every dropped index MUST be a CCX in this build (self-check); -/// if a build ever shifts so an index no longer points at a CCX we abort loudly rather -/// than emit a corrupt circuit. This is the source-side port of the grinder's post-build -/// filter, now inside `build()` so it survives an `src/point_add`-only submission. -/// Bit-exact: the removed gates never fire for any valid curve-point input. -/// Deep-strip: remove CCX gates verified never-firing over 1e8 inputs. -/// Applied as the FINAL pass because the index list was derived from the final -/// emitted stream. -fn apply_d2_deep_strip(ops: Vec) -> Vec { - use std::collections::HashSet; - let drop: HashSet = d2_deep_strip::D2_DEEP_STRIP.iter().copied().collect(); - ops.into_iter().enumerate().filter(|(i, _)| !drop.contains(i)).map(|(_, o)| o).collect() -} - -/// Identity-keyed deep strip. Instead of positional indices (which any op-stream edit -/// invalidates), each census-dead CCX/CCZ is keyed by its operand tuple -/// (kind, q_control2, q_control1, q_target, c_condition) plus the k-th-occurrence ordinal -/// of that tuple in stream order. Derived once from a 1e8 fire-census; re-applies to any -/// edited stream that does not relabel the dead region, with no re-census. -/// -/// Two keyed transforms share the single ordinal pass: -/// DEAD_KEYS -- the gate never fires on any reachable input; delete it. -/// DOWNGRADE_KEYS -- the gate fires, but one control is redundant *as a value*: -/// either it is 1 on every shot the classical condition admits, or -/// the two controls are always equal. Either way CCX(c2,c1,t) -/// reduces exactly to CX(surviving,t) and CCZ to CZ, which the -/// cost model does not charge for. Zero qubits moved. -/// Neither transform touches branch selection, `step()` consumption or call counts: -/// this runs on the finished `Vec`, after every emission decision has been made. -fn apply_deep_strip_identity(ops: Vec) -> Vec { - use std::collections::HashMap; - type Tup = (u8, u64, u64, u64, u64); - - // Pass 1: how many times does each operand tuple occur in THIS stream? - // The ordinal in a key is only meaningful if that occupancy still matches - // the stream the census was taken on. If an unrelated edit adds or removes - // a gate with the same operands, every later ordinal for that tuple slides - // and the key silently names a different, live gate -- which deletes or - // downgrades a load-bearing Toffoli and corrupts the circuit. Measured - // consequence when this happened for real: 7535/9024 classical mismatches. - // So the census-time occupancy travels with every key as a tripwire, and a - // key whose tuple has moved is DISCARDED rather than applied. - let mut occ: HashMap = HashMap::new(); - for op in &ops { - let kb = op.kind as u8; - if kb == 13 || kb == 14 { - *occ.entry((kb, op.q_control2.0, op.q_control1.0, op.q_target.0, op.c_condition.0)) - .or_insert(0) += 1; - } - } - let mut stale = 0usize; - let mut dead: HashMap<(Tup, u32), ()> = HashMap::new(); - for &(k, c2, c1, t, cc, o, tot) in deep_strip_keys::DEAD_KEYS { - let tup = (k, c2, c1, t, cc); - if occ.get(&tup).copied() == Some(tot) { - dead.insert(((tup), o), ()); - } else { - stale += 1; - } - } - let mut down: HashMap<(Tup, u32), u8> = HashMap::new(); - for &(k, c2, c1, t, cc, o, tot, act) in deep_strip_keys::DOWNGRADE_KEYS { - let tup = (k, c2, c1, t, cc); - if occ.get(&tup).copied() == Some(tot) { - down.insert(((tup), o), act); - } else { - stale += 1; - } - } - if stale > 0 { - eprintln!( - " [deep-strip-identity] WARNING: {} keys discarded -- their operand tuple's \ - occupancy changed since the census, so their ordinals no longer address the \ - censused gate. Re-run the census against this op stream to recover them.", - stale - ); - } - if dead.is_empty() && down.is_empty() { - return ops; - } - - // Pass 2: apply, assigning ordinals in the same stream order the census used. - let mut ord: HashMap = HashMap::new(); - let mut out = Vec::with_capacity(ops.len()); - let mut removed = 0usize; - let mut downgraded = 0usize; - for op in ops { - let kb = op.kind as u8; // CCX=13, CCZ=14 in the serialized stream - if kb == 13 || kb == 14 { - let tup = (kb, op.q_control2.0, op.q_control1.0, op.q_target.0, op.c_condition.0); - let o = ord.entry(tup).or_insert(0); - let key = (tup, *o); - *o += 1; - if dead.contains_key(&key) { - removed += 1; - continue; - } - if let Some(&act) = down.get(&key) { - let mut nop = op; - nop.kind = if kb == 13 { OperationType::CX } else { OperationType::CZ }; - // act==1: q_control1 is the redundant one, q_control2 survives. - // act==2: q_control2 is redundant (implied by q_control1). - if act == 1 { - nop.q_control1 = op.q_control2; - } - nop.q_control2 = crate::circuit::NO_QUBIT; - nop.validate(); - downgraded += 1; - out.push(nop); - continue; - } - } - out.push(op); - } - eprintln!( - "[deep-strip-identity] removed {} / {} dead; downgraded {} / {} to CX/CZ; {} stale keys skipped", - removed, - deep_strip_keys::DEAD_KEYS.len(), - downgraded, - deep_strip_keys::DOWNGRADE_KEYS.len(), - stale - ); - out -} - -/// Rewrite the 96-op identity tail to encode the ground nonce. Only q_target -/// changes (X;X pairs stay identities), so circuit function is untouched; the -/// Fiat-Shamir seed is what moves. -fn apply_tail_nonce(mut ops: Vec, nonce: u64) -> Vec { - let n = ops.len(); - assert!(n >= 96, "op stream too short for nonce tail"); - let start = n - 96; - for i in 0..96 { - assert!(ops[start + i].kind == OperationType::X, "tail op {} is not an X", start + i); - } - for b in 0..48 { - let t = if (nonce >> b) & 1 == 1 { QubitId(1) } else { QubitId(0) }; - ops[start + 2 * b].q_target = t; - ops[start + 2 * b + 1].q_target = t; - } - ops -} - -fn apply_m60_dead_t10(ops: Vec) -> Vec { - use std::collections::HashSet; - if std::env::var("M60_DISABLE").ok().as_deref() == Some("1") { - eprintln!(" [M-60] disabled -> emitting C1 (unfiltered)"); - return ops; - } - let drop: HashSet = m60_dead_t10::M60_DEAD_T10.iter().copied().collect(); - for &i in &drop { - let is_ccx = ops.get(i).map(|o| o.kind == OperationType::CCX).unwrap_or(false); - assert!( - is_ccx, - "[M-60] dead-set index {i} is not a CCX in this build (found {:?}); skip-set \ - misaligned with this nonce/config -- aborting to avoid a corrupt circuit", - ops.get(i).map(|o| o.kind) - ); - } - let n_before = ops.len(); - let kept: Vec = ops - .into_iter() - .enumerate() - .filter_map(|(i, op)| if drop.contains(&i) { None } else { Some(op) }) - .collect(); - eprintln!( - " [M-60] removed {} dead CCX (self-checked) -> {} ops (C2b circuit)", - n_before - kept.len(), - kept.len() - ); - kept -} - -/// W018 / W044: delegate to the straddle-aware net-restore CCZ self-inverse matcher -/// (`constprop::ccz_straddle_cancel`), which runs on the FINAL post-`apply_m60_dead_t10` -/// stream so the dead_t10 absolute-index skip-set stays valid. Bit-exact in value AND -/// phase by construction (a proven CCZ.U.CCZ = U identity when U net-restores the triple). -/// Toggle off for the A/B differential with `TLM_CCZ_SELF_INVERSE_CANCEL=0`. -fn ccz_self_inverse_cancel(ops: Vec) -> Vec { - if std::env::var("TLM_CCZ_SELF_INVERSE_CANCEL").ok().as_deref() == Some("0") { - return ops; - } - trailmix_ludicrous::constprop::ccz_straddle_cancel(ops) -} - -// Retained-but-unused conservative (no-straddle) prototype, superseded by the -// straddle-aware matcher above. Kept for reference; not on any code path. -#[allow(dead_code, unreachable_code, unused)] -fn ccz_self_inverse_cancel_conservative(ops: Vec) -> Vec { - const NEVER: usize = usize::MAX; - - // Size the write-timeline tables from the max qubit / condition-bit id referenced. - let mut max_q: u64 = 0; - let mut max_b: u64 = 0; - for op in &ops { - for q in [op.q_control1.0, op.q_control2.0, op.q_target.0] { - if q != u64::MAX && q > max_q { - max_q = q; - } - } - for b in [op.c_condition.0, op.c_target.0] { - if b != u64::MAX && b > max_b { - max_b = b; - } - } - } - let num_q = max_q as usize + 1; - let num_b = max_b as usize + 1; - - let mut wlast_q = vec![NEVER; num_q]; // last basis-changing WRITE index per qubit - let mut wlast_b = vec![NEVER; num_b]; // last WRITE index per condition bit - - let mut cond_epoch: u64 = 0; - let mut cond_stack: Vec = Vec::new(); - - struct PendCcz { - idx: usize, - cb: u64, - epoch: u64, - } - let mut pending: std::collections::HashMap<(u64, u64, u64), PendCcz> = - std::collections::HashMap::new(); - let mut killed = vec![false; ops.len()]; - // Diagnostics: how many CCZ repeat a triple at all (upper bound on any matcher's - // pairable population), and how many same-triple candidates the clean-support - // predicate rejected (a large gap here would mean a straddle matcher could help). - let mut seen_triples: std::collections::HashSet<(u64, u64, u64)> = - std::collections::HashSet::new(); - let mut repeat_triple_ccz: usize = 0; - let mut rejected_not_clean: usize = 0; - let mut total_ccz: usize = 0; - - let touched_after = |s: usize, p: usize| s != NEVER && s > p; - let set_w = |tbl: &mut Vec, id: u64, i: usize| { - if (id as usize) < tbl.len() { - tbl[id as usize] = i; - } - }; - - for (i, op) in ops.iter().enumerate() { - match op.kind { - OperationType::PushCondition => { - cond_epoch += 1; - cond_stack.push(op.c_condition.0); - } - OperationType::PopCondition => { - cond_epoch += 1; - cond_stack.pop(); - } - OperationType::CCZ => { - let mut tri = [op.q_control1.0, op.q_control2.0, op.q_target.0]; - tri.sort_unstable(); - // Skip malformed/degenerate triples (a real CCZ has 3 distinct live qubits). - if tri[2] != u64::MAX && tri[0] != tri[1] && tri[1] != tri[2] { - let key = (tri[0], tri[1], tri[2]); - let cb = op.c_condition.0; - total_ccz += 1; - if !seen_triples.insert(key) { - repeat_triple_ccz += 1; - } - let mut cancelled = false; - let mut matched_pending = false; - if let Some(p) = pending.get(&key) { - matched_pending = true; - let same_cond = p.cb == cb && p.epoch == cond_epoch; - let qs_clean = !touched_after(wlast_q[tri[0] as usize], p.idx) - && !touched_after(wlast_q[tri[1] as usize], p.idx) - && !touched_after(wlast_q[tri[2] as usize], p.idx); - let cond_clean = - cb == u64::MAX || !touched_after(wlast_b[cb as usize], p.idx); - let stack_clean = cond_stack.iter().all(|&sb| { - sb == u64::MAX || !touched_after(wlast_b[sb as usize], p.idx) - }); - if same_cond && qs_clean && cond_clean && stack_clean { - killed[p.idx] = true; - killed[i] = true; - cancelled = true; - } - } - if matched_pending && !cancelled { - rejected_not_clean += 1; - } - if cancelled { - pending.remove(&key); - } else { - pending.insert( - key, - PendCcz { - idx: i, - cb, - epoch: cond_epoch, - }, - ); - } - } - // CCZ is diagonal: it writes nothing, so no wlast update. - } - OperationType::CCX - | OperationType::CX - | OperationType::X - | OperationType::R => { - set_w(&mut wlast_q, op.q_target.0, i); - } - OperationType::Swap => { - set_w(&mut wlast_q, op.q_control1.0, i); - set_w(&mut wlast_q, op.q_target.0, i); - } - OperationType::Hmr => { - set_w(&mut wlast_q, op.q_target.0, i); - set_w(&mut wlast_b, op.c_target.0, i); - } - OperationType::BitInvert - | OperationType::BitStore0 - | OperationType::BitStore1 => { - set_w(&mut wlast_b, op.c_target.0, i); - } - OperationType::CZ - | OperationType::Z - | OperationType::Neg - | OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - } - } - - let n_before = ops.len(); - let kept: Vec = ops - .into_iter() - .enumerate() - .filter_map(|(i, op)| if killed[i] { None } else { Some(op) }) - .collect(); - let removed = n_before - kept.len(); - eprintln!( - " [W018 CCZ] cancelled {} CCZ ({} self-inverse pairs) -> {} ops", - removed, - removed / 2, - kept.len() - ); - eprintln!( - " [W018 CCZ] diag: total_ccz={} repeat_triple_ccz={} rejected_not_clean={}", - total_ccz, repeat_triple_ccz, rejected_not_clean - ); - kept -} - -pub fn build() -> Vec { - // M-60 (C2b): bake the dead_t10 winning Fiat-Shamir nonce so the challenge harness - // reproduces the validated winner. Forced (not set_default) to win over the C1 default. - // The nonce only appends identity X-pairs at the tail; the dead-CCX skip-set applied - // post-fanout (apply_m60_dead_t10) is nonce-invariant. - std::env::set_var("DIALOG_TAIL_NONCE", "9000624727621"); - // --- submission-4: stacked bit-exact wins (all ε=0) --- - std::env::set_var("TLM_KG_INC_VENT", "1"); // E284: KG-inc measurement vent (-198 CCX) - std::env::set_var("W1155_FWD_EQ_REV", "1"); // W1155: fwd cswap dead := rev predicate (-504) - std::env::set_var("TLM_SQUARE_FROM_ZERO", "1"); // M023: from-zero adder specialization (-1522) - // E208 (codec mcx_clean_k), E275 (2nd fanout pass), W1077 (dead-carry band), E251 (gcd dead - // ranges) are hard edits / default-on and need no flag here. - // --- GAP_J2 comparator narrowing (delta=2 over divsteps i<200) --- - // Slack is concentrated in the first ~200 divsteps; i>=200 has none. - // SUB4_NO_GAP=1 disables it (used to isolate the bit-exact wins for verification). - if std::env::var("SUB4_NO_GAP").ok().as_deref() != Some("1") { - std::env::set_var("TLM_GAP_J2_TRUNC_ONLY", "1"); - std::env::set_var("TLM_GAP_J2_DELTA", "2"); - std::env::set_var("TLM_GAP_J2_LO", "0"); - std::env::set_var("TLM_GAP_J2_HI", "200"); - } - // M-60's baked index list is derived against a different op stream and would - // misalign here; the d2 deep-strip below supersedes it. - std::env::set_var("M60_DISABLE", "1"); - configure_q1153_second512_submission_defaults(); - - if std::env::var("TLM_SQ_SELFTEST").ok().as_deref() == Some("1") { - arith::square_addsub_selftest::run(); - if std::env::var("TLM_SQ_SELFTEST_ONLY").ok().as_deref() == Some("1") { - std::process::exit(0); - } - } - - if std::env::var("DIALOG_GCD_K5_HEAD11_SELFTEST").is_ok() { - match dialog_gcd_k5_head11_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_HEAD11_SELFTEST: PASS (2048-word head codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_HEAD11_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_HEAD11_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL3_SELFTEST").is_ok() { - match dialog_gcd_k5_tail3_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL3_SELFTEST: PASS (two-step pair codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL3_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL3_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST").is_ok() { - match dialog_gcd_k5_tail3_top32_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST: PASS (32-word weighted codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST").is_ok() { - match dialog_gcd_k5_tail6_graph9_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST: PASS (75-word graph codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST").is_ok() { - match dialog_gcd_k5_tail6_graph_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST: PASS (32-word graph codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL7_SELFTEST").is_ok() { - match dialog_gcd_k5_tail7_codec_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL7_SELFTEST: PASS (20-word codec reversible and phase clean)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL7_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL7_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST").is_ok() { - match dialog_gcd_k5_tail7_fixed_apply_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST: PASS (fixed digit-4 apply matches fused apply)" - ), - Err(e) => panic!("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("SQUARE_WINDOW_SELFTEST").is_ok() { - match square_window_selftest() { - Ok(()) => eprintln!("SQUARE_WINDOW_SELFTEST: PASS"), - Err(e) => panic!("SQUARE_WINDOW_SELFTEST: FAIL: {e}"), - } - if std::env::var("SQUARE_WINDOW_SELFTEST_ONLY").ok().as_deref() == Some("1") { - return Vec::new(); - } - } - if std::env::var("FOLD_FREED_TAIL_SELFTEST").is_ok() { - match fold_freed_tail_selftest() { - Ok(()) => eprintln!("FOLD_FREED_TAIL_SELFTEST: PASS (freed-tail ≡ baseline, ancilla & phase clean)"), - Err(e) => panic!("FOLD_FREED_TAIL_SELFTEST: FAIL: {e}"), - } - if std::env::var("FOLD_FREED_TAIL_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("SPECIAL_FOLD_PARK_SELFTEST").is_ok() { - match special_fold_park_selftest() { - Ok(()) => eprintln!( - "SPECIAL_FOLD_PARK_SELFTEST: PASS (parked fold ≡ baseline, ancilla & phase clean)" - ), - Err(e) => panic!("SPECIAL_FOLD_PARK_SELFTEST: FAIL: {e}"), - } - if std::env::var("SPECIAL_FOLD_PARK_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - if std::env::var("DIALOG_GCD_FUSED_APPLY_SELFTEST").is_ok() { - match dialog_gcd_k5_tail7_fixed_apply_selftest() { - Ok(()) => eprintln!( - "DIALOG_GCD_FUSED_APPLY_SELFTEST: PASS (fused double/halve value, ancilla, phase)" - ), - Err(e) => panic!("DIALOG_GCD_FUSED_APPLY_SELFTEST: FAIL: {e}"), - } - if std::env::var("DIALOG_GCD_FUSED_APPLY_SELFTEST_ONLY") - .ok() - .as_deref() - == Some("1") - { - return Vec::new(); - } - } - - set_default_env("LUD_EXTRA_FOLD_VENTS", "0"); - set_default_env("LUD_EXTRA_FOLD_MIN_G", "0"); - set_default_env("LUD_EXTRA_FOLD_MAX_G", "999"); - set_default_env("DIALOG_TAIL_NONCE", "2430844"); - set_default_env("TLM_FOLD_TAIL_CINC", "1"); - set_default_env("TLM_CODEC_DIAMOND_MCX", "1"); - set_default_env("SINGLE_CCX_FANOUT_DISABLE", "0"); - - set_default_env("TLM_SQUARE_F_RAMP10_DIRECT32_TAGS", ""); - set_default_env("TLM_SQUARE_F_SHIFTED_LOW", "1"); - - set_default_env("TLM_GRAD_FINAL_NO_COUT", "1"); - set_default_env("TLM_APPLY_FWD_FIRST_CSWAP_SKIP", "1"); - set_default_env("CONSTPROP_MAX_ITERS", "16"); - - set_default_env("TLM_TARGET_Q", "1155"); - set_default_env("TLM_FOLD_BOUNDARY_ZERO_DIRECT", "1"); - set_default_env("TLM_FOLD_CHUNK_FORCE", "4"); - set_default_env("TLM_TARGET_FOLD_CALL_RESERVE_OVERRIDES", "173:3,175:3,177:3,256:11,257:11,336:3,338:3,340:3,176:3,178:3,180:3,254:5,259:20,333:3,335:3,337:3,179:3,181:3,183:3,182:3,184:3,186:3,327:3,329:3,330:3,331:3,332:3,334:3"); - set_default_env("TLM_TARGET_FFG_CALL_RESERVE_OVERRIDES", "184:4,186:4,188:4,205:6,207:6,209:6,220:7,222:7,224:7,238:8,240:8,242:8,251:9,257:10,262:10,355:10,362:10,359:10,181:3,183:3,185:3,187:4,189:4,191:4,196:5,198:5,200:5,208:6,210:6,212:6,223:7,225:7,227:7,241:8,243:8,245:8,250:9,252:9,190:4,192:4,193:5,194:4,195:5,197:5,199:5,201:5,202:6,203:5,204:6,206:6,211:6,213:6,214:7,215:6,216:7,218:7,226:7,228:8,229:8,230:8,231:8,233:8,244:8,246:8,247:9,253:9,254:10,259:11,358:10,340:11,341:11,342:11,343:11,344:11,345:11,346:11,347:11,348:11,349:11,350:11"); - set_default_env("TLM_APPLY_FWD_S2_ZERO_LAST", "1"); - set_default_env("TLM_APPLY_INV_S2_ZERO_LAST", "1"); - set_default_env("TLM_APPLY_FWD_CSWAP_SKIP_LAST", "2"); - set_default_env("TLM_APPLY_INV_CSWAP_SKIP_LAST", "1"); - set_default_env("TLM_FOLD_RELEASE_CONTROLS", "1"); - set_default_env("TLM_TARGET_FFG_RESERVE", "9"); - set_default_env( - "TLM_TARGET_FFG_CALL_RESERVES", - concat!( - "163:8,165:8,166:7,167:8,168:7,169:6,170:7,171:6,172:5,173:6,174:5,175:4,176:5,177:4,178:3,179:4,180:3,181:2,182:3,183:2,184:1,185:2,186:1,187:0,188:1,189:0,190:3,191:0,192:3,193:3,194:3,195:3,196:4,197:3,198:4,199:4,200:4,201:4,202:4,203:4,204:4,205:5,206:4,207:5,208:5,209:5,210:5,211:5,212:5,213:5,214:5,215:5,216:5,217:6,218:5,219:6,220:6,221:6,222:6,223:6,224:6,225:6,226:6,227:6,228:6,229:6,230:6,231:6,232:7,233:6,234:7,235:7,236:7,237:7,238:7,239:7,240:7,241:7,242:7,243:7,244:7,245:7,246:7,247:7,248:8,249:8,250:8,251:8,252:8,253:8,254:8,", - "509:8,510:8,511:8,512:8,513:8,514:8,515:8,516:7,517:7,518:7,519:7,520:7,521:7,522:7,523:7,524:7,525:7,526:7,527:7,528:7,529:7,530:6,531:7,532:6,533:6,534:6,535:6,536:6,537:6,538:6,539:6,540:6,541:6,542:6,543:6,544:6,545:5,546:6,547:5,548:5,549:5,550:5,551:5,552:5,553:5,554:5,555:5,556:5,557:4,558:5,559:4,560:4,561:4,562:4,563:4,564:4,565:4,566:3,567:4,568:3,569:3,570:3,571:3,572:0,573:3,574:0,575:1,576:0,577:1,578:2,579:1,580:2,581:3,582:2,583:3,584:4,585:3,586:4,587:5,588:4,589:5,590:6,591:5,592:6,593:7,594:6,595:7,596:8,597:7,598:8,600:8", - ), - ); - set_default_env("TLM_TARGET_FOLD_RESERVE", "4"); - set_default_env( - "TLM_TARGET_FOLD_CALL_RESERVES", - concat!( - "170:3,172:3,173:2,174:3,175:2,176:1,177:2,178:1,179:0,180:1,181:0,182:0,183:0,184:0,185:3,186:0,187:3,188:3,189:3,190:3,191:3,192:3,193:3,195:3,", - "251:3,252:3,253:3,254:3,255:3,256:3,257:3,258:3,259:3,260:3,261:3,262:3,318:3,320:3,321:3,322:3,323:3,324:3,325:3,326:3,327:0,328:3,329:0,330:0,331:0,332:0,333:1,334:0,335:1,336:2,337:1,338:2,339:3,340:2,341:3,343:3", - ), - ); - set_default_env("TLM_GCD_RESELECT_LAYOUT", "1"); - set_default_env("TLM_DIRECT_VARCHUNK", "1"); - set_default_env("TLM_COUT_LAYOUT_SEARCH", "1"); - set_default_env("TLM_COUT_LAYOUT_MARGIN", "0"); - set_default_env("TLM_COUT_LAYOUT_FORCE_M1_KS", "129"); - - // Per-chunk carry-erase comparison width. The chunked cout adder pays `chunked_len` emitted CCX - // (half that executed, it sits under push_condition) purely to re-derive each chunk carry-out - // from the finished sum. Restricting that comparison to the top 22 bits of the chunk is wrong - // only when those 22 bits tie and the low part borrows. - // - // The first 24 erase calls are exempt: at the start of the walk the Bezout pair still holds - // small values, so a chunk's information lives in its LOW bits and a top-window comparison - // carries no signal at all. Measured: capping those calls saturates phase-garbage at 141/141 - // batches, exempting them puts it back on the intrinsic baseline. - // Set TLM_COUT_ERASE_CAP=0 to disable; that restores a byte-identical op stream. - set_default_env("TLM_COUT_ERASE_CAP", "22"); - set_default_env("TLM_COUT_ERASE_CAP_CALLS", "24:9999"); - set_default_env("TLM_GCD_ADAPTIVE_LAYOUT_SEARCH", "1"); - set_default_env("TLM_GCD_ADAPTIVE_LAYOUT_MARGIN", "0"); - - set_default_env("TLM_PARK_ODD_U0", "1"); - set_default_env("TLM_LOAN_ODD_U0", "1"); - set_default_env("TLM_PARK_EVEN_V0", "1"); - set_default_env("TLM_LOAN_EVEN_V0", "1"); - set_default_env("TLM_LOAN_GCD_Y0", "1"); - set_default_env("TLM_HYB_V_DELTA", "2"); - set_default_env("TLM_COUT_K_DELTA", "2"); - set_default_env("TLM_FOLD_DELTA", "2"); - set_default_env("TLM_FFG_DELTA", "0"); - set_default_env("TLM_GCD_K_ADJUST_AFTER", "169"); - set_default_env("TLM_GCD_K_ADJUST_BEFORE", "196"); - set_default_env("TLM_GCD_K_ADJUST", "-2"); - - set_default_env("TLM_FFG_SKIP_STRUCTURAL_DEAD_CALLS", "1"); - set_default_env("TLM_FFG_SKIP_TOP_CARRY31", "1"); - set_default_env("TLM_FFG_SKIP_TOP_CARRY30", "1"); - set_default_env("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS", "1"); - set_default_env("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS", "1"); - set_default_env("TLM_COMPARE_SKIP_EXACT_REMAINDER", "1"); - set_default_env("TLM_GIDNEY_SKIP_STRUCTURAL_DEAD_CALLS", "1"); - set_default_env("TLM_GIDNEY_SKIP_EXACT_REMAINDER", "1"); - set_default_env("TLM_CONST_CHUNK_SKIP_STRUCTURAL_DEAD_CALLS", "1"); - set_default_env("TLM_CONST_CHUNK_SKIP_EXACT_REMAINDER", "1"); - set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CARRIES", "1"); - set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_SHIFT0", "1"); - set_default_env("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER", "1"); - set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_DIRTY_FOLD", "1"); - set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CLEAN_WINDOW", "1"); - set_default_env("TLM_ADD_CONST_SKIP_STRUCTURAL_DEAD_CARRIES", "1"); - set_default_env("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS", "1"); - set_default_env("TLM_GCD_SKIP_EXACT_FORWARD_CSWAPS", "1"); - set_default_env("TLM_GCD_SKIP_STRUCTURAL_DEAD_SHIFTS", "1"); - set_default_env("TLM_GCD_SKIP_EXACT_SHIFT_REMAINDER", "1"); - set_default_env("TLM_COMPARE_SKIP_EXACT_CIN_REMAINDER", "1"); - set_default_env("TLM_FUSED_SKIP_EXACT_BOUNDARY_ZERO", "1"); - set_default_env("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ", "1"); - set_default_env("TLM_FFG_SKIP_EXACT_TOP29_REMAINDER", "1"); - set_default_env("TLM_GCD_SKIP_REVERSE_DIAGONAL_EDGE", "1"); - set_default_env("TLM_FFG_SKIP_INVERSE_MOD_SUB_TOP29", "1"); - set_default_env("TLM_FFG_INVERSE_TOP29_MAX_CALL", "180"); - set_default_env("TLM_FUSED_CLEAN_FOLD_SKIP_TOP31", "1"); - set_default_env("TLM_GIDNEY_SKIP_SMALL_RESIDUAL_DEAD", "1"); - let mut ops = trailmix_ludicrous::build_trailmix_ludicrous_ops(); - - if let Ok(k) = std::env::var("TLM_SEED_PERTURB").unwrap_or_default().parse::() { - for _ in 0..k { - ops.push(crate::circuit::Op { - kind: crate::circuit::OperationType::DebugPrint, - q_control2: crate::circuit::NO_QUBIT, - q_control1: crate::circuit::NO_QUBIT, - q_target: crate::circuit::NO_QUBIT, - c_target: crate::circuit::NO_BIT, - c_condition: crate::circuit::NO_BIT, - r_target: crate::circuit::NO_REG, - }); - } - } - if std::env::var("SINGLE_CCX_FANOUT_DISABLE") - .ok() - .as_deref() - == Some("1") - { - return ops; - } - let input_ops = ops.len(); - let mut fanout_passes = 0usize; - loop { - match single_ccx_fanout::rewrite_first_target_fanout(ops.clone(), 96) { - Ok((rewritten, _witness)) => { - fanout_passes += 1; - ops = rewritten; - } - Err(error) => { - eprintln!( - "SINGLE_CCX_FANOUT: STOP passes={} input_ops={} output_ops={} reason={}", - fanout_passes, - input_ops, - ops.len(), - error, - ); - break; - } - } - } - assert!(fanout_passes >= 1, "single-fanout rewrite failed to find first pass"); - eprintln!( - "SINGLE_CCX_FANOUT: SUMMARY input_ops={} output_ops={} passes={}", - input_ops, - ops.len(), - fanout_passes, - ); - let ops = apply_m60_dead_t10(ops); - let ops = ccz_self_inverse_cancel(ops); - let mut ops = trailmix_ludicrous::constprop::ccx_final_cancel(ops); - // E275: re-run single_ccx_fanout to fixpoint over the post-cancel stream (-13 CCX, bit-exact). - if std::env::var("SINGLE_CCX_FANOUT_SECOND_PASS").ok().as_deref() != Some("0") { - loop { - match single_ccx_fanout::rewrite_first_target_fanout(ops.clone(), 96) { - Ok((rewritten, _w)) => { ops = rewritten; } - Err(_e) => break, - } - } - } - // submission-4: the baked d2 deep-strip is indexed for the OLD (pre-bit-exact-wins) op - // stream and would misfire here; it is a near-eps lever and is re-derived on the composed - // stream separately. Disable it for the pure bit-exact-wins circuit unless explicitly re-enabled. - // Identity-keyed deep strip (1442 census-dead gates, zero-error) on by default; - // SUB4_APPLY_STRIP=0 disables for A/B measurement. - // The strip keys its gates by `(kind, operands, k-th occurrence ordinal)`, so like - // the census certificates it is only valid at the baked divstep count. - // Identity-keyed deep strip, re-mined at 1e9 against THIS stream. Keys carry the - // census-time tuple occupancy, a self-check strictly stronger than gating on - // baked_artifacts_valid(): it catches ANY ordinal-moving edit and discards only - // the affected keys, loudly, instead of disabling the table. - let ops = if std::env::var("SUB4_APPLY_STRIP").ok().as_deref() == Some("0") { - ops - } else { - apply_deep_strip_identity(ops) - }; - // Tail nonce for the exact H2 risk-3.0 stream (9024/9024 PASS, score 1,487,599,474). - // SUB4_TAIL_NONCE overrides it for controlled re-grinding. - let nonce: u64 = std::env::var("SUB4_TAIL_NONCE") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(200321420125); - let ops = apply_tail_nonce(ops, nonce); - // `TLM_DIRTY_SCAN_FINAL=1` runs the reset/phase audit on the stream `eval_circuit` - // will actually see, i.e. after every rewrite pass. Default off. - if std::env::var_os("TLM_DIRTY_SCAN_FINAL").is_some() { - dirtyscan::scan(&ops, &[]); - } - ops -} - -pub fn square_window_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - const SHOTS: usize = 64; - let nbits = std::env::var("SQUARE_WINDOW_SELFTEST_NBITS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(24); - assert!(nbits > 0); - let packed_value_check = 2 * nbits < 64; - let wide_value_check = nbits <= 256; - let mask = if packed_value_check { (1u64 << nbits) - 1 } else { u64::MAX }; - let out_mask = if packed_value_check { (1u64 << (2 * nbits)) - 1 } else { u64::MAX }; - let xs: Vec = (0..SHOTS as u64) - .map(|s| { - let r = s - .wrapping_mul(0x9E37_79B9_7F4A_7C15) - .wrapping_add(0xA076_1D64_78BD_642F); - let r = (r ^ (r >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); - r & mask - }) - .collect(); - let x_masks: Vec = (0..nbits) - .map(|k| { - if packed_value_check { - xs.iter() - .enumerate() - .fold(0u64, |acc, (shot, &xv)| acc | (((xv >> k) & 1) << shot)) - } else { - let z = (k as u64) - .wrapping_mul(0xD6E8_FD9D_50B5_8A51) - .wrapping_add(0x9E37_79B9_7F4A_7C15); - let z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB); - z ^ (z >> 31) - } - }) - .collect(); - - let build_one = |roundtrip: bool| -> (Vec, Vec, Vec, usize, usize) { - let mut b = B::new(); - let x = b.alloc_qubits(nbits); - let tmp = b.alloc_qubits(2 * nbits); - schoolbook_square_symmetric_lowq_selfhosted(&mut b, &x, &tmp); - if roundtrip { - schoolbook_square_symmetric_lowq_selfhosted_inverse(&mut b, &x, &tmp); - } - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - (b.ops, x, tmp, nq, nb) - }; - - let run = |ops: &[Op], - x: &[QubitId], - tmp: &[QubitId], - nq: usize, - nb: usize| - -> (Vec, Vec, u64) { - let mut seed = sha3::Shake128::default(); - seed.update(b"square-window-selftest"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - sim.clear_for_shot(); - for k in 0..nbits { - *sim.qubit_mut(x[k]) = x_masks[k]; - } - sim.apply_iter(ops.iter()); - let out_x_masks: Vec = x.iter().map(|&q| sim.qubit(q)).collect(); - let out_tmp_masks: Vec = tmp.iter().map(|&q| sim.qubit(q)).collect(); - (out_x_masks, out_tmp_masks, sim.phase) - }; - - let (ops_fwd, x_fwd, tmp_fwd, nq_fwd, nb_fwd) = build_one(false); - let (out_x_masks, out_tmp_masks, phase) = run(&ops_fwd, &x_fwd, &tmp_fwd, nq_fwd, nb_fwd); - if phase != 0 { - return Err(format!("forward phase garbage 0x{phase:x}")); - } - for (k, (&got, &want)) in out_x_masks.iter().zip(x_masks.iter()).enumerate() { - if got != want { - return Err(format!("forward x bit {k} changed")); - } - } - if packed_value_check { - for shot in 0..SHOTS { - let got = out_tmp_masks - .iter() - .take(2 * nbits) - .enumerate() - .fold(0u64, |acc, (k, &bits)| acc | (((bits >> shot) & 1) << k)); - let want = xs[shot].wrapping_mul(xs[shot]) & out_mask; - if got != want { - return Err(format!( - "forward value mismatch shot {shot}: tmp got 0x{got:x} want 0x{want:x}" - )); - } - } - } else if wide_value_check { - let in_limbs = (nbits + 63) / 64; - let out_limbs = (2 * nbits + 63) / 64; - for shot in 0..SHOTS { - let mut x_limbs = vec![0u64; in_limbs]; - for k in 0..nbits { - if (x_masks[k] >> shot) & 1 != 0 { - x_limbs[k / 64] |= 1u64 << (k % 64); - } - } - let mut product = vec![0u64; out_limbs]; - for i in 0..in_limbs { - let mut carry = 0u128; - for j in 0..in_limbs { - let idx = i + j; - if idx >= out_limbs { - break; - } - let cur = product[idx] as u128 - + (x_limbs[i] as u128) * (x_limbs[j] as u128) - + carry; - product[idx] = cur as u64; - carry = cur >> 64; - } - let mut idx = i + in_limbs; - while carry != 0 && idx < out_limbs { - let cur = product[idx] as u128 + carry; - product[idx] = cur as u64; - carry = cur >> 64; - idx += 1; - } - } - for k in 0..(2 * nbits) { - let got = (out_tmp_masks[k] >> shot) & 1; - let want = (product[k / 64] >> (k % 64)) & 1; - if got != want { - return Err(format!("forward value mismatch shot {shot} bit {k}")); - } - } - } - } - - let (ops_rt, x_rt, tmp_rt, nq_rt, nb_rt) = build_one(true); - let (out_x_masks, out_tmp_masks, phase) = run(&ops_rt, &x_rt, &tmp_rt, nq_rt, nb_rt); - if phase != 0 { - return Err(format!("roundtrip phase garbage 0x{phase:x}")); - } - for (k, (&got, &want)) in out_x_masks.iter().zip(x_masks.iter()).enumerate() { - if got != want { - return Err(format!("roundtrip x bit {k} changed")); - } - } - for (k, &got) in out_tmp_masks.iter().enumerate() { - if got != 0 { - return Err(format!("roundtrip tmp bit {k} dirty mask 0x{got:x}")); - } - } - Ok(()) -} - -pub fn fold_freed_tail_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - let hi_delta = 33usize; - let hi_c = 32usize; - let nbits = 64usize; - for &windowed in &[true, false] { - let last = if windowed { - hi_delta + 19 - } else { - nbits - 2 - }; - for ed in 0u64..4 { - let e_val = ed & 1; - let d_val = (ed >> 1) & 1; - for &is_add in &[true, false] { - - let build_one = |freed: bool| -> (Vec, Vec, usize, usize) { - let mut b = B::new(); - let y = b.alloc_qubits(nbits); - let ovf1 = b.alloc_qubit(); - let ovf2 = b.alloc_qubit(); - let s2 = b.alloc_qubit(); - let e = b.alloc_qubit(); - let d = b.alloc_qubit(); - let h = b.alloc_qubit(); - let xed = b.alloc_qubit(); - let eord = b.alloc_qubit(); - let n10 = b.alloc_qubit(); - - b.x(s2); - if d_val == 1 { - b.x(ovf1); - } - if e_val == 1 { - b.x(ovf2); - } - b.ccx(ovf1, s2, d); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.ccx(e, d, h); - b.cx(e, xed); - b.cx(d, xed); - b.cx(xed, eord); - b.cx(h, eord); - b.cx(d, n10); - b.cx(h, n10); - if freed { - fold_ripple_freed_tail_ed( - &mut b, - &y, - e, - d, - h, - xed, - eord, - n10, - Some((ovf1, ovf2, s2)), - None, - last, - is_add, - ); - } else { - let controls = - secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); - if is_add { - cadd_per_position_controls_trunc(&mut b, &y, &controls, last); - } else { - csub_per_position_controls_trunc(&mut b, &y, &controls, last); - } - } - - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.ccx(e, d, h); - b.cx(ovf2, e); - b.cx(d, e); - b.cx(ovf1, e); - b.ccx(ovf1, s2, d); - if e_val == 1 { - b.x(ovf2); - } - if d_val == 1 { - b.x(ovf1); - } - b.x(s2); - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - (b.ops, y, nq, nb) - }; - let (ops_base, y_b, nq_b, nb_b) = build_one(false); - let (ops_freed, y_f, nq_f, nb_f) = build_one(true); - - let mask: u64 = if nbits >= 64 { u64::MAX } else { (1u64 << nbits) - 1 }; - let ys: Vec = (0..64u64) - .map(|s| { - let r = s - .wrapping_mul(0x9E37_79B9_7F4A_7C15) - .wrapping_add(0xD1B5_4A32_D192_ED03); - let r = (r ^ (r >> 31)).wrapping_mul(0xBF58_476D_1CE4_E5B9); - let r = r ^ (r >> 27); - let base = r & mask; - - if s % 4 == 0 { - base | (mask & !((1u64 << (hi_delta + 1)) - 1)) - } else if s % 4 == 1 { - base & ((1u64 << (hi_delta + 1)) - 1) - } else { - base - } - }) - .collect(); - - let run = |ops: &[Op], y: &[QubitId], nq: usize, nb: usize| -> (Vec, bool, u64) { - let mut s2 = sha3::Shake128::default(); - s2.update(b"fold-sim"); - let mut xof2 = s2.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof2); - sim.clear_for_shot(); - for (shot, &yv) in ys.iter().enumerate() { - for k in 0..nbits { - if (yv >> k) & 1 != 0 { - *sim.qubit_mut(y[k]) |= 1u64 << shot; - } - } - } - sim.apply_iter(ops.iter()); - let outs: Vec = (0..64) - .map(|shot| { - let mut v = 0u64; - for k in 0..nbits { - v |= ((sim.qubit(y[k]) >> shot) & 1) << k; - } - v - }) - .collect(); - let anc_clean = - (nbits..nq).all(|q| sim.qubit(QubitId(q as u64)) == 0); - (outs, anc_clean, sim.phase) - }; - let (out_b, clean_b, phase_b) = run(&ops_base, &y_b, nq_b, nb_b); - let (out_f, clean_f, phase_f) = run(&ops_freed, &y_f, nq_f, nb_f); - - if !clean_b { - return Err(format!("baseline left ancilla dirty (ed={ed} add={is_add} win={windowed})")); - } - if !clean_f { - return Err(format!("freed-tail left ancilla dirty (ed={ed} add={is_add} win={windowed})")); - } - if phase_f != 0 { - return Err(format!("freed-tail left phase garbage 0x{phase_f:x} (ed={ed} add={is_add} win={windowed})")); - } - let _ = phase_b; - for shot in 0..64 { - if out_b[shot] != out_f[shot] { - return Err(format!( - "value mismatch shot {shot}: base 0x{:x} freed 0x{:x} (ed={ed} add={is_add} win={windowed}, y_in=0x{:x})", - out_b[shot], out_f[shot], ys[shot] - )); - } - } - } - } - } - Ok(()) -} - -pub fn special_fold_park_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let c = U256::MAX - .wrapping_sub(SECP256K1_P) - .wrapping_add(U256::from(1u64)); - let nbits = 64usize; - let window = 20usize; - - for ctrl_value in 0u64..=1 { - for &is_add in &[true, false] { - let build_one = |parked: bool| { - let mut b = B::new(); - let acc = b.alloc_qubits(nbits); - let ctrl = b.alloc_qubit(); - let scratch = b.alloc_qubits(5); - if ctrl_value != 0 { - b.x(ctrl); - } - if parked { - if is_add { - cadd_nbit_const_direct_trunc_fast_releasing_scratch( - &mut b, &acc, c, ctrl, window, &scratch, - ); - } else { - csub_nbit_const_direct_trunc_fast_releasing_scratch( - &mut b, &acc, c, ctrl, window, &scratch, - ); - } - } else if is_add { - cadd_nbit_const_direct_trunc_fast_borrowed_carries( - &mut b, &acc, c, ctrl, window, &scratch, - ); - } else { - csub_nbit_const_direct_trunc_fast_borrowed_carries( - &mut b, &acc, c, ctrl, window, &scratch, - ); - } - if ctrl_value != 0 { - b.x(ctrl); - } - (b.ops, acc, b.next_qubit as usize, b.next_bit as usize) - }; - - let (base_ops, base_acc, base_nq, base_nb) = build_one(false); - let (parked_ops, parked_acc, parked_nq, parked_nb) = build_one(true); - let inputs: Vec = (0..64u64) - .map(|shot| { - let mixed = shot - .wrapping_mul(0x9E37_79B9_7F4A_7C15) - .wrapping_add(0xD1B5_4A32_D192_ED03); - match shot % 4 { - 0 => mixed | (!0u64 << 33), - 1 => mixed & ((1u64 << 34) - 1), - _ => mixed ^ (mixed >> 29), - } - }) - .collect(); - - let run = |ops: &[Op], acc: &[QubitId], nq: usize, nb: usize| { - let mut seed = Shake256::default(); - seed.update(b"special-fold-park-selftest"); - seed.update(&[ctrl_value as u8, is_add as u8]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - sim.clear_for_shot(); - for (shot, &input) in inputs.iter().enumerate() { - for bit_index in 0..nbits { - if (input >> bit_index) & 1 != 0 { - *sim.qubit_mut(acc[bit_index]) |= 1u64 << shot; - } - } - } - sim.apply_iter(ops.iter()); - let outputs: Vec = (0..64) - .map(|shot| { - let mut value = 0u64; - for bit_index in 0..nbits { - value |= ((sim.qubit(acc[bit_index]) >> shot) & 1) << bit_index; - } - value - }) - .collect(); - let clean = (nbits..nq).all(|q| sim.qubit(QubitId(q as u64)) == 0); - (outputs, clean, sim.phase) - }; - - let (base_out, base_clean, base_phase) = - run(&base_ops, &base_acc, base_nq, base_nb); - let (parked_out, parked_clean, parked_phase) = - run(&parked_ops, &parked_acc, parked_nq, parked_nb); - if !base_clean || base_phase != 0 { - return Err(format!( - "baseline dirty: ctrl={ctrl_value} add={is_add} clean={base_clean} phase=0x{base_phase:x}" - )); - } - if !parked_clean || parked_phase != 0 { - return Err(format!( - "parked dirty: ctrl={ctrl_value} add={is_add} clean={parked_clean} phase=0x{parked_phase:x}" - )); - } - if base_out != parked_out { - let shot = base_out - .iter() - .zip(&parked_out) - .position(|(base, parked)| base != parked) - .unwrap_or(0); - return Err(format!( - "value mismatch shot {shot}: base=0x{:x} parked=0x{:x} input=0x{:x} ctrl={ctrl_value} add={is_add}", - base_out[shot], parked_out[shot], inputs[shot] - )); - } - } - } - Ok(()) -} - -#[cfg(test)] -mod direct_const_tests { - use super::*; - use sha3::{ - digest::{ExtendableOutput, Update, XofReader}, - Shake128, - }; - - fn set_reg(sim: &mut Simulator<'_, R>, qs: &[QubitId], val: u64, shot: usize) { - for (i, &q) in qs.iter().enumerate() { - if ((val >> i) & 1) != 0 { - *sim.qubit_mut(q) |= 1u64 << shot; - } else { - *sim.qubit_mut(q) &= !(1u64 << shot); - } - } - } - - fn get_reg(sim: &Simulator<'_, R>, qs: &[QubitId], shot: usize) -> u64 { - let mut out = 0u64; - for (i, &q) in qs.iter().enumerate() { - out |= ((sim.qubit(q) >> shot) & 1) << i; - } - out - } - - #[test] - fn one_inv_dx3_blocker_is_fail_closed_on_cleanup_invariant() { - assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("Rx-Qx")); - assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("second inversion")); - assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("dirty reset")); - } - - #[test] - fn dialog_gcd_selected_body_nocin_matches_cin_reference() { - if let Err(e) = dialog_gcd_selected_body_nocin_selftest() { - panic!("no-c_in selected body selftest failed: {e}"); - } - } - - #[test] - fn aliased_gate_wrappers_are_not_silent_noops() { - let mut b = B::new(); - let q0 = b.alloc_qubit(); - let q1 = b.alloc_qubit(); - b.cz(q0, q0); - b.ccz(q0, q0, q1); - b.ccz(q0, q1, q0); - b.ccz(q0, q0, q0); - b.ccx(q0, q0, q1); - let kinds = b.ops.iter().map(|op| op.kind).collect::>(); - assert_eq!( - kinds, - vec![ - OperationType::Z, - OperationType::CZ, - OperationType::CZ, - OperationType::Z, - OperationType::CX, - ] - ); - assert!(std::panic::catch_unwind(|| { - let mut b = B::new(); - let q = b.alloc_qubit(); - b.cx(q, q); - }) - .is_err()); - assert!(std::panic::catch_unwind(|| { - let mut b = B::new(); - let q0 = b.alloc_qubit(); - let q1 = b.alloc_qubit(); - b.ccx(q0, q1, q0); - }) - .is_err()); - } - - #[test] - fn dx3_witness_is_not_an_output_cleanup_coordinate() { - let p = SECP256K1_P; - let beta = U256::from_str_radix( - "7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE", - 16, - ) - .unwrap(); - let dx = U256::from(0x1234_5678_9abc_def0u64); - let beta_dx = beta.mul_mod(dx, p); - assert_ne!(dx, beta_dx); - assert_eq!(beta.mul_mod(beta, p).mul_mod(beta, p), U256::from(1u64)); - assert_eq!( - dx.mul_mod(dx, p).mul_mod(dx, p), - beta_dx.mul_mod(beta_dx, p).mul_mod(beta_dx, p) - ); - } - - fn assert_borrowed_carry_adder_basis(is_sub: bool) { - const N: usize = 5; - const MOD: u64 = 1 << N; - let mut b = B::new(); - let a = b.alloc_qubits(N); - let acc = b.alloc_qubits(N); - let carries = b.alloc_qubits(N - 1); - if is_sub { - sub_nbit_qq_fast_borrowed_carries(&mut b, &a, &acc, &carries); - } else { - add_nbit_qq_fast_borrowed_carries(&mut b, &a, &acc, &carries); - } - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - - for batch in 0..16usize { - let mut seed = Shake128::default(); - seed.update(if is_sub { - b"borrowed-sub-small" - } else { - b"borrowed-add-small" - }); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for shot in 0..64usize { - let case = batch * 64 + shot; - let x = (case as u64) & (MOD - 1); - let y = ((case as u64) >> N) & (MOD - 1); - set_reg(&mut sim, &acc, x, shot); - set_reg(&mut sim, &a, y, shot); - } - sim.apply(&b.ops); - assert_eq!( - sim.global_phase(), - 0, - "borrowed carry adder left phase garbage" - ); - for shot in 0..64usize { - let case = batch * 64 + shot; - let x = (case as u64) & (MOD - 1); - let y = ((case as u64) >> N) & (MOD - 1); - let expect = if is_sub { - x.wrapping_sub(y) & (MOD - 1) - } else { - x.wrapping_add(y) & (MOD - 1) - }; - assert_eq!(get_reg(&sim, &acc, shot), expect, "case {case}"); - assert_eq!(get_reg(&sim, &a, shot), y, "a changed in case {case}"); - assert_eq!( - get_reg(&sim, &carries, shot), - 0, - "borrowed carries not clean in case {case}" - ); - } - } - } - - #[test] - fn borrowed_carry_add_small_basis_is_clean() { - assert_borrowed_carry_adder_basis(false); - } - - #[test] - fn borrowed_carry_sub_small_basis_is_clean() { - assert_borrowed_carry_adder_basis(true); - } - - fn sub_mod_p(a: U256, b: U256, p: U256) -> U256 { - if a >= b { - a - b - } else { - p - (b - a) - } - } - - #[test] - fn direct_controlled_const_sub_small_basis_is_phase_clean() { - const N: usize = 8; - let c = U256::from(0b1011_0111u64); - let mut b = B::new(); - let acc = b.alloc_qubits(N); - let ctrl = b.alloc_qubit(); - csub_nbit_const_direct_fast(&mut b, &acc, c, ctrl); - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - - let mut seed = Shake128::default(); - seed.update(b"direct-csub-small"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for shot in 0..64usize { - let x = ((shot * 37 + 11) & 0xff) as u64; - let ctrl_v = (shot & 1) as u64; - set_reg(&mut sim, &acc, x, shot); - if ctrl_v != 0 { - *sim.qubit_mut(ctrl) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - assert_eq!(sim.global_phase(), 0, "direct csub left phase garbage"); - for shot in 0..64usize { - let x = ((shot * 37 + 11) & 0xff) as u64; - let ctrl_v = (shot & 1) as u64; - let expect = x.wrapping_sub(ctrl_v * 0b1011_0111) & 0xff; - assert_eq!(get_reg(&sim, &acc, shot), expect, "shot {shot}"); - assert_eq!((sim.qubit(ctrl) >> shot) & 1, ctrl_v, "ctrl shot {shot}"); - } - } - - #[test] - fn direct_controlled_const_add_small_basis_is_phase_clean() { - const N: usize = 8; - let c = U256::from(0b1011_0111u64); - let mut b = B::new(); - let acc = b.alloc_qubits(N); - let ctrl = b.alloc_qubit(); - cadd_nbit_const_direct_fast(&mut b, &acc, c, ctrl); - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - - let mut seed = Shake128::default(); - seed.update(b"direct-cadd-small"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for shot in 0..64usize { - let x = ((shot * 37 + 11) & 0xff) as u64; - let ctrl_v = (shot & 1) as u64; - set_reg(&mut sim, &acc, x, shot); - if ctrl_v != 0 { - *sim.qubit_mut(ctrl) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - assert_eq!(sim.global_phase(), 0, "direct cadd left phase garbage"); - for shot in 0..64usize { - let x = ((shot * 37 + 11) & 0xff) as u64; - let ctrl_v = (shot & 1) as u64; - let expect = x.wrapping_add(ctrl_v * 0b1011_0111) & 0xff; - assert_eq!(get_reg(&sim, &acc, shot), expect, "shot {shot}"); - assert_eq!((sim.qubit(ctrl) >> shot) & 1, ctrl_v, "ctrl shot {shot}"); - } - } - - #[test] - fn round84_fused_square_xtail_component_matches_relation() { - let ops = build_round84_fused_square_xtail_component(); - let (num_qubits, num_bits, _num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(regs.len(), 4); - let p = SECP256K1_P; - let cases: Vec<(U256, U256, U256)> = (0..32u64) - .map(|i| { - let tx = U256::from_limbs([ - 0x9e37_79b9_7f4a_7c15u64.wrapping_mul(i + 1), - 0xd1b5_4a32_d192_ed03u64.wrapping_mul(i + 3), - 0x94d0_49bb_1331_11ebu64.wrapping_mul(i + 5), - 0x2545_f491_4f6c_dd1du64.wrapping_mul(i + 7), - ]) % p; - let lam = U256::from_limbs([ - 0xbf58_476d_1ce4_e5b9u64.wrapping_mul(i + 11), - 0x94d0_49bb_1331_11ebu64.wrapping_mul(i + 13), - 0xdbe6_d5d5_fe4c_ce2fu64.wrapping_mul(i + 17), - 0xa409_3822_299f_31d0u64.wrapping_mul(i + 19), - ]) % p; - let ox = U256::from_limbs([ - 0x632b_e59b_d9b4_e019u64.wrapping_mul(i + 23), - 0x8515_7af5_4f1d_2d2du64.wrapping_mul(i + 29), - 0x9e37_79b9_7f4a_7c15u64.wrapping_mul(i + 31), - 0xbf58_476d_1ce4_e5b9u64.wrapping_mul(i + 37), - ]) % p; - (tx, lam, ox) - }) - .collect(); - - let mut seed = Shake128::default(); - seed.update(b"round84-xtail-component"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - for (shot, (tx, lam, ox)) in cases.iter().enumerate() { - sim.set_register(®s[0], *tx, shot); - sim.set_register(®s[1], *lam, shot); - sim.set_register(®s[2], *ox, shot); - sim.set_register(®s[3], U256::ZERO, shot); - } - - sim.apply(&ops); - for (shot, (tx, lam, ox)) in cases.iter().enumerate() { - let expected = sub_mod_p( - sub_mod_p(lam.mul_mod(*lam, p), *tx, p), - ox.add_mod(*ox, p), - p, - ); - assert_eq!( - sim.get_register(®s[0], shot), - expected, - "x-tail shot {shot}" - ); - assert_eq!(sim.get_register(®s[1], shot), *lam, "lambda shot {shot}"); - assert_eq!( - sim.get_register(®s[2], shot), - *ox, - "offset-x shot {shot}" - ); - } - let live_mask = (1u64 << cases.len()) - 1; - assert_eq!(sim.global_phase() & live_mask, 0, "x-tail phase garbage"); - for reg in ®s { - for item in reg { - if let QubitOrBit::Qubit(q) = *item { - *sim.qubit_mut(q) = 0; - } - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "x-tail ancilla garbage q{q}" - ); - } - } - - #[test] - fn round190_selector_fused_source_live_residual_is_exact_on_small_widths() { - for width in [2usize, 3, 4] { - let ops = build_round190_selector_fused_source_live_residual_width(width); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 3, "width {width} register count"); - assert_eq!(regs.len(), 3, "width {width} regs"); - assert_eq!(num_bits as usize, width, "width {width} hmr bits"); - assert_eq!(num_qubits as usize, 4 * width + 3, "width {width} qubits"); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), width, "width {width} reg {idx}"); - assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); - } - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!(toffoli_ops, 3 * width, "width {width} toffoli"); - let pred_reg: Vec = regs[0] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let add_reg: Vec = regs[1] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let target_reg: Vec = regs[2] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - - let modulus = 1u64 << width; - let states = modulus * modulus * modulus; - let mut seed = Shake128::default(); - seed.update(b"round190-selector-fused-source-live-residual"); - seed.update(&[width as u8]); - let mut xof = seed.finalize_xof(); - for batch_start in (0..states).step_by(64) { - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let batch_end = (batch_start + 64).min(states); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let predecessor = case & (modulus - 1); - let addend = (case >> width) & (modulus - 1); - let target = (case >> (2 * width)) & (modulus - 1); - set_reg(&mut sim, &pred_reg, predecessor, shot); - set_reg(&mut sim, &add_reg, addend, shot); - set_reg(&mut sim, &target_reg, target, shot); - } - - sim.apply(&ops); - let live_mask = if batch_end - batch_start == 64 { - u64::MAX - } else { - (1u64 << (batch_end - batch_start)) - 1 - }; - assert_eq!( - sim.global_phase() & live_mask, - 0, - "width {width} selector-fused residual phase garbage" - ); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let predecessor = case & (modulus - 1); - let addend = (case >> width) & (modulus - 1); - let target = (case >> (2 * width)) & (modulus - 1); - let low = predecessor & 0b11; - let expected = if low == 0 { - target - } else if ((predecessor >> 1) & 1) != 0 { - target.wrapping_sub(addend) & (modulus - 1) - } else { - target.wrapping_add(addend) & (modulus - 1) - }; - assert_eq!( - get_reg(&sim, &pred_reg, shot), - predecessor, - "width {width} predecessor changed case {case}" - ); - assert_eq!( - get_reg(&sim, &add_reg, shot), - addend, - "width {width} addend changed case {case}" - ); - assert_eq!( - get_reg(&sim, &target_reg, shot), - expected, - "width {width} target mismatch case {case}" - ); - } - for reg in [&pred_reg, &add_reg, &target_reg] { - for &q in reg { - *sim.qubit_mut(q) = 0; - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "width {width} scratch garbage q{q}" - ); - } - } - } - } - - #[test] - fn round190_external_active_signed_digit_is_select0_safe_on_small_widths() { - for width in [2usize, 3, 4] { - let ops = build_round190_external_active_signed_digit_width(width); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 4, "width {width} register count"); - assert_eq!(regs.len(), 4, "width {width} regs"); - assert_eq!(num_bits as usize, width, "width {width} hmr bits"); - assert_eq!(num_qubits as usize, 3 * width + 4, "width {width} qubits"); - assert_eq!(regs[0].len(), 1, "width {width} active width"); - assert_eq!(regs[1].len(), 1, "width {width} sign width"); - assert_eq!(regs[2].len(), width, "width {width} addend width"); - assert_eq!(regs[3].len(), width, "width {width} target width"); - for (idx, reg) in regs.iter().enumerate() { - assert!( - reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_))), - "width {width} reg {idx} must be qubits" - ); - } - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!(toffoli_ops, 3 * width - 2, "width {width} toffoli"); - - let active_q = match regs[0][0] { - QubitOrBit::Qubit(q) => q, - _ => unreachable!(), - }; - let sign_q = match regs[1][0] { - QubitOrBit::Qubit(q) => q, - _ => unreachable!(), - }; - let add_reg: Vec = regs[2] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let target_reg: Vec = regs[3] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - - let modulus = 1u64 << width; - let states = 4 * modulus * modulus; - let mut seed = Shake128::default(); - seed.update(b"round190-external-active-signed-digit"); - seed.update(&[width as u8]); - let mut xof = seed.finalize_xof(); - for batch_start in (0..states).step_by(64) { - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let batch_end = (batch_start + 64).min(states); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let active = case & 1; - let sign = (case >> 1) & 1; - let addend = (case >> 2) & (modulus - 1); - let target = (case >> (2 + width)) & (modulus - 1); - *sim.qubit_mut(active_q) |= active << shot; - *sim.qubit_mut(sign_q) |= sign << shot; - set_reg(&mut sim, &add_reg, addend, shot); - set_reg(&mut sim, &target_reg, target, shot); - } - - sim.apply(&ops); - let live_mask = if batch_end - batch_start == 64 { - u64::MAX - } else { - (1u64 << (batch_end - batch_start)) - 1 - }; - assert_eq!( - sim.global_phase() & live_mask, - 0, - "width {width} external-active phase garbage" - ); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let active = case & 1; - let sign = (case >> 1) & 1; - let addend = (case >> 2) & (modulus - 1); - let target = (case >> (2 + width)) & (modulus - 1); - let expected = if active == 0 { - target - } else if sign != 0 { - target.wrapping_sub(addend) & (modulus - 1) - } else { - target.wrapping_add(addend) & (modulus - 1) - }; - assert_eq!( - (sim.qubit(active_q) >> shot) & 1, - active, - "width {width} active changed case {case}" - ); - assert_eq!( - (sim.qubit(sign_q) >> shot) & 1, - sign, - "width {width} sign changed case {case}" - ); - assert_eq!( - get_reg(&sim, &add_reg, shot), - addend, - "width {width} addend changed case {case}" - ); - assert_eq!( - get_reg(&sim, &target_reg, shot), - expected, - "width {width} target mismatch case {case}" - ); - } - *sim.qubit_mut(active_q) = 0; - *sim.qubit_mut(sign_q) = 0; - for reg in [&add_reg, &target_reg] { - for &q in reg { - *sim.qubit_mut(q) = 0; - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "width {width} external-active scratch garbage q{q}" - ); - } - } - } - } - - #[test] - fn round190_shared_active_external_digits_reuse_selector_safely_on_small_widths() { - for (width, digits) in [(2usize, 3usize), (3, 2)] { - let ops = build_round190_shared_active_external_signed_digits_width(width, digits); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!( - num_registers as usize, - 1 + 2 * digits, - "width {width} digits {digits} register count" - ); - assert_eq!( - regs.len(), - 1 + 2 * digits, - "width {width} digits {digits} regs" - ); - assert_eq!( - num_bits as usize, - width * digits, - "width {width} digits {digits} hmr bits" - ); - assert_eq!( - num_qubits as usize, - (2 * digits + 2) * width + 3, - "width {width} digits {digits} qubits" - ); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), width, "width {width} digits {digits} reg {idx}"); - assert!( - reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_))), - "width {width} digits {digits} reg {idx} must be qubits" - ); - } - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!( - toffoli_ops, - 2 + digits * (3 * width - 2), - "width {width} digits {digits} toffoli" - ); - - let qregs: Vec> = regs - .iter() - .map(|reg| { - reg.iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect() - }) - .collect(); - - let modulus = 1u64 << width; - let mut states = modulus; - for _ in 0..digits { - states *= modulus * modulus; - } - let mut seed = Shake128::default(); - seed.update(b"round190-shared-active-external-digits"); - seed.update(&[width as u8, digits as u8]); - let mut xof = seed.finalize_xof(); - for batch_start in (0..states).step_by(64) { - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let batch_end = (batch_start + 64).min(states); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let mut cursor = case; - let predecessor = cursor & (modulus - 1); - cursor >>= width; - set_reg(&mut sim, &qregs[0], predecessor, shot); - for digit in 0..digits { - let addend = cursor & (modulus - 1); - cursor >>= width; - let target = cursor & (modulus - 1); - cursor >>= width; - set_reg(&mut sim, &qregs[1 + 2 * digit], addend, shot); - set_reg(&mut sim, &qregs[2 + 2 * digit], target, shot); - } - } - - sim.apply(&ops); - let live_mask = if batch_end - batch_start == 64 { - u64::MAX - } else { - (1u64 << (batch_end - batch_start)) - 1 - }; - assert_eq!( - sim.global_phase() & live_mask, - 0, - "width {width} digits {digits} shared-active phase garbage" - ); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let mut cursor = case; - let predecessor = cursor & (modulus - 1); - cursor >>= width; - assert_eq!( - get_reg(&sim, &qregs[0], shot), - predecessor, - "width {width} digits {digits} predecessor changed case {case}" - ); - let active = (predecessor & 0b11) != 0; - let sign = ((predecessor >> 1) & 1) != 0; - for digit in 0..digits { - let addend = cursor & (modulus - 1); - cursor >>= width; - let target = cursor & (modulus - 1); - cursor >>= width; - let expected = if !active { - target - } else if sign { - target.wrapping_sub(addend) & (modulus - 1) - } else { - target.wrapping_add(addend) & (modulus - 1) - }; - assert_eq!( - get_reg(&sim, &qregs[1 + 2 * digit], shot), - addend, - "width {width} digits {digits} addend {digit} changed case {case}" - ); - assert_eq!( - get_reg(&sim, &qregs[2 + 2 * digit], shot), - expected, - "width {width} digits {digits} target {digit} mismatch case {case}" - ); - } - } - for reg in &qregs { - for &q in reg { - *sim.qubit_mut(q) = 0; - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "width {width} digits {digits} shared-active scratch garbage q{q}" - ); - } - } - } - } - - #[test] - fn round190_two_slot_router_is_exact_only_under_exactly_one_active_invariant() { - for width in [2usize, 3] { - let ops = build_round190_two_slot_exactly_one_active_router_width(width); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 6, "width {width} register count"); - assert_eq!(regs.len(), 6, "width {width} regs"); - assert_eq!(num_bits as usize, width - 1, "width {width} hmr bits"); - assert_eq!(num_qubits as usize, 7 * width + 2, "width {width} qubits"); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), width, "width {width} reg {idx}"); - assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); - } - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!(toffoli_ops, 7 * width + 1, "width {width} toffoli"); - - let qregs: Vec> = regs - .iter() - .map(|reg| { - reg.iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect() - }) - .collect(); - let modulus = 1u64 << width; - let active_predecessors: Vec = - (0..modulus).filter(|pred| (pred & 0b11) != 0).collect(); - let inactive_predecessors: Vec = - (0..modulus).filter(|pred| (pred & 0b11) == 0).collect(); - - let mut cases = Vec::new(); - if width == 2 { - for active_slot in 0..2usize { - for &active_pred in &active_predecessors { - for &inactive_pred in &inactive_predecessors { - for add0 in 0..modulus { - for target0 in 0..modulus { - for add1 in 0..modulus { - for target1 in 0..modulus { - let (pred0, pred1) = if active_slot == 0 { - (active_pred, inactive_pred) - } else { - (inactive_pred, active_pred) - }; - cases.push(( - active_slot, - pred0, - add0, - target0, - pred1, - add1, - target1, - )); - } - } - } - } - } - } - } - } else { - for i in 0..512u64 { - let active_slot = (i & 1) as usize; - let active_pred = - active_predecessors[((i / 2) as usize) % active_predecessors.len()]; - let inactive_pred = - inactive_predecessors[((i / 14) as usize) % inactive_predecessors.len()]; - let add0 = (3 * i + 1) & (modulus - 1); - let target0 = (5 * i + 2) & (modulus - 1); - let add1 = (7 * i + 3) & (modulus - 1); - let target1 = (11 * i + 4) & (modulus - 1); - let (pred0, pred1) = if active_slot == 0 { - (active_pred, inactive_pred) - } else { - (inactive_pred, active_pred) - }; - cases.push((active_slot, pred0, add0, target0, pred1, add1, target1)); - } - } - - let mut seed = Shake128::default(); - seed.update(b"round190-two-slot-router"); - seed.update(&[width as u8]); - let mut xof = seed.finalize_xof(); - for batch_start in (0..cases.len()).step_by(64) { - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let batch_end = (batch_start + 64).min(cases.len()); - for (shot, case) in cases[batch_start..batch_end].iter().enumerate() { - let &(_, pred0, add0, target0, pred1, add1, target1) = case; - set_reg(&mut sim, &qregs[0], pred0, shot); - set_reg(&mut sim, &qregs[1], add0, shot); - set_reg(&mut sim, &qregs[2], target0, shot); - set_reg(&mut sim, &qregs[3], pred1, shot); - set_reg(&mut sim, &qregs[4], add1, shot); - set_reg(&mut sim, &qregs[5], target1, shot); - } - - sim.apply(&ops); - let live_mask = if batch_end - batch_start == 64 { - u64::MAX - } else { - (1u64 << (batch_end - batch_start)) - 1 - }; - assert_eq!( - sim.global_phase() & live_mask, - 0, - "width {width} two-slot router phase garbage" - ); - for (shot, case) in cases[batch_start..batch_end].iter().enumerate() { - let &(active_slot, pred0, add0, target0, pred1, add1, target1) = case; - let sign = if active_slot == 0 { - (pred0 >> 1) & 1 - } else { - (pred1 >> 1) & 1 - }; - let expected0 = if active_slot == 0 { - if sign != 0 { - target0.wrapping_sub(add0) & (modulus - 1) - } else { - target0.wrapping_add(add0) & (modulus - 1) - } - } else { - target0 - }; - let expected1 = if active_slot == 1 { - if sign != 0 { - target1.wrapping_sub(add1) & (modulus - 1) - } else { - target1.wrapping_add(add1) & (modulus - 1) - } - } else { - target1 - }; - assert_eq!(get_reg(&sim, &qregs[0], shot), pred0, "pred0 case {case:?}"); - assert_eq!(get_reg(&sim, &qregs[1], shot), add0, "add0 case {case:?}"); - assert_eq!( - get_reg(&sim, &qregs[2], shot), - expected0, - "target0 case {case:?}" - ); - assert_eq!(get_reg(&sim, &qregs[3], shot), pred1, "pred1 case {case:?}"); - assert_eq!(get_reg(&sim, &qregs[4], shot), add1, "add1 case {case:?}"); - assert_eq!( - get_reg(&sim, &qregs[5], shot), - expected1, - "target1 case {case:?}" - ); - } - for reg in &qregs { - for &q in reg { - *sim.qubit_mut(q) = 0; - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "width {width} two-slot router scratch garbage q{q}" - ); - } - } - } - } - - #[test] - fn round190_active_source_live_signed_digit_hmr_is_exact_on_active_rows() { - for width in [2usize, 3, 4] { - let ops = build_round190_active_source_live_signed_digit_hmr_width(width); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 3, "width {width} register count"); - assert_eq!(regs.len(), 3, "width {width} regs"); - assert_eq!(num_bits as usize, width - 1, "width {width} hmr bits"); - assert_eq!(num_qubits as usize, 4 * width + 1, "width {width} qubits"); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), width, "width {width} reg {idx}"); - assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); - } - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!(toffoli_ops, width - 1, "width {width} toffoli"); - let pred_reg: Vec = regs[0] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let add_reg: Vec = regs[1] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let target_reg: Vec = regs[2] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - - let modulus = 1u64 << width; - let active_predecessors: Vec = - (0..modulus).filter(|pred| (pred & 0b11) != 0).collect(); - let states = active_predecessors.len() as u64 * modulus * modulus; - let mut seed = Shake128::default(); - seed.update(b"round190-active-source-live-signed-digit-hmr"); - seed.update(&[width as u8]); - let mut xof = seed.finalize_xof(); - for batch_start in (0..states).step_by(64) { - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let batch_end = (batch_start + 64).min(states); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let pred_idx = (case % active_predecessors.len() as u64) as usize; - let addend = (case / active_predecessors.len() as u64) & (modulus - 1); - let target = - (case / (active_predecessors.len() as u64 * modulus)) & (modulus - 1); - let predecessor = active_predecessors[pred_idx]; - set_reg(&mut sim, &pred_reg, predecessor, shot); - set_reg(&mut sim, &add_reg, addend, shot); - set_reg(&mut sim, &target_reg, target, shot); - } - - sim.apply(&ops); - let live_mask = if batch_end - batch_start == 64 { - u64::MAX - } else { - (1u64 << (batch_end - batch_start)) - 1 - }; - assert_eq!( - sim.global_phase() & live_mask, - 0, - "width {width} active HMR signed digit phase garbage" - ); - for case in batch_start..batch_end { - let shot = (case - batch_start) as usize; - let pred_idx = (case % active_predecessors.len() as u64) as usize; - let addend = (case / active_predecessors.len() as u64) & (modulus - 1); - let target = - (case / (active_predecessors.len() as u64 * modulus)) & (modulus - 1); - let predecessor = active_predecessors[pred_idx]; - let expected = if ((predecessor >> 1) & 1) != 0 { - target.wrapping_sub(addend) & (modulus - 1) - } else { - target.wrapping_add(addend) & (modulus - 1) - }; - assert_eq!( - get_reg(&sim, &pred_reg, shot), - predecessor, - "width {width} predecessor changed case {case}" - ); - assert_eq!( - get_reg(&sim, &add_reg, shot), - addend, - "width {width} addend changed case {case}" - ); - assert_eq!( - get_reg(&sim, &target_reg, shot), - expected, - "width {width} target mismatch case {case}" - ); - } - for reg in [&pred_reg, &add_reg, &target_reg] { - for &q in reg { - *sim.qubit_mut(q) = 0; - } - } - for q in 0..num_qubits { - assert_eq!( - sim.qubit(QubitId(q)) & live_mask, - 0, - "width {width} active HMR scratch garbage q{q}" - ); - } - } - } - } - - #[test] - fn round190_active_hmr_digit_is_not_select0_safe() { - const WIDTH: usize = 3; - let ops = build_round190_active_source_live_signed_digit_hmr_width(WIDTH); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 3); - assert_eq!(regs.len(), 3); - let pred_reg: Vec = regs[0] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let add_reg: Vec = regs[1] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - let target_reg: Vec = regs[2] - .iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => unreachable!(), - }) - .collect(); - - let mut seed = Shake128::default(); - seed.update(b"round190-active-hmr-not-select0-safe"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - let inactive_predecessor = 0u64; - let addend = 3u64; - let target = 4u64; - set_reg(&mut sim, &pred_reg, inactive_predecessor, 0); - set_reg(&mut sim, &add_reg, addend, 0); - set_reg(&mut sim, &target_reg, target, 0); - - sim.apply(&ops); - let got_target = get_reg(&sim, &target_reg, 0); - println!("METRIC round190_active_hmr_inactive_predecessor={inactive_predecessor}"); - println!("METRIC round190_active_hmr_inactive_addend={addend}"); - println!("METRIC round190_active_hmr_inactive_target_before={target}"); - println!("METRIC round190_active_hmr_inactive_target_after={got_target}"); - assert_eq!(get_reg(&sim, &pred_reg, 0), inactive_predecessor); - assert_eq!(get_reg(&sim, &add_reg, 0), addend); - assert_ne!( - got_target, target, - "active-HMR digit cannot be used as the select0-safe production residual" - ); - } - - fn qubit_reg(reg: &[QubitOrBit]) -> Vec { - reg.iter() - .map(|item| match item { - QubitOrBit::Qubit(q) => *q, - _ => panic!("expected qubit register"), - }) - .collect() - } - - fn round556_expected( - width: usize, - q_bits: usize, - rem: u64, - rem_divisor: u64, - coeff_seed: u64, - coeff_divisor: u64, - sigma: u64, - q_increment: u64, - ) -> Option<(u64, u64)> { - let modulus = 1u64 << width; - let mask = modulus - 1; - if rem_divisor == 0 || coeff_divisor == 0 { - return None; - } - if (rem_divisor << (q_bits - 1)) >= modulus { - return None; - } - if (coeff_divisor << (q_bits - 1)) >= modulus { - return None; - } - let quotient = rem / rem_divisor; - if quotient >= (1u64 << q_bits) { - return None; - } - if coeff_seed >= coeff_divisor { - return None; - } - let coeff_restored = coeff_seed + (quotient + q_increment) * coeff_divisor; - if coeff_restored >= modulus { - return None; - } - let coeff = coeff_restored.wrapping_sub((sigma & 1) * coeff_divisor) & mask; - Some((rem % rem_divisor, coeff)) - } - - #[test] - fn round556_shifted_source_row_component_has_material_free_bound() { - const WIDTH: usize = 258; - const QBITS: usize = 26; - let (ops, phases, peak_qubits, peak_phase) = - build_round556_shifted_source_row_component_phase_resources(WIDTH, QBITS); - let (num_qubits, _num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - let old_materialized_formula = (6 * QBITS + 4) * WIDTH - (2 * QBITS + 2); - let shifted_source_q = 6 * WIDTH + QBITS + 5; - - assert_eq!(num_registers, 5); - assert_eq!(regs[0].len(), WIDTH); - assert_eq!(regs[1].len(), WIDTH); - assert_eq!(regs[2].len(), WIDTH); - assert_eq!(regs[3].len(), WIDTH); - assert_eq!(regs[4].len(), 4 + QBITS); - assert_eq!(num_qubits as usize, shifted_source_q); - assert_eq!(peak_qubits as usize, shifted_source_q); - assert!(toffoli_ops <= old_materialized_formula); - assert!(phases - .iter() - .any(|row| row.phase == "round556_shifted_source_remainder_digits")); - assert_eq!(peak_phase, "round556_shifted_source_remainder_digits"); - } - - #[test] - fn round556_shifted_source_row_component_matches_round120_relation() { - const WIDTH: usize = 5; - const QBITS: usize = 3; - let ops = build_round556_shifted_source_row_component(WIDTH, QBITS); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - assert_eq!(num_registers, 5); - let rem_reg = qubit_reg(®s[0]); - let rem_divisor_reg = qubit_reg(®s[1]); - let coeff_reg = qubit_reg(®s[2]); - let coeff_divisor_reg = qubit_reg(®s[3]); - let meta_reg = qubit_reg(®s[4]); - - let mut public = vec![false; num_qubits as usize]; - for reg in [ - &rem_reg, - &rem_divisor_reg, - &coeff_reg, - &coeff_divisor_reg, - &meta_reg, - ] { - for &q in reg { - public[q.0 as usize] = true; - } - } - - let mut cases = Vec::new(); - let modulus = 1u64 << WIDTH; - for rem_divisor in 1..modulus { - for coeff_divisor in 1..modulus { - for rem in 0..modulus { - for coeff_seed in 0..coeff_divisor { - for sigma in 0..=1u64 { - for q_increment in 0..=1u64 { - if let Some(expected) = round556_expected( - WIDTH, - QBITS, - rem, - rem_divisor, - coeff_seed, - coeff_divisor, - sigma, - q_increment, - ) { - cases.push(( - rem, - rem_divisor, - coeff_seed, - coeff_divisor, - sigma, - q_increment, - expected, - )); - } - } - } - } - } - } - } - assert!(!cases.is_empty()); - - let mut seed = Shake128::default(); - seed.update(b"round556-shifted-source-row-relation"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, case) in chunk.iter().enumerate() { - let (rem, rem_divisor, coeff_seed, coeff_divisor, sigma, q_increment, _) = *case; - set_reg(&mut sim, &rem_reg, rem, shot); - set_reg(&mut sim, &rem_divisor_reg, rem_divisor, shot); - set_reg(&mut sim, &coeff_reg, coeff_seed, shot); - set_reg(&mut sim, &coeff_divisor_reg, coeff_divisor, shot); - set_reg(&mut sim, &meta_reg, sigma | (q_increment << 1), shot); - } - sim.apply(&ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for q in 0..num_qubits { - if !public[q as usize] { - assert_eq!( - sim.qubit(QubitId(q as u32)) & live, - 0, - "scratch q{q} dirty in batch {batch}" - ); - } - } - for (shot, case) in chunk.iter().enumerate() { - let ( - _rem, - rem_divisor, - _coeff_seed, - coeff_divisor, - sigma, - q_increment, - (expected_rem, expected_coeff), - ) = *case; - assert_eq!( - get_reg(&sim, &rem_reg, shot), - expected_rem, - "batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &rem_divisor_reg, shot), - rem_divisor, - "batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &coeff_reg, shot), - expected_coeff, - "batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &coeff_divisor_reg, shot), - coeff_divisor, - "batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &meta_reg, shot), - sigma | (q_increment << 1), - "batch {batch} shot {shot}" - ); - } - } - } - - #[test] - fn direct_centered_shifted_source_qbit_row_fit_bench_has_sidecar_bound() { - const Q_BITS: usize = DIRECT_CENTERED_LOW_BRANCH_META_BITS; - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_shifted_source_qbit_row_fit_bench_phase_resources(Q_BITS); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(num_registers, 4); - assert_eq!(regs.len(), 4); - assert!(num_bits as usize >= 2 * N); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), N, "register {idx} width"); - } - let sidecar_q = 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS; - assert_eq!(num_qubits as usize, sidecar_q); - assert_eq!(peak_qubits as usize, sidecar_q); - assert_eq!( - toffoli_ops, - Q_BITS * (6 * N - 2) - 2 * Q_BITS * (Q_BITS - 1) - ); - assert_eq!( - peak_phase, - "direct_centered_shifted_source_qbit_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_shifted_source_qbit_remainder_digits")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_shifted_source_qbit_coeff_digits")); - } - - #[test] - fn direct_centered_shifted_source_qbit_row_toy_is_exact_and_phase_clean() { - const WIDTH: usize = 5; - const QBITS: usize = 3; - let mut b = B::new(); - let rem = b.alloc_qubits(WIDTH); - let rem_divisor = b.alloc_qubits(WIDTH); - let coeff = b.alloc_qubits(WIDTH); - let coeff_divisor = b.alloc_qubits(WIDTH); - let qbits = b.alloc_qubits(QBITS); - let gated = b.alloc_qubits(WIDTH); - let lt_tmp = b.alloc_qubit(); - let sign_one = b.alloc_qubit(); - let nonnegative = b.alloc_qubit(); - let carries = b.alloc_qubits(WIDTH - 1); - emit_direct_centered_shifted_source_qbit_row( - &mut b, - &rem, - &rem_divisor, - &coeff, - &coeff_divisor, - &qbits, - &gated, - lt_tmp, - sign_one, - nonnegative, - &carries, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut public = vec![false; nq]; - for reg in [&rem, &rem_divisor, &coeff, &coeff_divisor] { - for &q in reg { - public[q.0 as usize] = true; - } - } - - let modulus = 1u64 << WIDTH; - let mut cases = Vec::new(); - for rem_divisor_value in 1..modulus { - for coeff_divisor_value in 1..modulus { - for rem_value in 0..modulus { - for coeff_seed in 0..coeff_divisor_value { - if let Some(expected) = round556_expected( - WIDTH, - QBITS, - rem_value, - rem_divisor_value, - coeff_seed, - coeff_divisor_value, - 0, - 0, - ) { - cases.push(( - rem_value, - rem_divisor_value, - coeff_seed, - coeff_divisor_value, - expected, - )); - } - } - } - } - } - assert!(!cases.is_empty()); - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-shifted-source-qbit-row-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, case) in chunk.iter().enumerate() { - let (rem_value, rem_divisor_value, coeff_seed, coeff_divisor_value, _) = *case; - set_reg(&mut sim, &rem, rem_value, shot); - set_reg(&mut sim, &rem_divisor, rem_divisor_value, shot); - set_reg(&mut sim, &coeff, coeff_seed, shot); - set_reg(&mut sim, &coeff_divisor, coeff_divisor_value, shot); - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for q in 0..nq { - if !public[q] { - assert_eq!( - sim.qubit(QubitId(q as u32)) & live, - 0, - "scratch q{q} dirty in batch {batch}" - ); - } - } - for (shot, case) in chunk.iter().enumerate() { - let ( - _rem_value, - rem_divisor_value, - _coeff_seed, - coeff_divisor_value, - (expected_rem, expected_coeff), - ) = *case; - assert_eq!(get_reg(&sim, &rem, shot), expected_rem); - assert_eq!(get_reg(&sim, &rem_divisor, shot), rem_divisor_value); - assert_eq!(get_reg(&sim, &coeff, shot), expected_coeff); - assert_eq!(get_reg(&sim, &coeff_divisor, shot), coeff_divisor_value); - } - } - } - - #[test] - fn direct_centered_branch_sidecar_component_has_relaxed_google_abi_shape() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_branch_sidecar_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N); - for (idx, reg) in regs.iter().enumerate() { - assert_eq!(reg.len(), N, "register {idx} width"); - } - for item in ®s[0] { - assert!(matches!(item, QubitOrBit::Qubit(_)), "r0 must be qubits"); - } - for item in ®s[1] { - assert!(matches!(item, QubitOrBit::Qubit(_)), "r1 must be qubits"); - } - for item in ®s[2] { - assert!(matches!(item, QubitOrBit::Bit(_)), "r2 must be bits"); - } - for item in ®s[3] { - assert!(matches!(item, QubitOrBit::Bit(_)), "r3 must be bits"); - } - - let scratch = num_qubits as usize - 2 * N; - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!( - scratch, - DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert!(scratch <= DIRECT_CENTERED_RELAXED_SCRATCH_BUDGET); - assert!(num_qubits as usize <= DIRECT_CENTERED_RELAXED_Q_TARGET); - assert!(toffoli_ops < DIRECT_CENTERED_RELAXED_T_TARGET); - assert_eq!(toffoli_ops, 936); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(peak_phase, "direct_centered_sidecar_google_abi"); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_sidecar_emit_branch_history")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_sidecar_clear_branch_history")); - } - - #[test] - fn direct_centered_branch_digit_clean_toy_is_exact() { - const W: usize = 5; - let mut b = B::new(); - let coeff_acc = b.alloc_qubits(W); - let coeff_v = b.alloc_qubits(W); - let branch = b.alloc_qubit(); - let sign = b.alloc_qubit(); - let gated = b.alloc_qubits(W); - let carry = b.alloc_qubit(); - emit_direct_centered_branch_digit_update_clean( - &mut b, &coeff_acc, &coeff_v, branch, sign, &gated, carry, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let modulus = 1u64 << W; - let mut cases = Vec::new(); - for acc in 0..modulus { - for source in 0..modulus { - for branch_value in 0..=1u64 { - for sign_value in 0..=1u64 { - let expected = if branch_value == 0 { - acc - } else if sign_value != 0 { - (acc + source) & (modulus - 1) - } else { - acc.wrapping_sub(source) & (modulus - 1) - }; - cases.push((acc, source, branch_value, sign_value, expected)); - } - } - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-branch-digit-clean-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(acc, source, branch_value, sign_value, _expected)) in - chunk.iter().enumerate() - { - set_reg(&mut sim, &coeff_acc, acc, shot); - set_reg(&mut sim, &coeff_v, source, shot); - if branch_value != 0 { - *sim.qubit_mut(branch) |= 1u64 << shot; - } - if sign_value != 0 { - *sim.qubit_mut(sign) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - assert_eq!(sim.qubit(carry) & live, 0, "carry dirty in batch {batch}"); - for (shot, &(acc, source, branch_value, sign_value, expected)) in - chunk.iter().enumerate() - { - assert_eq!( - get_reg(&sim, &gated, shot), - 0, - "gated dirty in batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &coeff_acc, shot), - expected, - "batch {batch} shot {shot}" - ); - assert_eq!( - get_reg(&sim, &coeff_v, shot), - source, - "batch {batch} shot {shot}" - ); - assert_eq!( - (sim.qubit(branch) >> shot) & 1, - branch_value, - "batch {batch} shot {shot}" - ); - assert_eq!( - (sim.qubit(sign) >> shot) & 1, - sign_value, - "batch {batch} shot {shot}" - ); - let _ = acc; - } - } - } - - #[test] - fn direct_centered_branch_replay_then_fast_finalizer_toy_is_exact() { - const W: usize = 4; - const HISTORY: usize = 3; - let mut b = B::new(); - let coeff_acc = b.alloc_qubits(W); - let coeff_v = b.alloc_qubits(W); - let pred_a = b.alloc_qubits(HISTORY); - let pred_b = b.alloc_qubits(HISTORY); - let branch = b.alloc_qubits(HISTORY); - let sign = b.alloc_qubit(); - let gated = b.alloc_qubits(W); - let digit_carry = b.alloc_qubit(); - let nonnegative = b.alloc_qubit(); - let extra_carry = b.alloc_qubit(); - - for i in 0..HISTORY { - b.ccx(pred_a[i], pred_b[i], branch[i]); - } - for &branch_bit in &branch { - emit_direct_centered_branch_digit_update_clean( - &mut b, - &coeff_acc, - &coeff_v, - branch_bit, - sign, - &gated, - digit_carry, - ); - } - for i in (1..HISTORY).rev() { - b.ccx(pred_a[i], pred_b[i], branch[i]); - } - let carries = [branch[1], branch[2], extra_carry]; - emit_direct_centered_branch_retained_finalizer_fast( - &mut b, - &coeff_acc, - &coeff_v, - branch[0], - &gated, - nonnegative, - &carries, - ); - b.ccx(pred_a[0], pred_b[0], branch[0]); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let modulus = 1u64 << W; - let mask = modulus - 1; - let mut cases = Vec::new(); - for acc in 0..modulus { - for source in 0..modulus { - for pred_a_value in 0..(1u64 << HISTORY) { - for pred_b_value in 0..(1u64 << HISTORY) { - for sign_value in 0..=1u64 { - let mut expected = acc; - for i in 0..HISTORY { - let branch_value = - ((pred_a_value >> i) & 1) & ((pred_b_value >> i) & 1); - if branch_value != 0 { - expected = if sign_value != 0 { - expected.wrapping_add(source) & mask - } else { - expected.wrapping_sub(source) & mask - }; - } - } - if (pred_a_value & 1) != 0 && (pred_b_value & 1) != 0 { - expected = expected.wrapping_sub(source) & mask; - } - cases.push(( - acc, - source, - pred_a_value, - pred_b_value, - sign_value, - expected, - )); - } - } - } - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-branch-replay-fast-finalizer-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(acc, source, pred_a_value, pred_b_value, sign_value, _expected)) in - chunk.iter().enumerate() - { - set_reg(&mut sim, &coeff_acc, acc, shot); - set_reg(&mut sim, &coeff_v, source, shot); - set_reg(&mut sim, &pred_a, pred_a_value, shot); - set_reg(&mut sim, &pred_b, pred_b_value, shot); - if sign_value != 0 { - *sim.qubit_mut(sign) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - assert_eq!(sim.qubit(digit_carry) & live, 0, "digit carry dirty"); - assert_eq!(sim.qubit(nonnegative) & live, 0, "nonnegative dirty"); - assert_eq!(sim.qubit(extra_carry) & live, 0, "extra carry dirty"); - for &branch_bit in &branch { - assert_eq!(sim.qubit(branch_bit) & live, 0, "branch history dirty"); - } - for (shot, &(acc, source, pred_a_value, pred_b_value, sign_value, expected)) in - chunk.iter().enumerate() - { - assert_eq!( - get_reg(&sim, &coeff_acc, shot), - expected, - "batch {batch} shot {shot}" - ); - assert_eq!(get_reg(&sim, &gated, shot), 0); - assert_eq!(get_reg(&sim, &coeff_v, shot), source); - assert_eq!(get_reg(&sim, &pred_a, shot), pred_a_value); - assert_eq!(get_reg(&sim, &pred_b, shot), pred_b_value); - assert_eq!((sim.qubit(sign) >> shot) & 1, sign_value); - let _ = acc; - } - } - } - - #[test] - fn direct_centered_low_path_branch_predicate_toy_is_exact() { - const W: usize = 4; - let mut b = B::new(); - let low_path = b.alloc_qubits(W); - let divisor = b.alloc_qubits(W); - let branch = b.alloc_qubit(); - let shifted = b.alloc_qubits(W + 1); - let divisor_high = b.alloc_qubit(); - let cmp_cin = b.alloc_qubit(); - emit_direct_centered_low_path_branch_toggle( - &mut b, - &low_path, - &divisor, - branch, - &shifted, - divisor_high, - cmp_cin, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut cases = Vec::new(); - for low_value in 0..(1u64 << W) { - for divisor_value in 0..(1u64 << W) { - for initial_branch in 0..=1u64 { - let predicate = if 2 * low_value >= divisor_value { 1 } else { 0 }; - cases.push(( - low_value, - divisor_value, - initial_branch, - initial_branch ^ predicate, - )); - } - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-low-path-branch-predicate-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(low_value, divisor_value, initial_branch, _expected_branch)) in - chunk.iter().enumerate() - { - set_reg(&mut sim, &low_path, low_value, shot); - set_reg(&mut sim, &divisor, divisor_value, shot); - if initial_branch != 0 { - *sim.qubit_mut(branch) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for &wire in &shifted { - assert_eq!(sim.qubit(wire) & live, 0, "shifted scratch dirty"); - } - assert_eq!( - sim.qubit(divisor_high) & live, - 0, - "divisor-high scratch dirty" - ); - assert_eq!(sim.qubit(cmp_cin) & live, 0, "cmp-cin scratch dirty"); - for (shot, &(low_value, divisor_value, _initial_branch, expected_branch)) in - chunk.iter().enumerate() - { - assert_eq!(get_reg(&sim, &low_path, shot), low_value); - assert_eq!(get_reg(&sim, &divisor, shot), divisor_value); - assert_eq!( - (sim.qubit(branch) >> shot) & 1, - expected_branch, - "batch {batch} shot {shot}" - ); - } - } - } - - #[test] - fn direct_centered_branch_predicate_step_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_branch_predicate_step_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 3 * N); - let scratch = num_qubits as usize - 2 * N; - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!( - scratch, - DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert!(scratch <= DIRECT_CENTERED_RELAXED_SCRATCH_BUDGET); - assert!(num_qubits as usize <= DIRECT_CENTERED_RELAXED_Q_TARGET); - assert!(toffoli_ops < 2_000); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!( - peak_phase, - "direct_centered_branch_predicate_step_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_predicate_compare")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); - } - - #[test] - fn direct_centered_binary_trie_qrom_toy_is_exact_and_phase_clean() { - const ADDRESS_BITS: usize = 3; - const TARGET_BITS: usize = 5; - const ROWS: usize = 6; - - let table_words: Vec = (0..ROWS) - .map(|row| ((row as u64).wrapping_mul(0b10101) ^ 0b10010) & ((1u64 << TARGET_BITS) - 1)) - .collect(); - - let mut b = B::new(); - let address = b.alloc_qubits(ADDRESS_BITS); - let target = b.alloc_qubits(TARGET_BITS); - emit_direct_centered_binary_trie_qrom_xor_table( - &mut b, - &address, - &target, - ROWS, - &table_words, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut public = vec![false; nq]; - for &q in address.iter().chain(target.iter()) { - public[q.0 as usize] = true; - } - - let mut cases = Vec::new(); - for addr in 0..(1u64 << ADDRESS_BITS) { - for before in 0..(1u64 << TARGET_BITS) { - let loaded = if (addr as usize) < ROWS { - table_words[addr as usize] - } else { - 0 - }; - cases.push((addr, before, before ^ loaded)); - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-binary-trie-qrom-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(addr, before, _expected)) in chunk.iter().enumerate() { - set_reg(&mut sim, &address, addr, shot); - set_reg(&mut sim, &target, before, shot); - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for q in 0..nq { - if !public[q] { - assert_eq!( - sim.qubit(QubitId(q as u32)) & live, - 0, - "scratch q{q} dirty in batch {batch}" - ); - } - } - for (shot, &(addr, _before, expected)) in chunk.iter().enumerate() { - assert_eq!(get_reg(&sim, &address, shot), addr); - assert_eq!(get_reg(&sim, &target, shot), expected); - } - } - } - - #[test] - fn direct_centered_binary_trie_qrom_roundtrip_toy_is_exact_and_phase_clean() { - const ADDRESS_BITS: usize = 3; - const TARGET_BITS: usize = 9; - const ROWS: usize = 6; - - let table_words = direct_centered_binary_trie_qrom_table_words(ROWS, TARGET_BITS); - - let mut b = B::new(); - let address = b.alloc_qubits(ADDRESS_BITS); - let target = b.alloc_qubits(TARGET_BITS); - emit_direct_centered_binary_trie_qrom_xor_table( - &mut b, - &address, - &target, - ROWS, - &table_words, - ); - emit_direct_centered_binary_trie_qrom_xor_table( - &mut b, - &address, - &target, - ROWS, - &table_words, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut public = vec![false; nq]; - for &q in address.iter().chain(target.iter()) { - public[q.0 as usize] = true; - } - - let mut cases = Vec::new(); - for addr in 0..(1u64 << ADDRESS_BITS) { - for before in 0..(1u64 << TARGET_BITS) { - cases.push((addr, before)); - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-binary-trie-qrom-roundtrip-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(addr, before)) in chunk.iter().enumerate() { - set_reg(&mut sim, &address, addr, shot); - set_reg(&mut sim, &target, before, shot); - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for q in 0..nq { - if !public[q] { - assert_eq!( - sim.qubit(QubitId(q as u32)) & live, - 0, - "scratch q{q} dirty in batch {batch}" - ); - } - } - for (shot, &(addr, before)) in chunk.iter().enumerate() { - assert_eq!(get_reg(&sim, &address, shot), addr); - assert_eq!(get_reg(&sim, &target, shot), before); - } - } - } - - #[test] - fn direct_centered_binary_trie_qrom_hits_round728_row_multiplier_budget() { - const ROWS: usize = 4_934; - const ADDRESS_BITS: usize = 13; - const TARGET_BITS: usize = 16; - - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_binary_trie_qrom_bench_phase_resources( - ROWS, - ADDRESS_BITS, - TARGET_BITS, - ); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - let expected_nodes = direct_centered_binary_trie_qrom_node_count(ROWS, ADDRESS_BITS); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N + expected_nodes); - assert_eq!(toffoli_ops, expected_nodes); - assert!(toffoli_ops <= 2 * ROWS + ADDRESS_BITS); - assert!(toffoli_ops <= 6 * ROWS); - assert_eq!(num_qubits as usize, 2 * N + ADDRESS_BITS + 1); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(peak_phase, "direct_centered_binary_trie_qrom_unary_walk"); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_binary_trie_qrom_unary_walk")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_binary_trie_qrom_clear_root")); - } - - #[test] - fn direct_centered_binary_trie_qrom_roundtrip_fits_round730_wide_payload_budget() { - const ROWS: usize = 4_934; - const ADDRESS_BITS: usize = 13; - const TARGET_BITS: usize = 84; - - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_binary_trie_qrom_roundtrip_bench_phase_resources( - ROWS, - ADDRESS_BITS, - TARGET_BITS, - ); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - let expected_nodes = direct_centered_binary_trie_qrom_node_count(ROWS, ADDRESS_BITS); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N + 2 * expected_nodes); - assert_eq!(toffoli_ops, 2 * expected_nodes); - assert_eq!(toffoli_ops, 19_746); - assert!(toffoli_ops <= 4 * ROWS + 2 * ADDRESS_BITS); - assert_eq!(num_qubits as usize, 2 * N + ADDRESS_BITS + 1); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!( - peak_phase, - "direct_centered_binary_trie_qrom_roundtrip_load_walk" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_binary_trie_qrom_roundtrip_load_walk")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_binary_trie_qrom_roundtrip_clear_walk")); - } - - #[test] - fn direct_centered_inline_predicate_finalizer_delta_fits_google_fast_width_if_replay_deleted() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_inline_predicate_finalizer_delta_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 3 * N - 1); - let scratch = num_qubits as usize - 2 * N; - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - assert_eq!( - scratch, - DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS - ); - assert_eq!(num_qubits as usize, 1_425); - assert!(toffoli_ops < 122_000); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!( - peak_phase, - "direct_centered_inline_predicate_delta_alloc_dual_history_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_predicate_compare")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); - assert!(!phases - .iter() - .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); - } - - #[test] - fn direct_centered_branch_retained_finalizer_toy_is_exact() { - const W: usize = 5; - let mut b = B::new(); - let remainder = b.alloc_qubits(W); - let divisor = b.alloc_qubits(W); - let branch = b.alloc_qubit(); - let gated = b.alloc_qubits(W); - let carry = b.alloc_qubit(); - emit_direct_centered_branch_retained_finalizer( - &mut b, &remainder, &divisor, branch, &gated, carry, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let modulus = 1u64 << W; - let mut cases = 0usize; - for divisor_value in 1..(1u64 << (W - 1)) { - for final_remainder in 0..divisor_value { - for branch_value in 0..=1u64 { - let prefinal = final_remainder + branch_value * divisor_value; - if prefinal >= modulus { - continue; - } - cases += 1; - let mut seed = Shake128::default(); - seed.update(&(cases as u64).to_le_bytes()); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - set_reg(&mut sim, &remainder, prefinal, 0); - set_reg(&mut sim, &divisor, divisor_value, 0); - if branch_value != 0 { - *sim.qubit_mut(branch) |= 1; - } - sim.apply(&b.ops); - assert_eq!(get_reg(&sim, &remainder, 0), final_remainder); - assert_eq!(get_reg(&sim, &divisor, 0), divisor_value); - assert_eq!((sim.qubit(branch) & 1), branch_value); - assert_eq!(sim.qubit(carry) & 1, 0); - assert_eq!(get_reg(&sim, &gated, 0), 0); - } - } - } - assert_eq!(cases, 240); - } - - #[test] - fn direct_centered_branch_retained_fast_finalizer_toy_is_exact() { - const W: usize = 5; - let mut b = B::new(); - let remainder = b.alloc_qubits(W); - let divisor = b.alloc_qubits(W); - let branch = b.alloc_qubit(); - let gated = b.alloc_qubits(W); - let nonnegative = b.alloc_qubit(); - let carries = b.alloc_qubits(W - 1); - emit_direct_centered_branch_retained_finalizer_fast( - &mut b, - &remainder, - &divisor, - branch, - &gated, - nonnegative, - &carries, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let modulus = 1u64 << W; - let mut cases = 0usize; - for divisor_value in 1..(1u64 << (W - 1)) { - for final_remainder in 0..divisor_value { - for branch_value in 0..=1u64 { - let prefinal = final_remainder + branch_value * divisor_value; - if prefinal >= modulus { - continue; - } - cases += 1; - let mut seed = Shake128::default(); - seed.update(&(0xFA57_0000u64 + cases as u64).to_le_bytes()); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - set_reg(&mut sim, &remainder, prefinal, 0); - set_reg(&mut sim, &divisor, divisor_value, 0); - if branch_value != 0 { - *sim.qubit_mut(branch) |= 1; - } - sim.apply(&b.ops); - assert_eq!(get_reg(&sim, &remainder, 0), final_remainder); - assert_eq!(get_reg(&sim, &divisor, 0), divisor_value); - assert_eq!(sim.qubit(branch) & 1, branch_value); - assert_eq!(sim.qubit(nonnegative) & 1, 0); - assert_eq!(get_reg(&sim, &gated, 0), 0); - assert_eq!(get_reg(&sim, &carries, 0), 0); - assert_eq!(sim.global_phase() & 1, 0); - } - } - } - assert_eq!(cases, 240); - } - - #[test] - fn direct_centered_branch_retained_finalizer_component_has_expected_shape() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_branch_retained_finalizer_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N); - assert_eq!(num_qubits as usize, 2 * N + N + 2); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, 4 * N - 2); - assert_eq!( - peak_phase, - "direct_centered_branch_retained_finalizer_google_abi" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_finalizer_subtract")); - } - - #[test] - fn direct_centered_branch_digit_clean_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_branch_digit_clean_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 3 * N); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, 3 * N - 2); - assert_eq!( - peak_phase, - "direct_centered_branch_digit_clean_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); - } - - #[test] - fn direct_centered_remainder_abs_swap_transition_toy_is_exact() { - const W: usize = 4; - let mut b = B::new(); - let low_path = b.alloc_qubits(W); - let divisor = b.alloc_qubits(W); - let branch = b.alloc_qubit(); - let gated = b.alloc_qubits(W); - let carries = b.alloc_qubits(W - 1); - emit_direct_centered_remainder_abs_swap_transition( - &mut b, &low_path, &divisor, branch, &gated, &carries, - ); - - let nq = b.next_qubit as usize; - let nb = b.next_bit as usize; - let mut cases = Vec::new(); - for divisor_value in 1..(1u64 << W) { - for low_value in 0..divisor_value { - let branch_value = u64::from(2 * low_value >= divisor_value); - let next_divisor = if branch_value == 0 { - low_value - } else { - divisor_value - low_value - }; - cases.push((low_value, divisor_value, branch_value, next_divisor)); - } - } - - let mut seed = Shake128::default(); - seed.update(b"direct-centered-remainder-abs-swap-transition-toy"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(nq, nb, &mut xof); - for (batch, chunk) in cases.chunks(64).enumerate() { - sim.clear_for_shot(); - for (shot, &(low_value, divisor_value, branch_value, _next_divisor)) in - chunk.iter().enumerate() - { - set_reg(&mut sim, &low_path, low_value, shot); - set_reg(&mut sim, &divisor, divisor_value, shot); - if branch_value != 0 { - *sim.qubit_mut(branch) |= 1u64 << shot; - } - } - sim.apply(&b.ops); - let live = if chunk.len() == 64 { - u64::MAX - } else { - (1u64 << chunk.len()) - 1 - }; - assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); - for &wire in &gated { - assert_eq!(sim.qubit(wire) & live, 0, "gated divisor dirty"); - } - for &wire in &carries { - assert_eq!(sim.qubit(wire) & live, 0, "borrowed carry dirty"); - } - for (shot, &(_low_value, divisor_value, branch_value, next_divisor)) in - chunk.iter().enumerate() - { - assert_eq!(get_reg(&sim, &low_path, shot), divisor_value); - assert_eq!(get_reg(&sim, &divisor, shot), next_divisor); - assert_eq!((sim.qubit(branch) >> shot) & 1, branch_value); - } - } - } - - #[test] - fn direct_centered_row_transition_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_row_transition_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - let hmr_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::Hmr)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 4 * N - 1); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, 2 * N - 1); - assert_eq!(hmr_ops, N - 1 + N); - assert_eq!(peak_phase, "direct_centered_row_transition_alloc_envelope"); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_row_transition_abs_add")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_row_transition_swap_next_state")); - } - - #[test] - fn direct_centered_branch_replay_finalizer_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_branch_replay_finalizer_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!( - num_bits as usize, - 2 * N + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * N + (N - 1) - ); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!( - toffoli_ops, - DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * (3 * N - 2) - + (2 * DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS) - + (3 * N - 1) - ); - assert_eq!( - peak_phase, - "direct_centered_branch_replay_finalizer_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_replay_clear_nonfinal_history")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); - } - - #[test] - fn direct_centered_predicate_replay_finalizer_fit_materializes_full_tail_projection() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_predicate_replay_finalizer_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - let predicate_toggle_t = 2 * (N + 1); - let branch_digit_t = 3 * N - 2; - let finalizer_t = 3 * N - 1; - let expected_tail_t = DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS - * (2 * predicate_toggle_t + branch_digit_t) - + finalizer_t; - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!( - num_bits as usize, - 2 * N + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * N + (N - 1) - ); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, expected_tail_t); - assert_eq!(toffoli_ops, 210_665); - assert_eq!( - peak_phase, - "direct_centered_predicate_replay_finalizer_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_predicate_compare")); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); - } - - #[test] - fn direct_centered_sidecar_finalizer_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_sidecar_finalizer_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, 4 * N - 2); - assert_eq!( - peak_phase, - "direct_centered_sidecar_finalizer_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_finalizer_gate_divisor")); - } - - #[test] - fn direct_centered_sidecar_fast_finalizer_fit_stays_inside_round714_envelope() { - let (ops, phases, peak_qubits, peak_phase) = - build_direct_centered_sidecar_fast_finalizer_fit_bench_phase_resources(); - let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); - let toffoli_ops = ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(); - - assert_eq!(regs.len(), 4); - assert_eq!(num_registers, 4); - assert_eq!(num_bits as usize, 2 * N + N - 1); - assert_eq!( - num_qubits as usize, - 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS - ); - assert_eq!(peak_qubits as usize, num_qubits as usize); - assert_eq!(toffoli_ops, 3 * N - 1); - assert_eq!( - peak_phase, - "direct_centered_sidecar_fast_finalizer_alloc_envelope" - ); - assert!(phases - .iter() - .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); - } -} + +use alloy_primitives::U256; +use sha3::{ + digest::{ExtendableOutput, Update, XofReader}, + Shake256, +}; + +use crate::circuit::{analyze_ops, BitId, Op, OperationType, QubitId, QubitOrBit, RegisterId}; +use crate::sim::Simulator; +use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; + +pub mod venting; + +mod emit; +pub(crate) use emit::*; + +mod arith; +pub(crate) use arith::*; + +mod rounds; +pub(crate) use rounds::*; + +pub mod trailmix_ludicrous; +mod single_ccx_fanout; + +thread_local! { + static D1_PHASE_CORRECTED_PRODUCT_CORE_SCOPE: std::cell::Cell = + std::cell::Cell::new(false); + static OP_SITE_TRACE: std::cell::RefCell> = + std::cell::RefCell::new(Vec::new()); + static OP_TRACE_CONTEXT: std::cell::Cell = std::cell::Cell::new(0); +} + +fn d1_phase_corrected_product_core_active() -> bool { + D1_PHASE_CORRECTED_PRODUCT_CORE_SCOPE.with(|scope| scope.get()) +} + +pub type OpSite = (&'static str, u32, u32); + +pub(crate) fn op_site_trace_enabled() -> bool { + static ENABLED: std::sync::OnceLock = std::sync::OnceLock::new(); + *ENABLED.get_or_init(|| std::env::var_os("TRACE_OP_SITES").is_some()) +} + +fn reset_op_site_trace() { + if op_site_trace_enabled() { + OP_SITE_TRACE.with(|sites| sites.borrow_mut().clear()); + } +} + +fn record_op_site(site: OpSite) { + if op_site_trace_enabled() { + OP_SITE_TRACE.with(|sites| sites.borrow_mut().push(site)); + } +} + +pub(crate) fn set_op_trace_context(context: u32) -> u32 { + if !op_site_trace_enabled() { + return 0; + } + OP_TRACE_CONTEXT.with(|slot| { + let old = slot.get(); + slot.set(context); + old + }) +} + +pub(crate) fn restore_op_trace_context(context: u32) { + if op_site_trace_enabled() { + OP_TRACE_CONTEXT.with(|slot| slot.set(context)); + } +} + +pub(crate) fn take_op_site_trace_for_constprop(expected_len: usize) -> Option> { + if !op_site_trace_enabled() { + return None; + } + OP_SITE_TRACE.with(|sites| { + let mut sites = sites.borrow_mut(); + assert_eq!( + sites.len(), + expected_len, + "op site trace length before constprop" + ); + Some(std::mem::take(&mut *sites)) + }) +} + +pub(crate) fn set_op_site_trace_from_constprop(sites: Vec) { + if op_site_trace_enabled() { + OP_SITE_TRACE.with(|slot| *slot.borrow_mut() = sites); + } +} + +pub fn take_last_op_sites() -> Vec { + OP_SITE_TRACE.with(|sites| std::mem::take(&mut *sites.borrow_mut())) +} + +pub struct B { + pub ops: Vec, + pub count_only: bool, + pub counted_ops: usize, + pub counted_kind_ops: [usize; 18], + pub counted_phase_kind_ops: [usize; 18], + pub counted_phase_start_ops: usize, + pub counted_phase_rows: Vec, + pub counted_registers: Vec>, + pub next_qubit: u32, + pub next_bit: u32, + pub next_register: u32, + pub free_qubits: Vec, + pub active_qubits: u32, + pub peak_qubits: u32, + pub peak_ops_idx: usize, + pub peak_phase: &'static str, + pub phase: &'static str, + pub peak_log: Vec<(u32, &'static str, usize)>, + pub phase_active_max: std::collections::BTreeMap<&'static str, u32>, + pub phase_active_regions: Vec<(usize, &'static str, u32)>, + pub current_phase_active_max: u32, + + pub phase_transitions: Vec<(usize, &'static str)>, + pub active_timeline: Vec<(usize, u32)>, + + pub k2_shift2_log: Vec, + + pub b0: B0Census, +} + +#[derive(Default)] +pub struct B0Census { + pub enabled: bool, + pub win_lo: usize, + pub win_hi: usize, + + pub owner: std::collections::HashMap, + + pub batch_ctx: Option<(&'static str, u32)>, + pub best_active: u32, + pub best_ops: usize, + pub best_phase: &'static str, + pub best_snapshot: Option>, + pub printed: bool, + + pub phase_filter: Option, +} + +#[derive(Clone, Copy)] +struct CountSnapshot { + ops: usize, + kind_ops: [usize; 18], + phase_kind_ops: [usize; 18], + phase_start_ops: usize, + phase_rows_len: usize, + phase: &'static str, +} + +#[derive(Clone, Debug)] +pub struct PhaseResource { + pub phase: &'static str, + pub start: usize, + pub end: usize, + pub ops: usize, + pub toffoli_ops: usize, + pub ccx_ops: usize, + pub ccz_ops: usize, + pub hmr_ops: usize, + pub r_ops: usize, +} + +impl B { + fn new() -> Self { + reset_op_site_trace(); + Self { + ops: Vec::new(), + count_only: false, + counted_ops: 0, + counted_kind_ops: [0; 18], + counted_phase_kind_ops: [0; 18], + counted_phase_start_ops: 0, + counted_phase_rows: Vec::new(), + counted_registers: Vec::new(), + next_qubit: 0, + next_bit: 0, + next_register: 0, + free_qubits: Vec::new(), + active_qubits: 0, + peak_qubits: 0, + peak_ops_idx: 0, + peak_phase: "", + phase: "init", + peak_log: Vec::new(), + phase_active_max: std::collections::BTreeMap::new(), + phase_active_regions: Vec::new(), + current_phase_active_max: 0, + phase_transitions: Vec::new(), + active_timeline: Vec::new(), + k2_shift2_log: Vec::new(), + b0: { + let lo = std::env::var("B0_WIN_LO") + .ok() + .and_then(|v| v.parse::().ok()); + let hi = std::env::var("B0_WIN_HI") + .ok() + .and_then(|v| v.parse::().ok()); + match (lo, hi) { + (Some(lo), Some(hi)) => B0Census { + enabled: true, + win_lo: lo, + win_hi: hi, + phase_filter: std::env::var("B0_PHASE").ok().filter(|s| !s.is_empty()), + ..Default::default() + }, + _ => B0Census::default(), + } + }, + } + } + fn new_count_only() -> Self { + let mut b = Self::new(); + b.count_only = true; + b + } + + pub fn new_for_test() -> Self { + Self::new() + } + pub fn take_ops(&mut self) -> Vec { + std::mem::take(&mut self.ops) + } + #[track_caller] + fn push_op(&mut self, op: Op) { + self.counted_ops += 1; + self.counted_kind_ops[op.kind as usize] += 1; + self.counted_phase_kind_ops[op.kind as usize] += 1; + if !self.count_only { + let loc = std::panic::Location::caller(); + let context = OP_TRACE_CONTEXT.with(|slot| slot.get()); + record_op_site((loc.file(), loc.line(), context)); + self.ops.push(op); + } + } + fn count_snapshot(&self) -> CountSnapshot { + CountSnapshot { + ops: self.counted_ops, + kind_ops: self.counted_kind_ops, + phase_kind_ops: self.counted_phase_kind_ops, + phase_start_ops: self.counted_phase_start_ops, + phase_rows_len: self.counted_phase_rows.len(), + phase: self.phase, + } + } + fn count_delta_since(&self, snap: CountSnapshot) -> [usize; 18] { + let mut out = [0usize; 18]; + for (idx, slot) in out.iter_mut().enumerate() { + *slot = self.counted_kind_ops[idx] - snap.kind_ops[idx]; + } + out + } + fn restore_count_snapshot(&mut self, snap: CountSnapshot) { + self.counted_ops = snap.ops; + self.counted_kind_ops = snap.kind_ops; + self.counted_phase_kind_ops = snap.phase_kind_ops; + self.counted_phase_start_ops = snap.phase_start_ops; + self.counted_phase_rows.truncate(snap.phase_rows_len); + self.phase = snap.phase; + } + fn add_counted_kind(&mut self, kind: OperationType, count: usize) { + self.counted_ops += count; + self.counted_kind_ops[kind as usize] += count; + self.counted_phase_kind_ops[kind as usize] += count; + } + fn current_ops_len(&self) -> usize { + if self.count_only { + self.counted_ops + } else { + self.ops.len() + } + } + fn close_counted_phase(&mut self) { + if !self.count_only { + return; + } + let start = self.counted_phase_start_ops; + let end = self.counted_ops; + if start < end { + let ccx_ops = self.counted_phase_kind_ops[OperationType::CCX as usize]; + let ccz_ops = self.counted_phase_kind_ops[OperationType::CCZ as usize]; + let hmr_ops = self.counted_phase_kind_ops[OperationType::Hmr as usize]; + let r_ops = self.counted_phase_kind_ops[OperationType::R as usize]; + self.counted_phase_rows.push(PhaseResource { + phase: self.phase, + start, + end, + ops: end - start, + toffoli_ops: ccx_ops + ccz_ops, + ccx_ops, + ccz_ops, + hmr_ops, + r_ops, + }); + } + self.counted_phase_start_ops = self.counted_ops; + self.counted_phase_kind_ops = [0; 18]; + } + fn set_phase(&mut self, p: &'static str) { + self.close_phase_active_region(); + self.close_counted_phase(); + self.phase = p; + if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { + self.current_phase_active_max = self.active_qubits; + } + self.phase_transitions.push((self.current_ops_len(), p)); + } + fn record_active_timeline(&mut self) { + if std::env::var("PROFILE_ACTIVE_TIMELINE").is_ok() { + self.active_timeline + .push((self.current_ops_len(), self.active_qubits)); + } + } + fn record_phase_active(&mut self) { + self.record_active_timeline(); + if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { + let entry = self.phase_active_max.entry(self.phase).or_insert(0); + if self.active_qubits > *entry { + *entry = self.active_qubits; + } + if self.active_qubits > self.current_phase_active_max { + self.current_phase_active_max = self.active_qubits; + } + } + } + fn close_phase_active_region(&mut self) { + if std::env::var("TRACE_PHASE_ACTIVE").is_ok() && self.current_phase_active_max > 0 { + self.phase_active_regions.push(( + self.current_ops_len(), + self.phase, + self.current_phase_active_max, + )); + self.current_phase_active_max = 0; + } + } + + fn b0_on_alloc(&mut self, qid: u64, file: &'static str, line: u32) { + if !self.b0.enabled || self.count_only { + return; + } + let ctx = match self.b0.batch_ctx { + Some((f, l)) => (self.phase, f, l), + None => (self.phase, file, line), + }; + self.b0.owner.insert(qid, ctx); + self.b0_sample(); + } + fn b0_on_free(&mut self, qid: u64) { + if !self.b0.enabled || self.count_only { + return; + } + self.b0.owner.remove(&qid); + self.b0_sample(); + } + fn b0_sample(&mut self) { + if self.b0.printed { + return; + } + let cur = self.current_ops_len(); + if cur > self.b0.win_hi { + self.b0_print(); + return; + } + if cur >= self.b0.win_lo && self.active_qubits > self.b0.best_active { + if let Some(f) = &self.b0.phase_filter { + if !self.phase.contains(f.as_str()) { + return; + } + } + self.b0.best_active = self.active_qubits; + self.b0.best_ops = cur; + self.b0.best_phase = self.phase; + self.b0.best_snapshot = Some(self.b0.owner.clone()); + } + } + + pub fn b0_finalize(&mut self) { + if self.b0.enabled && !self.b0.printed { + self.b0_print(); + } + } + fn b0_print(&mut self) { + self.b0.printed = true; + let snap = match self.b0.best_snapshot.take() { + Some(s) => s, + None => return, + }; + let mut hist: std::collections::HashMap<(&'static str, &'static str, u32), u32> = + std::collections::HashMap::new(); + for v in snap.values() { + *hist.entry(*v).or_insert(0) += 1; + } + let mut rows: Vec<((&'static str, &'static str, u32), u32)> = hist.into_iter().collect(); + rows.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0))); + eprintln!( + "B0_CENSUS_BEGIN best_active={} best_ops={} best_phase={} n_live={} n_groups={} win=[{},{}]", + self.b0.best_active, + self.b0.best_ops, + self.b0.best_phase, + snap.len(), + rows.len(), + self.b0.win_lo, + self.b0.win_hi + ); + for ((phase, file, line), cnt) in &rows { + eprintln!("B0_OWN count={cnt} phase={phase} caller={file}:{line}"); + } + eprintln!("B0_CENSUS_END"); + } + #[track_caller] + fn alloc_qubit(&mut self) -> QubitId { + self.active_qubits += 1; + self.record_phase_active(); + if let Ok(threshold) = std::env::var("TRACE_ALLOC_NEAR_PEAK") + .ok() + .and_then(|value| value.parse::().ok()) + .ok_or(()) + { + if self.active_qubits >= threshold { + let caller = std::panic::Location::caller(); + eprintln!( + "ALLOC_NEAR active={} next_idx={} phase='{}' ops_idx={} free_pool={} caller={}:{}", + self.active_qubits, + self.next_qubit, + self.phase, + self.current_ops_len(), + self.free_qubits.len(), + caller.file(), + caller.line(), + ); + } + } + if self.active_qubits > self.peak_qubits { + self.peak_qubits = self.active_qubits; + self.peak_ops_idx = self.current_ops_len(); + self.peak_phase = self.phase; + if std::env::var("TRACE_EACH_PEAK").is_ok() { + eprintln!( + "PEAK active={} next_idx={} phase='{}' ops_idx={}", + self.active_qubits, + self.next_qubit, + self.phase, + self.current_ops_len() + ); + } + } + if std::env::var("TRACE_PEAK").is_ok() && self.active_qubits + 10 >= self.peak_qubits { + self.peak_log + .push((self.active_qubits, self.phase, self.current_ops_len())); + } + let qid = if let Some(q) = self.free_qubits.pop() { + QubitId(q.into()) + } else { + let q = self.next_qubit; + self.next_qubit += 1; + QubitId(q.into()) + }; + if self.b0.enabled && !self.count_only { + let caller = std::panic::Location::caller(); + self.b0_on_alloc(qid.0, caller.file(), caller.line()); + } + qid + } + #[track_caller] + fn alloc_qubits(&mut self, n: usize) -> Vec { + if self.b0.enabled { + let c = std::panic::Location::caller(); + self.b0.batch_ctx = Some((c.file(), c.line())); + let out = (0..n).map(|_| self.alloc_qubit()).collect(); + self.b0.batch_ctx = None; + out + } else { + (0..n).map(|_| self.alloc_qubit()).collect() + } + } + fn alloc_bit(&mut self) -> BitId { + let b = self.next_bit; + self.next_bit += 1; + BitId(b.into()) + } + fn alloc_bits(&mut self, n: usize) -> Vec { + (0..n).map(|_| self.alloc_bit()).collect() + } + fn free(&mut self, q: QubitId) { + self.r(q); + self.free_qubits + .push(q.0.try_into().expect("qubit id fits in u32")); + if self.active_qubits > 0 { + self.active_qubits -= 1; + } + self.record_active_timeline(); + self.b0_on_free(q.0); + } + fn free_vec(&mut self, qs: &[QubitId]) { + for &q in qs { + self.free(q); + } + } + fn reacquire(&mut self, q: QubitId) { + let pos = self + .free_qubits + .iter() + .position(|&free_q| u64::from(free_q) == q.0) + .expect("reacquire qubit that is not currently free"); + self.free_qubits.swap_remove(pos); + self.active_qubits += 1; + self.record_phase_active(); + if self.active_qubits > self.peak_qubits { + self.peak_qubits = self.active_qubits; + self.peak_ops_idx = self.current_ops_len(); + self.peak_phase = self.phase; + if std::env::var("TRACE_EACH_PEAK").is_ok() { + eprintln!( + "PEAK active={} next_idx={} phase='{}' ops_idx={}", + self.active_qubits, + self.next_qubit, + self.phase, + self.current_ops_len() + ); + } + } + if std::env::var("TRACE_PEAK").is_ok() && self.active_qubits + 10 >= self.peak_qubits { + self.peak_log + .push((self.active_qubits, self.phase, self.current_ops_len())); + } + + if self.b0.enabled && !self.count_only { + self.b0_on_alloc(q.0, "reacquire", 0); + } + } + fn reacquire_vec(&mut self, qs: &[QubitId]) { + for &q in qs { + self.reacquire(q); + } + } + fn declare_qubit_register(&mut self, qs: &[QubitId]) { + let r = RegisterId(self.next_register.into()); + self.next_register += 1; + for &q in qs { + while self.counted_registers.len() <= r.0 as usize { + self.counted_registers.push(Vec::new()); + } + self.counted_registers[r.0 as usize].push(QubitOrBit::Qubit(q)); + let mut op = Op::empty(); + op.kind = OperationType::AppendToRegister; + op.q_target = q; + op.r_target = r; + self.push_op(op); + } + let mut op = Op::empty(); + op.kind = OperationType::Register; + op.r_target = r; + self.push_op(op); + } + fn declare_bit_register(&mut self, bs: &[BitId]) { + let r = RegisterId(self.next_register.into()); + self.next_register += 1; + for &b in bs { + while self.counted_registers.len() <= r.0 as usize { + self.counted_registers.push(Vec::new()); + } + self.counted_registers[r.0 as usize].push(QubitOrBit::Bit(b)); + let mut op = Op::empty(); + op.kind = OperationType::AppendToRegister; + op.c_target = b; + op.r_target = r; + self.push_op(op); + } + let mut op = Op::empty(); + op.kind = OperationType::Register; + op.r_target = r; + self.push_op(op); + } + fn x(&mut self, q: QubitId) { + let mut op = Op::empty(); + op.kind = OperationType::X; + op.q_target = q; + self.push_op(op); + } + fn cx(&mut self, ctrl: QubitId, tgt: QubitId) { + if ctrl == tgt { + panic!("invalid CX with aliased control/target {:?}", ctrl); + } + let mut op = Op::empty(); + op.kind = OperationType::CX; + op.q_control1 = ctrl; + op.q_target = tgt; + self.push_op(op); + } + #[track_caller] + fn ccx(&mut self, c1: QubitId, c2: QubitId, tgt: QubitId) { + if c1 == c2 { + if c1 != tgt { + self.cx(c1, tgt); + } + return; + } + if c1 == tgt || c2 == tgt { + panic!( + "invalid CCX with target aliased to a control: {:?}, {:?}, {:?}", + c1, c2, tgt + ); + } + let mut op = Op::empty(); + op.kind = OperationType::CCX; + op.q_control2 = c1; + op.q_control1 = c2; + op.q_target = tgt; + self.push_op(op); + } + fn cz(&mut self, a: QubitId, b: QubitId) { + if a == b { + let mut op = Op::empty(); + op.kind = OperationType::Z; + op.q_target = a; + self.push_op(op); + return; + } + let mut op = Op::empty(); + op.kind = OperationType::CZ; + op.q_control1 = a; + op.q_target = b; + self.push_op(op); + } + fn push_condition(&mut self, cond: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::PushCondition; + op.c_condition = cond; + self.push_op(op); + } + fn pop_condition(&mut self) { + let mut op = Op::empty(); + op.kind = OperationType::PopCondition; + self.push_op(op); + } + fn swap(&mut self, a: QubitId, b: QubitId) { + if a == b { + return; + } + let mut op = Op::empty(); + op.kind = OperationType::Swap; + op.q_control1 = a; + op.q_target = b; + self.push_op(op); + } + fn r(&mut self, q: QubitId) { + let mut op = Op::empty(); + op.kind = OperationType::R; + op.q_target = q; + self.push_op(op); + } + fn x_if(&mut self, q: QubitId, cond: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::X; + op.q_target = q; + op.c_condition = cond; + self.push_op(op); + } + + fn hmr(&mut self, q: QubitId, c: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::Hmr; + op.q_target = q; + op.c_target = c; + self.push_op(op); + } + + fn z_if(&mut self, q: QubitId, cond: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::Z; + op.q_target = q; + op.c_condition = cond; + self.push_op(op); + } + fn cz_if(&mut self, a: QubitId, b: QubitId, cond: BitId) { + if a == b { + self.z_if(a, cond); + return; + } + let mut op = Op::empty(); + op.kind = OperationType::CZ; + op.q_control1 = a; + op.q_target = b; + op.c_condition = cond; + self.push_op(op); + } + + fn bit_store0(&mut self, dst: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::BitStore0; + op.c_target = dst; + self.push_op(op); + } + + fn bit_store1(&mut self, dst: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::BitStore1; + op.c_target = dst; + self.push_op(op); + } + + fn bit_invert(&mut self, dst: BitId) { + let mut op = Op::empty(); + op.kind = OperationType::BitInvert; + op.c_target = dst; + self.push_op(op); + } + + fn bit_copy(&mut self, dst: BitId, a: BitId) { + self.bit_store0(dst); + self.push_condition(a); + self.bit_store1(dst); + self.pop_condition(); + } + + fn bit_xor_into(&mut self, dst: BitId, a: BitId) { + self.push_condition(a); + self.bit_invert(dst); + self.pop_condition(); + } + + fn bit_and_xor_into(&mut self, dst: BitId, a: BitId, b: BitId) { + self.push_condition(a); + self.push_condition(b); + self.bit_invert(dst); + self.pop_condition(); + self.pop_condition(); + } +} + +pub const N: usize = 256; + +pub const SECP256K1_P: U256 = U256::from_limbs([ + 0xFFFFFFFEFFFFFC2F, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, + 0xFFFFFFFFFFFFFFFF, +]); + +pub const ONE_INV_DX3_AFFINE_PA_ENV: &str = "ONE_INV_DX3_AFFINE_PA"; +pub const ONE_INV_DX3_AFFINE_PA_BLOCKER: &str = + "ONE_INV_DX3_AFFINE_PA_BLOCKED: the dx^3 algebra gives Rx and Ry with \ + one inversion of w=dx^3, but a clean in-place Google-ABI circuit must \ + also uncompute w, dx^2, and the Kaliski input copy after tx/ty have been \ + overwritten by Rx/Ry. At that point dx is recoverable only by the inverse \ + affine add P=R-Q, whose denominator is Rx-Qx. That is a second inversion, \ + or else a retained 256-bit dx witness / dirty reset, so this path cannot \ + emit a clean one-inversion four-register PA."; + +fn direct_const_walks_enabled() -> bool { + std::env::var("KAL_DIRECT_CONST_WALKS").ok().as_deref() == Some("1") +} + +fn secp_direct_const_arith_enabled() -> bool { + std::env::var("SECP_DIRECT_CONST_ARITH").ok().as_deref() == Some("1") +} + +fn r84_lowq_enabled() -> bool { + std::env::var("R84_LOWQ").ok().as_deref() == Some("1") +} + +fn r84_lowq_cin_borrow_enabled() -> bool { + std::env::var("R84_LOWQ_CIN_BORROW").ok().as_deref() == Some("1") +} + +fn kal_vent_modadd_enabled() -> bool { + std::env::var("KAL_VENT_MODADD").ok().as_deref() == Some("1") +} + +fn kal_vent_halve_enabled() -> bool { + std::env::var("KAL_VENT_HALVE").ok().as_deref() == Some("1") +} + +const ALT_SEED_COUNT: usize = 5; +const ALT_SEED_COMMIT: usize = 24; +const ALT_SEED_SHOTS: usize = 4096; +const ALT_SEED_CLASSICAL_LIMIT: usize = 2; + +fn secp256k1_curve() -> WeierstrassEllipticCurve { + WeierstrassEllipticCurve { + modulus: U256::from_str_radix( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + 16, + ) + .unwrap(), + a: U256::from(0), + b: U256::from(7), + gx: U256::from_str_radix( + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + 16, + ) + .unwrap(), + gy: U256::from_str_radix( + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + 16, + ) + .unwrap(), + order: U256::from_str_radix( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + 16, + ) + .unwrap(), + } +} + +fn alt_seed_xof(ops: &[Op], tag: u64) -> sha3::Shake256Reader { + let mut hasher = Shake256::default(); + hasher.update(b"quantum_ecc-alt-seed-v1"); + hasher.update(&tag.to_le_bytes()); + hasher.update(&(ops.len() as u64).to_le_bytes()); + for op in ops { + hasher.update(&[op.kind as u8]); + hasher.update(&op.q_control2.0.to_le_bytes()); + hasher.update(&op.q_control1.0.to_le_bytes()); + hasher.update(&op.q_target.0.to_le_bytes()); + hasher.update(&op.c_target.0.to_le_bytes()); + hasher.update(&op.c_condition.0.to_le_bytes()); + hasher.update(&op.r_target.0.to_le_bytes()); + } + hasher.finalize_xof() +} + +fn run_alt_seed_checks(ops: &[Op]) { + let n_seeds = if std::env::var("ALT_SEED_COMMIT").is_ok() { + ALT_SEED_COMMIT + } else { + ALT_SEED_COUNT + }; + + let curve = secp256k1_curve(); + let (total_qubits, num_bits, _num_regs, regs) = analyze_ops(ops.iter()); + assert!(regs.len() == 4); + for (i, r) in regs.iter().enumerate() { + assert_eq!(r.len(), 256, "register {i} should be 256 wide"); + } + for q in ®s[0] { + assert!(matches!(q, QubitOrBit::Qubit(_))); + } + for q in ®s[1] { + assert!(matches!(q, QubitOrBit::Qubit(_))); + } + for q in ®s[2] { + assert!(matches!(q, QubitOrBit::Bit(_))); + } + for q in ®s[3] { + assert!(matches!(q, QubitOrBit::Bit(_))); + } + + eprintln!( + "=== alternate-seed diagnostic ({} seeds × {} shots, classical_limit={}, parallel) ===", + n_seeds, ALT_SEED_SHOTS, ALT_SEED_CLASSICAL_LIMIT, + ); + + let results: Vec<(u64, usize, usize, usize)> = std::thread::scope(|scope| { + let curve = &curve; + let regs = ®s; + let mut handles = Vec::with_capacity(n_seeds); + for tag_idx in 0..n_seeds { + let tag = (tag_idx as u64) + 1; + let handle = scope.spawn(move || { + const BATCH: usize = 64; + let mut xof = alt_seed_xof(ops, tag); + let mut targets = Vec::with_capacity(ALT_SEED_SHOTS); + let mut offsets = Vec::with_capacity(ALT_SEED_SHOTS); + let mut expected = Vec::with_capacity(ALT_SEED_SHOTS); + while targets.len() < ALT_SEED_SHOTS { + let mut rb = [[0u8; 32]; 2]; + xof.read(&mut rb[0]); + xof.read(&mut rb[1]); + let k1 = U256::from_le_bytes(rb[0]); + let k2 = U256::from_le_bytes(rb[1]); + let t = curve.mul(curve.gx, curve.gy, k1); + let o = curve.mul(curve.gx, curve.gy, k2); + if t.0 == o.0 { + continue; + } + if t.0.is_zero() && t.1.is_zero() { + continue; + } + if o.0.is_zero() && o.1.is_zero() { + continue; + } + let e = curve.add(t.0, t.1, o.0, o.1); + targets.push(t); + offsets.push(o); + expected.push(e); + } + + let mut sim = Simulator::new(total_qubits as usize, num_bits as usize, &mut xof); + let mut classical_failures = 0usize; + let mut phase_garbage_batches = 0usize; + let mut ancilla_garbage_batches = 0usize; + let num_batches = (ALT_SEED_SHOTS + BATCH - 1) / BATCH; + for batch in 0..num_batches { + let bs = BATCH.min(ALT_SEED_SHOTS - batch * BATCH); + let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; + sim.clear_for_shot(); + for shot in 0..bs { + let i = batch * BATCH + shot; + sim.set_register(®s[0], targets[i].0, shot); + sim.set_register(®s[1], targets[i].1, shot); + sim.set_register(®s[2], offsets[i].0, shot); + sim.set_register(®s[3], offsets[i].1, shot); + } + sim.apply_iter(ops.iter()); + for shot in 0..bs { + let i = batch * BATCH + shot; + let gx = sim.get_register(®s[0], shot); + let gy = sim.get_register(®s[1], shot); + if gx != expected[i].0 || gy != expected[i].1 { + classical_failures += 1; + } + } + let phase = sim.phase & cond_mask; + if phase != 0 { + phase_garbage_batches += 1; + } + for register in regs { + for qb in register { + if let QubitOrBit::Qubit(q) = *qb { + *sim.qubit_mut(q) = 0; + } + } + } + let mut garbage = false; + for q in 0..total_qubits { + if (sim.qubit(QubitId(q)) & cond_mask) != 0 { + garbage = true; + break; + } + } + if garbage { + ancilla_garbage_batches += 1; + } + } + ( + tag, + classical_failures, + phase_garbage_batches, + ancilla_garbage_batches, + ) + }); + handles.push(handle); + } + handles.into_iter().map(|h| h.join().unwrap()).collect() + }); + + let mut total_classical = 0usize; + let mut total_phase_batches = 0usize; + let mut total_ancilla_batches = 0usize; + for (tag, classical_failures, phase_garbage_batches, ancilla_garbage_batches) in &results { + total_classical += classical_failures; + total_phase_batches += phase_garbage_batches; + total_ancilla_batches += ancilla_garbage_batches; + eprintln!( + "ALT-SEED tag={} classical_mismatches={} phase_batches={} ancilla_batches={}", + tag, classical_failures, phase_garbage_batches, ancilla_garbage_batches, + ); + } + + println!("METRIC altseed_classical_total={}", total_classical); + println!("METRIC altseed_phase_batches_total={}", total_phase_batches); + println!( + "METRIC altseed_ancilla_batches_total={}", + total_ancilla_batches + ); + + let phase_limit: usize = std::env::var("ALT_SEED_PHASE_LIMIT") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(0); + assert!( + total_phase_batches <= phase_limit, + "ALT-SEED PHASE FAILURE: {} phase-garbage batches (limit {}) across {} seeds × {} shots", + total_phase_batches, + phase_limit, + n_seeds, + ALT_SEED_SHOTS, + ); + assert!( + total_ancilla_batches == 0, + "ALT-SEED ANCILLA FAILURE: {} ancilla-garbage batches across {} seeds × {} shots", + total_ancilla_batches, + n_seeds, + ALT_SEED_SHOTS, + ); + assert!( + total_classical <= ALT_SEED_CLASSICAL_LIMIT, + "ALT-SEED CLASSICAL FAILURE: {} classical mismatches exceeds limit {} across {} seeds × {} shots", + total_classical, + ALT_SEED_CLASSICAL_LIMIT, + n_seeds, + ALT_SEED_SHOTS, + ); +} + +#[cfg(test)] +mod d1_inplace_lowerer_tests { + use super::*; + + fn build_product_ops() -> Vec { + let mut b = B::new(); + let h = b.alloc_qubits(N); + b.declare_qubit_register(&h); + let n = b.alloc_qubits(N); + b.declare_qubit_register(&n); + d1_inplace_product_lowerer_with_kaliski_clean(&mut b, &h, &n, SECP256K1_P, 400); + b.ops + } + + fn build_quotient_ops() -> Vec { + let mut b = B::new(); + let h = b.alloc_qubits(N); + b.declare_qubit_register(&h); + let n = b.alloc_qubits(N); + b.declare_qubit_register(&n); + d1_inplace_quotient_lowerer_with_kaliski_clean(&mut b, &h, &n, SECP256K1_P, 400); + b.ops + } + + fn toffoli_count(ops: &[Op]) -> usize { + ops.iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count() + } + + fn assert_two_word_d1_abi(ops: &[Op]) -> (u32, u32, u32) { + let (qubits, bits, registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(registers, 2); + assert_eq!(regs.len(), 2); + for reg in regs { + assert_eq!(reg.len(), N); + assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); + } + (qubits, bits, registers) + } + + #[test] + fn d1_inplace_product_lowerer_component_stats_are_pinned() { + let ops = build_product_ops(); + let (qubits, bits, registers) = assert_two_word_d1_abi(&ops); + assert_eq!(qubits, 2475); + assert_eq!(bits, 1_141_762); + assert_eq!(registers, 2); + assert_eq!(toffoli_count(&ops), 1_919_786); + } + + #[test] + fn d1_inplace_quotient_lowerer_component_stats_are_pinned() { + let ops = build_quotient_ops(); + let (qubits, bits, registers) = assert_two_word_d1_abi(&ops); + assert_eq!(qubits, 2475); + assert_eq!(bits, 0); + assert_eq!(registers, 2); + assert_eq!(toffoli_count(&ops), 1_919_786); + assert!(ops + .iter() + .all(|op| op.c_condition == crate::circuit::NO_BIT)); + assert!(ops.iter().all(|op| { + !matches!( + op.kind, + OperationType::Hmr | OperationType::Neg | OperationType::R + ) + })); + } + + #[test] + fn round8_output_side_cleanup_hook_is_env_gated() { + let saved = std::env::var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP").ok(); + std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP"); + assert!(!round8_qtail_output_side_cleanup_enabled()); + std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP", "1"); + assert!(round8_qtail_output_side_cleanup_enabled()); + match saved { + Some(value) => std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP", value), + None => std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP"), + } + } + + #[test] + fn round8_output_side_cleanup_hook_fails_closed_until_emitter_exists() { + let mut b = B::new(); + let tx = b.alloc_qubits(N); + let ty = b.alloc_qubits(N); + let ox = b.alloc_bits(N); + let oy = b.alloc_bits(N); + let panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { + round8_emit_output_side_cleanup_or_fail(&mut b, &tx, &ty, &ox, &oy, SECP256K1_P); + })) + .expect_err("output-side qtail hook must fail closed"); + let message = panic + .downcast_ref::() + .map(String::as_str) + .or_else(|| panic.downcast_ref::<&str>().copied()) + .expect("panic has message"); + assert!(message.contains("ROUND8_QTAIL_OUTPUT_SIDE_CLEANUP=1")); + assert!(message.contains("regular c=Rx-Qx inverse")); + assert!(message.contains("Round368 singular")); + assert!(message.contains("9024 Google")); + } + + #[test] + fn round8_output_side_regular_phase_repair_probe_is_separately_gated() { + let saved = std::env::var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR").ok(); + std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR"); + assert!(!round8_qtail_output_side_regular_phase_repair_enabled()); + std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR", "1"); + assert!(round8_qtail_output_side_regular_phase_repair_enabled()); + match saved { + Some(value) => { + std::env::set_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR", value) + } + None => std::env::remove_var("ROUND8_QTAIL_OUTPUT_SIDE_REGULAR_PHASE_REPAIR"), + } + } + + #[test] + fn round8_qtail_round217_product_reuse_hook_is_env_gated() { + let saved = std::env::var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE").ok(); + std::env::remove_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE"); + assert!(!round8_qtail_round217_product_reuse_enabled()); + std::env::set_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE", "1"); + assert!(round8_qtail_round217_product_reuse_enabled()); + match saved { + Some(value) => std::env::set_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE", value), + None => std::env::remove_var("ROUND8_QTAIL_ROUND217_PRODUCT_REUSE"), + } + } + + #[test] + fn round8_qtail_round217_product_reuse_hook_fails_closed_before_body() { + let plan = round218_b5_transport::round218_b5_source_live_product_lowerer_body_plan(); + assert!(!plan.body_emits_gates); + assert!(!plan.codegen_allowed_now); + assert_eq!( + plan.selected_route, + "round217_sampled_product_m2_contract_path" + ); + assert!(plan + .phase_blocks + .iter() + .any(|block| block.phase.contains("hash_history"))); + } + + #[test] + fn round218_source_live_product_lowerer_plan_rejects_full_source_alias() { + let plan = round218_b5_transport::round218_b5_source_live_product_lowerer_body_plan(); + assert!(!plan.body_emits_gates); + assert!(!plan.codegen_allowed_now); + assert!(plan + .phase_blocks + .iter() + .all(|block| !block.backend_primitive.contains("full_source_product"))); + assert!(plan + .missing_object + .contains("promotable no-history qtail/Round217 product splice")); + } +} + +fn set_default_env(name: &str, value: &str) { + if std::env::var_os(name).is_none() { + std::env::set_var(name, value); + } +} + +const Q1153_SECOND512_SUBMISSION_NONCE: &str = "193806910775884"; + +fn configure_q1153_second512_submission_defaults() { + set_default_env("DIALOG_TAIL_NONCE", Q1153_SECOND512_SUBMISSION_NONCE); + set_default_env("TLM_TARGET_Q", "1152"); + set_default_env("TLM_FOLD_CHUNK_ZERO_CIN", "1"); + set_default_env("TLM_FFG_MAX_G", "47"); + set_default_env("TLM_APPLY_ADD_SKIP_LASTK", "1"); + set_default_env("TLM_FOLD_TAIL_CINC", "1"); + set_default_env("TLM_CODEC_DIAMOND_MCX", "1"); + set_default_env("SINGLE_CCX_FANOUT_DISABLE", "0"); + + set_default_env("TLM_FFG_RELEASE_CY0_DURING_SUFFIX", "1"); + set_default_env("TLM_FFG_RELEASE_CY0_CALLS", "178,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,203,208,210,211,212,213,215,217,219,221,226,232,234,235,236,237,239"); + set_default_env("TLM_APPLY_FWD_CSWAP_SKIP_LAST", "2"); + set_default_env("TLM_COORD_RSUB_FUSED", "1"); + set_default_env("TLM_SQUARE_VENT_MARGIN", "0"); + set_default_env("TLM_COORD_ADD3X_TRUNC", "1"); + set_default_env("TLM_SQUARE_VENT_SHIFTED", "1"); + set_default_env("TLM_SQUARE_PEAK_CAP", "1152"); + set_default_env("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS", "1"); +} + +fn configure_ecdsafail_submission_route() { + set_default_env("DIALOG_GCD_VENTED_BODY_ODD_LOWBIT", "1"); + set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "19"); + set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1015"); + set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "18"); + set_default_env("DIALOG_GCD_FOLD_FREE_FIRST_HIGH_CARRY", "1"); + + set_default_env("DIALOG_GCD_ACTIVE_ITERATIONS", "258"); + set_default_env("DIALOG_GCD_APPLY_BOUNDARY_FREE_OWNED_DURING_REPLAY", "1"); + set_default_env("DIALOG_GCD_APPLY_BORROW_FUTURE_BOUNDARY_CARRIES", "1"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS", "20"); + set_default_env( + "DIALOG_GCD_APPLY_CHUNKED_F_CUTS", + "17,34,50,66,81,96,110,124,137,150,163,175,187,198,209,219,229,238,247", + ); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_MAX_BITS", "2"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_TARGET", "1168"); + set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "18"); + set_default_env("DIALOG_GCD_APPLY_IMPLICIT_HIGH_ZERO", "1"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_EXTRA", "3"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_MAP", "11:1,12:1,13:1"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_STEPS", "8,9,10"); + set_default_env( + "DIALOG_GCD_BODY_CARRY_BAND_TRIMS", + "0,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3", + ); + set_default_env("DIALOG_GCD_COMPARE_BITS", "46"); + set_default_env( + "DIALOG_GCD_COMPARE_STEP_BITS", + "181:48,194:48,199:48,202:48,207:48,212:48,216:48", + ); + set_default_env( + "DIALOG_GCD_FOLD_CARRY_TRUNC_STEP_WINDOWS", + "", + ); + set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "17"); + set_default_env("DIALOG_GCD_FOLD_FREED_TAIL", "1"); + set_default_env("DIALOG_GCD_FOLD_FREED_TAIL_ED", "1"); + set_default_env("DIALOG_GCD_FOLD_HOST_DERIVED_CONTROLS", "1"); + set_default_env("DIALOG_GCD_FOLD_HOST_E_TOP_CARRY", "1"); + set_default_env("DIALOG_GCD_FOLD_MAJ1", "1"); + set_default_env("DIALOG_GCD_FOLD_MAJ2", "1"); + set_default_env("DIALOG_GCD_FOLD_PARK_LOW_CARRIES", "15"); + set_default_env( + "DIALOG_GCD_FOLD_PARK_LOW_CARRIES_STEP_MAP", + "0:17,3:16,8:16,9:16,10:16,21:17,22:16,24:16,26:16,33:16,34:16,37:17,41:16,42:17,51:16,55:16,65:17,73:16,77:16,81:16,82:16,86:16,87:16,97:16,104:16,109:16,110:16,120:16,129:16,132:17,134:16,141:17,142:16,146:16,157:16,160:16,169:16,170:17,174:16,177:16,191:16,192:16,198:16,205:16,206:16,212:16,215:16,216:16,217:16,224:17,228:16", + ); + set_default_env("DIALOG_GCD_FOLD_STREAM_CONTROLS", "1"); + set_default_env("DIALOG_FUSE_C_FORM", "1"); + set_default_env("DIALOG_FUSE_X_RESTORE", "1"); + set_default_env("DIALOG_GCD_K2", "1"); + set_default_env("DIALOG_GCD_K5_CLEAN_BLOCK", "1"); + set_default_env("DIALOG_GCD_K5_FIXED_TAIL_APPLY", "0"); + set_default_env("DIALOG_GCD_K5_FREE_CLEAN_BLOCK_DURING_SHIFT", "1"); + set_default_env("DIALOG_GCD_K5_HEAD11_CODEC", "1"); + set_default_env("DIALOG_GCD_K5_HEAD11_STREAM_PAIR_APPLY", "1"); + set_default_env("DIALOG_GCD_K5_HEAD11_SPLIT_PAIR_SHIFT_APPLY", "1"); + set_default_env("DIALOG_GCD_K5_HEAD11_PAIR01_S2_PERMUTE_APPLY", "1"); + set_default_env( + "DIALOG_GCD_K5_HEAD11_PAIR23_S2_BORROW_PAIR01_APPLY", + "1", + ); + set_default_env("DIALOG_GCD_K5_PARTIAL_RAW_RELEASE", "8"); + set_default_env("DIALOG_GCD_K5_RELEASE_SCALE_BITS", "5"); + set_default_env("DIALOG_GCD_K5_STREAM_PAIR_APPLY", "1"); + set_default_env("DIALOG_GCD_K5_TAIL3_FIXED_LAST", "0"); + set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_CODEC", "1"); + set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_STREAM_APPLY", "1"); + set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_SPLIT_SLOT_APPLY", "1"); + set_default_env("DIALOG_GCD_K5_TAIL3_TOP32_FINAL_S2_CONST_APPLY", "1"); + set_default_env("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH", "1"); + set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE", "1"); + set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN", "0"); + set_default_env("DIALOG_GCD_PERPOS_MAJ2", "1"); + set_default_env("DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL", "1"); + set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB", "0"); + set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH", "1"); + set_default_env("DIALOG_GCD_RUNWAY_PARTIAL_BLOCK", "1"); + set_default_env("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT", "1"); + set_default_env("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES", "1"); + set_default_env( + "DIALOG_GCD_SPECIAL_FOLD_CARRY_TRUNC_STEP_WINDOWS", + "10:19,11:19,21:20,63:19,74:19,100:19,107:19,110:19,118:19,135:19,136:19,137:19,188:20,204:19,227:20,241:19", + ); + set_default_env("DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES", "16"); + set_default_env( + "DIALOG_GCD_SPECIAL_FOLD_PARK_LOW_CARRIES_STEP_MAP", + "", + ); + set_default_env("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH", "1"); + set_default_env( + "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", + "1:24,4:21,6:25,7:20,10:22,11:20,19:21,21:21,22:21,23:23,28:21,30:22,32:20,33:24,34:25,48:21,49:22,55:22,62:23,64:20,66:21,71:22,86:20,92:21,113:21,116:21,118:20,119:24,120:21,121:20,127:20,129:22,131:22,142:22,144:21,145:23,147:21,151:23,153:23,154:23,155:20,156:24,159:22,161:24,165:21,166:21,168:21,173:20,175:21,178:21,184:22,185:20,187:23,188:22,190:20,193:21,194:22,196:20,197:21,199:21,203:22,205:22,209:20,210:21,213:20,217:22,221:21,222:23,229:21,236:21,241:21", + ); + set_default_env( + "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", + "3:21,5:21,10:23,11:22,14:22,17:20,27:22,33:20,34:22,38:21,42:22,47:21,50:22,51:21,53:20,54:21,58:21,60:21,65:21,67:23,68:25,73:20,74:20,75:23,77:21,78:20,84:21,89:23,91:22,95:22,98:26,103:21,109:22,110:22,114:22,118:22,127:26,135:20,136:20,137:22,143:21,149:21,152:20,154:26,155:20,156:22,157:20,158:26,166:20,178:20,181:20,186:24,188:25,191:21,194:20,198:20,200:21,201:21,202:23,203:23,204:22,212:25,213:20,214:22,221:20,223:21,228:21,231:23,243:21,246:20", + ); + set_default_env("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM", "0"); + set_default_env("DIALOG_GCD_WIDTH_MARGIN", "10"); + set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1017"); + set_default_env("LUD_EXTRA_FOLD_VENTS", "1"); + set_default_env("LUD_EXTRA_FOLD_MIN_G", "24"); + set_default_env("KAL_DOUBLE_CARRY_TRUNC_W", "19"); + set_default_env("KAL_FOLD_CARRY_TRUNC_W", "18"); + set_default_env("SQUARE_ROW_MAX_SEG", "141"); + set_default_env("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS", "18"); + set_default_env( + "SQUARE_ROW_WINDOW_CLEAN_ROW_BITS", + "2:20,11:20,12:20,13:21,16:22,19:20,20:21,21:20,26:21,29:21,32:21,37:21,44:22,46:20,53:21,56:20,64:20,70:20,75:20,78:20,87:20", + ); + set_default_env( + "SQUARE_ROW_WINDOW_CLEAN_SITE_BITS", + "1:0:f:19,3:0:r:21,9:0:f:22,10:0:r:21,13:0:r:22,14:0:r:20,15:0:r:19,17:0:r:20,26:0:f:22,36:0:f:20,38:0:f:20,38:0:r:20,39:0:r:19,40:0:r:22,41:0:r:19,42:0:r:20,43:0:r:19,45:0:r:19,47:0:f:22,47:0:r:19,48:0:r:20,50:0:f:22,50:0:r:22,51:0:f:22,54:0:f:19,57:0:r:19,59:0:f:19,60:0:f:19,62:0:f:22,62:0:r:21,63:0:f:20,65:0:f:19,66:0:f:21,66:0:r:21,67:0:f:19,68:0:r:21,71:0:r:20,72:0:f:21,73:0:r:21,74:0:r:19,76:0:r:21,79:0:r:20,81:0:f:20,83:0:r:22,89:0:r:19,90:0:r:21,91:0:f:21,92:0:r:21,95:0:r:20,97:0:r:21,102:0:f:20,103:0:r:19,104:0:r:19,107:0:f:20,109:0:f:21,110:0:f:19,110:0:r:20", + ); + set_default_env("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR", "1"); + + set_default_env("SKIP_ALT_SEED_CHECKS", "1"); + set_default_env("DIALOG_GCD_COMPRESSED_SIDECAR_LOG", "1"); + + set_default_env("SQUARE_ROW_WINDOW_CLEAN_COMPARE_BITS", "21"); + set_default_env("SQUARE_ROW_WINDOW_MEASURED_CARRY_CLEAR", "1"); + set_default_env("ROUND84_KEEP_QUOTIENT_PRODUCT", "1"); + set_default_env("DIALOG_GCD_FOLD_CARRY_TRUNC_W", "17"); + set_default_env("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT", "1"); + set_default_env("DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE", "1"); + set_default_env("DIALOG_GCD_HOST_REVERSE_RAW_BLOCK", "1"); + set_default_env("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY", "1"); + set_default_env("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY_BLOCKS", "999"); + set_default_env("DIALOG_GCD_COMPOSITE_SCRATCH", "1"); + + set_default_env("DIALOG_GCD_BORROW_CURRENT_BLOCK", "1"); + + set_default_env("DIALOG_GCD_CTRL_BODY_VENTED", "1"); + set_default_env("DIALOG_GCD_APPLY_REPLAY_SWAP_HOST", "1"); + set_default_env("SQUARE_SELFHOST_SAFE_LANE_REUSE", "1"); + set_default_env("SQUARE_SELFHOST_GATE_SUFFIX_CARRIES", "0"); + + set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE", "1"); + + set_default_env("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN", "0"); + + set_default_env("KAL_DOUBLE_CARRY_TRUNC_W", "19"); + + set_default_env("KAL_FOLD_CARRY_TRUNC_W", "18"); + set_default_env("DIALOG_GCD_ROUND763_DEDUP", "1"); + set_default_env("DIALOG_GCD_ROUND763_COMPRESS_LEVER", "1"); + set_default_env("DIALOG_GCD_MEASURED_UNDERFLOW_GATE", "1"); + + set_default_env("DIALOG_GCD_COMPARE_BITS", "46"); + + set_default_env("DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS", "18"); + set_default_env("DIALOG_GCD_APPLY_BOUNDARY_CONDITIONAL_REPLAY", "1"); + set_default_env("DIALOG_GCD_SELECTED_BODY_STREAM_SUFFIX_MAP", "3:2,4:3,5:5,6:6,7:7,8:5,9:7,10:5,11:7,12:6,13:7,14:5,15:6,16:3,17:5,18:1,19:3,21:1"); + + set_default_env("DIALOG_GCD_REVERSE_BRANCH_CONDITIONAL_REPLAY", "1"); + set_default_env("DIALOG_GCD_SPECIAL_CLEAN_CONDITIONAL_REPLAY", "1"); + set_default_env("MOD_FAST_FLAG_CONDITIONAL_REPLAY", "1"); + set_default_env("DIALOG_GCD_RAW_PA", "1"); + set_default_env("DIALOG_GCD_K2", "1"); + + set_default_env("DIALOG_GCD_APPLY_FUSED_FOLD", "1"); + + set_default_env("DIALOG_GCD_K2_PAIR_COMPRESS", "1"); + + set_default_env("DIALOG_GCD_ACTIVE_ITERATIONS", "258"); + set_default_env("DIALOG_GCD_PERPOS_MAJ2", "1"); + set_default_env("DIALOG_GCD_FUSED_HCLEAR_MEASURED", "1"); + set_default_env("DIALOG_GCD_FUSED_DCLEAR_MEASURED", "1"); + set_default_env("DIALOG_GCD_FUSED_HALVE_EDCLEAR_MEASURED", "1"); + set_default_env("DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE", "1"); + set_default_env("DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL", "1"); + set_default_env("DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE", "1"); + set_default_env("DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB", "1"); + set_default_env("DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD", "1"); + set_default_env("DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN", "1"); + + set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB", "0"); + set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH", "1"); + set_default_env("DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES", "1"); + + set_default_env("ROUND84_XTAIL_KARATSUBA", "0"); + + set_default_env("KARA_SOL_DBL_FAST", "1"); + + set_default_env("KARA_FREE_Z1_TOPBIT", "1"); + + set_default_env("DIALOG_GCD_WIDTH_MARGIN", "10"); + + set_default_env("DIALOG_GCD_MEASURED_APPLY_SUB", "1"); + + set_default_env("DIALOG_GCD_HOST_GATED", "1"); + set_default_env("DIALOG_GCD_APPLY_WINDOW_BLOCKS", "2"); + + set_default_env("ROUND84_XTAIL_BORROW_CARRIES", "1"); + + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS", "16"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM4", "0"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM5", "0"); + + set_default_env("KARA_Z02_LOWQ", "1"); + set_default_env("KARA_Z2_SELFHOST", "1"); + set_default_env("KARA_SOL_MOD_VENT", "1"); + + set_default_env("DIALOG_GCD_BRANCH_BITS_HOST_COMPARATOR", "1"); + + set_default_env("DIALOG_GCD_BODY_HOST_CIN", "1"); + set_default_env("DIALOG_GCD_LATE_BORROW_UV_HIGH", "1"); + + set_default_env("DIALOG_GCD_BODY_CARRY_BAND_TRIMS", "0,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3"); + set_default_env("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM", "0"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_STEPS", "8,9,10"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_EXTRA", "3"); + set_default_env("DIALOG_GCD_BINDER_NOTCH_MAP", "11:1,12:1,13:1"); + set_default_env( + "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", + "113:21,131:21,142:22,187:23,205:22,210:21", + ); + set_default_env( + "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", + "42:22,91:22,118:22,149:21", + ); + set_default_env("DIALOG_GCD_FUSED_OVFCLEAR_MEASURED", "1"); + + set_default_env("DIALOG_GCD_APPLY_FINAL_LOWQ", "0"); + + set_default_env("R84_LOWQ", "1"); + set_default_env("R84_LOWQ_CIN_BORROW", "1"); + set_default_env("R84_QPROD_NAF", "1"); + + set_default_env("ROUND84_INPLACE_SOLINAS_FOLD", "1"); + set_default_env("ROUND84_INPLACE_QUOTIENT_CARRY_TRUNC_W", "21"); + + set_default_env("SQUARE_ROW_MAX_SEG", "176"); + set_default_env("DIALOG_GCD_K5_CLEAN_BLOCK", "1"); + set_default_env("DIALOG_GCD_FOLD_PARK_LOW_CARRIES", "1"); + set_default_env("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES", "1"); + set_default_env("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK", "1"); + set_default_env("DIALOG_GCD_FOLD_FREED_TAIL", "1"); + set_default_env("DIALOG_GCD_BORROW_CURRENT_S2", "1"); + set_default_env("DIALOG_GCD_BORROW_ZERO_RAW_FUTURE", "1"); + set_default_env("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT", "1"); + set_default_env("DIALOG_GCD_APPLY_BOUNDARY_SPLIT", "100"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT", "50"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT2", "100"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT3", "150"); + set_default_env("DIALOG_GCD_APPLY_CHUNKED_F_CUT4", "190"); + + set_default_env("DIALOG_GCD_WIDTH_SLOPE_X1000", "1017"); + + set_default_env("DIALOG_REROLL", "4269"); + set_default_env("DIALOG_POST_SUB_REROLL", "503292"); + + set_default_env("DIALOG_GCD_SELECTED_BODY_NOCIN", "1"); + + set_default_env("ROUND84_FOLD_FAST_ADD", "0"); + set_default_env("DIALOG_GCD_FOLD_MAJ2", "1"); + set_default_env("DIALOG_GCD_FOLD_MAJ1", "1"); + set_default_env("DIALOG_GCD_APPLY_FINAL_TOPCLEAN", "0"); + set_default_env("ROUND84_QPROD_VENT_PAD", "1"); + set_default_env("DIALOG_GCD_FOLD_FREED_TAIL_ED", "1"); + set_default_env("DIALOG_GCD_APPLY_FINAL_WINDOWED_FAST_BLOCKS", "0"); + + set_default_env("DIALOG_GCD_FUSED_BRANCH_BITS", "1"); + + set_default_env("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH", "1"); +} + +pub fn build_builder() -> B { + configure_ecdsafail_submission_route(); + + let mut builder = if std::env::var("POINT_ADD_COUNT_ONLY").ok().as_deref() == Some("1") { + B::new_count_only() + } else { + B::new() + }; + let b = &mut builder; + + let tx = b.alloc_qubits(N); + b.declare_qubit_register(&tx); + + let ty = b.alloc_qubits(N); + b.declare_qubit_register(&ty); + + let ox = b.alloc_bits(N); + b.declare_bit_register(&ox); + + let oy = b.alloc_bits(N); + b.declare_bit_register(&oy); + + if let Some(k) = std::env::var("DIALOG_REROLL") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&k| k > 0) + { + b.set_phase("dialog_reroll"); + for _ in 0..k { + b.x(tx[0]); + b.x(tx[0]); + } + } + + let p = SECP256K1_P; + + mod_sub_qb(b, &tx, &ox, p); + mod_sub_qb(b, &ty, &oy, p); + if let Some(k) = std::env::var("DIALOG_POST_SUB_REROLL") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&k| k > 0) + { + b.set_phase("dialog_post_sub_reroll"); + for _ in 0..k { + b.x(tx[1]); + b.x(tx[1]); + } + } + + emit_dialog_gcd_raw_pa(b, &tx, &ty, &ox, &oy, p); + + if !b.count_only && std::env::var("SKIP_ALT_SEED_CHECKS").ok().as_deref() != Some("1") { + run_alt_seed_checks(&b.ops); + } + + if !b.count_only && std::env::var("TRACE_PEAK").is_ok() { + eprintln!( + "DEBUG peak_qubits={} at phase='{}' ops_idx={} total_ops={}", + b.peak_qubits, + b.peak_phase, + b.peak_ops_idx, + b.ops.len() + ); + let pk = b.peak_qubits; + let mut uniq: std::collections::BTreeMap<&'static str, (u32, usize)> = + std::collections::BTreeMap::new(); + for (a, ph, op) in &b.peak_log { + if *a + 5 >= pk { + let entry = uniq.entry(ph).or_insert((*a, *op)); + if *a > entry.0 { + *entry = (*a, *op); + } + } + } + for (ph, (a, op)) in uniq.iter() { + eprintln!("DEBUG near_peak active={} phase='{}' ops_idx={}", a, ph, op); + } + } + + if !b.count_only && std::env::var("DUMP_PHASE_BOUNDS").is_ok() { + for (op_idx, phase) in &b.phase_transitions { + eprintln!("PHASE_BOUND op_idx={op_idx} phase={phase}"); + } + } + + if !b.count_only && std::env::var("TRACE_PHASES").is_ok() { + + let trans = &b.phase_transitions; + let n_ops = b.ops.len(); + + let mut agg: std::collections::BTreeMap<&'static str, (u64, u64, u64)> = + std::collections::BTreeMap::new(); + + let mut regions: Vec<(&'static str, usize, u64, u64, u64)> = Vec::new(); + for i in 0..trans.len() { + let start = trans[i].0; + let end = if i + 1 < trans.len() { + trans[i + 1].0 + } else { + n_ops + }; + let phase = trans[i].1; + let mut tof: u64 = 0; + let mut cli: u64 = 0; + let mut other: u64 = 0; + for op in &b.ops[start..end] { + match op.kind { + OperationType::CCX | OperationType::CCZ => tof += 1, + OperationType::CX + | OperationType::CZ + | OperationType::Swap + | OperationType::Hmr + | OperationType::R => cli += 1, + _ => other += 1, + } + } + regions.push((phase, start, tof, cli, other)); + let e = agg.entry(phase).or_insert((0, 0, 0)); + e.0 += tof; + e.1 += cli; + e.2 += other; + } + let total_tof: u64 = agg.values().map(|v| v.0).sum(); + eprintln!("=== per-phase emitted Toffoli (classical view; executed-shot stats are in harness) ==="); + eprintln!( + "{:<40} {:>12} {:>12} {:>6}", + "phase", "ccx", "cliff", "%tof" + ); + let mut v: Vec<_> = agg.iter().collect(); + v.sort_by(|a, b| b.1 .0.cmp(&a.1 .0)); + for (ph, (t, c, _o)) in v { + let pct = if total_tof > 0 { + (*t as f64) * 100.0 / (total_tof as f64) + } else { + 0.0 + }; + eprintln!("{:<40} {:>12} {:>12} {:>5.1}%", ph, t, c, pct); + } + eprintln!("total_ccx_emitted={} total_ops={}", total_tof, n_ops); + if std::env::var("TRACE_PHASES_VERBOSE").is_ok() { + eprintln!("--- per-region (ordered) ---"); + for (ph, start, tof, cli, _o) in ®ions { + if *tof == 0 && *cli == 0 { + continue; + } + eprintln!("@{:<10} {:<40} ccx={} cli={}", start, ph, tof, cli); + } + } + } + + if std::env::var("TRACE_PHASE_ACTIVE").is_ok() { + b.close_phase_active_region(); + eprintln!("=== per-phase active qubit maxima ==="); + eprintln!("{:<48} {:>12}", "phase", "active_q"); + let mut v: Vec<_> = b.phase_active_max.iter().collect(); + v.sort_by(|a, b| b.1.cmp(a.1).then_with(|| a.0.cmp(b.0))); + let top_n = std::env::var("TRACE_PHASE_ACTIVE_TOP") + .ok() + .and_then(|s| s.parse::().ok()); + let mut printed = 0usize; + for (phase, active) in v { + if top_n.is_some_and(|limit| printed >= limit) { + break; + } + eprintln!("{:<48} {:>12}", phase, active); + printed += 1; + } + if std::env::var("TRACE_PHASE_ACTIVE_REGIONS").is_ok() { + eprintln!("--- per-region active qubit maxima (ordered) ---"); + for (end, phase, active) in &b.phase_active_regions { + eprintln!("@{:<10} {:<48} active_q={}", end, phase, active); + } + } + } + + if let Some(nonce) = std::env::var("DIALOG_TAIL_NONCE") + .ok() + .and_then(|s| s.parse::().ok()) + { + const NONCE_BITS: u32 = 48; + b.set_phase("dialog_tail_nonce"); + for i in 0..NONCE_BITS { + let q = if (nonce >> i) & 1 == 1 { tx[1] } else { tx[0] }; + b.x(q); + b.x(q); + } + } + + builder +} + +pub fn build() -> Vec { + configure_q1153_second512_submission_defaults(); + + if std::env::var("TLM_SQ_SELFTEST").ok().as_deref() == Some("1") { + arith::square_addsub_selftest::run(); + if std::env::var("TLM_SQ_SELFTEST_ONLY").ok().as_deref() == Some("1") { + std::process::exit(0); + } + } + + if std::env::var("DIALOG_GCD_K5_HEAD11_SELFTEST").is_ok() { + match dialog_gcd_k5_head11_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_HEAD11_SELFTEST: PASS (2048-word head codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_HEAD11_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_HEAD11_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL3_SELFTEST").is_ok() { + match dialog_gcd_k5_tail3_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL3_SELFTEST: PASS (two-step pair codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL3_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL3_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST").is_ok() { + match dialog_gcd_k5_tail3_top32_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST: PASS (32-word weighted codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST").is_ok() { + match dialog_gcd_k5_tail6_graph9_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST: PASS (75-word graph codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST").is_ok() { + match dialog_gcd_k5_tail6_graph_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST: PASS (32-word graph codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL7_SELFTEST").is_ok() { + match dialog_gcd_k5_tail7_codec_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL7_SELFTEST: PASS (20-word codec reversible and phase clean)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL7_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL7_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST").is_ok() { + match dialog_gcd_k5_tail7_fixed_apply_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST: PASS (fixed digit-4 apply matches fused apply)" + ), + Err(e) => panic!("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_K5_TAIL7_FIXED_APPLY_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("SQUARE_WINDOW_SELFTEST").is_ok() { + match square_window_selftest() { + Ok(()) => eprintln!("SQUARE_WINDOW_SELFTEST: PASS"), + Err(e) => panic!("SQUARE_WINDOW_SELFTEST: FAIL: {e}"), + } + if std::env::var("SQUARE_WINDOW_SELFTEST_ONLY").ok().as_deref() == Some("1") { + return Vec::new(); + } + } + if std::env::var("FOLD_FREED_TAIL_SELFTEST").is_ok() { + match fold_freed_tail_selftest() { + Ok(()) => eprintln!("FOLD_FREED_TAIL_SELFTEST: PASS (freed-tail ≡ baseline, ancilla & phase clean)"), + Err(e) => panic!("FOLD_FREED_TAIL_SELFTEST: FAIL: {e}"), + } + if std::env::var("FOLD_FREED_TAIL_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("SPECIAL_FOLD_PARK_SELFTEST").is_ok() { + match special_fold_park_selftest() { + Ok(()) => eprintln!( + "SPECIAL_FOLD_PARK_SELFTEST: PASS (parked fold ≡ baseline, ancilla & phase clean)" + ), + Err(e) => panic!("SPECIAL_FOLD_PARK_SELFTEST: FAIL: {e}"), + } + if std::env::var("SPECIAL_FOLD_PARK_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + if std::env::var("DIALOG_GCD_FUSED_APPLY_SELFTEST").is_ok() { + match dialog_gcd_k5_tail7_fixed_apply_selftest() { + Ok(()) => eprintln!( + "DIALOG_GCD_FUSED_APPLY_SELFTEST: PASS (fused double/halve value, ancilla, phase)" + ), + Err(e) => panic!("DIALOG_GCD_FUSED_APPLY_SELFTEST: FAIL: {e}"), + } + if std::env::var("DIALOG_GCD_FUSED_APPLY_SELFTEST_ONLY") + .ok() + .as_deref() + == Some("1") + { + return Vec::new(); + } + } + + set_default_env("LUD_EXTRA_FOLD_VENTS", "0"); + set_default_env("LUD_EXTRA_FOLD_MIN_G", "0"); + set_default_env("LUD_EXTRA_FOLD_MAX_G", "999"); + set_default_env("DIALOG_TAIL_NONCE", "2430844"); + set_default_env("TLM_FOLD_TAIL_CINC", "1"); + set_default_env("TLM_CODEC_DIAMOND_MCX", "1"); + set_default_env("SINGLE_CCX_FANOUT_DISABLE", "0"); + + set_default_env("TLM_SQUARE_F_RAMP10_DIRECT32_TAGS", ""); + set_default_env("TLM_SQUARE_F_SHIFTED_LOW", "1"); + + set_default_env("TLM_GRAD_FINAL_NO_COUT", "1"); + set_default_env("TLM_APPLY_FWD_FIRST_CSWAP_SKIP", "1"); + set_default_env("CONSTPROP_MAX_ITERS", "16"); + + set_default_env("TLM_TARGET_Q", "1155"); + set_default_env("TLM_FOLD_BOUNDARY_ZERO_DIRECT", "1"); + set_default_env("TLM_FOLD_CHUNK_FORCE", "4"); + set_default_env("TLM_TARGET_FOLD_CALL_RESERVE_OVERRIDES", "173:3,175:3,177:3,256:11,257:11,336:3,338:3,340:3,176:3,178:3,180:3,254:5,259:20,333:3,335:3,337:3,179:3,181:3,183:3,182:3,184:3,186:3,327:3,329:3,330:3,331:3,332:3,334:3"); + set_default_env("TLM_TARGET_FFG_CALL_RESERVE_OVERRIDES", "184:4,186:4,188:4,205:6,207:6,209:6,220:7,222:7,224:7,238:8,240:8,242:8,251:9,257:10,262:10,355:10,362:10,359:10,181:3,183:3,185:3,187:4,189:4,191:4,196:5,198:5,200:5,208:6,210:6,212:6,223:7,225:7,227:7,241:8,243:8,245:8,250:9,252:9,190:4,192:4,193:5,194:4,195:5,197:5,199:5,201:5,202:6,203:5,204:6,206:6,211:6,213:6,214:7,215:6,216:7,218:7,226:7,228:8,229:8,230:8,231:8,233:8,244:8,246:8,247:9,253:9,254:10,259:11,358:10,340:11,341:11,342:11,343:11,344:11,345:11,346:11,347:11,348:11,349:11,350:11"); + set_default_env("TLM_APPLY_FWD_S2_ZERO_LAST", "1"); + set_default_env("TLM_APPLY_INV_S2_ZERO_LAST", "1"); + set_default_env("TLM_APPLY_FWD_CSWAP_SKIP_LAST", "2"); + set_default_env("TLM_APPLY_INV_CSWAP_SKIP_LAST", "1"); + set_default_env("TLM_FOLD_RELEASE_CONTROLS", "1"); + set_default_env("TLM_TARGET_FFG_RESERVE", "9"); + set_default_env( + "TLM_TARGET_FFG_CALL_RESERVES", + concat!( + "163:8,165:8,166:7,167:8,168:7,169:6,170:7,171:6,172:5,173:6,174:5,175:4,176:5,177:4,178:3,179:4,180:3,181:2,182:3,183:2,184:1,185:2,186:1,187:0,188:1,189:0,190:3,191:0,192:3,193:3,194:3,195:3,196:4,197:3,198:4,199:4,200:4,201:4,202:4,203:4,204:4,205:5,206:4,207:5,208:5,209:5,210:5,211:5,212:5,213:5,214:5,215:5,216:5,217:6,218:5,219:6,220:6,221:6,222:6,223:6,224:6,225:6,226:6,227:6,228:6,229:6,230:6,231:6,232:7,233:6,234:7,235:7,236:7,237:7,238:7,239:7,240:7,241:7,242:7,243:7,244:7,245:7,246:7,247:7,248:8,249:8,250:8,251:8,252:8,253:8,254:8,", + "509:8,510:8,511:8,512:8,513:8,514:8,515:8,516:7,517:7,518:7,519:7,520:7,521:7,522:7,523:7,524:7,525:7,526:7,527:7,528:7,529:7,530:6,531:7,532:6,533:6,534:6,535:6,536:6,537:6,538:6,539:6,540:6,541:6,542:6,543:6,544:6,545:5,546:6,547:5,548:5,549:5,550:5,551:5,552:5,553:5,554:5,555:5,556:5,557:4,558:5,559:4,560:4,561:4,562:4,563:4,564:4,565:4,566:3,567:4,568:3,569:3,570:3,571:3,572:0,573:3,574:0,575:1,576:0,577:1,578:2,579:1,580:2,581:3,582:2,583:3,584:4,585:3,586:4,587:5,588:4,589:5,590:6,591:5,592:6,593:7,594:6,595:7,596:8,597:7,598:8,600:8", + ), + ); + set_default_env("TLM_TARGET_FOLD_RESERVE", "4"); + set_default_env( + "TLM_TARGET_FOLD_CALL_RESERVES", + concat!( + "170:3,172:3,173:2,174:3,175:2,176:1,177:2,178:1,179:0,180:1,181:0,182:0,183:0,184:0,185:3,186:0,187:3,188:3,189:3,190:3,191:3,192:3,193:3,195:3,", + "251:3,252:3,253:3,254:3,255:3,256:3,257:3,258:3,259:3,260:3,261:3,262:3,318:3,320:3,321:3,322:3,323:3,324:3,325:3,326:3,327:0,328:3,329:0,330:0,331:0,332:0,333:1,334:0,335:1,336:2,337:1,338:2,339:3,340:2,341:3,343:3", + ), + ); + set_default_env("TLM_GCD_RESELECT_LAYOUT", "1"); + set_default_env("TLM_DIRECT_VARCHUNK", "1"); + set_default_env("TLM_COUT_LAYOUT_SEARCH", "1"); + set_default_env("TLM_COUT_LAYOUT_MARGIN", "0"); + set_default_env("TLM_COUT_LAYOUT_FORCE_M1_KS", "129"); + set_default_env("TLM_GCD_ADAPTIVE_LAYOUT_SEARCH", "1"); + set_default_env("TLM_GCD_ADAPTIVE_LAYOUT_MARGIN", "0"); + + set_default_env("TLM_PARK_ODD_U0", "1"); + set_default_env("TLM_LOAN_ODD_U0", "1"); + set_default_env("TLM_PARK_EVEN_V0", "1"); + set_default_env("TLM_LOAN_EVEN_V0", "1"); + set_default_env("TLM_LOAN_GCD_Y0", "1"); + set_default_env("TLM_HYB_V_DELTA", "2"); + set_default_env("TLM_COUT_K_DELTA", "2"); + set_default_env("TLM_FOLD_DELTA", "2"); + set_default_env("TLM_FFG_DELTA", "0"); + set_default_env("TLM_GCD_K_ADJUST_AFTER", "169"); + set_default_env("TLM_GCD_K_ADJUST_BEFORE", "196"); + set_default_env("TLM_GCD_K_ADJUST", "-2"); + + set_default_env("TLM_FFG_SKIP_STRUCTURAL_DEAD_CALLS", "1"); + set_default_env("TLM_FFG_SKIP_TOP_CARRY31", "1"); + set_default_env("TLM_FFG_SKIP_TOP_CARRY30", "1"); + set_default_env("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS", "1"); + set_default_env("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS", "1"); + set_default_env("TLM_COMPARE_SKIP_EXACT_REMAINDER", "1"); + set_default_env("TLM_GIDNEY_SKIP_STRUCTURAL_DEAD_CALLS", "1"); + set_default_env("TLM_GIDNEY_SKIP_EXACT_REMAINDER", "1"); + set_default_env("TLM_CONST_CHUNK_SKIP_STRUCTURAL_DEAD_CALLS", "1"); + set_default_env("TLM_CONST_CHUNK_SKIP_EXACT_REMAINDER", "1"); + set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CARRIES", "1"); + set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_SHIFT0", "1"); + set_default_env("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER", "1"); + set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_DIRTY_FOLD", "1"); + set_default_env("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CLEAN_WINDOW", "1"); + set_default_env("TLM_ADD_CONST_SKIP_STRUCTURAL_DEAD_CARRIES", "1"); + set_default_env("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS", "1"); + set_default_env("TLM_GCD_SKIP_EXACT_FORWARD_CSWAPS", "1"); + set_default_env("TLM_GCD_SKIP_STRUCTURAL_DEAD_SHIFTS", "1"); + set_default_env("TLM_GCD_SKIP_EXACT_SHIFT_REMAINDER", "1"); + set_default_env("TLM_COMPARE_SKIP_EXACT_CIN_REMAINDER", "1"); + set_default_env("TLM_FUSED_SKIP_EXACT_BOUNDARY_ZERO", "1"); + set_default_env("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ", "1"); + set_default_env("TLM_FFG_SKIP_EXACT_TOP29_REMAINDER", "1"); + set_default_env("TLM_GCD_SKIP_REVERSE_DIAGONAL_EDGE", "1"); + set_default_env("TLM_FFG_SKIP_INVERSE_MOD_SUB_TOP29", "1"); + set_default_env("TLM_FFG_INVERSE_TOP29_MAX_CALL", "180"); + set_default_env("TLM_FUSED_CLEAN_FOLD_SKIP_TOP31", "1"); + set_default_env("TLM_GIDNEY_SKIP_SMALL_RESIDUAL_DEAD", "1"); + let mut ops = trailmix_ludicrous::build_trailmix_ludicrous_ops(); + + if let Ok(k) = std::env::var("TLM_SEED_PERTURB").unwrap_or_default().parse::() { + for _ in 0..k { + ops.push(crate::circuit::Op { + kind: crate::circuit::OperationType::DebugPrint, + q_control2: crate::circuit::NO_QUBIT, + q_control1: crate::circuit::NO_QUBIT, + q_target: crate::circuit::NO_QUBIT, + c_target: crate::circuit::NO_BIT, + c_condition: crate::circuit::NO_BIT, + r_target: crate::circuit::NO_REG, + }); + } + } + if std::env::var("SINGLE_CCX_FANOUT_DISABLE") + .ok() + .as_deref() + == Some("1") + { + return ops; + } + let input_ops = ops.len(); + let mut fanout_passes = 0usize; + loop { + match single_ccx_fanout::rewrite_first_target_fanout(ops.clone(), 96) { + Ok((rewritten, _witness)) => { + fanout_passes += 1; + ops = rewritten; + } + Err(error) => { + eprintln!( + "SINGLE_CCX_FANOUT: STOP passes={} input_ops={} output_ops={} reason={}", + fanout_passes, + input_ops, + ops.len(), + error, + ); + break; + } + } + } + assert!(fanout_passes >= 1, "single-fanout rewrite failed to find first pass"); + eprintln!( + "SINGLE_CCX_FANOUT: SUMMARY input_ops={} output_ops={} passes={}", + input_ops, + ops.len(), + fanout_passes, + ); + ops +} + +pub fn square_window_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + const SHOTS: usize = 64; + let nbits = std::env::var("SQUARE_WINDOW_SELFTEST_NBITS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(24); + assert!(nbits > 0); + let packed_value_check = 2 * nbits < 64; + let wide_value_check = nbits <= 256; + let mask = if packed_value_check { (1u64 << nbits) - 1 } else { u64::MAX }; + let out_mask = if packed_value_check { (1u64 << (2 * nbits)) - 1 } else { u64::MAX }; + let xs: Vec = (0..SHOTS as u64) + .map(|s| { + let r = s + .wrapping_mul(0x9E37_79B9_7F4A_7C15) + .wrapping_add(0xA076_1D64_78BD_642F); + let r = (r ^ (r >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); + r & mask + }) + .collect(); + let x_masks: Vec = (0..nbits) + .map(|k| { + if packed_value_check { + xs.iter() + .enumerate() + .fold(0u64, |acc, (shot, &xv)| acc | (((xv >> k) & 1) << shot)) + } else { + let z = (k as u64) + .wrapping_mul(0xD6E8_FD9D_50B5_8A51) + .wrapping_add(0x9E37_79B9_7F4A_7C15); + let z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB); + z ^ (z >> 31) + } + }) + .collect(); + + let build_one = |roundtrip: bool| -> (Vec, Vec, Vec, usize, usize) { + let mut b = B::new(); + let x = b.alloc_qubits(nbits); + let tmp = b.alloc_qubits(2 * nbits); + schoolbook_square_symmetric_lowq_selfhosted(&mut b, &x, &tmp); + if roundtrip { + schoolbook_square_symmetric_lowq_selfhosted_inverse(&mut b, &x, &tmp); + } + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + (b.ops, x, tmp, nq, nb) + }; + + let run = |ops: &[Op], + x: &[QubitId], + tmp: &[QubitId], + nq: usize, + nb: usize| + -> (Vec, Vec, u64) { + let mut seed = sha3::Shake128::default(); + seed.update(b"square-window-selftest"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + sim.clear_for_shot(); + for k in 0..nbits { + *sim.qubit_mut(x[k]) = x_masks[k]; + } + sim.apply_iter(ops.iter()); + let out_x_masks: Vec = x.iter().map(|&q| sim.qubit(q)).collect(); + let out_tmp_masks: Vec = tmp.iter().map(|&q| sim.qubit(q)).collect(); + (out_x_masks, out_tmp_masks, sim.phase) + }; + + let (ops_fwd, x_fwd, tmp_fwd, nq_fwd, nb_fwd) = build_one(false); + let (out_x_masks, out_tmp_masks, phase) = run(&ops_fwd, &x_fwd, &tmp_fwd, nq_fwd, nb_fwd); + if phase != 0 { + return Err(format!("forward phase garbage 0x{phase:x}")); + } + for (k, (&got, &want)) in out_x_masks.iter().zip(x_masks.iter()).enumerate() { + if got != want { + return Err(format!("forward x bit {k} changed")); + } + } + if packed_value_check { + for shot in 0..SHOTS { + let got = out_tmp_masks + .iter() + .take(2 * nbits) + .enumerate() + .fold(0u64, |acc, (k, &bits)| acc | (((bits >> shot) & 1) << k)); + let want = xs[shot].wrapping_mul(xs[shot]) & out_mask; + if got != want { + return Err(format!( + "forward value mismatch shot {shot}: tmp got 0x{got:x} want 0x{want:x}" + )); + } + } + } else if wide_value_check { + let in_limbs = (nbits + 63) / 64; + let out_limbs = (2 * nbits + 63) / 64; + for shot in 0..SHOTS { + let mut x_limbs = vec![0u64; in_limbs]; + for k in 0..nbits { + if (x_masks[k] >> shot) & 1 != 0 { + x_limbs[k / 64] |= 1u64 << (k % 64); + } + } + let mut product = vec![0u64; out_limbs]; + for i in 0..in_limbs { + let mut carry = 0u128; + for j in 0..in_limbs { + let idx = i + j; + if idx >= out_limbs { + break; + } + let cur = product[idx] as u128 + + (x_limbs[i] as u128) * (x_limbs[j] as u128) + + carry; + product[idx] = cur as u64; + carry = cur >> 64; + } + let mut idx = i + in_limbs; + while carry != 0 && idx < out_limbs { + let cur = product[idx] as u128 + carry; + product[idx] = cur as u64; + carry = cur >> 64; + idx += 1; + } + } + for k in 0..(2 * nbits) { + let got = (out_tmp_masks[k] >> shot) & 1; + let want = (product[k / 64] >> (k % 64)) & 1; + if got != want { + return Err(format!("forward value mismatch shot {shot} bit {k}")); + } + } + } + } + + let (ops_rt, x_rt, tmp_rt, nq_rt, nb_rt) = build_one(true); + let (out_x_masks, out_tmp_masks, phase) = run(&ops_rt, &x_rt, &tmp_rt, nq_rt, nb_rt); + if phase != 0 { + return Err(format!("roundtrip phase garbage 0x{phase:x}")); + } + for (k, (&got, &want)) in out_x_masks.iter().zip(x_masks.iter()).enumerate() { + if got != want { + return Err(format!("roundtrip x bit {k} changed")); + } + } + for (k, &got) in out_tmp_masks.iter().enumerate() { + if got != 0 { + return Err(format!("roundtrip tmp bit {k} dirty mask 0x{got:x}")); + } + } + Ok(()) +} + +pub fn fold_freed_tail_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + let hi_delta = 33usize; + let hi_c = 32usize; + let nbits = 64usize; + for &windowed in &[true, false] { + let last = if windowed { + hi_delta + 19 + } else { + nbits - 2 + }; + for ed in 0u64..4 { + let e_val = ed & 1; + let d_val = (ed >> 1) & 1; + for &is_add in &[true, false] { + + let build_one = |freed: bool| -> (Vec, Vec, usize, usize) { + let mut b = B::new(); + let y = b.alloc_qubits(nbits); + let ovf1 = b.alloc_qubit(); + let ovf2 = b.alloc_qubit(); + let s2 = b.alloc_qubit(); + let e = b.alloc_qubit(); + let d = b.alloc_qubit(); + let h = b.alloc_qubit(); + let xed = b.alloc_qubit(); + let eord = b.alloc_qubit(); + let n10 = b.alloc_qubit(); + + b.x(s2); + if d_val == 1 { + b.x(ovf1); + } + if e_val == 1 { + b.x(ovf2); + } + b.ccx(ovf1, s2, d); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.ccx(e, d, h); + b.cx(e, xed); + b.cx(d, xed); + b.cx(xed, eord); + b.cx(h, eord); + b.cx(d, n10); + b.cx(h, n10); + if freed { + fold_ripple_freed_tail_ed( + &mut b, + &y, + e, + d, + h, + xed, + eord, + n10, + Some((ovf1, ovf2, s2)), + None, + last, + is_add, + ); + } else { + let controls = + secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); + if is_add { + cadd_per_position_controls_trunc(&mut b, &y, &controls, last); + } else { + csub_per_position_controls_trunc(&mut b, &y, &controls, last); + } + } + + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.ccx(e, d, h); + b.cx(ovf2, e); + b.cx(d, e); + b.cx(ovf1, e); + b.ccx(ovf1, s2, d); + if e_val == 1 { + b.x(ovf2); + } + if d_val == 1 { + b.x(ovf1); + } + b.x(s2); + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + (b.ops, y, nq, nb) + }; + let (ops_base, y_b, nq_b, nb_b) = build_one(false); + let (ops_freed, y_f, nq_f, nb_f) = build_one(true); + + let mask: u64 = if nbits >= 64 { u64::MAX } else { (1u64 << nbits) - 1 }; + let ys: Vec = (0..64u64) + .map(|s| { + let r = s + .wrapping_mul(0x9E37_79B9_7F4A_7C15) + .wrapping_add(0xD1B5_4A32_D192_ED03); + let r = (r ^ (r >> 31)).wrapping_mul(0xBF58_476D_1CE4_E5B9); + let r = r ^ (r >> 27); + let base = r & mask; + + if s % 4 == 0 { + base | (mask & !((1u64 << (hi_delta + 1)) - 1)) + } else if s % 4 == 1 { + base & ((1u64 << (hi_delta + 1)) - 1) + } else { + base + } + }) + .collect(); + + let run = |ops: &[Op], y: &[QubitId], nq: usize, nb: usize| -> (Vec, bool, u64) { + let mut s2 = sha3::Shake128::default(); + s2.update(b"fold-sim"); + let mut xof2 = s2.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof2); + sim.clear_for_shot(); + for (shot, &yv) in ys.iter().enumerate() { + for k in 0..nbits { + if (yv >> k) & 1 != 0 { + *sim.qubit_mut(y[k]) |= 1u64 << shot; + } + } + } + sim.apply_iter(ops.iter()); + let outs: Vec = (0..64) + .map(|shot| { + let mut v = 0u64; + for k in 0..nbits { + v |= ((sim.qubit(y[k]) >> shot) & 1) << k; + } + v + }) + .collect(); + let anc_clean = + (nbits..nq).all(|q| sim.qubit(QubitId(q as u64)) == 0); + (outs, anc_clean, sim.phase) + }; + let (out_b, clean_b, phase_b) = run(&ops_base, &y_b, nq_b, nb_b); + let (out_f, clean_f, phase_f) = run(&ops_freed, &y_f, nq_f, nb_f); + + if !clean_b { + return Err(format!("baseline left ancilla dirty (ed={ed} add={is_add} win={windowed})")); + } + if !clean_f { + return Err(format!("freed-tail left ancilla dirty (ed={ed} add={is_add} win={windowed})")); + } + if phase_f != 0 { + return Err(format!("freed-tail left phase garbage 0x{phase_f:x} (ed={ed} add={is_add} win={windowed})")); + } + let _ = phase_b; + for shot in 0..64 { + if out_b[shot] != out_f[shot] { + return Err(format!( + "value mismatch shot {shot}: base 0x{:x} freed 0x{:x} (ed={ed} add={is_add} win={windowed}, y_in=0x{:x})", + out_b[shot], out_f[shot], ys[shot] + )); + } + } + } + } + } + Ok(()) +} + +pub fn special_fold_park_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let c = U256::MAX + .wrapping_sub(SECP256K1_P) + .wrapping_add(U256::from(1u64)); + let nbits = 64usize; + let window = 20usize; + + for ctrl_value in 0u64..=1 { + for &is_add in &[true, false] { + let build_one = |parked: bool| { + let mut b = B::new(); + let acc = b.alloc_qubits(nbits); + let ctrl = b.alloc_qubit(); + let scratch = b.alloc_qubits(5); + if ctrl_value != 0 { + b.x(ctrl); + } + if parked { + if is_add { + cadd_nbit_const_direct_trunc_fast_releasing_scratch( + &mut b, &acc, c, ctrl, window, &scratch, + ); + } else { + csub_nbit_const_direct_trunc_fast_releasing_scratch( + &mut b, &acc, c, ctrl, window, &scratch, + ); + } + } else if is_add { + cadd_nbit_const_direct_trunc_fast_borrowed_carries( + &mut b, &acc, c, ctrl, window, &scratch, + ); + } else { + csub_nbit_const_direct_trunc_fast_borrowed_carries( + &mut b, &acc, c, ctrl, window, &scratch, + ); + } + if ctrl_value != 0 { + b.x(ctrl); + } + (b.ops, acc, b.next_qubit as usize, b.next_bit as usize) + }; + + let (base_ops, base_acc, base_nq, base_nb) = build_one(false); + let (parked_ops, parked_acc, parked_nq, parked_nb) = build_one(true); + let inputs: Vec = (0..64u64) + .map(|shot| { + let mixed = shot + .wrapping_mul(0x9E37_79B9_7F4A_7C15) + .wrapping_add(0xD1B5_4A32_D192_ED03); + match shot % 4 { + 0 => mixed | (!0u64 << 33), + 1 => mixed & ((1u64 << 34) - 1), + _ => mixed ^ (mixed >> 29), + } + }) + .collect(); + + let run = |ops: &[Op], acc: &[QubitId], nq: usize, nb: usize| { + let mut seed = Shake256::default(); + seed.update(b"special-fold-park-selftest"); + seed.update(&[ctrl_value as u8, is_add as u8]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + sim.clear_for_shot(); + for (shot, &input) in inputs.iter().enumerate() { + for bit_index in 0..nbits { + if (input >> bit_index) & 1 != 0 { + *sim.qubit_mut(acc[bit_index]) |= 1u64 << shot; + } + } + } + sim.apply_iter(ops.iter()); + let outputs: Vec = (0..64) + .map(|shot| { + let mut value = 0u64; + for bit_index in 0..nbits { + value |= ((sim.qubit(acc[bit_index]) >> shot) & 1) << bit_index; + } + value + }) + .collect(); + let clean = (nbits..nq).all(|q| sim.qubit(QubitId(q as u64)) == 0); + (outputs, clean, sim.phase) + }; + + let (base_out, base_clean, base_phase) = + run(&base_ops, &base_acc, base_nq, base_nb); + let (parked_out, parked_clean, parked_phase) = + run(&parked_ops, &parked_acc, parked_nq, parked_nb); + if !base_clean || base_phase != 0 { + return Err(format!( + "baseline dirty: ctrl={ctrl_value} add={is_add} clean={base_clean} phase=0x{base_phase:x}" + )); + } + if !parked_clean || parked_phase != 0 { + return Err(format!( + "parked dirty: ctrl={ctrl_value} add={is_add} clean={parked_clean} phase=0x{parked_phase:x}" + )); + } + if base_out != parked_out { + let shot = base_out + .iter() + .zip(&parked_out) + .position(|(base, parked)| base != parked) + .unwrap_or(0); + return Err(format!( + "value mismatch shot {shot}: base=0x{:x} parked=0x{:x} input=0x{:x} ctrl={ctrl_value} add={is_add}", + base_out[shot], parked_out[shot], inputs[shot] + )); + } + } + } + Ok(()) +} + +#[cfg(test)] +mod direct_const_tests { + use super::*; + use sha3::{ + digest::{ExtendableOutput, Update, XofReader}, + Shake128, + }; + + fn set_reg(sim: &mut Simulator<'_, R>, qs: &[QubitId], val: u64, shot: usize) { + for (i, &q) in qs.iter().enumerate() { + if ((val >> i) & 1) != 0 { + *sim.qubit_mut(q) |= 1u64 << shot; + } else { + *sim.qubit_mut(q) &= !(1u64 << shot); + } + } + } + + fn get_reg(sim: &Simulator<'_, R>, qs: &[QubitId], shot: usize) -> u64 { + let mut out = 0u64; + for (i, &q) in qs.iter().enumerate() { + out |= ((sim.qubit(q) >> shot) & 1) << i; + } + out + } + + #[test] + fn one_inv_dx3_blocker_is_fail_closed_on_cleanup_invariant() { + assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("Rx-Qx")); + assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("second inversion")); + assert!(ONE_INV_DX3_AFFINE_PA_BLOCKER.contains("dirty reset")); + } + + #[test] + fn dialog_gcd_selected_body_nocin_matches_cin_reference() { + if let Err(e) = dialog_gcd_selected_body_nocin_selftest() { + panic!("no-c_in selected body selftest failed: {e}"); + } + } + + #[test] + fn aliased_gate_wrappers_are_not_silent_noops() { + let mut b = B::new(); + let q0 = b.alloc_qubit(); + let q1 = b.alloc_qubit(); + b.cz(q0, q0); + b.ccz(q0, q0, q1); + b.ccz(q0, q1, q0); + b.ccz(q0, q0, q0); + b.ccx(q0, q0, q1); + let kinds = b.ops.iter().map(|op| op.kind).collect::>(); + assert_eq!( + kinds, + vec![ + OperationType::Z, + OperationType::CZ, + OperationType::CZ, + OperationType::Z, + OperationType::CX, + ] + ); + assert!(std::panic::catch_unwind(|| { + let mut b = B::new(); + let q = b.alloc_qubit(); + b.cx(q, q); + }) + .is_err()); + assert!(std::panic::catch_unwind(|| { + let mut b = B::new(); + let q0 = b.alloc_qubit(); + let q1 = b.alloc_qubit(); + b.ccx(q0, q1, q0); + }) + .is_err()); + } + + #[test] + fn dx3_witness_is_not_an_output_cleanup_coordinate() { + let p = SECP256K1_P; + let beta = U256::from_str_radix( + "7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE", + 16, + ) + .unwrap(); + let dx = U256::from(0x1234_5678_9abc_def0u64); + let beta_dx = beta.mul_mod(dx, p); + assert_ne!(dx, beta_dx); + assert_eq!(beta.mul_mod(beta, p).mul_mod(beta, p), U256::from(1u64)); + assert_eq!( + dx.mul_mod(dx, p).mul_mod(dx, p), + beta_dx.mul_mod(beta_dx, p).mul_mod(beta_dx, p) + ); + } + + fn assert_borrowed_carry_adder_basis(is_sub: bool) { + const N: usize = 5; + const MOD: u64 = 1 << N; + let mut b = B::new(); + let a = b.alloc_qubits(N); + let acc = b.alloc_qubits(N); + let carries = b.alloc_qubits(N - 1); + if is_sub { + sub_nbit_qq_fast_borrowed_carries(&mut b, &a, &acc, &carries); + } else { + add_nbit_qq_fast_borrowed_carries(&mut b, &a, &acc, &carries); + } + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + + for batch in 0..16usize { + let mut seed = Shake128::default(); + seed.update(if is_sub { + b"borrowed-sub-small" + } else { + b"borrowed-add-small" + }); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for shot in 0..64usize { + let case = batch * 64 + shot; + let x = (case as u64) & (MOD - 1); + let y = ((case as u64) >> N) & (MOD - 1); + set_reg(&mut sim, &acc, x, shot); + set_reg(&mut sim, &a, y, shot); + } + sim.apply(&b.ops); + assert_eq!( + sim.global_phase(), + 0, + "borrowed carry adder left phase garbage" + ); + for shot in 0..64usize { + let case = batch * 64 + shot; + let x = (case as u64) & (MOD - 1); + let y = ((case as u64) >> N) & (MOD - 1); + let expect = if is_sub { + x.wrapping_sub(y) & (MOD - 1) + } else { + x.wrapping_add(y) & (MOD - 1) + }; + assert_eq!(get_reg(&sim, &acc, shot), expect, "case {case}"); + assert_eq!(get_reg(&sim, &a, shot), y, "a changed in case {case}"); + assert_eq!( + get_reg(&sim, &carries, shot), + 0, + "borrowed carries not clean in case {case}" + ); + } + } + } + + #[test] + fn borrowed_carry_add_small_basis_is_clean() { + assert_borrowed_carry_adder_basis(false); + } + + #[test] + fn borrowed_carry_sub_small_basis_is_clean() { + assert_borrowed_carry_adder_basis(true); + } + + fn sub_mod_p(a: U256, b: U256, p: U256) -> U256 { + if a >= b { + a - b + } else { + p - (b - a) + } + } + + #[test] + fn direct_controlled_const_sub_small_basis_is_phase_clean() { + const N: usize = 8; + let c = U256::from(0b1011_0111u64); + let mut b = B::new(); + let acc = b.alloc_qubits(N); + let ctrl = b.alloc_qubit(); + csub_nbit_const_direct_fast(&mut b, &acc, c, ctrl); + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + + let mut seed = Shake128::default(); + seed.update(b"direct-csub-small"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for shot in 0..64usize { + let x = ((shot * 37 + 11) & 0xff) as u64; + let ctrl_v = (shot & 1) as u64; + set_reg(&mut sim, &acc, x, shot); + if ctrl_v != 0 { + *sim.qubit_mut(ctrl) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + assert_eq!(sim.global_phase(), 0, "direct csub left phase garbage"); + for shot in 0..64usize { + let x = ((shot * 37 + 11) & 0xff) as u64; + let ctrl_v = (shot & 1) as u64; + let expect = x.wrapping_sub(ctrl_v * 0b1011_0111) & 0xff; + assert_eq!(get_reg(&sim, &acc, shot), expect, "shot {shot}"); + assert_eq!((sim.qubit(ctrl) >> shot) & 1, ctrl_v, "ctrl shot {shot}"); + } + } + + #[test] + fn direct_controlled_const_add_small_basis_is_phase_clean() { + const N: usize = 8; + let c = U256::from(0b1011_0111u64); + let mut b = B::new(); + let acc = b.alloc_qubits(N); + let ctrl = b.alloc_qubit(); + cadd_nbit_const_direct_fast(&mut b, &acc, c, ctrl); + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + + let mut seed = Shake128::default(); + seed.update(b"direct-cadd-small"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for shot in 0..64usize { + let x = ((shot * 37 + 11) & 0xff) as u64; + let ctrl_v = (shot & 1) as u64; + set_reg(&mut sim, &acc, x, shot); + if ctrl_v != 0 { + *sim.qubit_mut(ctrl) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + assert_eq!(sim.global_phase(), 0, "direct cadd left phase garbage"); + for shot in 0..64usize { + let x = ((shot * 37 + 11) & 0xff) as u64; + let ctrl_v = (shot & 1) as u64; + let expect = x.wrapping_add(ctrl_v * 0b1011_0111) & 0xff; + assert_eq!(get_reg(&sim, &acc, shot), expect, "shot {shot}"); + assert_eq!((sim.qubit(ctrl) >> shot) & 1, ctrl_v, "ctrl shot {shot}"); + } + } + + #[test] + fn round84_fused_square_xtail_component_matches_relation() { + let ops = build_round84_fused_square_xtail_component(); + let (num_qubits, num_bits, _num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(regs.len(), 4); + let p = SECP256K1_P; + let cases: Vec<(U256, U256, U256)> = (0..32u64) + .map(|i| { + let tx = U256::from_limbs([ + 0x9e37_79b9_7f4a_7c15u64.wrapping_mul(i + 1), + 0xd1b5_4a32_d192_ed03u64.wrapping_mul(i + 3), + 0x94d0_49bb_1331_11ebu64.wrapping_mul(i + 5), + 0x2545_f491_4f6c_dd1du64.wrapping_mul(i + 7), + ]) % p; + let lam = U256::from_limbs([ + 0xbf58_476d_1ce4_e5b9u64.wrapping_mul(i + 11), + 0x94d0_49bb_1331_11ebu64.wrapping_mul(i + 13), + 0xdbe6_d5d5_fe4c_ce2fu64.wrapping_mul(i + 17), + 0xa409_3822_299f_31d0u64.wrapping_mul(i + 19), + ]) % p; + let ox = U256::from_limbs([ + 0x632b_e59b_d9b4_e019u64.wrapping_mul(i + 23), + 0x8515_7af5_4f1d_2d2du64.wrapping_mul(i + 29), + 0x9e37_79b9_7f4a_7c15u64.wrapping_mul(i + 31), + 0xbf58_476d_1ce4_e5b9u64.wrapping_mul(i + 37), + ]) % p; + (tx, lam, ox) + }) + .collect(); + + let mut seed = Shake128::default(); + seed.update(b"round84-xtail-component"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + for (shot, (tx, lam, ox)) in cases.iter().enumerate() { + sim.set_register(®s[0], *tx, shot); + sim.set_register(®s[1], *lam, shot); + sim.set_register(®s[2], *ox, shot); + sim.set_register(®s[3], U256::ZERO, shot); + } + + sim.apply(&ops); + for (shot, (tx, lam, ox)) in cases.iter().enumerate() { + let expected = sub_mod_p( + sub_mod_p(lam.mul_mod(*lam, p), *tx, p), + ox.add_mod(*ox, p), + p, + ); + assert_eq!( + sim.get_register(®s[0], shot), + expected, + "x-tail shot {shot}" + ); + assert_eq!(sim.get_register(®s[1], shot), *lam, "lambda shot {shot}"); + assert_eq!( + sim.get_register(®s[2], shot), + *ox, + "offset-x shot {shot}" + ); + } + let live_mask = (1u64 << cases.len()) - 1; + assert_eq!(sim.global_phase() & live_mask, 0, "x-tail phase garbage"); + for reg in ®s { + for item in reg { + if let QubitOrBit::Qubit(q) = *item { + *sim.qubit_mut(q) = 0; + } + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "x-tail ancilla garbage q{q}" + ); + } + } + + #[test] + fn round190_selector_fused_source_live_residual_is_exact_on_small_widths() { + for width in [2usize, 3, 4] { + let ops = build_round190_selector_fused_source_live_residual_width(width); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 3, "width {width} register count"); + assert_eq!(regs.len(), 3, "width {width} regs"); + assert_eq!(num_bits as usize, width, "width {width} hmr bits"); + assert_eq!(num_qubits as usize, 4 * width + 3, "width {width} qubits"); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), width, "width {width} reg {idx}"); + assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); + } + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!(toffoli_ops, 3 * width, "width {width} toffoli"); + let pred_reg: Vec = regs[0] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let add_reg: Vec = regs[1] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let target_reg: Vec = regs[2] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + + let modulus = 1u64 << width; + let states = modulus * modulus * modulus; + let mut seed = Shake128::default(); + seed.update(b"round190-selector-fused-source-live-residual"); + seed.update(&[width as u8]); + let mut xof = seed.finalize_xof(); + for batch_start in (0..states).step_by(64) { + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let batch_end = (batch_start + 64).min(states); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let predecessor = case & (modulus - 1); + let addend = (case >> width) & (modulus - 1); + let target = (case >> (2 * width)) & (modulus - 1); + set_reg(&mut sim, &pred_reg, predecessor, shot); + set_reg(&mut sim, &add_reg, addend, shot); + set_reg(&mut sim, &target_reg, target, shot); + } + + sim.apply(&ops); + let live_mask = if batch_end - batch_start == 64 { + u64::MAX + } else { + (1u64 << (batch_end - batch_start)) - 1 + }; + assert_eq!( + sim.global_phase() & live_mask, + 0, + "width {width} selector-fused residual phase garbage" + ); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let predecessor = case & (modulus - 1); + let addend = (case >> width) & (modulus - 1); + let target = (case >> (2 * width)) & (modulus - 1); + let low = predecessor & 0b11; + let expected = if low == 0 { + target + } else if ((predecessor >> 1) & 1) != 0 { + target.wrapping_sub(addend) & (modulus - 1) + } else { + target.wrapping_add(addend) & (modulus - 1) + }; + assert_eq!( + get_reg(&sim, &pred_reg, shot), + predecessor, + "width {width} predecessor changed case {case}" + ); + assert_eq!( + get_reg(&sim, &add_reg, shot), + addend, + "width {width} addend changed case {case}" + ); + assert_eq!( + get_reg(&sim, &target_reg, shot), + expected, + "width {width} target mismatch case {case}" + ); + } + for reg in [&pred_reg, &add_reg, &target_reg] { + for &q in reg { + *sim.qubit_mut(q) = 0; + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "width {width} scratch garbage q{q}" + ); + } + } + } + } + + #[test] + fn round190_external_active_signed_digit_is_select0_safe_on_small_widths() { + for width in [2usize, 3, 4] { + let ops = build_round190_external_active_signed_digit_width(width); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 4, "width {width} register count"); + assert_eq!(regs.len(), 4, "width {width} regs"); + assert_eq!(num_bits as usize, width, "width {width} hmr bits"); + assert_eq!(num_qubits as usize, 3 * width + 4, "width {width} qubits"); + assert_eq!(regs[0].len(), 1, "width {width} active width"); + assert_eq!(regs[1].len(), 1, "width {width} sign width"); + assert_eq!(regs[2].len(), width, "width {width} addend width"); + assert_eq!(regs[3].len(), width, "width {width} target width"); + for (idx, reg) in regs.iter().enumerate() { + assert!( + reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_))), + "width {width} reg {idx} must be qubits" + ); + } + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!(toffoli_ops, 3 * width - 2, "width {width} toffoli"); + + let active_q = match regs[0][0] { + QubitOrBit::Qubit(q) => q, + _ => unreachable!(), + }; + let sign_q = match regs[1][0] { + QubitOrBit::Qubit(q) => q, + _ => unreachable!(), + }; + let add_reg: Vec = regs[2] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let target_reg: Vec = regs[3] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + + let modulus = 1u64 << width; + let states = 4 * modulus * modulus; + let mut seed = Shake128::default(); + seed.update(b"round190-external-active-signed-digit"); + seed.update(&[width as u8]); + let mut xof = seed.finalize_xof(); + for batch_start in (0..states).step_by(64) { + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let batch_end = (batch_start + 64).min(states); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let active = case & 1; + let sign = (case >> 1) & 1; + let addend = (case >> 2) & (modulus - 1); + let target = (case >> (2 + width)) & (modulus - 1); + *sim.qubit_mut(active_q) |= active << shot; + *sim.qubit_mut(sign_q) |= sign << shot; + set_reg(&mut sim, &add_reg, addend, shot); + set_reg(&mut sim, &target_reg, target, shot); + } + + sim.apply(&ops); + let live_mask = if batch_end - batch_start == 64 { + u64::MAX + } else { + (1u64 << (batch_end - batch_start)) - 1 + }; + assert_eq!( + sim.global_phase() & live_mask, + 0, + "width {width} external-active phase garbage" + ); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let active = case & 1; + let sign = (case >> 1) & 1; + let addend = (case >> 2) & (modulus - 1); + let target = (case >> (2 + width)) & (modulus - 1); + let expected = if active == 0 { + target + } else if sign != 0 { + target.wrapping_sub(addend) & (modulus - 1) + } else { + target.wrapping_add(addend) & (modulus - 1) + }; + assert_eq!( + (sim.qubit(active_q) >> shot) & 1, + active, + "width {width} active changed case {case}" + ); + assert_eq!( + (sim.qubit(sign_q) >> shot) & 1, + sign, + "width {width} sign changed case {case}" + ); + assert_eq!( + get_reg(&sim, &add_reg, shot), + addend, + "width {width} addend changed case {case}" + ); + assert_eq!( + get_reg(&sim, &target_reg, shot), + expected, + "width {width} target mismatch case {case}" + ); + } + *sim.qubit_mut(active_q) = 0; + *sim.qubit_mut(sign_q) = 0; + for reg in [&add_reg, &target_reg] { + for &q in reg { + *sim.qubit_mut(q) = 0; + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "width {width} external-active scratch garbage q{q}" + ); + } + } + } + } + + #[test] + fn round190_shared_active_external_digits_reuse_selector_safely_on_small_widths() { + for (width, digits) in [(2usize, 3usize), (3, 2)] { + let ops = build_round190_shared_active_external_signed_digits_width(width, digits); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!( + num_registers as usize, + 1 + 2 * digits, + "width {width} digits {digits} register count" + ); + assert_eq!( + regs.len(), + 1 + 2 * digits, + "width {width} digits {digits} regs" + ); + assert_eq!( + num_bits as usize, + width * digits, + "width {width} digits {digits} hmr bits" + ); + assert_eq!( + num_qubits as usize, + (2 * digits + 2) * width + 3, + "width {width} digits {digits} qubits" + ); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), width, "width {width} digits {digits} reg {idx}"); + assert!( + reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_))), + "width {width} digits {digits} reg {idx} must be qubits" + ); + } + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!( + toffoli_ops, + 2 + digits * (3 * width - 2), + "width {width} digits {digits} toffoli" + ); + + let qregs: Vec> = regs + .iter() + .map(|reg| { + reg.iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect() + }) + .collect(); + + let modulus = 1u64 << width; + let mut states = modulus; + for _ in 0..digits { + states *= modulus * modulus; + } + let mut seed = Shake128::default(); + seed.update(b"round190-shared-active-external-digits"); + seed.update(&[width as u8, digits as u8]); + let mut xof = seed.finalize_xof(); + for batch_start in (0..states).step_by(64) { + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let batch_end = (batch_start + 64).min(states); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let mut cursor = case; + let predecessor = cursor & (modulus - 1); + cursor >>= width; + set_reg(&mut sim, &qregs[0], predecessor, shot); + for digit in 0..digits { + let addend = cursor & (modulus - 1); + cursor >>= width; + let target = cursor & (modulus - 1); + cursor >>= width; + set_reg(&mut sim, &qregs[1 + 2 * digit], addend, shot); + set_reg(&mut sim, &qregs[2 + 2 * digit], target, shot); + } + } + + sim.apply(&ops); + let live_mask = if batch_end - batch_start == 64 { + u64::MAX + } else { + (1u64 << (batch_end - batch_start)) - 1 + }; + assert_eq!( + sim.global_phase() & live_mask, + 0, + "width {width} digits {digits} shared-active phase garbage" + ); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let mut cursor = case; + let predecessor = cursor & (modulus - 1); + cursor >>= width; + assert_eq!( + get_reg(&sim, &qregs[0], shot), + predecessor, + "width {width} digits {digits} predecessor changed case {case}" + ); + let active = (predecessor & 0b11) != 0; + let sign = ((predecessor >> 1) & 1) != 0; + for digit in 0..digits { + let addend = cursor & (modulus - 1); + cursor >>= width; + let target = cursor & (modulus - 1); + cursor >>= width; + let expected = if !active { + target + } else if sign { + target.wrapping_sub(addend) & (modulus - 1) + } else { + target.wrapping_add(addend) & (modulus - 1) + }; + assert_eq!( + get_reg(&sim, &qregs[1 + 2 * digit], shot), + addend, + "width {width} digits {digits} addend {digit} changed case {case}" + ); + assert_eq!( + get_reg(&sim, &qregs[2 + 2 * digit], shot), + expected, + "width {width} digits {digits} target {digit} mismatch case {case}" + ); + } + } + for reg in &qregs { + for &q in reg { + *sim.qubit_mut(q) = 0; + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "width {width} digits {digits} shared-active scratch garbage q{q}" + ); + } + } + } + } + + #[test] + fn round190_two_slot_router_is_exact_only_under_exactly_one_active_invariant() { + for width in [2usize, 3] { + let ops = build_round190_two_slot_exactly_one_active_router_width(width); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 6, "width {width} register count"); + assert_eq!(regs.len(), 6, "width {width} regs"); + assert_eq!(num_bits as usize, width - 1, "width {width} hmr bits"); + assert_eq!(num_qubits as usize, 7 * width + 2, "width {width} qubits"); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), width, "width {width} reg {idx}"); + assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); + } + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!(toffoli_ops, 7 * width + 1, "width {width} toffoli"); + + let qregs: Vec> = regs + .iter() + .map(|reg| { + reg.iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect() + }) + .collect(); + let modulus = 1u64 << width; + let active_predecessors: Vec = + (0..modulus).filter(|pred| (pred & 0b11) != 0).collect(); + let inactive_predecessors: Vec = + (0..modulus).filter(|pred| (pred & 0b11) == 0).collect(); + + let mut cases = Vec::new(); + if width == 2 { + for active_slot in 0..2usize { + for &active_pred in &active_predecessors { + for &inactive_pred in &inactive_predecessors { + for add0 in 0..modulus { + for target0 in 0..modulus { + for add1 in 0..modulus { + for target1 in 0..modulus { + let (pred0, pred1) = if active_slot == 0 { + (active_pred, inactive_pred) + } else { + (inactive_pred, active_pred) + }; + cases.push(( + active_slot, + pred0, + add0, + target0, + pred1, + add1, + target1, + )); + } + } + } + } + } + } + } + } else { + for i in 0..512u64 { + let active_slot = (i & 1) as usize; + let active_pred = + active_predecessors[((i / 2) as usize) % active_predecessors.len()]; + let inactive_pred = + inactive_predecessors[((i / 14) as usize) % inactive_predecessors.len()]; + let add0 = (3 * i + 1) & (modulus - 1); + let target0 = (5 * i + 2) & (modulus - 1); + let add1 = (7 * i + 3) & (modulus - 1); + let target1 = (11 * i + 4) & (modulus - 1); + let (pred0, pred1) = if active_slot == 0 { + (active_pred, inactive_pred) + } else { + (inactive_pred, active_pred) + }; + cases.push((active_slot, pred0, add0, target0, pred1, add1, target1)); + } + } + + let mut seed = Shake128::default(); + seed.update(b"round190-two-slot-router"); + seed.update(&[width as u8]); + let mut xof = seed.finalize_xof(); + for batch_start in (0..cases.len()).step_by(64) { + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let batch_end = (batch_start + 64).min(cases.len()); + for (shot, case) in cases[batch_start..batch_end].iter().enumerate() { + let &(_, pred0, add0, target0, pred1, add1, target1) = case; + set_reg(&mut sim, &qregs[0], pred0, shot); + set_reg(&mut sim, &qregs[1], add0, shot); + set_reg(&mut sim, &qregs[2], target0, shot); + set_reg(&mut sim, &qregs[3], pred1, shot); + set_reg(&mut sim, &qregs[4], add1, shot); + set_reg(&mut sim, &qregs[5], target1, shot); + } + + sim.apply(&ops); + let live_mask = if batch_end - batch_start == 64 { + u64::MAX + } else { + (1u64 << (batch_end - batch_start)) - 1 + }; + assert_eq!( + sim.global_phase() & live_mask, + 0, + "width {width} two-slot router phase garbage" + ); + for (shot, case) in cases[batch_start..batch_end].iter().enumerate() { + let &(active_slot, pred0, add0, target0, pred1, add1, target1) = case; + let sign = if active_slot == 0 { + (pred0 >> 1) & 1 + } else { + (pred1 >> 1) & 1 + }; + let expected0 = if active_slot == 0 { + if sign != 0 { + target0.wrapping_sub(add0) & (modulus - 1) + } else { + target0.wrapping_add(add0) & (modulus - 1) + } + } else { + target0 + }; + let expected1 = if active_slot == 1 { + if sign != 0 { + target1.wrapping_sub(add1) & (modulus - 1) + } else { + target1.wrapping_add(add1) & (modulus - 1) + } + } else { + target1 + }; + assert_eq!(get_reg(&sim, &qregs[0], shot), pred0, "pred0 case {case:?}"); + assert_eq!(get_reg(&sim, &qregs[1], shot), add0, "add0 case {case:?}"); + assert_eq!( + get_reg(&sim, &qregs[2], shot), + expected0, + "target0 case {case:?}" + ); + assert_eq!(get_reg(&sim, &qregs[3], shot), pred1, "pred1 case {case:?}"); + assert_eq!(get_reg(&sim, &qregs[4], shot), add1, "add1 case {case:?}"); + assert_eq!( + get_reg(&sim, &qregs[5], shot), + expected1, + "target1 case {case:?}" + ); + } + for reg in &qregs { + for &q in reg { + *sim.qubit_mut(q) = 0; + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "width {width} two-slot router scratch garbage q{q}" + ); + } + } + } + } + + #[test] + fn round190_active_source_live_signed_digit_hmr_is_exact_on_active_rows() { + for width in [2usize, 3, 4] { + let ops = build_round190_active_source_live_signed_digit_hmr_width(width); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 3, "width {width} register count"); + assert_eq!(regs.len(), 3, "width {width} regs"); + assert_eq!(num_bits as usize, width - 1, "width {width} hmr bits"); + assert_eq!(num_qubits as usize, 4 * width + 1, "width {width} qubits"); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), width, "width {width} reg {idx}"); + assert!(reg.iter().all(|item| matches!(item, QubitOrBit::Qubit(_)))); + } + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!(toffoli_ops, width - 1, "width {width} toffoli"); + let pred_reg: Vec = regs[0] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let add_reg: Vec = regs[1] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let target_reg: Vec = regs[2] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + + let modulus = 1u64 << width; + let active_predecessors: Vec = + (0..modulus).filter(|pred| (pred & 0b11) != 0).collect(); + let states = active_predecessors.len() as u64 * modulus * modulus; + let mut seed = Shake128::default(); + seed.update(b"round190-active-source-live-signed-digit-hmr"); + seed.update(&[width as u8]); + let mut xof = seed.finalize_xof(); + for batch_start in (0..states).step_by(64) { + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let batch_end = (batch_start + 64).min(states); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let pred_idx = (case % active_predecessors.len() as u64) as usize; + let addend = (case / active_predecessors.len() as u64) & (modulus - 1); + let target = + (case / (active_predecessors.len() as u64 * modulus)) & (modulus - 1); + let predecessor = active_predecessors[pred_idx]; + set_reg(&mut sim, &pred_reg, predecessor, shot); + set_reg(&mut sim, &add_reg, addend, shot); + set_reg(&mut sim, &target_reg, target, shot); + } + + sim.apply(&ops); + let live_mask = if batch_end - batch_start == 64 { + u64::MAX + } else { + (1u64 << (batch_end - batch_start)) - 1 + }; + assert_eq!( + sim.global_phase() & live_mask, + 0, + "width {width} active HMR signed digit phase garbage" + ); + for case in batch_start..batch_end { + let shot = (case - batch_start) as usize; + let pred_idx = (case % active_predecessors.len() as u64) as usize; + let addend = (case / active_predecessors.len() as u64) & (modulus - 1); + let target = + (case / (active_predecessors.len() as u64 * modulus)) & (modulus - 1); + let predecessor = active_predecessors[pred_idx]; + let expected = if ((predecessor >> 1) & 1) != 0 { + target.wrapping_sub(addend) & (modulus - 1) + } else { + target.wrapping_add(addend) & (modulus - 1) + }; + assert_eq!( + get_reg(&sim, &pred_reg, shot), + predecessor, + "width {width} predecessor changed case {case}" + ); + assert_eq!( + get_reg(&sim, &add_reg, shot), + addend, + "width {width} addend changed case {case}" + ); + assert_eq!( + get_reg(&sim, &target_reg, shot), + expected, + "width {width} target mismatch case {case}" + ); + } + for reg in [&pred_reg, &add_reg, &target_reg] { + for &q in reg { + *sim.qubit_mut(q) = 0; + } + } + for q in 0..num_qubits { + assert_eq!( + sim.qubit(QubitId(q)) & live_mask, + 0, + "width {width} active HMR scratch garbage q{q}" + ); + } + } + } + } + + #[test] + fn round190_active_hmr_digit_is_not_select0_safe() { + const WIDTH: usize = 3; + let ops = build_round190_active_source_live_signed_digit_hmr_width(WIDTH); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 3); + assert_eq!(regs.len(), 3); + let pred_reg: Vec = regs[0] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let add_reg: Vec = regs[1] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + let target_reg: Vec = regs[2] + .iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => unreachable!(), + }) + .collect(); + + let mut seed = Shake128::default(); + seed.update(b"round190-active-hmr-not-select0-safe"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + let inactive_predecessor = 0u64; + let addend = 3u64; + let target = 4u64; + set_reg(&mut sim, &pred_reg, inactive_predecessor, 0); + set_reg(&mut sim, &add_reg, addend, 0); + set_reg(&mut sim, &target_reg, target, 0); + + sim.apply(&ops); + let got_target = get_reg(&sim, &target_reg, 0); + println!("METRIC round190_active_hmr_inactive_predecessor={inactive_predecessor}"); + println!("METRIC round190_active_hmr_inactive_addend={addend}"); + println!("METRIC round190_active_hmr_inactive_target_before={target}"); + println!("METRIC round190_active_hmr_inactive_target_after={got_target}"); + assert_eq!(get_reg(&sim, &pred_reg, 0), inactive_predecessor); + assert_eq!(get_reg(&sim, &add_reg, 0), addend); + assert_ne!( + got_target, target, + "active-HMR digit cannot be used as the select0-safe production residual" + ); + } + + fn qubit_reg(reg: &[QubitOrBit]) -> Vec { + reg.iter() + .map(|item| match item { + QubitOrBit::Qubit(q) => *q, + _ => panic!("expected qubit register"), + }) + .collect() + } + + fn round556_expected( + width: usize, + q_bits: usize, + rem: u64, + rem_divisor: u64, + coeff_seed: u64, + coeff_divisor: u64, + sigma: u64, + q_increment: u64, + ) -> Option<(u64, u64)> { + let modulus = 1u64 << width; + let mask = modulus - 1; + if rem_divisor == 0 || coeff_divisor == 0 { + return None; + } + if (rem_divisor << (q_bits - 1)) >= modulus { + return None; + } + if (coeff_divisor << (q_bits - 1)) >= modulus { + return None; + } + let quotient = rem / rem_divisor; + if quotient >= (1u64 << q_bits) { + return None; + } + if coeff_seed >= coeff_divisor { + return None; + } + let coeff_restored = coeff_seed + (quotient + q_increment) * coeff_divisor; + if coeff_restored >= modulus { + return None; + } + let coeff = coeff_restored.wrapping_sub((sigma & 1) * coeff_divisor) & mask; + Some((rem % rem_divisor, coeff)) + } + + #[test] + fn round556_shifted_source_row_component_has_material_free_bound() { + const WIDTH: usize = 258; + const QBITS: usize = 26; + let (ops, phases, peak_qubits, peak_phase) = + build_round556_shifted_source_row_component_phase_resources(WIDTH, QBITS); + let (num_qubits, _num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + let old_materialized_formula = (6 * QBITS + 4) * WIDTH - (2 * QBITS + 2); + let shifted_source_q = 6 * WIDTH + QBITS + 5; + + assert_eq!(num_registers, 5); + assert_eq!(regs[0].len(), WIDTH); + assert_eq!(regs[1].len(), WIDTH); + assert_eq!(regs[2].len(), WIDTH); + assert_eq!(regs[3].len(), WIDTH); + assert_eq!(regs[4].len(), 4 + QBITS); + assert_eq!(num_qubits as usize, shifted_source_q); + assert_eq!(peak_qubits as usize, shifted_source_q); + assert!(toffoli_ops <= old_materialized_formula); + assert!(phases + .iter() + .any(|row| row.phase == "round556_shifted_source_remainder_digits")); + assert_eq!(peak_phase, "round556_shifted_source_remainder_digits"); + } + + #[test] + fn round556_shifted_source_row_component_matches_round120_relation() { + const WIDTH: usize = 5; + const QBITS: usize = 3; + let ops = build_round556_shifted_source_row_component(WIDTH, QBITS); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + assert_eq!(num_registers, 5); + let rem_reg = qubit_reg(®s[0]); + let rem_divisor_reg = qubit_reg(®s[1]); + let coeff_reg = qubit_reg(®s[2]); + let coeff_divisor_reg = qubit_reg(®s[3]); + let meta_reg = qubit_reg(®s[4]); + + let mut public = vec![false; num_qubits as usize]; + for reg in [ + &rem_reg, + &rem_divisor_reg, + &coeff_reg, + &coeff_divisor_reg, + &meta_reg, + ] { + for &q in reg { + public[q.0 as usize] = true; + } + } + + let mut cases = Vec::new(); + let modulus = 1u64 << WIDTH; + for rem_divisor in 1..modulus { + for coeff_divisor in 1..modulus { + for rem in 0..modulus { + for coeff_seed in 0..coeff_divisor { + for sigma in 0..=1u64 { + for q_increment in 0..=1u64 { + if let Some(expected) = round556_expected( + WIDTH, + QBITS, + rem, + rem_divisor, + coeff_seed, + coeff_divisor, + sigma, + q_increment, + ) { + cases.push(( + rem, + rem_divisor, + coeff_seed, + coeff_divisor, + sigma, + q_increment, + expected, + )); + } + } + } + } + } + } + } + assert!(!cases.is_empty()); + + let mut seed = Shake128::default(); + seed.update(b"round556-shifted-source-row-relation"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits as usize, num_bits as usize, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, case) in chunk.iter().enumerate() { + let (rem, rem_divisor, coeff_seed, coeff_divisor, sigma, q_increment, _) = *case; + set_reg(&mut sim, &rem_reg, rem, shot); + set_reg(&mut sim, &rem_divisor_reg, rem_divisor, shot); + set_reg(&mut sim, &coeff_reg, coeff_seed, shot); + set_reg(&mut sim, &coeff_divisor_reg, coeff_divisor, shot); + set_reg(&mut sim, &meta_reg, sigma | (q_increment << 1), shot); + } + sim.apply(&ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for q in 0..num_qubits { + if !public[q as usize] { + assert_eq!( + sim.qubit(QubitId(q as u32)) & live, + 0, + "scratch q{q} dirty in batch {batch}" + ); + } + } + for (shot, case) in chunk.iter().enumerate() { + let ( + _rem, + rem_divisor, + _coeff_seed, + coeff_divisor, + sigma, + q_increment, + (expected_rem, expected_coeff), + ) = *case; + assert_eq!( + get_reg(&sim, &rem_reg, shot), + expected_rem, + "batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &rem_divisor_reg, shot), + rem_divisor, + "batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &coeff_reg, shot), + expected_coeff, + "batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &coeff_divisor_reg, shot), + coeff_divisor, + "batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &meta_reg, shot), + sigma | (q_increment << 1), + "batch {batch} shot {shot}" + ); + } + } + } + + #[test] + fn direct_centered_shifted_source_qbit_row_fit_bench_has_sidecar_bound() { + const Q_BITS: usize = DIRECT_CENTERED_LOW_BRANCH_META_BITS; + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_shifted_source_qbit_row_fit_bench_phase_resources(Q_BITS); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(num_registers, 4); + assert_eq!(regs.len(), 4); + assert!(num_bits as usize >= 2 * N); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), N, "register {idx} width"); + } + let sidecar_q = 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS; + assert_eq!(num_qubits as usize, sidecar_q); + assert_eq!(peak_qubits as usize, sidecar_q); + assert_eq!( + toffoli_ops, + Q_BITS * (6 * N - 2) - 2 * Q_BITS * (Q_BITS - 1) + ); + assert_eq!( + peak_phase, + "direct_centered_shifted_source_qbit_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_shifted_source_qbit_remainder_digits")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_shifted_source_qbit_coeff_digits")); + } + + #[test] + fn direct_centered_shifted_source_qbit_row_toy_is_exact_and_phase_clean() { + const WIDTH: usize = 5; + const QBITS: usize = 3; + let mut b = B::new(); + let rem = b.alloc_qubits(WIDTH); + let rem_divisor = b.alloc_qubits(WIDTH); + let coeff = b.alloc_qubits(WIDTH); + let coeff_divisor = b.alloc_qubits(WIDTH); + let qbits = b.alloc_qubits(QBITS); + let gated = b.alloc_qubits(WIDTH); + let lt_tmp = b.alloc_qubit(); + let sign_one = b.alloc_qubit(); + let nonnegative = b.alloc_qubit(); + let carries = b.alloc_qubits(WIDTH - 1); + emit_direct_centered_shifted_source_qbit_row( + &mut b, + &rem, + &rem_divisor, + &coeff, + &coeff_divisor, + &qbits, + &gated, + lt_tmp, + sign_one, + nonnegative, + &carries, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut public = vec![false; nq]; + for reg in [&rem, &rem_divisor, &coeff, &coeff_divisor] { + for &q in reg { + public[q.0 as usize] = true; + } + } + + let modulus = 1u64 << WIDTH; + let mut cases = Vec::new(); + for rem_divisor_value in 1..modulus { + for coeff_divisor_value in 1..modulus { + for rem_value in 0..modulus { + for coeff_seed in 0..coeff_divisor_value { + if let Some(expected) = round556_expected( + WIDTH, + QBITS, + rem_value, + rem_divisor_value, + coeff_seed, + coeff_divisor_value, + 0, + 0, + ) { + cases.push(( + rem_value, + rem_divisor_value, + coeff_seed, + coeff_divisor_value, + expected, + )); + } + } + } + } + } + assert!(!cases.is_empty()); + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-shifted-source-qbit-row-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, case) in chunk.iter().enumerate() { + let (rem_value, rem_divisor_value, coeff_seed, coeff_divisor_value, _) = *case; + set_reg(&mut sim, &rem, rem_value, shot); + set_reg(&mut sim, &rem_divisor, rem_divisor_value, shot); + set_reg(&mut sim, &coeff, coeff_seed, shot); + set_reg(&mut sim, &coeff_divisor, coeff_divisor_value, shot); + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for q in 0..nq { + if !public[q] { + assert_eq!( + sim.qubit(QubitId(q as u32)) & live, + 0, + "scratch q{q} dirty in batch {batch}" + ); + } + } + for (shot, case) in chunk.iter().enumerate() { + let ( + _rem_value, + rem_divisor_value, + _coeff_seed, + coeff_divisor_value, + (expected_rem, expected_coeff), + ) = *case; + assert_eq!(get_reg(&sim, &rem, shot), expected_rem); + assert_eq!(get_reg(&sim, &rem_divisor, shot), rem_divisor_value); + assert_eq!(get_reg(&sim, &coeff, shot), expected_coeff); + assert_eq!(get_reg(&sim, &coeff_divisor, shot), coeff_divisor_value); + } + } + } + + #[test] + fn direct_centered_branch_sidecar_component_has_relaxed_google_abi_shape() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_branch_sidecar_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N); + for (idx, reg) in regs.iter().enumerate() { + assert_eq!(reg.len(), N, "register {idx} width"); + } + for item in ®s[0] { + assert!(matches!(item, QubitOrBit::Qubit(_)), "r0 must be qubits"); + } + for item in ®s[1] { + assert!(matches!(item, QubitOrBit::Qubit(_)), "r1 must be qubits"); + } + for item in ®s[2] { + assert!(matches!(item, QubitOrBit::Bit(_)), "r2 must be bits"); + } + for item in ®s[3] { + assert!(matches!(item, QubitOrBit::Bit(_)), "r3 must be bits"); + } + + let scratch = num_qubits as usize - 2 * N; + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!( + scratch, + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert!(scratch <= DIRECT_CENTERED_RELAXED_SCRATCH_BUDGET); + assert!(num_qubits as usize <= DIRECT_CENTERED_RELAXED_Q_TARGET); + assert!(toffoli_ops < DIRECT_CENTERED_RELAXED_T_TARGET); + assert_eq!(toffoli_ops, 936); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(peak_phase, "direct_centered_sidecar_google_abi"); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_sidecar_emit_branch_history")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_sidecar_clear_branch_history")); + } + + #[test] + fn direct_centered_branch_digit_clean_toy_is_exact() { + const W: usize = 5; + let mut b = B::new(); + let coeff_acc = b.alloc_qubits(W); + let coeff_v = b.alloc_qubits(W); + let branch = b.alloc_qubit(); + let sign = b.alloc_qubit(); + let gated = b.alloc_qubits(W); + let carry = b.alloc_qubit(); + emit_direct_centered_branch_digit_update_clean( + &mut b, &coeff_acc, &coeff_v, branch, sign, &gated, carry, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let modulus = 1u64 << W; + let mut cases = Vec::new(); + for acc in 0..modulus { + for source in 0..modulus { + for branch_value in 0..=1u64 { + for sign_value in 0..=1u64 { + let expected = if branch_value == 0 { + acc + } else if sign_value != 0 { + (acc + source) & (modulus - 1) + } else { + acc.wrapping_sub(source) & (modulus - 1) + }; + cases.push((acc, source, branch_value, sign_value, expected)); + } + } + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-branch-digit-clean-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(acc, source, branch_value, sign_value, _expected)) in + chunk.iter().enumerate() + { + set_reg(&mut sim, &coeff_acc, acc, shot); + set_reg(&mut sim, &coeff_v, source, shot); + if branch_value != 0 { + *sim.qubit_mut(branch) |= 1u64 << shot; + } + if sign_value != 0 { + *sim.qubit_mut(sign) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + assert_eq!(sim.qubit(carry) & live, 0, "carry dirty in batch {batch}"); + for (shot, &(acc, source, branch_value, sign_value, expected)) in + chunk.iter().enumerate() + { + assert_eq!( + get_reg(&sim, &gated, shot), + 0, + "gated dirty in batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &coeff_acc, shot), + expected, + "batch {batch} shot {shot}" + ); + assert_eq!( + get_reg(&sim, &coeff_v, shot), + source, + "batch {batch} shot {shot}" + ); + assert_eq!( + (sim.qubit(branch) >> shot) & 1, + branch_value, + "batch {batch} shot {shot}" + ); + assert_eq!( + (sim.qubit(sign) >> shot) & 1, + sign_value, + "batch {batch} shot {shot}" + ); + let _ = acc; + } + } + } + + #[test] + fn direct_centered_branch_replay_then_fast_finalizer_toy_is_exact() { + const W: usize = 4; + const HISTORY: usize = 3; + let mut b = B::new(); + let coeff_acc = b.alloc_qubits(W); + let coeff_v = b.alloc_qubits(W); + let pred_a = b.alloc_qubits(HISTORY); + let pred_b = b.alloc_qubits(HISTORY); + let branch = b.alloc_qubits(HISTORY); + let sign = b.alloc_qubit(); + let gated = b.alloc_qubits(W); + let digit_carry = b.alloc_qubit(); + let nonnegative = b.alloc_qubit(); + let extra_carry = b.alloc_qubit(); + + for i in 0..HISTORY { + b.ccx(pred_a[i], pred_b[i], branch[i]); + } + for &branch_bit in &branch { + emit_direct_centered_branch_digit_update_clean( + &mut b, + &coeff_acc, + &coeff_v, + branch_bit, + sign, + &gated, + digit_carry, + ); + } + for i in (1..HISTORY).rev() { + b.ccx(pred_a[i], pred_b[i], branch[i]); + } + let carries = [branch[1], branch[2], extra_carry]; + emit_direct_centered_branch_retained_finalizer_fast( + &mut b, + &coeff_acc, + &coeff_v, + branch[0], + &gated, + nonnegative, + &carries, + ); + b.ccx(pred_a[0], pred_b[0], branch[0]); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let modulus = 1u64 << W; + let mask = modulus - 1; + let mut cases = Vec::new(); + for acc in 0..modulus { + for source in 0..modulus { + for pred_a_value in 0..(1u64 << HISTORY) { + for pred_b_value in 0..(1u64 << HISTORY) { + for sign_value in 0..=1u64 { + let mut expected = acc; + for i in 0..HISTORY { + let branch_value = + ((pred_a_value >> i) & 1) & ((pred_b_value >> i) & 1); + if branch_value != 0 { + expected = if sign_value != 0 { + expected.wrapping_add(source) & mask + } else { + expected.wrapping_sub(source) & mask + }; + } + } + if (pred_a_value & 1) != 0 && (pred_b_value & 1) != 0 { + expected = expected.wrapping_sub(source) & mask; + } + cases.push(( + acc, + source, + pred_a_value, + pred_b_value, + sign_value, + expected, + )); + } + } + } + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-branch-replay-fast-finalizer-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(acc, source, pred_a_value, pred_b_value, sign_value, _expected)) in + chunk.iter().enumerate() + { + set_reg(&mut sim, &coeff_acc, acc, shot); + set_reg(&mut sim, &coeff_v, source, shot); + set_reg(&mut sim, &pred_a, pred_a_value, shot); + set_reg(&mut sim, &pred_b, pred_b_value, shot); + if sign_value != 0 { + *sim.qubit_mut(sign) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + assert_eq!(sim.qubit(digit_carry) & live, 0, "digit carry dirty"); + assert_eq!(sim.qubit(nonnegative) & live, 0, "nonnegative dirty"); + assert_eq!(sim.qubit(extra_carry) & live, 0, "extra carry dirty"); + for &branch_bit in &branch { + assert_eq!(sim.qubit(branch_bit) & live, 0, "branch history dirty"); + } + for (shot, &(acc, source, pred_a_value, pred_b_value, sign_value, expected)) in + chunk.iter().enumerate() + { + assert_eq!( + get_reg(&sim, &coeff_acc, shot), + expected, + "batch {batch} shot {shot}" + ); + assert_eq!(get_reg(&sim, &gated, shot), 0); + assert_eq!(get_reg(&sim, &coeff_v, shot), source); + assert_eq!(get_reg(&sim, &pred_a, shot), pred_a_value); + assert_eq!(get_reg(&sim, &pred_b, shot), pred_b_value); + assert_eq!((sim.qubit(sign) >> shot) & 1, sign_value); + let _ = acc; + } + } + } + + #[test] + fn direct_centered_low_path_branch_predicate_toy_is_exact() { + const W: usize = 4; + let mut b = B::new(); + let low_path = b.alloc_qubits(W); + let divisor = b.alloc_qubits(W); + let branch = b.alloc_qubit(); + let shifted = b.alloc_qubits(W + 1); + let divisor_high = b.alloc_qubit(); + let cmp_cin = b.alloc_qubit(); + emit_direct_centered_low_path_branch_toggle( + &mut b, + &low_path, + &divisor, + branch, + &shifted, + divisor_high, + cmp_cin, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut cases = Vec::new(); + for low_value in 0..(1u64 << W) { + for divisor_value in 0..(1u64 << W) { + for initial_branch in 0..=1u64 { + let predicate = if 2 * low_value >= divisor_value { 1 } else { 0 }; + cases.push(( + low_value, + divisor_value, + initial_branch, + initial_branch ^ predicate, + )); + } + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-low-path-branch-predicate-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(low_value, divisor_value, initial_branch, _expected_branch)) in + chunk.iter().enumerate() + { + set_reg(&mut sim, &low_path, low_value, shot); + set_reg(&mut sim, &divisor, divisor_value, shot); + if initial_branch != 0 { + *sim.qubit_mut(branch) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for &wire in &shifted { + assert_eq!(sim.qubit(wire) & live, 0, "shifted scratch dirty"); + } + assert_eq!( + sim.qubit(divisor_high) & live, + 0, + "divisor-high scratch dirty" + ); + assert_eq!(sim.qubit(cmp_cin) & live, 0, "cmp-cin scratch dirty"); + for (shot, &(low_value, divisor_value, _initial_branch, expected_branch)) in + chunk.iter().enumerate() + { + assert_eq!(get_reg(&sim, &low_path, shot), low_value); + assert_eq!(get_reg(&sim, &divisor, shot), divisor_value); + assert_eq!( + (sim.qubit(branch) >> shot) & 1, + expected_branch, + "batch {batch} shot {shot}" + ); + } + } + } + + #[test] + fn direct_centered_branch_predicate_step_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_branch_predicate_step_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 3 * N); + let scratch = num_qubits as usize - 2 * N; + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!( + scratch, + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert!(scratch <= DIRECT_CENTERED_RELAXED_SCRATCH_BUDGET); + assert!(num_qubits as usize <= DIRECT_CENTERED_RELAXED_Q_TARGET); + assert!(toffoli_ops < 2_000); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!( + peak_phase, + "direct_centered_branch_predicate_step_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_predicate_compare")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); + } + + #[test] + fn direct_centered_binary_trie_qrom_toy_is_exact_and_phase_clean() { + const ADDRESS_BITS: usize = 3; + const TARGET_BITS: usize = 5; + const ROWS: usize = 6; + + let table_words: Vec = (0..ROWS) + .map(|row| ((row as u64).wrapping_mul(0b10101) ^ 0b10010) & ((1u64 << TARGET_BITS) - 1)) + .collect(); + + let mut b = B::new(); + let address = b.alloc_qubits(ADDRESS_BITS); + let target = b.alloc_qubits(TARGET_BITS); + emit_direct_centered_binary_trie_qrom_xor_table( + &mut b, + &address, + &target, + ROWS, + &table_words, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut public = vec![false; nq]; + for &q in address.iter().chain(target.iter()) { + public[q.0 as usize] = true; + } + + let mut cases = Vec::new(); + for addr in 0..(1u64 << ADDRESS_BITS) { + for before in 0..(1u64 << TARGET_BITS) { + let loaded = if (addr as usize) < ROWS { + table_words[addr as usize] + } else { + 0 + }; + cases.push((addr, before, before ^ loaded)); + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-binary-trie-qrom-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(addr, before, _expected)) in chunk.iter().enumerate() { + set_reg(&mut sim, &address, addr, shot); + set_reg(&mut sim, &target, before, shot); + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for q in 0..nq { + if !public[q] { + assert_eq!( + sim.qubit(QubitId(q as u32)) & live, + 0, + "scratch q{q} dirty in batch {batch}" + ); + } + } + for (shot, &(addr, _before, expected)) in chunk.iter().enumerate() { + assert_eq!(get_reg(&sim, &address, shot), addr); + assert_eq!(get_reg(&sim, &target, shot), expected); + } + } + } + + #[test] + fn direct_centered_binary_trie_qrom_roundtrip_toy_is_exact_and_phase_clean() { + const ADDRESS_BITS: usize = 3; + const TARGET_BITS: usize = 9; + const ROWS: usize = 6; + + let table_words = direct_centered_binary_trie_qrom_table_words(ROWS, TARGET_BITS); + + let mut b = B::new(); + let address = b.alloc_qubits(ADDRESS_BITS); + let target = b.alloc_qubits(TARGET_BITS); + emit_direct_centered_binary_trie_qrom_xor_table( + &mut b, + &address, + &target, + ROWS, + &table_words, + ); + emit_direct_centered_binary_trie_qrom_xor_table( + &mut b, + &address, + &target, + ROWS, + &table_words, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut public = vec![false; nq]; + for &q in address.iter().chain(target.iter()) { + public[q.0 as usize] = true; + } + + let mut cases = Vec::new(); + for addr in 0..(1u64 << ADDRESS_BITS) { + for before in 0..(1u64 << TARGET_BITS) { + cases.push((addr, before)); + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-binary-trie-qrom-roundtrip-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(addr, before)) in chunk.iter().enumerate() { + set_reg(&mut sim, &address, addr, shot); + set_reg(&mut sim, &target, before, shot); + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for q in 0..nq { + if !public[q] { + assert_eq!( + sim.qubit(QubitId(q as u32)) & live, + 0, + "scratch q{q} dirty in batch {batch}" + ); + } + } + for (shot, &(addr, before)) in chunk.iter().enumerate() { + assert_eq!(get_reg(&sim, &address, shot), addr); + assert_eq!(get_reg(&sim, &target, shot), before); + } + } + } + + #[test] + fn direct_centered_binary_trie_qrom_hits_round728_row_multiplier_budget() { + const ROWS: usize = 4_934; + const ADDRESS_BITS: usize = 13; + const TARGET_BITS: usize = 16; + + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_binary_trie_qrom_bench_phase_resources( + ROWS, + ADDRESS_BITS, + TARGET_BITS, + ); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + let expected_nodes = direct_centered_binary_trie_qrom_node_count(ROWS, ADDRESS_BITS); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N + expected_nodes); + assert_eq!(toffoli_ops, expected_nodes); + assert!(toffoli_ops <= 2 * ROWS + ADDRESS_BITS); + assert!(toffoli_ops <= 6 * ROWS); + assert_eq!(num_qubits as usize, 2 * N + ADDRESS_BITS + 1); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(peak_phase, "direct_centered_binary_trie_qrom_unary_walk"); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_binary_trie_qrom_unary_walk")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_binary_trie_qrom_clear_root")); + } + + #[test] + fn direct_centered_binary_trie_qrom_roundtrip_fits_round730_wide_payload_budget() { + const ROWS: usize = 4_934; + const ADDRESS_BITS: usize = 13; + const TARGET_BITS: usize = 84; + + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_binary_trie_qrom_roundtrip_bench_phase_resources( + ROWS, + ADDRESS_BITS, + TARGET_BITS, + ); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + let expected_nodes = direct_centered_binary_trie_qrom_node_count(ROWS, ADDRESS_BITS); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N + 2 * expected_nodes); + assert_eq!(toffoli_ops, 2 * expected_nodes); + assert_eq!(toffoli_ops, 19_746); + assert!(toffoli_ops <= 4 * ROWS + 2 * ADDRESS_BITS); + assert_eq!(num_qubits as usize, 2 * N + ADDRESS_BITS + 1); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!( + peak_phase, + "direct_centered_binary_trie_qrom_roundtrip_load_walk" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_binary_trie_qrom_roundtrip_load_walk")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_binary_trie_qrom_roundtrip_clear_walk")); + } + + #[test] + fn direct_centered_inline_predicate_finalizer_delta_fits_google_fast_width_if_replay_deleted() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_inline_predicate_finalizer_delta_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 3 * N - 1); + let scratch = num_qubits as usize - 2 * N; + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + assert_eq!( + scratch, + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS + ); + assert_eq!(num_qubits as usize, 1_425); + assert!(toffoli_ops < 122_000); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!( + peak_phase, + "direct_centered_inline_predicate_delta_alloc_dual_history_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_predicate_compare")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); + assert!(!phases + .iter() + .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); + } + + #[test] + fn direct_centered_branch_retained_finalizer_toy_is_exact() { + const W: usize = 5; + let mut b = B::new(); + let remainder = b.alloc_qubits(W); + let divisor = b.alloc_qubits(W); + let branch = b.alloc_qubit(); + let gated = b.alloc_qubits(W); + let carry = b.alloc_qubit(); + emit_direct_centered_branch_retained_finalizer( + &mut b, &remainder, &divisor, branch, &gated, carry, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let modulus = 1u64 << W; + let mut cases = 0usize; + for divisor_value in 1..(1u64 << (W - 1)) { + for final_remainder in 0..divisor_value { + for branch_value in 0..=1u64 { + let prefinal = final_remainder + branch_value * divisor_value; + if prefinal >= modulus { + continue; + } + cases += 1; + let mut seed = Shake128::default(); + seed.update(&(cases as u64).to_le_bytes()); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + set_reg(&mut sim, &remainder, prefinal, 0); + set_reg(&mut sim, &divisor, divisor_value, 0); + if branch_value != 0 { + *sim.qubit_mut(branch) |= 1; + } + sim.apply(&b.ops); + assert_eq!(get_reg(&sim, &remainder, 0), final_remainder); + assert_eq!(get_reg(&sim, &divisor, 0), divisor_value); + assert_eq!((sim.qubit(branch) & 1), branch_value); + assert_eq!(sim.qubit(carry) & 1, 0); + assert_eq!(get_reg(&sim, &gated, 0), 0); + } + } + } + assert_eq!(cases, 240); + } + + #[test] + fn direct_centered_branch_retained_fast_finalizer_toy_is_exact() { + const W: usize = 5; + let mut b = B::new(); + let remainder = b.alloc_qubits(W); + let divisor = b.alloc_qubits(W); + let branch = b.alloc_qubit(); + let gated = b.alloc_qubits(W); + let nonnegative = b.alloc_qubit(); + let carries = b.alloc_qubits(W - 1); + emit_direct_centered_branch_retained_finalizer_fast( + &mut b, + &remainder, + &divisor, + branch, + &gated, + nonnegative, + &carries, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let modulus = 1u64 << W; + let mut cases = 0usize; + for divisor_value in 1..(1u64 << (W - 1)) { + for final_remainder in 0..divisor_value { + for branch_value in 0..=1u64 { + let prefinal = final_remainder + branch_value * divisor_value; + if prefinal >= modulus { + continue; + } + cases += 1; + let mut seed = Shake128::default(); + seed.update(&(0xFA57_0000u64 + cases as u64).to_le_bytes()); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + set_reg(&mut sim, &remainder, prefinal, 0); + set_reg(&mut sim, &divisor, divisor_value, 0); + if branch_value != 0 { + *sim.qubit_mut(branch) |= 1; + } + sim.apply(&b.ops); + assert_eq!(get_reg(&sim, &remainder, 0), final_remainder); + assert_eq!(get_reg(&sim, &divisor, 0), divisor_value); + assert_eq!(sim.qubit(branch) & 1, branch_value); + assert_eq!(sim.qubit(nonnegative) & 1, 0); + assert_eq!(get_reg(&sim, &gated, 0), 0); + assert_eq!(get_reg(&sim, &carries, 0), 0); + assert_eq!(sim.global_phase() & 1, 0); + } + } + } + assert_eq!(cases, 240); + } + + #[test] + fn direct_centered_branch_retained_finalizer_component_has_expected_shape() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_branch_retained_finalizer_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N); + assert_eq!(num_qubits as usize, 2 * N + N + 2); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, 4 * N - 2); + assert_eq!( + peak_phase, + "direct_centered_branch_retained_finalizer_google_abi" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_finalizer_subtract")); + } + + #[test] + fn direct_centered_branch_digit_clean_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_branch_digit_clean_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 3 * N); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, 3 * N - 2); + assert_eq!( + peak_phase, + "direct_centered_branch_digit_clean_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_digit_clean_addsub")); + } + + #[test] + fn direct_centered_remainder_abs_swap_transition_toy_is_exact() { + const W: usize = 4; + let mut b = B::new(); + let low_path = b.alloc_qubits(W); + let divisor = b.alloc_qubits(W); + let branch = b.alloc_qubit(); + let gated = b.alloc_qubits(W); + let carries = b.alloc_qubits(W - 1); + emit_direct_centered_remainder_abs_swap_transition( + &mut b, &low_path, &divisor, branch, &gated, &carries, + ); + + let nq = b.next_qubit as usize; + let nb = b.next_bit as usize; + let mut cases = Vec::new(); + for divisor_value in 1..(1u64 << W) { + for low_value in 0..divisor_value { + let branch_value = u64::from(2 * low_value >= divisor_value); + let next_divisor = if branch_value == 0 { + low_value + } else { + divisor_value - low_value + }; + cases.push((low_value, divisor_value, branch_value, next_divisor)); + } + } + + let mut seed = Shake128::default(); + seed.update(b"direct-centered-remainder-abs-swap-transition-toy"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(nq, nb, &mut xof); + for (batch, chunk) in cases.chunks(64).enumerate() { + sim.clear_for_shot(); + for (shot, &(low_value, divisor_value, branch_value, _next_divisor)) in + chunk.iter().enumerate() + { + set_reg(&mut sim, &low_path, low_value, shot); + set_reg(&mut sim, &divisor, divisor_value, shot); + if branch_value != 0 { + *sim.qubit_mut(branch) |= 1u64 << shot; + } + } + sim.apply(&b.ops); + let live = if chunk.len() == 64 { + u64::MAX + } else { + (1u64 << chunk.len()) - 1 + }; + assert_eq!(sim.global_phase() & live, 0, "phase dirty in batch {batch}"); + for &wire in &gated { + assert_eq!(sim.qubit(wire) & live, 0, "gated divisor dirty"); + } + for &wire in &carries { + assert_eq!(sim.qubit(wire) & live, 0, "borrowed carry dirty"); + } + for (shot, &(_low_value, divisor_value, branch_value, next_divisor)) in + chunk.iter().enumerate() + { + assert_eq!(get_reg(&sim, &low_path, shot), divisor_value); + assert_eq!(get_reg(&sim, &divisor, shot), next_divisor); + assert_eq!((sim.qubit(branch) >> shot) & 1, branch_value); + } + } + } + + #[test] + fn direct_centered_row_transition_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_row_transition_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + let hmr_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::Hmr)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 4 * N - 1); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, 2 * N - 1); + assert_eq!(hmr_ops, N - 1 + N); + assert_eq!(peak_phase, "direct_centered_row_transition_alloc_envelope"); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_row_transition_abs_add")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_row_transition_swap_next_state")); + } + + #[test] + fn direct_centered_branch_replay_finalizer_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_branch_replay_finalizer_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!( + num_bits as usize, + 2 * N + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * N + (N - 1) + ); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!( + toffoli_ops, + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * (3 * N - 2) + + (2 * DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS) + + (3 * N - 1) + ); + assert_eq!( + peak_phase, + "direct_centered_branch_replay_finalizer_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_replay_clear_nonfinal_history")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); + } + + #[test] + fn direct_centered_predicate_replay_finalizer_fit_materializes_full_tail_projection() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_predicate_replay_finalizer_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + let predicate_toggle_t = 2 * (N + 1); + let branch_digit_t = 3 * N - 2; + let finalizer_t = 3 * N - 1; + let expected_tail_t = DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS + * (2 * predicate_toggle_t + branch_digit_t) + + finalizer_t; + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!( + num_bits as usize, + 2 * N + DIRECT_CENTERED_EXPLICIT_BRANCH_HISTORY_BITS * N + (N - 1) + ); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, expected_tail_t); + assert_eq!(toffoli_ops, 210_665); + assert_eq!( + peak_phase, + "direct_centered_predicate_replay_finalizer_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_predicate_compare")); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); + } + + #[test] + fn direct_centered_sidecar_finalizer_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_sidecar_finalizer_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, 4 * N - 2); + assert_eq!( + peak_phase, + "direct_centered_sidecar_finalizer_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_finalizer_gate_divisor")); + } + + #[test] + fn direct_centered_sidecar_fast_finalizer_fit_stays_inside_round714_envelope() { + let (ops, phases, peak_qubits, peak_phase) = + build_direct_centered_sidecar_fast_finalizer_fit_bench_phase_resources(); + let (num_qubits, num_bits, num_registers, regs) = analyze_ops(ops.iter().copied()); + let toffoli_ops = ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(); + + assert_eq!(regs.len(), 4); + assert_eq!(num_registers, 4); + assert_eq!(num_bits as usize, 2 * N + N - 1); + assert_eq!( + num_qubits as usize, + 2 * N + DIRECT_CENTERED_BRANCH_SIDECAR_COMPONENT_SCRATCH_BITS + ); + assert_eq!(peak_qubits as usize, num_qubits as usize); + assert_eq!(toffoli_ops, 3 * N - 1); + assert_eq!( + peak_phase, + "direct_centered_sidecar_fast_finalizer_alloc_envelope" + ); + assert!(phases + .iter() + .any(|row| row.phase == "direct_centered_branch_retained_fast_finalizer_subtract")); + } +} diff --git a/src/point_add/rounds/dialog/compressed.rs b/src/point_add/rounds/dialog/compressed.rs index 2d23d88a..efacfa2a 100644 --- a/src/point_add/rounds/dialog/compressed.rs +++ b/src/point_add/rounds/dialog/compressed.rs @@ -1,6319 +1,6319 @@ - -use super::*; - -pub(crate) fn round763_dedup_enabled() -> bool { - - std::env::var("DIALOG_GCD_ROUND763_DEDUP").ok().as_deref() == Some("1") -} - -pub(crate) fn round763_compress_lever_enabled() -> bool { - - std::env::var("DIALOG_GCD_ROUND763_COMPRESS_LEVER") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn emit_dialog_gcd_round763_compressor(b: &mut B, block: &[QubitId]) { - assert_eq!(block.len(), 6); - if round763_compress_lever_enabled() { - b.cx(block[5], block[3]); - b.ccx(block[3], block[4], block[5]); - b.cx(block[1], block[4]); - b.cx(block[1], block[0]); - b.ccx(block[4], block[5], block[1]); - b.cx(block[0], block[2]); - b.ccx(block[2], block[5], block[0]); - b.ccx(block[0], block[1], block[5]); - return; - } - b.ccx(block[4], block[5], block[3]); - b.ccx(block[3], block[4], block[5]); - b.ccx(block[1], block[2], block[4]); - if round763_dedup_enabled() { - b.cx(block[1], block[0]); - } else { - b.ccx(block[1], block[3], block[4]); - b.cx(block[1], block[0]); - b.ccx(block[1], block[3], block[4]); - } - b.ccx(block[4], block[5], block[1]); - b.ccx(block[0], block[5], block[2]); - b.ccx(block[2], block[5], block[0]); - b.ccx(block[0], block[1], block[5]); -} - -pub(crate) fn emit_dialog_gcd_round763_compressor_inverse(b: &mut B, block: &[QubitId]) { - assert_eq!(block.len(), 6); - if round763_compress_lever_enabled() { - b.ccx(block[0], block[1], block[5]); - b.ccx(block[2], block[5], block[0]); - b.cx(block[0], block[2]); - b.ccx(block[4], block[5], block[1]); - b.cx(block[1], block[0]); - b.cx(block[1], block[4]); - b.ccx(block[3], block[4], block[5]); - b.cx(block[5], block[3]); - return; - } - b.ccx(block[0], block[1], block[5]); - b.ccx(block[2], block[5], block[0]); - b.ccx(block[0], block[5], block[2]); - b.ccx(block[4], block[5], block[1]); - if round763_dedup_enabled() { - b.cx(block[1], block[0]); - } else { - b.ccx(block[1], block[3], block[4]); - b.cx(block[1], block[0]); - b.ccx(block[1], block[3], block[4]); - } - b.ccx(block[1], block[2], block[4]); - b.ccx(block[3], block[4], block[5]); - b.ccx(block[4], block[5], block[3]); -} - -const DIALOG_GCD_K5_DATA_WIRES: [usize; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]; -const DIALOG_GCD_K5_HEAD11_DATA_WIRES: [usize; 11] = - [0, 1, 2, 4, 5, 6, 7, 8, 9, 11, 12]; -const DIALOG_GCD_K5_TAIL3_DATA_WIRES: [usize; 5] = [1, 10, 2, 3, 11]; -const DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES: [usize; 9] = [0, 1, 2, 3, 4, 5, 10, 11, 12]; -const DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES: [usize; 5] = [6, 7, 8, 9, 13]; -const DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT: u8 = 25; -const DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF: [&[u16]; 5] = [ - &[1, 2, 4, 32, 34, 64, 128], - &[4, 10, 16, 20, 24, 32, 64, 136, 256], - &[1, 6, 8, 16, 34, 128], - &[6, 32, 64], - &[4, 6, 8, 10, 32, 80, 128, 130, 256], -]; -const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_CODE_CONSTANT: u8 = 3; -const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_ENCODER_ANF: [&[u16]; 5] = [ - &[6, 8, 16, 20, 24, 64, 80, 128, 130, 136], - &[2, 6, 10, 16, 80, 128, 130], - &[2, 10, 16, 64, 80, 128, 130], - &[2, 4, 6, 8, 16, 64], - &[1, 2, 6, 10, 16, 20, 24, 64, 128, 136], -]; -const DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF: [&[u16]; 9] = [ - &[0, 6, 7, 9, 10, 17, 19, 22, 23, 24, 25, 29, 31], - &[0, 2, 7, 8, 10, 14, 16, 19, 24], - &[0, 16, 17, 19, 20, 24, 25, 26, 28], - &[0, 1, 2, 3, 4, 5, 6, 8, 11, 12, 15, 16, 18, 21, 26, 28], - &[0, 3, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 20, 21, 25], - &[26, 27], - &[2, 7, 10, 14, 16, 18, 22, 23, 24], - &[1, 6, 7, 8, 9, 10, 16, 18, 19, 20, 27, 28, 29, 30], - &[0, 9, 13, 22, 24, 28, 31], -]; -const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF: [&[u16]; 9] = [ - &[0, 1, 13, 17, 24, 25, 26], - &[0, 1, 2, 7, 10, 12, 13, 14, 31], - &[0, 6, 7, 8, 10, 12, 15], - &[4, 5, 7, 12, 22, 23, 27], - &[0, 1, 5, 12, 13, 27, 30], - &[], - &[1, 4, 7, 8, 9, 27], - &[0, 4, 8, 9, 16, 17, 20, 21, 30], - &[0], -]; -pub(crate) const DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT: [u16; 32] = [ - 0x124, 0x125, 0x12b, 0x129, 0x128, 0x12f, 0x12d, 0x14b, - 0x149, 0x158, 0x15b, 0x159, 0x147, 0x145, 0x12c, 0x16b, - 0x169, 0x15f, 0x15d, 0x178, 0x14f, 0x04b, 0x15c, 0x049, - 0x058, 0x14d, 0x148, 0x0c5, 0x0c7, 0x17b, 0x038, 0x02b, -]; -#[derive(Clone, Copy)] -enum DialogGcdK5FableGate { - X(usize), - Cx(usize, usize), - Ccx(usize, usize, usize), -} - -const DIALOG_GCD_K5_FABLE_GATES: &[DialogGcdK5FableGate] = &[ - DialogGcdK5FableGate::Cx(7, 6), - DialogGcdK5FableGate::Cx(6, 7), - DialogGcdK5FableGate::Cx(7, 6), - DialogGcdK5FableGate::Cx(8, 7), - DialogGcdK5FableGate::Cx(7, 8), - DialogGcdK5FableGate::Cx(9, 6), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::Ccx(10, 6, 9), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(9, 6), - DialogGcdK5FableGate::Cx(11, 10), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(5, 11), - DialogGcdK5FableGate::Ccx(6, 10, 5), - DialogGcdK5FableGate::Cx(5, 11), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::Cx(11, 10), - DialogGcdK5FableGate::Cx(10, 4), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::Cx(10, 11), - DialogGcdK5FableGate::Ccx(6, 4, 10), - DialogGcdK5FableGate::Cx(10, 11), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::Cx(10, 4), - DialogGcdK5FableGate::Cx(7, 4), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(5, 7), - DialogGcdK5FableGate::Cx(5, 9), - DialogGcdK5FableGate::Ccx(10, 4, 5), - DialogGcdK5FableGate::Cx(5, 9), - DialogGcdK5FableGate::Cx(5, 7), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(7, 4), - DialogGcdK5FableGate::Cx(10, 4), - DialogGcdK5FableGate::Cx(7, 5), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::Cx(9, 11), - DialogGcdK5FableGate::Ccx(4, 5, 9), - DialogGcdK5FableGate::Cx(9, 11), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::Cx(7, 5), - DialogGcdK5FableGate::Cx(10, 4), - DialogGcdK5FableGate::Cx(9, 8), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Ccx(10, 8, 9), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(9, 8), - DialogGcdK5FableGate::Cx(4, 8), - DialogGcdK5FableGate::Cx(11, 4), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::Cx(5, 11), - DialogGcdK5FableGate::Ccx(8, 4, 5), - DialogGcdK5FableGate::Cx(5, 11), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::Cx(11, 4), - DialogGcdK5FableGate::Cx(4, 8), - DialogGcdK5FableGate::Cx(7, 4), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::Ccx(5, 4, 7), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::Cx(7, 4), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::Ccx(4, 8, 6), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::X(11), - DialogGcdK5FableGate::Cx(4, 5), - DialogGcdK5FableGate::Cx(4, 8), - DialogGcdK5FableGate::Cx(4, 10), - DialogGcdK5FableGate::Ccx(6, 11, 4), - DialogGcdK5FableGate::Cx(4, 10), - DialogGcdK5FableGate::Cx(4, 8), - DialogGcdK5FableGate::Cx(4, 5), - DialogGcdK5FableGate::X(11), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::Cx(9, 5), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Ccx(10, 5, 9), - DialogGcdK5FableGate::X(10), - DialogGcdK5FableGate::Cx(9, 5), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::X(9), - DialogGcdK5FableGate::Ccx(7, 8, 13), - DialogGcdK5FableGate::Cx(4, 6), - DialogGcdK5FableGate::Ccx(13, 9, 4), - DialogGcdK5FableGate::Cx(4, 6), - DialogGcdK5FableGate::Ccx(7, 8, 13), - DialogGcdK5FableGate::X(9), - DialogGcdK5FableGate::X(8), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::X(11), - DialogGcdK5FableGate::Ccx(4, 6, 13), - DialogGcdK5FableGate::Ccx(13, 11, 10), - DialogGcdK5FableGate::Ccx(4, 6, 13), - DialogGcdK5FableGate::X(11), - DialogGcdK5FableGate::X(6), - DialogGcdK5FableGate::X(4), - DialogGcdK5FableGate::X(10), -]; - -fn dialog_gcd_k5_fable_wire(data: &[QubitId; 13], ancilla: QubitId, wire: usize) -> QubitId { - if wire == 13 { - ancilla - } else { - debug_assert!(wire < data.len()); - data[wire] - } -} - -fn dialog_gcd_k5_emit_fable_gate( - b: &mut B, - data: &[QubitId; 13], - ancilla: QubitId, - gate: DialogGcdK5FableGate, -) { - match gate { - DialogGcdK5FableGate::X(a) => b.x(dialog_gcd_k5_fable_wire(data, ancilla, a)), - DialogGcdK5FableGate::Cx(a, c) => b.cx( - dialog_gcd_k5_fable_wire(data, ancilla, a), - dialog_gcd_k5_fable_wire(data, ancilla, c), - ), - DialogGcdK5FableGate::Ccx(a, c, t) => b.ccx( - dialog_gcd_k5_fable_wire(data, ancilla, a), - dialog_gcd_k5_fable_wire(data, ancilla, c), - dialog_gcd_k5_fable_wire(data, ancilla, t), - ), - } -} - -fn dialog_gcd_k5_emit_fable_codec( - b: &mut B, - data: &[QubitId; 13], - ancilla: QubitId, - inverse: bool, -) { - if inverse { - for &gate in DIALOG_GCD_K5_FABLE_GATES.iter().rev() { - dialog_gcd_k5_emit_fable_gate(b, data, ancilla, gate); - } - } else { - for &gate in DIALOG_GCD_K5_FABLE_GATES { - dialog_gcd_k5_emit_fable_gate(b, data, ancilla, gate); - } - } -} - -fn emit_dialog_gcd_k5_clean_compressor(b: &mut B, data: &[QubitId; 13], ancilla: QubitId) { - dialog_gcd_k5_emit_fable_codec(b, data, ancilla, false); -} - -fn emit_dialog_gcd_k5_clean_compressor_inverse( - b: &mut B, - data: &[QubitId; 13], - ancilla: QubitId, -) { - dialog_gcd_k5_emit_fable_codec(b, data, ancilla, true); -} - -fn dialog_gcd_k5_head11_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 5 - && std::env::var("DIALOG_GCD_K5_HEAD11_CODEC") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tight_partial_block_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && std::env::var("DIALOG_GCD_K5_TIGHT_PARTIAL_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail3_fixed_last_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 3 - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 3 - && std::env::var("DIALOG_GCD_K5_TAIL3_FIXED_LAST") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail3_top32_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 3 - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 3 - && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_CODEC") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail3_top32_stream_apply_enabled() -> bool { - dialog_gcd_k5_tail3_top32_enabled() - && dialog_gcd_apply_replay_swap_host_enabled() - && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_STREAM_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail3_top32_split_slot_apply_enabled() -> bool { - dialog_gcd_k5_tail3_top32_stream_apply_enabled() - && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SPLIT_SLOT_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() -> bool { - dialog_gcd_k5_tail3_top32_split_slot_apply_enabled() - && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_FINAL_S2_CONST_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_head11_stream_pair_apply_enabled() -> bool { - dialog_gcd_k5_head11_enabled() - && dialog_gcd_apply_replay_swap_host_enabled() - && std::env::var("DIALOG_GCD_K5_HEAD11_STREAM_PAIR_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_head11_split_pair_shift_apply_enabled() -> bool { - dialog_gcd_k5_head11_stream_pair_apply_enabled() - && std::env::var("DIALOG_GCD_K5_HEAD11_SPLIT_PAIR_SHIFT_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled() -> bool { - dialog_gcd_k5_head11_split_pair_shift_apply_enabled() - && std::env::var("DIALOG_GCD_K5_HEAD11_PAIR01_S2_PERMUTE_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled() -> bool { - dialog_gcd_k5_head11_split_pair_shift_apply_enabled() - && std::env::var("DIALOG_GCD_K5_HEAD11_PAIR23_S2_BORROW_PAIR01_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_stream_pair_apply_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_apply_replay_swap_host_enabled() - && std::env::var("DIALOG_GCD_K5_STREAM_PAIR_APPLY") - .ok() - .as_deref() - == Some("1") -} - -fn emit_dialog_gcd_k5_head11_preconditioner(b: &mut B, data: &[QubitId; 13]) { - b.x(data[0]); - b.ccx(data[0], data[1], data[3]); - b.ccx(data[2], data[3], data[0]); - b.cx(data[0], data[3]); -} - -fn emit_dialog_gcd_k5_head11_preconditioner_inverse( - b: &mut B, - data: &[QubitId; 13], -) { - b.cx(data[0], data[3]); - b.ccx(data[2], data[3], data[0]); - b.ccx(data[0], data[1], data[3]); - b.x(data[0]); -} - -fn emit_dialog_gcd_k5_pair_encoder(b: &mut B, pair_raw: &[QubitId; 6]) { - let core = [pair_raw[0], pair_raw[1], pair_raw[4], pair_raw[2], pair_raw[3]]; - b.cx(core[1], core[2]); - b.cx(core[0], core[4]); - b.x(core[3]); - b.ccx(core[2], core[3], core[1]); - b.cx(core[3], core[4]); - b.ccx(core[3], core[4], core[0]); - b.cx(core[2], core[4]); - b.cx(core[0], core[3]); - b.cx(core[3], core[2]); - b.cx(core[3], core[4]); - b.ccx(core[1], core[3], core[0]); - b.cx(core[1], core[0]); - b.cx(core[3], core[0]); -} - -fn emit_dialog_gcd_k5_pair_encoder_inverse(b: &mut B, pair_raw: &[QubitId; 6]) { - let core = [pair_raw[0], pair_raw[1], pair_raw[4], pair_raw[2], pair_raw[3]]; - b.cx(core[3], core[0]); - b.cx(core[1], core[0]); - b.ccx(core[1], core[3], core[0]); - b.cx(core[3], core[4]); - b.cx(core[3], core[2]); - b.cx(core[0], core[3]); - b.cx(core[2], core[4]); - b.ccx(core[3], core[4], core[0]); - b.cx(core[3], core[4]); - b.ccx(core[2], core[3], core[1]); - b.x(core[3]); - b.cx(core[0], core[4]); - b.cx(core[1], core[2]); -} - -fn dialog_gcd_raw_s2(raw_block: &[QubitId], slot: usize) -> QubitId { - raw_block[2 * dialog_gcd_sidecar_group_size() + slot] -} - -fn dialog_gcd_block_raw_s2( - raw_block: &[QubitId], - block_steps: usize, - slot: usize, -) -> QubitId { - if dialog_gcd_k5_tail6_graph9_enabled() && block_steps == 6 { - assert!(slot < DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS); - raw_block[2 * DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS + slot] - } else if dialog_gcd_k5_tail6_graph_enabled() && block_steps == 6 { - assert!(slot < DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS); - raw_block[2 * DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS + slot] - } else if dialog_gcd_k5_tail7_enabled() && block_steps == 7 { - assert!(slot < DIALOG_GCD_K5_TAIL7_STORED_STEPS); - raw_block[2 * DIALOG_GCD_K5_TAIL7_STORED_STEPS + slot] - } else { - dialog_gcd_raw_s2(raw_block, slot) - } -} - -fn dialog_gcd_k5_pair01(raw_block: &[QubitId]) -> [QubitId; 6] { - [ - raw_block[0], - raw_block[1], - raw_block[2], - raw_block[3], - dialog_gcd_raw_s2(raw_block, 0), - dialog_gcd_raw_s2(raw_block, 1), - ] -} - -fn dialog_gcd_k5_pair23(raw_block: &[QubitId]) -> [QubitId; 6] { - [ - raw_block[4], - raw_block[5], - raw_block[6], - raw_block[7], - dialog_gcd_raw_s2(raw_block, 2), - dialog_gcd_raw_s2(raw_block, 3), - ] -} - -fn dialog_gcd_k5_data_from_raw(raw_block: &[QubitId]) -> [QubitId; 13] { - [ - raw_block[1], - dialog_gcd_raw_s2(raw_block, 0), - raw_block[2], - raw_block[3], - dialog_gcd_raw_s2(raw_block, 1), - raw_block[5], - dialog_gcd_raw_s2(raw_block, 2), - raw_block[6], - raw_block[7], - dialog_gcd_raw_s2(raw_block, 3), - raw_block[8], - raw_block[9], - dialog_gcd_raw_s2(raw_block, 4), - ] -} - -fn dialog_gcd_k5_partial_raw_clean_scratch( - raw_block: &[QubitId], - steps: usize, -) -> Vec { - if !dialog_gcd_k5_clean_block_enabled() - || dialog_gcd_k5_tail_pair1_enabled() - || steps >= dialog_gcd_sidecar_group_size() - { - return Vec::new(); - } - assert_eq!(raw_block.len(), 15); - assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); - let branch_end = 2 * dialog_gcd_sidecar_group_size(); - let fixed_tail_branch = if dialog_gcd_k5_tail3_fixed_last_enabled() && steps == 3 { - &raw_block[2 * (steps - 1)..2 * steps] - } else { - &[][..] - }; - fixed_tail_branch - .iter() - .chain(raw_block[2 * steps..branch_end].iter()) - .chain(raw_block[branch_end + steps..].iter()) - .copied() - .collect() -} - -fn dialog_gcd_k5_partial_raw_release_bits() -> usize { - std::env::var("DIALOG_GCD_K5_PARTIAL_RAW_RELEASE") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0) -} - -fn dialog_gcd_k5_transfer_survivors( - b: &mut B, - compressed_block: &[QubitId], - data: &[QubitId; 13], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 12); - for (i, &wire) in DIALOG_GCD_K5_DATA_WIRES.iter().enumerate() { - if swap_host { - b.swap(compressed_block[i], data[wire]); - } else { - b.cx(compressed_block[i], data[wire]); - } - } -} - -fn dialog_gcd_k5_head11_transfer_survivors( - b: &mut B, - compressed_block: &[QubitId], - data: &[QubitId; 13], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); - for (i, &wire) in DIALOG_GCD_K5_HEAD11_DATA_WIRES.iter().enumerate() { - if swap_host { - b.swap(compressed_block[i], data[wire]); - } else { - b.cx(compressed_block[i], data[wire]); - } - } -} - -fn dialog_gcd_k5_head11_compress_raw_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); - assert_eq!(raw_block.len(), 15); - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); - let data = dialog_gcd_k5_data_from_raw(raw_block); - emit_dialog_gcd_k5_head11_preconditioner(b, &data); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); - b.free(ancilla); - dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); -} - -fn dialog_gcd_k5_head11_decompress_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); - b.free(ancilla); - emit_dialog_gcd_k5_head11_preconditioner_inverse(b, &data); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); -} - -fn dialog_gcd_k5_compress_data_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 12); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); - b.free(ancilla); - dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); -} - -fn dialog_gcd_k5_decompress_block_to_data( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 12); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); - b.free(ancilla); -} - -fn dialog_gcd_k5_stream_pairs_start(b: &mut B, raw_block: &[QubitId]) { - assert_eq!(raw_block.len(), 15); - - b.free(raw_block[0]); - b.free(raw_block[4]); -} - -fn dialog_gcd_k5_stream_pairs_before_slot( - b: &mut B, - raw_block: &[QubitId], - slot: usize, -) { - match slot { - 3 => { - b.reacquire(raw_block[4]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); - } - 1 => { - b.reacquire(raw_block[0]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); - } - _ => {} - } -} - -fn dialog_gcd_k5_stream_pairs_after_slot_forward( - b: &mut B, - raw_block: &[QubitId], - slot: usize, -) { - match slot { - 2 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); - b.free(raw_block[4]); - } - 0 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - b.free(raw_block[0]); - } - _ => {} - } -} - -fn dialog_gcd_k5_stream_pairs_before_slot_reverse( - b: &mut B, - raw_block: &[QubitId], - slot: usize, -) { - match slot { - 0 => { - b.reacquire(raw_block[0]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); - } - 2 => { - b.reacquire(raw_block[4]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); - } - _ => {} - } -} - -fn dialog_gcd_k5_stream_pairs_after_slot_reverse( - b: &mut B, - raw_block: &[QubitId], - slot: usize, -) { - match slot { - 1 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - b.free(raw_block[0]); - } - 3 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); - b.free(raw_block[4]); - } - _ => {} - } -} - -fn dialog_gcd_k5_stream_pairs_finish(b: &mut B, raw_block: &[QubitId]) { - b.reacquire(raw_block[0]); - b.reacquire(raw_block[4]); -} - -fn dialog_gcd_k5_head11_pair_for_slot(slot: usize) -> usize { - assert!(slot < 4); - slot / 2 -} - -fn dialog_gcd_k5_head11_open_pair_for_slot(b: &mut B, raw_block: &[QubitId], slot: usize) { - match dialog_gcd_k5_head11_pair_for_slot(slot) { - 0 => { - b.reacquire(raw_block[0]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); - } - 1 => { - b.reacquire(raw_block[4]); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); - } - _ => unreachable!(), - } -} - -fn dialog_gcd_k5_head11_close_pair_for_slot(b: &mut B, raw_block: &[QubitId], slot: usize) { - match dialog_gcd_k5_head11_pair_for_slot(slot) { - 0 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - b.free(raw_block[0]); - } - 1 => { - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); - b.free(raw_block[4]); - } - _ => unreachable!(), - } -} - -fn dialog_gcd_k5_head11_pair01_expose_s2(b: &mut B, raw_block: &[QubitId]) { - let w = [ - raw_block[1], - raw_block[10], - raw_block[2], - raw_block[3], - raw_block[11], - ]; - b.cx(w[0], w[2]); - b.cx(w[1], w[0]); - b.ccx(w[0], w[2], w[1]); -} - -fn dialog_gcd_k5_head11_pair01_unexpose_s2(b: &mut B, raw_block: &[QubitId]) { - let w = [ - raw_block[1], - raw_block[10], - raw_block[2], - raw_block[3], - raw_block[11], - ]; - b.ccx(w[0], w[2], w[1]); - b.cx(w[1], w[0]); - b.cx(w[0], w[2]); -} - -fn dialog_gcd_k5_head11_pair01_zero_lane(b: &mut B, raw_block: &[QubitId]) { - let w = [ - raw_block[1], - raw_block[10], - raw_block[2], - raw_block[3], - raw_block[11], - ]; - b.x(w[0]); - b.x(w[2]); - b.ccx(w[0], w[1], w[3]); - b.ccx(w[2], w[3], w[0]); -} - -fn dialog_gcd_k5_head11_pair01_unzero_lane(b: &mut B, raw_block: &[QubitId]) { - let w = [ - raw_block[1], - raw_block[10], - raw_block[2], - raw_block[3], - raw_block[11], - ]; - b.ccx(w[2], w[3], w[0]); - b.ccx(w[0], w[1], w[3]); - b.x(w[2]); - b.x(w[0]); -} - -const DIALOG_GCD_K5_HEAD11_PAIR23_S2_ANF: &[u16] = &[1, 2, 3, 4, 7, 9, 11, 13, 15]; - -fn dialog_gcd_k5_head11_toggle_pair23_s2_into( - b: &mut B, - raw_block: &[QubitId], - target: QubitId, -) { - let code = [ - raw_block[5], - raw_block[12], - raw_block[6], - raw_block[7], - raw_block[13], - ]; - dialog_gcd_toggle_anf_with_dirty( - b, - &code, - target, - raw_block, - DIALOG_GCD_K5_HEAD11_PAIR23_S2_ANF, - ); -} - -fn dialog_gcd_k5_head11_compress_data_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!( - compressed_block.len(), - DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - ); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - emit_dialog_gcd_k5_head11_preconditioner(b, &data); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); - b.free(ancilla); - dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); -} - -fn dialog_gcd_k5_head11_decompress_block_to_data( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!( - compressed_block.len(), - DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - ); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); - b.free(ancilla); - emit_dialog_gcd_k5_head11_preconditioner_inverse(b, &data); -} - -fn dialog_gcd_k5_head11_pair_encode_word(bits: &mut [bool; 15], slots: [usize; 2]) { - let wire = [ - 3 * slots[0], - 3 * slots[0] + 1, - 3 * slots[0] + 2, - 3 * slots[1], - 3 * slots[1] + 1, - ]; - bits[wire[2]] ^= bits[wire[1]]; - bits[wire[4]] ^= bits[wire[0]]; - bits[wire[3]] ^= true; - bits[wire[1]] ^= bits[wire[2]] && bits[wire[3]]; - bits[wire[4]] ^= bits[wire[3]]; - bits[wire[0]] ^= bits[wire[3]] && bits[wire[4]]; - bits[wire[4]] ^= bits[wire[2]]; - bits[wire[3]] ^= bits[wire[0]]; - bits[wire[2]] ^= bits[wire[3]]; - bits[wire[4]] ^= bits[wire[3]]; - bits[wire[0]] ^= bits[wire[1]] && bits[wire[3]]; - bits[wire[0]] ^= bits[wire[1]]; - bits[wire[0]] ^= bits[wire[3]]; -} - -fn dialog_gcd_k5_head11_code_word(pattern: u16) -> Option { - let mut raw = std::array::from_fn::<_, 15, _>(|bit| (pattern >> bit) & 1 != 0); - dialog_gcd_k5_head11_pair_encode_word(&mut raw, [0, 1]); - dialog_gcd_k5_head11_pair_encode_word(&mut raw, [2, 3]); - if raw[0] || raw[6] { - return None; - } - - const RAW_DATA_INDICES: [usize; 13] = - [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14]; - let mut wires = [false; 14]; - for (index, raw_index) in RAW_DATA_INDICES.into_iter().enumerate() { - wires[index] = raw[raw_index]; - } - wires[0] ^= true; - wires[3] ^= wires[0] && wires[1]; - wires[0] ^= wires[2] && wires[3]; - wires[3] ^= wires[0]; - for &gate in DIALOG_GCD_K5_FABLE_GATES { - match gate { - DialogGcdK5FableGate::X(a) => wires[a] ^= true, - DialogGcdK5FableGate::Cx(a, c) => wires[c] ^= wires[a], - DialogGcdK5FableGate::Ccx(a, c, t) => wires[t] ^= wires[a] && wires[c], - } - } - if wires[3] || wires[10] || wires[13] { - return None; - } - Some( - DIALOG_GCD_K5_HEAD11_DATA_WIRES - .iter() - .enumerate() - .fold(0u16, |code, (index, &wire)| { - code | (u16::from(wires[wire]) << index) - }), - ) -} - -pub(crate) fn dialog_gcd_k5_head11_supports(pattern: u16) -> bool { - dialog_gcd_k5_head11_code_word(pattern).is_some() -} - -pub(crate) fn dialog_gcd_k5_head11_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let supported = (0u16..1 << 15) - .filter(|&pattern| dialog_gcd_k5_head11_supports(pattern)) - .collect::>(); - if supported.len() != 1 << DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() { - return Err(format!( - "expected 2048 supported head words, got {}", - supported.len() - )); - } - let mut seen_codes = vec![false; 1 << DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()]; - for &pattern in &supported { - let code = dialog_gcd_k5_head11_code_word(pattern).expect("filtered support"); - if std::mem::replace(&mut seen_codes[code as usize], true) { - return Err(format!("duplicate head code 0x{code:03x}")); - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_head11_decompress_block_to_raw(&mut b, &code, &raw, true); - } else { - dialog_gcd_k5_head11_compress_raw_to_block(&mut b, &code, &raw, true); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - let forward_codec = build_codec(false); - let reverse_codec = build_codec(true); - - for batch_start in (0..supported.len()).step_by(64) { - let patterns = &supported[batch_start..batch_start + 64]; - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()]; - for (shot, &pattern) in patterns.iter().enumerate() { - let shot_bit = 1u64 << shot; - for slot in 0..5 { - if (pattern >> (3 * slot)) & 1 != 0 { - raw_masks[2 * slot] |= shot_bit; - } - if (pattern >> (3 * slot + 1)) & 1 != 0 { - raw_masks[2 * slot + 1] |= shot_bit; - } - if (pattern >> (3 * slot + 2)) & 1 != 0 { - raw_masks[10 + slot] |= shot_bit; - } - } - let code = dialog_gcd_k5_head11_code_word(pattern).expect("supported pattern"); - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let run = |decompress: bool| { - let (ops, code, raw, num_qubits, num_bits) = - if decompress { &reverse_codec } else { &forward_codec }; - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-head11-codec-selftest"); - seed.update(&(batch_start as u64).to_le_bytes()); - seed.update(&[u8::from(decompress)]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(*num_qubits, *num_bits, &mut xof); - sim.clear_for_shot(); - let source = if decompress { - &code_masks[..] - } else { - &raw_masks[..] - }; - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let (forward_code, forward_raw, forward_phase) = run(false); - if forward_phase != 0 { - return Err(format!( - "forward phase garbage in batch {batch_start}: 0x{forward_phase:x}" - )); - } - if forward_code != code_masks { - return Err(format!( - "forward code mismatch in batch {batch_start}: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw.iter().any(|&mask| mask != 0) { - return Err(format!( - "forward raw garbage in batch {batch_start}: {forward_raw:x?}" - )); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true); - if reverse_phase != 0 { - return Err(format!( - "reverse phase garbage in batch {batch_start}: 0x{reverse_phase:x}" - )); - } - if reverse_code.iter().any(|&mask| mask != 0) { - return Err(format!( - "reverse code garbage in batch {batch_start}: {reverse_code:x?}" - )); - } - if reverse_raw != raw_masks { - return Err(format!( - "reverse raw mismatch in batch {batch_start}: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - } - Ok(()) -} - -fn dialog_gcd_k5_compress_raw_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 12); - assert_eq!(raw_block.len(), 15); - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); - let data = dialog_gcd_k5_data_from_raw(raw_block); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); - b.free(ancilla); - dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); -} - -fn dialog_gcd_k5_decompress_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 12); - assert_eq!(raw_block.len(), 15); - let data = dialog_gcd_k5_data_from_raw(raw_block); - dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); - let ancilla = b.alloc_qubit(); - emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); - b.free(ancilla); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); -} - -fn dialog_gcd_k5_compress_partial_raw_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, - swap_host: bool, -) { - assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); - assert_eq!(raw_block.len(), 15); - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - assert!( - compressed_block.len() == dialog_gcd_block_bits() - || compressed_block.len() == base_bits + steps - ); - let raw_base = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; - emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); - for i in 0..base_bits { - if swap_host { b.swap(compressed_block[i], raw_block[i]); } else { b.cx(compressed_block[i], raw_block[i]); } - } - for slot in 0..steps { - let s2 = dialog_gcd_raw_s2(raw_block, slot); - if swap_host { b.swap(compressed_block[base_bits + slot], s2); } else { b.cx(compressed_block[base_bits + slot], s2); } - } -} - -fn dialog_gcd_k5_decompress_partial_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, - swap_host: bool, -) { - assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); - assert_eq!(raw_block.len(), 15); - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - assert!( - compressed_block.len() == dialog_gcd_block_bits() - || compressed_block.len() == base_bits + steps - ); - let raw_base = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; - for i in 0..base_bits { - if swap_host { b.swap(compressed_block[i], raw_block[i]); } else { b.cx(compressed_block[i], raw_block[i]); } - } - emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); - for slot in 0..steps { - let s2 = dialog_gcd_raw_s2(raw_block, slot); - if swap_host { b.swap(compressed_block[base_bits + slot], s2); } else { b.cx(compressed_block[base_bits + slot], s2); } - } -} - -fn dialog_gcd_k5_tail_pair1_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && !dialog_gcd_k5_tail7_enabled() - && !dialog_gcd_k5_tail6_graph_enabled() - && !dialog_gcd_k5_tail6_graph9_enabled() - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 2 - && std::env::var("DIALOG_GCD_K5_TAIL_PAIR1") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail6_graph9_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 6 - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 1 - && std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_CODEC") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_release_decoded_block_bits() -> usize { - if !dialog_gcd_k5_clean_block_enabled() || !dialog_gcd_apply_replay_swap_host_enabled() { - return 0; - } - std::env::var("DIALOG_GCD_K5_RELEASE_DECODED_BLOCK_BITS") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0) -} - -fn dialog_gcd_k5_release_decoded_tail_bits() -> usize { - std::env::var("DIALOG_GCD_K5_RELEASE_DECODED_TAIL_BITS") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or_else(dialog_gcd_k5_release_decoded_block_bits) -} - -fn dialog_gcd_k5_release_scale_bits() -> usize { - std::env::var("DIALOG_GCD_K5_RELEASE_SCALE_BITS") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0) -} - -fn dialog_gcd_k5_tail6_graph_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 6 - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 1 - && std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_CODEC") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_tail7_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && dialog_gcd_active_iterations() >= 7 - && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 2 - && std::env::var("DIALOG_GCD_K5_TAIL7_CODEC") - .ok() - .as_deref() - == Some("1") -} - -const DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS: usize = 3; -const DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS: usize = 6; -const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS] = - [0x0d4, 0x0d1, 0x040, 0x05f, 0x00d, 0x081]; -const DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT: u8 = 0x26; -const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CONSTANT: u16 = 0x1dc; -const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_DECODE_MASKS: [u8; 9] = - [0x00, 0x3a, 0x03, 0x13, 0x26, 0x00, 0x04, 0x20, 0x00]; -const DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK: u16 = 0x085; -const DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_ANF: &[u16] = &[0x00, 0x02, 0x04, 0x05, 0x32]; -pub(crate) const DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT: [u32; 32] = [ - 0x24924, 0x24925, 0x24928, 0x24929, 0x2492b, 0x2492c, 0x2492d, 0x2492f, - 0x24944, 0x24945, 0x24947, 0x24948, 0x24949, 0x2494b, 0x2494d, 0x2494f, - 0x24958, 0x24959, 0x2495b, 0x2495c, 0x2495d, 0x2495f, 0x24965, 0x24967, - 0x24968, 0x24969, 0x2496b, 0x24978, 0x24979, 0x2497b, 0x2497d, 0x2497f, -]; - -const DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS: usize = 4; -const DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS: usize = 9; -const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS] = - [0x9dc, 0xb6a, 0x717, 0x404, 0xe92, 0x00c, 0xa17, 0x7af, 0xf44]; -const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT: u16 = 0xc6c; -const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS: [u16; 12] = [ - 0x058, 0x000, 0x131, 0x111, 0x18e, 0x01b, 0x0d2, 0x000, 0x17d, 0x0a7, - 0x139, 0x000, -]; -const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK: u16 = 0x71e; -const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT: usize = 1; -const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF: &[u16] = &[ - 0x000, 0x002, 0x003, 0x006, 0x008, 0x00a, 0x011, 0x012, 0x020, 0x021, - 0x024, 0x040, 0x041, 0x042, 0x048, 0x060, 0x080, 0x081, 0x088, 0x0a0, - 0x100, 0x02c, 0x034, 0x064, 0x0a2, 0x0a4, -]; -pub(crate) const DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT: [u32; 75] = [ - 0x24924, 0x24925, 0x24928, 0x24929, 0x2492b, 0x2492c, 0x2492d, 0x2492f, - 0x24944, 0x24945, 0x24947, 0x24948, 0x24949, 0x2494b, 0x2494d, 0x2494f, - 0x24958, 0x24959, 0x2495b, 0x2495c, 0x2495d, 0x2495f, 0x24965, 0x24967, - 0x24968, 0x24969, 0x2496b, 0x24978, 0x24979, 0x2497b, 0x2497d, 0x2497f, - 0x24a27, 0x24a29, 0x24a2b, 0x24a2d, 0x24a2f, 0x24a38, 0x24a3f, 0x24a45, - 0x24a47, 0x24a49, 0x24a4b, 0x24a4d, 0x24a58, 0x24a59, 0x24a5b, 0x24a5f, - 0x24a65, 0x24a68, 0x24a6b, 0x24a78, 0x24a7c, 0x24ac5, 0x24ac8, 0x24ac9, - 0x24acb, 0x24acd, 0x24add, 0x24ae9, 0x24af8, 0x24af9, 0x24b29, 0x24b3c, - 0x24b3d, 0x24b45, 0x24b49, 0x24b4b, 0x24b5f, 0x24b79, 0x24bc5, 0x24bc9, - 0x24bd8, 0x24be4, 0x24bf9, -]; - -const DIALOG_GCD_K5_TAIL7_STORED_STEPS: usize = 4; -const DIALOG_GCD_K5_TAIL7_CODE_BITS: usize = 5; -const DIALOG_GCD_K5_TAIL7_PACKED_CODE_MASKS: [u32; DIALOG_GCD_K5_TAIL7_CODE_BITS] = - [0x8a0, 0x204, 0x80011, 0x38, 0x100402]; -const DIALOG_GCD_K5_TAIL7_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL7_CODE_BITS] = - [0x0a20, 0x0140, 0x0009, 0x020c, 0x0082]; -const DIALOG_GCD_K5_TAIL7_CODE_CONSTANT: u8 = 1 << 4; -pub(crate) const DIALOG_GCD_K5_TAIL7_SUPPORT: [u32; 20] = [ - 0x124924, 0x124925, 0x124929, 0x12492b, 0x124928, 0x12492d, 0x12492f, - 0x12494b, 0x124947, 0x124945, 0x12492c, 0x124958, 0x124949, 0x12495b, - 0x124959, 0x124967, 0x12495d, 0x124a4b, 0x12497f, 0x124979, -]; -const DIALOG_GCD_K5_TAIL7_RAW_ANF: [&[u16]; 12] = [ - &[1, 4, 7, 10, 12, 24, 28], - &[0, 16], - &[0, 7, 8, 10, 12, 24, 28], - &[1, 7, 10, 12, 24, 28], - &[1, 8, 9, 26], - &[], - &[11], - &[], - &[2, 11], - &[0, 1], - &[0, 11], - &[0], -]; - -fn dialog_gcd_toggle_mcx_with_dirty( - b: &mut B, - controls: &[QubitId], - dirty: &[QubitId], - target: QubitId, -) { - assert!(!controls.contains(&target)); - assert!(controls - .iter() - .enumerate() - .all(|(index, q)| !controls[..index].contains(q))); - match controls.len() { - 0 => b.x(target), - 1 => b.cx(controls[0], target), - 2 => b.ccx(controls[0], controls[1], target), - count => { - assert!(dirty.len() >= count - 2); - let bridge = dirty[0]; - assert_ne!(bridge, target); - assert!(!controls.contains(&bridge)); - dialog_gcd_toggle_mcx_with_dirty( - b, - &controls[..count - 1], - &dirty[1..], - bridge, - ); - b.ccx(bridge, controls[count - 1], target); - dialog_gcd_toggle_mcx_with_dirty( - b, - &controls[..count - 1], - &dirty[1..], - bridge, - ); - b.ccx(bridge, controls[count - 1], target); - } - } -} - -fn dialog_gcd_toggle_anf_with_dirty( - b: &mut B, - code: &[QubitId], - target: QubitId, - dirty_pool: &[QubitId], - terms: &[u16], -) { - assert!(code.len() <= u16::BITS as usize); - assert!(!code.contains(&target)); - for &mask in terms { - let controls = code - .iter() - .enumerate() - .filter_map(|(index, &q)| ((mask >> index) & 1 != 0).then_some(q)) - .collect::>(); - let dirty = dirty_pool - .iter() - .copied() - .filter(|q| *q != target && !controls.contains(q)) - .collect::>(); - dialog_gcd_toggle_mcx_with_dirty(b, &controls, &dirty, target); - } -} - -fn dialog_gcd_k5_tail6_graph9_toggle_code_from_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (code_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS - .iter() - .enumerate() - { - for raw_bit in 0..12 { - if (mask >> raw_bit) & 1 != 0 { - b.cx(raw_block[raw_bit], code[code_index]); - } - } - } -} - -fn dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (raw_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS - .iter() - .enumerate() - { - if (DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT >> raw_index) & 1 != 0 { - b.x(raw_block[raw_index]); - } - for code_bit in 0..DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS { - if (mask >> code_bit) & 1 != 0 { - b.cx(code[code_bit], raw_block[raw_index]); - } - } - } -} - -fn dialog_gcd_k5_tail6_graph9_toggle_selector_fanout( - b: &mut B, - raw_block: &[QubitId], -) { - assert_eq!(raw_block.len(), 15); - assert_ne!( - (DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK - >> DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT) - & 1, - 0 - ); - let pivot = raw_block[DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT]; - for raw_index in 0..12 { - if raw_index != DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT - && (DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK >> raw_index) & 1 != 0 - { - b.cx(pivot, raw_block[raw_index]); - } - } -} - -fn dialog_gcd_k5_tail6_graph9_toggle_selector( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_toggle_anf_with_dirty( - b, - code, - raw_block[DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT], - raw_block, - DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF, - ); -} - -fn dialog_gcd_k5_tail6_graph9_compress_raw_to_block( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail6_graph9_toggle_code_from_raw(b, code, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code(b, code, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_selector_fanout(b, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_selector(b, code, raw_block); -} - -fn dialog_gcd_k5_tail6_graph9_decompress_block_to_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail6_graph9_toggle_selector(b, code, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_selector_fanout(b, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code(b, code, raw_block); - dialog_gcd_k5_tail6_graph9_toggle_code_from_raw(b, code, raw_block); -} - -fn dialog_gcd_k5_tail6_graph9_raw_word(pattern: u32) -> u16 { - let mut raw_word = 0u16; - for slot in 0..DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS { - let digit = ((pattern >> (3 * slot)) & 7) as u16; - raw_word |= (digit & 1) << (2 * slot); - raw_word |= ((digit >> 1) & 1) << (2 * slot + 1); - raw_word |= ((digit >> 2) & 1) - << (2 * DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS + slot); - } - raw_word -} - -fn dialog_gcd_k5_tail6_graph9_code_word(raw_word: u16) -> u16 { - DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS - .iter() - .enumerate() - .fold(0u16, |code, (index, &mask)| { - code ^ ((((raw_word & mask).count_ones() & 1) as u16) << index) - }) -} - -fn dialog_gcd_k5_tail6_graph9_selector_word(code: u16) -> u16 { - DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF - .iter() - .fold(0u16, |selector, &term| { - selector ^ u16::from(code & term == term) - }) -} - -fn dialog_gcd_k5_tail6_graph9_decode_word(code: u16) -> u16 { - let selector = dialog_gcd_k5_tail6_graph9_selector_word(code); - DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS - .iter() - .enumerate() - .fold(DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT, |raw, (index, &mask)| { - let bit = ((code & mask).count_ones() & 1) as u16 - ^ (selector - & ((DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK >> index) & 1)); - raw ^ (bit << index) - }) -} - -pub(crate) fn dialog_gcd_k5_tail6_graph9_supports(pattern: u32) -> bool { - if pattern >> 12 != 0x24 { - return false; - } - let raw = dialog_gcd_k5_tail6_graph9_raw_word(pattern); - let code = dialog_gcd_k5_tail6_graph9_code_word(raw); - dialog_gcd_k5_tail6_graph9_decode_word(code) == raw -} - -pub(crate) fn dialog_gcd_k5_tail6_graph9_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - for batch_start in (0..DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT.len()).step_by(64) { - let patterns = &DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT - [batch_start..(batch_start + 64).min(DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT.len())]; - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS]; - for (shot, &pattern) in patterns.iter().enumerate() { - if !dialog_gcd_k5_tail6_graph9_supports(pattern) { - return Err(format!("support pattern 0x{pattern:x} fails graph relation")); - } - let shot_bit = 1u64 << shot; - let raw_word = dialog_gcd_k5_tail6_graph9_raw_word(pattern); - for raw_bit in 0..12 { - if (raw_word >> raw_bit) & 1 != 0 { - raw_masks[raw_bit] |= shot_bit; - } - } - let code = dialog_gcd_k5_tail6_graph9_code_word(raw_word); - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_tail6_graph9_decompress_block_to_raw(&mut b, &code, &raw); - } else { - dialog_gcd_k5_tail6_graph9_compress_raw_to_block(&mut b, &code, &raw); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |decompress: bool| { - let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail6-graph9-codec-selftest"); - seed.update(&(batch_start as u64).to_le_bytes()); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let active_mask = if patterns.len() == 64 { - u64::MAX - } else { - (1u64 << patterns.len()) - 1 - }; - let (forward_code, forward_raw, forward_phase) = run(false); - if forward_phase & active_mask != 0 { - return Err(format!( - "forward phase garbage in batch {batch_start}: 0x{:x}", - forward_phase & active_mask - )); - } - if forward_code - .iter() - .zip(code_masks.iter()) - .any(|(&got, &want)| (got ^ want) & active_mask != 0) - { - return Err(format!( - "forward code mismatch in batch {batch_start}: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw - .iter() - .any(|&mask| mask & active_mask != 0) - { - return Err(format!( - "forward raw garbage in batch {batch_start}: {forward_raw:x?}" - )); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true); - if reverse_phase & active_mask != 0 { - return Err(format!( - "reverse phase garbage in batch {batch_start}: 0x{:x}", - reverse_phase & active_mask - )); - } - if reverse_code - .iter() - .any(|&mask| mask & active_mask != 0) - { - return Err(format!( - "reverse code garbage in batch {batch_start}: {reverse_code:x?}" - )); - } - if reverse_raw - .iter() - .zip(raw_masks.iter()) - .any(|(&got, &want)| (got ^ want) & active_mask != 0) - { - return Err(format!( - "reverse raw mismatch in batch {batch_start}: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - } - Ok(()) -} - -fn dialog_gcd_k5_tail6_graph_toggle_code_from_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (code_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS - .iter() - .enumerate() - { - for raw_bit in 0..9 { - if (mask >> raw_bit) & 1 != 0 { - b.cx(raw_block[raw_bit], code[code_index]); - } - } - if (DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT >> code_index) & 1 != 0 { - b.x(code[code_index]); - } - } -} - -fn dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (raw_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_DECODE_MASKS - .iter() - .enumerate() - { - if (DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CONSTANT >> raw_index) & 1 != 0 { - b.x(raw_block[raw_index]); - } - for code_bit in 0..DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS { - if (mask >> code_bit) & 1 != 0 { - b.cx(code[code_bit], raw_block[raw_index]); - } - } - } -} - -fn dialog_gcd_k5_tail6_graph_toggle_selector_fanout( - b: &mut B, - raw_block: &[QubitId], -) { - assert_eq!(raw_block.len(), 15); - let pivot = raw_block[0]; - assert_eq!(DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK & 1, 1); - for raw_index in 1..9 { - if (DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK >> raw_index) & 1 != 0 { - b.cx(pivot, raw_block[raw_index]); - } - } -} - -fn dialog_gcd_k5_tail6_graph_toggle_selector( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_toggle_anf_with_dirty( - b, - code, - raw_block[0], - raw_block, - DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_ANF, - ); -} - -fn dialog_gcd_k5_tail6_graph_compress_raw_to_block( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail6_graph_toggle_code_from_raw(b, code, raw_block); - dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code(b, code, raw_block); - dialog_gcd_k5_tail6_graph_toggle_selector_fanout(b, raw_block); - dialog_gcd_k5_tail6_graph_toggle_selector(b, code, raw_block); -} - -fn dialog_gcd_k5_tail6_graph_decompress_block_to_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail6_graph_toggle_selector(b, code, raw_block); - dialog_gcd_k5_tail6_graph_toggle_selector_fanout(b, raw_block); - dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code(b, code, raw_block); - dialog_gcd_k5_tail6_graph_toggle_code_from_raw(b, code, raw_block); -} - -pub(crate) fn dialog_gcd_k5_tail6_graph_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS]; - for shot in 0..64 { - let pattern = - DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT[shot % DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT.len()]; - let shot_bit = 1u64 << shot; - let mut raw_word = 0u16; - for slot in 0..DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS { - if (pattern >> (3 * slot)) & 1 != 0 { - raw_masks[2 * slot] |= shot_bit; - raw_word |= 1 << (2 * slot); - } - if (pattern >> (3 * slot + 1)) & 1 != 0 { - raw_masks[2 * slot + 1] |= shot_bit; - raw_word |= 1 << (2 * slot + 1); - } - if (pattern >> (3 * slot + 2)) & 1 != 0 { - let raw_index = 2 * DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS + slot; - raw_masks[raw_index] |= shot_bit; - raw_word |= 1 << raw_index; - } - } - let code = DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS - .iter() - .enumerate() - .fold(DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT, |packed, (index, &mask)| { - packed ^ ((((raw_word & mask).count_ones() & 1) as u8) << index) - }); - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_tail6_graph_decompress_block_to_raw(&mut b, &code, &raw); - } else { - dialog_gcd_k5_tail6_graph_compress_raw_to_block(&mut b, &code, &raw); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |decompress: bool| { - let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail6-graph-codec-selftest"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let (forward_code, forward_raw, forward_phase) = run(false); - if forward_phase != 0 { - return Err(format!("forward phase garbage 0x{forward_phase:x}")); - } - if forward_code != code_masks { - return Err(format!( - "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw.iter().any(|&mask| mask != 0) { - return Err(format!("forward raw garbage: {forward_raw:x?}")); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true); - if reverse_phase != 0 { - return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); - } - if reverse_code.iter().any(|&mask| mask != 0) { - return Err(format!("reverse code garbage: {reverse_code:x?}")); - } - if reverse_raw != raw_masks { - return Err(format!( - "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - Ok(()) -} - -fn dialog_gcd_k5_tail7_toggle_code_from_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL7_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (code_index, &mask) in DIALOG_GCD_K5_TAIL7_RAW_CODE_MASKS.iter().enumerate() { - for raw_bit in 0..12 { - if (mask >> raw_bit) & 1 != 0 { - b.cx(raw_block[raw_bit], code[code_index]); - } - } - if (DIALOG_GCD_K5_TAIL7_CODE_CONSTANT >> code_index) & 1 != 0 { - b.x(code[code_index]); - } - } -} - -fn dialog_gcd_k5_tail7_toggle_raw_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL7_CODE_BITS); - assert_eq!(raw_block.len(), 15); - for (raw_index, terms) in DIALOG_GCD_K5_TAIL7_RAW_ANF.iter().enumerate() { - dialog_gcd_toggle_anf_with_dirty(b, code, raw_block[raw_index], raw_block, terms); - } -} - -fn dialog_gcd_k5_tail7_compress_raw_to_block( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail7_toggle_code_from_raw(b, code, raw_block); - dialog_gcd_k5_tail7_toggle_raw_from_code(b, code, raw_block); -} - -fn dialog_gcd_k5_tail7_decompress_block_to_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - dialog_gcd_k5_tail7_toggle_raw_from_code(b, code, raw_block); - dialog_gcd_k5_tail7_toggle_code_from_raw(b, code, raw_block); -} - -fn dialog_gcd_k5_tail3_transfer_survivors( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - assert_eq!(raw_block.len(), 15); - for (index, &wire) in DIALOG_GCD_K5_TAIL3_DATA_WIRES.iter().enumerate() { - if swap_host { - b.swap(compressed_block[index], raw_block[wire]); - } else { - b.cx(compressed_block[index], raw_block[wire]); - } - } -} - -fn dialog_gcd_k5_tail3_top32_raw(raw_block: &[QubitId]) -> [QubitId; 9] { - assert_eq!(raw_block.len(), 15); - DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES.map(|wire| raw_block[wire]) -} - -fn dialog_gcd_k5_tail3_top32_toggle_code_from_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); - let code_constant = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { - DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_CODE_CONSTANT - } else { - DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT - }; - for code_index in 0..DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF.len() { - let terms = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { - DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_ENCODER_ANF[code_index] - } else { - DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF[code_index] - }; - if (code_constant >> code_index) & 1 != 0 { - b.x(code[code_index]); - } - for &mask in terms { - let controls = raw - .iter() - .enumerate() - .filter_map(|(index, &q)| ((mask >> index) & 1 != 0).then_some(q)) - .collect::>(); - assert!(controls.len() <= 2); - dialog_gcd_toggle_mcx_with_dirty(b, &controls, raw_block, code[code_index]); - } - } -} - -fn dialog_gcd_k5_tail3_top32_toggle_raw_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(code.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); - for raw_index in 0..DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF.len() { - let terms = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { - DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF[raw_index] - } else { - DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index] - }; - dialog_gcd_toggle_anf_with_dirty(b, code, raw[raw_index], raw_block, terms); - } -} - -fn dialog_gcd_k5_tail3_top32_slot_raw( - raw_block: &[QubitId], - slot: usize, -) -> [QubitId; 3] { - assert_eq!(raw_block.len(), 15); - assert!(slot < 3); - [raw_block[2 * slot], raw_block[2 * slot + 1], raw_block[10 + slot]] -} - -fn dialog_gcd_k5_tail3_top32_slot_branch_raw( - raw_block: &[QubitId], - slot: usize, -) -> [QubitId; 2] { - assert_eq!(raw_block.len(), 15); - assert!(slot < 3); - [raw_block[2 * slot], raw_block[2 * slot + 1]] -} - -fn dialog_gcd_k5_tail3_top32_slot_shift_raw( - raw_block: &[QubitId], - slot: usize, -) -> [QubitId; 1] { - assert_eq!(raw_block.len(), 15); - assert!(slot < 3); - [raw_block[10 + slot]] -} - -fn dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - raw_indices: &[usize], -) { - let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); - for &raw_index in raw_indices { - dialog_gcd_toggle_anf_with_dirty( - b, - code, - raw[raw_index], - raw_block, - if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { - DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF[raw_index] - } else { - DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index] - }, - ); - } -} - -fn dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - slot: usize, -) { - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b, - code, - raw_block, - &[2 * slot, 2 * slot + 1], - ); -} - -fn dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - slot: usize, -) { - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code(b, code, raw_block, &[6 + slot]); -} - -fn dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - slot: usize, -) { - let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); - for raw_index in [2 * slot, 2 * slot + 1, 6 + slot] { - dialog_gcd_toggle_anf_with_dirty( - b, - code, - raw[raw_index], - raw_block, - DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index], - ); - } -} - -fn dialog_gcd_k5_tail3_top32_stream_scratch(raw_block: &[QubitId]) -> Vec { - assert_eq!(raw_block.len(), 15); - DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES - .iter() - .map(|&wire| raw_block[wire]) - .collect() -} - -fn dialog_gcd_k5_tail3_top32_stream_dynamic(raw_block: &[QubitId]) -> Vec { - assert_eq!(raw_block.len(), 15); - raw_block - .iter() - .enumerate() - .filter_map(|(wire, &q)| { - (!DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES.contains(&wire)).then_some(q) - }) - .collect() -} - -fn dialog_gcd_k5_tail3_top32_compress_raw_to_block( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - if swap_host { - dialog_gcd_k5_tail3_top32_toggle_code_from_raw(b, code, raw_block); - } - dialog_gcd_k5_tail3_top32_toggle_raw_from_code(b, code, raw_block); -} - -fn dialog_gcd_k5_tail3_top32_decompress_block_to_raw( - b: &mut B, - code: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - dialog_gcd_k5_tail3_top32_toggle_raw_from_code(b, code, raw_block); - if swap_host { - dialog_gcd_k5_tail3_top32_toggle_code_from_raw(b, code, raw_block); - } -} - -fn dialog_gcd_k5_tail3_top32_raw_word(pattern: u16) -> u16 { - (0..3).fold(0u16, |raw, slot| { - let digit = (pattern >> (3 * slot)) & 7; - raw - | ((digit & 1) << (2 * slot)) - | (((digit >> 1) & 1) << (2 * slot + 1)) - | (((digit >> 2) & 1) << (6 + slot)) - }) -} - -fn dialog_gcd_k5_tail3_top32_code_word(raw: u16) -> u8 { - DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF - .iter() - .enumerate() - .fold(DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT, |code, (index, terms)| { - let bit = terms - .iter() - .fold(0u8, |value, &mask| value ^ u8::from(raw & mask == mask)); - code ^ (bit << index) - }) -} - -fn dialog_gcd_k5_tail3_top32_decode_word(code: u8) -> u16 { - DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF - .iter() - .enumerate() - .fold(0u16, |raw, (index, terms)| { - let bit = terms.iter().fold(0u16, |value, &mask| { - value ^ u16::from((u16::from(code) & mask) == mask) - }); - raw ^ (bit << index) - }) -} - -pub(crate) fn dialog_gcd_k5_tail3_top32_supports(pattern: u16) -> bool { - DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT.contains(&pattern) -} - -pub(crate) fn dialog_gcd_k5_tail3_top32_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let mut seen_codes = [false; 1 << DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; - for &pattern in &DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT { - let raw = dialog_gcd_k5_tail3_top32_raw_word(pattern); - let code = dialog_gcd_k5_tail3_top32_code_word(raw); - if std::mem::replace(&mut seen_codes[code as usize], true) { - return Err(format!( - "duplicate top32 code for pattern 0x{pattern:03x}: 0x{code:02x}" - )); - } - let decoded = dialog_gcd_k5_tail3_top32_decode_word(code); - if decoded != raw { - return Err(format!( - "top32 word mismatch for pattern 0x{pattern:03x}: got 0x{decoded:03x}, want 0x{raw:03x}" - )); - } - } - if seen_codes.iter().any(|seen| !seen) { - return Err("top32 codec does not cover all 32 code words".to_string()); - } - - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; - for shot in 0..64 { - let pattern = DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT - [shot % DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT.len()]; - let raw = dialog_gcd_k5_tail3_top32_raw_word(pattern); - let code = dialog_gcd_k5_tail3_top32_code_word(raw); - let shot_bit = 1u64 << shot; - for (index, &wire) in DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES - .iter() - .enumerate() - { - if (raw >> index) & 1 != 0 { - raw_masks[wire] |= shot_bit; - } - } - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_tail3_top32_decompress_block_to_raw(&mut b, &code, &raw, true); - } else { - dialog_gcd_k5_tail3_top32_compress_raw_to_block(&mut b, &code, &raw, true); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |decompress: bool, source: &[u64]| { - let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail3-top32-codec-selftest"); - seed.update(&[u8::from(decompress)]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let (forward_code, forward_raw, forward_phase) = run(false, &raw_masks); - if forward_phase != 0 { - return Err(format!("top32 forward phase garbage 0x{forward_phase:x}")); - } - if forward_code != code_masks { - return Err(format!( - "top32 forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw.iter().any(|&mask| mask != 0) { - return Err(format!("top32 forward raw garbage: {forward_raw:x?}")); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true, &code_masks); - if reverse_phase != 0 { - return Err(format!("top32 reverse phase garbage 0x{reverse_phase:x}")); - } - if reverse_code.iter().any(|&mask| mask != 0) { - return Err(format!("top32 reverse code garbage: {reverse_code:x?}")); - } - if reverse_raw != raw_masks { - return Err(format!( - "top32 reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - Ok(()) -} - -fn dialog_gcd_k5_tail3_compress_raw_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - assert_eq!(raw_block.len(), 15); - emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); - dialog_gcd_k5_tail3_transfer_survivors(b, compressed_block, raw_block, swap_host); -} - -fn dialog_gcd_k5_tail3_decompress_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - assert_eq!(raw_block.len(), 15); - dialog_gcd_k5_tail3_transfer_survivors(b, compressed_block, raw_block, swap_host); - emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); -} - -fn dialog_gcd_k5_tail3_code_word(left: u8, right: u8) -> Option { - let mut raw = [false; 15]; - for (slot, digit) in [left, right].into_iter().enumerate() { - raw[3 * slot] = digit & 1 != 0; - raw[3 * slot + 1] = digit & 2 != 0; - raw[3 * slot + 2] = digit & 4 != 0; - } - dialog_gcd_k5_head11_pair_encode_word(&mut raw, [0, 1]); - if raw[0] { - return None; - } - Some( - [1usize, 2, 3, 4, 5] - .iter() - .enumerate() - .fold(0u8, |code, (index, &wire)| { - code | (u8::from(raw[wire]) << index) - }), - ) -} - -pub(crate) fn dialog_gcd_k5_tail3_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - const DIGITS: [u8; 6] = [0, 1, 3, 4, 5, 7]; - let supported = DIGITS - .into_iter() - .flat_map(|left| DIGITS.into_iter().map(move |right| (left, right))) - .filter(|&(left, right)| dialog_gcd_k5_tail3_code_word(left, right).is_some()) - .collect::>(); - if supported.len() != 30 { - return Err(format!( - "expected 30 supported tail pairs, got {}", - supported.len() - )); - } - let mut seen_codes = [false; 1 << DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; - for &(left, right) in &supported { - let code = dialog_gcd_k5_tail3_code_word(left, right).expect("filtered support"); - if std::mem::replace(&mut seen_codes[code as usize], true) { - return Err(format!( - "duplicate tail-pair code for digits ({left}, {right}): 0x{code:02x}" - )); - } - } - - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; - for shot in 0..64 { - let (left, right) = supported[shot % supported.len()]; - let shot_bit = 1u64 << shot; - for (slot, digit) in [left, right].into_iter().enumerate() { - if digit & 1 != 0 { - raw_masks[2 * slot] |= shot_bit; - } - if digit & 2 != 0 { - raw_masks[2 * slot + 1] |= shot_bit; - } - if digit & 4 != 0 { - raw_masks[10 + slot] |= shot_bit; - } - } - let code = dialog_gcd_k5_tail3_code_word(left, right).expect("supported pair"); - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_tail3_decompress_block_to_raw(&mut b, &code, &raw, true); - } else { - dialog_gcd_k5_tail3_compress_raw_to_block(&mut b, &code, &raw, true); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |decompress: bool, source: &[u64]| { - let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail3-codec-selftest"); - seed.update(&[u8::from(decompress)]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let (forward_code, forward_raw, forward_phase) = run(false, &raw_masks); - if forward_phase != 0 { - return Err(format!("forward phase garbage 0x{forward_phase:x}")); - } - if forward_code != code_masks { - return Err(format!( - "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw.iter().any(|&mask| mask != 0) { - return Err(format!("forward raw garbage: {forward_raw:x?}")); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true, &forward_code); - if reverse_phase != 0 { - return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); - } - if reverse_code.iter().any(|&mask| mask != 0) { - return Err(format!("reverse code garbage: {reverse_code:x?}")); - } - if reverse_raw != raw_masks { - return Err(format!( - "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - Ok(()) -} - -pub(crate) fn dialog_gcd_k5_tail7_codec_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let mut raw_masks = [0u64; 15]; - let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL7_CODE_BITS]; - for shot in 0..64 { - let pattern = DIALOG_GCD_K5_TAIL7_SUPPORT[shot % DIALOG_GCD_K5_TAIL7_SUPPORT.len()]; - let shot_bit = 1u64 << shot; - for slot in 0..DIALOG_GCD_K5_TAIL7_STORED_STEPS { - if (pattern >> (3 * slot)) & 1 != 0 { - raw_masks[2 * slot] |= shot_bit; - } - if (pattern >> (3 * slot + 1)) & 1 != 0 { - raw_masks[2 * slot + 1] |= shot_bit; - } - if (pattern >> (3 * slot + 2)) & 1 != 0 { - raw_masks[2 * DIALOG_GCD_K5_TAIL7_STORED_STEPS + slot] |= shot_bit; - } - } - let code = DIALOG_GCD_K5_TAIL7_PACKED_CODE_MASKS - .iter() - .enumerate() - .fold(0u8, |packed, (index, &mask)| { - packed | ((((pattern & mask).count_ones() & 1) as u8) << index) - }); - for (index, mask) in code_masks.iter_mut().enumerate() { - if (code >> index) & 1 != 0 { - *mask |= shot_bit; - } - } - } - - let build_codec = |decompress: bool| { - let mut b = B::new(); - let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL7_CODE_BITS); - let raw = b.alloc_qubits(15); - if decompress { - dialog_gcd_k5_tail7_decompress_block_to_raw(&mut b, &code, &raw); - } else { - dialog_gcd_k5_tail7_compress_raw_to_block(&mut b, &code, &raw); - } - (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |decompress: bool| { - let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail7-codec-selftest"); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; - let targets = if decompress { &code[..] } else { &raw[..] }; - for (&qubit, &mask) in targets.iter().zip(source.iter()) { - *sim.qubit_mut(qubit) = mask; - } - sim.apply_iter(ops.iter()); - ( - code.iter().map(|&q| sim.qubit(q)).collect::>(), - raw.iter().map(|&q| sim.qubit(q)).collect::>(), - sim.phase, - ) - }; - - let (forward_code, forward_raw, forward_phase) = run(false); - if forward_phase != 0 { - return Err(format!("forward phase garbage 0x{forward_phase:x}")); - } - if forward_code != code_masks { - return Err(format!( - "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" - )); - } - if forward_raw.iter().any(|&mask| mask != 0) { - return Err(format!("forward raw garbage: {forward_raw:x?}")); - } - - let (reverse_code, reverse_raw, reverse_phase) = run(true); - if reverse_phase != 0 { - return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); - } - if reverse_code.iter().any(|&mask| mask != 0) { - return Err(format!("reverse code garbage: {reverse_code:x?}")); - } - if reverse_raw != raw_masks { - return Err(format!( - "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" - )); - } - Ok(()) -} - -fn dialog_gcd_k5_tail_pair1_compress_raw_to_block( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 1); - assert_eq!(raw_block.len(), 15); - - if swap_host { - b.swap(compressed_block[0], raw_block[0]); - } else { - b.cx(compressed_block[0], raw_block[0]); - } - b.x(dialog_gcd_raw_s2(raw_block, 0)); - b.x(dialog_gcd_raw_s2(raw_block, 1)); -} - -fn dialog_gcd_k5_tail_pair1_decompress_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - swap_host: bool, -) { - assert_eq!(compressed_block.len(), 1); - assert_eq!(raw_block.len(), 15); - b.x(dialog_gcd_raw_s2(raw_block, 1)); - b.x(dialog_gcd_raw_s2(raw_block, 0)); - if swap_host { - b.swap(compressed_block[0], raw_block[0]); - } else { - b.cx(compressed_block[0], raw_block[0]); - } -} - -pub(crate) fn emit_dialog_gcd_round763_compressed_block_swapper( - b: &mut B, - pair: &[QubitId], - compressed_block: &[QubitId], - scratch: QubitId, - slot: usize, -) { - assert_eq!(pair.len(), 2); - assert_eq!(compressed_block.len(), 5); - assert!(slot < 3); - let mut block = compressed_block.to_vec(); - block.push(scratch); - emit_dialog_gcd_round763_compressor_inverse(b, &block); - b.swap(pair[0], block[2 * slot]); - b.swap(pair[1], block[2 * slot + 1]); - emit_dialog_gcd_round763_compressor(b, &block); -} - -pub(crate) fn dialog_gcd_compressed_sidecar_blocks() -> usize { - let group_size = dialog_gcd_sidecar_group_size(); - let blocks = (dialog_gcd_active_iterations() + group_size - 1) / group_size; - if dialog_gcd_k5_tail7_enabled() - || dialog_gcd_k5_tail6_graph_enabled() - || dialog_gcd_k5_tail6_graph9_enabled() - { - blocks - 1 - } else { - blocks - } -} - -fn dialog_gcd_compressed_sidecar_block_index(step: usize) -> usize { - if dialog_gcd_k5_tail7_enabled() - && step >= dialog_gcd_active_iterations() - 7 - || dialog_gcd_k5_tail6_graph_enabled() - && step >= dialog_gcd_active_iterations() - 6 - || dialog_gcd_k5_tail6_graph9_enabled() - && step >= dialog_gcd_active_iterations() - 6 - { - dialog_gcd_compressed_sidecar_blocks() - 1 - } else { - step / dialog_gcd_sidecar_group_size() - } -} - -fn dialog_gcd_compressed_sidecar_block_bits(block: usize) -> usize { - if dialog_gcd_k5_head11_enabled() && block == 0 { - DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - } else if dialog_gcd_k5_tail6_graph9_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS - } else if dialog_gcd_k5_tail6_graph_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS - } else if dialog_gcd_k5_tail7_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - DIALOG_GCD_K5_TAIL7_CODE_BITS - } else if dialog_gcd_k5_tail_pair1_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - 1 - } else if (dialog_gcd_k5_tail3_fixed_last_enabled() - || dialog_gcd_k5_tail3_top32_enabled()) - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - } else if dialog_gcd_k5_tight_partial_block_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let steps = end - start; - if steps < dialog_gcd_sidecar_group_size() { - DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + steps - } else { - dialog_gcd_block_bits() - } - } else { - dialog_gcd_block_bits() - } -} - -fn dialog_gcd_compressed_sidecar_block_offset(block: usize) -> usize { - (0..block) - .map(dialog_gcd_compressed_sidecar_block_bits) - .sum() -} - -pub(crate) fn dialog_gcd_compressed_sidecar_bits() -> usize { - (0..dialog_gcd_compressed_sidecar_blocks()) - .map(dialog_gcd_compressed_sidecar_block_bits) - .sum() -} - -pub(crate) fn dialog_gcd_compressed_sidecar_block(compressed_log: &[QubitId], step: usize) -> &[QubitId] { - let block = dialog_gcd_compressed_sidecar_block_index(step); - let start = dialog_gcd_compressed_sidecar_block_offset(block); - let bits = dialog_gcd_compressed_sidecar_block_bits(block); - &compressed_log[start..start + bits] -} - -pub(crate) fn dialog_gcd_compressed_log_u_high_runway_enabled() -> bool { - - std::env::var("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY") - .ok() - .as_deref() - == Some("1") -} - -fn dialog_gcd_k5_constant_tail_stored_steps(block_steps: usize) -> Option { - if dialog_gcd_k5_tail3_fixed_last_enabled() && block_steps == 3 { - Some(2) - } else if dialog_gcd_k5_tail6_graph9_enabled() && block_steps == 6 { - Some(DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS) - } else if dialog_gcd_k5_tail6_graph_enabled() && block_steps == 6 { - Some(DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS) - } else if dialog_gcd_k5_tail7_enabled() && block_steps == 7 { - Some(DIALOG_GCD_K5_TAIL7_STORED_STEPS) - } else { - None - } -} - -fn dialog_gcd_k5_fixed_tail_apply_enabled() -> bool { - (dialog_gcd_k5_tail3_fixed_last_enabled() - || dialog_gcd_k5_tail7_enabled() - || dialog_gcd_k5_tail6_graph_enabled() - || dialog_gcd_k5_tail6_graph9_enabled()) - && (std::env::var("DIALOG_GCD_K5_FIXED_TAIL_APPLY") - .ok() - .as_deref() - == Some("1") - || std::env::var("DIALOG_GCD_K5_TAIL7_UNCONDITIONAL_APPLY") - .ok() - .as_deref() - == Some("1")) -} - -pub(crate) fn dialog_gcd_compressed_log_u_high_runway_blocks() -> usize { - - std::env::var("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY_BLOCKS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(16) -} - -fn dialog_gcd_runway_partial_block_enabled() -> bool { - std::env::var("DIALOG_GCD_RUNWAY_PARTIAL_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -#[derive(Clone, Debug)] -pub(crate) struct DialogGcdCompressedLogUHighRunway { - remapped_log: Vec, - parked_u_indices: Vec, -} - -pub(crate) fn dialog_gcd_slice_intersects(a: &[QubitId], b: &[QubitId]) -> bool { - a.iter().any(|q| b.contains(q)) -} - -pub(crate) fn dialog_gcd_runway_layout() -> Vec<(usize, usize)> { - - let raw_block_bits = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; - let Some(highest_host) = N.checked_sub(raw_block_bits + 1) else { - return Vec::new(); - }; - let blocks = dialog_gcd_compressed_sidecar_blocks(); - - let first_allowed = blocks.saturating_sub(dialog_gcd_compressed_log_u_high_runway_blocks()); - for first_block in first_allowed..blocks { - let first_bits = dialog_gcd_compressed_sidecar_block_bits(first_block); - let first_slots = if dialog_gcd_runway_partial_block_enabled() { - 0..first_bits - } else { - 0..1 - }; - for first_slot in first_slots { - let mut next_host = highest_host; - let mut layout = Vec::with_capacity( - (first_block..blocks) - .map(dialog_gcd_compressed_sidecar_block_bits) - .sum::() - - first_slot, - ); - let mut fits = true; - for block in first_block..blocks { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let active_threshold = (start..end) - .map(dialog_gcd_tobitvector_active_width) - .max() - .unwrap_or(1); - let block_offset = dialog_gcd_compressed_sidecar_block_offset(block); - let slot_start = if block == first_block { first_slot } else { 0 }; - for slot in slot_start..dialog_gcd_compressed_sidecar_block_bits(block) { - if next_host < active_threshold { - fits = false; - break; - } - layout.push((block_offset + slot, next_host)); - let Some(next) = next_host.checked_sub(1) else { - fits = false; - break; - }; - next_host = next; - } - if !fits { - break; - } - } - if fits { - return layout; - } - } - } - Vec::new() -} - -pub(crate) fn dialog_gcd_allocated_compressed_sidecar_bits() -> usize { - if dialog_gcd_compressed_log_u_high_runway_enabled() { - dialog_gcd_compressed_sidecar_bits() - dialog_gcd_runway_layout().len() - } else { - dialog_gcd_compressed_sidecar_bits() - } -} - -pub(crate) fn dialog_gcd_build_compressed_log_u_high_runway( - u: &[QubitId], - allocated_log: &[QubitId], -) -> Option { - if !dialog_gcd_compressed_log_u_high_runway_enabled() { - return None; - } - assert_eq!(u.len(), N); - let layout = dialog_gcd_runway_layout(); - if layout.is_empty() { - return None; - } - - let expected_allocated = dialog_gcd_compressed_sidecar_bits() - layout.len(); - assert_eq!(allocated_log.len(), expected_allocated); - let first_relocated = layout[0].0; - assert_eq!(first_relocated, allocated_log.len()); - let mut remapped_log = allocated_log.to_vec(); - let mut parked_u_indices = Vec::with_capacity(layout.len()); - for (log_index, u_index) in layout { - - assert_eq!(log_index, remapped_log.len()); - remapped_log.push(u[u_index]); - parked_u_indices.push(u_index); - } - assert_eq!(remapped_log.len(), dialog_gcd_compressed_sidecar_bits()); - Some(DialogGcdCompressedLogUHighRunway { - remapped_log, - parked_u_indices, - }) -} - -pub(crate) fn dialog_gcd_release_terminal_u( - b: &mut B, - u: &[QubitId], - runway: Option<&DialogGcdCompressedLogUHighRunway>, -) { - for (index, &q) in u.iter().enumerate() { - if runway.is_none_or(|r| !r.parked_u_indices.contains(&index)) { - b.free(q); - } - } -} - -pub(crate) fn dialog_gcd_reacquire_terminal_u( - b: &mut B, - u: &[QubitId], - runway: Option<&DialogGcdCompressedLogUHighRunway>, -) { - for (index, &q) in u.iter().enumerate() { - if runway.is_none_or(|r| !r.parked_u_indices.contains(&index)) { - b.reacquire(q); - } - } -} - -pub(crate) fn dialog_gcd_runway_safe_future_prefix<'a>( - future: Option<&'a [QubitId]>, - u: &[QubitId], - active_width: usize, -) -> Option<&'a [QubitId]> { - let active_u = &u[..active_width]; - future - .map(|slice| { - let safe = slice - .iter() - .position(|q| active_u.contains(q)) - .unwrap_or(slice.len()); - &slice[..safe] - }) - .filter(|slice| !slice.is_empty()) -} - -pub(crate) fn dialog_gcd_composite_scratch_enabled() -> bool { - std::env::var("DIALOG_GCD_COMPOSITE_SCRATCH") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_borrow_current_block_enabled() -> bool { - - std::env::var("DIALOG_GCD_BORROW_CURRENT_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_borrow_current_s2_enabled() -> bool { - - std::env::var("DIALOG_GCD_BORROW_CURRENT_S2") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_cshift_enabled() -> bool { - std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_tobit_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_tobit_fwd_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_tobit_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_FWD_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_tobit_rev_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_tobit_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_REV_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_apply_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_apply_double_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_apply_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_DOUBLE_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_skip_zero_edge_apply_halve_cshift_enabled() -> bool { - dialog_gcd_skip_zero_edge_apply_cshift_enabled() - || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_HALVE_CSHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_borrow_zero_raw_future_enabled() -> bool { - - std::env::var("DIALOG_GCD_BORROW_ZERO_RAW_FUTURE") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) struct DialogGcdCompositeScratch { - lanes: Vec, - owned: Vec, -} - -pub(crate) fn dialog_gcd_build_composite_scratch( - b: &mut B, - future: Option<&[QubitId]>, - u: &[QubitId], - v: &[QubitId], - compressed_log: &[QubitId], - raw_block: &[QubitId], - active_width: usize, - step: usize, -) -> DialogGcdCompositeScratch { - - let body_start = if dialog_gcd_odd_u_lowbit_fastpath_enabled() { - 1 - } else { - 0 - }; - let body_w = dialog_gcd_body_carry_trunc_width(active_width, step); - let body_len = body_w.saturating_sub(body_start); - let nocin = dialog_gcd_selected_body_nocin_enabled() - && !dialog_gcd_selected_body_nocin_keep_pool() - && body_start >= 1 - && body_len >= 1; - let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); - let want = if !dialog_gcd_raw_tobitvector_materialized_sub_enabled() { - - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - let comparator_need = compare_bits + 1; - let body_need = if dialog_gcd_ctrl_body_vented_enabled() { - active_width.saturating_sub(1) - } else { - 0 - }; - comparator_need.max(body_need).min(2 * active_width - 1).max(1) - } else if nocin && stream_suffix >= 2 { - 2 * (body_len - stream_suffix) + 1 - } else if nocin && dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 - { - 2 * (body_len - 1) - } else if nocin { - - (2 * body_len - 1).min(2 * active_width - 1) - } else { - 2 * active_width - 1 - }; - let mut lanes = Vec::with_capacity(want); - let mut push = |q: QubitId| { - if lanes.len() < want - && !lanes.contains(&q) - && !raw_block.contains(&q) - && !u[..active_width].contains(&q) - && !v[..active_width].contains(&q) - { - lanes.push(q); - } - }; - if let Some(future) = dialog_gcd_runway_safe_future_prefix(future, u, active_width) { - for &q in future { - push(q); - } - } - if dialog_gcd_borrow_current_block_enabled() { - - let block_cells = dialog_gcd_compressed_sidecar_block(compressed_log, step); - for &q in block_cells { - push(q); - } - } - for &q in &v[active_width..] { - push(q); - } - for &q in &u[active_width..] { - if !compressed_log.contains(&q) { - push(q); - } - } - if dialog_gcd_borrow_current_s2_enabled() && !raw_block.is_empty() { - - let group_size = dialog_gcd_sidecar_group_size(); - let slot = step % group_size; - let s2 = raw_block[2 * group_size + slot]; - if lanes.len() < want - && !lanes.contains(&s2) - && !u[..active_width].contains(&s2) - && !v[..active_width].contains(&s2) - { - lanes.push(s2); - } - if dialog_gcd_trio_width_notch_enabled() && slot == 0 && group_size >= 2 { - let sibling_s2 = raw_block[2 * group_size + 1]; - if lanes.len() < want - && !lanes.contains(&sibling_s2) - && !u[..active_width].contains(&sibling_s2) - && !v[..active_width].contains(&sibling_s2) - { - lanes.push(sibling_s2); - } - } - } - if dialog_gcd_borrow_zero_raw_future_enabled() && !raw_block.is_empty() { - let group_size = dialog_gcd_sidecar_group_size(); - let slot = step % group_size; - let mut push_raw_zero = |q: QubitId| { - if lanes.len() < want - && !lanes.contains(&q) - && !u[..active_width].contains(&q) - && !v[..active_width].contains(&q) - { - lanes.push(q); - } - }; - for future_slot in (slot + 1)..group_size { - push_raw_zero(raw_block[2 * future_slot]); - push_raw_zero(raw_block[2 * future_slot + 1]); - if dialog_gcd_k2_enabled() { - push_raw_zero(raw_block[2 * group_size + future_slot]); - } - } - } - let owned = b.alloc_qubits(want - lanes.len()); - if std::env::var("PROBE_SCRATCH").is_ok() && active_width >= 254 { - eprintln!( - "SCRATCH step={} aw={} body_w={} body_len={} want={} borrowed={} owned={}", - step, - active_width, - body_w, - body_len, - want, - lanes.len(), - owned.len() - ); - } - lanes.extend_from_slice(&owned); - DialogGcdCompositeScratch { lanes, owned } -} - -pub(crate) fn dialog_gcd_pick_runway_safe_borrow_slice<'a>( - future: Option<&'a [QubitId]>, - u: &'a [QubitId], - compressed_log: &[QubitId], - active_width: usize, -) -> Option<&'a [QubitId]> { - if !dialog_gcd_compressed_log_u_high_runway_enabled() { - return dialog_gcd_pick_borrow_slice(future, u, active_width); - } - - let safe_future = dialog_gcd_runway_safe_future_prefix(future, u, active_width); - if dialog_gcd_late_borrow_uv_high_enabled() && active_width >= 1 { - let want = 2 * active_width - 1; - let short = safe_future.map_or(true, |slice| slice.len() < want); - if short && u.len() >= active_width + want { - let candidate = &u[active_width..active_width + want]; - - if !dialog_gcd_slice_intersects(candidate, compressed_log) { - return Some(candidate); - } - } - } - safe_future -} - -pub(crate) fn dialog_gcd_host_reverse_raw_block_enabled() -> bool { - - if dialog_gcd_k2_enabled() - && std::env::var("DIALOG_GCD_K2_HOST_RAW_BLOCK") - .ok() - .as_deref() - != Some("1") - { - return false; - } - std::env::var("DIALOG_GCD_HOST_REVERSE_RAW_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_k2_apply_inplace_raw_block_enabled() -> bool { - dialog_gcd_k2_pair_compress_enabled() - && std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_k5_free_clean_block_during_shift_enabled() -> bool { - dialog_gcd_k5_clean_block_enabled() - && std::env::var("DIALOG_GCD_K5_FREE_CLEAN_BLOCK_DURING_SHIFT") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_reverse_raw_block_host<'a>( - u: &'a [QubitId], - compressed_log: &'a [QubitId], - block: usize, -) -> Option<&'a [QubitId]> { - if !dialog_gcd_host_reverse_raw_block_enabled() { - return None; - } - let (start, _) = dialog_gcd_compressed_sidecar_block_step_range(block); - let active_width = dialog_gcd_tobitvector_active_width(start); - let want = 2 * active_width - 1; - let raw_bits = dialog_gcd_raw_block_len(); - if u.len().saturating_sub(active_width) >= want + raw_bits { - let candidate = &u[u.len() - raw_bits..]; - if !dialog_gcd_compressed_log_u_high_runway_enabled() - || !dialog_gcd_slice_intersects(candidate, compressed_log) - { - return Some(candidate); - } - } - let future_start = dialog_gcd_compressed_sidecar_block_offset(block + 1); - let future = compressed_log.get(future_start..)?; - if future.len() < want + raw_bits { - return None; - } - if !dialog_gcd_compressed_log_u_high_runway_enabled() { - return Some(&future[future.len() - raw_bits..]); - } - - future[want..] - .windows(raw_bits) - .rev() - .find(|candidate| !dialog_gcd_slice_intersects(candidate, &u[..active_width])) -} - -pub(crate) fn dialog_gcd_forward_raw_block_host<'a>( - u: &'a [QubitId], - compressed_log: &'a [QubitId], - block: usize, -) -> Option<&'a [QubitId]> { - if !dialog_gcd_host_reverse_raw_block_enabled() { - return None; - } - let (start, _) = dialog_gcd_compressed_sidecar_block_step_range(block); - let active_width = dialog_gcd_tobitvector_active_width(start); - let want = 2 * active_width - 1; - let raw_bits = dialog_gcd_raw_block_len(); - let future_start = dialog_gcd_compressed_sidecar_block_offset(block + 1); - if let Some(future) = compressed_log.get(future_start..) { - if future.len() >= want + raw_bits { - if !dialog_gcd_compressed_log_u_high_runway_enabled() { - return Some(&future[future.len() - raw_bits..]); - } - if let Some(candidate) = future[want..] - .windows(raw_bits) - .rev() - .find(|candidate| !dialog_gcd_slice_intersects(candidate, &u[..active_width])) - { - return Some(candidate); - } - } - } - if u.len().saturating_sub(active_width) >= want + raw_bits { - let candidate = &u[u.len() - raw_bits..]; - if !dialog_gcd_compressed_log_u_high_runway_enabled() - || !dialog_gcd_slice_intersects(candidate, compressed_log) - { - Some(candidate) - } else { - None - } - } else { - None - } -} - -pub(crate) fn dialog_gcd_compressed_sidecar_future_carry_slice( - compressed_log: &[QubitId], - step: usize, - active_width: usize, -) -> Option<&[QubitId]> { - if !dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() { - return None; - } - let carry_need = active_width.saturating_sub(1); - - let want = if dialog_gcd_host_gated_enabled() { - 2 * active_width - 1 - } else { - carry_need - }; - let next_block = dialog_gcd_compressed_sidecar_block_index(step) + 1; - let start = dialog_gcd_compressed_sidecar_block_offset(next_block); - compressed_log - .get(start..) - .filter(|future| future.len() >= carry_need) - .map(|future| &future[..future.len().min(want)]) -} - -pub(crate) fn dialog_gcd_compressed_sidecar_block_step_range(block: usize) -> (usize, usize) { - if (dialog_gcd_k5_tail6_graph_enabled() || dialog_gcd_k5_tail6_graph9_enabled()) - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - return ( - dialog_gcd_active_iterations() - 6, - dialog_gcd_active_iterations(), - ); - } - if dialog_gcd_k5_tail7_enabled() - && block + 1 == dialog_gcd_compressed_sidecar_blocks() - { - return ( - dialog_gcd_active_iterations() - 7, - dialog_gcd_active_iterations(), - ); - } - let group_size = dialog_gcd_sidecar_group_size(); - let start = block * group_size; - let end = (start + group_size).min(dialog_gcd_active_iterations()); - (start, end) -} - -pub(crate) fn dialog_gcd_copy_compressed_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, -) { - if dialog_gcd_k5_head11_enabled() - && steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - { - dialog_gcd_k5_head11_decompress_block_to_raw( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - - b.cx(raw_block[0], raw_block[1]); - return; - } - if dialog_gcd_k5_tail6_graph9_enabled() - && steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS - { - dialog_gcd_k5_tail6_graph9_decompress_block_to_raw(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail6_graph_enabled() - && steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS - { - dialog_gcd_k5_tail6_graph_decompress_block_to_raw(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail7_enabled() - && steps == 7 - && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS - { - dialog_gcd_k5_tail7_decompress_block_to_raw(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail3_top32_enabled() - && steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_top32_decompress_block_to_raw( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_tail3_fixed_last_enabled() - && steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_decompress_block_to_raw( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_tail_pair1_enabled() && steps == 2 && compressed_block.len() == 1 { - dialog_gcd_k5_tail_pair1_decompress_block_to_raw( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_clean_block_enabled() { - if steps == 5 { - dialog_gcd_k5_decompress_block_to_raw( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - } else { - dialog_gcd_k5_decompress_partial_block_to_raw( - b, - compressed_block, - raw_block, - steps, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - } - return; - } - if dialog_gcd_k2_pair_compress_enabled() { - dialog_gcd_k2_pair_copy_compressed_block_to_raw(b, compressed_block, raw_block, steps); - return; - } - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - let raw_base = 2 * dialog_gcd_sidecar_group_size(); - assert_eq!(compressed_block.len(), dialog_gcd_block_bits()); - assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); - let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); - for i in 0..base_bits { - if swap_host { - b.swap(compressed_block[i], raw_block[i]); - } else { - b.cx(compressed_block[i], raw_block[i]); - } - } - emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); - - for j in base_bits..dialog_gcd_block_bits() { - let r = raw_base + (j - base_bits); - if swap_host { - b.swap(compressed_block[j], raw_block[r]); - } else { - b.cx(compressed_block[j], raw_block[r]); - } - } -} - -pub(crate) fn dialog_gcd_clear_raw_block_copy( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, -) { - if dialog_gcd_k5_head11_enabled() - && steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - { - - b.cx(raw_block[0], raw_block[1]); - dialog_gcd_k5_head11_compress_raw_to_block( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_tail6_graph9_enabled() - && steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS - { - dialog_gcd_k5_tail6_graph9_compress_raw_to_block(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail6_graph_enabled() - && steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS - { - dialog_gcd_k5_tail6_graph_compress_raw_to_block(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail7_enabled() - && steps == 7 - && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS - { - dialog_gcd_k5_tail7_compress_raw_to_block(b, compressed_block, raw_block); - return; - } - if dialog_gcd_k5_tail3_top32_enabled() - && steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_top32_compress_raw_to_block( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_tail3_fixed_last_enabled() - && steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_compress_raw_to_block( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_tail_pair1_enabled() && steps == 2 && compressed_block.len() == 1 { - dialog_gcd_k5_tail_pair1_compress_raw_to_block( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - return; - } - if dialog_gcd_k5_clean_block_enabled() { - if steps == 5 { - dialog_gcd_k5_compress_raw_to_block( - b, - compressed_block, - raw_block, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - } else { - dialog_gcd_k5_compress_partial_raw_to_block( - b, - compressed_block, - raw_block, - steps, - dialog_gcd_apply_replay_swap_host_enabled(), - ); - } - return; - } - if dialog_gcd_k2_pair_compress_enabled() { - dialog_gcd_k2_pair_clear_raw_block_copy(b, compressed_block, raw_block, steps); - return; - } - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - let raw_base = 2 * dialog_gcd_sidecar_group_size(); - assert_eq!(compressed_block.len(), dialog_gcd_block_bits()); - assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); - let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); - - for j in base_bits..dialog_gcd_block_bits() { - let r = raw_base + (j - base_bits); - if swap_host { - b.swap(compressed_block[j], raw_block[r]); - } else { - b.cx(compressed_block[j], raw_block[r]); - } - } - emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); - for i in 0..base_bits { - if swap_host { - b.swap(compressed_block[i], raw_block[i]); - } else { - b.cx(compressed_block[i], raw_block[i]); - } - } -} - -pub(crate) fn dialog_gcd_k2_pair_inplace_raw_frame( - compressed_block: &[QubitId], - raw0: QubitId, -) -> [QubitId; 6] { - assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); - [ - raw0, - compressed_block[0], - compressed_block[2], - compressed_block[3], - compressed_block[1], - compressed_block[4], - ] -} - -pub(crate) fn dialog_gcd_k2_pair_inplace_decompress_block( - b: &mut B, - compressed_block: &[QubitId], - raw0: QubitId, - steps: usize, -) -> [QubitId; 6] { - assert_eq!(steps, 2, "in-place K2 apply currently requires full pair blocks"); - let raw_frame = dialog_gcd_k2_pair_inplace_raw_frame(compressed_block, raw0); - let core = dialog_gcd_k2_pair_core(&raw_frame); - emit_dialog_gcd_k2_pair_core_encoder_inverse(b, &core); - raw_frame -} - -pub(crate) fn dialog_gcd_k2_pair_inplace_clear_block( - b: &mut B, - compressed_block: &[QubitId], - raw0: QubitId, - steps: usize, -) { - assert_eq!(steps, 2, "in-place K2 apply currently requires full pair blocks"); - let raw_frame = dialog_gcd_k2_pair_inplace_raw_frame(compressed_block, raw0); - let core = dialog_gcd_k2_pair_core(&raw_frame); - emit_dialog_gcd_k2_pair_core_encoder(b, &core); -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - compressed_log: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert!(raw_block.is_empty() || raw_block.len() == dialog_gcd_raw_block_len()); - assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); - - for block in 0..dialog_gcd_compressed_sidecar_blocks() { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let block_steps = end - start; - let hosted_raw_block = dialog_gcd_forward_raw_block_host(u, compressed_log, block); - let owned_raw_block = - if dialog_gcd_host_reverse_raw_block_enabled() && hosted_raw_block.is_none() { - b.alloc_qubits(dialog_gcd_raw_block_len()) - } else { - Vec::new() - }; - let raw_block = hosted_raw_block.unwrap_or_else(|| { - if owned_raw_block.is_empty() { - raw_block - } else { - &owned_raw_block - } - }); - for step in start..end { - let slot = step - start; - if dialog_gcd_k5_constant_tail_stored_steps(block_steps) - .is_some_and(|stored_steps| slot >= stored_steps) - { - let active_width = dialog_gcd_tobitvector_active_width(step); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - let v_shift = &v[..shift_width]; - b.set_phase("dialog_gcd_compressed_block_tobitvector_tail7_constant_shift"); - dialog_gcd_shift_right_assuming_even(b, v_shift); - dialog_gcd_shift_right_assuming_even(b, v_shift); - continue; - } - let b0 = raw_block[2 * slot]; - let b0_and_b1 = raw_block[2 * slot + 1]; - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - let future = dialog_gcd_compressed_sidecar_future_carry_slice( - compressed_log, - step, - active_width, - ); - let composite_scratch = dialog_gcd_composite_scratch_enabled().then(|| { - dialog_gcd_build_composite_scratch( - b, - future, - u, - v, - compressed_log, - raw_block, - active_width, - step, - ) - }); - let borrowed_carries = composite_scratch.as_ref().map_or_else( - || { - dialog_gcd_pick_runway_safe_borrow_slice( - future, - u, - compressed_log, - active_width, - ) - }, - |scratch| Some(scratch.lanes.as_slice()), - ); - - b.set_phase("dialog_gcd_compressed_block_tobitvector_branch_bits"); - b.cx(v[0], b0); - if dialog_gcd_fused_branch_bits_enabled() { - - if dialog_gcd_branch_bits_host_comparator_enabled() { - - dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - borrowed_carries, - ); - } else { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } - } else { - let cmp = b.alloc_qubit(); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.free(cmp); - } - - b.set_phase("dialog_gcd_compressed_block_tobitvector_cswap"); - let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); - for (i, (&ui, &vi)) in u[..cswap_width] - .iter() - .zip(v[..cswap_width].iter()) - .enumerate() - { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_compressed_block_tobitvector_subtract"); - dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); - if std::env::var("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT") - .ok() - .as_deref() - == Some("1") - { - if let Some(scratch) = composite_scratch.as_ref() { - b.free_vec(&scratch.owned); - } - } - - b.set_phase("dialog_gcd_compressed_block_tobitvector_shift"); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - let v_shift = &v[..shift_width]; - dialog_gcd_shift_right_assuming_even(b, v_shift); - if dialog_gcd_k2_enabled() { - - let s2 = dialog_gcd_block_raw_s2(raw_block, block_steps, slot); - let v0 = v_active[0]; - if std::env::var("DIALOG_GCD_K2_FORCE0").ok().as_deref() != Some("1") { - b.cx(v0, s2); - b.x(s2); - } - let pairs = v_shift.len().saturating_sub(1); - for i in 0..pairs { - if dialog_gcd_skip_zero_edge_tobit_fwd_cshift_enabled() && i + 1 == pairs { - continue; - } - let (lo, hi) = (v_shift[i], v_shift[i + 1]); - cswap(b, s2, lo, hi); - } - } - if std::env::var("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT") - .ok() - .as_deref() - != Some("1") - { - if let Some(scratch) = composite_scratch.as_ref() { - b.free_vec(&scratch.owned); - } - } - } - - b.set_phase("dialog_gcd_compressed_block_tobitvector_compress_block"); - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); - if dialog_gcd_compressed_log_u_high_runway_enabled() { - - assert!( - !dialog_gcd_slice_intersects( - compressed_block, - &u[..dialog_gcd_tobitvector_active_width(start)] - ), - "compressed-log runway overlaps active forward u prefix at block {block}" - ); - } - if dialog_gcd_k5_head11_enabled() - && start == 0 - && block_steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - { - dialog_gcd_k5_head11_compress_raw_to_block(b, compressed_block, raw_block, true); - } else if dialog_gcd_k5_tail6_graph9_enabled() - && block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS - { - dialog_gcd_k5_tail6_graph9_compress_raw_to_block(b, compressed_block, raw_block); - } else if dialog_gcd_k5_tail6_graph_enabled() - && block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS - { - dialog_gcd_k5_tail6_graph_compress_raw_to_block(b, compressed_block, raw_block); - } else if dialog_gcd_k5_tail7_enabled() - && block_steps == 7 - && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS - { - dialog_gcd_k5_tail7_compress_raw_to_block(b, compressed_block, raw_block); - } else if dialog_gcd_k5_tail3_top32_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_top32_compress_raw_to_block( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_tail3_fixed_last_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_compress_raw_to_block( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_tail_pair1_enabled() - && end - start == 2 - && compressed_block.len() == 1 - { - dialog_gcd_k5_tail_pair1_compress_raw_to_block( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_clean_block_enabled() { - if end - start == 5 { - dialog_gcd_k5_compress_raw_to_block(b, compressed_block, raw_block, true); - } else { - dialog_gcd_k5_compress_partial_raw_to_block( - b, - compressed_block, - raw_block, - end - start, - true, - ); - } - } else if dialog_gcd_k2_pair_compress_enabled() { - dialog_gcd_k2_pair_clear_raw_block_copy(b, compressed_block, raw_block, end - start); - } else { - let raw_base = 2 * dialog_gcd_sidecar_group_size(); - emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); - for i in 0..base_bits { - b.swap(raw_block[i], compressed_block[i]); - } - - for j in base_bits..dialog_gcd_block_bits() { - b.swap(raw_block[raw_base + (j - base_bits)], compressed_block[j]); - } - } - if !owned_raw_block.is_empty() { - b.free_vec(&owned_raw_block); - } - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - compressed_log: &[QubitId], - raw_block: &[QubitId], -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert!(raw_block.is_empty() || raw_block.len() == dialog_gcd_raw_block_len()); - assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); - - for block in (0..dialog_gcd_compressed_sidecar_blocks()).rev() { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let block_steps = end - start; - let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); - let hosted_raw_block = dialog_gcd_reverse_raw_block_host(u, compressed_log, block); - let owned_raw_block = - if dialog_gcd_host_reverse_raw_block_enabled() && hosted_raw_block.is_none() { - b.alloc_qubits(dialog_gcd_raw_block_len()) - } else { - Vec::new() - }; - let raw_block = hosted_raw_block.unwrap_or_else(|| { - if owned_raw_block.is_empty() { - raw_block - } else { - &owned_raw_block - } - }); - - b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_decompress_block"); - if dialog_gcd_compressed_log_u_high_runway_enabled() { - - assert!( - !dialog_gcd_slice_intersects( - compressed_block, - &u[..dialog_gcd_tobitvector_active_width(start)] - ), - "compressed-log runway overlaps active reverse u prefix at block {block}" - ); - } - { - let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; - if dialog_gcd_k5_head11_enabled() - && start == 0 - && block_steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() - { - dialog_gcd_k5_head11_decompress_block_to_raw( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_tail6_graph9_enabled() - && block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS - { - dialog_gcd_k5_tail6_graph9_decompress_block_to_raw( - b, - compressed_block, - raw_block, - ); - } else if dialog_gcd_k5_tail6_graph_enabled() - && block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS - { - dialog_gcd_k5_tail6_graph_decompress_block_to_raw( - b, - compressed_block, - raw_block, - ); - } else if dialog_gcd_k5_tail7_enabled() - && block_steps == 7 - && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS - { - dialog_gcd_k5_tail7_decompress_block_to_raw( - b, - compressed_block, - raw_block, - ); - } else if dialog_gcd_k5_tail3_top32_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_top32_decompress_block_to_raw( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_tail3_fixed_last_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() - { - dialog_gcd_k5_tail3_decompress_block_to_raw( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_tail_pair1_enabled() - && end - start == 2 - && compressed_block.len() == 1 - { - dialog_gcd_k5_tail_pair1_decompress_block_to_raw( - b, - compressed_block, - raw_block, - true, - ); - } else if dialog_gcd_k5_clean_block_enabled() { - if end - start == 5 { - dialog_gcd_k5_decompress_block_to_raw(b, compressed_block, raw_block, true); - } else { - dialog_gcd_k5_decompress_partial_block_to_raw( - b, - compressed_block, - raw_block, - end - start, - true, - ); - } - } else if dialog_gcd_k2_pair_compress_enabled() { - dialog_gcd_k2_pair_copy_compressed_block_to_raw( - b, - compressed_block, - raw_block, - end - start, - ); - } else { - let raw_base = 2 * dialog_gcd_sidecar_group_size(); - for i in 0..base_bits { - b.swap(compressed_block[i], raw_block[i]); - } - emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); - - for j in base_bits..dialog_gcd_block_bits() { - b.swap(compressed_block[j], raw_block[raw_base + (j - base_bits)]); - } - } - } - - for step in (start..end).rev() { - let slot = step - start; - if dialog_gcd_k5_constant_tail_stored_steps(block_steps) - .is_some_and(|stored_steps| slot >= stored_steps) - { - let active_width = dialog_gcd_tobitvector_active_width(step); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - let v_shift = &v[..shift_width]; - b.set_phase( - "dialog_gcd_compressed_block_tobitvector_reverse_tail7_constant_unshift", - ); - dialog_gcd_unshift_right_assuming_even(b, v_shift); - dialog_gcd_unshift_right_assuming_even(b, v_shift); - continue; - } - let b0 = raw_block[2 * slot]; - let b0_and_b1 = raw_block[2 * slot + 1]; - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_unshift"); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - let v_shift = &v[..shift_width]; - if dialog_gcd_k2_enabled() { - - let s2 = dialog_gcd_block_raw_s2(raw_block, block_steps, slot); - let pairs = v_shift.len().saturating_sub(1); - for i in (0..pairs).rev() { - if dialog_gcd_skip_zero_edge_tobit_rev_cshift_enabled() && i + 1 == pairs { - continue; - } - let (lo, hi) = (v_shift[i], v_shift[i + 1]); - cswap(b, s2, lo, hi); - } - let v0 = v_active[0]; - if std::env::var("DIALOG_GCD_K2_FORCE0").ok().as_deref() != Some("1") { - b.x(s2); - b.cx(v0, s2); - } - } - dialog_gcd_unshift_right_assuming_even(b, v_shift); - - b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_add"); - let future = dialog_gcd_compressed_sidecar_future_carry_slice( - compressed_log, - step, - active_width, - ); - let composite_scratch = dialog_gcd_composite_scratch_enabled().then(|| { - dialog_gcd_build_composite_scratch( - b, - future, - u, - v, - compressed_log, - raw_block, - active_width, - step, - ) - }); - let borrowed_carries = composite_scratch.as_ref().map_or_else( - || { - dialog_gcd_pick_runway_safe_borrow_slice( - future, - u, - compressed_log, - active_width, - ) - }, - |scratch| Some(scratch.lanes.as_slice()), - ); - dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); - - b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_cswap"); - let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); - for (i, (&ui, &vi)) in u[..cswap_width] - .iter() - .zip(v[..cswap_width].iter()) - .enumerate() - { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_branch_bits"); - if dialog_gcd_reverse_branch_conditional_replay_enabled() { - let phase = b.alloc_bit(); - b.hmr(b0_and_b1, phase); - dialog_gcd_cmp_gt_truncated_phase_conditioned_hosted( - b, - u_active, - v_active, - b0, - phase, - compare_bits, - borrowed_carries, - ); - } else if dialog_gcd_fused_branch_bits_enabled() { - - if dialog_gcd_branch_bits_host_comparator_enabled() { - - dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - borrowed_carries, - ); - } else { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } - } else { - let cmp = b.alloc_qubit(); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.free(cmp); - } - b.cx(v[0], b0); - if let Some(scratch) = composite_scratch { - b.free_vec(&scratch.owned); - } - } - if !owned_raw_block.is_empty() { - b.free_vec(&owned_raw_block); - } - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( - b: &mut B, - compressed_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, - raw_block: &[QubitId], -) { - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - let inplace_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); - if inplace_raw { - assert!(raw_block.is_empty()); - } else { - assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); - } - let inplace_raw0 = if inplace_raw { - Some(b.alloc_qubit()) - } else { - None - }; - - for block in (0..dialog_gcd_compressed_sidecar_blocks()).rev() { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let block_steps = end - start; - let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); - let head11_block = dialog_gcd_k5_head11_enabled() - && start == 0 - && block_steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len(); - let stream_tail3 = dialog_gcd_k5_tail3_top32_stream_apply_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len(); - let split_stream_tail3 = - stream_tail3 && dialog_gcd_k5_tail3_top32_split_slot_apply_enabled(); - - b.set_phase("dialog_gcd_compressed_block_apply_decompress_block"); - let raw_frame = inplace_raw0.map(|raw0| { - dialog_gcd_k2_pair_inplace_decompress_block(b, compressed_block, raw0, end - start) - }); - let stream_head11_pairs = dialog_gcd_k5_head11_stream_pair_apply_enabled() - && raw_frame.is_none() - && head11_block; - let split_head11_pair_shift = stream_head11_pairs - && dialog_gcd_k5_head11_split_pair_shift_apply_enabled(); - let stream_k5_pairs = dialog_gcd_k5_stream_pair_apply_enabled() - && raw_frame.is_none() - && !stream_tail3 - && !head11_block - && block_steps == 5 - && compressed_block.len() == 12; - if stream_head11_pairs { - dialog_gcd_k5_head11_decompress_block_to_data( - b, - compressed_block, - raw_block, - true, - ); - } else if stream_k5_pairs { - dialog_gcd_k5_decompress_block_to_data(b, compressed_block, raw_block, true); - } else if raw_frame.is_none() && !stream_tail3 { - dialog_gcd_copy_compressed_block_to_raw(b, compressed_block, raw_block, end - start); - } - if head11_block && !stream_head11_pairs { - b.free(raw_block[1]); - } - let released_code_bits = if !stream_tail3 - && raw_frame.is_none() - && dialog_gcd_apply_replay_swap_host_enabled() - { - let requested = if (block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS) - || ((dialog_gcd_k5_tail3_fixed_last_enabled() - || dialog_gcd_k5_tail3_top32_enabled()) - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()) - { - dialog_gcd_k5_release_decoded_tail_bits() - } else { - dialog_gcd_k5_release_decoded_block_bits() - }; - requested.min(compressed_block.len()) - } else { - 0 - }; - let retained_code_bits = compressed_block.len() - released_code_bits; - let released_code = &compressed_block[retained_code_bits..]; - b.free_vec(released_code); - let raw = raw_frame.as_ref().map_or(raw_block, |frame| &frame[..]); - if stream_head11_pairs || stream_k5_pairs { - dialog_gcd_k5_stream_pairs_start(b, raw); - } - let stream_clean_scratch = if stream_tail3 { - dialog_gcd_k5_tail3_top32_stream_scratch(raw) - } else { - Vec::new() - }; - let stream_dynamic_raw = if stream_tail3 { - dialog_gcd_k5_tail3_top32_stream_dynamic(raw) - } else { - Vec::new() - }; - if stream_tail3 { - b.free_vec(&stream_dynamic_raw); - } - let scale_release_bits = if stream_tail3 { - 0 - } else { - dialog_gcd_k5_release_scale_bits().min(retained_code_bits) - }; - let scale_released_code = - &compressed_block[retained_code_bits - scale_release_bits..retained_code_bits]; - let shift_clean_code = if stream_tail3 { - stream_clean_scratch.as_slice() - } else { - &compressed_block[..retained_code_bits - scale_release_bits] - }; - let tail_clean_scratch = if dialog_gcd_k5_tail_pair1_enabled() - && end - start == 2 - && compressed_block.len() == 1 - { - raw.iter() - .enumerate() - .filter_map(|(index, &q)| { - (!matches!(index, 0 | 2 | 10 | 11)).then_some(q) - }) - .chain(compressed_block.iter().copied()) - .collect::>() - } else { - Vec::new() - }; - let mut partial_raw_clean_scratch = if stream_tail3 { - Vec::new() - } else { - dialog_gcd_k5_partial_raw_clean_scratch(raw, block_steps) - }; - let partial_release = - dialog_gcd_k5_partial_raw_release_bits().min(partial_raw_clean_scratch.len()); - let released_partial_raw = - partial_raw_clean_scratch.split_off(partial_raw_clean_scratch.len() - partial_release); - b.free_vec(&released_partial_raw); - let mut combined_clean_scratch = Vec::new(); - if stream_tail3 { - combined_clean_scratch.extend_from_slice(&stream_clean_scratch); - } else if !inplace_raw && dialog_gcd_apply_replay_swap_host_enabled() { - combined_clean_scratch.extend_from_slice(&compressed_block[..retained_code_bits]); - combined_clean_scratch.extend_from_slice(&partial_raw_clean_scratch); - } - let block_clean_scratch = if !tail_clean_scratch.is_empty() { - tail_clean_scratch.as_slice() - } else { - combined_clean_scratch.as_slice() - }; - - for step in (start..end).rev() { - let slot = step - start; - let top32_final_s2_const = stream_tail3 - && split_stream_tail3 - && dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() - && slot + 1 == block_steps; - let constant_tail_stored_steps = - dialog_gcd_k5_constant_tail_stored_steps(block_steps); - if constant_tail_stored_steps.is_some_and(|stored_steps| slot >= stored_steps) { - let stored_steps = constant_tail_stored_steps.expect("checked above"); - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_scale_release"); - b.free_vec(scale_released_code); - } - b.set_phase("dialog_gcd_compressed_block_apply_tail7_constant_double_y"); - if dialog_gcd_k5_fixed_tail_apply_enabled() { - dialog_gcd_fixed_double_twice_y(b, y, p); - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); - b.reacquire_vec(scale_released_code); - } - continue; - } - let one = raw[12]; - if slot + 1 == block_steps { - b.x(one); - } - if dialog_gcd_apply_fused_fold_enabled() { - dialog_gcd_fused_double_y_at_step(b, y, p, one, Some(step)); - } else { - mod_double_inplace_fast(b, y, p); - cmod_double_inplace_lazy(b, y, p, one); - } - if slot == stored_steps { - b.x(one); - } - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); - b.reacquire_vec(scale_released_code); - } - continue; - } - if stream_tail3 { - if split_stream_tail3 { - if !top32_final_s2_const { - let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); - b.reacquire_vec(&shift_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } else { - let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); - b.reacquire_vec(&slot_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } - let split_head11_pair_slot = split_head11_pair_shift && slot < 4; - let split_head11_permute_shift = split_head11_pair_slot - && slot == 0 - && dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled(); - let split_head11_borrow_pair23_shift = split_head11_pair_slot - && slot == 2 - && dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled(); - let split_head11_open_for_shift = split_head11_pair_slot - && matches!(slot, 0 | 2) - && !split_head11_permute_shift - && !split_head11_borrow_pair23_shift; - if stream_k5_pairs || (stream_head11_pairs && !split_head11_pair_shift) { - dialog_gcd_k5_stream_pairs_before_slot(b, raw, slot); - } - if split_head11_open_for_shift { - dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); - } - if split_head11_permute_shift { - dialog_gcd_k5_head11_pair01_expose_s2(b, raw); - } - if split_head11_borrow_pair23_shift { - dialog_gcd_k5_head11_pair01_zero_lane(b, raw); - dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); - } - let b0 = raw[2 * slot]; - let b0_and_b1 = if head11_block && slot == 0 { - raw[0] - } else { - raw[2 * slot + 1] - }; - - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_scale_release"); - b.free_vec(scale_released_code); - } - b.set_phase("dialog_gcd_compressed_block_apply_double_y"); - let apply_k2 = dialog_gcd_k2_enabled() - && std::env::var("DIALOG_GCD_K2_NO_APPLY").ok().as_deref() != Some("1"); - let free_clean_code = !inplace_raw - && dialog_gcd_apply_replay_swap_host_enabled() - && dialog_gcd_k5_free_clean_block_during_shift_enabled(); - if free_clean_code { - b.free_vec(shift_clean_code); - } - if top32_final_s2_const && apply_k2 { - dialog_gcd_fixed_double_twice_y(b, y, p); - } else if apply_k2 && dialog_gcd_apply_fused_fold_enabled() { - - let s2 = if split_head11_borrow_pair23_shift { - raw[1] - } else { - dialog_gcd_block_raw_s2(raw, block_steps, slot) - }; - dialog_gcd_fused_double_y_at_step(b, y, p, s2, Some(step)); - } else { - mod_double_inplace_fast(b, y, p); - if apply_k2 { - - let s2 = if split_head11_borrow_pair23_shift { - raw[1] - } else { - dialog_gcd_block_raw_s2(raw, block_steps, slot) - }; - cmod_double_inplace_lazy(b, y, p, s2); - } - } - if free_clean_code { - b.reacquire_vec(shift_clean_code); - } - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); - b.reacquire_vec(scale_released_code); - } - if split_head11_permute_shift { - dialog_gcd_k5_head11_pair01_unexpose_s2(b, raw); - } - if split_head11_borrow_pair23_shift { - dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); - dialog_gcd_k5_head11_pair01_unzero_lane(b, raw); - } - if split_stream_tail3 { - if top32_final_s2_const { - b.reacquire(raw[2 * slot]); - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b, - compressed_block, - raw, - &[2 * slot], - ); - } else { - let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&shift_raw); - let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); - b.reacquire_vec(&branch_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } - if split_head11_pair_slot && !split_head11_open_for_shift { - dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); - } - - b.set_phase("dialog_gcd_compressed_block_apply_cadd"); - if dialog_gcd_raw_apply_materialized_special_add_enabled() { - let owned_clean_scratch = if inplace_raw { - b.alloc_qubits(dialog_gcd_block_bits()) - } else { - Vec::new() - }; - let clean_scratch = if inplace_raw { - owned_clean_scratch.as_slice() - } else { - block_clean_scratch - }; - dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - y, - x, - b0, - p, - clean_scratch, - Some(step), - ); - if inplace_raw { - b.free_vec(&owned_clean_scratch); - } - } else if dialog_gcd_raw_apply_direct_special_add_enabled() { - dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); - } else { - cmod_add_qq_lowq(b, y, x, b0, p); - } - - b.set_phase("dialog_gcd_compressed_block_apply_cswap"); - if !top32_final_s2_const { - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - } - if stream_tail3 { - if split_stream_tail3 { - if top32_final_s2_const { - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b, - compressed_block, - raw, - &[2 * slot], - ); - b.free(raw[2 * slot]); - } else { - let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&branch_raw); - } - } else { - let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&slot_raw); - } - } - if split_head11_pair_slot { - dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); - } else if stream_k5_pairs || stream_head11_pairs { - dialog_gcd_k5_stream_pairs_after_slot_forward(b, raw, slot); - } - } - - if !released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reacquire_block"); - b.reacquire_vec(released_code); - } - if !released_partial_raw.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reacquire_partial_raw"); - b.reacquire_vec(&released_partial_raw); - } - if head11_block && !stream_head11_pairs { - b.reacquire(raw_block[1]); - } - b.set_phase("dialog_gcd_compressed_block_apply_clear_block_copy"); - if stream_tail3 { - b.reacquire_vec(&stream_dynamic_raw); - } else if stream_head11_pairs { - dialog_gcd_k5_stream_pairs_finish(b, raw_block); - dialog_gcd_k5_head11_compress_data_to_block( - b, - compressed_block, - raw_block, - true, - ); - } else if stream_k5_pairs { - dialog_gcd_k5_stream_pairs_finish(b, raw_block); - dialog_gcd_k5_compress_data_to_block(b, compressed_block, raw_block, true); - } else if let Some(raw0) = inplace_raw0 { - dialog_gcd_k2_pair_inplace_clear_block(b, compressed_block, raw0, end - start); - } else { - dialog_gcd_clear_raw_block_copy(b, compressed_block, raw_block, end - start); - } - } - - if let Some(raw0) = inplace_raw0 { - b.free(raw0); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( - b: &mut B, - compressed_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, - raw_block: &[QubitId], -) { - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - let inplace_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); - if inplace_raw { - assert!(raw_block.is_empty()); - } else { - assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); - } - let inplace_raw0 = if inplace_raw { - Some(b.alloc_qubit()) - } else { - None - }; - - for block in 0..dialog_gcd_compressed_sidecar_blocks() { - let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); - let block_steps = end - start; - let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); - let head11_block = dialog_gcd_k5_head11_enabled() - && start == 0 - && block_steps == 5 - && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len(); - let stream_tail3 = dialog_gcd_k5_tail3_top32_stream_apply_enabled() - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len(); - let split_stream_tail3 = - stream_tail3 && dialog_gcd_k5_tail3_top32_split_slot_apply_enabled(); - - b.set_phase("dialog_gcd_compressed_block_apply_reverse_decompress_block"); - let raw_frame = inplace_raw0.map(|raw0| { - dialog_gcd_k2_pair_inplace_decompress_block(b, compressed_block, raw0, end - start) - }); - let stream_head11_pairs = dialog_gcd_k5_head11_stream_pair_apply_enabled() - && raw_frame.is_none() - && head11_block; - let split_head11_pair_shift = stream_head11_pairs - && dialog_gcd_k5_head11_split_pair_shift_apply_enabled(); - let stream_k5_pairs = dialog_gcd_k5_stream_pair_apply_enabled() - && raw_frame.is_none() - && !stream_tail3 - && !head11_block - && block_steps == 5 - && compressed_block.len() == 12; - if stream_head11_pairs { - dialog_gcd_k5_head11_decompress_block_to_data( - b, - compressed_block, - raw_block, - true, - ); - } else if stream_k5_pairs { - dialog_gcd_k5_decompress_block_to_data(b, compressed_block, raw_block, true); - } else if raw_frame.is_none() && !stream_tail3 { - dialog_gcd_copy_compressed_block_to_raw(b, compressed_block, raw_block, end - start); - } - if head11_block && !stream_head11_pairs { - b.free(raw_block[1]); - } - let released_code_bits = if !stream_tail3 - && raw_frame.is_none() - && dialog_gcd_apply_replay_swap_host_enabled() - { - let requested = if (block_steps == 6 - && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS) - || ((dialog_gcd_k5_tail3_fixed_last_enabled() - || dialog_gcd_k5_tail3_top32_enabled()) - && block_steps == 3 - && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()) - { - dialog_gcd_k5_release_decoded_tail_bits() - } else { - dialog_gcd_k5_release_decoded_block_bits() - }; - requested.min(compressed_block.len()) - } else { - 0 - }; - let retained_code_bits = compressed_block.len() - released_code_bits; - let released_code = &compressed_block[retained_code_bits..]; - b.free_vec(released_code); - let raw = raw_frame.as_ref().map_or(raw_block, |frame| &frame[..]); - if stream_head11_pairs || stream_k5_pairs { - dialog_gcd_k5_stream_pairs_start(b, raw); - } - let stream_clean_scratch = if stream_tail3 { - dialog_gcd_k5_tail3_top32_stream_scratch(raw) - } else { - Vec::new() - }; - let stream_dynamic_raw = if stream_tail3 { - dialog_gcd_k5_tail3_top32_stream_dynamic(raw) - } else { - Vec::new() - }; - if stream_tail3 { - b.free_vec(&stream_dynamic_raw); - } - let scale_release_bits = if stream_tail3 { - 0 - } else { - dialog_gcd_k5_release_scale_bits().min(retained_code_bits) - }; - let scale_released_code = - &compressed_block[retained_code_bits - scale_release_bits..retained_code_bits]; - let shift_clean_code = if stream_tail3 { - stream_clean_scratch.as_slice() - } else { - &compressed_block[..retained_code_bits - scale_release_bits] - }; - let tail_clean_scratch = if dialog_gcd_k5_tail_pair1_enabled() - && end - start == 2 - && compressed_block.len() == 1 - { - raw.iter() - .enumerate() - .filter_map(|(index, &q)| { - (!matches!(index, 0 | 2 | 10 | 11)).then_some(q) - }) - .chain(compressed_block.iter().copied()) - .collect::>() - } else { - Vec::new() - }; - let mut partial_raw_clean_scratch = if stream_tail3 { - Vec::new() - } else { - dialog_gcd_k5_partial_raw_clean_scratch(raw, block_steps) - }; - let partial_release = - dialog_gcd_k5_partial_raw_release_bits().min(partial_raw_clean_scratch.len()); - let released_partial_raw = - partial_raw_clean_scratch.split_off(partial_raw_clean_scratch.len() - partial_release); - b.free_vec(&released_partial_raw); - let mut combined_clean_scratch = Vec::new(); - if stream_tail3 { - combined_clean_scratch.extend_from_slice(&stream_clean_scratch); - } else if !inplace_raw && dialog_gcd_apply_replay_swap_host_enabled() { - combined_clean_scratch.extend_from_slice(&compressed_block[..retained_code_bits]); - combined_clean_scratch.extend_from_slice(&partial_raw_clean_scratch); - } - let block_clean_scratch = if !tail_clean_scratch.is_empty() { - tail_clean_scratch.as_slice() - } else { - combined_clean_scratch.as_slice() - }; - - for step in start..end { - let slot = step - start; - let top32_final_s2_const = stream_tail3 - && split_stream_tail3 - && dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() - && slot + 1 == block_steps; - let constant_tail_stored_steps = - dialog_gcd_k5_constant_tail_stored_steps(block_steps); - if constant_tail_stored_steps.is_some_and(|stored_steps| slot >= stored_steps) { - let stored_steps = constant_tail_stored_steps.expect("checked above"); - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_release"); - b.free_vec(scale_released_code); - } - b.set_phase( - "dialog_gcd_compressed_block_apply_reverse_tail7_constant_halve_y", - ); - if dialog_gcd_k5_fixed_tail_apply_enabled() { - dialog_gcd_fixed_halve_twice_y(b, y, p); - if !scale_released_code.is_empty() { - b.set_phase( - "dialog_gcd_compressed_block_apply_reverse_scale_reacquire", - ); - b.reacquire_vec(scale_released_code); - } - continue; - } - let one = raw[12]; - if slot == stored_steps { - b.x(one); - } - if dialog_gcd_apply_fused_fold_enabled() - && std::env::var("DIALOG_GCD_FUSE_HALVE_OFF").ok().as_deref() != Some("1") - { - dialog_gcd_fused_halve_y_at_step(b, y, p, one, Some(step)); - } else { - mod_halve_inplace_fast(b, y, p); - cmod_halve_inplace_lazy(b, y, p, one); - } - if slot + 1 == block_steps { - b.x(one); - } - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_reacquire"); - b.reacquire_vec(scale_released_code); - } - continue; - } - if stream_tail3 { - if split_stream_tail3 { - if top32_final_s2_const { - b.reacquire(raw[2 * slot]); - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b, - compressed_block, - raw, - &[2 * slot], - ); - } else { - let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); - b.reacquire_vec(&branch_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } else { - let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); - b.reacquire_vec(&slot_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } - let split_head11_pair_slot = split_head11_pair_shift && slot < 4; - let split_head11_permute_shift = split_head11_pair_slot - && slot == 0 - && dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled(); - let split_head11_borrow_pair23_shift = split_head11_pair_slot - && slot == 2 - && dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled(); - let split_head11_keep_open_for_shift = split_head11_pair_slot - && matches!(slot, 0 | 2) - && !split_head11_permute_shift - && !split_head11_borrow_pair23_shift; - if stream_k5_pairs || (stream_head11_pairs && !split_head11_pair_shift) { - dialog_gcd_k5_stream_pairs_before_slot_reverse(b, raw, slot); - } - if split_head11_pair_slot { - dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); - } - let b0 = raw[2 * slot]; - let b0_and_b1 = if head11_block && slot == 0 { - raw[0] - } else { - raw[2 * slot + 1] - }; - - b.set_phase("dialog_gcd_compressed_block_apply_reverse_cswap"); - if !top32_final_s2_const { - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - } - - b.set_phase("dialog_gcd_compressed_block_apply_reverse_csub"); - if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { - let owned_clean_scratch = if inplace_raw { - b.alloc_qubits(dialog_gcd_block_bits()) - } else { - Vec::new() - }; - let clean_scratch = if inplace_raw { - owned_clean_scratch.as_slice() - } else { - block_clean_scratch - }; - dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - y, - x, - b0, - p, - clean_scratch, - Some(step), - ); - if inplace_raw { - b.free_vec(&owned_clean_scratch); - } - } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { - cmod_sub_qq(b, y, x, b0, p); - } else { - cmod_sub_qq_lowq(b, y, x, b0, p); - } - if split_head11_pair_slot && !split_head11_keep_open_for_shift { - dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); - } - if split_head11_permute_shift { - dialog_gcd_k5_head11_pair01_expose_s2(b, raw); - } - if split_head11_borrow_pair23_shift { - dialog_gcd_k5_head11_pair01_zero_lane(b, raw); - dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); - } - if split_stream_tail3 { - if top32_final_s2_const { - dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( - b, - compressed_block, - raw, - &[2 * slot], - ); - b.free(raw[2 * slot]); - } else { - let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&branch_raw); - let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); - b.reacquire_vec(&shift_raw); - dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( - b, - compressed_block, - raw, - slot, - ); - } - } - - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_release"); - b.free_vec(scale_released_code); - } - b.set_phase("dialog_gcd_compressed_block_apply_reverse_halve_y"); - let apply_k2 = dialog_gcd_k2_enabled() - && std::env::var("DIALOG_GCD_K2_NO_APPLY").ok().as_deref() != Some("1"); - let free_clean_code = !inplace_raw - && dialog_gcd_apply_replay_swap_host_enabled() - && dialog_gcd_k5_free_clean_block_during_shift_enabled(); - if free_clean_code { - b.free_vec(shift_clean_code); - } - if top32_final_s2_const && apply_k2 { - dialog_gcd_fixed_halve_twice_y(b, y, p); - } else if apply_k2 - && dialog_gcd_apply_fused_fold_enabled() - && std::env::var("DIALOG_GCD_FUSE_HALVE_OFF").ok().as_deref() != Some("1") - { - - let s2 = if split_head11_borrow_pair23_shift { - raw[1] - } else { - dialog_gcd_block_raw_s2(raw, block_steps, slot) - }; - dialog_gcd_fused_halve_y_at_step(b, y, p, s2, Some(step)); - } else { - mod_halve_inplace_fast(b, y, p); - if apply_k2 { - - let s2 = if split_head11_borrow_pair23_shift { - raw[1] - } else { - dialog_gcd_block_raw_s2(raw, block_steps, slot) - }; - cmod_halve_inplace_lazy(b, y, p, s2); - } - } - if free_clean_code { - b.reacquire_vec(shift_clean_code); - } - if !scale_released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_reacquire"); - b.reacquire_vec(scale_released_code); - } - if split_head11_borrow_pair23_shift { - dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); - dialog_gcd_k5_head11_pair01_unzero_lane(b, raw); - } - if split_head11_keep_open_for_shift { - dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); - } else if split_head11_permute_shift { - dialog_gcd_k5_head11_pair01_unexpose_s2(b, raw); - } else if !split_head11_pair_slot && (stream_k5_pairs || stream_head11_pairs) { - dialog_gcd_k5_stream_pairs_after_slot_reverse(b, raw, slot); - } - if stream_tail3 { - if split_stream_tail3 { - if !top32_final_s2_const { - let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&shift_raw); - } - } else { - let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); - dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( - b, - compressed_block, - raw, - slot, - ); - b.free_vec(&slot_raw); - } - } - } - - if !released_code.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_reacquire_block"); - b.reacquire_vec(released_code); - } - if !released_partial_raw.is_empty() { - b.set_phase("dialog_gcd_compressed_block_apply_reverse_reacquire_partial_raw"); - b.reacquire_vec(&released_partial_raw); - } - if head11_block && !stream_head11_pairs { - b.reacquire(raw_block[1]); - } - b.set_phase("dialog_gcd_compressed_block_apply_reverse_clear_block_copy"); - if stream_tail3 { - b.reacquire_vec(&stream_dynamic_raw); - } else if stream_head11_pairs { - dialog_gcd_k5_stream_pairs_finish(b, raw_block); - dialog_gcd_k5_head11_compress_data_to_block( - b, - compressed_block, - raw_block, - true, - ); - } else if stream_k5_pairs { - dialog_gcd_k5_stream_pairs_finish(b, raw_block); - dialog_gcd_k5_compress_data_to_block(b, compressed_block, raw_block, true); - } else if let Some(raw0) = inplace_raw0 { - dialog_gcd_k2_pair_inplace_clear_block(b, compressed_block, raw0, end - start); - } else { - dialog_gcd_clear_raw_block_copy(b, compressed_block, raw_block, end - start); - } - } - - if let Some(raw0) = inplace_raw0 { - b.free(raw0); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - compressed_log: &[QubitId], - pair: &[QubitId], - scratch: QubitId, -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert_eq!(pair.len(), 2); - assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); - - for step in 0..dialog_gcd_active_iterations() { - let b0 = pair[0]; - let b0_and_b1 = pair[1]; - let cmp = b.alloc_qubit(); - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_branch_bits"); - b.cx(v[0], b0); - if dialog_gcd_fused_branch_bits_enabled() { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } else { - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - } - b.free(cmp); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_cswap"); - let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); - for (i, (&ui, &vi)) in u[..cswap_width] - .iter() - .zip(v[..cswap_width].iter()) - .enumerate() - { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_subtract"); - let borrowed_carries = - dialog_gcd_compressed_sidecar_future_carry_slice(compressed_log, step, active_width); - dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_shift"); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - dialog_gcd_shift_right_assuming_even(b, &v[..shift_width]); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_absorb_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - compressed_log: &[QubitId], - pair: &[QubitId], - scratch: QubitId, -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert_eq!(pair.len(), 2); - assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); - - for step in (0..dialog_gcd_active_iterations()).rev() { - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_load_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - - let b0 = pair[0]; - let b0_and_b1 = pair[1]; - let cmp = b.alloc_qubit(); - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_unshift"); - let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); - dialog_gcd_unshift_right_assuming_even(b, &v[..shift_width]); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_add"); - let borrowed_carries = - dialog_gcd_compressed_sidecar_future_carry_slice(compressed_log, step, active_width); - dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_cswap"); - let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); - for (i, (&ui, &vi)) in u[..cswap_width] - .iter() - .zip(v[..cswap_width].iter()) - .enumerate() - { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_branch_bits"); - if dialog_gcd_fused_branch_bits_enabled() { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } else { - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - } - b.free(cmp); - b.cx(v[0], b0); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector( - b: &mut B, - compressed_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, - pair: &[QubitId], - scratch: QubitId, -) { - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - assert_eq!(pair.len(), 2); - - for step in (0..dialog_gcd_active_iterations()).rev() { - b.set_phase("dialog_gcd_compressed_sidecar_apply_load_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - - let b0 = pair[0]; - let b0_and_b1 = pair[1]; - - b.set_phase("dialog_gcd_compressed_sidecar_apply_double_y"); - mod_double_inplace_fast(b, y, p); - - b.set_phase("dialog_gcd_compressed_sidecar_apply_cadd"); - if dialog_gcd_raw_apply_materialized_special_add_enabled() { - dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); - } else if dialog_gcd_raw_apply_direct_special_add_enabled() { - dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); - } else { - cmod_add_qq_lowq(b, y, x, b0, p); - } - - b.set_phase("dialog_gcd_compressed_sidecar_apply_cswap"); - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - - b.set_phase("dialog_gcd_compressed_sidecar_apply_unload_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( - b: &mut B, - compressed_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, - pair: &[QubitId], - scratch: QubitId, -) { - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - assert_eq!(pair.len(), 2); - - for step in 0..dialog_gcd_active_iterations() { - b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_load_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - - let b0 = pair[0]; - let b0_and_b1 = pair[1]; - - b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_cswap"); - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - - b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_csub"); - if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { - dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); - } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { - cmod_sub_qq(b, y, x, b0, p); - } else { - cmod_sub_qq_lowq(b, y, x, b0, p); - } - - b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_halve_y"); - mod_halve_inplace_fast(b, y, p); - - b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_unload_pair"); - let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); - emit_dialog_gcd_round763_compressed_block_swapper( - b, - pair, - block, - scratch, - step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, - ); - } -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_ipmul_block_lifecycle( - b: &mut B, - factor: &[QubitId], - target: &[QubitId], - p: U256, -) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - let compressed_log = b.alloc_qubits(dialog_gcd_allocated_compressed_sidecar_bits()); - let raw_block = if dialog_gcd_host_reverse_raw_block_enabled() { - Vec::new() - } else { - b.alloc_qubits(dialog_gcd_raw_block_len()) - }; - let u = b.alloc_qubits(N); - let runway = dialog_gcd_build_compressed_log_u_high_runway(&u, &compressed_log); - let replay_log = runway - .as_ref() - .map_or(compressed_log.as_slice(), |r| r.remapped_log.as_slice()); - b.set_phase("dialog_gcd_compressed_block_ipmul_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_compressed_block_ipmul_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_compressed_block_ipmul_release_terminal_u"); - b.x(u[0]); - dialog_gcd_release_terminal_u(b, &u, runway.as_ref()); - - b.set_phase("dialog_gcd_compressed_block_ipmul_apply_bitvector_reuse_factor_zero"); - let inplace_apply_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); - if inplace_apply_raw && !raw_block.is_empty() { - b.free_vec(&raw_block); - } - let apply_raw_block = if !inplace_apply_raw && dialog_gcd_host_reverse_raw_block_enabled() { - b.alloc_qubits(dialog_gcd_raw_block_len()) - } else { - Vec::new() - }; - emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( - b, - replay_log, - target, - factor, - p, - if inplace_apply_raw { - &[] - } else if apply_raw_block.is_empty() { - &raw_block - } else { - &apply_raw_block - }, - ); - if !apply_raw_block.is_empty() { - b.free_vec(&apply_raw_block); - } - - if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { - b.set_phase("dialog_gcd_compressed_block_ipmul_clear_p_residual_source_lane"); - for i in 0..N { - if bit(p, i) { - b.x(target[i]); - } - } - } - - b.set_phase("dialog_gcd_compressed_block_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - if inplace_apply_raw && !raw_block.is_empty() { - b.reacquire_vec(&raw_block); - } - - b.set_phase("dialog_gcd_compressed_block_ipmul_reacquire_terminal_u"); - dialog_gcd_reacquire_terminal_u(b, &u, runway.as_ref()); - b.set_phase("dialog_gcd_compressed_block_ipmul_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_compressed_block_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - if !b.k2_shift2_log.is_empty() { - let log = std::mem::take(&mut b.k2_shift2_log); - b.free_vec(&log); - } - b.free_vec(&u); - if !raw_block.is_empty() { - b.free_vec(&raw_block); - } - b.free_vec(&compressed_log); - return; - } - - let tmp = b.alloc_qubits(N); - b.set_phase("dialog_gcd_compressed_block_ipmul_apply_bitvector"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( - b, replay_log, target, &tmp, p, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], tmp[i]); - } - - b.set_phase("dialog_gcd_compressed_block_ipmul_free_zero_tmp"); - b.free_vec(&tmp); - - b.set_phase("dialog_gcd_compressed_block_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - if !b.k2_shift2_log.is_empty() { - let log = std::mem::take(&mut b.k2_shift2_log); - b.free_vec(&log); - } - b.free_vec(&u); - b.free_vec(&raw_block); - b.free_vec(&compressed_log); -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_ipmul( - b: &mut B, - factor: &[QubitId], - target: &[QubitId], - p: U256, -) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - if dialog_gcd_compressed_block_lifecycle_enabled() { - emit_dialog_gcd_compressed_sidecar_ipmul_block_lifecycle(b, factor, target, p); - return; - } - - let compressed_log = b.alloc_qubits(dialog_gcd_compressed_sidecar_bits()); - let pair = b.alloc_qubits(2); - let compressor_scratch = b.alloc_qubit(); - let u = b.alloc_qubits(N); - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_release_terminal_u"); - b.x(u[0]); - b.free_vec(&u); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_apply_bitvector_reuse_factor_zero"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector( - b, - &compressed_log, - target, - factor, - p, - &pair, - compressor_scratch, - ); - - if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_clear_p_residual_source_lane"); - for i in 0..N { - if bit(p, i) { - b.x(target[i]); - } - } - } - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_reacquire_terminal_u"); - b.reacquire_vec(&u); - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free(compressor_scratch); - b.free_vec(&pair); - b.free_vec(&compressed_log); - return; - } - - let tmp = b.alloc_qubits(N); - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_apply_bitvector"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector( - b, - &compressed_log, - target, - &tmp, - p, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], tmp[i]); - } - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_free_zero_tmp"); - b.free_vec(&tmp); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free(compressor_scratch); - b.free_vec(&pair); - b.free_vec(&compressed_log); -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_quotient_block_lifecycle( - b: &mut B, - factor: &[QubitId], - target: &[QubitId], - p: U256, -) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - let compressed_log = b.alloc_qubits(dialog_gcd_allocated_compressed_sidecar_bits()); - let raw_block = if dialog_gcd_host_reverse_raw_block_enabled() { - Vec::new() - } else { - b.alloc_qubits(dialog_gcd_raw_block_len()) - }; - let u = b.alloc_qubits(N); - let runway = dialog_gcd_build_compressed_log_u_high_runway(&u, &compressed_log); - let replay_log = runway - .as_ref() - .map_or(compressed_log.as_slice(), |r| r.remapped_log.as_slice()); - b.set_phase("dialog_gcd_compressed_block_quotient_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_compressed_block_quotient_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - if dialog_gcd_raw_quotient_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_compressed_block_quotient_release_terminal_u"); - b.x(u[0]); - dialog_gcd_release_terminal_u(b, &u, runway.as_ref()); - - b.set_phase("dialog_gcd_compressed_block_quotient_apply_reverse_reuse_factor_zero"); - let inplace_apply_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); - if inplace_apply_raw && !raw_block.is_empty() { - b.free_vec(&raw_block); - } - let apply_raw_block = if !inplace_apply_raw && dialog_gcd_host_reverse_raw_block_enabled() { - b.alloc_qubits(dialog_gcd_raw_block_len()) - } else { - Vec::new() - }; - emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( - b, - replay_log, - factor, - target, - p, - if inplace_apply_raw { - &[] - } else if apply_raw_block.is_empty() { - &raw_block - } else { - &apply_raw_block - }, - ); - if !apply_raw_block.is_empty() { - b.free_vec(&apply_raw_block); - } - - b.set_phase("dialog_gcd_compressed_block_quotient_swap_quotient_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - if inplace_apply_raw && !raw_block.is_empty() { - b.reacquire_vec(&raw_block); - } - - b.set_phase("dialog_gcd_compressed_block_quotient_reacquire_terminal_u"); - dialog_gcd_reacquire_terminal_u(b, &u, runway.as_ref()); - b.set_phase("dialog_gcd_compressed_block_quotient_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_compressed_block_quotient_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - if !b.k2_shift2_log.is_empty() { - let log = std::mem::take(&mut b.k2_shift2_log); - b.free_vec(&log); - } - b.free_vec(&u); - if !raw_block.is_empty() { - b.free_vec(&raw_block); - } - b.free_vec(&compressed_log); - return; - } - - b.set_phase("dialog_gcd_compressed_block_quotient_apply_reverse"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( - b, replay_log, factor, target, p, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_quotient_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( - b, &u, factor, replay_log, &raw_block, - ); - - b.set_phase("dialog_gcd_compressed_block_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - if !b.k2_shift2_log.is_empty() { - let log = std::mem::take(&mut b.k2_shift2_log); - b.free_vec(&log); - } - b.free_vec(&u); - b.free_vec(&raw_block); - b.free_vec(&compressed_log); -} - -pub(crate) fn emit_dialog_gcd_compressed_sidecar_quotient( - b: &mut B, - factor: &[QubitId], - target: &[QubitId], - p: U256, -) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - if dialog_gcd_compressed_block_lifecycle_enabled() { - emit_dialog_gcd_compressed_sidecar_quotient_block_lifecycle(b, factor, target, p); - return; - } - - let compressed_log = b.alloc_qubits(dialog_gcd_compressed_sidecar_bits()); - let pair = b.alloc_qubits(2); - let compressor_scratch = b.alloc_qubit(); - let u = b.alloc_qubits(N); - b.set_phase("dialog_gcd_compressed_sidecar_quotient_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - if dialog_gcd_raw_quotient_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_compressed_sidecar_quotient_release_terminal_u"); - b.x(u[0]); - b.free_vec(&u); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_apply_reverse_reuse_factor_zero"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( - b, - &compressed_log, - factor, - target, - p, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_swap_quotient_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_reacquire_terminal_u"); - b.reacquire_vec(&u); - b.set_phase("dialog_gcd_compressed_sidecar_quotient_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free(compressor_scratch); - b.free_vec(&pair); - b.free_vec(&compressed_log); - return; - } - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_apply_reverse"); - emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( - b, - &compressed_log, - factor, - target, - p, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_uncompute_tobitvector"); - emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( - b, - &u, - factor, - &compressed_log, - &pair, - compressor_scratch, - ); - - b.set_phase("dialog_gcd_compressed_sidecar_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free(compressor_scratch); - b.free_vec(&pair); - b.free_vec(&compressed_log); -} - -pub(crate) fn emit_dialog_gcd_k2_pair_core_encoder(b: &mut B, core: &[QubitId]) { - assert_eq!(core.len(), 5); - - b.cx(core[1], core[2]); - b.cx(core[0], core[4]); - b.x(core[3]); - b.ccx(core[2], core[3], core[1]); - b.cx(core[3], core[4]); - b.ccx(core[3], core[4], core[0]); - b.cx(core[2], core[4]); - b.cx(core[0], core[3]); - b.cx(core[3], core[2]); - b.cx(core[3], core[4]); - b.ccx(core[1], core[3], core[0]); - b.cx(core[1], core[0]); - b.cx(core[3], core[0]); -} - -pub(crate) fn emit_dialog_gcd_k2_pair_core_encoder_inverse(b: &mut B, core: &[QubitId]) { - assert_eq!(core.len(), 5); - - b.cx(core[3], core[0]); - b.cx(core[1], core[0]); - b.ccx(core[1], core[3], core[0]); - b.cx(core[3], core[4]); - b.cx(core[3], core[2]); - b.cx(core[0], core[3]); - b.cx(core[2], core[4]); - b.ccx(core[3], core[4], core[0]); - b.cx(core[3], core[4]); - b.ccx(core[2], core[3], core[1]); - b.x(core[3]); - b.cx(core[0], core[4]); - b.cx(core[1], core[2]); -} - -pub(crate) fn dialog_gcd_k2_pair_core(raw_block: &[QubitId]) -> [QubitId; 5] { - assert_eq!(raw_block.len(), 6); - [ - raw_block[0], - raw_block[1], - raw_block[4], - raw_block[2], - raw_block[3], - ] -} - -pub(crate) fn dialog_gcd_k2_pair_copy_compressed_block_to_raw( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); - assert_eq!(raw_block.len(), 6); - assert!((1..=2).contains(&steps)); - let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); - if steps == 1 { - let raw_encoded = [raw_block[0], raw_block[1], raw_block[4]]; - for (&c, &r) in compressed_block.iter().take(3).zip(raw_encoded.iter()) { - if swap_host { - b.swap(c, r); - } else { - b.cx(c, r); - } - } - return; - } - let raw_encoded = [raw_block[1], raw_block[4], raw_block[2], raw_block[3], raw_block[5]]; - for (&c, &r) in compressed_block.iter().zip(raw_encoded.iter()) { - if swap_host { - b.swap(c, r); - } else { - b.cx(c, r); - } - } - let core = dialog_gcd_k2_pair_core(raw_block); - emit_dialog_gcd_k2_pair_core_encoder_inverse(b, &core); -} - -pub(crate) fn dialog_gcd_k2_pair_clear_raw_block_copy( - b: &mut B, - compressed_block: &[QubitId], - raw_block: &[QubitId], - steps: usize, -) { - assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); - assert_eq!(raw_block.len(), 6); - assert!((1..=2).contains(&steps)); - let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); - if steps == 1 { - let raw_encoded = [raw_block[0], raw_block[1], raw_block[4]]; - for (&c, &r) in compressed_block.iter().take(3).zip(raw_encoded.iter()) { - if swap_host { - b.swap(c, r); - } else { - b.cx(c, r); - } - } - return; - } - let core = dialog_gcd_k2_pair_core(raw_block); - emit_dialog_gcd_k2_pair_core_encoder(b, &core); - let raw_encoded = [raw_block[1], raw_block[4], raw_block[2], raw_block[3], raw_block[5]]; - for (&c, &r) in compressed_block.iter().zip(raw_encoded.iter()) { - if swap_host { - b.swap(c, r); - } else { - b.cx(c, r); - } - } -} - -fn dialog_gcd_fixed_twice_fold( - b: &mut B, - y: &[QubitId], - p: U256, - e: QubitId, - d: QubitId, - is_add: bool, -) { - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - let h = b.alloc_qubit(); - b.ccx(e, d, h); - let xed = b.alloc_qubit(); - b.cx(e, xed); - b.cx(d, xed); - let eord = b.alloc_qubit(); - b.cx(xed, eord); - b.cx(h, eord); - let n10 = b.alloc_qubit(); - b.cx(d, n10); - b.cx(h, n10); - - let hi_c = highest_set_bit(c); - let hi_delta = hi_c + 1; - let controls = secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); - let last = match fold_only_carry_trunc_window().or_else(double_carry_trunc_window) { - Some(w) => core::cmp::min(y.len() - 2, hi_delta.saturating_add(w)), - None => y.len() - 2, - }; - if fold_freed_tail_enabled() && last > hi_delta { - fold_ripple_freed_tail(b, y, e, d, h, xed, eord, n10, last, is_add); - } else if is_add { - cadd_per_position_controls_trunc(b, y, &controls, last); - } else { - csub_per_position_controls_trunc(b, y, &controls, last); - } - - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(n10); - b.free(eord); - b.free(xed); - if dialog_gcd_fused_hclear_measured_enabled() { - let measured = b.alloc_bit(); - b.hmr(h, measured); - b.cz_if(e, d, measured); - } else { - b.ccx(e, d, h); - } - b.free(h); -} - -fn dialog_gcd_fixed_double_twice_y(b: &mut B, y: &[QubitId], p: U256) { - let n = y.len(); - debug_assert_eq!(n, 256); - let ovf1 = b.alloc_qubit(); - b.swap(y[n - 1], ovf1); - for i in (0..n - 1).rev() { - b.swap(y[i], y[i + 1]); - } - let ovf2 = b.alloc_qubit(); - b.swap(y[n - 1], ovf2); - for i in (0..n - 1).rev() { - b.swap(y[i], y[i + 1]); - } - - dialog_gcd_fixed_twice_fold(b, y, p, ovf2, ovf1, true); - b.cx(y[0], ovf2); - b.cx(y[1], ovf1); - b.free(ovf2); - b.free(ovf1); -} - -fn dialog_gcd_fixed_halve_twice_y(b: &mut B, y: &[QubitId], p: U256) { - let n = y.len(); - debug_assert_eq!(n, 256); - let ovf2 = b.alloc_qubit(); - let ovf1 = b.alloc_qubit(); - b.cx(y[0], ovf2); - b.cx(y[1], ovf1); - - dialog_gcd_fixed_twice_fold(b, y, p, ovf2, ovf1, false); - for i in 0..n - 1 { - b.swap(y[i], y[i + 1]); - } - b.swap(y[n - 1], ovf2); - b.free(ovf2); - for i in 0..n - 1 { - b.swap(y[i], y[i + 1]); - } - b.swap(y[n - 1], ovf1); - b.free(ovf1); -} - -pub(crate) fn dialog_gcd_k5_tail7_fixed_apply_selftest() -> Result<(), String> { - use sha3::digest::{ExtendableOutput, Update}; - - let input_masks = (0..N) - .map(|bit| { - let x = (bit as u64) - .wrapping_mul(0x9E37_79B9_7F4A_7C15) - .wrapping_add(0xD1B5_4A32_D192_ED03); - let x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); - x ^ (x >> 27) - }) - .collect::>(); - - for reverse in [false, true] { - let build_one = |fixed: bool| { - let mut b = B::new(); - let y = b.alloc_qubits(N); - if fixed { - if reverse { - dialog_gcd_fixed_halve_twice_y(&mut b, &y, SECP256K1_P); - } else { - dialog_gcd_fixed_double_twice_y(&mut b, &y, SECP256K1_P); - } - } else { - let one = b.alloc_qubit(); - b.x(one); - if reverse { - dialog_gcd_fused_halve_y(&mut b, &y, SECP256K1_P, one); - } else { - dialog_gcd_fused_double_y(&mut b, &y, SECP256K1_P, one); - } - b.x(one); - b.free(one); - } - (b.ops, y, b.next_qubit as usize, b.next_bit as usize) - }; - - let run = |fixed: bool| { - let (ops, y, num_qubits, num_bits) = build_one(fixed); - let mut seed = sha3::Shake128::default(); - seed.update(b"dialog-gcd-k5-tail7-fixed-apply-selftest"); - seed.update(&[reverse as u8, fixed as u8]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); - sim.clear_for_shot(); - for (&q, &mask) in y.iter().zip(input_masks.iter()) { - *sim.qubit_mut(q) = mask; - } - sim.apply_iter(ops.iter()); - let output = y.iter().map(|&q| sim.qubit(q)).collect::>(); - let clean = (N..num_qubits).all(|q| sim.qubit(QubitId(q as u64)) == 0); - (output, clean, sim.phase) - }; - - let (baseline, baseline_clean, baseline_phase) = run(false); - let (fixed, fixed_clean, fixed_phase) = run(true); - if !baseline_clean || baseline_phase != 0 { - return Err(format!( - "baseline dirty: reverse={reverse} clean={baseline_clean} phase=0x{baseline_phase:x}" - )); - } - if !fixed_clean || fixed_phase != 0 { - return Err(format!( - "fixed dirty: reverse={reverse} clean={fixed_clean} phase=0x{fixed_phase:x}" - )); - } - if baseline != fixed { - let bit = baseline - .iter() - .zip(fixed.iter()) - .position(|(a, b)| a != b) - .expect("different vectors have a differing bit"); - return Err(format!( - "value mismatch: reverse={reverse} bit={bit} baseline=0x{:x} fixed=0x{:x}", - baseline[bit], fixed[bit] - )); - } - } - Ok(()) -} - -pub(crate) fn dialog_gcd_fused_double_y(b: &mut B, y: &[QubitId], p: U256, s2: QubitId) { - dialog_gcd_fused_double_y_at_step(b, y, p, s2, None); -} - -pub(crate) fn dialog_gcd_fused_double_y_at_step( - b: &mut B, - y: &[QubitId], - p: U256, - s2: QubitId, - step: Option, -) { - let n = y.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let ovf1 = b.alloc_qubit(); - b.swap(y[n - 1], ovf1); - for i in (0..n - 1).rev() { - b.swap(y[i], y[i + 1]); - } - - let ovf2 = b.alloc_qubit(); - cswap(b, s2, y[n - 1], ovf2); - for i in (0..n - 1).rev() { - if dialog_gcd_skip_zero_edge_apply_double_cshift_enabled() && i == 0 { - continue; - } - cswap(b, s2, y[i], y[i + 1]); - } - - let e = b.alloc_qubit(); - let d = b.alloc_qubit(); - let hi_delta = highest_set_bit(c) + 1; - let last = match dialog_gcd_fused_fold_carry_trunc_window(step) { - Some(w) => core::cmp::min(n - 2, hi_delta.saturating_add(w)), - None => n - 2, - }; - if fold_stream_controls_enabled() && fold_freed_tail_enabled() && last > hi_delta { - if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { - b.set_phase("dialog_gcd_streamed_double_setup"); - } - b.ccx(ovf1, s2, d); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - fold_ripple_freed_tail_ed_streamed( - b, - y, - e, - d, - Some((ovf1, ovf2, s2)), - fold_park_low_carries_at_step(step), - last, - true, - ); - if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { - b.set_phase("dialog_gcd_streamed_double_cleanup"); - } - } else { - let h = b.alloc_qubit(); - b.ccx(ovf1, s2, d); - b.cx(ovf1, e); - b.cx(d, e); - b.cx(ovf2, e); - b.ccx(ovf2, d, h); - let xed = b.alloc_qubit(); - b.cx(e, xed); - b.cx(d, xed); - let eord = b.alloc_qubit(); - b.cx(xed, eord); - b.cx(h, eord); - let n10 = b.alloc_qubit(); - b.cx(d, n10); - b.cx(h, n10); - - let mut controls: Vec> = vec![None; hi_delta + 1]; - controls[0] = Some(e); - controls[1] = Some(d); - controls[4] = Some(e); - controls[5] = Some(d); - controls[6] = Some(e); - controls[7] = Some(xed); - controls[8] = Some(eord); - controls[9] = Some(eord); - controls[10] = Some(n10); - controls[11] = Some(h); - controls[highest_set_bit(c)] = Some(e); - controls[hi_delta] = Some(d); - if fold_freed_tail_enabled() && last > hi_delta { - fold_ripple_freed_tail_ed( - b, - y, - e, - d, - h, - xed, - eord, - n10, - Some((ovf1, ovf2, s2)), - step, - last, - true, - ); - } else { - cadd_per_position_controls_trunc(b, y, &controls, last); - } - - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(n10); - b.free(eord); - b.free(xed); - if dialog_gcd_fused_hclear_measured_enabled() { - let m = b.alloc_bit(); - b.hmr(h, m); - b.cz_if(ovf2, d, m); - } else { - b.ccx(ovf2, d, h); - } - b.free(h); - } - - b.cx(y[0], e); - - if dialog_gcd_fused_dclear_measured_enabled() { - let m = b.alloc_bit(); - b.hmr(d, m); - b.cz_if(ovf1, s2, m); - } else { - b.ccx(s2, y[1], d); - } - b.free(d); - b.free(e); - - if dialog_gcd_fused_ovfclear_measured_enabled() { - let m = b.alloc_bit(); - b.hmr(ovf1, m); - b.cz_if(s2, y[1], m); - b.x(s2); - b.cz_if(s2, y[0], m); - b.x(s2); - } else { - b.ccx(s2, y[1], ovf1); - b.x(s2); - b.ccx(s2, y[0], ovf1); - b.x(s2); - } - b.free(ovf1); - - if dialog_gcd_fused_ovfclear_measured_enabled() { - let m = b.alloc_bit(); - b.hmr(ovf2, m); - b.cz_if(s2, y[0], m); - } else { - b.ccx(s2, y[0], ovf2); - } - b.free(ovf2); -} - -pub(crate) fn dialog_gcd_fused_halve_y(b: &mut B, y: &[QubitId], p: U256, s2: QubitId) { - dialog_gcd_fused_halve_y_at_step(b, y, p, s2, None); -} - -pub(crate) fn dialog_gcd_fused_halve_y_at_step( - b: &mut B, - y: &[QubitId], - p: U256, - s2: QubitId, - step: Option, -) { - let n = y.len(); - debug_assert_eq!(n, 256); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); - - let e = b.alloc_qubit(); - let d = b.alloc_qubit(); - let hi_delta = highest_set_bit(c) + 1; - let last = match dialog_gcd_fused_fold_carry_trunc_window(step) { - Some(w) => core::cmp::min(n - 2, hi_delta.saturating_add(w)), - None => n - 2, - }; - let (ovf2, ovf1) = - if fold_stream_controls_enabled() && fold_freed_tail_enabled() && last > hi_delta { - if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { - b.set_phase("dialog_gcd_streamed_halve_setup"); - } - b.cx(y[0], e); - b.ccx(s2, y[1], d); - let ovf2 = b.alloc_qubit(); - let ovf1 = b.alloc_qubit(); - b.ccx(e, s2, ovf2); - b.cx(e, ovf1); - let xed = b.alloc_qubit(); - b.cx(e, xed); - b.cx(d, xed); - b.ccx(s2, xed, ovf1); - b.cx(d, xed); - b.cx(e, xed); - b.free(xed); - fold_ripple_freed_tail_ed_streamed( - b, - y, - e, - d, - Some((ovf1, ovf2, s2)), - fold_park_low_carries_at_step(step), - last, - false, - ); - if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { - b.set_phase("dialog_gcd_streamed_halve_cleanup"); - } - (ovf2, ovf1) - } else { - let h = b.alloc_qubit(); - b.cx(y[0], e); - b.ccx(s2, y[1], d); - b.ccx(e, d, h); - let xed = b.alloc_qubit(); - b.cx(e, xed); - b.cx(d, xed); - let eord = b.alloc_qubit(); - b.cx(xed, eord); - b.cx(h, eord); - let n10 = b.alloc_qubit(); - b.cx(d, n10); - b.cx(h, n10); - let ovf2 = b.alloc_qubit(); - let ovf1 = b.alloc_qubit(); - b.ccx(e, s2, ovf2); - b.cx(e, ovf1); - b.ccx(s2, xed, ovf1); - - let mut controls: Vec> = vec![None; hi_delta + 1]; - controls[0] = Some(e); - controls[1] = Some(d); - controls[4] = Some(e); - controls[5] = Some(d); - controls[6] = Some(e); - controls[7] = Some(xed); - controls[8] = Some(eord); - controls[9] = Some(eord); - controls[10] = Some(n10); - controls[11] = Some(h); - controls[highest_set_bit(c)] = Some(e); - controls[hi_delta] = Some(d); - if fold_freed_tail_enabled() && last > hi_delta { - fold_ripple_freed_tail_ed( - b, - y, - e, - d, - h, - xed, - eord, - n10, - Some((ovf1, ovf2, s2)), - step, - last, - false, - ); - } else { - csub_per_position_controls_trunc(b, y, &controls, last); - } - - b.cx(h, n10); - b.cx(d, n10); - b.cx(h, eord); - b.cx(xed, eord); - b.cx(d, xed); - b.cx(e, xed); - b.free(n10); - b.free(eord); - b.free(xed); - if dialog_gcd_fused_hclear_measured_enabled() { - let m = b.alloc_bit(); - b.hmr(h, m); - b.cz_if(e, d, m); - } else { - b.ccx(e, d, h); - } - b.free(h); - (ovf2, ovf1) - }; - - if dialog_gcd_fused_halve_edclear_measured_enabled() { - let me = b.alloc_bit(); - b.hmr(e, me); - b.x(s2); - b.cz_if(s2, ovf1, me); - b.x(s2); - b.cz_if(s2, ovf2, me); - let md = b.alloc_bit(); - b.hmr(d, md); - b.cz_if(s2, ovf1, md); - } else { - b.x(s2); - b.ccx(s2, ovf1, e); - b.x(s2); - b.ccx(s2, ovf2, e); - b.ccx(s2, ovf1, d); - } - b.free(e); - b.free(d); - - for i in 0..n - 1 { - if dialog_gcd_skip_zero_edge_apply_halve_cshift_enabled() && i == 0 { - continue; - } - cswap(b, s2, y[i], y[i + 1]); - } - cswap(b, s2, y[n - 1], ovf2); - - b.free(ovf2); - - for i in 0..n - 1 { - b.swap(y[i], y[i + 1]); - } - b.swap(y[n - 1], ovf1); - - b.free(ovf1); -} + +use super::*; + +pub(crate) fn round763_dedup_enabled() -> bool { + + std::env::var("DIALOG_GCD_ROUND763_DEDUP").ok().as_deref() == Some("1") +} + +pub(crate) fn round763_compress_lever_enabled() -> bool { + + std::env::var("DIALOG_GCD_ROUND763_COMPRESS_LEVER") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn emit_dialog_gcd_round763_compressor(b: &mut B, block: &[QubitId]) { + assert_eq!(block.len(), 6); + if round763_compress_lever_enabled() { + b.cx(block[5], block[3]); + b.ccx(block[3], block[4], block[5]); + b.cx(block[1], block[4]); + b.cx(block[1], block[0]); + b.ccx(block[4], block[5], block[1]); + b.cx(block[0], block[2]); + b.ccx(block[2], block[5], block[0]); + b.ccx(block[0], block[1], block[5]); + return; + } + b.ccx(block[4], block[5], block[3]); + b.ccx(block[3], block[4], block[5]); + b.ccx(block[1], block[2], block[4]); + if round763_dedup_enabled() { + b.cx(block[1], block[0]); + } else { + b.ccx(block[1], block[3], block[4]); + b.cx(block[1], block[0]); + b.ccx(block[1], block[3], block[4]); + } + b.ccx(block[4], block[5], block[1]); + b.ccx(block[0], block[5], block[2]); + b.ccx(block[2], block[5], block[0]); + b.ccx(block[0], block[1], block[5]); +} + +pub(crate) fn emit_dialog_gcd_round763_compressor_inverse(b: &mut B, block: &[QubitId]) { + assert_eq!(block.len(), 6); + if round763_compress_lever_enabled() { + b.ccx(block[0], block[1], block[5]); + b.ccx(block[2], block[5], block[0]); + b.cx(block[0], block[2]); + b.ccx(block[4], block[5], block[1]); + b.cx(block[1], block[0]); + b.cx(block[1], block[4]); + b.ccx(block[3], block[4], block[5]); + b.cx(block[5], block[3]); + return; + } + b.ccx(block[0], block[1], block[5]); + b.ccx(block[2], block[5], block[0]); + b.ccx(block[0], block[5], block[2]); + b.ccx(block[4], block[5], block[1]); + if round763_dedup_enabled() { + b.cx(block[1], block[0]); + } else { + b.ccx(block[1], block[3], block[4]); + b.cx(block[1], block[0]); + b.ccx(block[1], block[3], block[4]); + } + b.ccx(block[1], block[2], block[4]); + b.ccx(block[3], block[4], block[5]); + b.ccx(block[4], block[5], block[3]); +} + +const DIALOG_GCD_K5_DATA_WIRES: [usize; 12] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]; +const DIALOG_GCD_K5_HEAD11_DATA_WIRES: [usize; 11] = + [0, 1, 2, 4, 5, 6, 7, 8, 9, 11, 12]; +const DIALOG_GCD_K5_TAIL3_DATA_WIRES: [usize; 5] = [1, 10, 2, 3, 11]; +const DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES: [usize; 9] = [0, 1, 2, 3, 4, 5, 10, 11, 12]; +const DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES: [usize; 5] = [6, 7, 8, 9, 13]; +const DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT: u8 = 25; +const DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF: [&[u16]; 5] = [ + &[1, 2, 4, 32, 34, 64, 128], + &[4, 10, 16, 20, 24, 32, 64, 136, 256], + &[1, 6, 8, 16, 34, 128], + &[6, 32, 64], + &[4, 6, 8, 10, 32, 80, 128, 130, 256], +]; +const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_CODE_CONSTANT: u8 = 3; +const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_ENCODER_ANF: [&[u16]; 5] = [ + &[6, 8, 16, 20, 24, 64, 80, 128, 130, 136], + &[2, 6, 10, 16, 80, 128, 130], + &[2, 10, 16, 64, 80, 128, 130], + &[2, 4, 6, 8, 16, 64], + &[1, 2, 6, 10, 16, 20, 24, 64, 128, 136], +]; +const DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF: [&[u16]; 9] = [ + &[0, 6, 7, 9, 10, 17, 19, 22, 23, 24, 25, 29, 31], + &[0, 2, 7, 8, 10, 14, 16, 19, 24], + &[0, 16, 17, 19, 20, 24, 25, 26, 28], + &[0, 1, 2, 3, 4, 5, 6, 8, 11, 12, 15, 16, 18, 21, 26, 28], + &[0, 3, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 17, 18, 20, 21, 25], + &[26, 27], + &[2, 7, 10, 14, 16, 18, 22, 23, 24], + &[1, 6, 7, 8, 9, 10, 16, 18, 19, 20, 27, 28, 29, 30], + &[0, 9, 13, 22, 24, 28, 31], +]; +const DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF: [&[u16]; 9] = [ + &[0, 1, 13, 17, 24, 25, 26], + &[0, 1, 2, 7, 10, 12, 13, 14, 31], + &[0, 6, 7, 8, 10, 12, 15], + &[4, 5, 7, 12, 22, 23, 27], + &[0, 1, 5, 12, 13, 27, 30], + &[], + &[1, 4, 7, 8, 9, 27], + &[0, 4, 8, 9, 16, 17, 20, 21, 30], + &[0], +]; +pub(crate) const DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT: [u16; 32] = [ + 0x124, 0x125, 0x12b, 0x129, 0x128, 0x12f, 0x12d, 0x14b, + 0x149, 0x158, 0x15b, 0x159, 0x147, 0x145, 0x12c, 0x16b, + 0x169, 0x15f, 0x15d, 0x178, 0x14f, 0x04b, 0x15c, 0x049, + 0x058, 0x14d, 0x148, 0x0c5, 0x0c7, 0x17b, 0x038, 0x02b, +]; +#[derive(Clone, Copy)] +enum DialogGcdK5FableGate { + X(usize), + Cx(usize, usize), + Ccx(usize, usize, usize), +} + +const DIALOG_GCD_K5_FABLE_GATES: &[DialogGcdK5FableGate] = &[ + DialogGcdK5FableGate::Cx(7, 6), + DialogGcdK5FableGate::Cx(6, 7), + DialogGcdK5FableGate::Cx(7, 6), + DialogGcdK5FableGate::Cx(8, 7), + DialogGcdK5FableGate::Cx(7, 8), + DialogGcdK5FableGate::Cx(9, 6), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::Ccx(10, 6, 9), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(9, 6), + DialogGcdK5FableGate::Cx(11, 10), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(5, 11), + DialogGcdK5FableGate::Ccx(6, 10, 5), + DialogGcdK5FableGate::Cx(5, 11), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::Cx(11, 10), + DialogGcdK5FableGate::Cx(10, 4), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::Cx(10, 11), + DialogGcdK5FableGate::Ccx(6, 4, 10), + DialogGcdK5FableGate::Cx(10, 11), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::Cx(10, 4), + DialogGcdK5FableGate::Cx(7, 4), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(5, 7), + DialogGcdK5FableGate::Cx(5, 9), + DialogGcdK5FableGate::Ccx(10, 4, 5), + DialogGcdK5FableGate::Cx(5, 9), + DialogGcdK5FableGate::Cx(5, 7), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(7, 4), + DialogGcdK5FableGate::Cx(10, 4), + DialogGcdK5FableGate::Cx(7, 5), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::Cx(9, 11), + DialogGcdK5FableGate::Ccx(4, 5, 9), + DialogGcdK5FableGate::Cx(9, 11), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::Cx(7, 5), + DialogGcdK5FableGate::Cx(10, 4), + DialogGcdK5FableGate::Cx(9, 8), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Ccx(10, 8, 9), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(9, 8), + DialogGcdK5FableGate::Cx(4, 8), + DialogGcdK5FableGate::Cx(11, 4), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::Cx(5, 11), + DialogGcdK5FableGate::Ccx(8, 4, 5), + DialogGcdK5FableGate::Cx(5, 11), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::Cx(11, 4), + DialogGcdK5FableGate::Cx(4, 8), + DialogGcdK5FableGate::Cx(7, 4), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::Ccx(5, 4, 7), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::Cx(7, 4), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::Ccx(4, 8, 6), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::X(11), + DialogGcdK5FableGate::Cx(4, 5), + DialogGcdK5FableGate::Cx(4, 8), + DialogGcdK5FableGate::Cx(4, 10), + DialogGcdK5FableGate::Ccx(6, 11, 4), + DialogGcdK5FableGate::Cx(4, 10), + DialogGcdK5FableGate::Cx(4, 8), + DialogGcdK5FableGate::Cx(4, 5), + DialogGcdK5FableGate::X(11), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::Cx(9, 5), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Ccx(10, 5, 9), + DialogGcdK5FableGate::X(10), + DialogGcdK5FableGate::Cx(9, 5), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::X(9), + DialogGcdK5FableGate::Ccx(7, 8, 13), + DialogGcdK5FableGate::Cx(4, 6), + DialogGcdK5FableGate::Ccx(13, 9, 4), + DialogGcdK5FableGate::Cx(4, 6), + DialogGcdK5FableGate::Ccx(7, 8, 13), + DialogGcdK5FableGate::X(9), + DialogGcdK5FableGate::X(8), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::X(11), + DialogGcdK5FableGate::Ccx(4, 6, 13), + DialogGcdK5FableGate::Ccx(13, 11, 10), + DialogGcdK5FableGate::Ccx(4, 6, 13), + DialogGcdK5FableGate::X(11), + DialogGcdK5FableGate::X(6), + DialogGcdK5FableGate::X(4), + DialogGcdK5FableGate::X(10), +]; + +fn dialog_gcd_k5_fable_wire(data: &[QubitId; 13], ancilla: QubitId, wire: usize) -> QubitId { + if wire == 13 { + ancilla + } else { + debug_assert!(wire < data.len()); + data[wire] + } +} + +fn dialog_gcd_k5_emit_fable_gate( + b: &mut B, + data: &[QubitId; 13], + ancilla: QubitId, + gate: DialogGcdK5FableGate, +) { + match gate { + DialogGcdK5FableGate::X(a) => b.x(dialog_gcd_k5_fable_wire(data, ancilla, a)), + DialogGcdK5FableGate::Cx(a, c) => b.cx( + dialog_gcd_k5_fable_wire(data, ancilla, a), + dialog_gcd_k5_fable_wire(data, ancilla, c), + ), + DialogGcdK5FableGate::Ccx(a, c, t) => b.ccx( + dialog_gcd_k5_fable_wire(data, ancilla, a), + dialog_gcd_k5_fable_wire(data, ancilla, c), + dialog_gcd_k5_fable_wire(data, ancilla, t), + ), + } +} + +fn dialog_gcd_k5_emit_fable_codec( + b: &mut B, + data: &[QubitId; 13], + ancilla: QubitId, + inverse: bool, +) { + if inverse { + for &gate in DIALOG_GCD_K5_FABLE_GATES.iter().rev() { + dialog_gcd_k5_emit_fable_gate(b, data, ancilla, gate); + } + } else { + for &gate in DIALOG_GCD_K5_FABLE_GATES { + dialog_gcd_k5_emit_fable_gate(b, data, ancilla, gate); + } + } +} + +fn emit_dialog_gcd_k5_clean_compressor(b: &mut B, data: &[QubitId; 13], ancilla: QubitId) { + dialog_gcd_k5_emit_fable_codec(b, data, ancilla, false); +} + +fn emit_dialog_gcd_k5_clean_compressor_inverse( + b: &mut B, + data: &[QubitId; 13], + ancilla: QubitId, +) { + dialog_gcd_k5_emit_fable_codec(b, data, ancilla, true); +} + +fn dialog_gcd_k5_head11_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 5 + && std::env::var("DIALOG_GCD_K5_HEAD11_CODEC") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tight_partial_block_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && std::env::var("DIALOG_GCD_K5_TIGHT_PARTIAL_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail3_fixed_last_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 3 + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 3 + && std::env::var("DIALOG_GCD_K5_TAIL3_FIXED_LAST") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail3_top32_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 3 + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 3 + && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_CODEC") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail3_top32_stream_apply_enabled() -> bool { + dialog_gcd_k5_tail3_top32_enabled() + && dialog_gcd_apply_replay_swap_host_enabled() + && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_STREAM_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail3_top32_split_slot_apply_enabled() -> bool { + dialog_gcd_k5_tail3_top32_stream_apply_enabled() + && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_SPLIT_SLOT_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() -> bool { + dialog_gcd_k5_tail3_top32_split_slot_apply_enabled() + && std::env::var("DIALOG_GCD_K5_TAIL3_TOP32_FINAL_S2_CONST_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_head11_stream_pair_apply_enabled() -> bool { + dialog_gcd_k5_head11_enabled() + && dialog_gcd_apply_replay_swap_host_enabled() + && std::env::var("DIALOG_GCD_K5_HEAD11_STREAM_PAIR_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_head11_split_pair_shift_apply_enabled() -> bool { + dialog_gcd_k5_head11_stream_pair_apply_enabled() + && std::env::var("DIALOG_GCD_K5_HEAD11_SPLIT_PAIR_SHIFT_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled() -> bool { + dialog_gcd_k5_head11_split_pair_shift_apply_enabled() + && std::env::var("DIALOG_GCD_K5_HEAD11_PAIR01_S2_PERMUTE_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled() -> bool { + dialog_gcd_k5_head11_split_pair_shift_apply_enabled() + && std::env::var("DIALOG_GCD_K5_HEAD11_PAIR23_S2_BORROW_PAIR01_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_stream_pair_apply_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_apply_replay_swap_host_enabled() + && std::env::var("DIALOG_GCD_K5_STREAM_PAIR_APPLY") + .ok() + .as_deref() + == Some("1") +} + +fn emit_dialog_gcd_k5_head11_preconditioner(b: &mut B, data: &[QubitId; 13]) { + b.x(data[0]); + b.ccx(data[0], data[1], data[3]); + b.ccx(data[2], data[3], data[0]); + b.cx(data[0], data[3]); +} + +fn emit_dialog_gcd_k5_head11_preconditioner_inverse( + b: &mut B, + data: &[QubitId; 13], +) { + b.cx(data[0], data[3]); + b.ccx(data[2], data[3], data[0]); + b.ccx(data[0], data[1], data[3]); + b.x(data[0]); +} + +fn emit_dialog_gcd_k5_pair_encoder(b: &mut B, pair_raw: &[QubitId; 6]) { + let core = [pair_raw[0], pair_raw[1], pair_raw[4], pair_raw[2], pair_raw[3]]; + b.cx(core[1], core[2]); + b.cx(core[0], core[4]); + b.x(core[3]); + b.ccx(core[2], core[3], core[1]); + b.cx(core[3], core[4]); + b.ccx(core[3], core[4], core[0]); + b.cx(core[2], core[4]); + b.cx(core[0], core[3]); + b.cx(core[3], core[2]); + b.cx(core[3], core[4]); + b.ccx(core[1], core[3], core[0]); + b.cx(core[1], core[0]); + b.cx(core[3], core[0]); +} + +fn emit_dialog_gcd_k5_pair_encoder_inverse(b: &mut B, pair_raw: &[QubitId; 6]) { + let core = [pair_raw[0], pair_raw[1], pair_raw[4], pair_raw[2], pair_raw[3]]; + b.cx(core[3], core[0]); + b.cx(core[1], core[0]); + b.ccx(core[1], core[3], core[0]); + b.cx(core[3], core[4]); + b.cx(core[3], core[2]); + b.cx(core[0], core[3]); + b.cx(core[2], core[4]); + b.ccx(core[3], core[4], core[0]); + b.cx(core[3], core[4]); + b.ccx(core[2], core[3], core[1]); + b.x(core[3]); + b.cx(core[0], core[4]); + b.cx(core[1], core[2]); +} + +fn dialog_gcd_raw_s2(raw_block: &[QubitId], slot: usize) -> QubitId { + raw_block[2 * dialog_gcd_sidecar_group_size() + slot] +} + +fn dialog_gcd_block_raw_s2( + raw_block: &[QubitId], + block_steps: usize, + slot: usize, +) -> QubitId { + if dialog_gcd_k5_tail6_graph9_enabled() && block_steps == 6 { + assert!(slot < DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS); + raw_block[2 * DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS + slot] + } else if dialog_gcd_k5_tail6_graph_enabled() && block_steps == 6 { + assert!(slot < DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS); + raw_block[2 * DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS + slot] + } else if dialog_gcd_k5_tail7_enabled() && block_steps == 7 { + assert!(slot < DIALOG_GCD_K5_TAIL7_STORED_STEPS); + raw_block[2 * DIALOG_GCD_K5_TAIL7_STORED_STEPS + slot] + } else { + dialog_gcd_raw_s2(raw_block, slot) + } +} + +fn dialog_gcd_k5_pair01(raw_block: &[QubitId]) -> [QubitId; 6] { + [ + raw_block[0], + raw_block[1], + raw_block[2], + raw_block[3], + dialog_gcd_raw_s2(raw_block, 0), + dialog_gcd_raw_s2(raw_block, 1), + ] +} + +fn dialog_gcd_k5_pair23(raw_block: &[QubitId]) -> [QubitId; 6] { + [ + raw_block[4], + raw_block[5], + raw_block[6], + raw_block[7], + dialog_gcd_raw_s2(raw_block, 2), + dialog_gcd_raw_s2(raw_block, 3), + ] +} + +fn dialog_gcd_k5_data_from_raw(raw_block: &[QubitId]) -> [QubitId; 13] { + [ + raw_block[1], + dialog_gcd_raw_s2(raw_block, 0), + raw_block[2], + raw_block[3], + dialog_gcd_raw_s2(raw_block, 1), + raw_block[5], + dialog_gcd_raw_s2(raw_block, 2), + raw_block[6], + raw_block[7], + dialog_gcd_raw_s2(raw_block, 3), + raw_block[8], + raw_block[9], + dialog_gcd_raw_s2(raw_block, 4), + ] +} + +fn dialog_gcd_k5_partial_raw_clean_scratch( + raw_block: &[QubitId], + steps: usize, +) -> Vec { + if !dialog_gcd_k5_clean_block_enabled() + || dialog_gcd_k5_tail_pair1_enabled() + || steps >= dialog_gcd_sidecar_group_size() + { + return Vec::new(); + } + assert_eq!(raw_block.len(), 15); + assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); + let branch_end = 2 * dialog_gcd_sidecar_group_size(); + let fixed_tail_branch = if dialog_gcd_k5_tail3_fixed_last_enabled() && steps == 3 { + &raw_block[2 * (steps - 1)..2 * steps] + } else { + &[][..] + }; + fixed_tail_branch + .iter() + .chain(raw_block[2 * steps..branch_end].iter()) + .chain(raw_block[branch_end + steps..].iter()) + .copied() + .collect() +} + +fn dialog_gcd_k5_partial_raw_release_bits() -> usize { + std::env::var("DIALOG_GCD_K5_PARTIAL_RAW_RELEASE") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0) +} + +fn dialog_gcd_k5_transfer_survivors( + b: &mut B, + compressed_block: &[QubitId], + data: &[QubitId; 13], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 12); + for (i, &wire) in DIALOG_GCD_K5_DATA_WIRES.iter().enumerate() { + if swap_host { + b.swap(compressed_block[i], data[wire]); + } else { + b.cx(compressed_block[i], data[wire]); + } + } +} + +fn dialog_gcd_k5_head11_transfer_survivors( + b: &mut B, + compressed_block: &[QubitId], + data: &[QubitId; 13], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); + for (i, &wire) in DIALOG_GCD_K5_HEAD11_DATA_WIRES.iter().enumerate() { + if swap_host { + b.swap(compressed_block[i], data[wire]); + } else { + b.cx(compressed_block[i], data[wire]); + } + } +} + +fn dialog_gcd_k5_head11_compress_raw_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); + assert_eq!(raw_block.len(), 15); + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); + let data = dialog_gcd_k5_data_from_raw(raw_block); + emit_dialog_gcd_k5_head11_preconditioner(b, &data); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); + b.free(ancilla); + dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); +} + +fn dialog_gcd_k5_head11_decompress_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); + b.free(ancilla); + emit_dialog_gcd_k5_head11_preconditioner_inverse(b, &data); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); +} + +fn dialog_gcd_k5_compress_data_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 12); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); + b.free(ancilla); + dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); +} + +fn dialog_gcd_k5_decompress_block_to_data( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 12); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); + b.free(ancilla); +} + +fn dialog_gcd_k5_stream_pairs_start(b: &mut B, raw_block: &[QubitId]) { + assert_eq!(raw_block.len(), 15); + + b.free(raw_block[0]); + b.free(raw_block[4]); +} + +fn dialog_gcd_k5_stream_pairs_before_slot( + b: &mut B, + raw_block: &[QubitId], + slot: usize, +) { + match slot { + 3 => { + b.reacquire(raw_block[4]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); + } + 1 => { + b.reacquire(raw_block[0]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); + } + _ => {} + } +} + +fn dialog_gcd_k5_stream_pairs_after_slot_forward( + b: &mut B, + raw_block: &[QubitId], + slot: usize, +) { + match slot { + 2 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); + b.free(raw_block[4]); + } + 0 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + b.free(raw_block[0]); + } + _ => {} + } +} + +fn dialog_gcd_k5_stream_pairs_before_slot_reverse( + b: &mut B, + raw_block: &[QubitId], + slot: usize, +) { + match slot { + 0 => { + b.reacquire(raw_block[0]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); + } + 2 => { + b.reacquire(raw_block[4]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); + } + _ => {} + } +} + +fn dialog_gcd_k5_stream_pairs_after_slot_reverse( + b: &mut B, + raw_block: &[QubitId], + slot: usize, +) { + match slot { + 1 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + b.free(raw_block[0]); + } + 3 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); + b.free(raw_block[4]); + } + _ => {} + } +} + +fn dialog_gcd_k5_stream_pairs_finish(b: &mut B, raw_block: &[QubitId]) { + b.reacquire(raw_block[0]); + b.reacquire(raw_block[4]); +} + +fn dialog_gcd_k5_head11_pair_for_slot(slot: usize) -> usize { + assert!(slot < 4); + slot / 2 +} + +fn dialog_gcd_k5_head11_open_pair_for_slot(b: &mut B, raw_block: &[QubitId], slot: usize) { + match dialog_gcd_k5_head11_pair_for_slot(slot) { + 0 => { + b.reacquire(raw_block[0]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); + } + 1 => { + b.reacquire(raw_block[4]); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); + } + _ => unreachable!(), + } +} + +fn dialog_gcd_k5_head11_close_pair_for_slot(b: &mut B, raw_block: &[QubitId], slot: usize) { + match dialog_gcd_k5_head11_pair_for_slot(slot) { + 0 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + b.free(raw_block[0]); + } + 1 => { + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); + b.free(raw_block[4]); + } + _ => unreachable!(), + } +} + +fn dialog_gcd_k5_head11_pair01_expose_s2(b: &mut B, raw_block: &[QubitId]) { + let w = [ + raw_block[1], + raw_block[10], + raw_block[2], + raw_block[3], + raw_block[11], + ]; + b.cx(w[0], w[2]); + b.cx(w[1], w[0]); + b.ccx(w[0], w[2], w[1]); +} + +fn dialog_gcd_k5_head11_pair01_unexpose_s2(b: &mut B, raw_block: &[QubitId]) { + let w = [ + raw_block[1], + raw_block[10], + raw_block[2], + raw_block[3], + raw_block[11], + ]; + b.ccx(w[0], w[2], w[1]); + b.cx(w[1], w[0]); + b.cx(w[0], w[2]); +} + +fn dialog_gcd_k5_head11_pair01_zero_lane(b: &mut B, raw_block: &[QubitId]) { + let w = [ + raw_block[1], + raw_block[10], + raw_block[2], + raw_block[3], + raw_block[11], + ]; + b.x(w[0]); + b.x(w[2]); + b.ccx(w[0], w[1], w[3]); + b.ccx(w[2], w[3], w[0]); +} + +fn dialog_gcd_k5_head11_pair01_unzero_lane(b: &mut B, raw_block: &[QubitId]) { + let w = [ + raw_block[1], + raw_block[10], + raw_block[2], + raw_block[3], + raw_block[11], + ]; + b.ccx(w[2], w[3], w[0]); + b.ccx(w[0], w[1], w[3]); + b.x(w[2]); + b.x(w[0]); +} + +const DIALOG_GCD_K5_HEAD11_PAIR23_S2_ANF: &[u16] = &[1, 2, 3, 4, 7, 9, 11, 13, 15]; + +fn dialog_gcd_k5_head11_toggle_pair23_s2_into( + b: &mut B, + raw_block: &[QubitId], + target: QubitId, +) { + let code = [ + raw_block[5], + raw_block[12], + raw_block[6], + raw_block[7], + raw_block[13], + ]; + dialog_gcd_toggle_anf_with_dirty( + b, + &code, + target, + raw_block, + DIALOG_GCD_K5_HEAD11_PAIR23_S2_ANF, + ); +} + +fn dialog_gcd_k5_head11_compress_data_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!( + compressed_block.len(), + DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + ); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + emit_dialog_gcd_k5_head11_preconditioner(b, &data); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); + b.free(ancilla); + dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); +} + +fn dialog_gcd_k5_head11_decompress_block_to_data( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!( + compressed_block.len(), + DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + ); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + dialog_gcd_k5_head11_transfer_survivors(b, compressed_block, &data, swap_host); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); + b.free(ancilla); + emit_dialog_gcd_k5_head11_preconditioner_inverse(b, &data); +} + +fn dialog_gcd_k5_head11_pair_encode_word(bits: &mut [bool; 15], slots: [usize; 2]) { + let wire = [ + 3 * slots[0], + 3 * slots[0] + 1, + 3 * slots[0] + 2, + 3 * slots[1], + 3 * slots[1] + 1, + ]; + bits[wire[2]] ^= bits[wire[1]]; + bits[wire[4]] ^= bits[wire[0]]; + bits[wire[3]] ^= true; + bits[wire[1]] ^= bits[wire[2]] && bits[wire[3]]; + bits[wire[4]] ^= bits[wire[3]]; + bits[wire[0]] ^= bits[wire[3]] && bits[wire[4]]; + bits[wire[4]] ^= bits[wire[2]]; + bits[wire[3]] ^= bits[wire[0]]; + bits[wire[2]] ^= bits[wire[3]]; + bits[wire[4]] ^= bits[wire[3]]; + bits[wire[0]] ^= bits[wire[1]] && bits[wire[3]]; + bits[wire[0]] ^= bits[wire[1]]; + bits[wire[0]] ^= bits[wire[3]]; +} + +fn dialog_gcd_k5_head11_code_word(pattern: u16) -> Option { + let mut raw = std::array::from_fn::<_, 15, _>(|bit| (pattern >> bit) & 1 != 0); + dialog_gcd_k5_head11_pair_encode_word(&mut raw, [0, 1]); + dialog_gcd_k5_head11_pair_encode_word(&mut raw, [2, 3]); + if raw[0] || raw[6] { + return None; + } + + const RAW_DATA_INDICES: [usize; 13] = + [1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14]; + let mut wires = [false; 14]; + for (index, raw_index) in RAW_DATA_INDICES.into_iter().enumerate() { + wires[index] = raw[raw_index]; + } + wires[0] ^= true; + wires[3] ^= wires[0] && wires[1]; + wires[0] ^= wires[2] && wires[3]; + wires[3] ^= wires[0]; + for &gate in DIALOG_GCD_K5_FABLE_GATES { + match gate { + DialogGcdK5FableGate::X(a) => wires[a] ^= true, + DialogGcdK5FableGate::Cx(a, c) => wires[c] ^= wires[a], + DialogGcdK5FableGate::Ccx(a, c, t) => wires[t] ^= wires[a] && wires[c], + } + } + if wires[3] || wires[10] || wires[13] { + return None; + } + Some( + DIALOG_GCD_K5_HEAD11_DATA_WIRES + .iter() + .enumerate() + .fold(0u16, |code, (index, &wire)| { + code | (u16::from(wires[wire]) << index) + }), + ) +} + +pub(crate) fn dialog_gcd_k5_head11_supports(pattern: u16) -> bool { + dialog_gcd_k5_head11_code_word(pattern).is_some() +} + +pub(crate) fn dialog_gcd_k5_head11_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let supported = (0u16..1 << 15) + .filter(|&pattern| dialog_gcd_k5_head11_supports(pattern)) + .collect::>(); + if supported.len() != 1 << DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() { + return Err(format!( + "expected 2048 supported head words, got {}", + supported.len() + )); + } + let mut seen_codes = vec![false; 1 << DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()]; + for &pattern in &supported { + let code = dialog_gcd_k5_head11_code_word(pattern).expect("filtered support"); + if std::mem::replace(&mut seen_codes[code as usize], true) { + return Err(format!("duplicate head code 0x{code:03x}")); + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_head11_decompress_block_to_raw(&mut b, &code, &raw, true); + } else { + dialog_gcd_k5_head11_compress_raw_to_block(&mut b, &code, &raw, true); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + let forward_codec = build_codec(false); + let reverse_codec = build_codec(true); + + for batch_start in (0..supported.len()).step_by(64) { + let patterns = &supported[batch_start..batch_start + 64]; + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_HEAD11_DATA_WIRES.len()]; + for (shot, &pattern) in patterns.iter().enumerate() { + let shot_bit = 1u64 << shot; + for slot in 0..5 { + if (pattern >> (3 * slot)) & 1 != 0 { + raw_masks[2 * slot] |= shot_bit; + } + if (pattern >> (3 * slot + 1)) & 1 != 0 { + raw_masks[2 * slot + 1] |= shot_bit; + } + if (pattern >> (3 * slot + 2)) & 1 != 0 { + raw_masks[10 + slot] |= shot_bit; + } + } + let code = dialog_gcd_k5_head11_code_word(pattern).expect("supported pattern"); + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let run = |decompress: bool| { + let (ops, code, raw, num_qubits, num_bits) = + if decompress { &reverse_codec } else { &forward_codec }; + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-head11-codec-selftest"); + seed.update(&(batch_start as u64).to_le_bytes()); + seed.update(&[u8::from(decompress)]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(*num_qubits, *num_bits, &mut xof); + sim.clear_for_shot(); + let source = if decompress { + &code_masks[..] + } else { + &raw_masks[..] + }; + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let (forward_code, forward_raw, forward_phase) = run(false); + if forward_phase != 0 { + return Err(format!( + "forward phase garbage in batch {batch_start}: 0x{forward_phase:x}" + )); + } + if forward_code != code_masks { + return Err(format!( + "forward code mismatch in batch {batch_start}: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw.iter().any(|&mask| mask != 0) { + return Err(format!( + "forward raw garbage in batch {batch_start}: {forward_raw:x?}" + )); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true); + if reverse_phase != 0 { + return Err(format!( + "reverse phase garbage in batch {batch_start}: 0x{reverse_phase:x}" + )); + } + if reverse_code.iter().any(|&mask| mask != 0) { + return Err(format!( + "reverse code garbage in batch {batch_start}: {reverse_code:x?}" + )); + } + if reverse_raw != raw_masks { + return Err(format!( + "reverse raw mismatch in batch {batch_start}: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + } + Ok(()) +} + +fn dialog_gcd_k5_compress_raw_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 12); + assert_eq!(raw_block.len(), 15); + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair23(raw_block)); + let data = dialog_gcd_k5_data_from_raw(raw_block); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor(b, &data, ancilla); + b.free(ancilla); + dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); +} + +fn dialog_gcd_k5_decompress_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 12); + assert_eq!(raw_block.len(), 15); + let data = dialog_gcd_k5_data_from_raw(raw_block); + dialog_gcd_k5_transfer_survivors(b, compressed_block, &data, swap_host); + let ancilla = b.alloc_qubit(); + emit_dialog_gcd_k5_clean_compressor_inverse(b, &data, ancilla); + b.free(ancilla); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair23(raw_block)); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); +} + +fn dialog_gcd_k5_compress_partial_raw_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, + swap_host: bool, +) { + assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); + assert_eq!(raw_block.len(), 15); + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + assert!( + compressed_block.len() == dialog_gcd_block_bits() + || compressed_block.len() == base_bits + steps + ); + let raw_base = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; + emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); + for i in 0..base_bits { + if swap_host { b.swap(compressed_block[i], raw_block[i]); } else { b.cx(compressed_block[i], raw_block[i]); } + } + for slot in 0..steps { + let s2 = dialog_gcd_raw_s2(raw_block, slot); + if swap_host { b.swap(compressed_block[base_bits + slot], s2); } else { b.cx(compressed_block[base_bits + slot], s2); } + } +} + +fn dialog_gcd_k5_decompress_partial_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, + swap_host: bool, +) { + assert!(steps <= DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE); + assert_eq!(raw_block.len(), 15); + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + assert!( + compressed_block.len() == dialog_gcd_block_bits() + || compressed_block.len() == base_bits + steps + ); + let raw_base = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; + for i in 0..base_bits { + if swap_host { b.swap(compressed_block[i], raw_block[i]); } else { b.cx(compressed_block[i], raw_block[i]); } + } + emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); + for slot in 0..steps { + let s2 = dialog_gcd_raw_s2(raw_block, slot); + if swap_host { b.swap(compressed_block[base_bits + slot], s2); } else { b.cx(compressed_block[base_bits + slot], s2); } + } +} + +fn dialog_gcd_k5_tail_pair1_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && !dialog_gcd_k5_tail7_enabled() + && !dialog_gcd_k5_tail6_graph_enabled() + && !dialog_gcd_k5_tail6_graph9_enabled() + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 2 + && std::env::var("DIALOG_GCD_K5_TAIL_PAIR1") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail6_graph9_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 6 + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 1 + && std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH9_CODEC") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_release_decoded_block_bits() -> usize { + if !dialog_gcd_k5_clean_block_enabled() || !dialog_gcd_apply_replay_swap_host_enabled() { + return 0; + } + std::env::var("DIALOG_GCD_K5_RELEASE_DECODED_BLOCK_BITS") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0) +} + +fn dialog_gcd_k5_release_decoded_tail_bits() -> usize { + std::env::var("DIALOG_GCD_K5_RELEASE_DECODED_TAIL_BITS") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or_else(dialog_gcd_k5_release_decoded_block_bits) +} + +fn dialog_gcd_k5_release_scale_bits() -> usize { + std::env::var("DIALOG_GCD_K5_RELEASE_SCALE_BITS") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0) +} + +fn dialog_gcd_k5_tail6_graph_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 6 + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 1 + && std::env::var("DIALOG_GCD_K5_TAIL6_GRAPH_CODEC") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_tail7_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && dialog_gcd_active_iterations() >= 7 + && dialog_gcd_active_iterations() % dialog_gcd_sidecar_group_size() == 2 + && std::env::var("DIALOG_GCD_K5_TAIL7_CODEC") + .ok() + .as_deref() + == Some("1") +} + +const DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS: usize = 3; +const DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS: usize = 6; +const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS] = + [0x0d4, 0x0d1, 0x040, 0x05f, 0x00d, 0x081]; +const DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT: u8 = 0x26; +const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CONSTANT: u16 = 0x1dc; +const DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_DECODE_MASKS: [u8; 9] = + [0x00, 0x3a, 0x03, 0x13, 0x26, 0x00, 0x04, 0x20, 0x00]; +const DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK: u16 = 0x085; +const DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_ANF: &[u16] = &[0x00, 0x02, 0x04, 0x05, 0x32]; +pub(crate) const DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT: [u32; 32] = [ + 0x24924, 0x24925, 0x24928, 0x24929, 0x2492b, 0x2492c, 0x2492d, 0x2492f, + 0x24944, 0x24945, 0x24947, 0x24948, 0x24949, 0x2494b, 0x2494d, 0x2494f, + 0x24958, 0x24959, 0x2495b, 0x2495c, 0x2495d, 0x2495f, 0x24965, 0x24967, + 0x24968, 0x24969, 0x2496b, 0x24978, 0x24979, 0x2497b, 0x2497d, 0x2497f, +]; + +const DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS: usize = 4; +const DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS: usize = 9; +const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS] = + [0x9dc, 0xb6a, 0x717, 0x404, 0xe92, 0x00c, 0xa17, 0x7af, 0xf44]; +const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT: u16 = 0xc6c; +const DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS: [u16; 12] = [ + 0x058, 0x000, 0x131, 0x111, 0x18e, 0x01b, 0x0d2, 0x000, 0x17d, 0x0a7, + 0x139, 0x000, +]; +const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK: u16 = 0x71e; +const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT: usize = 1; +const DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF: &[u16] = &[ + 0x000, 0x002, 0x003, 0x006, 0x008, 0x00a, 0x011, 0x012, 0x020, 0x021, + 0x024, 0x040, 0x041, 0x042, 0x048, 0x060, 0x080, 0x081, 0x088, 0x0a0, + 0x100, 0x02c, 0x034, 0x064, 0x0a2, 0x0a4, +]; +pub(crate) const DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT: [u32; 75] = [ + 0x24924, 0x24925, 0x24928, 0x24929, 0x2492b, 0x2492c, 0x2492d, 0x2492f, + 0x24944, 0x24945, 0x24947, 0x24948, 0x24949, 0x2494b, 0x2494d, 0x2494f, + 0x24958, 0x24959, 0x2495b, 0x2495c, 0x2495d, 0x2495f, 0x24965, 0x24967, + 0x24968, 0x24969, 0x2496b, 0x24978, 0x24979, 0x2497b, 0x2497d, 0x2497f, + 0x24a27, 0x24a29, 0x24a2b, 0x24a2d, 0x24a2f, 0x24a38, 0x24a3f, 0x24a45, + 0x24a47, 0x24a49, 0x24a4b, 0x24a4d, 0x24a58, 0x24a59, 0x24a5b, 0x24a5f, + 0x24a65, 0x24a68, 0x24a6b, 0x24a78, 0x24a7c, 0x24ac5, 0x24ac8, 0x24ac9, + 0x24acb, 0x24acd, 0x24add, 0x24ae9, 0x24af8, 0x24af9, 0x24b29, 0x24b3c, + 0x24b3d, 0x24b45, 0x24b49, 0x24b4b, 0x24b5f, 0x24b79, 0x24bc5, 0x24bc9, + 0x24bd8, 0x24be4, 0x24bf9, +]; + +const DIALOG_GCD_K5_TAIL7_STORED_STEPS: usize = 4; +const DIALOG_GCD_K5_TAIL7_CODE_BITS: usize = 5; +const DIALOG_GCD_K5_TAIL7_PACKED_CODE_MASKS: [u32; DIALOG_GCD_K5_TAIL7_CODE_BITS] = + [0x8a0, 0x204, 0x80011, 0x38, 0x100402]; +const DIALOG_GCD_K5_TAIL7_RAW_CODE_MASKS: [u16; DIALOG_GCD_K5_TAIL7_CODE_BITS] = + [0x0a20, 0x0140, 0x0009, 0x020c, 0x0082]; +const DIALOG_GCD_K5_TAIL7_CODE_CONSTANT: u8 = 1 << 4; +pub(crate) const DIALOG_GCD_K5_TAIL7_SUPPORT: [u32; 20] = [ + 0x124924, 0x124925, 0x124929, 0x12492b, 0x124928, 0x12492d, 0x12492f, + 0x12494b, 0x124947, 0x124945, 0x12492c, 0x124958, 0x124949, 0x12495b, + 0x124959, 0x124967, 0x12495d, 0x124a4b, 0x12497f, 0x124979, +]; +const DIALOG_GCD_K5_TAIL7_RAW_ANF: [&[u16]; 12] = [ + &[1, 4, 7, 10, 12, 24, 28], + &[0, 16], + &[0, 7, 8, 10, 12, 24, 28], + &[1, 7, 10, 12, 24, 28], + &[1, 8, 9, 26], + &[], + &[11], + &[], + &[2, 11], + &[0, 1], + &[0, 11], + &[0], +]; + +fn dialog_gcd_toggle_mcx_with_dirty( + b: &mut B, + controls: &[QubitId], + dirty: &[QubitId], + target: QubitId, +) { + assert!(!controls.contains(&target)); + assert!(controls + .iter() + .enumerate() + .all(|(index, q)| !controls[..index].contains(q))); + match controls.len() { + 0 => b.x(target), + 1 => b.cx(controls[0], target), + 2 => b.ccx(controls[0], controls[1], target), + count => { + assert!(dirty.len() >= count - 2); + let bridge = dirty[0]; + assert_ne!(bridge, target); + assert!(!controls.contains(&bridge)); + dialog_gcd_toggle_mcx_with_dirty( + b, + &controls[..count - 1], + &dirty[1..], + bridge, + ); + b.ccx(bridge, controls[count - 1], target); + dialog_gcd_toggle_mcx_with_dirty( + b, + &controls[..count - 1], + &dirty[1..], + bridge, + ); + b.ccx(bridge, controls[count - 1], target); + } + } +} + +fn dialog_gcd_toggle_anf_with_dirty( + b: &mut B, + code: &[QubitId], + target: QubitId, + dirty_pool: &[QubitId], + terms: &[u16], +) { + assert!(code.len() <= u16::BITS as usize); + assert!(!code.contains(&target)); + for &mask in terms { + let controls = code + .iter() + .enumerate() + .filter_map(|(index, &q)| ((mask >> index) & 1 != 0).then_some(q)) + .collect::>(); + let dirty = dirty_pool + .iter() + .copied() + .filter(|q| *q != target && !controls.contains(q)) + .collect::>(); + dialog_gcd_toggle_mcx_with_dirty(b, &controls, &dirty, target); + } +} + +fn dialog_gcd_k5_tail6_graph9_toggle_code_from_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (code_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS + .iter() + .enumerate() + { + for raw_bit in 0..12 { + if (mask >> raw_bit) & 1 != 0 { + b.cx(raw_block[raw_bit], code[code_index]); + } + } + } +} + +fn dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (raw_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS + .iter() + .enumerate() + { + if (DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT >> raw_index) & 1 != 0 { + b.x(raw_block[raw_index]); + } + for code_bit in 0..DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS { + if (mask >> code_bit) & 1 != 0 { + b.cx(code[code_bit], raw_block[raw_index]); + } + } + } +} + +fn dialog_gcd_k5_tail6_graph9_toggle_selector_fanout( + b: &mut B, + raw_block: &[QubitId], +) { + assert_eq!(raw_block.len(), 15); + assert_ne!( + (DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK + >> DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT) + & 1, + 0 + ); + let pivot = raw_block[DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT]; + for raw_index in 0..12 { + if raw_index != DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT + && (DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK >> raw_index) & 1 != 0 + { + b.cx(pivot, raw_block[raw_index]); + } + } +} + +fn dialog_gcd_k5_tail6_graph9_toggle_selector( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_toggle_anf_with_dirty( + b, + code, + raw_block[DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_PIVOT], + raw_block, + DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF, + ); +} + +fn dialog_gcd_k5_tail6_graph9_compress_raw_to_block( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail6_graph9_toggle_code_from_raw(b, code, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code(b, code, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_selector_fanout(b, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_selector(b, code, raw_block); +} + +fn dialog_gcd_k5_tail6_graph9_decompress_block_to_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail6_graph9_toggle_selector(b, code, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_selector_fanout(b, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_linear_raw_from_code(b, code, raw_block); + dialog_gcd_k5_tail6_graph9_toggle_code_from_raw(b, code, raw_block); +} + +fn dialog_gcd_k5_tail6_graph9_raw_word(pattern: u32) -> u16 { + let mut raw_word = 0u16; + for slot in 0..DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS { + let digit = ((pattern >> (3 * slot)) & 7) as u16; + raw_word |= (digit & 1) << (2 * slot); + raw_word |= ((digit >> 1) & 1) << (2 * slot + 1); + raw_word |= ((digit >> 2) & 1) + << (2 * DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS + slot); + } + raw_word +} + +fn dialog_gcd_k5_tail6_graph9_code_word(raw_word: u16) -> u16 { + DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_MASKS + .iter() + .enumerate() + .fold(0u16, |code, (index, &mask)| { + code ^ ((((raw_word & mask).count_ones() & 1) as u16) << index) + }) +} + +fn dialog_gcd_k5_tail6_graph9_selector_word(code: u16) -> u16 { + DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_ANF + .iter() + .fold(0u16, |selector, &term| { + selector ^ u16::from(code & term == term) + }) +} + +fn dialog_gcd_k5_tail6_graph9_decode_word(code: u16) -> u16 { + let selector = dialog_gcd_k5_tail6_graph9_selector_word(code); + DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CODE_DECODE_MASKS + .iter() + .enumerate() + .fold(DIALOG_GCD_K5_TAIL6_GRAPH9_RAW_CONSTANT, |raw, (index, &mask)| { + let bit = ((code & mask).count_ones() & 1) as u16 + ^ (selector + & ((DIALOG_GCD_K5_TAIL6_GRAPH9_SELECTOR_RAW_MASK >> index) & 1)); + raw ^ (bit << index) + }) +} + +pub(crate) fn dialog_gcd_k5_tail6_graph9_supports(pattern: u32) -> bool { + if pattern >> 12 != 0x24 { + return false; + } + let raw = dialog_gcd_k5_tail6_graph9_raw_word(pattern); + let code = dialog_gcd_k5_tail6_graph9_code_word(raw); + dialog_gcd_k5_tail6_graph9_decode_word(code) == raw +} + +pub(crate) fn dialog_gcd_k5_tail6_graph9_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + for batch_start in (0..DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT.len()).step_by(64) { + let patterns = &DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT + [batch_start..(batch_start + 64).min(DIALOG_GCD_K5_TAIL6_GRAPH9_SUPPORT.len())]; + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS]; + for (shot, &pattern) in patterns.iter().enumerate() { + if !dialog_gcd_k5_tail6_graph9_supports(pattern) { + return Err(format!("support pattern 0x{pattern:x} fails graph relation")); + } + let shot_bit = 1u64 << shot; + let raw_word = dialog_gcd_k5_tail6_graph9_raw_word(pattern); + for raw_bit in 0..12 { + if (raw_word >> raw_bit) & 1 != 0 { + raw_masks[raw_bit] |= shot_bit; + } + } + let code = dialog_gcd_k5_tail6_graph9_code_word(raw_word); + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_tail6_graph9_decompress_block_to_raw(&mut b, &code, &raw); + } else { + dialog_gcd_k5_tail6_graph9_compress_raw_to_block(&mut b, &code, &raw); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |decompress: bool| { + let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail6-graph9-codec-selftest"); + seed.update(&(batch_start as u64).to_le_bytes()); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let active_mask = if patterns.len() == 64 { + u64::MAX + } else { + (1u64 << patterns.len()) - 1 + }; + let (forward_code, forward_raw, forward_phase) = run(false); + if forward_phase & active_mask != 0 { + return Err(format!( + "forward phase garbage in batch {batch_start}: 0x{:x}", + forward_phase & active_mask + )); + } + if forward_code + .iter() + .zip(code_masks.iter()) + .any(|(&got, &want)| (got ^ want) & active_mask != 0) + { + return Err(format!( + "forward code mismatch in batch {batch_start}: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw + .iter() + .any(|&mask| mask & active_mask != 0) + { + return Err(format!( + "forward raw garbage in batch {batch_start}: {forward_raw:x?}" + )); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true); + if reverse_phase & active_mask != 0 { + return Err(format!( + "reverse phase garbage in batch {batch_start}: 0x{:x}", + reverse_phase & active_mask + )); + } + if reverse_code + .iter() + .any(|&mask| mask & active_mask != 0) + { + return Err(format!( + "reverse code garbage in batch {batch_start}: {reverse_code:x?}" + )); + } + if reverse_raw + .iter() + .zip(raw_masks.iter()) + .any(|(&got, &want)| (got ^ want) & active_mask != 0) + { + return Err(format!( + "reverse raw mismatch in batch {batch_start}: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + } + Ok(()) +} + +fn dialog_gcd_k5_tail6_graph_toggle_code_from_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (code_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS + .iter() + .enumerate() + { + for raw_bit in 0..9 { + if (mask >> raw_bit) & 1 != 0 { + b.cx(raw_block[raw_bit], code[code_index]); + } + } + if (DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT >> code_index) & 1 != 0 { + b.x(code[code_index]); + } + } +} + +fn dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (raw_index, &mask) in DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_DECODE_MASKS + .iter() + .enumerate() + { + if (DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CONSTANT >> raw_index) & 1 != 0 { + b.x(raw_block[raw_index]); + } + for code_bit in 0..DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS { + if (mask >> code_bit) & 1 != 0 { + b.cx(code[code_bit], raw_block[raw_index]); + } + } + } +} + +fn dialog_gcd_k5_tail6_graph_toggle_selector_fanout( + b: &mut B, + raw_block: &[QubitId], +) { + assert_eq!(raw_block.len(), 15); + let pivot = raw_block[0]; + assert_eq!(DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK & 1, 1); + for raw_index in 1..9 { + if (DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_RAW_MASK >> raw_index) & 1 != 0 { + b.cx(pivot, raw_block[raw_index]); + } + } +} + +fn dialog_gcd_k5_tail6_graph_toggle_selector( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_toggle_anf_with_dirty( + b, + code, + raw_block[0], + raw_block, + DIALOG_GCD_K5_TAIL6_GRAPH_SELECTOR_ANF, + ); +} + +fn dialog_gcd_k5_tail6_graph_compress_raw_to_block( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail6_graph_toggle_code_from_raw(b, code, raw_block); + dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code(b, code, raw_block); + dialog_gcd_k5_tail6_graph_toggle_selector_fanout(b, raw_block); + dialog_gcd_k5_tail6_graph_toggle_selector(b, code, raw_block); +} + +fn dialog_gcd_k5_tail6_graph_decompress_block_to_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail6_graph_toggle_selector(b, code, raw_block); + dialog_gcd_k5_tail6_graph_toggle_selector_fanout(b, raw_block); + dialog_gcd_k5_tail6_graph_toggle_linear_raw_from_code(b, code, raw_block); + dialog_gcd_k5_tail6_graph_toggle_code_from_raw(b, code, raw_block); +} + +pub(crate) fn dialog_gcd_k5_tail6_graph_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS]; + for shot in 0..64 { + let pattern = + DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT[shot % DIALOG_GCD_K5_TAIL6_GRAPH_SUPPORT.len()]; + let shot_bit = 1u64 << shot; + let mut raw_word = 0u16; + for slot in 0..DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS { + if (pattern >> (3 * slot)) & 1 != 0 { + raw_masks[2 * slot] |= shot_bit; + raw_word |= 1 << (2 * slot); + } + if (pattern >> (3 * slot + 1)) & 1 != 0 { + raw_masks[2 * slot + 1] |= shot_bit; + raw_word |= 1 << (2 * slot + 1); + } + if (pattern >> (3 * slot + 2)) & 1 != 0 { + let raw_index = 2 * DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS + slot; + raw_masks[raw_index] |= shot_bit; + raw_word |= 1 << raw_index; + } + } + let code = DIALOG_GCD_K5_TAIL6_GRAPH_RAW_CODE_MASKS + .iter() + .enumerate() + .fold(DIALOG_GCD_K5_TAIL6_GRAPH_CODE_CONSTANT, |packed, (index, &mask)| { + packed ^ ((((raw_word & mask).count_ones() & 1) as u8) << index) + }); + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_tail6_graph_decompress_block_to_raw(&mut b, &code, &raw); + } else { + dialog_gcd_k5_tail6_graph_compress_raw_to_block(&mut b, &code, &raw); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |decompress: bool| { + let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail6-graph-codec-selftest"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let (forward_code, forward_raw, forward_phase) = run(false); + if forward_phase != 0 { + return Err(format!("forward phase garbage 0x{forward_phase:x}")); + } + if forward_code != code_masks { + return Err(format!( + "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw.iter().any(|&mask| mask != 0) { + return Err(format!("forward raw garbage: {forward_raw:x?}")); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true); + if reverse_phase != 0 { + return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); + } + if reverse_code.iter().any(|&mask| mask != 0) { + return Err(format!("reverse code garbage: {reverse_code:x?}")); + } + if reverse_raw != raw_masks { + return Err(format!( + "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + Ok(()) +} + +fn dialog_gcd_k5_tail7_toggle_code_from_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL7_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (code_index, &mask) in DIALOG_GCD_K5_TAIL7_RAW_CODE_MASKS.iter().enumerate() { + for raw_bit in 0..12 { + if (mask >> raw_bit) & 1 != 0 { + b.cx(raw_block[raw_bit], code[code_index]); + } + } + if (DIALOG_GCD_K5_TAIL7_CODE_CONSTANT >> code_index) & 1 != 0 { + b.x(code[code_index]); + } + } +} + +fn dialog_gcd_k5_tail7_toggle_raw_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL7_CODE_BITS); + assert_eq!(raw_block.len(), 15); + for (raw_index, terms) in DIALOG_GCD_K5_TAIL7_RAW_ANF.iter().enumerate() { + dialog_gcd_toggle_anf_with_dirty(b, code, raw_block[raw_index], raw_block, terms); + } +} + +fn dialog_gcd_k5_tail7_compress_raw_to_block( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail7_toggle_code_from_raw(b, code, raw_block); + dialog_gcd_k5_tail7_toggle_raw_from_code(b, code, raw_block); +} + +fn dialog_gcd_k5_tail7_decompress_block_to_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + dialog_gcd_k5_tail7_toggle_raw_from_code(b, code, raw_block); + dialog_gcd_k5_tail7_toggle_code_from_raw(b, code, raw_block); +} + +fn dialog_gcd_k5_tail3_transfer_survivors( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + assert_eq!(raw_block.len(), 15); + for (index, &wire) in DIALOG_GCD_K5_TAIL3_DATA_WIRES.iter().enumerate() { + if swap_host { + b.swap(compressed_block[index], raw_block[wire]); + } else { + b.cx(compressed_block[index], raw_block[wire]); + } + } +} + +fn dialog_gcd_k5_tail3_top32_raw(raw_block: &[QubitId]) -> [QubitId; 9] { + assert_eq!(raw_block.len(), 15); + DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES.map(|wire| raw_block[wire]) +} + +fn dialog_gcd_k5_tail3_top32_toggle_code_from_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); + let code_constant = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { + DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_CODE_CONSTANT + } else { + DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT + }; + for code_index in 0..DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF.len() { + let terms = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { + DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_ENCODER_ANF[code_index] + } else { + DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF[code_index] + }; + if (code_constant >> code_index) & 1 != 0 { + b.x(code[code_index]); + } + for &mask in terms { + let controls = raw + .iter() + .enumerate() + .filter_map(|(index, &q)| ((mask >> index) & 1 != 0).then_some(q)) + .collect::>(); + assert!(controls.len() <= 2); + dialog_gcd_toggle_mcx_with_dirty(b, &controls, raw_block, code[code_index]); + } + } +} + +fn dialog_gcd_k5_tail3_top32_toggle_raw_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(code.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); + for raw_index in 0..DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF.len() { + let terms = if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { + DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF[raw_index] + } else { + DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index] + }; + dialog_gcd_toggle_anf_with_dirty(b, code, raw[raw_index], raw_block, terms); + } +} + +fn dialog_gcd_k5_tail3_top32_slot_raw( + raw_block: &[QubitId], + slot: usize, +) -> [QubitId; 3] { + assert_eq!(raw_block.len(), 15); + assert!(slot < 3); + [raw_block[2 * slot], raw_block[2 * slot + 1], raw_block[10 + slot]] +} + +fn dialog_gcd_k5_tail3_top32_slot_branch_raw( + raw_block: &[QubitId], + slot: usize, +) -> [QubitId; 2] { + assert_eq!(raw_block.len(), 15); + assert!(slot < 3); + [raw_block[2 * slot], raw_block[2 * slot + 1]] +} + +fn dialog_gcd_k5_tail3_top32_slot_shift_raw( + raw_block: &[QubitId], + slot: usize, +) -> [QubitId; 1] { + assert_eq!(raw_block.len(), 15); + assert!(slot < 3); + [raw_block[10 + slot]] +} + +fn dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + raw_indices: &[usize], +) { + let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); + for &raw_index in raw_indices { + dialog_gcd_toggle_anf_with_dirty( + b, + code, + raw[raw_index], + raw_block, + if dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() { + DIALOG_GCD_K5_TAIL3_TOP32_S2CONST_DECODER_ANF[raw_index] + } else { + DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index] + }, + ); + } +} + +fn dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + slot: usize, +) { + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b, + code, + raw_block, + &[2 * slot, 2 * slot + 1], + ); +} + +fn dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + slot: usize, +) { + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code(b, code, raw_block, &[6 + slot]); +} + +fn dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + slot: usize, +) { + let raw = dialog_gcd_k5_tail3_top32_raw(raw_block); + for raw_index in [2 * slot, 2 * slot + 1, 6 + slot] { + dialog_gcd_toggle_anf_with_dirty( + b, + code, + raw[raw_index], + raw_block, + DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF[raw_index], + ); + } +} + +fn dialog_gcd_k5_tail3_top32_stream_scratch(raw_block: &[QubitId]) -> Vec { + assert_eq!(raw_block.len(), 15); + DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES + .iter() + .map(|&wire| raw_block[wire]) + .collect() +} + +fn dialog_gcd_k5_tail3_top32_stream_dynamic(raw_block: &[QubitId]) -> Vec { + assert_eq!(raw_block.len(), 15); + raw_block + .iter() + .enumerate() + .filter_map(|(wire, &q)| { + (!DIALOG_GCD_K5_TAIL3_TOP32_STREAM_SCRATCH_WIRES.contains(&wire)).then_some(q) + }) + .collect() +} + +fn dialog_gcd_k5_tail3_top32_compress_raw_to_block( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + if swap_host { + dialog_gcd_k5_tail3_top32_toggle_code_from_raw(b, code, raw_block); + } + dialog_gcd_k5_tail3_top32_toggle_raw_from_code(b, code, raw_block); +} + +fn dialog_gcd_k5_tail3_top32_decompress_block_to_raw( + b: &mut B, + code: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + dialog_gcd_k5_tail3_top32_toggle_raw_from_code(b, code, raw_block); + if swap_host { + dialog_gcd_k5_tail3_top32_toggle_code_from_raw(b, code, raw_block); + } +} + +fn dialog_gcd_k5_tail3_top32_raw_word(pattern: u16) -> u16 { + (0..3).fold(0u16, |raw, slot| { + let digit = (pattern >> (3 * slot)) & 7; + raw + | ((digit & 1) << (2 * slot)) + | (((digit >> 1) & 1) << (2 * slot + 1)) + | (((digit >> 2) & 1) << (6 + slot)) + }) +} + +fn dialog_gcd_k5_tail3_top32_code_word(raw: u16) -> u8 { + DIALOG_GCD_K5_TAIL3_TOP32_ENCODER_ANF + .iter() + .enumerate() + .fold(DIALOG_GCD_K5_TAIL3_TOP32_CODE_CONSTANT, |code, (index, terms)| { + let bit = terms + .iter() + .fold(0u8, |value, &mask| value ^ u8::from(raw & mask == mask)); + code ^ (bit << index) + }) +} + +fn dialog_gcd_k5_tail3_top32_decode_word(code: u8) -> u16 { + DIALOG_GCD_K5_TAIL3_TOP32_DECODER_ANF + .iter() + .enumerate() + .fold(0u16, |raw, (index, terms)| { + let bit = terms.iter().fold(0u16, |value, &mask| { + value ^ u16::from((u16::from(code) & mask) == mask) + }); + raw ^ (bit << index) + }) +} + +pub(crate) fn dialog_gcd_k5_tail3_top32_supports(pattern: u16) -> bool { + DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT.contains(&pattern) +} + +pub(crate) fn dialog_gcd_k5_tail3_top32_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let mut seen_codes = [false; 1 << DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; + for &pattern in &DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT { + let raw = dialog_gcd_k5_tail3_top32_raw_word(pattern); + let code = dialog_gcd_k5_tail3_top32_code_word(raw); + if std::mem::replace(&mut seen_codes[code as usize], true) { + return Err(format!( + "duplicate top32 code for pattern 0x{pattern:03x}: 0x{code:02x}" + )); + } + let decoded = dialog_gcd_k5_tail3_top32_decode_word(code); + if decoded != raw { + return Err(format!( + "top32 word mismatch for pattern 0x{pattern:03x}: got 0x{decoded:03x}, want 0x{raw:03x}" + )); + } + } + if seen_codes.iter().any(|seen| !seen) { + return Err("top32 codec does not cover all 32 code words".to_string()); + } + + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; + for shot in 0..64 { + let pattern = DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT + [shot % DIALOG_GCD_K5_TAIL3_TOP32_SUPPORT.len()]; + let raw = dialog_gcd_k5_tail3_top32_raw_word(pattern); + let code = dialog_gcd_k5_tail3_top32_code_word(raw); + let shot_bit = 1u64 << shot; + for (index, &wire) in DIALOG_GCD_K5_TAIL3_TOP32_RAW_WIRES + .iter() + .enumerate() + { + if (raw >> index) & 1 != 0 { + raw_masks[wire] |= shot_bit; + } + } + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_tail3_top32_decompress_block_to_raw(&mut b, &code, &raw, true); + } else { + dialog_gcd_k5_tail3_top32_compress_raw_to_block(&mut b, &code, &raw, true); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |decompress: bool, source: &[u64]| { + let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail3-top32-codec-selftest"); + seed.update(&[u8::from(decompress)]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let (forward_code, forward_raw, forward_phase) = run(false, &raw_masks); + if forward_phase != 0 { + return Err(format!("top32 forward phase garbage 0x{forward_phase:x}")); + } + if forward_code != code_masks { + return Err(format!( + "top32 forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw.iter().any(|&mask| mask != 0) { + return Err(format!("top32 forward raw garbage: {forward_raw:x?}")); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true, &code_masks); + if reverse_phase != 0 { + return Err(format!("top32 reverse phase garbage 0x{reverse_phase:x}")); + } + if reverse_code.iter().any(|&mask| mask != 0) { + return Err(format!("top32 reverse code garbage: {reverse_code:x?}")); + } + if reverse_raw != raw_masks { + return Err(format!( + "top32 reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + Ok(()) +} + +fn dialog_gcd_k5_tail3_compress_raw_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + assert_eq!(raw_block.len(), 15); + emit_dialog_gcd_k5_pair_encoder(b, &dialog_gcd_k5_pair01(raw_block)); + dialog_gcd_k5_tail3_transfer_survivors(b, compressed_block, raw_block, swap_host); +} + +fn dialog_gcd_k5_tail3_decompress_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + assert_eq!(raw_block.len(), 15); + dialog_gcd_k5_tail3_transfer_survivors(b, compressed_block, raw_block, swap_host); + emit_dialog_gcd_k5_pair_encoder_inverse(b, &dialog_gcd_k5_pair01(raw_block)); +} + +fn dialog_gcd_k5_tail3_code_word(left: u8, right: u8) -> Option { + let mut raw = [false; 15]; + for (slot, digit) in [left, right].into_iter().enumerate() { + raw[3 * slot] = digit & 1 != 0; + raw[3 * slot + 1] = digit & 2 != 0; + raw[3 * slot + 2] = digit & 4 != 0; + } + dialog_gcd_k5_head11_pair_encode_word(&mut raw, [0, 1]); + if raw[0] { + return None; + } + Some( + [1usize, 2, 3, 4, 5] + .iter() + .enumerate() + .fold(0u8, |code, (index, &wire)| { + code | (u8::from(raw[wire]) << index) + }), + ) +} + +pub(crate) fn dialog_gcd_k5_tail3_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + const DIGITS: [u8; 6] = [0, 1, 3, 4, 5, 7]; + let supported = DIGITS + .into_iter() + .flat_map(|left| DIGITS.into_iter().map(move |right| (left, right))) + .filter(|&(left, right)| dialog_gcd_k5_tail3_code_word(left, right).is_some()) + .collect::>(); + if supported.len() != 30 { + return Err(format!( + "expected 30 supported tail pairs, got {}", + supported.len() + )); + } + let mut seen_codes = [false; 1 << DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; + for &(left, right) in &supported { + let code = dialog_gcd_k5_tail3_code_word(left, right).expect("filtered support"); + if std::mem::replace(&mut seen_codes[code as usize], true) { + return Err(format!( + "duplicate tail-pair code for digits ({left}, {right}): 0x{code:02x}" + )); + } + } + + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()]; + for shot in 0..64 { + let (left, right) = supported[shot % supported.len()]; + let shot_bit = 1u64 << shot; + for (slot, digit) in [left, right].into_iter().enumerate() { + if digit & 1 != 0 { + raw_masks[2 * slot] |= shot_bit; + } + if digit & 2 != 0 { + raw_masks[2 * slot + 1] |= shot_bit; + } + if digit & 4 != 0 { + raw_masks[10 + slot] |= shot_bit; + } + } + let code = dialog_gcd_k5_tail3_code_word(left, right).expect("supported pair"); + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_tail3_decompress_block_to_raw(&mut b, &code, &raw, true); + } else { + dialog_gcd_k5_tail3_compress_raw_to_block(&mut b, &code, &raw, true); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |decompress: bool, source: &[u64]| { + let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail3-codec-selftest"); + seed.update(&[u8::from(decompress)]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let (forward_code, forward_raw, forward_phase) = run(false, &raw_masks); + if forward_phase != 0 { + return Err(format!("forward phase garbage 0x{forward_phase:x}")); + } + if forward_code != code_masks { + return Err(format!( + "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw.iter().any(|&mask| mask != 0) { + return Err(format!("forward raw garbage: {forward_raw:x?}")); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true, &forward_code); + if reverse_phase != 0 { + return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); + } + if reverse_code.iter().any(|&mask| mask != 0) { + return Err(format!("reverse code garbage: {reverse_code:x?}")); + } + if reverse_raw != raw_masks { + return Err(format!( + "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + Ok(()) +} + +pub(crate) fn dialog_gcd_k5_tail7_codec_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let mut raw_masks = [0u64; 15]; + let mut code_masks = [0u64; DIALOG_GCD_K5_TAIL7_CODE_BITS]; + for shot in 0..64 { + let pattern = DIALOG_GCD_K5_TAIL7_SUPPORT[shot % DIALOG_GCD_K5_TAIL7_SUPPORT.len()]; + let shot_bit = 1u64 << shot; + for slot in 0..DIALOG_GCD_K5_TAIL7_STORED_STEPS { + if (pattern >> (3 * slot)) & 1 != 0 { + raw_masks[2 * slot] |= shot_bit; + } + if (pattern >> (3 * slot + 1)) & 1 != 0 { + raw_masks[2 * slot + 1] |= shot_bit; + } + if (pattern >> (3 * slot + 2)) & 1 != 0 { + raw_masks[2 * DIALOG_GCD_K5_TAIL7_STORED_STEPS + slot] |= shot_bit; + } + } + let code = DIALOG_GCD_K5_TAIL7_PACKED_CODE_MASKS + .iter() + .enumerate() + .fold(0u8, |packed, (index, &mask)| { + packed | ((((pattern & mask).count_ones() & 1) as u8) << index) + }); + for (index, mask) in code_masks.iter_mut().enumerate() { + if (code >> index) & 1 != 0 { + *mask |= shot_bit; + } + } + } + + let build_codec = |decompress: bool| { + let mut b = B::new(); + let code = b.alloc_qubits(DIALOG_GCD_K5_TAIL7_CODE_BITS); + let raw = b.alloc_qubits(15); + if decompress { + dialog_gcd_k5_tail7_decompress_block_to_raw(&mut b, &code, &raw); + } else { + dialog_gcd_k5_tail7_compress_raw_to_block(&mut b, &code, &raw); + } + (b.ops, code, raw, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |decompress: bool| { + let (ops, code, raw, num_qubits, num_bits) = build_codec(decompress); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail7-codec-selftest"); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + let source = if decompress { &code_masks[..] } else { &raw_masks[..] }; + let targets = if decompress { &code[..] } else { &raw[..] }; + for (&qubit, &mask) in targets.iter().zip(source.iter()) { + *sim.qubit_mut(qubit) = mask; + } + sim.apply_iter(ops.iter()); + ( + code.iter().map(|&q| sim.qubit(q)).collect::>(), + raw.iter().map(|&q| sim.qubit(q)).collect::>(), + sim.phase, + ) + }; + + let (forward_code, forward_raw, forward_phase) = run(false); + if forward_phase != 0 { + return Err(format!("forward phase garbage 0x{forward_phase:x}")); + } + if forward_code != code_masks { + return Err(format!( + "forward code mismatch: got {forward_code:x?}, want {code_masks:x?}" + )); + } + if forward_raw.iter().any(|&mask| mask != 0) { + return Err(format!("forward raw garbage: {forward_raw:x?}")); + } + + let (reverse_code, reverse_raw, reverse_phase) = run(true); + if reverse_phase != 0 { + return Err(format!("reverse phase garbage 0x{reverse_phase:x}")); + } + if reverse_code.iter().any(|&mask| mask != 0) { + return Err(format!("reverse code garbage: {reverse_code:x?}")); + } + if reverse_raw != raw_masks { + return Err(format!( + "reverse raw mismatch: got {reverse_raw:x?}, want {raw_masks:x?}" + )); + } + Ok(()) +} + +fn dialog_gcd_k5_tail_pair1_compress_raw_to_block( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 1); + assert_eq!(raw_block.len(), 15); + + if swap_host { + b.swap(compressed_block[0], raw_block[0]); + } else { + b.cx(compressed_block[0], raw_block[0]); + } + b.x(dialog_gcd_raw_s2(raw_block, 0)); + b.x(dialog_gcd_raw_s2(raw_block, 1)); +} + +fn dialog_gcd_k5_tail_pair1_decompress_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + swap_host: bool, +) { + assert_eq!(compressed_block.len(), 1); + assert_eq!(raw_block.len(), 15); + b.x(dialog_gcd_raw_s2(raw_block, 1)); + b.x(dialog_gcd_raw_s2(raw_block, 0)); + if swap_host { + b.swap(compressed_block[0], raw_block[0]); + } else { + b.cx(compressed_block[0], raw_block[0]); + } +} + +pub(crate) fn emit_dialog_gcd_round763_compressed_block_swapper( + b: &mut B, + pair: &[QubitId], + compressed_block: &[QubitId], + scratch: QubitId, + slot: usize, +) { + assert_eq!(pair.len(), 2); + assert_eq!(compressed_block.len(), 5); + assert!(slot < 3); + let mut block = compressed_block.to_vec(); + block.push(scratch); + emit_dialog_gcd_round763_compressor_inverse(b, &block); + b.swap(pair[0], block[2 * slot]); + b.swap(pair[1], block[2 * slot + 1]); + emit_dialog_gcd_round763_compressor(b, &block); +} + +pub(crate) fn dialog_gcd_compressed_sidecar_blocks() -> usize { + let group_size = dialog_gcd_sidecar_group_size(); + let blocks = (dialog_gcd_active_iterations() + group_size - 1) / group_size; + if dialog_gcd_k5_tail7_enabled() + || dialog_gcd_k5_tail6_graph_enabled() + || dialog_gcd_k5_tail6_graph9_enabled() + { + blocks - 1 + } else { + blocks + } +} + +fn dialog_gcd_compressed_sidecar_block_index(step: usize) -> usize { + if dialog_gcd_k5_tail7_enabled() + && step >= dialog_gcd_active_iterations() - 7 + || dialog_gcd_k5_tail6_graph_enabled() + && step >= dialog_gcd_active_iterations() - 6 + || dialog_gcd_k5_tail6_graph9_enabled() + && step >= dialog_gcd_active_iterations() - 6 + { + dialog_gcd_compressed_sidecar_blocks() - 1 + } else { + step / dialog_gcd_sidecar_group_size() + } +} + +fn dialog_gcd_compressed_sidecar_block_bits(block: usize) -> usize { + if dialog_gcd_k5_head11_enabled() && block == 0 { + DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + } else if dialog_gcd_k5_tail6_graph9_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS + } else if dialog_gcd_k5_tail6_graph_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS + } else if dialog_gcd_k5_tail7_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + DIALOG_GCD_K5_TAIL7_CODE_BITS + } else if dialog_gcd_k5_tail_pair1_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + 1 + } else if (dialog_gcd_k5_tail3_fixed_last_enabled() + || dialog_gcd_k5_tail3_top32_enabled()) + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + } else if dialog_gcd_k5_tight_partial_block_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let steps = end - start; + if steps < dialog_gcd_sidecar_group_size() { + DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + steps + } else { + dialog_gcd_block_bits() + } + } else { + dialog_gcd_block_bits() + } +} + +fn dialog_gcd_compressed_sidecar_block_offset(block: usize) -> usize { + (0..block) + .map(dialog_gcd_compressed_sidecar_block_bits) + .sum() +} + +pub(crate) fn dialog_gcd_compressed_sidecar_bits() -> usize { + (0..dialog_gcd_compressed_sidecar_blocks()) + .map(dialog_gcd_compressed_sidecar_block_bits) + .sum() +} + +pub(crate) fn dialog_gcd_compressed_sidecar_block(compressed_log: &[QubitId], step: usize) -> &[QubitId] { + let block = dialog_gcd_compressed_sidecar_block_index(step); + let start = dialog_gcd_compressed_sidecar_block_offset(block); + let bits = dialog_gcd_compressed_sidecar_block_bits(block); + &compressed_log[start..start + bits] +} + +pub(crate) fn dialog_gcd_compressed_log_u_high_runway_enabled() -> bool { + + std::env::var("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY") + .ok() + .as_deref() + == Some("1") +} + +fn dialog_gcd_k5_constant_tail_stored_steps(block_steps: usize) -> Option { + if dialog_gcd_k5_tail3_fixed_last_enabled() && block_steps == 3 { + Some(2) + } else if dialog_gcd_k5_tail6_graph9_enabled() && block_steps == 6 { + Some(DIALOG_GCD_K5_TAIL6_GRAPH9_STORED_STEPS) + } else if dialog_gcd_k5_tail6_graph_enabled() && block_steps == 6 { + Some(DIALOG_GCD_K5_TAIL6_GRAPH_STORED_STEPS) + } else if dialog_gcd_k5_tail7_enabled() && block_steps == 7 { + Some(DIALOG_GCD_K5_TAIL7_STORED_STEPS) + } else { + None + } +} + +fn dialog_gcd_k5_fixed_tail_apply_enabled() -> bool { + (dialog_gcd_k5_tail3_fixed_last_enabled() + || dialog_gcd_k5_tail7_enabled() + || dialog_gcd_k5_tail6_graph_enabled() + || dialog_gcd_k5_tail6_graph9_enabled()) + && (std::env::var("DIALOG_GCD_K5_FIXED_TAIL_APPLY") + .ok() + .as_deref() + == Some("1") + || std::env::var("DIALOG_GCD_K5_TAIL7_UNCONDITIONAL_APPLY") + .ok() + .as_deref() + == Some("1")) +} + +pub(crate) fn dialog_gcd_compressed_log_u_high_runway_blocks() -> usize { + + std::env::var("DIALOG_GCD_COMPRESSED_LOG_U_HIGH_RUNWAY_BLOCKS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(16) +} + +fn dialog_gcd_runway_partial_block_enabled() -> bool { + std::env::var("DIALOG_GCD_RUNWAY_PARTIAL_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +#[derive(Clone, Debug)] +pub(crate) struct DialogGcdCompressedLogUHighRunway { + remapped_log: Vec, + parked_u_indices: Vec, +} + +pub(crate) fn dialog_gcd_slice_intersects(a: &[QubitId], b: &[QubitId]) -> bool { + a.iter().any(|q| b.contains(q)) +} + +pub(crate) fn dialog_gcd_runway_layout() -> Vec<(usize, usize)> { + + let raw_block_bits = 2 * DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE; + let Some(highest_host) = N.checked_sub(raw_block_bits + 1) else { + return Vec::new(); + }; + let blocks = dialog_gcd_compressed_sidecar_blocks(); + + let first_allowed = blocks.saturating_sub(dialog_gcd_compressed_log_u_high_runway_blocks()); + for first_block in first_allowed..blocks { + let first_bits = dialog_gcd_compressed_sidecar_block_bits(first_block); + let first_slots = if dialog_gcd_runway_partial_block_enabled() { + 0..first_bits + } else { + 0..1 + }; + for first_slot in first_slots { + let mut next_host = highest_host; + let mut layout = Vec::with_capacity( + (first_block..blocks) + .map(dialog_gcd_compressed_sidecar_block_bits) + .sum::() + - first_slot, + ); + let mut fits = true; + for block in first_block..blocks { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let active_threshold = (start..end) + .map(dialog_gcd_tobitvector_active_width) + .max() + .unwrap_or(1); + let block_offset = dialog_gcd_compressed_sidecar_block_offset(block); + let slot_start = if block == first_block { first_slot } else { 0 }; + for slot in slot_start..dialog_gcd_compressed_sidecar_block_bits(block) { + if next_host < active_threshold { + fits = false; + break; + } + layout.push((block_offset + slot, next_host)); + let Some(next) = next_host.checked_sub(1) else { + fits = false; + break; + }; + next_host = next; + } + if !fits { + break; + } + } + if fits { + return layout; + } + } + } + Vec::new() +} + +pub(crate) fn dialog_gcd_allocated_compressed_sidecar_bits() -> usize { + if dialog_gcd_compressed_log_u_high_runway_enabled() { + dialog_gcd_compressed_sidecar_bits() - dialog_gcd_runway_layout().len() + } else { + dialog_gcd_compressed_sidecar_bits() + } +} + +pub(crate) fn dialog_gcd_build_compressed_log_u_high_runway( + u: &[QubitId], + allocated_log: &[QubitId], +) -> Option { + if !dialog_gcd_compressed_log_u_high_runway_enabled() { + return None; + } + assert_eq!(u.len(), N); + let layout = dialog_gcd_runway_layout(); + if layout.is_empty() { + return None; + } + + let expected_allocated = dialog_gcd_compressed_sidecar_bits() - layout.len(); + assert_eq!(allocated_log.len(), expected_allocated); + let first_relocated = layout[0].0; + assert_eq!(first_relocated, allocated_log.len()); + let mut remapped_log = allocated_log.to_vec(); + let mut parked_u_indices = Vec::with_capacity(layout.len()); + for (log_index, u_index) in layout { + + assert_eq!(log_index, remapped_log.len()); + remapped_log.push(u[u_index]); + parked_u_indices.push(u_index); + } + assert_eq!(remapped_log.len(), dialog_gcd_compressed_sidecar_bits()); + Some(DialogGcdCompressedLogUHighRunway { + remapped_log, + parked_u_indices, + }) +} + +pub(crate) fn dialog_gcd_release_terminal_u( + b: &mut B, + u: &[QubitId], + runway: Option<&DialogGcdCompressedLogUHighRunway>, +) { + for (index, &q) in u.iter().enumerate() { + if runway.is_none_or(|r| !r.parked_u_indices.contains(&index)) { + b.free(q); + } + } +} + +pub(crate) fn dialog_gcd_reacquire_terminal_u( + b: &mut B, + u: &[QubitId], + runway: Option<&DialogGcdCompressedLogUHighRunway>, +) { + for (index, &q) in u.iter().enumerate() { + if runway.is_none_or(|r| !r.parked_u_indices.contains(&index)) { + b.reacquire(q); + } + } +} + +pub(crate) fn dialog_gcd_runway_safe_future_prefix<'a>( + future: Option<&'a [QubitId]>, + u: &[QubitId], + active_width: usize, +) -> Option<&'a [QubitId]> { + let active_u = &u[..active_width]; + future + .map(|slice| { + let safe = slice + .iter() + .position(|q| active_u.contains(q)) + .unwrap_or(slice.len()); + &slice[..safe] + }) + .filter(|slice| !slice.is_empty()) +} + +pub(crate) fn dialog_gcd_composite_scratch_enabled() -> bool { + std::env::var("DIALOG_GCD_COMPOSITE_SCRATCH") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_borrow_current_block_enabled() -> bool { + + std::env::var("DIALOG_GCD_BORROW_CURRENT_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_borrow_current_s2_enabled() -> bool { + + std::env::var("DIALOG_GCD_BORROW_CURRENT_S2") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_cshift_enabled() -> bool { + std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_tobit_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_tobit_fwd_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_tobit_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_FWD_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_tobit_rev_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_tobit_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_TOBIT_REV_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_apply_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_apply_double_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_apply_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_DOUBLE_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_skip_zero_edge_apply_halve_cshift_enabled() -> bool { + dialog_gcd_skip_zero_edge_apply_cshift_enabled() + || std::env::var("DIALOG_GCD_SKIP_ZERO_EDGE_APPLY_HALVE_CSHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_borrow_zero_raw_future_enabled() -> bool { + + std::env::var("DIALOG_GCD_BORROW_ZERO_RAW_FUTURE") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) struct DialogGcdCompositeScratch { + lanes: Vec, + owned: Vec, +} + +pub(crate) fn dialog_gcd_build_composite_scratch( + b: &mut B, + future: Option<&[QubitId]>, + u: &[QubitId], + v: &[QubitId], + compressed_log: &[QubitId], + raw_block: &[QubitId], + active_width: usize, + step: usize, +) -> DialogGcdCompositeScratch { + + let body_start = if dialog_gcd_odd_u_lowbit_fastpath_enabled() { + 1 + } else { + 0 + }; + let body_w = dialog_gcd_body_carry_trunc_width(active_width, step); + let body_len = body_w.saturating_sub(body_start); + let nocin = dialog_gcd_selected_body_nocin_enabled() + && !dialog_gcd_selected_body_nocin_keep_pool() + && body_start >= 1 + && body_len >= 1; + let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); + let want = if !dialog_gcd_raw_tobitvector_materialized_sub_enabled() { + + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + let comparator_need = compare_bits + 1; + let body_need = if dialog_gcd_ctrl_body_vented_enabled() { + active_width.saturating_sub(1) + } else { + 0 + }; + comparator_need.max(body_need).min(2 * active_width - 1).max(1) + } else if nocin && stream_suffix >= 2 { + 2 * (body_len - stream_suffix) + 1 + } else if nocin && dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 + { + 2 * (body_len - 1) + } else if nocin { + + (2 * body_len - 1).min(2 * active_width - 1) + } else { + 2 * active_width - 1 + }; + let mut lanes = Vec::with_capacity(want); + let mut push = |q: QubitId| { + if lanes.len() < want + && !lanes.contains(&q) + && !raw_block.contains(&q) + && !u[..active_width].contains(&q) + && !v[..active_width].contains(&q) + { + lanes.push(q); + } + }; + if let Some(future) = dialog_gcd_runway_safe_future_prefix(future, u, active_width) { + for &q in future { + push(q); + } + } + if dialog_gcd_borrow_current_block_enabled() { + + let block_cells = dialog_gcd_compressed_sidecar_block(compressed_log, step); + for &q in block_cells { + push(q); + } + } + for &q in &v[active_width..] { + push(q); + } + for &q in &u[active_width..] { + if !compressed_log.contains(&q) { + push(q); + } + } + if dialog_gcd_borrow_current_s2_enabled() && !raw_block.is_empty() { + + let group_size = dialog_gcd_sidecar_group_size(); + let slot = step % group_size; + let s2 = raw_block[2 * group_size + slot]; + if lanes.len() < want + && !lanes.contains(&s2) + && !u[..active_width].contains(&s2) + && !v[..active_width].contains(&s2) + { + lanes.push(s2); + } + if dialog_gcd_trio_width_notch_enabled() && slot == 0 && group_size >= 2 { + let sibling_s2 = raw_block[2 * group_size + 1]; + if lanes.len() < want + && !lanes.contains(&sibling_s2) + && !u[..active_width].contains(&sibling_s2) + && !v[..active_width].contains(&sibling_s2) + { + lanes.push(sibling_s2); + } + } + } + if dialog_gcd_borrow_zero_raw_future_enabled() && !raw_block.is_empty() { + let group_size = dialog_gcd_sidecar_group_size(); + let slot = step % group_size; + let mut push_raw_zero = |q: QubitId| { + if lanes.len() < want + && !lanes.contains(&q) + && !u[..active_width].contains(&q) + && !v[..active_width].contains(&q) + { + lanes.push(q); + } + }; + for future_slot in (slot + 1)..group_size { + push_raw_zero(raw_block[2 * future_slot]); + push_raw_zero(raw_block[2 * future_slot + 1]); + if dialog_gcd_k2_enabled() { + push_raw_zero(raw_block[2 * group_size + future_slot]); + } + } + } + let owned = b.alloc_qubits(want - lanes.len()); + if std::env::var("PROBE_SCRATCH").is_ok() && active_width >= 254 { + eprintln!( + "SCRATCH step={} aw={} body_w={} body_len={} want={} borrowed={} owned={}", + step, + active_width, + body_w, + body_len, + want, + lanes.len(), + owned.len() + ); + } + lanes.extend_from_slice(&owned); + DialogGcdCompositeScratch { lanes, owned } +} + +pub(crate) fn dialog_gcd_pick_runway_safe_borrow_slice<'a>( + future: Option<&'a [QubitId]>, + u: &'a [QubitId], + compressed_log: &[QubitId], + active_width: usize, +) -> Option<&'a [QubitId]> { + if !dialog_gcd_compressed_log_u_high_runway_enabled() { + return dialog_gcd_pick_borrow_slice(future, u, active_width); + } + + let safe_future = dialog_gcd_runway_safe_future_prefix(future, u, active_width); + if dialog_gcd_late_borrow_uv_high_enabled() && active_width >= 1 { + let want = 2 * active_width - 1; + let short = safe_future.map_or(true, |slice| slice.len() < want); + if short && u.len() >= active_width + want { + let candidate = &u[active_width..active_width + want]; + + if !dialog_gcd_slice_intersects(candidate, compressed_log) { + return Some(candidate); + } + } + } + safe_future +} + +pub(crate) fn dialog_gcd_host_reverse_raw_block_enabled() -> bool { + + if dialog_gcd_k2_enabled() + && std::env::var("DIALOG_GCD_K2_HOST_RAW_BLOCK") + .ok() + .as_deref() + != Some("1") + { + return false; + } + std::env::var("DIALOG_GCD_HOST_REVERSE_RAW_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_k2_apply_inplace_raw_block_enabled() -> bool { + dialog_gcd_k2_pair_compress_enabled() + && std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_k5_free_clean_block_during_shift_enabled() -> bool { + dialog_gcd_k5_clean_block_enabled() + && std::env::var("DIALOG_GCD_K5_FREE_CLEAN_BLOCK_DURING_SHIFT") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_reverse_raw_block_host<'a>( + u: &'a [QubitId], + compressed_log: &'a [QubitId], + block: usize, +) -> Option<&'a [QubitId]> { + if !dialog_gcd_host_reverse_raw_block_enabled() { + return None; + } + let (start, _) = dialog_gcd_compressed_sidecar_block_step_range(block); + let active_width = dialog_gcd_tobitvector_active_width(start); + let want = 2 * active_width - 1; + let raw_bits = dialog_gcd_raw_block_len(); + if u.len().saturating_sub(active_width) >= want + raw_bits { + let candidate = &u[u.len() - raw_bits..]; + if !dialog_gcd_compressed_log_u_high_runway_enabled() + || !dialog_gcd_slice_intersects(candidate, compressed_log) + { + return Some(candidate); + } + } + let future_start = dialog_gcd_compressed_sidecar_block_offset(block + 1); + let future = compressed_log.get(future_start..)?; + if future.len() < want + raw_bits { + return None; + } + if !dialog_gcd_compressed_log_u_high_runway_enabled() { + return Some(&future[future.len() - raw_bits..]); + } + + future[want..] + .windows(raw_bits) + .rev() + .find(|candidate| !dialog_gcd_slice_intersects(candidate, &u[..active_width])) +} + +pub(crate) fn dialog_gcd_forward_raw_block_host<'a>( + u: &'a [QubitId], + compressed_log: &'a [QubitId], + block: usize, +) -> Option<&'a [QubitId]> { + if !dialog_gcd_host_reverse_raw_block_enabled() { + return None; + } + let (start, _) = dialog_gcd_compressed_sidecar_block_step_range(block); + let active_width = dialog_gcd_tobitvector_active_width(start); + let want = 2 * active_width - 1; + let raw_bits = dialog_gcd_raw_block_len(); + let future_start = dialog_gcd_compressed_sidecar_block_offset(block + 1); + if let Some(future) = compressed_log.get(future_start..) { + if future.len() >= want + raw_bits { + if !dialog_gcd_compressed_log_u_high_runway_enabled() { + return Some(&future[future.len() - raw_bits..]); + } + if let Some(candidate) = future[want..] + .windows(raw_bits) + .rev() + .find(|candidate| !dialog_gcd_slice_intersects(candidate, &u[..active_width])) + { + return Some(candidate); + } + } + } + if u.len().saturating_sub(active_width) >= want + raw_bits { + let candidate = &u[u.len() - raw_bits..]; + if !dialog_gcd_compressed_log_u_high_runway_enabled() + || !dialog_gcd_slice_intersects(candidate, compressed_log) + { + Some(candidate) + } else { + None + } + } else { + None + } +} + +pub(crate) fn dialog_gcd_compressed_sidecar_future_carry_slice( + compressed_log: &[QubitId], + step: usize, + active_width: usize, +) -> Option<&[QubitId]> { + if !dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() { + return None; + } + let carry_need = active_width.saturating_sub(1); + + let want = if dialog_gcd_host_gated_enabled() { + 2 * active_width - 1 + } else { + carry_need + }; + let next_block = dialog_gcd_compressed_sidecar_block_index(step) + 1; + let start = dialog_gcd_compressed_sidecar_block_offset(next_block); + compressed_log + .get(start..) + .filter(|future| future.len() >= carry_need) + .map(|future| &future[..future.len().min(want)]) +} + +pub(crate) fn dialog_gcd_compressed_sidecar_block_step_range(block: usize) -> (usize, usize) { + if (dialog_gcd_k5_tail6_graph_enabled() || dialog_gcd_k5_tail6_graph9_enabled()) + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + return ( + dialog_gcd_active_iterations() - 6, + dialog_gcd_active_iterations(), + ); + } + if dialog_gcd_k5_tail7_enabled() + && block + 1 == dialog_gcd_compressed_sidecar_blocks() + { + return ( + dialog_gcd_active_iterations() - 7, + dialog_gcd_active_iterations(), + ); + } + let group_size = dialog_gcd_sidecar_group_size(); + let start = block * group_size; + let end = (start + group_size).min(dialog_gcd_active_iterations()); + (start, end) +} + +pub(crate) fn dialog_gcd_copy_compressed_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, +) { + if dialog_gcd_k5_head11_enabled() + && steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + { + dialog_gcd_k5_head11_decompress_block_to_raw( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + + b.cx(raw_block[0], raw_block[1]); + return; + } + if dialog_gcd_k5_tail6_graph9_enabled() + && steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS + { + dialog_gcd_k5_tail6_graph9_decompress_block_to_raw(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail6_graph_enabled() + && steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS + { + dialog_gcd_k5_tail6_graph_decompress_block_to_raw(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail7_enabled() + && steps == 7 + && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS + { + dialog_gcd_k5_tail7_decompress_block_to_raw(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail3_top32_enabled() + && steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_top32_decompress_block_to_raw( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_tail3_fixed_last_enabled() + && steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_decompress_block_to_raw( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_tail_pair1_enabled() && steps == 2 && compressed_block.len() == 1 { + dialog_gcd_k5_tail_pair1_decompress_block_to_raw( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_clean_block_enabled() { + if steps == 5 { + dialog_gcd_k5_decompress_block_to_raw( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + } else { + dialog_gcd_k5_decompress_partial_block_to_raw( + b, + compressed_block, + raw_block, + steps, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + } + return; + } + if dialog_gcd_k2_pair_compress_enabled() { + dialog_gcd_k2_pair_copy_compressed_block_to_raw(b, compressed_block, raw_block, steps); + return; + } + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + let raw_base = 2 * dialog_gcd_sidecar_group_size(); + assert_eq!(compressed_block.len(), dialog_gcd_block_bits()); + assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); + let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); + for i in 0..base_bits { + if swap_host { + b.swap(compressed_block[i], raw_block[i]); + } else { + b.cx(compressed_block[i], raw_block[i]); + } + } + emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); + + for j in base_bits..dialog_gcd_block_bits() { + let r = raw_base + (j - base_bits); + if swap_host { + b.swap(compressed_block[j], raw_block[r]); + } else { + b.cx(compressed_block[j], raw_block[r]); + } + } +} + +pub(crate) fn dialog_gcd_clear_raw_block_copy( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, +) { + if dialog_gcd_k5_head11_enabled() + && steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + { + + b.cx(raw_block[0], raw_block[1]); + dialog_gcd_k5_head11_compress_raw_to_block( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_tail6_graph9_enabled() + && steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS + { + dialog_gcd_k5_tail6_graph9_compress_raw_to_block(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail6_graph_enabled() + && steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS + { + dialog_gcd_k5_tail6_graph_compress_raw_to_block(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail7_enabled() + && steps == 7 + && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS + { + dialog_gcd_k5_tail7_compress_raw_to_block(b, compressed_block, raw_block); + return; + } + if dialog_gcd_k5_tail3_top32_enabled() + && steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_top32_compress_raw_to_block( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_tail3_fixed_last_enabled() + && steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_compress_raw_to_block( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_tail_pair1_enabled() && steps == 2 && compressed_block.len() == 1 { + dialog_gcd_k5_tail_pair1_compress_raw_to_block( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + return; + } + if dialog_gcd_k5_clean_block_enabled() { + if steps == 5 { + dialog_gcd_k5_compress_raw_to_block( + b, + compressed_block, + raw_block, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + } else { + dialog_gcd_k5_compress_partial_raw_to_block( + b, + compressed_block, + raw_block, + steps, + dialog_gcd_apply_replay_swap_host_enabled(), + ); + } + return; + } + if dialog_gcd_k2_pair_compress_enabled() { + dialog_gcd_k2_pair_clear_raw_block_copy(b, compressed_block, raw_block, steps); + return; + } + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + let raw_base = 2 * dialog_gcd_sidecar_group_size(); + assert_eq!(compressed_block.len(), dialog_gcd_block_bits()); + assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); + let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); + + for j in base_bits..dialog_gcd_block_bits() { + let r = raw_base + (j - base_bits); + if swap_host { + b.swap(compressed_block[j], raw_block[r]); + } else { + b.cx(compressed_block[j], raw_block[r]); + } + } + emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); + for i in 0..base_bits { + if swap_host { + b.swap(compressed_block[i], raw_block[i]); + } else { + b.cx(compressed_block[i], raw_block[i]); + } + } +} + +pub(crate) fn dialog_gcd_k2_pair_inplace_raw_frame( + compressed_block: &[QubitId], + raw0: QubitId, +) -> [QubitId; 6] { + assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); + [ + raw0, + compressed_block[0], + compressed_block[2], + compressed_block[3], + compressed_block[1], + compressed_block[4], + ] +} + +pub(crate) fn dialog_gcd_k2_pair_inplace_decompress_block( + b: &mut B, + compressed_block: &[QubitId], + raw0: QubitId, + steps: usize, +) -> [QubitId; 6] { + assert_eq!(steps, 2, "in-place K2 apply currently requires full pair blocks"); + let raw_frame = dialog_gcd_k2_pair_inplace_raw_frame(compressed_block, raw0); + let core = dialog_gcd_k2_pair_core(&raw_frame); + emit_dialog_gcd_k2_pair_core_encoder_inverse(b, &core); + raw_frame +} + +pub(crate) fn dialog_gcd_k2_pair_inplace_clear_block( + b: &mut B, + compressed_block: &[QubitId], + raw0: QubitId, + steps: usize, +) { + assert_eq!(steps, 2, "in-place K2 apply currently requires full pair blocks"); + let raw_frame = dialog_gcd_k2_pair_inplace_raw_frame(compressed_block, raw0); + let core = dialog_gcd_k2_pair_core(&raw_frame); + emit_dialog_gcd_k2_pair_core_encoder(b, &core); +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + compressed_log: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert!(raw_block.is_empty() || raw_block.len() == dialog_gcd_raw_block_len()); + assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); + + for block in 0..dialog_gcd_compressed_sidecar_blocks() { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let block_steps = end - start; + let hosted_raw_block = dialog_gcd_forward_raw_block_host(u, compressed_log, block); + let owned_raw_block = + if dialog_gcd_host_reverse_raw_block_enabled() && hosted_raw_block.is_none() { + b.alloc_qubits(dialog_gcd_raw_block_len()) + } else { + Vec::new() + }; + let raw_block = hosted_raw_block.unwrap_or_else(|| { + if owned_raw_block.is_empty() { + raw_block + } else { + &owned_raw_block + } + }); + for step in start..end { + let slot = step - start; + if dialog_gcd_k5_constant_tail_stored_steps(block_steps) + .is_some_and(|stored_steps| slot >= stored_steps) + { + let active_width = dialog_gcd_tobitvector_active_width(step); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + let v_shift = &v[..shift_width]; + b.set_phase("dialog_gcd_compressed_block_tobitvector_tail7_constant_shift"); + dialog_gcd_shift_right_assuming_even(b, v_shift); + dialog_gcd_shift_right_assuming_even(b, v_shift); + continue; + } + let b0 = raw_block[2 * slot]; + let b0_and_b1 = raw_block[2 * slot + 1]; + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + let future = dialog_gcd_compressed_sidecar_future_carry_slice( + compressed_log, + step, + active_width, + ); + let composite_scratch = dialog_gcd_composite_scratch_enabled().then(|| { + dialog_gcd_build_composite_scratch( + b, + future, + u, + v, + compressed_log, + raw_block, + active_width, + step, + ) + }); + let borrowed_carries = composite_scratch.as_ref().map_or_else( + || { + dialog_gcd_pick_runway_safe_borrow_slice( + future, + u, + compressed_log, + active_width, + ) + }, + |scratch| Some(scratch.lanes.as_slice()), + ); + + b.set_phase("dialog_gcd_compressed_block_tobitvector_branch_bits"); + b.cx(v[0], b0); + if dialog_gcd_fused_branch_bits_enabled() { + + if dialog_gcd_branch_bits_host_comparator_enabled() { + + dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + borrowed_carries, + ); + } else { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } + } else { + let cmp = b.alloc_qubit(); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.free(cmp); + } + + b.set_phase("dialog_gcd_compressed_block_tobitvector_cswap"); + let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); + for (i, (&ui, &vi)) in u[..cswap_width] + .iter() + .zip(v[..cswap_width].iter()) + .enumerate() + { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_compressed_block_tobitvector_subtract"); + dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); + if std::env::var("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT") + .ok() + .as_deref() + == Some("1") + { + if let Some(scratch) = composite_scratch.as_ref() { + b.free_vec(&scratch.owned); + } + } + + b.set_phase("dialog_gcd_compressed_block_tobitvector_shift"); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + let v_shift = &v[..shift_width]; + dialog_gcd_shift_right_assuming_even(b, v_shift); + if dialog_gcd_k2_enabled() { + + let s2 = dialog_gcd_block_raw_s2(raw_block, block_steps, slot); + let v0 = v_active[0]; + if std::env::var("DIALOG_GCD_K2_FORCE0").ok().as_deref() != Some("1") { + b.cx(v0, s2); + b.x(s2); + } + let pairs = v_shift.len().saturating_sub(1); + for i in 0..pairs { + if dialog_gcd_skip_zero_edge_tobit_fwd_cshift_enabled() && i + 1 == pairs { + continue; + } + let (lo, hi) = (v_shift[i], v_shift[i + 1]); + cswap(b, s2, lo, hi); + } + } + if std::env::var("DIALOG_GCD_FREE_SCRATCH_BEFORE_SHIFT") + .ok() + .as_deref() + != Some("1") + { + if let Some(scratch) = composite_scratch.as_ref() { + b.free_vec(&scratch.owned); + } + } + } + + b.set_phase("dialog_gcd_compressed_block_tobitvector_compress_block"); + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); + if dialog_gcd_compressed_log_u_high_runway_enabled() { + + assert!( + !dialog_gcd_slice_intersects( + compressed_block, + &u[..dialog_gcd_tobitvector_active_width(start)] + ), + "compressed-log runway overlaps active forward u prefix at block {block}" + ); + } + if dialog_gcd_k5_head11_enabled() + && start == 0 + && block_steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + { + dialog_gcd_k5_head11_compress_raw_to_block(b, compressed_block, raw_block, true); + } else if dialog_gcd_k5_tail6_graph9_enabled() + && block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS + { + dialog_gcd_k5_tail6_graph9_compress_raw_to_block(b, compressed_block, raw_block); + } else if dialog_gcd_k5_tail6_graph_enabled() + && block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS + { + dialog_gcd_k5_tail6_graph_compress_raw_to_block(b, compressed_block, raw_block); + } else if dialog_gcd_k5_tail7_enabled() + && block_steps == 7 + && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS + { + dialog_gcd_k5_tail7_compress_raw_to_block(b, compressed_block, raw_block); + } else if dialog_gcd_k5_tail3_top32_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_top32_compress_raw_to_block( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_tail3_fixed_last_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_compress_raw_to_block( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_tail_pair1_enabled() + && end - start == 2 + && compressed_block.len() == 1 + { + dialog_gcd_k5_tail_pair1_compress_raw_to_block( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_clean_block_enabled() { + if end - start == 5 { + dialog_gcd_k5_compress_raw_to_block(b, compressed_block, raw_block, true); + } else { + dialog_gcd_k5_compress_partial_raw_to_block( + b, + compressed_block, + raw_block, + end - start, + true, + ); + } + } else if dialog_gcd_k2_pair_compress_enabled() { + dialog_gcd_k2_pair_clear_raw_block_copy(b, compressed_block, raw_block, end - start); + } else { + let raw_base = 2 * dialog_gcd_sidecar_group_size(); + emit_dialog_gcd_round763_compressor(b, &raw_block[0..raw_base]); + for i in 0..base_bits { + b.swap(raw_block[i], compressed_block[i]); + } + + for j in base_bits..dialog_gcd_block_bits() { + b.swap(raw_block[raw_base + (j - base_bits)], compressed_block[j]); + } + } + if !owned_raw_block.is_empty() { + b.free_vec(&owned_raw_block); + } + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + compressed_log: &[QubitId], + raw_block: &[QubitId], +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert!(raw_block.is_empty() || raw_block.len() == dialog_gcd_raw_block_len()); + assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); + + for block in (0..dialog_gcd_compressed_sidecar_blocks()).rev() { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let block_steps = end - start; + let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); + let hosted_raw_block = dialog_gcd_reverse_raw_block_host(u, compressed_log, block); + let owned_raw_block = + if dialog_gcd_host_reverse_raw_block_enabled() && hosted_raw_block.is_none() { + b.alloc_qubits(dialog_gcd_raw_block_len()) + } else { + Vec::new() + }; + let raw_block = hosted_raw_block.unwrap_or_else(|| { + if owned_raw_block.is_empty() { + raw_block + } else { + &owned_raw_block + } + }); + + b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_decompress_block"); + if dialog_gcd_compressed_log_u_high_runway_enabled() { + + assert!( + !dialog_gcd_slice_intersects( + compressed_block, + &u[..dialog_gcd_tobitvector_active_width(start)] + ), + "compressed-log runway overlaps active reverse u prefix at block {block}" + ); + } + { + let base_bits = DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS; + if dialog_gcd_k5_head11_enabled() + && start == 0 + && block_steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len() + { + dialog_gcd_k5_head11_decompress_block_to_raw( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_tail6_graph9_enabled() + && block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS + { + dialog_gcd_k5_tail6_graph9_decompress_block_to_raw( + b, + compressed_block, + raw_block, + ); + } else if dialog_gcd_k5_tail6_graph_enabled() + && block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH_CODE_BITS + { + dialog_gcd_k5_tail6_graph_decompress_block_to_raw( + b, + compressed_block, + raw_block, + ); + } else if dialog_gcd_k5_tail7_enabled() + && block_steps == 7 + && compressed_block.len() == DIALOG_GCD_K5_TAIL7_CODE_BITS + { + dialog_gcd_k5_tail7_decompress_block_to_raw( + b, + compressed_block, + raw_block, + ); + } else if dialog_gcd_k5_tail3_top32_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_top32_decompress_block_to_raw( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_tail3_fixed_last_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len() + { + dialog_gcd_k5_tail3_decompress_block_to_raw( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_tail_pair1_enabled() + && end - start == 2 + && compressed_block.len() == 1 + { + dialog_gcd_k5_tail_pair1_decompress_block_to_raw( + b, + compressed_block, + raw_block, + true, + ); + } else if dialog_gcd_k5_clean_block_enabled() { + if end - start == 5 { + dialog_gcd_k5_decompress_block_to_raw(b, compressed_block, raw_block, true); + } else { + dialog_gcd_k5_decompress_partial_block_to_raw( + b, + compressed_block, + raw_block, + end - start, + true, + ); + } + } else if dialog_gcd_k2_pair_compress_enabled() { + dialog_gcd_k2_pair_copy_compressed_block_to_raw( + b, + compressed_block, + raw_block, + end - start, + ); + } else { + let raw_base = 2 * dialog_gcd_sidecar_group_size(); + for i in 0..base_bits { + b.swap(compressed_block[i], raw_block[i]); + } + emit_dialog_gcd_round763_compressor_inverse(b, &raw_block[0..raw_base]); + + for j in base_bits..dialog_gcd_block_bits() { + b.swap(compressed_block[j], raw_block[raw_base + (j - base_bits)]); + } + } + } + + for step in (start..end).rev() { + let slot = step - start; + if dialog_gcd_k5_constant_tail_stored_steps(block_steps) + .is_some_and(|stored_steps| slot >= stored_steps) + { + let active_width = dialog_gcd_tobitvector_active_width(step); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + let v_shift = &v[..shift_width]; + b.set_phase( + "dialog_gcd_compressed_block_tobitvector_reverse_tail7_constant_unshift", + ); + dialog_gcd_unshift_right_assuming_even(b, v_shift); + dialog_gcd_unshift_right_assuming_even(b, v_shift); + continue; + } + let b0 = raw_block[2 * slot]; + let b0_and_b1 = raw_block[2 * slot + 1]; + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_unshift"); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + let v_shift = &v[..shift_width]; + if dialog_gcd_k2_enabled() { + + let s2 = dialog_gcd_block_raw_s2(raw_block, block_steps, slot); + let pairs = v_shift.len().saturating_sub(1); + for i in (0..pairs).rev() { + if dialog_gcd_skip_zero_edge_tobit_rev_cshift_enabled() && i + 1 == pairs { + continue; + } + let (lo, hi) = (v_shift[i], v_shift[i + 1]); + cswap(b, s2, lo, hi); + } + let v0 = v_active[0]; + if std::env::var("DIALOG_GCD_K2_FORCE0").ok().as_deref() != Some("1") { + b.x(s2); + b.cx(v0, s2); + } + } + dialog_gcd_unshift_right_assuming_even(b, v_shift); + + b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_add"); + let future = dialog_gcd_compressed_sidecar_future_carry_slice( + compressed_log, + step, + active_width, + ); + let composite_scratch = dialog_gcd_composite_scratch_enabled().then(|| { + dialog_gcd_build_composite_scratch( + b, + future, + u, + v, + compressed_log, + raw_block, + active_width, + step, + ) + }); + let borrowed_carries = composite_scratch.as_ref().map_or_else( + || { + dialog_gcd_pick_runway_safe_borrow_slice( + future, + u, + compressed_log, + active_width, + ) + }, + |scratch| Some(scratch.lanes.as_slice()), + ); + dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); + + b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_cswap"); + let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); + for (i, (&ui, &vi)) in u[..cswap_width] + .iter() + .zip(v[..cswap_width].iter()) + .enumerate() + { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_compressed_block_tobitvector_reverse_branch_bits"); + if dialog_gcd_reverse_branch_conditional_replay_enabled() { + let phase = b.alloc_bit(); + b.hmr(b0_and_b1, phase); + dialog_gcd_cmp_gt_truncated_phase_conditioned_hosted( + b, + u_active, + v_active, + b0, + phase, + compare_bits, + borrowed_carries, + ); + } else if dialog_gcd_fused_branch_bits_enabled() { + + if dialog_gcd_branch_bits_host_comparator_enabled() { + + dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + borrowed_carries, + ); + } else { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } + } else { + let cmp = b.alloc_qubit(); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.free(cmp); + } + b.cx(v[0], b0); + if let Some(scratch) = composite_scratch { + b.free_vec(&scratch.owned); + } + } + if !owned_raw_block.is_empty() { + b.free_vec(&owned_raw_block); + } + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( + b: &mut B, + compressed_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, + raw_block: &[QubitId], +) { + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + let inplace_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); + if inplace_raw { + assert!(raw_block.is_empty()); + } else { + assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); + } + let inplace_raw0 = if inplace_raw { + Some(b.alloc_qubit()) + } else { + None + }; + + for block in (0..dialog_gcd_compressed_sidecar_blocks()).rev() { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let block_steps = end - start; + let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); + let head11_block = dialog_gcd_k5_head11_enabled() + && start == 0 + && block_steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len(); + let stream_tail3 = dialog_gcd_k5_tail3_top32_stream_apply_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len(); + let split_stream_tail3 = + stream_tail3 && dialog_gcd_k5_tail3_top32_split_slot_apply_enabled(); + + b.set_phase("dialog_gcd_compressed_block_apply_decompress_block"); + let raw_frame = inplace_raw0.map(|raw0| { + dialog_gcd_k2_pair_inplace_decompress_block(b, compressed_block, raw0, end - start) + }); + let stream_head11_pairs = dialog_gcd_k5_head11_stream_pair_apply_enabled() + && raw_frame.is_none() + && head11_block; + let split_head11_pair_shift = stream_head11_pairs + && dialog_gcd_k5_head11_split_pair_shift_apply_enabled(); + let stream_k5_pairs = dialog_gcd_k5_stream_pair_apply_enabled() + && raw_frame.is_none() + && !stream_tail3 + && !head11_block + && block_steps == 5 + && compressed_block.len() == 12; + if stream_head11_pairs { + dialog_gcd_k5_head11_decompress_block_to_data( + b, + compressed_block, + raw_block, + true, + ); + } else if stream_k5_pairs { + dialog_gcd_k5_decompress_block_to_data(b, compressed_block, raw_block, true); + } else if raw_frame.is_none() && !stream_tail3 { + dialog_gcd_copy_compressed_block_to_raw(b, compressed_block, raw_block, end - start); + } + if head11_block && !stream_head11_pairs { + b.free(raw_block[1]); + } + let released_code_bits = if !stream_tail3 + && raw_frame.is_none() + && dialog_gcd_apply_replay_swap_host_enabled() + { + let requested = if (block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS) + || ((dialog_gcd_k5_tail3_fixed_last_enabled() + || dialog_gcd_k5_tail3_top32_enabled()) + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()) + { + dialog_gcd_k5_release_decoded_tail_bits() + } else { + dialog_gcd_k5_release_decoded_block_bits() + }; + requested.min(compressed_block.len()) + } else { + 0 + }; + let retained_code_bits = compressed_block.len() - released_code_bits; + let released_code = &compressed_block[retained_code_bits..]; + b.free_vec(released_code); + let raw = raw_frame.as_ref().map_or(raw_block, |frame| &frame[..]); + if stream_head11_pairs || stream_k5_pairs { + dialog_gcd_k5_stream_pairs_start(b, raw); + } + let stream_clean_scratch = if stream_tail3 { + dialog_gcd_k5_tail3_top32_stream_scratch(raw) + } else { + Vec::new() + }; + let stream_dynamic_raw = if stream_tail3 { + dialog_gcd_k5_tail3_top32_stream_dynamic(raw) + } else { + Vec::new() + }; + if stream_tail3 { + b.free_vec(&stream_dynamic_raw); + } + let scale_release_bits = if stream_tail3 { + 0 + } else { + dialog_gcd_k5_release_scale_bits().min(retained_code_bits) + }; + let scale_released_code = + &compressed_block[retained_code_bits - scale_release_bits..retained_code_bits]; + let shift_clean_code = if stream_tail3 { + stream_clean_scratch.as_slice() + } else { + &compressed_block[..retained_code_bits - scale_release_bits] + }; + let tail_clean_scratch = if dialog_gcd_k5_tail_pair1_enabled() + && end - start == 2 + && compressed_block.len() == 1 + { + raw.iter() + .enumerate() + .filter_map(|(index, &q)| { + (!matches!(index, 0 | 2 | 10 | 11)).then_some(q) + }) + .chain(compressed_block.iter().copied()) + .collect::>() + } else { + Vec::new() + }; + let mut partial_raw_clean_scratch = if stream_tail3 { + Vec::new() + } else { + dialog_gcd_k5_partial_raw_clean_scratch(raw, block_steps) + }; + let partial_release = + dialog_gcd_k5_partial_raw_release_bits().min(partial_raw_clean_scratch.len()); + let released_partial_raw = + partial_raw_clean_scratch.split_off(partial_raw_clean_scratch.len() - partial_release); + b.free_vec(&released_partial_raw); + let mut combined_clean_scratch = Vec::new(); + if stream_tail3 { + combined_clean_scratch.extend_from_slice(&stream_clean_scratch); + } else if !inplace_raw && dialog_gcd_apply_replay_swap_host_enabled() { + combined_clean_scratch.extend_from_slice(&compressed_block[..retained_code_bits]); + combined_clean_scratch.extend_from_slice(&partial_raw_clean_scratch); + } + let block_clean_scratch = if !tail_clean_scratch.is_empty() { + tail_clean_scratch.as_slice() + } else { + combined_clean_scratch.as_slice() + }; + + for step in (start..end).rev() { + let slot = step - start; + let top32_final_s2_const = stream_tail3 + && split_stream_tail3 + && dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() + && slot + 1 == block_steps; + let constant_tail_stored_steps = + dialog_gcd_k5_constant_tail_stored_steps(block_steps); + if constant_tail_stored_steps.is_some_and(|stored_steps| slot >= stored_steps) { + let stored_steps = constant_tail_stored_steps.expect("checked above"); + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_scale_release"); + b.free_vec(scale_released_code); + } + b.set_phase("dialog_gcd_compressed_block_apply_tail7_constant_double_y"); + if dialog_gcd_k5_fixed_tail_apply_enabled() { + dialog_gcd_fixed_double_twice_y(b, y, p); + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); + b.reacquire_vec(scale_released_code); + } + continue; + } + let one = raw[12]; + if slot + 1 == block_steps { + b.x(one); + } + if dialog_gcd_apply_fused_fold_enabled() { + dialog_gcd_fused_double_y_at_step(b, y, p, one, Some(step)); + } else { + mod_double_inplace_fast(b, y, p); + cmod_double_inplace_lazy(b, y, p, one); + } + if slot == stored_steps { + b.x(one); + } + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); + b.reacquire_vec(scale_released_code); + } + continue; + } + if stream_tail3 { + if split_stream_tail3 { + if !top32_final_s2_const { + let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); + b.reacquire_vec(&shift_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } else { + let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); + b.reacquire_vec(&slot_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } + let split_head11_pair_slot = split_head11_pair_shift && slot < 4; + let split_head11_permute_shift = split_head11_pair_slot + && slot == 0 + && dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled(); + let split_head11_borrow_pair23_shift = split_head11_pair_slot + && slot == 2 + && dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled(); + let split_head11_open_for_shift = split_head11_pair_slot + && matches!(slot, 0 | 2) + && !split_head11_permute_shift + && !split_head11_borrow_pair23_shift; + if stream_k5_pairs || (stream_head11_pairs && !split_head11_pair_shift) { + dialog_gcd_k5_stream_pairs_before_slot(b, raw, slot); + } + if split_head11_open_for_shift { + dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); + } + if split_head11_permute_shift { + dialog_gcd_k5_head11_pair01_expose_s2(b, raw); + } + if split_head11_borrow_pair23_shift { + dialog_gcd_k5_head11_pair01_zero_lane(b, raw); + dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); + } + let b0 = raw[2 * slot]; + let b0_and_b1 = if head11_block && slot == 0 { + raw[0] + } else { + raw[2 * slot + 1] + }; + + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_scale_release"); + b.free_vec(scale_released_code); + } + b.set_phase("dialog_gcd_compressed_block_apply_double_y"); + let apply_k2 = dialog_gcd_k2_enabled() + && std::env::var("DIALOG_GCD_K2_NO_APPLY").ok().as_deref() != Some("1"); + let free_clean_code = !inplace_raw + && dialog_gcd_apply_replay_swap_host_enabled() + && dialog_gcd_k5_free_clean_block_during_shift_enabled(); + if free_clean_code { + b.free_vec(shift_clean_code); + } + if top32_final_s2_const && apply_k2 { + dialog_gcd_fixed_double_twice_y(b, y, p); + } else if apply_k2 && dialog_gcd_apply_fused_fold_enabled() { + + let s2 = if split_head11_borrow_pair23_shift { + raw[1] + } else { + dialog_gcd_block_raw_s2(raw, block_steps, slot) + }; + dialog_gcd_fused_double_y_at_step(b, y, p, s2, Some(step)); + } else { + mod_double_inplace_fast(b, y, p); + if apply_k2 { + + let s2 = if split_head11_borrow_pair23_shift { + raw[1] + } else { + dialog_gcd_block_raw_s2(raw, block_steps, slot) + }; + cmod_double_inplace_lazy(b, y, p, s2); + } + } + if free_clean_code { + b.reacquire_vec(shift_clean_code); + } + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_scale_reacquire"); + b.reacquire_vec(scale_released_code); + } + if split_head11_permute_shift { + dialog_gcd_k5_head11_pair01_unexpose_s2(b, raw); + } + if split_head11_borrow_pair23_shift { + dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); + dialog_gcd_k5_head11_pair01_unzero_lane(b, raw); + } + if split_stream_tail3 { + if top32_final_s2_const { + b.reacquire(raw[2 * slot]); + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b, + compressed_block, + raw, + &[2 * slot], + ); + } else { + let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&shift_raw); + let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); + b.reacquire_vec(&branch_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } + if split_head11_pair_slot && !split_head11_open_for_shift { + dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); + } + + b.set_phase("dialog_gcd_compressed_block_apply_cadd"); + if dialog_gcd_raw_apply_materialized_special_add_enabled() { + let owned_clean_scratch = if inplace_raw { + b.alloc_qubits(dialog_gcd_block_bits()) + } else { + Vec::new() + }; + let clean_scratch = if inplace_raw { + owned_clean_scratch.as_slice() + } else { + block_clean_scratch + }; + dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + y, + x, + b0, + p, + clean_scratch, + Some(step), + ); + if inplace_raw { + b.free_vec(&owned_clean_scratch); + } + } else if dialog_gcd_raw_apply_direct_special_add_enabled() { + dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); + } else { + cmod_add_qq_lowq(b, y, x, b0, p); + } + + b.set_phase("dialog_gcd_compressed_block_apply_cswap"); + if !top32_final_s2_const { + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + } + if stream_tail3 { + if split_stream_tail3 { + if top32_final_s2_const { + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b, + compressed_block, + raw, + &[2 * slot], + ); + b.free(raw[2 * slot]); + } else { + let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&branch_raw); + } + } else { + let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&slot_raw); + } + } + if split_head11_pair_slot { + dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); + } else if stream_k5_pairs || stream_head11_pairs { + dialog_gcd_k5_stream_pairs_after_slot_forward(b, raw, slot); + } + } + + if !released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reacquire_block"); + b.reacquire_vec(released_code); + } + if !released_partial_raw.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reacquire_partial_raw"); + b.reacquire_vec(&released_partial_raw); + } + if head11_block && !stream_head11_pairs { + b.reacquire(raw_block[1]); + } + b.set_phase("dialog_gcd_compressed_block_apply_clear_block_copy"); + if stream_tail3 { + b.reacquire_vec(&stream_dynamic_raw); + } else if stream_head11_pairs { + dialog_gcd_k5_stream_pairs_finish(b, raw_block); + dialog_gcd_k5_head11_compress_data_to_block( + b, + compressed_block, + raw_block, + true, + ); + } else if stream_k5_pairs { + dialog_gcd_k5_stream_pairs_finish(b, raw_block); + dialog_gcd_k5_compress_data_to_block(b, compressed_block, raw_block, true); + } else if let Some(raw0) = inplace_raw0 { + dialog_gcd_k2_pair_inplace_clear_block(b, compressed_block, raw0, end - start); + } else { + dialog_gcd_clear_raw_block_copy(b, compressed_block, raw_block, end - start); + } + } + + if let Some(raw0) = inplace_raw0 { + b.free(raw0); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( + b: &mut B, + compressed_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, + raw_block: &[QubitId], +) { + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + let inplace_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); + if inplace_raw { + assert!(raw_block.is_empty()); + } else { + assert_eq!(raw_block.len(), dialog_gcd_raw_block_len()); + } + let inplace_raw0 = if inplace_raw { + Some(b.alloc_qubit()) + } else { + None + }; + + for block in 0..dialog_gcd_compressed_sidecar_blocks() { + let (start, end) = dialog_gcd_compressed_sidecar_block_step_range(block); + let block_steps = end - start; + let compressed_block = dialog_gcd_compressed_sidecar_block(compressed_log, start); + let head11_block = dialog_gcd_k5_head11_enabled() + && start == 0 + && block_steps == 5 + && compressed_block.len() == DIALOG_GCD_K5_HEAD11_DATA_WIRES.len(); + let stream_tail3 = dialog_gcd_k5_tail3_top32_stream_apply_enabled() + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len(); + let split_stream_tail3 = + stream_tail3 && dialog_gcd_k5_tail3_top32_split_slot_apply_enabled(); + + b.set_phase("dialog_gcd_compressed_block_apply_reverse_decompress_block"); + let raw_frame = inplace_raw0.map(|raw0| { + dialog_gcd_k2_pair_inplace_decompress_block(b, compressed_block, raw0, end - start) + }); + let stream_head11_pairs = dialog_gcd_k5_head11_stream_pair_apply_enabled() + && raw_frame.is_none() + && head11_block; + let split_head11_pair_shift = stream_head11_pairs + && dialog_gcd_k5_head11_split_pair_shift_apply_enabled(); + let stream_k5_pairs = dialog_gcd_k5_stream_pair_apply_enabled() + && raw_frame.is_none() + && !stream_tail3 + && !head11_block + && block_steps == 5 + && compressed_block.len() == 12; + if stream_head11_pairs { + dialog_gcd_k5_head11_decompress_block_to_data( + b, + compressed_block, + raw_block, + true, + ); + } else if stream_k5_pairs { + dialog_gcd_k5_decompress_block_to_data(b, compressed_block, raw_block, true); + } else if raw_frame.is_none() && !stream_tail3 { + dialog_gcd_copy_compressed_block_to_raw(b, compressed_block, raw_block, end - start); + } + if head11_block && !stream_head11_pairs { + b.free(raw_block[1]); + } + let released_code_bits = if !stream_tail3 + && raw_frame.is_none() + && dialog_gcd_apply_replay_swap_host_enabled() + { + let requested = if (block_steps == 6 + && compressed_block.len() == DIALOG_GCD_K5_TAIL6_GRAPH9_CODE_BITS) + || ((dialog_gcd_k5_tail3_fixed_last_enabled() + || dialog_gcd_k5_tail3_top32_enabled()) + && block_steps == 3 + && compressed_block.len() == DIALOG_GCD_K5_TAIL3_DATA_WIRES.len()) + { + dialog_gcd_k5_release_decoded_tail_bits() + } else { + dialog_gcd_k5_release_decoded_block_bits() + }; + requested.min(compressed_block.len()) + } else { + 0 + }; + let retained_code_bits = compressed_block.len() - released_code_bits; + let released_code = &compressed_block[retained_code_bits..]; + b.free_vec(released_code); + let raw = raw_frame.as_ref().map_or(raw_block, |frame| &frame[..]); + if stream_head11_pairs || stream_k5_pairs { + dialog_gcd_k5_stream_pairs_start(b, raw); + } + let stream_clean_scratch = if stream_tail3 { + dialog_gcd_k5_tail3_top32_stream_scratch(raw) + } else { + Vec::new() + }; + let stream_dynamic_raw = if stream_tail3 { + dialog_gcd_k5_tail3_top32_stream_dynamic(raw) + } else { + Vec::new() + }; + if stream_tail3 { + b.free_vec(&stream_dynamic_raw); + } + let scale_release_bits = if stream_tail3 { + 0 + } else { + dialog_gcd_k5_release_scale_bits().min(retained_code_bits) + }; + let scale_released_code = + &compressed_block[retained_code_bits - scale_release_bits..retained_code_bits]; + let shift_clean_code = if stream_tail3 { + stream_clean_scratch.as_slice() + } else { + &compressed_block[..retained_code_bits - scale_release_bits] + }; + let tail_clean_scratch = if dialog_gcd_k5_tail_pair1_enabled() + && end - start == 2 + && compressed_block.len() == 1 + { + raw.iter() + .enumerate() + .filter_map(|(index, &q)| { + (!matches!(index, 0 | 2 | 10 | 11)).then_some(q) + }) + .chain(compressed_block.iter().copied()) + .collect::>() + } else { + Vec::new() + }; + let mut partial_raw_clean_scratch = if stream_tail3 { + Vec::new() + } else { + dialog_gcd_k5_partial_raw_clean_scratch(raw, block_steps) + }; + let partial_release = + dialog_gcd_k5_partial_raw_release_bits().min(partial_raw_clean_scratch.len()); + let released_partial_raw = + partial_raw_clean_scratch.split_off(partial_raw_clean_scratch.len() - partial_release); + b.free_vec(&released_partial_raw); + let mut combined_clean_scratch = Vec::new(); + if stream_tail3 { + combined_clean_scratch.extend_from_slice(&stream_clean_scratch); + } else if !inplace_raw && dialog_gcd_apply_replay_swap_host_enabled() { + combined_clean_scratch.extend_from_slice(&compressed_block[..retained_code_bits]); + combined_clean_scratch.extend_from_slice(&partial_raw_clean_scratch); + } + let block_clean_scratch = if !tail_clean_scratch.is_empty() { + tail_clean_scratch.as_slice() + } else { + combined_clean_scratch.as_slice() + }; + + for step in start..end { + let slot = step - start; + let top32_final_s2_const = stream_tail3 + && split_stream_tail3 + && dialog_gcd_k5_tail3_top32_final_s2_const_apply_enabled() + && slot + 1 == block_steps; + let constant_tail_stored_steps = + dialog_gcd_k5_constant_tail_stored_steps(block_steps); + if constant_tail_stored_steps.is_some_and(|stored_steps| slot >= stored_steps) { + let stored_steps = constant_tail_stored_steps.expect("checked above"); + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_release"); + b.free_vec(scale_released_code); + } + b.set_phase( + "dialog_gcd_compressed_block_apply_reverse_tail7_constant_halve_y", + ); + if dialog_gcd_k5_fixed_tail_apply_enabled() { + dialog_gcd_fixed_halve_twice_y(b, y, p); + if !scale_released_code.is_empty() { + b.set_phase( + "dialog_gcd_compressed_block_apply_reverse_scale_reacquire", + ); + b.reacquire_vec(scale_released_code); + } + continue; + } + let one = raw[12]; + if slot == stored_steps { + b.x(one); + } + if dialog_gcd_apply_fused_fold_enabled() + && std::env::var("DIALOG_GCD_FUSE_HALVE_OFF").ok().as_deref() != Some("1") + { + dialog_gcd_fused_halve_y_at_step(b, y, p, one, Some(step)); + } else { + mod_halve_inplace_fast(b, y, p); + cmod_halve_inplace_lazy(b, y, p, one); + } + if slot + 1 == block_steps { + b.x(one); + } + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_reacquire"); + b.reacquire_vec(scale_released_code); + } + continue; + } + if stream_tail3 { + if split_stream_tail3 { + if top32_final_s2_const { + b.reacquire(raw[2 * slot]); + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b, + compressed_block, + raw, + &[2 * slot], + ); + } else { + let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); + b.reacquire_vec(&branch_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } else { + let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); + b.reacquire_vec(&slot_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } + let split_head11_pair_slot = split_head11_pair_shift && slot < 4; + let split_head11_permute_shift = split_head11_pair_slot + && slot == 0 + && dialog_gcd_k5_head11_pair01_s2_permute_apply_enabled(); + let split_head11_borrow_pair23_shift = split_head11_pair_slot + && slot == 2 + && dialog_gcd_k5_head11_pair23_s2_borrow_pair01_apply_enabled(); + let split_head11_keep_open_for_shift = split_head11_pair_slot + && matches!(slot, 0 | 2) + && !split_head11_permute_shift + && !split_head11_borrow_pair23_shift; + if stream_k5_pairs || (stream_head11_pairs && !split_head11_pair_shift) { + dialog_gcd_k5_stream_pairs_before_slot_reverse(b, raw, slot); + } + if split_head11_pair_slot { + dialog_gcd_k5_head11_open_pair_for_slot(b, raw, slot); + } + let b0 = raw[2 * slot]; + let b0_and_b1 = if head11_block && slot == 0 { + raw[0] + } else { + raw[2 * slot + 1] + }; + + b.set_phase("dialog_gcd_compressed_block_apply_reverse_cswap"); + if !top32_final_s2_const { + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + } + + b.set_phase("dialog_gcd_compressed_block_apply_reverse_csub"); + if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { + let owned_clean_scratch = if inplace_raw { + b.alloc_qubits(dialog_gcd_block_bits()) + } else { + Vec::new() + }; + let clean_scratch = if inplace_raw { + owned_clean_scratch.as_slice() + } else { + block_clean_scratch + }; + dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + y, + x, + b0, + p, + clean_scratch, + Some(step), + ); + if inplace_raw { + b.free_vec(&owned_clean_scratch); + } + } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { + cmod_sub_qq(b, y, x, b0, p); + } else { + cmod_sub_qq_lowq(b, y, x, b0, p); + } + if split_head11_pair_slot && !split_head11_keep_open_for_shift { + dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); + } + if split_head11_permute_shift { + dialog_gcd_k5_head11_pair01_expose_s2(b, raw); + } + if split_head11_borrow_pair23_shift { + dialog_gcd_k5_head11_pair01_zero_lane(b, raw); + dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); + } + if split_stream_tail3 { + if top32_final_s2_const { + dialog_gcd_k5_tail3_top32_toggle_raw_indices_from_code( + b, + compressed_block, + raw, + &[2 * slot], + ); + b.free(raw[2 * slot]); + } else { + let branch_raw = dialog_gcd_k5_tail3_top32_slot_branch_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_branch_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&branch_raw); + let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); + b.reacquire_vec(&shift_raw); + dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( + b, + compressed_block, + raw, + slot, + ); + } + } + + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_release"); + b.free_vec(scale_released_code); + } + b.set_phase("dialog_gcd_compressed_block_apply_reverse_halve_y"); + let apply_k2 = dialog_gcd_k2_enabled() + && std::env::var("DIALOG_GCD_K2_NO_APPLY").ok().as_deref() != Some("1"); + let free_clean_code = !inplace_raw + && dialog_gcd_apply_replay_swap_host_enabled() + && dialog_gcd_k5_free_clean_block_during_shift_enabled(); + if free_clean_code { + b.free_vec(shift_clean_code); + } + if top32_final_s2_const && apply_k2 { + dialog_gcd_fixed_halve_twice_y(b, y, p); + } else if apply_k2 + && dialog_gcd_apply_fused_fold_enabled() + && std::env::var("DIALOG_GCD_FUSE_HALVE_OFF").ok().as_deref() != Some("1") + { + + let s2 = if split_head11_borrow_pair23_shift { + raw[1] + } else { + dialog_gcd_block_raw_s2(raw, block_steps, slot) + }; + dialog_gcd_fused_halve_y_at_step(b, y, p, s2, Some(step)); + } else { + mod_halve_inplace_fast(b, y, p); + if apply_k2 { + + let s2 = if split_head11_borrow_pair23_shift { + raw[1] + } else { + dialog_gcd_block_raw_s2(raw, block_steps, slot) + }; + cmod_halve_inplace_lazy(b, y, p, s2); + } + } + if free_clean_code { + b.reacquire_vec(shift_clean_code); + } + if !scale_released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_scale_reacquire"); + b.reacquire_vec(scale_released_code); + } + if split_head11_borrow_pair23_shift { + dialog_gcd_k5_head11_toggle_pair23_s2_into(b, raw, raw[1]); + dialog_gcd_k5_head11_pair01_unzero_lane(b, raw); + } + if split_head11_keep_open_for_shift { + dialog_gcd_k5_head11_close_pair_for_slot(b, raw, slot); + } else if split_head11_permute_shift { + dialog_gcd_k5_head11_pair01_unexpose_s2(b, raw); + } else if !split_head11_pair_slot && (stream_k5_pairs || stream_head11_pairs) { + dialog_gcd_k5_stream_pairs_after_slot_reverse(b, raw, slot); + } + if stream_tail3 { + if split_stream_tail3 { + if !top32_final_s2_const { + let shift_raw = dialog_gcd_k5_tail3_top32_slot_shift_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_shift_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&shift_raw); + } + } else { + let slot_raw = dialog_gcd_k5_tail3_top32_slot_raw(raw, slot); + dialog_gcd_k5_tail3_top32_toggle_slot_raw_from_code( + b, + compressed_block, + raw, + slot, + ); + b.free_vec(&slot_raw); + } + } + } + + if !released_code.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_reacquire_block"); + b.reacquire_vec(released_code); + } + if !released_partial_raw.is_empty() { + b.set_phase("dialog_gcd_compressed_block_apply_reverse_reacquire_partial_raw"); + b.reacquire_vec(&released_partial_raw); + } + if head11_block && !stream_head11_pairs { + b.reacquire(raw_block[1]); + } + b.set_phase("dialog_gcd_compressed_block_apply_reverse_clear_block_copy"); + if stream_tail3 { + b.reacquire_vec(&stream_dynamic_raw); + } else if stream_head11_pairs { + dialog_gcd_k5_stream_pairs_finish(b, raw_block); + dialog_gcd_k5_head11_compress_data_to_block( + b, + compressed_block, + raw_block, + true, + ); + } else if stream_k5_pairs { + dialog_gcd_k5_stream_pairs_finish(b, raw_block); + dialog_gcd_k5_compress_data_to_block(b, compressed_block, raw_block, true); + } else if let Some(raw0) = inplace_raw0 { + dialog_gcd_k2_pair_inplace_clear_block(b, compressed_block, raw0, end - start); + } else { + dialog_gcd_clear_raw_block_copy(b, compressed_block, raw_block, end - start); + } + } + + if let Some(raw0) = inplace_raw0 { + b.free(raw0); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + compressed_log: &[QubitId], + pair: &[QubitId], + scratch: QubitId, +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert_eq!(pair.len(), 2); + assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); + + for step in 0..dialog_gcd_active_iterations() { + let b0 = pair[0]; + let b0_and_b1 = pair[1]; + let cmp = b.alloc_qubit(); + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_branch_bits"); + b.cx(v[0], b0); + if dialog_gcd_fused_branch_bits_enabled() { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } else { + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + } + b.free(cmp); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_cswap"); + let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); + for (i, (&ui, &vi)) in u[..cswap_width] + .iter() + .zip(v[..cswap_width].iter()) + .enumerate() + { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_subtract"); + let borrowed_carries = + dialog_gcd_compressed_sidecar_future_carry_slice(compressed_log, step, active_width); + dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_shift"); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + dialog_gcd_shift_right_assuming_even(b, &v[..shift_width]); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_absorb_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + compressed_log: &[QubitId], + pair: &[QubitId], + scratch: QubitId, +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert_eq!(pair.len(), 2); + assert!(compressed_log.len() >= dialog_gcd_compressed_sidecar_bits()); + + for step in (0..dialog_gcd_active_iterations()).rev() { + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_load_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + + let b0 = pair[0]; + let b0_and_b1 = pair[1]; + let cmp = b.alloc_qubit(); + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_unshift"); + let shift_width = dialog_gcd_tobitvector_shift_width(active_width, step); + dialog_gcd_unshift_right_assuming_even(b, &v[..shift_width]); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_add"); + let borrowed_carries = + dialog_gcd_compressed_sidecar_future_carry_slice(compressed_log, step, active_width); + dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_cswap"); + let cswap_width = dialog_gcd_tobitvector_cswap_width(active_width, step); + for (i, (&ui, &vi)) in u[..cswap_width] + .iter() + .zip(v[..cswap_width].iter()) + .enumerate() + { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_compressed_sidecar_tobitvector_reverse_branch_bits"); + if dialog_gcd_fused_branch_bits_enabled() { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } else { + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + } + b.free(cmp); + b.cx(v[0], b0); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector( + b: &mut B, + compressed_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, + pair: &[QubitId], + scratch: QubitId, +) { + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + assert_eq!(pair.len(), 2); + + for step in (0..dialog_gcd_active_iterations()).rev() { + b.set_phase("dialog_gcd_compressed_sidecar_apply_load_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + + let b0 = pair[0]; + let b0_and_b1 = pair[1]; + + b.set_phase("dialog_gcd_compressed_sidecar_apply_double_y"); + mod_double_inplace_fast(b, y, p); + + b.set_phase("dialog_gcd_compressed_sidecar_apply_cadd"); + if dialog_gcd_raw_apply_materialized_special_add_enabled() { + dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); + } else if dialog_gcd_raw_apply_direct_special_add_enabled() { + dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); + } else { + cmod_add_qq_lowq(b, y, x, b0, p); + } + + b.set_phase("dialog_gcd_compressed_sidecar_apply_cswap"); + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + + b.set_phase("dialog_gcd_compressed_sidecar_apply_unload_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( + b: &mut B, + compressed_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, + pair: &[QubitId], + scratch: QubitId, +) { + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + assert_eq!(pair.len(), 2); + + for step in 0..dialog_gcd_active_iterations() { + b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_load_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + + let b0 = pair[0]; + let b0_and_b1 = pair[1]; + + b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_cswap"); + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + + b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_csub"); + if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { + dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); + } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { + cmod_sub_qq(b, y, x, b0, p); + } else { + cmod_sub_qq_lowq(b, y, x, b0, p); + } + + b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_halve_y"); + mod_halve_inplace_fast(b, y, p); + + b.set_phase("dialog_gcd_compressed_sidecar_apply_reverse_unload_pair"); + let block = dialog_gcd_compressed_sidecar_block(compressed_log, step); + emit_dialog_gcd_round763_compressed_block_swapper( + b, + pair, + block, + scratch, + step % DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE, + ); + } +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_ipmul_block_lifecycle( + b: &mut B, + factor: &[QubitId], + target: &[QubitId], + p: U256, +) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + let compressed_log = b.alloc_qubits(dialog_gcd_allocated_compressed_sidecar_bits()); + let raw_block = if dialog_gcd_host_reverse_raw_block_enabled() { + Vec::new() + } else { + b.alloc_qubits(dialog_gcd_raw_block_len()) + }; + let u = b.alloc_qubits(N); + let runway = dialog_gcd_build_compressed_log_u_high_runway(&u, &compressed_log); + let replay_log = runway + .as_ref() + .map_or(compressed_log.as_slice(), |r| r.remapped_log.as_slice()); + b.set_phase("dialog_gcd_compressed_block_ipmul_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_compressed_block_ipmul_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_compressed_block_ipmul_release_terminal_u"); + b.x(u[0]); + dialog_gcd_release_terminal_u(b, &u, runway.as_ref()); + + b.set_phase("dialog_gcd_compressed_block_ipmul_apply_bitvector_reuse_factor_zero"); + let inplace_apply_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); + if inplace_apply_raw && !raw_block.is_empty() { + b.free_vec(&raw_block); + } + let apply_raw_block = if !inplace_apply_raw && dialog_gcd_host_reverse_raw_block_enabled() { + b.alloc_qubits(dialog_gcd_raw_block_len()) + } else { + Vec::new() + }; + emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( + b, + replay_log, + target, + factor, + p, + if inplace_apply_raw { + &[] + } else if apply_raw_block.is_empty() { + &raw_block + } else { + &apply_raw_block + }, + ); + if !apply_raw_block.is_empty() { + b.free_vec(&apply_raw_block); + } + + if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { + b.set_phase("dialog_gcd_compressed_block_ipmul_clear_p_residual_source_lane"); + for i in 0..N { + if bit(p, i) { + b.x(target[i]); + } + } + } + + b.set_phase("dialog_gcd_compressed_block_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + if inplace_apply_raw && !raw_block.is_empty() { + b.reacquire_vec(&raw_block); + } + + b.set_phase("dialog_gcd_compressed_block_ipmul_reacquire_terminal_u"); + dialog_gcd_reacquire_terminal_u(b, &u, runway.as_ref()); + b.set_phase("dialog_gcd_compressed_block_ipmul_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_compressed_block_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + if !b.k2_shift2_log.is_empty() { + let log = std::mem::take(&mut b.k2_shift2_log); + b.free_vec(&log); + } + b.free_vec(&u); + if !raw_block.is_empty() { + b.free_vec(&raw_block); + } + b.free_vec(&compressed_log); + return; + } + + let tmp = b.alloc_qubits(N); + b.set_phase("dialog_gcd_compressed_block_ipmul_apply_bitvector"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector_block_lifecycle( + b, replay_log, target, &tmp, p, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], tmp[i]); + } + + b.set_phase("dialog_gcd_compressed_block_ipmul_free_zero_tmp"); + b.free_vec(&tmp); + + b.set_phase("dialog_gcd_compressed_block_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + if !b.k2_shift2_log.is_empty() { + let log = std::mem::take(&mut b.k2_shift2_log); + b.free_vec(&log); + } + b.free_vec(&u); + b.free_vec(&raw_block); + b.free_vec(&compressed_log); +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_ipmul( + b: &mut B, + factor: &[QubitId], + target: &[QubitId], + p: U256, +) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + if dialog_gcd_compressed_block_lifecycle_enabled() { + emit_dialog_gcd_compressed_sidecar_ipmul_block_lifecycle(b, factor, target, p); + return; + } + + let compressed_log = b.alloc_qubits(dialog_gcd_compressed_sidecar_bits()); + let pair = b.alloc_qubits(2); + let compressor_scratch = b.alloc_qubit(); + let u = b.alloc_qubits(N); + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_release_terminal_u"); + b.x(u[0]); + b.free_vec(&u); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_apply_bitvector_reuse_factor_zero"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector( + b, + &compressed_log, + target, + factor, + p, + &pair, + compressor_scratch, + ); + + if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_clear_p_residual_source_lane"); + for i in 0..N { + if bit(p, i) { + b.x(target[i]); + } + } + } + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_reacquire_terminal_u"); + b.reacquire_vec(&u); + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free(compressor_scratch); + b.free_vec(&pair); + b.free_vec(&compressed_log); + return; + } + + let tmp = b.alloc_qubits(N); + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_apply_bitvector"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector( + b, + &compressed_log, + target, + &tmp, + p, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], tmp[i]); + } + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_free_zero_tmp"); + b.free_vec(&tmp); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free(compressor_scratch); + b.free_vec(&pair); + b.free_vec(&compressed_log); +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_quotient_block_lifecycle( + b: &mut B, + factor: &[QubitId], + target: &[QubitId], + p: U256, +) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + let compressed_log = b.alloc_qubits(dialog_gcd_allocated_compressed_sidecar_bits()); + let raw_block = if dialog_gcd_host_reverse_raw_block_enabled() { + Vec::new() + } else { + b.alloc_qubits(dialog_gcd_raw_block_len()) + }; + let u = b.alloc_qubits(N); + let runway = dialog_gcd_build_compressed_log_u_high_runway(&u, &compressed_log); + let replay_log = runway + .as_ref() + .map_or(compressed_log.as_slice(), |r| r.remapped_log.as_slice()); + b.set_phase("dialog_gcd_compressed_block_quotient_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_compressed_block_quotient_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + if dialog_gcd_raw_quotient_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_compressed_block_quotient_release_terminal_u"); + b.x(u[0]); + dialog_gcd_release_terminal_u(b, &u, runway.as_ref()); + + b.set_phase("dialog_gcd_compressed_block_quotient_apply_reverse_reuse_factor_zero"); + let inplace_apply_raw = dialog_gcd_k2_apply_inplace_raw_block_enabled(); + if inplace_apply_raw && !raw_block.is_empty() { + b.free_vec(&raw_block); + } + let apply_raw_block = if !inplace_apply_raw && dialog_gcd_host_reverse_raw_block_enabled() { + b.alloc_qubits(dialog_gcd_raw_block_len()) + } else { + Vec::new() + }; + emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( + b, + replay_log, + factor, + target, + p, + if inplace_apply_raw { + &[] + } else if apply_raw_block.is_empty() { + &raw_block + } else { + &apply_raw_block + }, + ); + if !apply_raw_block.is_empty() { + b.free_vec(&apply_raw_block); + } + + b.set_phase("dialog_gcd_compressed_block_quotient_swap_quotient_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + if inplace_apply_raw && !raw_block.is_empty() { + b.reacquire_vec(&raw_block); + } + + b.set_phase("dialog_gcd_compressed_block_quotient_reacquire_terminal_u"); + dialog_gcd_reacquire_terminal_u(b, &u, runway.as_ref()); + b.set_phase("dialog_gcd_compressed_block_quotient_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_compressed_block_quotient_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + if !b.k2_shift2_log.is_empty() { + let log = std::mem::take(&mut b.k2_shift2_log); + b.free_vec(&log); + } + b.free_vec(&u); + if !raw_block.is_empty() { + b.free_vec(&raw_block); + } + b.free_vec(&compressed_log); + return; + } + + b.set_phase("dialog_gcd_compressed_block_quotient_apply_reverse"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact_block_lifecycle( + b, replay_log, factor, target, p, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_quotient_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse_block_lifecycle( + b, &u, factor, replay_log, &raw_block, + ); + + b.set_phase("dialog_gcd_compressed_block_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + if !b.k2_shift2_log.is_empty() { + let log = std::mem::take(&mut b.k2_shift2_log); + b.free_vec(&log); + } + b.free_vec(&u); + b.free_vec(&raw_block); + b.free_vec(&compressed_log); +} + +pub(crate) fn emit_dialog_gcd_compressed_sidecar_quotient( + b: &mut B, + factor: &[QubitId], + target: &[QubitId], + p: U256, +) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + if dialog_gcd_compressed_block_lifecycle_enabled() { + emit_dialog_gcd_compressed_sidecar_quotient_block_lifecycle(b, factor, target, p); + return; + } + + let compressed_log = b.alloc_qubits(dialog_gcd_compressed_sidecar_bits()); + let pair = b.alloc_qubits(2); + let compressor_scratch = b.alloc_qubit(); + let u = b.alloc_qubits(N); + b.set_phase("dialog_gcd_compressed_sidecar_quotient_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + if dialog_gcd_raw_quotient_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_compressed_sidecar_quotient_release_terminal_u"); + b.x(u[0]); + b.free_vec(&u); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_apply_reverse_reuse_factor_zero"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( + b, + &compressed_log, + factor, + target, + p, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_swap_quotient_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_reacquire_terminal_u"); + b.reacquire_vec(&u); + b.set_phase("dialog_gcd_compressed_sidecar_quotient_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free(compressor_scratch); + b.free_vec(&pair); + b.free_vec(&compressed_log); + return; + } + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_apply_reverse"); + emit_dialog_gcd_compressed_sidecar_apply_bitvector_reverse_exact( + b, + &compressed_log, + factor, + target, + p, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_uncompute_tobitvector"); + emit_dialog_gcd_compressed_sidecar_tobitvector_steps_reverse( + b, + &u, + factor, + &compressed_log, + &pair, + compressor_scratch, + ); + + b.set_phase("dialog_gcd_compressed_sidecar_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free(compressor_scratch); + b.free_vec(&pair); + b.free_vec(&compressed_log); +} + +pub(crate) fn emit_dialog_gcd_k2_pair_core_encoder(b: &mut B, core: &[QubitId]) { + assert_eq!(core.len(), 5); + + b.cx(core[1], core[2]); + b.cx(core[0], core[4]); + b.x(core[3]); + b.ccx(core[2], core[3], core[1]); + b.cx(core[3], core[4]); + b.ccx(core[3], core[4], core[0]); + b.cx(core[2], core[4]); + b.cx(core[0], core[3]); + b.cx(core[3], core[2]); + b.cx(core[3], core[4]); + b.ccx(core[1], core[3], core[0]); + b.cx(core[1], core[0]); + b.cx(core[3], core[0]); +} + +pub(crate) fn emit_dialog_gcd_k2_pair_core_encoder_inverse(b: &mut B, core: &[QubitId]) { + assert_eq!(core.len(), 5); + + b.cx(core[3], core[0]); + b.cx(core[1], core[0]); + b.ccx(core[1], core[3], core[0]); + b.cx(core[3], core[4]); + b.cx(core[3], core[2]); + b.cx(core[0], core[3]); + b.cx(core[2], core[4]); + b.ccx(core[3], core[4], core[0]); + b.cx(core[3], core[4]); + b.ccx(core[2], core[3], core[1]); + b.x(core[3]); + b.cx(core[0], core[4]); + b.cx(core[1], core[2]); +} + +pub(crate) fn dialog_gcd_k2_pair_core(raw_block: &[QubitId]) -> [QubitId; 5] { + assert_eq!(raw_block.len(), 6); + [ + raw_block[0], + raw_block[1], + raw_block[4], + raw_block[2], + raw_block[3], + ] +} + +pub(crate) fn dialog_gcd_k2_pair_copy_compressed_block_to_raw( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); + assert_eq!(raw_block.len(), 6); + assert!((1..=2).contains(&steps)); + let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); + if steps == 1 { + let raw_encoded = [raw_block[0], raw_block[1], raw_block[4]]; + for (&c, &r) in compressed_block.iter().take(3).zip(raw_encoded.iter()) { + if swap_host { + b.swap(c, r); + } else { + b.cx(c, r); + } + } + return; + } + let raw_encoded = [raw_block[1], raw_block[4], raw_block[2], raw_block[3], raw_block[5]]; + for (&c, &r) in compressed_block.iter().zip(raw_encoded.iter()) { + if swap_host { + b.swap(c, r); + } else { + b.cx(c, r); + } + } + let core = dialog_gcd_k2_pair_core(raw_block); + emit_dialog_gcd_k2_pair_core_encoder_inverse(b, &core); +} + +pub(crate) fn dialog_gcd_k2_pair_clear_raw_block_copy( + b: &mut B, + compressed_block: &[QubitId], + raw_block: &[QubitId], + steps: usize, +) { + assert_eq!(compressed_block.len(), DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS); + assert_eq!(raw_block.len(), 6); + assert!((1..=2).contains(&steps)); + let swap_host = dialog_gcd_apply_replay_swap_host_enabled(); + if steps == 1 { + let raw_encoded = [raw_block[0], raw_block[1], raw_block[4]]; + for (&c, &r) in compressed_block.iter().take(3).zip(raw_encoded.iter()) { + if swap_host { + b.swap(c, r); + } else { + b.cx(c, r); + } + } + return; + } + let core = dialog_gcd_k2_pair_core(raw_block); + emit_dialog_gcd_k2_pair_core_encoder(b, &core); + let raw_encoded = [raw_block[1], raw_block[4], raw_block[2], raw_block[3], raw_block[5]]; + for (&c, &r) in compressed_block.iter().zip(raw_encoded.iter()) { + if swap_host { + b.swap(c, r); + } else { + b.cx(c, r); + } + } +} + +fn dialog_gcd_fixed_twice_fold( + b: &mut B, + y: &[QubitId], + p: U256, + e: QubitId, + d: QubitId, + is_add: bool, +) { + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + let h = b.alloc_qubit(); + b.ccx(e, d, h); + let xed = b.alloc_qubit(); + b.cx(e, xed); + b.cx(d, xed); + let eord = b.alloc_qubit(); + b.cx(xed, eord); + b.cx(h, eord); + let n10 = b.alloc_qubit(); + b.cx(d, n10); + b.cx(h, n10); + + let hi_c = highest_set_bit(c); + let hi_delta = hi_c + 1; + let controls = secp_fold_controls(e, d, h, xed, eord, n10, hi_delta, hi_c); + let last = match fold_only_carry_trunc_window().or_else(double_carry_trunc_window) { + Some(w) => core::cmp::min(y.len() - 2, hi_delta.saturating_add(w)), + None => y.len() - 2, + }; + if fold_freed_tail_enabled() && last > hi_delta { + fold_ripple_freed_tail(b, y, e, d, h, xed, eord, n10, last, is_add); + } else if is_add { + cadd_per_position_controls_trunc(b, y, &controls, last); + } else { + csub_per_position_controls_trunc(b, y, &controls, last); + } + + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(n10); + b.free(eord); + b.free(xed); + if dialog_gcd_fused_hclear_measured_enabled() { + let measured = b.alloc_bit(); + b.hmr(h, measured); + b.cz_if(e, d, measured); + } else { + b.ccx(e, d, h); + } + b.free(h); +} + +fn dialog_gcd_fixed_double_twice_y(b: &mut B, y: &[QubitId], p: U256) { + let n = y.len(); + debug_assert_eq!(n, 256); + let ovf1 = b.alloc_qubit(); + b.swap(y[n - 1], ovf1); + for i in (0..n - 1).rev() { + b.swap(y[i], y[i + 1]); + } + let ovf2 = b.alloc_qubit(); + b.swap(y[n - 1], ovf2); + for i in (0..n - 1).rev() { + b.swap(y[i], y[i + 1]); + } + + dialog_gcd_fixed_twice_fold(b, y, p, ovf2, ovf1, true); + b.cx(y[0], ovf2); + b.cx(y[1], ovf1); + b.free(ovf2); + b.free(ovf1); +} + +fn dialog_gcd_fixed_halve_twice_y(b: &mut B, y: &[QubitId], p: U256) { + let n = y.len(); + debug_assert_eq!(n, 256); + let ovf2 = b.alloc_qubit(); + let ovf1 = b.alloc_qubit(); + b.cx(y[0], ovf2); + b.cx(y[1], ovf1); + + dialog_gcd_fixed_twice_fold(b, y, p, ovf2, ovf1, false); + for i in 0..n - 1 { + b.swap(y[i], y[i + 1]); + } + b.swap(y[n - 1], ovf2); + b.free(ovf2); + for i in 0..n - 1 { + b.swap(y[i], y[i + 1]); + } + b.swap(y[n - 1], ovf1); + b.free(ovf1); +} + +pub(crate) fn dialog_gcd_k5_tail7_fixed_apply_selftest() -> Result<(), String> { + use sha3::digest::{ExtendableOutput, Update}; + + let input_masks = (0..N) + .map(|bit| { + let x = (bit as u64) + .wrapping_mul(0x9E37_79B9_7F4A_7C15) + .wrapping_add(0xD1B5_4A32_D192_ED03); + let x = (x ^ (x >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9); + x ^ (x >> 27) + }) + .collect::>(); + + for reverse in [false, true] { + let build_one = |fixed: bool| { + let mut b = B::new(); + let y = b.alloc_qubits(N); + if fixed { + if reverse { + dialog_gcd_fixed_halve_twice_y(&mut b, &y, SECP256K1_P); + } else { + dialog_gcd_fixed_double_twice_y(&mut b, &y, SECP256K1_P); + } + } else { + let one = b.alloc_qubit(); + b.x(one); + if reverse { + dialog_gcd_fused_halve_y(&mut b, &y, SECP256K1_P, one); + } else { + dialog_gcd_fused_double_y(&mut b, &y, SECP256K1_P, one); + } + b.x(one); + b.free(one); + } + (b.ops, y, b.next_qubit as usize, b.next_bit as usize) + }; + + let run = |fixed: bool| { + let (ops, y, num_qubits, num_bits) = build_one(fixed); + let mut seed = sha3::Shake128::default(); + seed.update(b"dialog-gcd-k5-tail7-fixed-apply-selftest"); + seed.update(&[reverse as u8, fixed as u8]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new(num_qubits, num_bits, &mut xof); + sim.clear_for_shot(); + for (&q, &mask) in y.iter().zip(input_masks.iter()) { + *sim.qubit_mut(q) = mask; + } + sim.apply_iter(ops.iter()); + let output = y.iter().map(|&q| sim.qubit(q)).collect::>(); + let clean = (N..num_qubits).all(|q| sim.qubit(QubitId(q as u64)) == 0); + (output, clean, sim.phase) + }; + + let (baseline, baseline_clean, baseline_phase) = run(false); + let (fixed, fixed_clean, fixed_phase) = run(true); + if !baseline_clean || baseline_phase != 0 { + return Err(format!( + "baseline dirty: reverse={reverse} clean={baseline_clean} phase=0x{baseline_phase:x}" + )); + } + if !fixed_clean || fixed_phase != 0 { + return Err(format!( + "fixed dirty: reverse={reverse} clean={fixed_clean} phase=0x{fixed_phase:x}" + )); + } + if baseline != fixed { + let bit = baseline + .iter() + .zip(fixed.iter()) + .position(|(a, b)| a != b) + .expect("different vectors have a differing bit"); + return Err(format!( + "value mismatch: reverse={reverse} bit={bit} baseline=0x{:x} fixed=0x{:x}", + baseline[bit], fixed[bit] + )); + } + } + Ok(()) +} + +pub(crate) fn dialog_gcd_fused_double_y(b: &mut B, y: &[QubitId], p: U256, s2: QubitId) { + dialog_gcd_fused_double_y_at_step(b, y, p, s2, None); +} + +pub(crate) fn dialog_gcd_fused_double_y_at_step( + b: &mut B, + y: &[QubitId], + p: U256, + s2: QubitId, + step: Option, +) { + let n = y.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let ovf1 = b.alloc_qubit(); + b.swap(y[n - 1], ovf1); + for i in (0..n - 1).rev() { + b.swap(y[i], y[i + 1]); + } + + let ovf2 = b.alloc_qubit(); + cswap(b, s2, y[n - 1], ovf2); + for i in (0..n - 1).rev() { + if dialog_gcd_skip_zero_edge_apply_double_cshift_enabled() && i == 0 { + continue; + } + cswap(b, s2, y[i], y[i + 1]); + } + + let e = b.alloc_qubit(); + let d = b.alloc_qubit(); + let hi_delta = highest_set_bit(c) + 1; + let last = match dialog_gcd_fused_fold_carry_trunc_window(step) { + Some(w) => core::cmp::min(n - 2, hi_delta.saturating_add(w)), + None => n - 2, + }; + if fold_stream_controls_enabled() && fold_freed_tail_enabled() && last > hi_delta { + if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { + b.set_phase("dialog_gcd_streamed_double_setup"); + } + b.ccx(ovf1, s2, d); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + fold_ripple_freed_tail_ed_streamed( + b, + y, + e, + d, + Some((ovf1, ovf2, s2)), + fold_park_low_carries_at_step(step), + last, + true, + ); + if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { + b.set_phase("dialog_gcd_streamed_double_cleanup"); + } + } else { + let h = b.alloc_qubit(); + b.ccx(ovf1, s2, d); + b.cx(ovf1, e); + b.cx(d, e); + b.cx(ovf2, e); + b.ccx(ovf2, d, h); + let xed = b.alloc_qubit(); + b.cx(e, xed); + b.cx(d, xed); + let eord = b.alloc_qubit(); + b.cx(xed, eord); + b.cx(h, eord); + let n10 = b.alloc_qubit(); + b.cx(d, n10); + b.cx(h, n10); + + let mut controls: Vec> = vec![None; hi_delta + 1]; + controls[0] = Some(e); + controls[1] = Some(d); + controls[4] = Some(e); + controls[5] = Some(d); + controls[6] = Some(e); + controls[7] = Some(xed); + controls[8] = Some(eord); + controls[9] = Some(eord); + controls[10] = Some(n10); + controls[11] = Some(h); + controls[highest_set_bit(c)] = Some(e); + controls[hi_delta] = Some(d); + if fold_freed_tail_enabled() && last > hi_delta { + fold_ripple_freed_tail_ed( + b, + y, + e, + d, + h, + xed, + eord, + n10, + Some((ovf1, ovf2, s2)), + step, + last, + true, + ); + } else { + cadd_per_position_controls_trunc(b, y, &controls, last); + } + + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(n10); + b.free(eord); + b.free(xed); + if dialog_gcd_fused_hclear_measured_enabled() { + let m = b.alloc_bit(); + b.hmr(h, m); + b.cz_if(ovf2, d, m); + } else { + b.ccx(ovf2, d, h); + } + b.free(h); + } + + b.cx(y[0], e); + + if dialog_gcd_fused_dclear_measured_enabled() { + let m = b.alloc_bit(); + b.hmr(d, m); + b.cz_if(ovf1, s2, m); + } else { + b.ccx(s2, y[1], d); + } + b.free(d); + b.free(e); + + if dialog_gcd_fused_ovfclear_measured_enabled() { + let m = b.alloc_bit(); + b.hmr(ovf1, m); + b.cz_if(s2, y[1], m); + b.x(s2); + b.cz_if(s2, y[0], m); + b.x(s2); + } else { + b.ccx(s2, y[1], ovf1); + b.x(s2); + b.ccx(s2, y[0], ovf1); + b.x(s2); + } + b.free(ovf1); + + if dialog_gcd_fused_ovfclear_measured_enabled() { + let m = b.alloc_bit(); + b.hmr(ovf2, m); + b.cz_if(s2, y[0], m); + } else { + b.ccx(s2, y[0], ovf2); + } + b.free(ovf2); +} + +pub(crate) fn dialog_gcd_fused_halve_y(b: &mut B, y: &[QubitId], p: U256, s2: QubitId) { + dialog_gcd_fused_halve_y_at_step(b, y, p, s2, None); +} + +pub(crate) fn dialog_gcd_fused_halve_y_at_step( + b: &mut B, + y: &[QubitId], + p: U256, + s2: QubitId, + step: Option, +) { + let n = y.len(); + debug_assert_eq!(n, 256); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1)); + + let e = b.alloc_qubit(); + let d = b.alloc_qubit(); + let hi_delta = highest_set_bit(c) + 1; + let last = match dialog_gcd_fused_fold_carry_trunc_window(step) { + Some(w) => core::cmp::min(n - 2, hi_delta.saturating_add(w)), + None => n - 2, + }; + let (ovf2, ovf1) = + if fold_stream_controls_enabled() && fold_freed_tail_enabled() && last > hi_delta { + if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { + b.set_phase("dialog_gcd_streamed_halve_setup"); + } + b.cx(y[0], e); + b.ccx(s2, y[1], d); + let ovf2 = b.alloc_qubit(); + let ovf1 = b.alloc_qubit(); + b.ccx(e, s2, ovf2); + b.cx(e, ovf1); + let xed = b.alloc_qubit(); + b.cx(e, xed); + b.cx(d, xed); + b.ccx(s2, xed, ovf1); + b.cx(d, xed); + b.cx(e, xed); + b.free(xed); + fold_ripple_freed_tail_ed_streamed( + b, + y, + e, + d, + Some((ovf1, ovf2, s2)), + fold_park_low_carries_at_step(step), + last, + false, + ); + if std::env::var("DIALOG_GCD_FOLD_PROFILE_PHASES").ok().as_deref() == Some("1") { + b.set_phase("dialog_gcd_streamed_halve_cleanup"); + } + (ovf2, ovf1) + } else { + let h = b.alloc_qubit(); + b.cx(y[0], e); + b.ccx(s2, y[1], d); + b.ccx(e, d, h); + let xed = b.alloc_qubit(); + b.cx(e, xed); + b.cx(d, xed); + let eord = b.alloc_qubit(); + b.cx(xed, eord); + b.cx(h, eord); + let n10 = b.alloc_qubit(); + b.cx(d, n10); + b.cx(h, n10); + let ovf2 = b.alloc_qubit(); + let ovf1 = b.alloc_qubit(); + b.ccx(e, s2, ovf2); + b.cx(e, ovf1); + b.ccx(s2, xed, ovf1); + + let mut controls: Vec> = vec![None; hi_delta + 1]; + controls[0] = Some(e); + controls[1] = Some(d); + controls[4] = Some(e); + controls[5] = Some(d); + controls[6] = Some(e); + controls[7] = Some(xed); + controls[8] = Some(eord); + controls[9] = Some(eord); + controls[10] = Some(n10); + controls[11] = Some(h); + controls[highest_set_bit(c)] = Some(e); + controls[hi_delta] = Some(d); + if fold_freed_tail_enabled() && last > hi_delta { + fold_ripple_freed_tail_ed( + b, + y, + e, + d, + h, + xed, + eord, + n10, + Some((ovf1, ovf2, s2)), + step, + last, + false, + ); + } else { + csub_per_position_controls_trunc(b, y, &controls, last); + } + + b.cx(h, n10); + b.cx(d, n10); + b.cx(h, eord); + b.cx(xed, eord); + b.cx(d, xed); + b.cx(e, xed); + b.free(n10); + b.free(eord); + b.free(xed); + if dialog_gcd_fused_hclear_measured_enabled() { + let m = b.alloc_bit(); + b.hmr(h, m); + b.cz_if(e, d, m); + } else { + b.ccx(e, d, h); + } + b.free(h); + (ovf2, ovf1) + }; + + if dialog_gcd_fused_halve_edclear_measured_enabled() { + let me = b.alloc_bit(); + b.hmr(e, me); + b.x(s2); + b.cz_if(s2, ovf1, me); + b.x(s2); + b.cz_if(s2, ovf2, me); + let md = b.alloc_bit(); + b.hmr(d, md); + b.cz_if(s2, ovf1, md); + } else { + b.x(s2); + b.ccx(s2, ovf1, e); + b.x(s2); + b.ccx(s2, ovf2, e); + b.ccx(s2, ovf1, d); + } + b.free(e); + b.free(d); + + for i in 0..n - 1 { + if dialog_gcd_skip_zero_edge_apply_halve_cshift_enabled() && i == 0 { + continue; + } + cswap(b, s2, y[i], y[i + 1]); + } + cswap(b, s2, y[n - 1], ovf2); + + b.free(ovf2); + + for i in 0..n - 1 { + b.swap(y[i], y[i + 1]); + } + b.swap(y[n - 1], ovf1); + + b.free(ovf1); +} diff --git a/src/point_add/rounds/dialog/config.rs b/src/point_add/rounds/dialog/config.rs index f89e40b7..95de296a 100644 --- a/src/point_add/rounds/dialog/config.rs +++ b/src/point_add/rounds/dialog/config.rs @@ -1,533 +1,533 @@ - -use super::*; - -pub const DIALOG_GCD_ACTIVE_ITERATIONS_ENV: &str = "DIALOG_GCD_ACTIVE_ITERATIONS"; -pub const DIALOG_GCD_COMPARE_BITS_ENV: &str = "DIALOG_GCD_COMPARE_BITS"; -pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE_ENV: &str = "DIALOG_GCD_PA9024_COMPARE_SCHEDULE"; -pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR_ENV: &str = - "DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR"; -pub const DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS_ENV: &str = "DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS"; -pub const DIALOG_GCD_COMPRESSED_SIDECAR_LOG_ENV: &str = "DIALOG_GCD_COMPRESSED_SIDECAR_LOG"; -pub const DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE_ENV: &str = "DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE"; -pub const DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD_ENV: &str = - "DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD"; -pub const DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD_ENV: &str = - "DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD"; -pub const DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB_ENV: &str = "DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB"; -pub const DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB_ENV: &str = - "DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB"; -pub const DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB_ENV: &str = - "DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB"; -pub const DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH_ENV: &str = - "DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH"; -pub const DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES_ENV: &str = - "DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES"; -pub const DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE_ENV: &str = "DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE"; -pub const DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL_ENV: &str = "DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL"; -pub const DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE_ENV: &str = - "DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE"; -pub const DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U_ENV: &str = - "DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U"; -pub const DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN_ENV: &str = "DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN"; -pub const DIALOG_GCD_RAW_PA_ENV: &str = "DIALOG_GCD_RAW_PA"; -pub const DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT"; -pub const DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL"; -pub const DIALOG_GCD_RAW_PA_STOP_AFTER_C_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_C"; -pub const DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2"; - -pub(crate) fn dialog_gcd_raw_apply_direct_special_add_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_apply_materialized_special_add_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_apply_reverse_fast_sub_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_chunked_f_blocks() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&blocks| blocks >= 2) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_cuts() -> Option> { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUTS") - .ok() - .filter(|value| !value.trim().is_empty()) - .map(|value| { - value - .split(',') - .map(|item| { - item.trim() - .parse::() - .expect("DIALOG_GCD_APPLY_CHUNKED_F_CUTS") - }) - .collect() - }) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_cut() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&cut| (1..N).contains(&cut)) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_cut2() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT2") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&cut| (1..N).contains(&cut)) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_cut3() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT3") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&cut| (1..N).contains(&cut)) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_cut4() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT4") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&cut| (1..N).contains(&cut)) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_custom4_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM4") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_chunked_f_custom5_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM5") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_REUSE_CIN_ZERO") - .ok() - .as_deref() - != Some("0") -} - -pub(crate) fn dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_FUSE_BOUNDARY_CLEARS") - .ok() - .as_deref() - != Some("0") -} - -pub(crate) fn dialog_gcd_apply_borrow_future_boundary_carries_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_BORROW_FUTURE_BOUNDARY_CARRIES") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_boundary_free_owned_during_replay_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_BOUNDARY_FREE_OWNED_DURING_REPLAY") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_implicit_high_zero_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_IMPLICIT_HIGH_ZERO") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_chunked_f_auto_topclean_target() -> Option { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_TARGET") - .ok() - .and_then(|value| value.parse::().ok()) - .filter(|&target| target > 0) -} - -pub(crate) fn dialog_gcd_apply_chunked_f_auto_topclean_max_bits() -> usize { - std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_MAX_BITS") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(1) -} - -pub(crate) fn dialog_gcd_apply_final_lowq_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_FINAL_LOWQ").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_fused_hclear_measured_enabled() -> bool { - std::env::var("DIALOG_GCD_FUSED_HCLEAR_MEASURED").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_fused_dclear_measured_enabled() -> bool { - std::env::var("DIALOG_GCD_FUSED_DCLEAR_MEASURED").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_fused_ovfclear_measured_enabled() -> bool { - std::env::var("DIALOG_GCD_FUSED_OVFCLEAR_MEASURED").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_fused_halve_edclear_measured_enabled() -> bool { - std::env::var("DIALOG_GCD_FUSED_HALVE_EDCLEAR_MEASURED").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_apply_final_windowed_fast_blocks() -> Option { - std::env::var("DIALOG_GCD_APPLY_FINAL_WINDOWED_FAST_BLOCKS") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&blocks| blocks >= 2) -} - -pub(crate) fn dialog_gcd_apply_final_topclean_bits() -> usize { - std::env::var("DIALOG_GCD_APPLY_FINAL_TOPCLEAN") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -pub(crate) fn dialog_gcd_apply_boundary_split() -> Option { - std::env::var("DIALOG_GCD_APPLY_BOUNDARY_SPLIT") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&split| split > 0) -} - -pub(crate) fn dialog_gcd_apply_boundary_conditional_replay_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_BOUNDARY_CONDITIONAL_REPLAY") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_reverse_branch_conditional_replay_enabled() -> bool { - std::env::var("DIALOG_GCD_REVERSE_BRANCH_CONDITIONAL_REPLAY") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_special_clean_conditional_replay_enabled() -> bool { - std::env::var("DIALOG_GCD_SPECIAL_CLEAN_CONDITIONAL_REPLAY") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_replay_swap_host_enabled() -> bool { - - std::env::var("DIALOG_GCD_APPLY_REPLAY_SWAP_HOST") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_tobitvector_materialized_sub_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_ctrl_body_vented_enabled() -> bool { - std::env::var("DIALOG_GCD_CTRL_BODY_VENTED") - .ok() - .as_deref() - != Some("0") -} - -pub(crate) fn dialog_gcd_raw_tobitvector_variable_width_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_ipmul_terminal_reuse_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_ipmul_clear_p_residual_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_quotient_terminal_reuse_enabled() -> bool { - if let Ok(value) = std::env::var(DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE_ENV) { - return value == "1"; - } - dialog_gcd_raw_ipmul_terminal_reuse_enabled() -} - -pub(crate) fn dialog_gcd_raw_quotient_keep_terminal_u_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_apply_truncated_clean_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_pa_stop_after_quotient_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_pa_stop_after_xtail_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_pa_stop_after_c_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_C_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_raw_pa_stop_after_pair2_enabled() -> bool { - std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) const DIALOG_GCD_MAX_ITERATIONS: usize = 402; -pub(crate) const DIALOG_GCD_RAW_LOG_BITS: usize = 2 * DIALOG_GCD_MAX_ITERATIONS; -pub(crate) const DIALOG_GCD_SPECIAL_ADD_LSBS: usize = 73; -pub(crate) const DIALOG_GCD_DEFAULT_COMPARE_BITS: usize = 77; -pub(crate) const DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE: usize = 3; -pub(crate) const DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS: usize = 5; - -pub(crate) fn dialog_gcd_compressed_sidecar_log_enabled() -> bool { - std::env::var(DIALOG_GCD_COMPRESSED_SIDECAR_LOG_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_compressed_block_lifecycle_enabled() -> bool { - if dialog_gcd_k5_clean_block_enabled() { - return true; - } - std::env::var(DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_k2_enabled() -> bool { - std::env::var("DIALOG_GCD_K2").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_k5_clean_block_enabled() -> bool { - dialog_gcd_k2_enabled() - && std::env::var("DIALOG_GCD_K5_CLEAN_BLOCK") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_block_bits() -> usize { - if dialog_gcd_k5_clean_block_enabled() { - 12 - } else if dialog_gcd_k2_pair_compress_enabled() { - - DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS - } else if dialog_gcd_k2_enabled() { - DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE - } else { - DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS - } -} - -pub(crate) fn dialog_gcd_raw_block_len() -> usize { - if dialog_gcd_k2_enabled() { - 3 * dialog_gcd_sidecar_group_size() - } else { - 2 * dialog_gcd_sidecar_group_size() - } -} - -pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE: [usize; 258] = [ - 22, 21, 24, 24, 28, 25, 29, 26, 29, 30, 33, 35, 31, 32, 31, 33, 33, 34, 30, 32, 33, 35, 33, 35, - 34, 33, 35, 35, 35, 34, 33, 33, 33, 34, 34, 38, 35, 35, 33, 36, 34, 36, 37, 36, 38, 36, 38, 36, - 42, 36, 37, 37, 39, 36, 36, 39, 37, 39, 35, 38, 38, 38, 36, 44, 37, 38, 36, 39, 41, 38, 37, 41, - 40, 35, 36, 37, 41, 38, 38, 38, 37, 37, 39, 37, 37, 37, 38, 39, 38, 37, 42, 40, 38, 38, 39, 43, - 41, 39, 40, 42, 40, 39, 44, 39, 44, 40, 43, 40, 40, 41, 42, 41, 43, 42, 45, 41, 43, 42, 43, 42, - 43, 42, 44, 42, 46, 41, 44, 42, 44, 42, 43, 46, 44, 43, 48, 50, 48, 44, 44, 44, 55, 46, 46, 44, - 43, 49, 44, 45, 44, 48, 44, 46, 45, 46, 45, 44, 45, 46, 48, 46, 45, 46, 50, 48, 44, 47, 47, 46, - 45, 46, 45, 48, 47, 49, 47, 47, 46, 49, 48, 49, 46, 48, 50, 51, 47, 54, 49, 48, 47, 48, 51, 50, - 53, 54, 50, 52, 50, 51, 53, 52, 49, 52, 50, 52, 49, 52, 49, 53, 51, 55, 52, 51, 51, 51, 49, 47, - 47, 45, 45, 43, 43, 41, 41, 39, 39, 37, 37, 35, 35, 33, 33, 31, 31, 29, 29, 27, 27, 25, 25, 23, - 23, 21, 21, 19, 19, 17, 17, 15, 15, 13, 13, 11, 11, 9, 9, 7, 7, 5, -]; - -pub(crate) fn dialog_gcd_active_iterations() -> usize { - std::env::var(DIALOG_GCD_ACTIVE_ITERATIONS_ENV) - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&iters| (1..=DIALOG_GCD_MAX_ITERATIONS).contains(&iters)) - .unwrap_or(DIALOG_GCD_MAX_ITERATIONS) -} - -pub(crate) fn dialog_gcd_compare_bits() -> usize { - std::env::var(DIALOG_GCD_COMPARE_BITS_ENV) - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&bits| (1..=N).contains(&bits)) - .unwrap_or(DIALOG_GCD_DEFAULT_COMPARE_BITS) -} - -pub(crate) fn dialog_gcd_apply_clean_compare_bits() -> usize { - std::env::var(DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS_ENV) - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&bits| (1..=N).contains(&bits)) - .unwrap_or_else(dialog_gcd_compare_bits) -} - -pub(crate) fn dialog_gcd_pa9024_compare_schedule_enabled() -> bool { - std::env::var(DIALOG_GCD_PA9024_COMPARE_SCHEDULE_ENV) - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_pa9024_compare_schedule_floor() -> usize { - std::env::var(DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR_ENV) - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&bits| bits <= N) - .unwrap_or(1) - .max(1) -} - -pub(crate) fn dialog_gcd_pa9024_compare_schedule_margin() -> usize { - std::env::var("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -fn dialog_gcd_compare_step_bits(step: usize) -> Option { - let map = std::env::var("DIALOG_GCD_COMPARE_STEP_BITS").ok()?; - map.split(',').rev().find_map(|entry| { - let (raw_step, raw_bits) = entry.trim().split_once(':')?; - if raw_step.trim().parse::().ok()? != step { - return None; - } - raw_bits.trim().parse::().ok() - }) -} - -pub(crate) fn dialog_gcd_compare_bits_for_step(step: usize, active_width: usize) -> usize { - if let Some(bits) = dialog_gcd_compare_step_bits(step) { - return bits.clamp(1, active_width); - } - let global = dialog_gcd_compare_bits().min(active_width); - if dialog_gcd_pa9024_compare_schedule_enabled() { - let scheduled = (DIALOG_GCD_PA9024_COMPARE_SCHEDULE - .get(step) - .copied() - .unwrap_or(global) - + dialog_gcd_pa9024_compare_schedule_margin()) - .max(dialog_gcd_pa9024_compare_schedule_floor()) - .min(active_width); - return scheduled.min(global).max(1); - } - global.max(1) -} - -pub(crate) fn dialog_gcd_fused_branch_bits_enabled() -> bool { - std::env::var("DIALOG_GCD_FUSED_BRANCH_BITS") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_odd_u_lowbit_fastpath_enabled() -> bool { - std::env::var("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_k2_pair_compress_enabled() -> bool { - dialog_gcd_k2_enabled() - && !dialog_gcd_k5_clean_block_enabled() - && std::env::var("DIALOG_GCD_K2_PAIR_COMPRESS") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_sidecar_group_size() -> usize { - if dialog_gcd_k5_clean_block_enabled() { - 5 - } else if dialog_gcd_k2_pair_compress_enabled() { - 2 - } else { - DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE - } -} - -pub(crate) fn dialog_gcd_apply_fused_fold_enabled() -> bool { - std::env::var("DIALOG_GCD_APPLY_FUSED_FOLD").ok().as_deref() == Some("1") -} - -pub const DIALOG_FUSE_C_FORM_ENV: &str = "DIALOG_FUSE_C_FORM"; -pub(crate) fn dialog_fuse_c_form_enabled() -> bool { - std::env::var(DIALOG_FUSE_C_FORM_ENV).ok().as_deref() == Some("1") -} - -pub const DIALOG_FUSE_X_RESTORE_ENV: &str = "DIALOG_FUSE_X_RESTORE"; -pub(crate) fn dialog_fuse_x_restore_enabled() -> bool { - std::env::var(DIALOG_FUSE_X_RESTORE_ENV).ok().as_deref() == Some("1") -} + +use super::*; + +pub const DIALOG_GCD_ACTIVE_ITERATIONS_ENV: &str = "DIALOG_GCD_ACTIVE_ITERATIONS"; +pub const DIALOG_GCD_COMPARE_BITS_ENV: &str = "DIALOG_GCD_COMPARE_BITS"; +pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE_ENV: &str = "DIALOG_GCD_PA9024_COMPARE_SCHEDULE"; +pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR_ENV: &str = + "DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR"; +pub const DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS_ENV: &str = "DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS"; +pub const DIALOG_GCD_COMPRESSED_SIDECAR_LOG_ENV: &str = "DIALOG_GCD_COMPRESSED_SIDECAR_LOG"; +pub const DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE_ENV: &str = "DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE"; +pub const DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD_ENV: &str = + "DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD"; +pub const DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD_ENV: &str = + "DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD"; +pub const DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB_ENV: &str = "DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB"; +pub const DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB_ENV: &str = + "DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB"; +pub const DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB_ENV: &str = + "DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB"; +pub const DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH_ENV: &str = + "DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH"; +pub const DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES_ENV: &str = + "DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES"; +pub const DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE_ENV: &str = "DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE"; +pub const DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL_ENV: &str = "DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL"; +pub const DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE_ENV: &str = + "DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE"; +pub const DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U_ENV: &str = + "DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U"; +pub const DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN_ENV: &str = "DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN"; +pub const DIALOG_GCD_RAW_PA_ENV: &str = "DIALOG_GCD_RAW_PA"; +pub const DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT"; +pub const DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL"; +pub const DIALOG_GCD_RAW_PA_STOP_AFTER_C_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_C"; +pub const DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2_ENV: &str = "DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2"; + +pub(crate) fn dialog_gcd_raw_apply_direct_special_add_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_APPLY_DIRECT_SPECIAL_ADD_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_apply_materialized_special_add_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_APPLY_MATERIALIZED_SPECIAL_ADD_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_apply_reverse_fast_sub_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_APPLY_REVERSE_FAST_SUB_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_APPLY_REVERSE_MATERIALIZED_SPECIAL_SUB_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_chunked_f_blocks() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_BLOCKS") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&blocks| blocks >= 2) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_cuts() -> Option> { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUTS") + .ok() + .filter(|value| !value.trim().is_empty()) + .map(|value| { + value + .split(',') + .map(|item| { + item.trim() + .parse::() + .expect("DIALOG_GCD_APPLY_CHUNKED_F_CUTS") + }) + .collect() + }) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_cut() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&cut| (1..N).contains(&cut)) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_cut2() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT2") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&cut| (1..N).contains(&cut)) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_cut3() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT3") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&cut| (1..N).contains(&cut)) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_cut4() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUT4") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&cut| (1..N).contains(&cut)) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_custom4_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM4") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_chunked_f_custom5_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_CUSTOM5") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_REUSE_CIN_ZERO") + .ok() + .as_deref() + != Some("0") +} + +pub(crate) fn dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_FUSE_BOUNDARY_CLEARS") + .ok() + .as_deref() + != Some("0") +} + +pub(crate) fn dialog_gcd_apply_borrow_future_boundary_carries_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_BORROW_FUTURE_BOUNDARY_CARRIES") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_boundary_free_owned_during_replay_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_BOUNDARY_FREE_OWNED_DURING_REPLAY") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_implicit_high_zero_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_IMPLICIT_HIGH_ZERO") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_chunked_f_auto_topclean_target() -> Option { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_TARGET") + .ok() + .and_then(|value| value.parse::().ok()) + .filter(|&target| target > 0) +} + +pub(crate) fn dialog_gcd_apply_chunked_f_auto_topclean_max_bits() -> usize { + std::env::var("DIALOG_GCD_APPLY_CHUNKED_F_AUTO_TOPCLEAN_MAX_BITS") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(1) +} + +pub(crate) fn dialog_gcd_apply_final_lowq_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_FINAL_LOWQ").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_fused_hclear_measured_enabled() -> bool { + std::env::var("DIALOG_GCD_FUSED_HCLEAR_MEASURED").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_fused_dclear_measured_enabled() -> bool { + std::env::var("DIALOG_GCD_FUSED_DCLEAR_MEASURED").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_fused_ovfclear_measured_enabled() -> bool { + std::env::var("DIALOG_GCD_FUSED_OVFCLEAR_MEASURED").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_fused_halve_edclear_measured_enabled() -> bool { + std::env::var("DIALOG_GCD_FUSED_HALVE_EDCLEAR_MEASURED").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_apply_final_windowed_fast_blocks() -> Option { + std::env::var("DIALOG_GCD_APPLY_FINAL_WINDOWED_FAST_BLOCKS") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&blocks| blocks >= 2) +} + +pub(crate) fn dialog_gcd_apply_final_topclean_bits() -> usize { + std::env::var("DIALOG_GCD_APPLY_FINAL_TOPCLEAN") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +pub(crate) fn dialog_gcd_apply_boundary_split() -> Option { + std::env::var("DIALOG_GCD_APPLY_BOUNDARY_SPLIT") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&split| split > 0) +} + +pub(crate) fn dialog_gcd_apply_boundary_conditional_replay_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_BOUNDARY_CONDITIONAL_REPLAY") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_reverse_branch_conditional_replay_enabled() -> bool { + std::env::var("DIALOG_GCD_REVERSE_BRANCH_CONDITIONAL_REPLAY") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_special_clean_conditional_replay_enabled() -> bool { + std::env::var("DIALOG_GCD_SPECIAL_CLEAN_CONDITIONAL_REPLAY") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_replay_swap_host_enabled() -> bool { + + std::env::var("DIALOG_GCD_APPLY_REPLAY_SWAP_HOST") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_tobitvector_materialized_sub_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_MATERIALIZED_SUB_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_ctrl_body_vented_enabled() -> bool { + std::env::var("DIALOG_GCD_CTRL_BODY_VENTED") + .ok() + .as_deref() + != Some("0") +} + +pub(crate) fn dialog_gcd_raw_tobitvector_variable_width_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_VARIABLE_WIDTH_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_TOBITVECTOR_BORROW_FUTURE_LOG_CARRIES_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_ipmul_terminal_reuse_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_IPMUL_TERMINAL_REUSE_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_ipmul_clear_p_residual_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_IPMUL_CLEAR_P_RESIDUAL_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_quotient_terminal_reuse_enabled() -> bool { + if let Ok(value) = std::env::var(DIALOG_GCD_RAW_QUOTIENT_TERMINAL_REUSE_ENV) { + return value == "1"; + } + dialog_gcd_raw_ipmul_terminal_reuse_enabled() +} + +pub(crate) fn dialog_gcd_raw_quotient_keep_terminal_u_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_QUOTIENT_KEEP_TERMINAL_U_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_apply_truncated_clean_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_APPLY_TRUNCATED_CLEAN_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_pa_stop_after_quotient_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_QUOTIENT_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_pa_stop_after_xtail_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_XTAIL_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_pa_stop_after_c_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_C_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_raw_pa_stop_after_pair2_enabled() -> bool { + std::env::var(DIALOG_GCD_RAW_PA_STOP_AFTER_PAIR2_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) const DIALOG_GCD_MAX_ITERATIONS: usize = 402; +pub(crate) const DIALOG_GCD_RAW_LOG_BITS: usize = 2 * DIALOG_GCD_MAX_ITERATIONS; +pub(crate) const DIALOG_GCD_SPECIAL_ADD_LSBS: usize = 73; +pub(crate) const DIALOG_GCD_DEFAULT_COMPARE_BITS: usize = 77; +pub(crate) const DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE: usize = 3; +pub(crate) const DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS: usize = 5; + +pub(crate) fn dialog_gcd_compressed_sidecar_log_enabled() -> bool { + std::env::var(DIALOG_GCD_COMPRESSED_SIDECAR_LOG_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_compressed_block_lifecycle_enabled() -> bool { + if dialog_gcd_k5_clean_block_enabled() { + return true; + } + std::env::var(DIALOG_GCD_COMPRESSED_BLOCK_LIFECYCLE_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_k2_enabled() -> bool { + std::env::var("DIALOG_GCD_K2").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_k5_clean_block_enabled() -> bool { + dialog_gcd_k2_enabled() + && std::env::var("DIALOG_GCD_K5_CLEAN_BLOCK") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_block_bits() -> usize { + if dialog_gcd_k5_clean_block_enabled() { + 12 + } else if dialog_gcd_k2_pair_compress_enabled() { + + DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + } else if dialog_gcd_k2_enabled() { + DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE + } else { + DIALOG_GCD_HIGH_TAIL_ALIAS_BLOCK_BITS + } +} + +pub(crate) fn dialog_gcd_raw_block_len() -> usize { + if dialog_gcd_k2_enabled() { + 3 * dialog_gcd_sidecar_group_size() + } else { + 2 * dialog_gcd_sidecar_group_size() + } +} + +pub const DIALOG_GCD_PA9024_COMPARE_SCHEDULE: [usize; 258] = [ + 22, 21, 24, 24, 28, 25, 29, 26, 29, 30, 33, 35, 31, 32, 31, 33, 33, 34, 30, 32, 33, 35, 33, 35, + 34, 33, 35, 35, 35, 34, 33, 33, 33, 34, 34, 38, 35, 35, 33, 36, 34, 36, 37, 36, 38, 36, 38, 36, + 42, 36, 37, 37, 39, 36, 36, 39, 37, 39, 35, 38, 38, 38, 36, 44, 37, 38, 36, 39, 41, 38, 37, 41, + 40, 35, 36, 37, 41, 38, 38, 38, 37, 37, 39, 37, 37, 37, 38, 39, 38, 37, 42, 40, 38, 38, 39, 43, + 41, 39, 40, 42, 40, 39, 44, 39, 44, 40, 43, 40, 40, 41, 42, 41, 43, 42, 45, 41, 43, 42, 43, 42, + 43, 42, 44, 42, 46, 41, 44, 42, 44, 42, 43, 46, 44, 43, 48, 50, 48, 44, 44, 44, 55, 46, 46, 44, + 43, 49, 44, 45, 44, 48, 44, 46, 45, 46, 45, 44, 45, 46, 48, 46, 45, 46, 50, 48, 44, 47, 47, 46, + 45, 46, 45, 48, 47, 49, 47, 47, 46, 49, 48, 49, 46, 48, 50, 51, 47, 54, 49, 48, 47, 48, 51, 50, + 53, 54, 50, 52, 50, 51, 53, 52, 49, 52, 50, 52, 49, 52, 49, 53, 51, 55, 52, 51, 51, 51, 49, 47, + 47, 45, 45, 43, 43, 41, 41, 39, 39, 37, 37, 35, 35, 33, 33, 31, 31, 29, 29, 27, 27, 25, 25, 23, + 23, 21, 21, 19, 19, 17, 17, 15, 15, 13, 13, 11, 11, 9, 9, 7, 7, 5, +]; + +pub(crate) fn dialog_gcd_active_iterations() -> usize { + std::env::var(DIALOG_GCD_ACTIVE_ITERATIONS_ENV) + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&iters| (1..=DIALOG_GCD_MAX_ITERATIONS).contains(&iters)) + .unwrap_or(DIALOG_GCD_MAX_ITERATIONS) +} + +pub(crate) fn dialog_gcd_compare_bits() -> usize { + std::env::var(DIALOG_GCD_COMPARE_BITS_ENV) + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&bits| (1..=N).contains(&bits)) + .unwrap_or(DIALOG_GCD_DEFAULT_COMPARE_BITS) +} + +pub(crate) fn dialog_gcd_apply_clean_compare_bits() -> usize { + std::env::var(DIALOG_GCD_APPLY_CLEAN_COMPARE_BITS_ENV) + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&bits| (1..=N).contains(&bits)) + .unwrap_or_else(dialog_gcd_compare_bits) +} + +pub(crate) fn dialog_gcd_pa9024_compare_schedule_enabled() -> bool { + std::env::var(DIALOG_GCD_PA9024_COMPARE_SCHEDULE_ENV) + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_pa9024_compare_schedule_floor() -> usize { + std::env::var(DIALOG_GCD_PA9024_COMPARE_SCHEDULE_FLOOR_ENV) + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&bits| bits <= N) + .unwrap_or(1) + .max(1) +} + +pub(crate) fn dialog_gcd_pa9024_compare_schedule_margin() -> usize { + std::env::var("DIALOG_GCD_PA9024_COMPARE_SCHEDULE_MARGIN") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) +} + +fn dialog_gcd_compare_step_bits(step: usize) -> Option { + let map = std::env::var("DIALOG_GCD_COMPARE_STEP_BITS").ok()?; + map.split(',').rev().find_map(|entry| { + let (raw_step, raw_bits) = entry.trim().split_once(':')?; + if raw_step.trim().parse::().ok()? != step { + return None; + } + raw_bits.trim().parse::().ok() + }) +} + +pub(crate) fn dialog_gcd_compare_bits_for_step(step: usize, active_width: usize) -> usize { + if let Some(bits) = dialog_gcd_compare_step_bits(step) { + return bits.clamp(1, active_width); + } + let global = dialog_gcd_compare_bits().min(active_width); + if dialog_gcd_pa9024_compare_schedule_enabled() { + let scheduled = (DIALOG_GCD_PA9024_COMPARE_SCHEDULE + .get(step) + .copied() + .unwrap_or(global) + + dialog_gcd_pa9024_compare_schedule_margin()) + .max(dialog_gcd_pa9024_compare_schedule_floor()) + .min(active_width); + return scheduled.min(global).max(1); + } + global.max(1) +} + +pub(crate) fn dialog_gcd_fused_branch_bits_enabled() -> bool { + std::env::var("DIALOG_GCD_FUSED_BRANCH_BITS") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_odd_u_lowbit_fastpath_enabled() -> bool { + std::env::var("DIALOG_GCD_ODD_U_LOWBIT_FASTPATH") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_k2_pair_compress_enabled() -> bool { + dialog_gcd_k2_enabled() + && !dialog_gcd_k5_clean_block_enabled() + && std::env::var("DIALOG_GCD_K2_PAIR_COMPRESS") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_sidecar_group_size() -> usize { + if dialog_gcd_k5_clean_block_enabled() { + 5 + } else if dialog_gcd_k2_pair_compress_enabled() { + 2 + } else { + DIALOG_GCD_HIGH_TAIL_ALIAS_GROUP_SIZE + } +} + +pub(crate) fn dialog_gcd_apply_fused_fold_enabled() -> bool { + std::env::var("DIALOG_GCD_APPLY_FUSED_FOLD").ok().as_deref() == Some("1") +} + +pub const DIALOG_FUSE_C_FORM_ENV: &str = "DIALOG_FUSE_C_FORM"; +pub(crate) fn dialog_fuse_c_form_enabled() -> bool { + std::env::var(DIALOG_FUSE_C_FORM_ENV).ok().as_deref() == Some("1") +} + +pub const DIALOG_FUSE_X_RESTORE_ENV: &str = "DIALOG_FUSE_X_RESTORE"; +pub(crate) fn dialog_fuse_x_restore_enabled() -> bool { + std::env::var(DIALOG_FUSE_X_RESTORE_ENV).ok().as_deref() == Some("1") +} diff --git a/src/point_add/rounds/dialog/mod.rs b/src/point_add/rounds/dialog/mod.rs index fa0be1a6..49b286fe 100644 --- a/src/point_add/rounds/dialog/mod.rs +++ b/src/point_add/rounds/dialog/mod.rs @@ -1,2834 +1,2834 @@ - -use super::*; - -mod compressed; -mod config; -pub(crate) use compressed::*; -pub(crate) use config::*; - -pub(crate) fn round84_emit_fused_square_xtail( - b: &mut B, - tx: &[QubitId], - lam: &[QubitId], - ox: &[BitId], - p: U256, -) { - b.set_phase("round84_fused_square_xtail_dx_sub_lam_square_lowq"); - if std::env::var("ROUND84_XTAIL_KARATSUBA").ok().as_deref() == Some("1") { - - squaring_sub_from_acc_karatsuba(b, tx, lam, p); - } else if std::env::var("ROUND84_XTAIL_WALK_SQUARE").ok().as_deref() == Some("1") { - squaring_sub_from_acc_walk_controls_lowq(b, tx, lam, p); - } else if std::env::var("ROUND84_XTAIL_SCHOOLBOOK").ok().as_deref() == Some("1") { - squaring_sub_from_acc_schoolbook(b, tx, lam, p); - } else { - squaring_sub_from_acc_schoolbook_lowq_shift22(b, tx, lam, p); - } - if dialog_fuse_c_form_enabled() { - return; - } - b.set_phase("round84_fused_square_xtail_add_double_ox"); - mod_add_double_qb(b, tx, ox, p); - b.set_phase("round84_fused_square_xtail_negate_to_x3"); - mod_neg_inplace_fast(b, tx, p); -} - -pub(crate) fn dialog_gcd_cmp_gt_truncated_into_width( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - flag: QubitId, - compare_bits: usize, -) { - assert_eq!(u.len(), v.len()); - assert!(!u.is_empty()); - let compare_bits = compare_bits.min(u.len()).max(1); - let start = u.len() - compare_bits; - cmp_lt_into_fast(b, &v[start..], &u[start..], flag); -} - -pub(crate) fn dialog_gcd_ccx_cmp_gt_truncated_into_width( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - target: QubitId, - compare_bits: usize, -) { - assert_eq!(u.len(), v.len()); - assert!(!u.is_empty()); - let compare_bits = compare_bits.min(u.len()).max(1); - let start = u.len() - compare_bits; - ccx_cmp_lt_into_fast(b, &v[start..], &u[start..], ctrl, target); -} - -pub(crate) fn dialog_gcd_branch_bits_host_comparator_enabled() -> bool { - std::env::var("DIALOG_GCD_BRANCH_BITS_HOST_COMPARATOR") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - target: QubitId, - compare_bits: usize, - borrowed: Option<&[QubitId]>, -) { - assert_eq!(u.len(), v.len()); - assert!(!u.is_empty()); - let compare_bits = compare_bits.min(u.len()).max(1); - let start = u.len() - compare_bits; - let cmp_u = &v[start..]; - let cmp_v = &u[start..]; - let n = cmp_u.len(); - - let need = n + 1; - let avail = borrowed.map(|s| s.len()).unwrap_or(0); - if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { - let slice = borrowed.expect("avail>0"); - let owned = b.alloc_qubits(need - avail); - let mut clean: Vec = Vec::with_capacity(need); - clean.extend_from_slice(slice); - clean.extend_from_slice(&owned); - let (c_in, carries) = clean.split_first().expect("need >= 1"); - ccx_cmp_lt_into_fast_borrowed_carries(b, cmp_u, cmp_v, ctrl, target, *c_in, &carries[..n]); - b.free_vec(&owned); - } else if let Some(slice) = borrowed.filter(|s| s.len() >= need) { - let (c_in, carries) = slice.split_first().expect("slice len >= n+1 > 0"); - ccx_cmp_lt_into_fast_borrowed_carries(b, cmp_u, cmp_v, ctrl, target, *c_in, &carries[..n]); - } else { - ccx_cmp_lt_into_fast(b, cmp_u, cmp_v, ctrl, target); - } -} - -pub(crate) fn dialog_gcd_cmp_gt_truncated_phase_conditioned_hosted( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - phase: BitId, - compare_bits: usize, - borrowed: Option<&[QubitId]>, -) { - assert_eq!(u.len(), v.len()); - assert!(!u.is_empty()); - let compare_bits = compare_bits.min(u.len()).max(1); - let start = u.len() - compare_bits; - let cmp_u = &v[start..]; - let cmp_v = &u[start..]; - let n = cmp_u.len(); - let need = n + 1; - let avail = borrowed.map(|s| s.len()).unwrap_or(0); - if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { - let slice = borrowed.expect("avail>0"); - let owned = b.alloc_qubits(need - avail); - let mut clean: Vec = Vec::with_capacity(need); - clean.extend_from_slice(slice); - clean.extend_from_slice(&owned); - let (c_in, carries) = clean.split_first().expect("need >= 1"); - cmp_lt_phase_conditioned_borrowed_carries( - b, - cmp_u, - cmp_v, - *c_in, - &carries[..n], - ctrl, - phase, - ); - b.free_vec(&owned); - } else if let Some(slice) = borrowed.filter(|s| s.len() >= need) { - let (c_in, carries) = slice.split_first().expect("slice len >= n+1 > 0"); - cmp_lt_phase_conditioned_borrowed_carries( - b, - cmp_u, - cmp_v, - *c_in, - &carries[..n], - ctrl, - phase, - ); - } else { - let c_in = b.alloc_qubit(); - cmp_lt_phase_conditioned_with_cin(b, cmp_u, cmp_v, c_in, ctrl, phase); - b.free(c_in); - } -} - -fn dialog_gcd_cmp_lt_phase_conditioned_hosted( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - phase: BitId, - borrowed: Option<&[QubitId]>, -) { - let n = u.len(); - assert_eq!(v.len(), n); - assert!(n > 0); - let need = n + 1; - let avail = borrowed.map_or(0, <[QubitId]>::len); - if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { - let borrowed = borrowed.expect("avail > 0"); - let owned = b.alloc_qubits(need - avail); - let mut clean = Vec::with_capacity(need); - clean.extend_from_slice(borrowed); - clean.extend_from_slice(&owned); - let (c_in, carries) = clean.split_first().expect("need >= 1"); - cmp_lt_phase_conditioned_borrowed_carries( - b, - u, - v, - *c_in, - &carries[..n], - ctrl, - phase, - ); - b.free_vec(&owned); - } else if let Some(borrowed) = borrowed.filter(|slice| slice.len() >= need) { - let (c_in, carries) = borrowed.split_first().expect("borrowed len >= n + 1"); - cmp_lt_phase_conditioned_borrowed_carries( - b, - u, - v, - *c_in, - &carries[..n], - ctrl, - phase, - ); - } else { - let c_in = b.alloc_qubit(); - cmp_lt_phase_conditioned_with_cin(b, u, v, c_in, ctrl, phase); - b.free(c_in); - } -} - -pub(crate) fn dialog_gcd_partial_host_comparator_enabled() -> bool { - std::env::var("DIALOG_GCD_PARTIAL_HOST_COMPARATOR") - .ok() - .as_deref() - != Some("0") -} - -pub(crate) fn dialog_gcd_shift_right_assuming_even(b: &mut B, v: &[QubitId]) { - assert!(!v.is_empty()); - for i in 0..v.len() - 1 { - b.swap(v[i], v[i + 1]); - } -} - -pub(crate) fn dialog_gcd_unshift_right_assuming_even(b: &mut B, v: &[QubitId]) { - assert!(!v.is_empty()); - for i in (0..v.len() - 1).rev() { - b.swap(v[i], v[i + 1]); - } -} - -pub(crate) fn dialog_gcd_width_margin() -> f64 { - - std::env::var("DIALOG_GCD_WIDTH_MARGIN") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|m| m.is_finite() && *m >= 0.0 && *m <= N as f64) - .unwrap_or(37.0) -} - -pub(crate) fn dialog_gcd_width_slope() -> f64 { - - std::env::var("DIALOG_GCD_WIDTH_SLOPE_X1000") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|s| s.is_finite() && *s > 0.0 && *s <= 4000.0) - .map(|s| s / 1000.0) - .unwrap_or(0.5 * 1.415) -} - -pub(crate) fn dialog_gcd_tobitvector_active_width(step: usize) -> usize { - if !dialog_gcd_raw_tobitvector_variable_width_enabled() { - return N; - } - let ideal = N as f64 - (step as f64) * dialog_gcd_width_slope() + dialog_gcd_width_margin(); - let rounded = ((ideal.max(1.0) / 2.0).ceil() as usize) * 2; - rounded - .saturating_add(dialog_gcd_width_step_bump(step)) - .clamp(1, N) -} - -fn dialog_gcd_step_map_value(env: &str, step: usize) -> usize { - let Ok(map) = std::env::var(env) else { - return 0; - }; - map.split(',') - .filter_map(|entry| { - let (s, value) = entry.trim().split_once(':')?; - Some(( - s.trim().parse::().ok()?, - value.trim().parse::().ok()?, - )) - }) - .filter_map(|(s, value)| (s == step).then_some(value)) - .sum() -} - -fn dialog_gcd_step_map_override(env: &str, step: usize) -> Option { - let map = std::env::var(env).ok()?; - map.split(',').rev().find_map(|entry| { - let (raw_step, raw_value) = entry.trim().split_once(':')?; - if raw_step.trim().parse::().ok()? != step { - return None; - } - raw_value.trim().parse::().ok() - }) -} - -pub(crate) fn dialog_gcd_width_step_bump(step: usize) -> usize { - dialog_gcd_step_map_value("DIALOG_GCD_WIDTH_STEP_BUMPS", step) -} - -pub(crate) fn dialog_gcd_body_step_giveback(step: usize) -> usize { - dialog_gcd_step_map_value("DIALOG_GCD_BODY_STEP_GIVEBACKS", step) -} - -pub(crate) fn dialog_gcd_fused_fold_carry_trunc_window( - step: Option, -) -> Option { - step.and_then(|step| { - dialog_gcd_step_map_override("DIALOG_GCD_FOLD_CARRY_TRUNC_STEP_WINDOWS", step) - }) - .filter(|&window| window > 0) - .or_else(fold_only_carry_trunc_window) - .or_else(double_carry_trunc_window) -} - -pub(crate) fn dialog_gcd_body_carry_band_trim(step: usize) -> Option { - let trims = std::env::var("DIALOG_GCD_BODY_CARRY_BAND_TRIMS").ok()?; - if trims.trim().is_empty() { - return None; - } - let trims: Vec = trims - .split(',') - .filter_map(|s| s.trim().parse::().ok()) - .collect(); - if trims.is_empty() { - return None; - } - let iters = dialog_gcd_active_iterations().max(1); - let band_size = ((iters + trims.len() - 1) / trims.len()).max(1); - let band = (step / band_size).min(trims.len() - 1); - Some(trims[band]) -} - -pub(crate) fn dialog_gcd_tobitvector_cswap_width(active_width: usize, step: usize) -> usize { - if std::env::var("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM") - .ok() - .as_deref() - == Some("1") - { - dialog_gcd_body_carry_trunc_width(active_width, step).min(active_width) - } else { - active_width - } -} - -pub(crate) fn dialog_gcd_tobitvector_shift_width(active_width: usize, step: usize) -> usize { - if std::env::var("DIALOG_GCD_TOBITVECTOR_SHIFT_BODY_TRIM") - .ok() - .as_deref() - == Some("1") - { - dialog_gcd_body_carry_trunc_width(active_width, step).min(active_width) - } else { - active_width - } -} - -pub(crate) fn dialog_gcd_body_carry_trunc_width(active_width: usize, step: usize) -> usize { - let mut w = dialog_gcd_body_carry_band_trim(step).unwrap_or_else(|| { - std::env::var("DIALOG_GCD_BODY_CARRY_TRUNC_W") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) - }); - if dialog_gcd_trio_width_notch_enabled() && step == dialog_gcd_trio_width_notch_step() { - w = w.saturating_add(dialog_gcd_trio_width_notch_extra()); - } - - if dialog_gcd_binder_notch_steps().contains(&step) { - w = w.saturating_add(dialog_gcd_binder_notch_extra()); - } - w = w.saturating_add(dialog_gcd_binder_notch_map_extra(step)); - w = w.saturating_sub(dialog_gcd_body_step_giveback(step)); - active_width.saturating_sub(w).max(2) -} - -pub(crate) fn dialog_gcd_vented_body_band_trim_enabled() -> bool { - std::env::var("DIALOG_GCD_VENTED_BODY_BAND_TRIM").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_vented_body_width(n: usize, step: usize) -> usize { - if !dialog_gcd_vented_body_band_trim_enabled() { - return n; - } - if let Some(u) = std::env::var("DIALOG_GCD_VENTED_BODY_UNIFORM_TRIM") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&u| u > 0) - { - return n.saturating_sub(u).max(2); - } - let mut w = dialog_gcd_body_carry_trunc_width(n, step).min(n).max(2); - - if let Some(cap) = std::env::var("DIALOG_GCD_VENTED_BODY_TRIM_CAP") - .ok() - .and_then(|s| s.parse::().ok()) - { - w = w.max(n.saturating_sub(cap)).min(n); - } - w -} - -pub(crate) fn dialog_gcd_vented_body_odd_lowbit_enabled() -> bool { - std::env::var("DIALOG_GCD_VENTED_BODY_ODD_LOWBIT").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_binder_notch_steps() -> Vec { - std::env::var("DIALOG_GCD_BINDER_NOTCH_STEPS") - .ok() - .map(|s| { - s.split(',') - .filter_map(|t| t.trim().parse::().ok()) - .collect() - }) - .unwrap_or_default() -} - -pub(crate) fn dialog_gcd_binder_notch_extra() -> usize { - std::env::var("DIALOG_GCD_BINDER_NOTCH_EXTRA") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(2) -} - -pub(crate) fn dialog_gcd_binder_notch_map_extra(step: usize) -> usize { - let Ok(map) = std::env::var("DIALOG_GCD_BINDER_NOTCH_MAP") else { - return 0; - }; - map.split(',') - .filter_map(|entry| { - let (s, extra) = entry.trim().split_once(':')?; - Some(( - s.trim().parse::().ok()?, - extra.trim().parse::().ok()?, - )) - }) - .filter_map(|(s, extra)| (s == step).then_some(extra)) - .sum() -} - -pub(crate) fn dialog_gcd_trio_width_notch_enabled() -> bool { - - std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH").ok().as_deref() != Some("0") -} - -pub(crate) fn dialog_gcd_trio_width_notch_step() -> usize { - std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH_STEP") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(11) -} - -pub(crate) fn dialog_gcd_trio_width_notch_extra() -> usize { - std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH_EXTRA") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(2) -} - -pub(crate) fn dialog_gcd_host_gated_enabled() -> bool { - - std::env::var("DIALOG_GCD_HOST_GATED").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_body_host_cin_enabled() -> bool { - - std::env::var("DIALOG_GCD_BODY_HOST_CIN").ok().as_deref() == Some("1") -} - -pub(crate) fn dialog_gcd_selected_body_nocin_enabled() -> bool { - - matches!( - std::env::var("DIALOG_GCD_SELECTED_BODY_NOCIN").ok().as_deref(), - Some("1") | Some("2") - ) -} - -pub(crate) fn dialog_gcd_selected_body_nocin_keep_pool() -> bool { - std::env::var("DIALOG_GCD_SELECTED_BODY_NOCIN").ok().as_deref() == Some("2") -} - -pub(crate) fn dialog_gcd_selected_body_stream_suffix_bits(step: usize, body_len: usize) -> usize { - let Ok(map) = std::env::var("DIALOG_GCD_SELECTED_BODY_STREAM_SUFFIX_MAP") else { - return 0; - }; - map.split(',') - .find_map(|entry| { - let (entry_step, entry_bits) = entry.trim().split_once(':')?; - let entry_step = entry_step.parse::().ok()?; - let entry_bits = entry_bits.parse::().ok()?; - (entry_step == step).then_some(entry_bits) - }) - .unwrap_or(0) - .min(body_len.saturating_sub(1)) -} - -pub(crate) fn dialog_gcd_selected_body_stream_top_enabled(step: usize, body_len: usize) -> bool { - dialog_gcd_selected_body_stream_suffix_bits(step, body_len) == 1 -} - -pub(crate) fn dialog_gcd_selected_body_stream_topclean_bits( - step: usize, - prefix_len: usize, -) -> usize { - if prefix_len <= 1 { - return 0; - } - let global = std::env::var("DIALOG_GCD_SELECTED_BODY_STREAM_TOPCLEAN") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0); - let mapped = dialog_gcd_step_map_value("DIALOG_GCD_SELECTED_BODY_STREAM_TOPCLEAN_MAP", step); - global.max(mapped).min(prefix_len - 1) -} - -pub(crate) fn dialog_gcd_late_borrow_uv_high_enabled() -> bool { - std::env::var("DIALOG_GCD_LATE_BORROW_UV_HIGH") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_pick_borrow_slice<'a>( - future: Option<&'a [QubitId]>, - u: &'a [QubitId], - active_width: usize, -) -> Option<&'a [QubitId]> { - if dialog_gcd_late_borrow_uv_high_enabled() && active_width >= 1 { - let want = 2 * active_width - 1; - let short = future.map_or(true, |s| s.len() < want); - if short && u.len() >= active_width + want { - return Some(&u[active_width..active_width + want]); - } - } - future -} - -pub(crate) fn dialog_gcd_controlled_sub_selected( - b: &mut B, - subtrahend: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - borrowed_carries: Option<&[QubitId]>, - step: usize, -) { - assert_eq!(subtrahend.len(), acc.len()); - assert!(!subtrahend.is_empty()); - if dialog_gcd_raw_tobitvector_materialized_sub_enabled() { - let n = subtrahend.len(); - let body_w = dialog_gcd_body_carry_trunc_width(n, step); - let odd_lowbit_fast = dialog_gcd_odd_u_lowbit_fastpath_enabled(); - let body_start = if odd_lowbit_fast { 1 } else { 0 }; - let body_len = body_w.saturating_sub(body_start); - let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); - let nocin_need = if stream_suffix >= 2 - && !dialog_gcd_selected_body_nocin_keep_pool() - { - 2 * (body_len - stream_suffix) + 1 - } else if dialog_gcd_selected_body_stream_top_enabled(step, body_len) - && !dialog_gcd_selected_body_nocin_keep_pool() - && body_len >= 2 - { - 2 * (body_len - 1) - } else if dialog_gcd_selected_body_nocin_keep_pool() { - - (n + body_len).max(2 * body_len - 1) - } else { - 2 * body_len - 1 - }; - let nocin = dialog_gcd_selected_body_nocin_enabled() - && body_start >= 1 - && body_len >= 1 - && borrowed_carries.map_or(false, |c| c.len() >= nocin_need); - if nocin { - if stream_suffix >= 2 { - let prefix_len = body_len - stream_suffix; - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, rest) = c.split_at(prefix_len); - let (gated, rest) = rest.split_at(prefix_len); - let scratch = rest[0]; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); - for j in 0..prefix_len { - b.ccx(ctrl, subtrahend[body_start + j], gated[j]); - } - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); - cuccaro_sub_fast_prefix_ctrl_suffix_no_cin( - b, - gated, - &subtrahend[body_start + prefix_len..body_w], - &acc[body_start..body_w], - ctrl, - carries, - scratch, - ); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); - for j in 0..prefix_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, subtrahend[body_start + j], m); - } - return; - } - if dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 { - let lower_len = body_len - 1; - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, gated) = c.split_at(lower_len); - let gated = &gated[..lower_len]; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); - for j in 0..lower_len { - b.ccx(ctrl, subtrahend[body_start + j], gated[j]); - } - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); - b.ccx(ctrl, subtrahend[body_w - 1], acc[body_w - 1]); - cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin( - b, - gated, - &acc[body_start..body_w], - carries, - ); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); - for j in 0..lower_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, subtrahend[body_start + j], m); - } - return; - } - - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, gated): (&[QubitId], &[QubitId]) = - if dialog_gcd_selected_body_nocin_keep_pool() { - - let carry_need = body_len - 1; - (&c[..carry_need], &c[n..n + body_len]) - } else { - let carry_need = body_len - 1; - (&c[..carry_need], &c[carry_need..carry_need + body_len]) - }; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); - for j in 0..body_len { - b.ccx(ctrl, subtrahend[body_start + j], gated[j]); - } - - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); - cuccaro_sub_fast_borrowed_carries_no_cin( - b, - gated, - &acc[body_start..body_w], - carries, - ); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); - for j in 0..body_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, subtrahend[body_start + j], m); - } - return; - } - - let gated_host: Option<&[QubitId]> = if dialog_gcd_host_gated_enabled() { - borrowed_carries.and_then(|c| { - if c.len() >= 2 * n - 1 { - Some(&c[n - 1..2 * n - 1]) - } else { - None - } - }) - } else { - None - }; - let mut gated_owned: Vec = Vec::new(); - let gated: &[QubitId] = match gated_host { - Some(h) => h, - None => { - gated_owned = b.alloc_qubits(n); - gated_owned.as_slice() - } - }; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); - for i in body_start..body_w { - b.ccx(ctrl, subtrahend[i], gated[i]); - } - if odd_lowbit_fast { - - b.cx(ctrl, acc[0]); - } - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); - if body_start < body_w { - if let Some(carries) = - borrowed_carries.filter(|carries| carries.len() >= body_len.saturating_sub(1)) - { - if dialog_gcd_body_host_cin_enabled() && body_start >= 1 { - - cuccaro_sub_fast_borrowed_carries( - b, - &gated[body_start..body_w], - &acc[body_start..body_w], - gated[0], - &carries[..body_len.saturating_sub(1)], - ); - } else { - sub_nbit_qq_fast_borrowed_carries( - b, - &gated[body_start..body_w], - &acc[body_start..body_w], - &carries[..body_len.saturating_sub(1)], - ); - } - } else { - sub_nbit_qq_fast(b, &gated[body_start..body_w], &acc[body_start..body_w]); - } - } - b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); - for i in body_start..body_w { - let m = b.alloc_bit(); - b.hmr(gated[i], m); - b.cz_if(ctrl, subtrahend[i], m); - } - if gated_host.is_none() { - b.free_vec(&gated_owned); - } - } else { - let n = subtrahend.len(); - if dialog_gcd_ctrl_body_vented_enabled() { - if let Some(vents) = - borrowed_carries.filter(|c| n >= 2 && c.len() >= n - 1) - { - let bw = dialog_gcd_vented_body_width(n, step); - if dialog_gcd_vented_body_odd_lowbit_enabled() - && dialog_gcd_odd_u_lowbit_fastpath_enabled() - && bw >= 3 - { - - b.cx(ctrl, acc[0]); - cuccaro_sub_ctrl_vented(b, &subtrahend[1..bw], &acc[1..bw], ctrl, &vents[..bw - 2]); - } else { - cuccaro_sub_ctrl_vented(b, &subtrahend[..bw], &acc[..bw], ctrl, &vents[..bw - 1]); - } - return; - } - } - cucc_sub_ctrl_lowq(b, subtrahend, acc, ctrl); - } -} - -pub(crate) fn dialog_gcd_controlled_add_selected( - b: &mut B, - addend: &[QubitId], - acc: &[QubitId], - ctrl: QubitId, - borrowed_carries: Option<&[QubitId]>, - step: usize, -) { - assert_eq!(addend.len(), acc.len()); - assert!(!addend.is_empty()); - if dialog_gcd_raw_tobitvector_materialized_sub_enabled() { - let n = addend.len(); - let body_w = dialog_gcd_body_carry_trunc_width(n, step); - let odd_lowbit_fast = dialog_gcd_odd_u_lowbit_fastpath_enabled(); - let body_start = if odd_lowbit_fast { 1 } else { 0 }; - let body_len = body_w.saturating_sub(body_start); - let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); - let nocin_need = if stream_suffix >= 2 - && !dialog_gcd_selected_body_nocin_keep_pool() - { - 2 * (body_len - stream_suffix) + 1 - } else if dialog_gcd_selected_body_stream_top_enabled(step, body_len) - && !dialog_gcd_selected_body_nocin_keep_pool() - && body_len >= 2 - { - 2 * (body_len - 1) - } else if dialog_gcd_selected_body_nocin_keep_pool() { - - (n + body_len).max(2 * body_len - 1) - } else { - 2 * body_len - 1 - }; - let nocin = dialog_gcd_selected_body_nocin_enabled() - && body_start >= 1 - && body_len >= 1 - && borrowed_carries.map_or(false, |c| c.len() >= nocin_need); - if nocin { - if stream_suffix >= 2 { - let prefix_len = body_len - stream_suffix; - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, rest) = c.split_at(prefix_len); - let (gated, rest) = rest.split_at(prefix_len); - let scratch = rest[0]; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); - for j in 0..prefix_len { - b.ccx(ctrl, addend[body_start + j], gated[j]); - } - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); - cuccaro_add_fast_prefix_ctrl_suffix_no_cin( - b, - gated, - &addend[body_start + prefix_len..body_w], - &acc[body_start..body_w], - ctrl, - carries, - scratch, - ); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); - for j in 0..prefix_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, addend[body_start + j], m); - } - return; - } - if dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 { - let lower_len = body_len - 1; - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, gated) = c.split_at(lower_len); - let gated = &gated[..lower_len]; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); - for j in 0..lower_len { - b.ccx(ctrl, addend[body_start + j], gated[j]); - } - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); - cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin( - b, - gated, - &acc[body_start..body_w], - carries, - ); - b.ccx(ctrl, addend[body_w - 1], acc[body_w - 1]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); - for j in 0..lower_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, addend[body_start + j], m); - } - return; - } - - let c = borrowed_carries.expect("nocin requires borrowed carries"); - let (carries, gated): (&[QubitId], &[QubitId]) = - if dialog_gcd_selected_body_nocin_keep_pool() { - let carry_need = body_len - 1; - (&c[..carry_need], &c[n..n + body_len]) - } else { - let carry_need = body_len - 1; - (&c[..carry_need], &c[carry_need..carry_need + body_len]) - }; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); - for j in 0..body_len { - b.ccx(ctrl, addend[body_start + j], gated[j]); - } - - b.cx(ctrl, acc[0]); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); - cuccaro_add_fast_borrowed_carries_no_cin( - b, - gated, - &acc[body_start..body_w], - carries, - ); - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); - for j in 0..body_len { - let m = b.alloc_bit(); - b.hmr(gated[j], m); - b.cz_if(ctrl, addend[body_start + j], m); - } - return; - } - let gated_host: Option<&[QubitId]> = if dialog_gcd_host_gated_enabled() { - borrowed_carries.and_then(|c| { - if c.len() >= 2 * n - 1 { - Some(&c[n - 1..2 * n - 1]) - } else { - None - } - }) - } else { - None - }; - let mut gated_owned: Vec = Vec::new(); - let gated: &[QubitId] = match gated_host { - Some(h) => h, - None => { - gated_owned = b.alloc_qubits(n); - gated_owned.as_slice() - } - }; - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); - for i in body_start..body_w { - b.ccx(ctrl, addend[i], gated[i]); - } - if odd_lowbit_fast { - - b.cx(ctrl, acc[0]); - } - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); - if body_start < body_w { - if let Some(carries) = - borrowed_carries.filter(|carries| carries.len() >= body_len.saturating_sub(1)) - { - if dialog_gcd_body_host_cin_enabled() && body_start >= 1 { - - cuccaro_add_fast_borrowed_carries( - b, - &gated[body_start..body_w], - &acc[body_start..body_w], - gated[0], - &carries[..body_len.saturating_sub(1)], - ); - } else { - add_nbit_qq_fast_borrowed_carries( - b, - &gated[body_start..body_w], - &acc[body_start..body_w], - &carries[..body_len.saturating_sub(1)], - ); - } - } else { - add_nbit_qq_fast(b, &gated[body_start..body_w], &acc[body_start..body_w]); - } - } - b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); - for i in body_start..body_w { - let m = b.alloc_bit(); - b.hmr(gated[i], m); - b.cz_if(ctrl, addend[i], m); - } - if gated_host.is_none() { - b.free_vec(&gated_owned); - } - } else { - let n = addend.len(); - if dialog_gcd_ctrl_body_vented_enabled() { - if let Some(vents) = - borrowed_carries.filter(|c| n >= 2 && c.len() >= n - 1) - { - let bw = dialog_gcd_vented_body_width(n, step); - if dialog_gcd_vented_body_odd_lowbit_enabled() - && dialog_gcd_odd_u_lowbit_fastpath_enabled() - && bw >= 3 - { - - b.cx(ctrl, acc[0]); - cuccaro_add_ctrl_vented(b, &addend[1..bw], &acc[1..bw], ctrl, &vents[..bw - 2]); - } else { - cuccaro_add_ctrl_vented(b, &addend[..bw], &acc[..bw], ctrl, &vents[..bw - 1]); - } - return; - } - } - cucc_add_ctrl_lowq(b, addend, acc, ctrl); - } -} - -pub(crate) fn dialog_gcd_future_log_carry_slice( - dialog_log: &[QubitId], - step: usize, - active_width: usize, -) -> Option<&[QubitId]> { - if !dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() { - return None; - } - let carry_need = active_width.saturating_sub(1); - let want = if dialog_gcd_host_gated_enabled() { - 2 * active_width - 1 - } else { - carry_need - }; - let start = 2 * (step + 1); - dialog_log - .get(start..) - .filter(|future| future.len() >= carry_need) - .map(|future| &future[..future.len().min(want)]) -} - -pub(crate) fn emit_dialog_gcd_raw_tobitvector_steps( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - dialog_log: &[QubitId], -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); - - for step in 0..dialog_gcd_active_iterations() { - let b0 = dialog_log[2 * step]; - let b0_and_b1 = dialog_log[2 * step + 1]; - let cmp = b.alloc_qubit(); - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - b.set_phase("dialog_gcd_raw_tobitvector_branch_bits"); - b.cx(v[0], b0); - if dialog_gcd_fused_branch_bits_enabled() { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } else { - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - } - b.free(cmp); - - b.set_phase("dialog_gcd_raw_tobitvector_cswap"); - for (i, (&ui, &vi)) in u_active.iter().zip(v_active.iter()).enumerate() { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_raw_tobitvector_subtract"); - let borrowed_carries = dialog_gcd_future_log_carry_slice(dialog_log, step, active_width); - dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); - - b.set_phase("dialog_gcd_raw_tobitvector_shift"); - dialog_gcd_shift_right_assuming_even(b, v_active); - } -} - -pub(crate) fn emit_dialog_gcd_raw_tobitvector_steps_reverse( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - dialog_log: &[QubitId], -) { - assert_eq!(u.len(), N); - assert_eq!(v.len(), N); - assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); - - for step in (0..dialog_gcd_active_iterations()).rev() { - let b0 = dialog_log[2 * step]; - let b0_and_b1 = dialog_log[2 * step + 1]; - let cmp = b.alloc_qubit(); - let active_width = dialog_gcd_tobitvector_active_width(step); - let u_active = &u[..active_width]; - let v_active = &v[..active_width]; - let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); - - b.set_phase("dialog_gcd_raw_tobitvector_reverse_unshift"); - dialog_gcd_unshift_right_assuming_even(b, v_active); - - b.set_phase("dialog_gcd_raw_tobitvector_reverse_add"); - let borrowed_carries = dialog_gcd_future_log_carry_slice(dialog_log, step, active_width); - dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); - - b.set_phase("dialog_gcd_raw_tobitvector_reverse_cswap"); - for (i, (&ui, &vi)) in u_active.iter().zip(v_active.iter()).enumerate() { - if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { - continue; - } - cswap(b, b0_and_b1, ui, vi); - } - - b.set_phase("dialog_gcd_raw_tobitvector_reverse_branch_bits"); - if dialog_gcd_fused_branch_bits_enabled() { - dialog_gcd_ccx_cmp_gt_truncated_into_width( - b, - u_active, - v_active, - b0, - b0_and_b1, - compare_bits, - ); - } else { - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - b.ccx(b0, cmp, b0_and_b1); - dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); - } - b.free(cmp); - b.cx(v[0], b0); - } -} - -pub(crate) fn dialog_gcd_cmod_add_pseudomersenne_lowq( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let a_ovf = b.alloc_qubit(); - let mut a_ext = a.to_vec(); - a_ext.push(a_ovf); - let c_in = b.alloc_qubit(); - let scratch = b.alloc_qubit(); - - b.set_phase("dialog_gcd_direct_special_cadd_raw_sum"); - cuccaro_add_ctrl_lowq(b, &a_ext, &acc_ext, ctrl, c_in, scratch); - b.free(scratch); - b.free(c_in); - b.free(a_ovf); - - b.set_phase("dialog_gcd_direct_special_overflow_fold"); - cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - - b.set_phase("dialog_gcd_direct_special_overflow_clean"); - cmp_lt_into(b, acc, a, acc_ovf); - unext_reg(b, acc_ovf); -} - -pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, -) { - dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, acc, a, ctrl, p, None); -} - -pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_at_step( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - step: Option, -) { - dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - acc, - a, - ctrl, - p, - &[], - step, - ); -} - -pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - clean_scratch: &[QubitId], -) { - dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - acc, - a, - ctrl, - p, - clean_scratch, - None, - ); -} - -pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - clean_scratch: &[QubitId], - step: Option, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - if let Some(blocks) = dialog_gcd_apply_chunked_f_blocks() - .filter(|_| dialog_gcd_raw_apply_truncated_clean_enabled()) - { - dialog_gcd_cmod_add_materialized_pseudomersenne_chunked( - b, - acc, - a, - ctrl, - p, - blocks, - clean_scratch, - step, - ); - return; - } - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - let f = b.alloc_qubits(N); - b.set_phase("dialog_gcd_materialized_special_load_addend"); - for i in 0..N { - b.ccx(ctrl, a[i], f[i]); - } - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let c_in = b.alloc_qubit(); - - b.set_phase("dialog_gcd_materialized_special_raw_sum"); - if let Some(w) = dialog_gcd_apply_window_blocks() { - cuccaro_add_fast_windowed_low_to_ext(b, &f, &acc_ext, c_in, w); - } else { - let f_ovf = b.alloc_qubit(); - let mut f_ext = f.clone(); - f_ext.push(f_ovf); - cuccaro_add_fast(b, &f_ext, &acc_ext, c_in); - b.free(f_ovf); - } - b.free(c_in); - - b.set_phase("dialog_gcd_materialized_special_overflow_fold"); - if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { - cadd_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); - } else { - cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_overflow_clean"); - if dialog_gcd_raw_apply_truncated_clean_enabled() { - let compare_start = N - dialog_gcd_special_overflow_clean_compare_bits(step); - cmp_lt_into_fast(b, &acc[compare_start..], &f[compare_start..], acc_ovf); - } else { - cmp_lt_into(b, acc, &f, acc_ovf); - } - unext_reg(b, acc_ovf); - - b.set_phase("dialog_gcd_materialized_special_clear_addend"); - for i in 0..N { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} - -pub(crate) fn dialog_gcd_measured_apply_sub_enabled() -> bool { - std::env::var("DIALOG_GCD_MEASURED_APPLY_SUB") - .ok() - .as_deref() - == Some("1") -} - -pub(crate) fn dialog_gcd_apply_window_blocks() -> Option { - std::env::var("DIALOG_GCD_APPLY_WINDOW_BLOCKS") - .ok() - .and_then(|s| s.parse::().ok()) - .filter(|&w| w >= 2) -} - -fn dialog_gcd_clean_truncated_underflow_with_borrowed( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - acc_ovf: QubitId, - step: Option, - borrowed: Option<&[QubitId]>, -) { - let compare_start = N - dialog_gcd_special_underflow_clean_compare_bits(step); - for &q in &a[compare_start..] { - b.x(q); - } - if dialog_gcd_special_clean_conditional_replay_enabled() { - let phase = b.alloc_bit(); - b.hmr(acc_ovf, phase); - b.z_if(ctrl, phase); - dialog_gcd_cmp_lt_phase_conditioned_hosted( - b, - &acc[compare_start..], - &a[compare_start..], - ctrl, - phase, - borrowed, - ); - } else { - b.cx(ctrl, acc_ovf); - ccx_cmp_lt_into_fast(b, &acc[compare_start..], &a[compare_start..], ctrl, acc_ovf); - } - for &q in &a[compare_start..] { - b.x(q); - } -} - -pub(crate) fn dialog_gcd_clean_truncated_underflow( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - acc_ovf: QubitId, - step: Option, -) { - dialog_gcd_clean_truncated_underflow_with_borrowed( - b, - acc, - a, - ctrl, - acc_ovf, - step, - None, - ); -} - -pub(crate) fn dialog_gcd_special_underflow_clean_compare_bits(step: Option) -> usize { - dialog_gcd_special_clean_compare_bits_from_env( - step, - "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", - ) -} - -pub(crate) fn dialog_gcd_special_overflow_clean_compare_bits(step: Option) -> usize { - dialog_gcd_special_clean_compare_bits_from_env( - step, - "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", - ) -} - -pub(crate) fn dialog_gcd_special_fold_carry_trunc_window( - step: Option, -) -> Option { - step.and_then(|step| { - dialog_gcd_step_map_override( - "DIALOG_GCD_SPECIAL_FOLD_CARRY_TRUNC_STEP_WINDOWS", - step, - ) - }) - .filter(|&window| window > 0) - .or_else(fold_carry_trunc_window) -} - -pub(crate) fn dialog_gcd_special_clean_compare_bits_from_env( - step: Option, - env_name: &str, -) -> usize { - let default_bits = dialog_gcd_apply_clean_compare_bits(); - let Some(step) = step else { - return default_bits; - }; - let Ok(spec) = std::env::var(env_name) else { - return default_bits; - }; - for item in spec.split(',') { - let Some((raw_step, raw_bits)) = item.trim().split_once(':') else { - continue; - }; - if raw_step.trim().parse::().ok() != Some(step) { - continue; - } - if let Ok(bits) = raw_bits.trim().parse::() { - if (1..=N).contains(&bits) { - return bits; - } - } - } - default_bits -} - -pub(crate) fn dialog_gcd_load_controlled_slice( - b: &mut B, - ctrl: QubitId, - source: &[QubitId], - lo: usize, - hi: usize, -) -> Vec { - assert!(lo <= hi); - assert!(hi <= source.len()); - let out = b.alloc_qubits(hi - lo); - for (i, &q) in source[lo..hi].iter().enumerate() { - b.ccx(ctrl, q, out[i]); - } - out -} - -pub(crate) fn dialog_gcd_clear_controlled_slice_hmr( - b: &mut B, - ctrl: QubitId, - source: &[QubitId], - lo: usize, - loaded: &[QubitId], -) { - assert!(lo + loaded.len() <= source.len()); - for (i, &q) in loaded.iter().enumerate() { - let m = b.alloc_bit(); - b.hmr(q, m); - b.cz_if(ctrl, source[lo + i], m); - } -} - -pub(crate) fn dialog_gcd_chunk_hi(blocks: usize, block: usize, ext_n: usize) -> usize { - if let Some(cuts) = dialog_gcd_apply_chunked_f_cuts() { - assert_eq!( - cuts.len() + 1, - blocks, - "DIALOG_GCD_APPLY_CHUNKED_F_CUTS must contain blocks-1 cuts" - ); - assert!( - cuts.first().is_some_and(|&cut| cut > 0) - && cuts.windows(2).all(|pair| pair[0] < pair[1]) - && cuts.last().is_some_and(|&cut| cut < ext_n), - "DIALOG_GCD_APPLY_CHUNKED_F_CUTS must be strictly increasing in 1..{ext_n}: {cuts:?}" - ); - if block < cuts.len() { - return cuts[block]; - } - } - if blocks == 4 && dialog_gcd_apply_chunked_f_custom4_enabled() { - let cuts = [ - dialog_gcd_apply_chunked_f_cut().unwrap_or(ext_n / 4), - dialog_gcd_apply_chunked_f_cut2().unwrap_or(ext_n / 2), - dialog_gcd_apply_chunked_f_cut3().unwrap_or(3 * ext_n / 4), - ]; - assert!( - cuts[0] < cuts[1] && cuts[1] < cuts[2] && cuts[2] < ext_n, - "custom four-chunk apply boundaries must be strictly increasing and below {ext_n}: {cuts:?}" - ); - if block < cuts.len() { - return cuts[block]; - } - } - if blocks == 5 && dialog_gcd_apply_chunked_f_custom5_enabled() { - let cuts = [ - dialog_gcd_apply_chunked_f_cut().unwrap_or(ext_n / 5), - dialog_gcd_apply_chunked_f_cut2().unwrap_or((2 * ext_n) / 5), - dialog_gcd_apply_chunked_f_cut3().unwrap_or((3 * ext_n) / 5), - dialog_gcd_apply_chunked_f_cut4().unwrap_or((4 * ext_n) / 5), - ]; - assert!( - cuts[0] < cuts[1] && cuts[1] < cuts[2] && cuts[2] < cuts[3] && cuts[3] < ext_n, - "custom five-chunk apply boundaries must be strictly increasing and below {ext_n}: {cuts:?}" - ); - if block < cuts.len() { - return cuts[block]; - } - } - if block == 0 && blocks <= 3 { - return dialog_gcd_apply_chunked_f_cut() - .unwrap_or(ext_n / 2) - .min(ext_n - 1); - } - if blocks == 3 && block == 1 { - return dialog_gcd_apply_chunked_f_cut2() - .unwrap_or(2 * ext_n / 3) - .min(ext_n - 1); - } - ((block + 1) * ext_n) / blocks -} - -fn dialog_gcd_add_fast_with_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - borrowed: &[QubitId], -) { - let needed = a.len().saturating_sub(1); - let borrowed = &borrowed[..borrowed.len().min(needed)]; - let owned = b.alloc_qubits(needed - borrowed.len()); - let mut carries = Vec::with_capacity(needed); - carries.extend_from_slice(borrowed); - carries.extend_from_slice(&owned); - cuccaro_add_fast_borrowed_carries(b, a, acc, c_in, &carries); - b.free_vec(&owned); -} - -fn dialog_gcd_sub_fast_with_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc: &[QubitId], - c_in: QubitId, - borrowed: &[QubitId], -) { - let needed = a.len().saturating_sub(1); - let borrowed = &borrowed[..borrowed.len().min(needed)]; - let owned = b.alloc_qubits(needed - borrowed.len()); - let mut carries = Vec::with_capacity(needed); - carries.extend_from_slice(borrowed); - carries.extend_from_slice(&owned); - cuccaro_sub_fast_borrowed_carries(b, a, acc, c_in, &carries); - b.free_vec(&owned); -} - -fn dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - borrowed: &[QubitId], -) { - let needed = a.len(); - let borrowed = &borrowed[..borrowed.len().min(needed)]; - let owned = b.alloc_qubits(needed - borrowed.len()); - let mut carries = Vec::with_capacity(needed); - carries.extend_from_slice(borrowed); - carries.extend_from_slice(&owned); - cuccaro_add_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, &carries); - b.free_vec(&owned); -} - -fn dialog_gcd_add_fast_low_to_ext_with_borrowed_carries_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - borrowed_carries: &[QubitId], - clean_top: usize, -) { - let clean_top = clean_top.min(a.len().saturating_sub(1)); - if clean_top == 0 { - return dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( - b, - a, - acc_ext, - c_in, - borrowed_carries, - ); - } - let needed_carries = a.len() - clean_top; - let borrowed = borrowed_carries.len().min(needed_carries); - let owned = b.alloc_qubits(needed_carries - borrowed); - let mut carries = Vec::with_capacity(needed_carries); - carries.extend_from_slice(&borrowed_carries[..borrowed]); - carries.extend_from_slice(&owned); - cuccaro_add_fast_low_to_ext_borrowed_carries_topclean( - b, - a, - acc_ext, - c_in, - &carries, - clean_top, - ); - b.free_vec(&owned); -} - -fn dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - borrowed: &[QubitId], -) { - let needed = a.len(); - let borrowed = &borrowed[..borrowed.len().min(needed)]; - let owned = b.alloc_qubits(needed - borrowed.len()); - let mut carries = Vec::with_capacity(needed); - carries.extend_from_slice(borrowed); - carries.extend_from_slice(&owned); - cuccaro_sub_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, &carries); - b.free_vec(&owned); -} - -fn dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries_topclean( - b: &mut B, - a: &[QubitId], - acc_ext: &[QubitId], - c_in: QubitId, - borrowed_carries: &[QubitId], - clean_top: usize, -) { - let clean_top = clean_top.min(a.len().saturating_sub(1)); - if clean_top == 0 { - return dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( - b, - a, - acc_ext, - c_in, - borrowed_carries, - ); - } - let needed_carries = a.len() - clean_top; - let borrowed = borrowed_carries.len().min(needed_carries); - let owned = b.alloc_qubits(needed_carries - borrowed); - let mut carries = Vec::with_capacity(needed_carries); - carries.extend_from_slice(&borrowed_carries[..borrowed]); - carries.extend_from_slice(&owned); - cuccaro_sub_fast_low_to_ext_borrowed_carries_topclean( - b, - a, - acc_ext, - c_in, - &carries, - clean_top, - ); - b.free_vec(&owned); -} - -fn dialog_gcd_conditional_boundary_replay( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - targets: &[(QubitId, usize)], -) { - assert!(!targets.is_empty()); - assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); - for index in (0..targets.len()).rev() { - let (target, p) = targets[index]; - let (start, carry_in) = if index == 0 { - (0, c_in) - } else { - (targets[index - 1].1, targets[index - 1].0) - }; - let phase = b.alloc_bit(); - b.hmr(target, phase); - cmp_lt_phase_conditioned_with_cin( - b, - &u[start..p], - &v[start..p], - carry_in, - ctrl, - phase, - ); - } -} - -fn dialog_gcd_conditional_boundary_replay_free_owned( - b: &mut B, - u: &[QubitId], - v: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - targets: &[(QubitId, usize, bool)], -) { - assert!(!targets.is_empty()); - assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); - for index in (0..targets.len()).rev() { - let (target, p, owned_target) = targets[index]; - let (start, carry_in) = if index == 0 { - (0, c_in) - } else { - (targets[index - 1].1, targets[index - 1].0) - }; - let phase = b.alloc_bit(); - b.hmr(target, phase); - if owned_target { - b.free(target); - } - cmp_lt_phase_conditioned_with_cin( - b, - &u[start..p], - &v[start..p], - carry_in, - ctrl, - phase, - ); - } -} - -fn dialog_gcd_apply_auto_topclean_bits( - active_before_ripple: u32, - source_len: usize, - future_boundary_carries: &[QubitId], -) -> usize { - let Some(target) = dialog_gcd_apply_chunked_f_auto_topclean_target() else { - return 0; - }; - if source_len <= 1 { - return 0; - } - let future_borrowed = future_boundary_carries.len().min(source_len); - let owned_carries_without_topclean = source_len - future_borrowed; - let projected_peak = active_before_ripple as usize + owned_carries_without_topclean; - let needed = projected_peak.saturating_sub(target as usize); - needed - .min(dialog_gcd_apply_chunked_f_auto_topclean_max_bits()) - .min(source_len - 1) -} - -pub(crate) fn dialog_gcd_add_ctrl_chunked_low_to_ext( - b: &mut B, - source: &[QubitId], - acc_ext: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - blocks: usize, - clean_scratch: &[QubitId], -) { - let n = source.len(); - assert_eq!(acc_ext.len(), n + 1); - for (i, &q) in clean_scratch.iter().enumerate() { - assert!(!clean_scratch[..i].contains(&q)); - assert!(!source.contains(&q)); - assert!(!acc_ext.contains(&q)); - assert_ne!(q, ctrl); - assert_ne!(q, c_in); - } - let ext_n = acc_ext.len(); - let blocks = blocks.max(2).min(ext_n); - let mut carry = c_in; - let mut lo = 0usize; - - let implicit_high_zero = dialog_gcd_apply_implicit_high_zero_enabled(); - let zero_host = (!implicit_high_zero) - .then(|| clean_scratch.first().copied()) - .flatten(); - let boundary_hosts = &clean_scratch - [usize::from(!implicit_high_zero && zero_host.is_some())..]; - let mut couts: Vec<(QubitId, usize, bool)> = Vec::new(); - - for blk in 0..blocks { - let hi = dialog_gcd_chunk_hi(blocks, blk, ext_n); - if hi <= lo { - continue; - } - if blk == blocks - 1 || hi == ext_n { - b.set_phase("dialog_gcd_apply_chunk_add_final_load"); - let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo.min(n), n); - b.set_phase("dialog_gcd_apply_chunk_add_final_ripple"); - let final_topclean = dialog_gcd_apply_final_topclean_bits() - .max(dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), &[])); - if final_topclean > 0 { - cuccaro_add_fast_low_to_ext_topclean(b, &f, &acc_ext[lo..hi], carry, final_topclean); - } else if let Some(window_blocks) = dialog_gcd_apply_final_windowed_fast_blocks() { - cuccaro_add_fast_windowed_low_to_ext( - b, - &f, - &acc_ext[lo..hi], - carry, - window_blocks, - ); - } else if dialog_gcd_apply_final_lowq_enabled() { - let zero = b.alloc_qubit(); - let mut f_ext = f.clone(); - f_ext.push(zero); - cuccaro_add(b, &f_ext, &acc_ext[lo..hi], carry); - b.free(zero); - } else { - cuccaro_add_fast_low_to_ext(b, &f, &acc_ext[lo..hi], carry); - } - b.set_phase("dialog_gcd_apply_chunk_add_final_clear"); - dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo.min(n), &f); - b.free_vec(&f); - break; - } - - assert!(hi <= n); - b.set_phase("dialog_gcd_apply_chunk_add_load"); - let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo, hi); - let needs_distinct_zero = - carry == c_in || !dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled(); - let (zero, owned_zero) = if needs_distinct_zero { - zero_host.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)) - } else { - (c_in, false) - }; - let (cout, owned_cout) = boundary_hosts - .get(couts.len()) - .copied() - .map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); - let mut acc_block = acc_ext[lo..hi].to_vec(); - acc_block.push(cout); - let future_boundary_carries = if dialog_gcd_apply_borrow_future_boundary_carries_enabled() { - boundary_hosts.get(couts.len() + 1..).unwrap_or(&[]) - } else { - &[] - }; - let topclean_bits = if implicit_high_zero { - dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), future_boundary_carries) - } else { - 0 - }; - b.set_phase("dialog_gcd_apply_chunk_add_ripple"); - if implicit_high_zero { - if topclean_bits > 0 { - dialog_gcd_add_fast_low_to_ext_with_borrowed_carries_topclean( - b, - &f, - &acc_block, - carry, - future_boundary_carries, - topclean_bits, - ); - } else { - dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( - b, - &f, - &acc_block, - carry, - future_boundary_carries, - ); - } - } else { - let mut a_block = f.clone(); - a_block.push(zero); - dialog_gcd_add_fast_with_borrowed_carries( - b, - &a_block, - &acc_block, - carry, - future_boundary_carries, - ); - } - if owned_zero { - b.free(zero); - } - b.set_phase("dialog_gcd_apply_chunk_add_clear"); - dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo, &f); - b.free_vec(&f); - couts.push((cout, hi, owned_cout)); - carry = cout; - lo = hi; - } - - let mut boundary_replay_freed_owned = false; - if dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() { - if let Some(&(_, p, _)) = couts.last() { - b.set_phase("dialog_gcd_apply_chunk_add_boundary_clear"); - let targets = couts - .iter() - .map(|&(cout, p, _)| (cout, p)) - .collect::>(); - if dialog_gcd_apply_boundary_conditional_replay_enabled() { - if dialog_gcd_apply_boundary_free_owned_during_replay_enabled() { - dialog_gcd_conditional_boundary_replay_free_owned( - b, - &acc_ext[..p], - &source[..p], - ctrl, - c_in, - &couts, - ); - boundary_replay_freed_owned = true; - } else { - dialog_gcd_conditional_boundary_replay( - b, - &acc_ext[..p], - &source[..p], - ctrl, - c_in, - &targets, - ); - } - } else if let Some(split) = dialog_gcd_apply_boundary_split() { - ccx_cmp_lt_into_fast_prefix_targets_split( - b, - &acc_ext[..p], - &source[..p], - ctrl, - &targets, - split.min(p.saturating_sub(1)), - ); - } else { - ccx_cmp_lt_into_fast_prefix_targets(b, &acc_ext[..p], &source[..p], ctrl, &targets); - } - } - } else { - for &(cout, p, _) in couts.iter().rev() { - b.set_phase("dialog_gcd_apply_chunk_add_boundary_clear"); - ccx_cmp_lt_into_fast(b, &acc_ext[..p], &source[..p], ctrl, cout); - } - } - for &(cout, _, owned_cout) in couts.iter().rev() { - if owned_cout && !boundary_replay_freed_owned { - b.free(cout); - } - } -} - -pub(crate) fn dialog_gcd_sub_ctrl_chunked_low_to_ext( - b: &mut B, - source: &[QubitId], - acc_ext: &[QubitId], - ctrl: QubitId, - c_in: QubitId, - blocks: usize, - clean_scratch: &[QubitId], -) { - let n = source.len(); - assert_eq!(acc_ext.len(), n + 1); - for (i, &q) in clean_scratch.iter().enumerate() { - assert!(!clean_scratch[..i].contains(&q)); - assert!(!source.contains(&q)); - assert!(!acc_ext.contains(&q)); - assert_ne!(q, ctrl); - assert_ne!(q, c_in); - } - let ext_n = acc_ext.len(); - let blocks = blocks.max(2).min(ext_n); - let mut borrow = c_in; - let mut lo = 0usize; - let implicit_high_zero = dialog_gcd_apply_implicit_high_zero_enabled(); - let zero_host = (!implicit_high_zero) - .then(|| clean_scratch.first().copied()) - .flatten(); - let boundary_hosts = &clean_scratch - [usize::from(!implicit_high_zero && zero_host.is_some())..]; - let mut bouts: Vec<(QubitId, usize, bool)> = Vec::new(); - - for blk in 0..blocks { - let hi = dialog_gcd_chunk_hi(blocks, blk, ext_n); - if hi <= lo { - continue; - } - if blk == blocks - 1 || hi == ext_n { - b.set_phase("dialog_gcd_apply_chunk_sub_final_load"); - let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo.min(n), n); - b.set_phase("dialog_gcd_apply_chunk_sub_final_ripple"); - let final_topclean = dialog_gcd_apply_final_topclean_bits() - .max(dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), &[])); - if final_topclean > 0 { - cuccaro_sub_fast_low_to_ext_topclean(b, &f, &acc_ext[lo..hi], borrow, final_topclean); - } else if let Some(window_blocks) = dialog_gcd_apply_final_windowed_fast_blocks() { - cuccaro_sub_fast_windowed_low_to_ext( - b, - &f, - &acc_ext[lo..hi], - borrow, - window_blocks, - ); - } else if dialog_gcd_apply_final_lowq_enabled() { - let zero = b.alloc_qubit(); - let mut f_ext = f.clone(); - f_ext.push(zero); - cuccaro_sub(b, &f_ext, &acc_ext[lo..hi], borrow); - b.free(zero); - } else { - cuccaro_sub_fast_low_to_ext(b, &f, &acc_ext[lo..hi], borrow); - } - b.set_phase("dialog_gcd_apply_chunk_sub_final_clear"); - dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo.min(n), &f); - b.free_vec(&f); - break; - } - - assert!(hi <= n); - b.set_phase("dialog_gcd_apply_chunk_sub_load"); - let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo, hi); - let needs_distinct_zero = - borrow == c_in || !dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled(); - let (zero, owned_zero) = if needs_distinct_zero { - zero_host.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)) - } else { - (c_in, false) - }; - let (bout, owned_bout) = boundary_hosts - .get(bouts.len()) - .copied() - .map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); - let mut acc_block = acc_ext[lo..hi].to_vec(); - acc_block.push(bout); - let future_boundary_carries = if dialog_gcd_apply_borrow_future_boundary_carries_enabled() { - boundary_hosts.get(bouts.len() + 1..).unwrap_or(&[]) - } else { - &[] - }; - let topclean_bits = if implicit_high_zero { - dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), future_boundary_carries) - } else { - 0 - }; - b.set_phase("dialog_gcd_apply_chunk_sub_ripple"); - if implicit_high_zero { - if topclean_bits > 0 { - dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries_topclean( - b, - &f, - &acc_block, - borrow, - future_boundary_carries, - topclean_bits, - ); - } else { - dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( - b, - &f, - &acc_block, - borrow, - future_boundary_carries, - ); - } - } else { - let mut a_block = f.clone(); - a_block.push(zero); - dialog_gcd_sub_fast_with_borrowed_carries( - b, - &a_block, - &acc_block, - borrow, - future_boundary_carries, - ); - } - if owned_zero { - b.free(zero); - } - b.set_phase("dialog_gcd_apply_chunk_sub_clear"); - dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo, &f); - b.free_vec(&f); - bouts.push((bout, hi, owned_bout)); - borrow = bout; - lo = hi; - } - - let mut boundary_replay_freed_owned = false; - if dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() { - if let Some(&(_, p, _)) = bouts.last() { - b.set_phase("dialog_gcd_apply_chunk_sub_boundary_clear"); - for i in 0..p { - b.x(source[i]); - } - let targets = bouts - .iter() - .map(|&(bout, p, _)| (bout, p)) - .collect::>(); - if dialog_gcd_apply_boundary_conditional_replay_enabled() { - if dialog_gcd_apply_boundary_free_owned_during_replay_enabled() { - dialog_gcd_conditional_boundary_replay_free_owned( - b, - &source[..p], - &acc_ext[..p], - ctrl, - c_in, - &bouts, - ); - boundary_replay_freed_owned = true; - } else { - dialog_gcd_conditional_boundary_replay( - b, - &source[..p], - &acc_ext[..p], - ctrl, - c_in, - &targets, - ); - } - } else if let Some(split) = dialog_gcd_apply_boundary_split() { - ccx_cmp_lt_into_fast_prefix_targets_split( - b, - &source[..p], - &acc_ext[..p], - ctrl, - &targets, - split.min(p.saturating_sub(1)), - ); - } else { - ccx_cmp_lt_into_fast_prefix_targets(b, &source[..p], &acc_ext[..p], ctrl, &targets); - } - for i in 0..p { - b.x(source[i]); - } - } - } else { - for &(bout, p, _) in bouts.iter().rev() { - b.set_phase("dialog_gcd_apply_chunk_sub_boundary_clear"); - for i in 0..p { - b.x(source[i]); - } - ccx_cmp_lt_into_fast(b, &source[..p], &acc_ext[..p], ctrl, bout); - for i in 0..p { - b.x(source[i]); - } - } - } - for &(bout, _, owned_bout) in bouts.iter().rev() { - if owned_bout && !boundary_replay_freed_owned { - b.free(bout); - } - } -} - -pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_chunked( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - blocks: usize, - clean_scratch: &[QubitId], - step: Option, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - for (i, &q) in clean_scratch.iter().enumerate() { - assert!(!clean_scratch[..i].contains(&q)); - assert!(!acc_ext.contains(&q)); - assert!(!a.contains(&q)); - assert_ne!(q, ctrl); - } - let (c_in, owned_c_in, inner_scratch) = clean_scratch.split_first().map_or_else( - || (b.alloc_qubit(), true, &[][..]), - |(&q, rest)| (q, false, rest), - ); - - b.set_phase("dialog_gcd_materialized_special_chunked_raw_sum"); - dialog_gcd_add_ctrl_chunked_low_to_ext(b, a, &acc_ext, ctrl, c_in, blocks, inner_scratch); - if owned_c_in { - b.free(c_in); - } - - b.set_phase("dialog_gcd_materialized_special_overflow_fold"); - if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { - let borrowed_carries = if std::env::var("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES") - .ok() - .as_deref() - == Some("1") - { - - clean_scratch - } else { - &[] - }; - if std::env::var("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH") - .ok() - .as_deref() - == Some("1") - && !borrowed_carries.is_empty() - { - assert_eq!( - std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") - .ok() - .as_deref(), - Some("1"), - "special-fold scratch release requires owned in-place apply scratch" - ); - cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b, - &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], - c, - acc_ovf, - w, - borrowed_carries, - step, - ); - } else { - cadd_nbit_const_direct_trunc_fast_borrowed_carries( - b, - &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], - c, - acc_ovf, - w, - borrowed_carries, - ); - } - } else { - cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_overflow_clean"); - let compare_start = N - dialog_gcd_special_overflow_clean_compare_bits(step); - if dialog_gcd_special_clean_conditional_replay_enabled() { - let phase = b.alloc_bit(); - b.hmr(acc_ovf, phase); - dialog_gcd_cmp_lt_phase_conditioned_hosted( - b, - &acc[compare_start..], - &a[compare_start..], - ctrl, - phase, - Some(clean_scratch), - ); - } else { - ccx_cmp_lt_into_fast(b, &acc[compare_start..], &a[compare_start..], ctrl, acc_ovf); - } - unext_reg(b, acc_ovf); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_chunked( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - blocks: usize, - clean_scratch: &[QubitId], - step: Option, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - for (i, &q) in clean_scratch.iter().enumerate() { - assert!(!clean_scratch[..i].contains(&q)); - assert!(!acc_ext.contains(&q)); - assert!(!a.contains(&q)); - assert_ne!(q, ctrl); - } - let (c_in, owned_c_in, inner_scratch) = clean_scratch.split_first().map_or_else( - || (b.alloc_qubit(), true, &[][..]), - |(&q, rest)| (q, false, rest), - ); - - b.set_phase("dialog_gcd_materialized_special_chunked_raw_difference"); - dialog_gcd_sub_ctrl_chunked_low_to_ext(b, a, &acc_ext, ctrl, c_in, blocks, inner_scratch); - if owned_c_in { - b.free(c_in); - } - - b.set_phase("dialog_gcd_materialized_special_underflow_fold"); - if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { - let borrowed_carries = if std::env::var("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES") - .ok() - .as_deref() - == Some("1") - { - - clean_scratch - } else { - &[] - }; - if std::env::var("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH") - .ok() - .as_deref() - == Some("1") - && !borrowed_carries.is_empty() - { - assert_eq!( - std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") - .ok() - .as_deref(), - Some("1"), - "special-fold scratch release requires owned in-place apply scratch" - ); - csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( - b, - &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], - c, - acc_ovf, - w, - borrowed_carries, - step, - ); - } else { - csub_nbit_const_direct_trunc_fast_borrowed_carries( - b, - &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], - c, - acc_ovf, - w, - borrowed_carries, - ); - } - } else { - csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_underflow_clean"); - dialog_gcd_clean_truncated_underflow_with_borrowed( - b, - acc, - a, - ctrl, - acc_ovf, - step, - Some(clean_scratch), - ); - unext_reg(b, acc_ovf); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, -) { - dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, acc, a, ctrl, p, None); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - step: Option, -) { - dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - acc, - a, - ctrl, - p, - &[], - step, - ); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - clean_scratch: &[QubitId], -) { - dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( - b, - acc, - a, - ctrl, - p, - clean_scratch, - None, - ); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - clean_scratch: &[QubitId], - step: Option, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - if let Some(blocks) = dialog_gcd_apply_chunked_f_blocks() - .filter(|_| dialog_gcd_raw_apply_truncated_clean_enabled()) - .filter(|_| dialog_gcd_measured_apply_sub_enabled()) - { - dialog_gcd_cmod_sub_materialized_pseudomersenne_chunked( - b, - acc, - a, - ctrl, - p, - blocks, - clean_scratch, - step, - ); - return; - } - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - let f = b.alloc_qubits(N); - b.set_phase("dialog_gcd_materialized_special_load_subtrahend"); - for i in 0..N { - b.ccx(ctrl, a[i], f[i]); - } - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - - b.set_phase("dialog_gcd_materialized_special_raw_difference"); - if dialog_gcd_measured_apply_sub_enabled() { - - let c_in = b.alloc_qubit(); - if let Some(w) = dialog_gcd_apply_window_blocks() { - cuccaro_sub_fast_windowed_low_to_ext(b, &f, &acc_ext, c_in, w); - } else { - let f_ovf = b.alloc_qubit(); - let mut f_ext = f.clone(); - f_ext.push(f_ovf); - cuccaro_sub_fast(b, &f_ext, &acc_ext, c_in); - b.free(f_ovf); - } - b.free(c_in); - } else { - let f_ovf = b.alloc_qubit(); - let mut f_ext = f.clone(); - f_ext.push(f_ovf); - sub_nbit_qq(b, &f_ext, &acc_ext); - b.free(f_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_underflow_fold"); - if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { - csub_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); - } else { - csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_underflow_clean"); - if dialog_gcd_raw_apply_truncated_clean_enabled() { - dialog_gcd_clean_truncated_underflow(b, acc, a, ctrl, acc_ovf, step); - } else { - b.x(acc_ovf); - mod_neg_inplace_fast(b, &f, p); - cmp_lt_into_fast(b, acc, &f, acc_ovf); - mod_neg_inplace_fast(b, &f, p); - } - unext_reg(b, acc_ovf); - - b.set_phase("dialog_gcd_materialized_special_clear_subtrahend"); - for i in 0..N { - let m = b.alloc_bit(); - b.hmr(f[i], m); - b.cz_if(ctrl, a[i], m); - } - b.free_vec(&f); -} - -pub(crate) fn emit_dialog_gcd_raw_apply_bitvector( - b: &mut B, - dialog_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, -) { - assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - - for step in (0..dialog_gcd_active_iterations()).rev() { - let b0 = dialog_log[2 * step]; - let b0_and_b1 = dialog_log[2 * step + 1]; - - b.set_phase("dialog_gcd_raw_apply_double_y"); - mod_double_inplace_fast(b, y, p); - - b.set_phase("dialog_gcd_raw_apply_cadd"); - if dialog_gcd_raw_apply_materialized_special_add_enabled() { - dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); - } else if dialog_gcd_raw_apply_direct_special_add_enabled() { - dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); - } else { - cmod_add_qq_lowq(b, y, x, b0, p); - } - - b.set_phase("dialog_gcd_raw_apply_cswap"); - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - } -} - -pub(crate) fn emit_dialog_gcd_raw_apply_bitvector_reverse_exact( - b: &mut B, - dialog_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, -) { - assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - - for step in 0..dialog_gcd_active_iterations() { - let b0 = dialog_log[2 * step]; - let b0_and_b1 = dialog_log[2 * step + 1]; - - b.set_phase("dialog_gcd_raw_apply_reverse_cswap"); - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - - b.set_phase("dialog_gcd_raw_apply_reverse_csub"); - if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { - dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); - } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { - cmod_sub_qq(b, y, x, b0, p); - } else { - cmod_sub_qq_lowq(b, y, x, b0, p); - } - - b.set_phase("dialog_gcd_raw_apply_reverse_halve_y"); - mod_halve_inplace_fast(b, y, p); - } -} - -pub(crate) fn cmod_sub_qq_lowq_borrowed_subtrahend( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - f: &[QubitId], -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - assert_eq!(f.len(), N); - - for i in 0..N { - b.ccx(ctrl, a[i], f[i]); - } - mod_sub_qq(b, acc, f, p); - for i in (0..N).rev() { - b.ccx(ctrl, a[i], f[i]); - } -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - f: &[QubitId], -) { - dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( - b, - acc, - a, - ctrl, - p, - f, - None, - ); -} - -pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( - b: &mut B, - acc: &[QubitId], - a: &[QubitId], - ctrl: QubitId, - p: U256, - f: &[QubitId], - step: Option, -) { - assert_eq!(acc.len(), N); - assert_eq!(a.len(), N); - assert_eq!(f.len(), N); - let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); - - b.set_phase("dialog_gcd_materialized_special_borrowed_load_subtrahend"); - for i in 0..N { - b.ccx(ctrl, a[i], f[i]); - } - - let (acc_ext, acc_ovf) = ext_reg(b, acc); - let f_ovf = b.alloc_qubit(); - let mut f_ext = f.to_vec(); - f_ext.push(f_ovf); - - b.set_phase("dialog_gcd_materialized_special_borrowed_raw_difference"); - sub_nbit_qq(b, &f_ext, &acc_ext); - b.free(f_ovf); - - b.set_phase("dialog_gcd_materialized_special_borrowed_underflow_fold"); - if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { - csub_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); - } else { - csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); - } - - b.set_phase("dialog_gcd_materialized_special_borrowed_underflow_clean"); - if dialog_gcd_raw_apply_truncated_clean_enabled() { - dialog_gcd_clean_truncated_underflow(b, acc, a, ctrl, acc_ovf, step); - } else { - b.x(acc_ovf); - mod_neg_inplace_fast(b, f, p); - cmp_lt_into_fast(b, acc, f, acc_ovf); - mod_neg_inplace_fast(b, f, p); - } - unext_reg(b, acc_ovf); - - b.set_phase("dialog_gcd_materialized_special_borrowed_clear_subtrahend"); - for i in (0..N).rev() { - b.ccx(ctrl, a[i], f[i]); - } -} - -pub(crate) fn emit_dialog_gcd_raw_apply_bitvector_reverse_borrowed_subtrahend( - b: &mut B, - dialog_log: &[QubitId], - x: &[QubitId], - y: &[QubitId], - p: U256, - f: &[QubitId], -) { - assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); - assert_eq!(x.len(), N); - assert_eq!(y.len(), N); - assert_eq!(f.len(), N); - - for step in 0..dialog_gcd_active_iterations() { - let b0 = dialog_log[2 * step]; - let b0_and_b1 = dialog_log[2 * step + 1]; - - b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_cswap"); - for (&xi, &yi) in x.iter().zip(y.iter()) { - cswap(b, b0_and_b1, xi, yi); - } - - b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_csub"); - if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { - dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( - b, - y, - x, - b0, - p, - f, - Some(step), - ); - } else { - cmod_sub_qq_lowq_borrowed_subtrahend(b, y, x, b0, p, f); - } - - b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_halve_y"); - mod_halve_inplace_fast(b, y, p); - } -} - -pub(crate) fn emit_dialog_gcd_raw_ipmul(b: &mut B, factor: &[QubitId], target: &[QubitId], p: U256) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - if dialog_gcd_compressed_sidecar_log_enabled() { - emit_dialog_gcd_compressed_sidecar_ipmul(b, factor, target, p); - return; - } - - let dialog_log = b.alloc_qubits(DIALOG_GCD_RAW_LOG_BITS); - let u = b.alloc_qubits(N); - b.set_phase("dialog_gcd_raw_ipmul_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_raw_ipmul_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps(b, &u, factor, &dialog_log); - - if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_raw_ipmul_release_terminal_u"); - b.x(u[0]); - b.free_vec(&u); - - b.set_phase("dialog_gcd_raw_ipmul_apply_bitvector_reuse_factor_zero"); - emit_dialog_gcd_raw_apply_bitvector(b, &dialog_log, target, factor, p); - - if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { - b.set_phase("dialog_gcd_raw_ipmul_clear_p_residual_source_lane"); - for i in 0..N { - if bit(p, i) { - b.x(target[i]); - } - } - } - - b.set_phase("dialog_gcd_raw_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - b.set_phase("dialog_gcd_raw_ipmul_reacquire_terminal_u"); - b.reacquire_vec(&u); - b.set_phase("dialog_gcd_raw_ipmul_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_raw_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); - - b.set_phase("dialog_gcd_raw_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free_vec(&dialog_log); - return; - } - - let tmp = b.alloc_qubits(N); - b.set_phase("dialog_gcd_raw_ipmul_apply_bitvector"); - emit_dialog_gcd_raw_apply_bitvector(b, &dialog_log, target, &tmp, p); - - b.set_phase("dialog_gcd_raw_ipmul_swap_product_into_target"); - for i in 0..N { - b.swap(target[i], tmp[i]); - } - - b.set_phase("dialog_gcd_raw_ipmul_free_zero_tmp"); - b.free_vec(&tmp); - - b.set_phase("dialog_gcd_raw_ipmul_uncompute_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); - - b.set_phase("dialog_gcd_raw_ipmul_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free_vec(&dialog_log); -} - -pub(crate) fn emit_dialog_gcd_raw_quotient(b: &mut B, factor: &[QubitId], target: &[QubitId], p: U256) { - assert_eq!(factor.len(), N); - assert_eq!(target.len(), N); - - if dialog_gcd_compressed_sidecar_log_enabled() { - emit_dialog_gcd_compressed_sidecar_quotient(b, factor, target, p); - return; - } - - let dialog_log = b.alloc_qubits(DIALOG_GCD_RAW_LOG_BITS); - let u = b.alloc_qubits(N); - b.set_phase("dialog_gcd_raw_quotient_load_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - - b.set_phase("dialog_gcd_raw_quotient_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps(b, &u, factor, &dialog_log); - - if dialog_gcd_raw_quotient_keep_terminal_u_enabled() { - b.set_phase("dialog_gcd_raw_quotient_zero_terminal_u_for_borrow"); - b.x(u[0]); - - b.set_phase("dialog_gcd_raw_quotient_apply_reverse_reuse_factor_zero_keep_u"); - emit_dialog_gcd_raw_apply_bitvector_reverse_borrowed_subtrahend( - b, - &dialog_log, - factor, - target, - p, - &u, - ); - - b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target_keep_u"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - b.set_phase("dialog_gcd_raw_quotient_restore_terminal_u_after_borrow"); - b.x(u[0]); - - b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector_keep_u"); - emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); - - b.set_phase("dialog_gcd_raw_quotient_unload_p_keep_u"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free_vec(&dialog_log); - return; - } - - if dialog_gcd_raw_quotient_terminal_reuse_enabled() { - b.set_phase("dialog_gcd_raw_quotient_release_terminal_u"); - b.x(u[0]); - b.free_vec(&u); - - b.set_phase("dialog_gcd_raw_quotient_apply_reverse_reuse_factor_zero"); - emit_dialog_gcd_raw_apply_bitvector_reverse_exact(b, &dialog_log, factor, target, p); - - b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target"); - for i in 0..N { - b.swap(target[i], factor[i]); - } - - b.set_phase("dialog_gcd_raw_quotient_reacquire_terminal_u"); - b.reacquire_vec(&u); - b.set_phase("dialog_gcd_raw_quotient_seed_terminal_u"); - b.x(u[0]); - - b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); - - b.set_phase("dialog_gcd_raw_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free_vec(&dialog_log); - return; - } - - let tmp = b.alloc_qubits(N); - b.set_phase("dialog_gcd_raw_quotient_apply_reverse"); - emit_dialog_gcd_raw_apply_bitvector_reverse_exact(b, &dialog_log, &tmp, target, p); - - b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target"); - for i in 0..N { - b.swap(target[i], tmp[i]); - } - - b.set_phase("dialog_gcd_raw_quotient_free_zero_tmp"); - b.free_vec(&tmp); - - b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector"); - emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); - - b.set_phase("dialog_gcd_raw_quotient_unload_p"); - for i in 0..N { - if bit(p, i) { - b.x(u[i]); - } - } - b.free_vec(&u); - b.free_vec(&dialog_log); -} - -pub(crate) fn emit_dialog_gcd_raw_pa( - b: &mut B, - tx: &[QubitId], - ty: &[QubitId], - ox: &[BitId], - oy: &[BitId], - p: U256, -) { - assert_eq!(tx.len(), N); - assert_eq!(ty.len(), N); - assert_eq!(ox.len(), N); - assert_eq!(oy.len(), N); - - b.set_phase("dialog_gcd_raw_pa_pair1_quotient"); - emit_dialog_gcd_raw_quotient(b, tx, ty, p); - if dialog_gcd_raw_pa_stop_after_quotient_enabled() { - return; - } - - round84_emit_fused_square_xtail(b, tx, ty, ox, p); - if dialog_gcd_raw_pa_stop_after_xtail_enabled() { - return; - } - - b.set_phase("dialog_gcd_raw_pa_c_ox_minus_rx"); - if dialog_fuse_c_form_enabled() { - mod_add_triple_qb(b, tx, ox, p); - } else { - mod_sub_qb(b, tx, ox, p); - mod_neg_inplace_fast(b, tx, p); - } - if dialog_gcd_raw_pa_stop_after_c_enabled() { - return; - } - - b.set_phase("dialog_gcd_raw_pa_pair2_product"); - emit_dialog_gcd_raw_ipmul(b, tx, ty, p); - if dialog_gcd_raw_pa_stop_after_pair2_enabled() { - return; - } - - b.set_phase("dialog_gcd_raw_pa_y_output"); - mod_sub_qb(b, ty, oy, p); - - b.set_phase("dialog_gcd_raw_pa_x_restore"); - if dialog_fuse_x_restore_enabled() { - mod_const_minus_reg_qb(b, tx, ox, p); - } else { - mod_neg_inplace_fast(b, tx, p); - mod_add_qb(b, tx, ox, p); - } -} + +use super::*; + +mod compressed; +mod config; +pub(crate) use compressed::*; +pub(crate) use config::*; + +pub(crate) fn round84_emit_fused_square_xtail( + b: &mut B, + tx: &[QubitId], + lam: &[QubitId], + ox: &[BitId], + p: U256, +) { + b.set_phase("round84_fused_square_xtail_dx_sub_lam_square_lowq"); + if std::env::var("ROUND84_XTAIL_KARATSUBA").ok().as_deref() == Some("1") { + + squaring_sub_from_acc_karatsuba(b, tx, lam, p); + } else if std::env::var("ROUND84_XTAIL_WALK_SQUARE").ok().as_deref() == Some("1") { + squaring_sub_from_acc_walk_controls_lowq(b, tx, lam, p); + } else if std::env::var("ROUND84_XTAIL_SCHOOLBOOK").ok().as_deref() == Some("1") { + squaring_sub_from_acc_schoolbook(b, tx, lam, p); + } else { + squaring_sub_from_acc_schoolbook_lowq_shift22(b, tx, lam, p); + } + if dialog_fuse_c_form_enabled() { + return; + } + b.set_phase("round84_fused_square_xtail_add_double_ox"); + mod_add_double_qb(b, tx, ox, p); + b.set_phase("round84_fused_square_xtail_negate_to_x3"); + mod_neg_inplace_fast(b, tx, p); +} + +pub(crate) fn dialog_gcd_cmp_gt_truncated_into_width( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + flag: QubitId, + compare_bits: usize, +) { + assert_eq!(u.len(), v.len()); + assert!(!u.is_empty()); + let compare_bits = compare_bits.min(u.len()).max(1); + let start = u.len() - compare_bits; + cmp_lt_into_fast(b, &v[start..], &u[start..], flag); +} + +pub(crate) fn dialog_gcd_ccx_cmp_gt_truncated_into_width( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + target: QubitId, + compare_bits: usize, +) { + assert_eq!(u.len(), v.len()); + assert!(!u.is_empty()); + let compare_bits = compare_bits.min(u.len()).max(1); + let start = u.len() - compare_bits; + ccx_cmp_lt_into_fast(b, &v[start..], &u[start..], ctrl, target); +} + +pub(crate) fn dialog_gcd_branch_bits_host_comparator_enabled() -> bool { + std::env::var("DIALOG_GCD_BRANCH_BITS_HOST_COMPARATOR") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_ccx_cmp_gt_truncated_into_width_hosted( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + target: QubitId, + compare_bits: usize, + borrowed: Option<&[QubitId]>, +) { + assert_eq!(u.len(), v.len()); + assert!(!u.is_empty()); + let compare_bits = compare_bits.min(u.len()).max(1); + let start = u.len() - compare_bits; + let cmp_u = &v[start..]; + let cmp_v = &u[start..]; + let n = cmp_u.len(); + + let need = n + 1; + let avail = borrowed.map(|s| s.len()).unwrap_or(0); + if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { + let slice = borrowed.expect("avail>0"); + let owned = b.alloc_qubits(need - avail); + let mut clean: Vec = Vec::with_capacity(need); + clean.extend_from_slice(slice); + clean.extend_from_slice(&owned); + let (c_in, carries) = clean.split_first().expect("need >= 1"); + ccx_cmp_lt_into_fast_borrowed_carries(b, cmp_u, cmp_v, ctrl, target, *c_in, &carries[..n]); + b.free_vec(&owned); + } else if let Some(slice) = borrowed.filter(|s| s.len() >= need) { + let (c_in, carries) = slice.split_first().expect("slice len >= n+1 > 0"); + ccx_cmp_lt_into_fast_borrowed_carries(b, cmp_u, cmp_v, ctrl, target, *c_in, &carries[..n]); + } else { + ccx_cmp_lt_into_fast(b, cmp_u, cmp_v, ctrl, target); + } +} + +pub(crate) fn dialog_gcd_cmp_gt_truncated_phase_conditioned_hosted( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + phase: BitId, + compare_bits: usize, + borrowed: Option<&[QubitId]>, +) { + assert_eq!(u.len(), v.len()); + assert!(!u.is_empty()); + let compare_bits = compare_bits.min(u.len()).max(1); + let start = u.len() - compare_bits; + let cmp_u = &v[start..]; + let cmp_v = &u[start..]; + let n = cmp_u.len(); + let need = n + 1; + let avail = borrowed.map(|s| s.len()).unwrap_or(0); + if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { + let slice = borrowed.expect("avail>0"); + let owned = b.alloc_qubits(need - avail); + let mut clean: Vec = Vec::with_capacity(need); + clean.extend_from_slice(slice); + clean.extend_from_slice(&owned); + let (c_in, carries) = clean.split_first().expect("need >= 1"); + cmp_lt_phase_conditioned_borrowed_carries( + b, + cmp_u, + cmp_v, + *c_in, + &carries[..n], + ctrl, + phase, + ); + b.free_vec(&owned); + } else if let Some(slice) = borrowed.filter(|s| s.len() >= need) { + let (c_in, carries) = slice.split_first().expect("slice len >= n+1 > 0"); + cmp_lt_phase_conditioned_borrowed_carries( + b, + cmp_u, + cmp_v, + *c_in, + &carries[..n], + ctrl, + phase, + ); + } else { + let c_in = b.alloc_qubit(); + cmp_lt_phase_conditioned_with_cin(b, cmp_u, cmp_v, c_in, ctrl, phase); + b.free(c_in); + } +} + +fn dialog_gcd_cmp_lt_phase_conditioned_hosted( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + phase: BitId, + borrowed: Option<&[QubitId]>, +) { + let n = u.len(); + assert_eq!(v.len(), n); + assert!(n > 0); + let need = n + 1; + let avail = borrowed.map_or(0, <[QubitId]>::len); + if dialog_gcd_partial_host_comparator_enabled() && avail > 0 && avail < need { + let borrowed = borrowed.expect("avail > 0"); + let owned = b.alloc_qubits(need - avail); + let mut clean = Vec::with_capacity(need); + clean.extend_from_slice(borrowed); + clean.extend_from_slice(&owned); + let (c_in, carries) = clean.split_first().expect("need >= 1"); + cmp_lt_phase_conditioned_borrowed_carries( + b, + u, + v, + *c_in, + &carries[..n], + ctrl, + phase, + ); + b.free_vec(&owned); + } else if let Some(borrowed) = borrowed.filter(|slice| slice.len() >= need) { + let (c_in, carries) = borrowed.split_first().expect("borrowed len >= n + 1"); + cmp_lt_phase_conditioned_borrowed_carries( + b, + u, + v, + *c_in, + &carries[..n], + ctrl, + phase, + ); + } else { + let c_in = b.alloc_qubit(); + cmp_lt_phase_conditioned_with_cin(b, u, v, c_in, ctrl, phase); + b.free(c_in); + } +} + +pub(crate) fn dialog_gcd_partial_host_comparator_enabled() -> bool { + std::env::var("DIALOG_GCD_PARTIAL_HOST_COMPARATOR") + .ok() + .as_deref() + != Some("0") +} + +pub(crate) fn dialog_gcd_shift_right_assuming_even(b: &mut B, v: &[QubitId]) { + assert!(!v.is_empty()); + for i in 0..v.len() - 1 { + b.swap(v[i], v[i + 1]); + } +} + +pub(crate) fn dialog_gcd_unshift_right_assuming_even(b: &mut B, v: &[QubitId]) { + assert!(!v.is_empty()); + for i in (0..v.len() - 1).rev() { + b.swap(v[i], v[i + 1]); + } +} + +pub(crate) fn dialog_gcd_width_margin() -> f64 { + + std::env::var("DIALOG_GCD_WIDTH_MARGIN") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|m| m.is_finite() && *m >= 0.0 && *m <= N as f64) + .unwrap_or(37.0) +} + +pub(crate) fn dialog_gcd_width_slope() -> f64 { + + std::env::var("DIALOG_GCD_WIDTH_SLOPE_X1000") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|s| s.is_finite() && *s > 0.0 && *s <= 4000.0) + .map(|s| s / 1000.0) + .unwrap_or(0.5 * 1.415) +} + +pub(crate) fn dialog_gcd_tobitvector_active_width(step: usize) -> usize { + if !dialog_gcd_raw_tobitvector_variable_width_enabled() { + return N; + } + let ideal = N as f64 - (step as f64) * dialog_gcd_width_slope() + dialog_gcd_width_margin(); + let rounded = ((ideal.max(1.0) / 2.0).ceil() as usize) * 2; + rounded + .saturating_add(dialog_gcd_width_step_bump(step)) + .clamp(1, N) +} + +fn dialog_gcd_step_map_value(env: &str, step: usize) -> usize { + let Ok(map) = std::env::var(env) else { + return 0; + }; + map.split(',') + .filter_map(|entry| { + let (s, value) = entry.trim().split_once(':')?; + Some(( + s.trim().parse::().ok()?, + value.trim().parse::().ok()?, + )) + }) + .filter_map(|(s, value)| (s == step).then_some(value)) + .sum() +} + +fn dialog_gcd_step_map_override(env: &str, step: usize) -> Option { + let map = std::env::var(env).ok()?; + map.split(',').rev().find_map(|entry| { + let (raw_step, raw_value) = entry.trim().split_once(':')?; + if raw_step.trim().parse::().ok()? != step { + return None; + } + raw_value.trim().parse::().ok() + }) +} + +pub(crate) fn dialog_gcd_width_step_bump(step: usize) -> usize { + dialog_gcd_step_map_value("DIALOG_GCD_WIDTH_STEP_BUMPS", step) +} + +pub(crate) fn dialog_gcd_body_step_giveback(step: usize) -> usize { + dialog_gcd_step_map_value("DIALOG_GCD_BODY_STEP_GIVEBACKS", step) +} + +pub(crate) fn dialog_gcd_fused_fold_carry_trunc_window( + step: Option, +) -> Option { + step.and_then(|step| { + dialog_gcd_step_map_override("DIALOG_GCD_FOLD_CARRY_TRUNC_STEP_WINDOWS", step) + }) + .filter(|&window| window > 0) + .or_else(fold_only_carry_trunc_window) + .or_else(double_carry_trunc_window) +} + +pub(crate) fn dialog_gcd_body_carry_band_trim(step: usize) -> Option { + let trims = std::env::var("DIALOG_GCD_BODY_CARRY_BAND_TRIMS").ok()?; + if trims.trim().is_empty() { + return None; + } + let trims: Vec = trims + .split(',') + .filter_map(|s| s.trim().parse::().ok()) + .collect(); + if trims.is_empty() { + return None; + } + let iters = dialog_gcd_active_iterations().max(1); + let band_size = ((iters + trims.len() - 1) / trims.len()).max(1); + let band = (step / band_size).min(trims.len() - 1); + Some(trims[band]) +} + +pub(crate) fn dialog_gcd_tobitvector_cswap_width(active_width: usize, step: usize) -> usize { + if std::env::var("DIALOG_GCD_TOBITVECTOR_CSWAP_BODY_TRIM") + .ok() + .as_deref() + == Some("1") + { + dialog_gcd_body_carry_trunc_width(active_width, step).min(active_width) + } else { + active_width + } +} + +pub(crate) fn dialog_gcd_tobitvector_shift_width(active_width: usize, step: usize) -> usize { + if std::env::var("DIALOG_GCD_TOBITVECTOR_SHIFT_BODY_TRIM") + .ok() + .as_deref() + == Some("1") + { + dialog_gcd_body_carry_trunc_width(active_width, step).min(active_width) + } else { + active_width + } +} + +pub(crate) fn dialog_gcd_body_carry_trunc_width(active_width: usize, step: usize) -> usize { + let mut w = dialog_gcd_body_carry_band_trim(step).unwrap_or_else(|| { + std::env::var("DIALOG_GCD_BODY_CARRY_TRUNC_W") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0) + }); + if dialog_gcd_trio_width_notch_enabled() && step == dialog_gcd_trio_width_notch_step() { + w = w.saturating_add(dialog_gcd_trio_width_notch_extra()); + } + + if dialog_gcd_binder_notch_steps().contains(&step) { + w = w.saturating_add(dialog_gcd_binder_notch_extra()); + } + w = w.saturating_add(dialog_gcd_binder_notch_map_extra(step)); + w = w.saturating_sub(dialog_gcd_body_step_giveback(step)); + active_width.saturating_sub(w).max(2) +} + +pub(crate) fn dialog_gcd_vented_body_band_trim_enabled() -> bool { + std::env::var("DIALOG_GCD_VENTED_BODY_BAND_TRIM").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_vented_body_width(n: usize, step: usize) -> usize { + if !dialog_gcd_vented_body_band_trim_enabled() { + return n; + } + if let Some(u) = std::env::var("DIALOG_GCD_VENTED_BODY_UNIFORM_TRIM") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&u| u > 0) + { + return n.saturating_sub(u).max(2); + } + let mut w = dialog_gcd_body_carry_trunc_width(n, step).min(n).max(2); + + if let Some(cap) = std::env::var("DIALOG_GCD_VENTED_BODY_TRIM_CAP") + .ok() + .and_then(|s| s.parse::().ok()) + { + w = w.max(n.saturating_sub(cap)).min(n); + } + w +} + +pub(crate) fn dialog_gcd_vented_body_odd_lowbit_enabled() -> bool { + std::env::var("DIALOG_GCD_VENTED_BODY_ODD_LOWBIT").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_binder_notch_steps() -> Vec { + std::env::var("DIALOG_GCD_BINDER_NOTCH_STEPS") + .ok() + .map(|s| { + s.split(',') + .filter_map(|t| t.trim().parse::().ok()) + .collect() + }) + .unwrap_or_default() +} + +pub(crate) fn dialog_gcd_binder_notch_extra() -> usize { + std::env::var("DIALOG_GCD_BINDER_NOTCH_EXTRA") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(2) +} + +pub(crate) fn dialog_gcd_binder_notch_map_extra(step: usize) -> usize { + let Ok(map) = std::env::var("DIALOG_GCD_BINDER_NOTCH_MAP") else { + return 0; + }; + map.split(',') + .filter_map(|entry| { + let (s, extra) = entry.trim().split_once(':')?; + Some(( + s.trim().parse::().ok()?, + extra.trim().parse::().ok()?, + )) + }) + .filter_map(|(s, extra)| (s == step).then_some(extra)) + .sum() +} + +pub(crate) fn dialog_gcd_trio_width_notch_enabled() -> bool { + + std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH").ok().as_deref() != Some("0") +} + +pub(crate) fn dialog_gcd_trio_width_notch_step() -> usize { + std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH_STEP") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(11) +} + +pub(crate) fn dialog_gcd_trio_width_notch_extra() -> usize { + std::env::var("DIALOG_GCD_TRIO_WIDTH_NOTCH_EXTRA") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(2) +} + +pub(crate) fn dialog_gcd_host_gated_enabled() -> bool { + + std::env::var("DIALOG_GCD_HOST_GATED").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_body_host_cin_enabled() -> bool { + + std::env::var("DIALOG_GCD_BODY_HOST_CIN").ok().as_deref() == Some("1") +} + +pub(crate) fn dialog_gcd_selected_body_nocin_enabled() -> bool { + + matches!( + std::env::var("DIALOG_GCD_SELECTED_BODY_NOCIN").ok().as_deref(), + Some("1") | Some("2") + ) +} + +pub(crate) fn dialog_gcd_selected_body_nocin_keep_pool() -> bool { + std::env::var("DIALOG_GCD_SELECTED_BODY_NOCIN").ok().as_deref() == Some("2") +} + +pub(crate) fn dialog_gcd_selected_body_stream_suffix_bits(step: usize, body_len: usize) -> usize { + let Ok(map) = std::env::var("DIALOG_GCD_SELECTED_BODY_STREAM_SUFFIX_MAP") else { + return 0; + }; + map.split(',') + .find_map(|entry| { + let (entry_step, entry_bits) = entry.trim().split_once(':')?; + let entry_step = entry_step.parse::().ok()?; + let entry_bits = entry_bits.parse::().ok()?; + (entry_step == step).then_some(entry_bits) + }) + .unwrap_or(0) + .min(body_len.saturating_sub(1)) +} + +pub(crate) fn dialog_gcd_selected_body_stream_top_enabled(step: usize, body_len: usize) -> bool { + dialog_gcd_selected_body_stream_suffix_bits(step, body_len) == 1 +} + +pub(crate) fn dialog_gcd_selected_body_stream_topclean_bits( + step: usize, + prefix_len: usize, +) -> usize { + if prefix_len <= 1 { + return 0; + } + let global = std::env::var("DIALOG_GCD_SELECTED_BODY_STREAM_TOPCLEAN") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(0); + let mapped = dialog_gcd_step_map_value("DIALOG_GCD_SELECTED_BODY_STREAM_TOPCLEAN_MAP", step); + global.max(mapped).min(prefix_len - 1) +} + +pub(crate) fn dialog_gcd_late_borrow_uv_high_enabled() -> bool { + std::env::var("DIALOG_GCD_LATE_BORROW_UV_HIGH") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_pick_borrow_slice<'a>( + future: Option<&'a [QubitId]>, + u: &'a [QubitId], + active_width: usize, +) -> Option<&'a [QubitId]> { + if dialog_gcd_late_borrow_uv_high_enabled() && active_width >= 1 { + let want = 2 * active_width - 1; + let short = future.map_or(true, |s| s.len() < want); + if short && u.len() >= active_width + want { + return Some(&u[active_width..active_width + want]); + } + } + future +} + +pub(crate) fn dialog_gcd_controlled_sub_selected( + b: &mut B, + subtrahend: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + borrowed_carries: Option<&[QubitId]>, + step: usize, +) { + assert_eq!(subtrahend.len(), acc.len()); + assert!(!subtrahend.is_empty()); + if dialog_gcd_raw_tobitvector_materialized_sub_enabled() { + let n = subtrahend.len(); + let body_w = dialog_gcd_body_carry_trunc_width(n, step); + let odd_lowbit_fast = dialog_gcd_odd_u_lowbit_fastpath_enabled(); + let body_start = if odd_lowbit_fast { 1 } else { 0 }; + let body_len = body_w.saturating_sub(body_start); + let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); + let nocin_need = if stream_suffix >= 2 + && !dialog_gcd_selected_body_nocin_keep_pool() + { + 2 * (body_len - stream_suffix) + 1 + } else if dialog_gcd_selected_body_stream_top_enabled(step, body_len) + && !dialog_gcd_selected_body_nocin_keep_pool() + && body_len >= 2 + { + 2 * (body_len - 1) + } else if dialog_gcd_selected_body_nocin_keep_pool() { + + (n + body_len).max(2 * body_len - 1) + } else { + 2 * body_len - 1 + }; + let nocin = dialog_gcd_selected_body_nocin_enabled() + && body_start >= 1 + && body_len >= 1 + && borrowed_carries.map_or(false, |c| c.len() >= nocin_need); + if nocin { + if stream_suffix >= 2 { + let prefix_len = body_len - stream_suffix; + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, rest) = c.split_at(prefix_len); + let (gated, rest) = rest.split_at(prefix_len); + let scratch = rest[0]; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); + for j in 0..prefix_len { + b.ccx(ctrl, subtrahend[body_start + j], gated[j]); + } + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); + cuccaro_sub_fast_prefix_ctrl_suffix_no_cin( + b, + gated, + &subtrahend[body_start + prefix_len..body_w], + &acc[body_start..body_w], + ctrl, + carries, + scratch, + ); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); + for j in 0..prefix_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, subtrahend[body_start + j], m); + } + return; + } + if dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 { + let lower_len = body_len - 1; + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, gated) = c.split_at(lower_len); + let gated = &gated[..lower_len]; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); + for j in 0..lower_len { + b.ccx(ctrl, subtrahend[body_start + j], gated[j]); + } + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); + b.ccx(ctrl, subtrahend[body_w - 1], acc[body_w - 1]); + cuccaro_sub_fast_low_to_ext_borrowed_carries_no_cin( + b, + gated, + &acc[body_start..body_w], + carries, + ); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); + for j in 0..lower_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, subtrahend[body_start + j], m); + } + return; + } + + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, gated): (&[QubitId], &[QubitId]) = + if dialog_gcd_selected_body_nocin_keep_pool() { + + let carry_need = body_len - 1; + (&c[..carry_need], &c[n..n + body_len]) + } else { + let carry_need = body_len - 1; + (&c[..carry_need], &c[carry_need..carry_need + body_len]) + }; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); + for j in 0..body_len { + b.ccx(ctrl, subtrahend[body_start + j], gated[j]); + } + + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); + cuccaro_sub_fast_borrowed_carries_no_cin( + b, + gated, + &acc[body_start..body_w], + carries, + ); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); + for j in 0..body_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, subtrahend[body_start + j], m); + } + return; + } + + let gated_host: Option<&[QubitId]> = if dialog_gcd_host_gated_enabled() { + borrowed_carries.and_then(|c| { + if c.len() >= 2 * n - 1 { + Some(&c[n - 1..2 * n - 1]) + } else { + None + } + }) + } else { + None + }; + let mut gated_owned: Vec = Vec::new(); + let gated: &[QubitId] = match gated_host { + Some(h) => h, + None => { + gated_owned = b.alloc_qubits(n); + gated_owned.as_slice() + } + }; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_load"); + for i in body_start..body_w { + b.ccx(ctrl, subtrahend[i], gated[i]); + } + if odd_lowbit_fast { + + b.cx(ctrl, acc[0]); + } + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_body"); + if body_start < body_w { + if let Some(carries) = + borrowed_carries.filter(|carries| carries.len() >= body_len.saturating_sub(1)) + { + if dialog_gcd_body_host_cin_enabled() && body_start >= 1 { + + cuccaro_sub_fast_borrowed_carries( + b, + &gated[body_start..body_w], + &acc[body_start..body_w], + gated[0], + &carries[..body_len.saturating_sub(1)], + ); + } else { + sub_nbit_qq_fast_borrowed_carries( + b, + &gated[body_start..body_w], + &acc[body_start..body_w], + &carries[..body_len.saturating_sub(1)], + ); + } + } else { + sub_nbit_qq_fast(b, &gated[body_start..body_w], &acc[body_start..body_w]); + } + } + b.set_phase("dialog_gcd_raw_tobitvector_materialized_sub_clear"); + for i in body_start..body_w { + let m = b.alloc_bit(); + b.hmr(gated[i], m); + b.cz_if(ctrl, subtrahend[i], m); + } + if gated_host.is_none() { + b.free_vec(&gated_owned); + } + } else { + let n = subtrahend.len(); + if dialog_gcd_ctrl_body_vented_enabled() { + if let Some(vents) = + borrowed_carries.filter(|c| n >= 2 && c.len() >= n - 1) + { + let bw = dialog_gcd_vented_body_width(n, step); + if dialog_gcd_vented_body_odd_lowbit_enabled() + && dialog_gcd_odd_u_lowbit_fastpath_enabled() + && bw >= 3 + { + + b.cx(ctrl, acc[0]); + cuccaro_sub_ctrl_vented(b, &subtrahend[1..bw], &acc[1..bw], ctrl, &vents[..bw - 2]); + } else { + cuccaro_sub_ctrl_vented(b, &subtrahend[..bw], &acc[..bw], ctrl, &vents[..bw - 1]); + } + return; + } + } + cucc_sub_ctrl_lowq(b, subtrahend, acc, ctrl); + } +} + +pub(crate) fn dialog_gcd_controlled_add_selected( + b: &mut B, + addend: &[QubitId], + acc: &[QubitId], + ctrl: QubitId, + borrowed_carries: Option<&[QubitId]>, + step: usize, +) { + assert_eq!(addend.len(), acc.len()); + assert!(!addend.is_empty()); + if dialog_gcd_raw_tobitvector_materialized_sub_enabled() { + let n = addend.len(); + let body_w = dialog_gcd_body_carry_trunc_width(n, step); + let odd_lowbit_fast = dialog_gcd_odd_u_lowbit_fastpath_enabled(); + let body_start = if odd_lowbit_fast { 1 } else { 0 }; + let body_len = body_w.saturating_sub(body_start); + let stream_suffix = dialog_gcd_selected_body_stream_suffix_bits(step, body_len); + let nocin_need = if stream_suffix >= 2 + && !dialog_gcd_selected_body_nocin_keep_pool() + { + 2 * (body_len - stream_suffix) + 1 + } else if dialog_gcd_selected_body_stream_top_enabled(step, body_len) + && !dialog_gcd_selected_body_nocin_keep_pool() + && body_len >= 2 + { + 2 * (body_len - 1) + } else if dialog_gcd_selected_body_nocin_keep_pool() { + + (n + body_len).max(2 * body_len - 1) + } else { + 2 * body_len - 1 + }; + let nocin = dialog_gcd_selected_body_nocin_enabled() + && body_start >= 1 + && body_len >= 1 + && borrowed_carries.map_or(false, |c| c.len() >= nocin_need); + if nocin { + if stream_suffix >= 2 { + let prefix_len = body_len - stream_suffix; + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, rest) = c.split_at(prefix_len); + let (gated, rest) = rest.split_at(prefix_len); + let scratch = rest[0]; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); + for j in 0..prefix_len { + b.ccx(ctrl, addend[body_start + j], gated[j]); + } + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); + cuccaro_add_fast_prefix_ctrl_suffix_no_cin( + b, + gated, + &addend[body_start + prefix_len..body_w], + &acc[body_start..body_w], + ctrl, + carries, + scratch, + ); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); + for j in 0..prefix_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, addend[body_start + j], m); + } + return; + } + if dialog_gcd_selected_body_stream_top_enabled(step, body_len) && body_len >= 2 { + let lower_len = body_len - 1; + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, gated) = c.split_at(lower_len); + let gated = &gated[..lower_len]; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); + for j in 0..lower_len { + b.ccx(ctrl, addend[body_start + j], gated[j]); + } + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); + cuccaro_add_fast_low_to_ext_borrowed_carries_no_cin( + b, + gated, + &acc[body_start..body_w], + carries, + ); + b.ccx(ctrl, addend[body_w - 1], acc[body_w - 1]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); + for j in 0..lower_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, addend[body_start + j], m); + } + return; + } + + let c = borrowed_carries.expect("nocin requires borrowed carries"); + let (carries, gated): (&[QubitId], &[QubitId]) = + if dialog_gcd_selected_body_nocin_keep_pool() { + let carry_need = body_len - 1; + (&c[..carry_need], &c[n..n + body_len]) + } else { + let carry_need = body_len - 1; + (&c[..carry_need], &c[carry_need..carry_need + body_len]) + }; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); + for j in 0..body_len { + b.ccx(ctrl, addend[body_start + j], gated[j]); + } + + b.cx(ctrl, acc[0]); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); + cuccaro_add_fast_borrowed_carries_no_cin( + b, + gated, + &acc[body_start..body_w], + carries, + ); + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); + for j in 0..body_len { + let m = b.alloc_bit(); + b.hmr(gated[j], m); + b.cz_if(ctrl, addend[body_start + j], m); + } + return; + } + let gated_host: Option<&[QubitId]> = if dialog_gcd_host_gated_enabled() { + borrowed_carries.and_then(|c| { + if c.len() >= 2 * n - 1 { + Some(&c[n - 1..2 * n - 1]) + } else { + None + } + }) + } else { + None + }; + let mut gated_owned: Vec = Vec::new(); + let gated: &[QubitId] = match gated_host { + Some(h) => h, + None => { + gated_owned = b.alloc_qubits(n); + gated_owned.as_slice() + } + }; + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_load"); + for i in body_start..body_w { + b.ccx(ctrl, addend[i], gated[i]); + } + if odd_lowbit_fast { + + b.cx(ctrl, acc[0]); + } + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_body"); + if body_start < body_w { + if let Some(carries) = + borrowed_carries.filter(|carries| carries.len() >= body_len.saturating_sub(1)) + { + if dialog_gcd_body_host_cin_enabled() && body_start >= 1 { + + cuccaro_add_fast_borrowed_carries( + b, + &gated[body_start..body_w], + &acc[body_start..body_w], + gated[0], + &carries[..body_len.saturating_sub(1)], + ); + } else { + add_nbit_qq_fast_borrowed_carries( + b, + &gated[body_start..body_w], + &acc[body_start..body_w], + &carries[..body_len.saturating_sub(1)], + ); + } + } else { + add_nbit_qq_fast(b, &gated[body_start..body_w], &acc[body_start..body_w]); + } + } + b.set_phase("dialog_gcd_raw_tobitvector_materialized_add_clear"); + for i in body_start..body_w { + let m = b.alloc_bit(); + b.hmr(gated[i], m); + b.cz_if(ctrl, addend[i], m); + } + if gated_host.is_none() { + b.free_vec(&gated_owned); + } + } else { + let n = addend.len(); + if dialog_gcd_ctrl_body_vented_enabled() { + if let Some(vents) = + borrowed_carries.filter(|c| n >= 2 && c.len() >= n - 1) + { + let bw = dialog_gcd_vented_body_width(n, step); + if dialog_gcd_vented_body_odd_lowbit_enabled() + && dialog_gcd_odd_u_lowbit_fastpath_enabled() + && bw >= 3 + { + + b.cx(ctrl, acc[0]); + cuccaro_add_ctrl_vented(b, &addend[1..bw], &acc[1..bw], ctrl, &vents[..bw - 2]); + } else { + cuccaro_add_ctrl_vented(b, &addend[..bw], &acc[..bw], ctrl, &vents[..bw - 1]); + } + return; + } + } + cucc_add_ctrl_lowq(b, addend, acc, ctrl); + } +} + +pub(crate) fn dialog_gcd_future_log_carry_slice( + dialog_log: &[QubitId], + step: usize, + active_width: usize, +) -> Option<&[QubitId]> { + if !dialog_gcd_raw_tobitvector_borrow_future_log_carries_enabled() { + return None; + } + let carry_need = active_width.saturating_sub(1); + let want = if dialog_gcd_host_gated_enabled() { + 2 * active_width - 1 + } else { + carry_need + }; + let start = 2 * (step + 1); + dialog_log + .get(start..) + .filter(|future| future.len() >= carry_need) + .map(|future| &future[..future.len().min(want)]) +} + +pub(crate) fn emit_dialog_gcd_raw_tobitvector_steps( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + dialog_log: &[QubitId], +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); + + for step in 0..dialog_gcd_active_iterations() { + let b0 = dialog_log[2 * step]; + let b0_and_b1 = dialog_log[2 * step + 1]; + let cmp = b.alloc_qubit(); + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + b.set_phase("dialog_gcd_raw_tobitvector_branch_bits"); + b.cx(v[0], b0); + if dialog_gcd_fused_branch_bits_enabled() { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } else { + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + } + b.free(cmp); + + b.set_phase("dialog_gcd_raw_tobitvector_cswap"); + for (i, (&ui, &vi)) in u_active.iter().zip(v_active.iter()).enumerate() { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_raw_tobitvector_subtract"); + let borrowed_carries = dialog_gcd_future_log_carry_slice(dialog_log, step, active_width); + dialog_gcd_controlled_sub_selected(b, u_active, v_active, b0, borrowed_carries, step); + + b.set_phase("dialog_gcd_raw_tobitvector_shift"); + dialog_gcd_shift_right_assuming_even(b, v_active); + } +} + +pub(crate) fn emit_dialog_gcd_raw_tobitvector_steps_reverse( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + dialog_log: &[QubitId], +) { + assert_eq!(u.len(), N); + assert_eq!(v.len(), N); + assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); + + for step in (0..dialog_gcd_active_iterations()).rev() { + let b0 = dialog_log[2 * step]; + let b0_and_b1 = dialog_log[2 * step + 1]; + let cmp = b.alloc_qubit(); + let active_width = dialog_gcd_tobitvector_active_width(step); + let u_active = &u[..active_width]; + let v_active = &v[..active_width]; + let compare_bits = dialog_gcd_compare_bits_for_step(step, active_width); + + b.set_phase("dialog_gcd_raw_tobitvector_reverse_unshift"); + dialog_gcd_unshift_right_assuming_even(b, v_active); + + b.set_phase("dialog_gcd_raw_tobitvector_reverse_add"); + let borrowed_carries = dialog_gcd_future_log_carry_slice(dialog_log, step, active_width); + dialog_gcd_controlled_add_selected(b, u_active, v_active, b0, borrowed_carries, step); + + b.set_phase("dialog_gcd_raw_tobitvector_reverse_cswap"); + for (i, (&ui, &vi)) in u_active.iter().zip(v_active.iter()).enumerate() { + if i == 0 && dialog_gcd_odd_u_lowbit_fastpath_enabled() { + continue; + } + cswap(b, b0_and_b1, ui, vi); + } + + b.set_phase("dialog_gcd_raw_tobitvector_reverse_branch_bits"); + if dialog_gcd_fused_branch_bits_enabled() { + dialog_gcd_ccx_cmp_gt_truncated_into_width( + b, + u_active, + v_active, + b0, + b0_and_b1, + compare_bits, + ); + } else { + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + b.ccx(b0, cmp, b0_and_b1); + dialog_gcd_cmp_gt_truncated_into_width(b, u_active, v_active, cmp, compare_bits); + } + b.free(cmp); + b.cx(v[0], b0); + } +} + +pub(crate) fn dialog_gcd_cmod_add_pseudomersenne_lowq( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let a_ovf = b.alloc_qubit(); + let mut a_ext = a.to_vec(); + a_ext.push(a_ovf); + let c_in = b.alloc_qubit(); + let scratch = b.alloc_qubit(); + + b.set_phase("dialog_gcd_direct_special_cadd_raw_sum"); + cuccaro_add_ctrl_lowq(b, &a_ext, &acc_ext, ctrl, c_in, scratch); + b.free(scratch); + b.free(c_in); + b.free(a_ovf); + + b.set_phase("dialog_gcd_direct_special_overflow_fold"); + cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + + b.set_phase("dialog_gcd_direct_special_overflow_clean"); + cmp_lt_into(b, acc, a, acc_ovf); + unext_reg(b, acc_ovf); +} + +pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, +) { + dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, acc, a, ctrl, p, None); +} + +pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_at_step( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + step: Option, +) { + dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + acc, + a, + ctrl, + p, + &[], + step, + ); +} + +pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + clean_scratch: &[QubitId], +) { + dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + acc, + a, + ctrl, + p, + clean_scratch, + None, + ); +} + +pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_with_clean_scratch_at_step( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + clean_scratch: &[QubitId], + step: Option, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + if let Some(blocks) = dialog_gcd_apply_chunked_f_blocks() + .filter(|_| dialog_gcd_raw_apply_truncated_clean_enabled()) + { + dialog_gcd_cmod_add_materialized_pseudomersenne_chunked( + b, + acc, + a, + ctrl, + p, + blocks, + clean_scratch, + step, + ); + return; + } + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + let f = b.alloc_qubits(N); + b.set_phase("dialog_gcd_materialized_special_load_addend"); + for i in 0..N { + b.ccx(ctrl, a[i], f[i]); + } + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let c_in = b.alloc_qubit(); + + b.set_phase("dialog_gcd_materialized_special_raw_sum"); + if let Some(w) = dialog_gcd_apply_window_blocks() { + cuccaro_add_fast_windowed_low_to_ext(b, &f, &acc_ext, c_in, w); + } else { + let f_ovf = b.alloc_qubit(); + let mut f_ext = f.clone(); + f_ext.push(f_ovf); + cuccaro_add_fast(b, &f_ext, &acc_ext, c_in); + b.free(f_ovf); + } + b.free(c_in); + + b.set_phase("dialog_gcd_materialized_special_overflow_fold"); + if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { + cadd_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); + } else { + cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_overflow_clean"); + if dialog_gcd_raw_apply_truncated_clean_enabled() { + let compare_start = N - dialog_gcd_special_overflow_clean_compare_bits(step); + cmp_lt_into_fast(b, &acc[compare_start..], &f[compare_start..], acc_ovf); + } else { + cmp_lt_into(b, acc, &f, acc_ovf); + } + unext_reg(b, acc_ovf); + + b.set_phase("dialog_gcd_materialized_special_clear_addend"); + for i in 0..N { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} + +pub(crate) fn dialog_gcd_measured_apply_sub_enabled() -> bool { + std::env::var("DIALOG_GCD_MEASURED_APPLY_SUB") + .ok() + .as_deref() + == Some("1") +} + +pub(crate) fn dialog_gcd_apply_window_blocks() -> Option { + std::env::var("DIALOG_GCD_APPLY_WINDOW_BLOCKS") + .ok() + .and_then(|s| s.parse::().ok()) + .filter(|&w| w >= 2) +} + +fn dialog_gcd_clean_truncated_underflow_with_borrowed( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + acc_ovf: QubitId, + step: Option, + borrowed: Option<&[QubitId]>, +) { + let compare_start = N - dialog_gcd_special_underflow_clean_compare_bits(step); + for &q in &a[compare_start..] { + b.x(q); + } + if dialog_gcd_special_clean_conditional_replay_enabled() { + let phase = b.alloc_bit(); + b.hmr(acc_ovf, phase); + b.z_if(ctrl, phase); + dialog_gcd_cmp_lt_phase_conditioned_hosted( + b, + &acc[compare_start..], + &a[compare_start..], + ctrl, + phase, + borrowed, + ); + } else { + b.cx(ctrl, acc_ovf); + ccx_cmp_lt_into_fast(b, &acc[compare_start..], &a[compare_start..], ctrl, acc_ovf); + } + for &q in &a[compare_start..] { + b.x(q); + } +} + +pub(crate) fn dialog_gcd_clean_truncated_underflow( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + acc_ovf: QubitId, + step: Option, +) { + dialog_gcd_clean_truncated_underflow_with_borrowed( + b, + acc, + a, + ctrl, + acc_ovf, + step, + None, + ); +} + +pub(crate) fn dialog_gcd_special_underflow_clean_compare_bits(step: Option) -> usize { + dialog_gcd_special_clean_compare_bits_from_env( + step, + "DIALOG_GCD_SPECIAL_UNDERFLOW_CLEAN_STEP_BITS", + ) +} + +pub(crate) fn dialog_gcd_special_overflow_clean_compare_bits(step: Option) -> usize { + dialog_gcd_special_clean_compare_bits_from_env( + step, + "DIALOG_GCD_SPECIAL_OVERFLOW_CLEAN_STEP_BITS", + ) +} + +pub(crate) fn dialog_gcd_special_fold_carry_trunc_window( + step: Option, +) -> Option { + step.and_then(|step| { + dialog_gcd_step_map_override( + "DIALOG_GCD_SPECIAL_FOLD_CARRY_TRUNC_STEP_WINDOWS", + step, + ) + }) + .filter(|&window| window > 0) + .or_else(fold_carry_trunc_window) +} + +pub(crate) fn dialog_gcd_special_clean_compare_bits_from_env( + step: Option, + env_name: &str, +) -> usize { + let default_bits = dialog_gcd_apply_clean_compare_bits(); + let Some(step) = step else { + return default_bits; + }; + let Ok(spec) = std::env::var(env_name) else { + return default_bits; + }; + for item in spec.split(',') { + let Some((raw_step, raw_bits)) = item.trim().split_once(':') else { + continue; + }; + if raw_step.trim().parse::().ok() != Some(step) { + continue; + } + if let Ok(bits) = raw_bits.trim().parse::() { + if (1..=N).contains(&bits) { + return bits; + } + } + } + default_bits +} + +pub(crate) fn dialog_gcd_load_controlled_slice( + b: &mut B, + ctrl: QubitId, + source: &[QubitId], + lo: usize, + hi: usize, +) -> Vec { + assert!(lo <= hi); + assert!(hi <= source.len()); + let out = b.alloc_qubits(hi - lo); + for (i, &q) in source[lo..hi].iter().enumerate() { + b.ccx(ctrl, q, out[i]); + } + out +} + +pub(crate) fn dialog_gcd_clear_controlled_slice_hmr( + b: &mut B, + ctrl: QubitId, + source: &[QubitId], + lo: usize, + loaded: &[QubitId], +) { + assert!(lo + loaded.len() <= source.len()); + for (i, &q) in loaded.iter().enumerate() { + let m = b.alloc_bit(); + b.hmr(q, m); + b.cz_if(ctrl, source[lo + i], m); + } +} + +pub(crate) fn dialog_gcd_chunk_hi(blocks: usize, block: usize, ext_n: usize) -> usize { + if let Some(cuts) = dialog_gcd_apply_chunked_f_cuts() { + assert_eq!( + cuts.len() + 1, + blocks, + "DIALOG_GCD_APPLY_CHUNKED_F_CUTS must contain blocks-1 cuts" + ); + assert!( + cuts.first().is_some_and(|&cut| cut > 0) + && cuts.windows(2).all(|pair| pair[0] < pair[1]) + && cuts.last().is_some_and(|&cut| cut < ext_n), + "DIALOG_GCD_APPLY_CHUNKED_F_CUTS must be strictly increasing in 1..{ext_n}: {cuts:?}" + ); + if block < cuts.len() { + return cuts[block]; + } + } + if blocks == 4 && dialog_gcd_apply_chunked_f_custom4_enabled() { + let cuts = [ + dialog_gcd_apply_chunked_f_cut().unwrap_or(ext_n / 4), + dialog_gcd_apply_chunked_f_cut2().unwrap_or(ext_n / 2), + dialog_gcd_apply_chunked_f_cut3().unwrap_or(3 * ext_n / 4), + ]; + assert!( + cuts[0] < cuts[1] && cuts[1] < cuts[2] && cuts[2] < ext_n, + "custom four-chunk apply boundaries must be strictly increasing and below {ext_n}: {cuts:?}" + ); + if block < cuts.len() { + return cuts[block]; + } + } + if blocks == 5 && dialog_gcd_apply_chunked_f_custom5_enabled() { + let cuts = [ + dialog_gcd_apply_chunked_f_cut().unwrap_or(ext_n / 5), + dialog_gcd_apply_chunked_f_cut2().unwrap_or((2 * ext_n) / 5), + dialog_gcd_apply_chunked_f_cut3().unwrap_or((3 * ext_n) / 5), + dialog_gcd_apply_chunked_f_cut4().unwrap_or((4 * ext_n) / 5), + ]; + assert!( + cuts[0] < cuts[1] && cuts[1] < cuts[2] && cuts[2] < cuts[3] && cuts[3] < ext_n, + "custom five-chunk apply boundaries must be strictly increasing and below {ext_n}: {cuts:?}" + ); + if block < cuts.len() { + return cuts[block]; + } + } + if block == 0 && blocks <= 3 { + return dialog_gcd_apply_chunked_f_cut() + .unwrap_or(ext_n / 2) + .min(ext_n - 1); + } + if blocks == 3 && block == 1 { + return dialog_gcd_apply_chunked_f_cut2() + .unwrap_or(2 * ext_n / 3) + .min(ext_n - 1); + } + ((block + 1) * ext_n) / blocks +} + +fn dialog_gcd_add_fast_with_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + c_in: QubitId, + borrowed: &[QubitId], +) { + let needed = a.len().saturating_sub(1); + let borrowed = &borrowed[..borrowed.len().min(needed)]; + let owned = b.alloc_qubits(needed - borrowed.len()); + let mut carries = Vec::with_capacity(needed); + carries.extend_from_slice(borrowed); + carries.extend_from_slice(&owned); + cuccaro_add_fast_borrowed_carries(b, a, acc, c_in, &carries); + b.free_vec(&owned); +} + +fn dialog_gcd_sub_fast_with_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc: &[QubitId], + c_in: QubitId, + borrowed: &[QubitId], +) { + let needed = a.len().saturating_sub(1); + let borrowed = &borrowed[..borrowed.len().min(needed)]; + let owned = b.alloc_qubits(needed - borrowed.len()); + let mut carries = Vec::with_capacity(needed); + carries.extend_from_slice(borrowed); + carries.extend_from_slice(&owned); + cuccaro_sub_fast_borrowed_carries(b, a, acc, c_in, &carries); + b.free_vec(&owned); +} + +fn dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + borrowed: &[QubitId], +) { + let needed = a.len(); + let borrowed = &borrowed[..borrowed.len().min(needed)]; + let owned = b.alloc_qubits(needed - borrowed.len()); + let mut carries = Vec::with_capacity(needed); + carries.extend_from_slice(borrowed); + carries.extend_from_slice(&owned); + cuccaro_add_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, &carries); + b.free_vec(&owned); +} + +fn dialog_gcd_add_fast_low_to_ext_with_borrowed_carries_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + borrowed_carries: &[QubitId], + clean_top: usize, +) { + let clean_top = clean_top.min(a.len().saturating_sub(1)); + if clean_top == 0 { + return dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( + b, + a, + acc_ext, + c_in, + borrowed_carries, + ); + } + let needed_carries = a.len() - clean_top; + let borrowed = borrowed_carries.len().min(needed_carries); + let owned = b.alloc_qubits(needed_carries - borrowed); + let mut carries = Vec::with_capacity(needed_carries); + carries.extend_from_slice(&borrowed_carries[..borrowed]); + carries.extend_from_slice(&owned); + cuccaro_add_fast_low_to_ext_borrowed_carries_topclean( + b, + a, + acc_ext, + c_in, + &carries, + clean_top, + ); + b.free_vec(&owned); +} + +fn dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + borrowed: &[QubitId], +) { + let needed = a.len(); + let borrowed = &borrowed[..borrowed.len().min(needed)]; + let owned = b.alloc_qubits(needed - borrowed.len()); + let mut carries = Vec::with_capacity(needed); + carries.extend_from_slice(borrowed); + carries.extend_from_slice(&owned); + cuccaro_sub_fast_low_to_ext_borrowed_carries(b, a, acc_ext, c_in, &carries); + b.free_vec(&owned); +} + +fn dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries_topclean( + b: &mut B, + a: &[QubitId], + acc_ext: &[QubitId], + c_in: QubitId, + borrowed_carries: &[QubitId], + clean_top: usize, +) { + let clean_top = clean_top.min(a.len().saturating_sub(1)); + if clean_top == 0 { + return dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( + b, + a, + acc_ext, + c_in, + borrowed_carries, + ); + } + let needed_carries = a.len() - clean_top; + let borrowed = borrowed_carries.len().min(needed_carries); + let owned = b.alloc_qubits(needed_carries - borrowed); + let mut carries = Vec::with_capacity(needed_carries); + carries.extend_from_slice(&borrowed_carries[..borrowed]); + carries.extend_from_slice(&owned); + cuccaro_sub_fast_low_to_ext_borrowed_carries_topclean( + b, + a, + acc_ext, + c_in, + &carries, + clean_top, + ); + b.free_vec(&owned); +} + +fn dialog_gcd_conditional_boundary_replay( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + targets: &[(QubitId, usize)], +) { + assert!(!targets.is_empty()); + assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); + for index in (0..targets.len()).rev() { + let (target, p) = targets[index]; + let (start, carry_in) = if index == 0 { + (0, c_in) + } else { + (targets[index - 1].1, targets[index - 1].0) + }; + let phase = b.alloc_bit(); + b.hmr(target, phase); + cmp_lt_phase_conditioned_with_cin( + b, + &u[start..p], + &v[start..p], + carry_in, + ctrl, + phase, + ); + } +} + +fn dialog_gcd_conditional_boundary_replay_free_owned( + b: &mut B, + u: &[QubitId], + v: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + targets: &[(QubitId, usize, bool)], +) { + assert!(!targets.is_empty()); + assert!(targets.windows(2).all(|w| w[0].1 < w[1].1)); + for index in (0..targets.len()).rev() { + let (target, p, owned_target) = targets[index]; + let (start, carry_in) = if index == 0 { + (0, c_in) + } else { + (targets[index - 1].1, targets[index - 1].0) + }; + let phase = b.alloc_bit(); + b.hmr(target, phase); + if owned_target { + b.free(target); + } + cmp_lt_phase_conditioned_with_cin( + b, + &u[start..p], + &v[start..p], + carry_in, + ctrl, + phase, + ); + } +} + +fn dialog_gcd_apply_auto_topclean_bits( + active_before_ripple: u32, + source_len: usize, + future_boundary_carries: &[QubitId], +) -> usize { + let Some(target) = dialog_gcd_apply_chunked_f_auto_topclean_target() else { + return 0; + }; + if source_len <= 1 { + return 0; + } + let future_borrowed = future_boundary_carries.len().min(source_len); + let owned_carries_without_topclean = source_len - future_borrowed; + let projected_peak = active_before_ripple as usize + owned_carries_without_topclean; + let needed = projected_peak.saturating_sub(target as usize); + needed + .min(dialog_gcd_apply_chunked_f_auto_topclean_max_bits()) + .min(source_len - 1) +} + +pub(crate) fn dialog_gcd_add_ctrl_chunked_low_to_ext( + b: &mut B, + source: &[QubitId], + acc_ext: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + blocks: usize, + clean_scratch: &[QubitId], +) { + let n = source.len(); + assert_eq!(acc_ext.len(), n + 1); + for (i, &q) in clean_scratch.iter().enumerate() { + assert!(!clean_scratch[..i].contains(&q)); + assert!(!source.contains(&q)); + assert!(!acc_ext.contains(&q)); + assert_ne!(q, ctrl); + assert_ne!(q, c_in); + } + let ext_n = acc_ext.len(); + let blocks = blocks.max(2).min(ext_n); + let mut carry = c_in; + let mut lo = 0usize; + + let implicit_high_zero = dialog_gcd_apply_implicit_high_zero_enabled(); + let zero_host = (!implicit_high_zero) + .then(|| clean_scratch.first().copied()) + .flatten(); + let boundary_hosts = &clean_scratch + [usize::from(!implicit_high_zero && zero_host.is_some())..]; + let mut couts: Vec<(QubitId, usize, bool)> = Vec::new(); + + for blk in 0..blocks { + let hi = dialog_gcd_chunk_hi(blocks, blk, ext_n); + if hi <= lo { + continue; + } + if blk == blocks - 1 || hi == ext_n { + b.set_phase("dialog_gcd_apply_chunk_add_final_load"); + let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo.min(n), n); + b.set_phase("dialog_gcd_apply_chunk_add_final_ripple"); + let final_topclean = dialog_gcd_apply_final_topclean_bits() + .max(dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), &[])); + if final_topclean > 0 { + cuccaro_add_fast_low_to_ext_topclean(b, &f, &acc_ext[lo..hi], carry, final_topclean); + } else if let Some(window_blocks) = dialog_gcd_apply_final_windowed_fast_blocks() { + cuccaro_add_fast_windowed_low_to_ext( + b, + &f, + &acc_ext[lo..hi], + carry, + window_blocks, + ); + } else if dialog_gcd_apply_final_lowq_enabled() { + let zero = b.alloc_qubit(); + let mut f_ext = f.clone(); + f_ext.push(zero); + cuccaro_add(b, &f_ext, &acc_ext[lo..hi], carry); + b.free(zero); + } else { + cuccaro_add_fast_low_to_ext(b, &f, &acc_ext[lo..hi], carry); + } + b.set_phase("dialog_gcd_apply_chunk_add_final_clear"); + dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo.min(n), &f); + b.free_vec(&f); + break; + } + + assert!(hi <= n); + b.set_phase("dialog_gcd_apply_chunk_add_load"); + let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo, hi); + let needs_distinct_zero = + carry == c_in || !dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled(); + let (zero, owned_zero) = if needs_distinct_zero { + zero_host.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)) + } else { + (c_in, false) + }; + let (cout, owned_cout) = boundary_hosts + .get(couts.len()) + .copied() + .map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); + let mut acc_block = acc_ext[lo..hi].to_vec(); + acc_block.push(cout); + let future_boundary_carries = if dialog_gcd_apply_borrow_future_boundary_carries_enabled() { + boundary_hosts.get(couts.len() + 1..).unwrap_or(&[]) + } else { + &[] + }; + let topclean_bits = if implicit_high_zero { + dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), future_boundary_carries) + } else { + 0 + }; + b.set_phase("dialog_gcd_apply_chunk_add_ripple"); + if implicit_high_zero { + if topclean_bits > 0 { + dialog_gcd_add_fast_low_to_ext_with_borrowed_carries_topclean( + b, + &f, + &acc_block, + carry, + future_boundary_carries, + topclean_bits, + ); + } else { + dialog_gcd_add_fast_low_to_ext_with_borrowed_carries( + b, + &f, + &acc_block, + carry, + future_boundary_carries, + ); + } + } else { + let mut a_block = f.clone(); + a_block.push(zero); + dialog_gcd_add_fast_with_borrowed_carries( + b, + &a_block, + &acc_block, + carry, + future_boundary_carries, + ); + } + if owned_zero { + b.free(zero); + } + b.set_phase("dialog_gcd_apply_chunk_add_clear"); + dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo, &f); + b.free_vec(&f); + couts.push((cout, hi, owned_cout)); + carry = cout; + lo = hi; + } + + let mut boundary_replay_freed_owned = false; + if dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() { + if let Some(&(_, p, _)) = couts.last() { + b.set_phase("dialog_gcd_apply_chunk_add_boundary_clear"); + let targets = couts + .iter() + .map(|&(cout, p, _)| (cout, p)) + .collect::>(); + if dialog_gcd_apply_boundary_conditional_replay_enabled() { + if dialog_gcd_apply_boundary_free_owned_during_replay_enabled() { + dialog_gcd_conditional_boundary_replay_free_owned( + b, + &acc_ext[..p], + &source[..p], + ctrl, + c_in, + &couts, + ); + boundary_replay_freed_owned = true; + } else { + dialog_gcd_conditional_boundary_replay( + b, + &acc_ext[..p], + &source[..p], + ctrl, + c_in, + &targets, + ); + } + } else if let Some(split) = dialog_gcd_apply_boundary_split() { + ccx_cmp_lt_into_fast_prefix_targets_split( + b, + &acc_ext[..p], + &source[..p], + ctrl, + &targets, + split.min(p.saturating_sub(1)), + ); + } else { + ccx_cmp_lt_into_fast_prefix_targets(b, &acc_ext[..p], &source[..p], ctrl, &targets); + } + } + } else { + for &(cout, p, _) in couts.iter().rev() { + b.set_phase("dialog_gcd_apply_chunk_add_boundary_clear"); + ccx_cmp_lt_into_fast(b, &acc_ext[..p], &source[..p], ctrl, cout); + } + } + for &(cout, _, owned_cout) in couts.iter().rev() { + if owned_cout && !boundary_replay_freed_owned { + b.free(cout); + } + } +} + +pub(crate) fn dialog_gcd_sub_ctrl_chunked_low_to_ext( + b: &mut B, + source: &[QubitId], + acc_ext: &[QubitId], + ctrl: QubitId, + c_in: QubitId, + blocks: usize, + clean_scratch: &[QubitId], +) { + let n = source.len(); + assert_eq!(acc_ext.len(), n + 1); + for (i, &q) in clean_scratch.iter().enumerate() { + assert!(!clean_scratch[..i].contains(&q)); + assert!(!source.contains(&q)); + assert!(!acc_ext.contains(&q)); + assert_ne!(q, ctrl); + assert_ne!(q, c_in); + } + let ext_n = acc_ext.len(); + let blocks = blocks.max(2).min(ext_n); + let mut borrow = c_in; + let mut lo = 0usize; + let implicit_high_zero = dialog_gcd_apply_implicit_high_zero_enabled(); + let zero_host = (!implicit_high_zero) + .then(|| clean_scratch.first().copied()) + .flatten(); + let boundary_hosts = &clean_scratch + [usize::from(!implicit_high_zero && zero_host.is_some())..]; + let mut bouts: Vec<(QubitId, usize, bool)> = Vec::new(); + + for blk in 0..blocks { + let hi = dialog_gcd_chunk_hi(blocks, blk, ext_n); + if hi <= lo { + continue; + } + if blk == blocks - 1 || hi == ext_n { + b.set_phase("dialog_gcd_apply_chunk_sub_final_load"); + let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo.min(n), n); + b.set_phase("dialog_gcd_apply_chunk_sub_final_ripple"); + let final_topclean = dialog_gcd_apply_final_topclean_bits() + .max(dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), &[])); + if final_topclean > 0 { + cuccaro_sub_fast_low_to_ext_topclean(b, &f, &acc_ext[lo..hi], borrow, final_topclean); + } else if let Some(window_blocks) = dialog_gcd_apply_final_windowed_fast_blocks() { + cuccaro_sub_fast_windowed_low_to_ext( + b, + &f, + &acc_ext[lo..hi], + borrow, + window_blocks, + ); + } else if dialog_gcd_apply_final_lowq_enabled() { + let zero = b.alloc_qubit(); + let mut f_ext = f.clone(); + f_ext.push(zero); + cuccaro_sub(b, &f_ext, &acc_ext[lo..hi], borrow); + b.free(zero); + } else { + cuccaro_sub_fast_low_to_ext(b, &f, &acc_ext[lo..hi], borrow); + } + b.set_phase("dialog_gcd_apply_chunk_sub_final_clear"); + dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo.min(n), &f); + b.free_vec(&f); + break; + } + + assert!(hi <= n); + b.set_phase("dialog_gcd_apply_chunk_sub_load"); + let f = dialog_gcd_load_controlled_slice(b, ctrl, source, lo, hi); + let needs_distinct_zero = + borrow == c_in || !dialog_gcd_apply_chunked_f_reuse_cin_zero_enabled(); + let (zero, owned_zero) = if needs_distinct_zero { + zero_host.map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)) + } else { + (c_in, false) + }; + let (bout, owned_bout) = boundary_hosts + .get(bouts.len()) + .copied() + .map_or_else(|| (b.alloc_qubit(), true), |q| (q, false)); + let mut acc_block = acc_ext[lo..hi].to_vec(); + acc_block.push(bout); + let future_boundary_carries = if dialog_gcd_apply_borrow_future_boundary_carries_enabled() { + boundary_hosts.get(bouts.len() + 1..).unwrap_or(&[]) + } else { + &[] + }; + let topclean_bits = if implicit_high_zero { + dialog_gcd_apply_auto_topclean_bits(b.active_qubits, f.len(), future_boundary_carries) + } else { + 0 + }; + b.set_phase("dialog_gcd_apply_chunk_sub_ripple"); + if implicit_high_zero { + if topclean_bits > 0 { + dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries_topclean( + b, + &f, + &acc_block, + borrow, + future_boundary_carries, + topclean_bits, + ); + } else { + dialog_gcd_sub_fast_low_to_ext_with_borrowed_carries( + b, + &f, + &acc_block, + borrow, + future_boundary_carries, + ); + } + } else { + let mut a_block = f.clone(); + a_block.push(zero); + dialog_gcd_sub_fast_with_borrowed_carries( + b, + &a_block, + &acc_block, + borrow, + future_boundary_carries, + ); + } + if owned_zero { + b.free(zero); + } + b.set_phase("dialog_gcd_apply_chunk_sub_clear"); + dialog_gcd_clear_controlled_slice_hmr(b, ctrl, source, lo, &f); + b.free_vec(&f); + bouts.push((bout, hi, owned_bout)); + borrow = bout; + lo = hi; + } + + let mut boundary_replay_freed_owned = false; + if dialog_gcd_apply_chunked_f_fuse_boundary_clears_enabled() { + if let Some(&(_, p, _)) = bouts.last() { + b.set_phase("dialog_gcd_apply_chunk_sub_boundary_clear"); + for i in 0..p { + b.x(source[i]); + } + let targets = bouts + .iter() + .map(|&(bout, p, _)| (bout, p)) + .collect::>(); + if dialog_gcd_apply_boundary_conditional_replay_enabled() { + if dialog_gcd_apply_boundary_free_owned_during_replay_enabled() { + dialog_gcd_conditional_boundary_replay_free_owned( + b, + &source[..p], + &acc_ext[..p], + ctrl, + c_in, + &bouts, + ); + boundary_replay_freed_owned = true; + } else { + dialog_gcd_conditional_boundary_replay( + b, + &source[..p], + &acc_ext[..p], + ctrl, + c_in, + &targets, + ); + } + } else if let Some(split) = dialog_gcd_apply_boundary_split() { + ccx_cmp_lt_into_fast_prefix_targets_split( + b, + &source[..p], + &acc_ext[..p], + ctrl, + &targets, + split.min(p.saturating_sub(1)), + ); + } else { + ccx_cmp_lt_into_fast_prefix_targets(b, &source[..p], &acc_ext[..p], ctrl, &targets); + } + for i in 0..p { + b.x(source[i]); + } + } + } else { + for &(bout, p, _) in bouts.iter().rev() { + b.set_phase("dialog_gcd_apply_chunk_sub_boundary_clear"); + for i in 0..p { + b.x(source[i]); + } + ccx_cmp_lt_into_fast(b, &source[..p], &acc_ext[..p], ctrl, bout); + for i in 0..p { + b.x(source[i]); + } + } + } + for &(bout, _, owned_bout) in bouts.iter().rev() { + if owned_bout && !boundary_replay_freed_owned { + b.free(bout); + } + } +} + +pub(crate) fn dialog_gcd_cmod_add_materialized_pseudomersenne_chunked( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + blocks: usize, + clean_scratch: &[QubitId], + step: Option, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + for (i, &q) in clean_scratch.iter().enumerate() { + assert!(!clean_scratch[..i].contains(&q)); + assert!(!acc_ext.contains(&q)); + assert!(!a.contains(&q)); + assert_ne!(q, ctrl); + } + let (c_in, owned_c_in, inner_scratch) = clean_scratch.split_first().map_or_else( + || (b.alloc_qubit(), true, &[][..]), + |(&q, rest)| (q, false, rest), + ); + + b.set_phase("dialog_gcd_materialized_special_chunked_raw_sum"); + dialog_gcd_add_ctrl_chunked_low_to_ext(b, a, &acc_ext, ctrl, c_in, blocks, inner_scratch); + if owned_c_in { + b.free(c_in); + } + + b.set_phase("dialog_gcd_materialized_special_overflow_fold"); + if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { + let borrowed_carries = if std::env::var("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES") + .ok() + .as_deref() + == Some("1") + { + + clean_scratch + } else { + &[] + }; + if std::env::var("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH") + .ok() + .as_deref() + == Some("1") + && !borrowed_carries.is_empty() + { + assert_eq!( + std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") + .ok() + .as_deref(), + Some("1"), + "special-fold scratch release requires owned in-place apply scratch" + ); + cadd_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b, + &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], + c, + acc_ovf, + w, + borrowed_carries, + step, + ); + } else { + cadd_nbit_const_direct_trunc_fast_borrowed_carries( + b, + &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], + c, + acc_ovf, + w, + borrowed_carries, + ); + } + } else { + cadd_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_overflow_clean"); + let compare_start = N - dialog_gcd_special_overflow_clean_compare_bits(step); + if dialog_gcd_special_clean_conditional_replay_enabled() { + let phase = b.alloc_bit(); + b.hmr(acc_ovf, phase); + dialog_gcd_cmp_lt_phase_conditioned_hosted( + b, + &acc[compare_start..], + &a[compare_start..], + ctrl, + phase, + Some(clean_scratch), + ); + } else { + ccx_cmp_lt_into_fast(b, &acc[compare_start..], &a[compare_start..], ctrl, acc_ovf); + } + unext_reg(b, acc_ovf); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_chunked( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + blocks: usize, + clean_scratch: &[QubitId], + step: Option, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + for (i, &q) in clean_scratch.iter().enumerate() { + assert!(!clean_scratch[..i].contains(&q)); + assert!(!acc_ext.contains(&q)); + assert!(!a.contains(&q)); + assert_ne!(q, ctrl); + } + let (c_in, owned_c_in, inner_scratch) = clean_scratch.split_first().map_or_else( + || (b.alloc_qubit(), true, &[][..]), + |(&q, rest)| (q, false, rest), + ); + + b.set_phase("dialog_gcd_materialized_special_chunked_raw_difference"); + dialog_gcd_sub_ctrl_chunked_low_to_ext(b, a, &acc_ext, ctrl, c_in, blocks, inner_scratch); + if owned_c_in { + b.free(c_in); + } + + b.set_phase("dialog_gcd_materialized_special_underflow_fold"); + if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { + let borrowed_carries = if std::env::var("DIALOG_GCD_SPECIAL_FOLD_BORROW_CARRIES") + .ok() + .as_deref() + == Some("1") + { + + clean_scratch + } else { + &[] + }; + if std::env::var("DIALOG_GCD_SPECIAL_FOLD_RELEASE_SCRATCH") + .ok() + .as_deref() + == Some("1") + && !borrowed_carries.is_empty() + { + assert_eq!( + std::env::var("DIALOG_GCD_K2_APPLY_INPLACE_RAW_BLOCK") + .ok() + .as_deref(), + Some("1"), + "special-fold scratch release requires owned in-place apply scratch" + ); + csub_nbit_const_direct_trunc_fast_releasing_scratch_at_step( + b, + &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], + c, + acc_ovf, + w, + borrowed_carries, + step, + ); + } else { + csub_nbit_const_direct_trunc_fast_borrowed_carries( + b, + &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], + c, + acc_ovf, + w, + borrowed_carries, + ); + } + } else { + csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_underflow_clean"); + dialog_gcd_clean_truncated_underflow_with_borrowed( + b, + acc, + a, + ctrl, + acc_ovf, + step, + Some(clean_scratch), + ); + unext_reg(b, acc_ovf); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, +) { + dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, acc, a, ctrl, p, None); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + step: Option, +) { + dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + acc, + a, + ctrl, + p, + &[], + step, + ); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + clean_scratch: &[QubitId], +) { + dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( + b, + acc, + a, + ctrl, + p, + clean_scratch, + None, + ); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_with_clean_scratch_at_step( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + clean_scratch: &[QubitId], + step: Option, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + if let Some(blocks) = dialog_gcd_apply_chunked_f_blocks() + .filter(|_| dialog_gcd_raw_apply_truncated_clean_enabled()) + .filter(|_| dialog_gcd_measured_apply_sub_enabled()) + { + dialog_gcd_cmod_sub_materialized_pseudomersenne_chunked( + b, + acc, + a, + ctrl, + p, + blocks, + clean_scratch, + step, + ); + return; + } + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + let f = b.alloc_qubits(N); + b.set_phase("dialog_gcd_materialized_special_load_subtrahend"); + for i in 0..N { + b.ccx(ctrl, a[i], f[i]); + } + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + + b.set_phase("dialog_gcd_materialized_special_raw_difference"); + if dialog_gcd_measured_apply_sub_enabled() { + + let c_in = b.alloc_qubit(); + if let Some(w) = dialog_gcd_apply_window_blocks() { + cuccaro_sub_fast_windowed_low_to_ext(b, &f, &acc_ext, c_in, w); + } else { + let f_ovf = b.alloc_qubit(); + let mut f_ext = f.clone(); + f_ext.push(f_ovf); + cuccaro_sub_fast(b, &f_ext, &acc_ext, c_in); + b.free(f_ovf); + } + b.free(c_in); + } else { + let f_ovf = b.alloc_qubit(); + let mut f_ext = f.clone(); + f_ext.push(f_ovf); + sub_nbit_qq(b, &f_ext, &acc_ext); + b.free(f_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_underflow_fold"); + if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { + csub_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); + } else { + csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_underflow_clean"); + if dialog_gcd_raw_apply_truncated_clean_enabled() { + dialog_gcd_clean_truncated_underflow(b, acc, a, ctrl, acc_ovf, step); + } else { + b.x(acc_ovf); + mod_neg_inplace_fast(b, &f, p); + cmp_lt_into_fast(b, acc, &f, acc_ovf); + mod_neg_inplace_fast(b, &f, p); + } + unext_reg(b, acc_ovf); + + b.set_phase("dialog_gcd_materialized_special_clear_subtrahend"); + for i in 0..N { + let m = b.alloc_bit(); + b.hmr(f[i], m); + b.cz_if(ctrl, a[i], m); + } + b.free_vec(&f); +} + +pub(crate) fn emit_dialog_gcd_raw_apply_bitvector( + b: &mut B, + dialog_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, +) { + assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + + for step in (0..dialog_gcd_active_iterations()).rev() { + let b0 = dialog_log[2 * step]; + let b0_and_b1 = dialog_log[2 * step + 1]; + + b.set_phase("dialog_gcd_raw_apply_double_y"); + mod_double_inplace_fast(b, y, p); + + b.set_phase("dialog_gcd_raw_apply_cadd"); + if dialog_gcd_raw_apply_materialized_special_add_enabled() { + dialog_gcd_cmod_add_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); + } else if dialog_gcd_raw_apply_direct_special_add_enabled() { + dialog_gcd_cmod_add_pseudomersenne_lowq(b, y, x, b0, p); + } else { + cmod_add_qq_lowq(b, y, x, b0, p); + } + + b.set_phase("dialog_gcd_raw_apply_cswap"); + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + } +} + +pub(crate) fn emit_dialog_gcd_raw_apply_bitvector_reverse_exact( + b: &mut B, + dialog_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, +) { + assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + + for step in 0..dialog_gcd_active_iterations() { + let b0 = dialog_log[2 * step]; + let b0_and_b1 = dialog_log[2 * step + 1]; + + b.set_phase("dialog_gcd_raw_apply_reverse_cswap"); + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + + b.set_phase("dialog_gcd_raw_apply_reverse_csub"); + if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { + dialog_gcd_cmod_sub_materialized_pseudomersenne_at_step(b, y, x, b0, p, Some(step)); + } else if dialog_gcd_raw_apply_reverse_fast_sub_enabled() { + cmod_sub_qq(b, y, x, b0, p); + } else { + cmod_sub_qq_lowq(b, y, x, b0, p); + } + + b.set_phase("dialog_gcd_raw_apply_reverse_halve_y"); + mod_halve_inplace_fast(b, y, p); + } +} + +pub(crate) fn cmod_sub_qq_lowq_borrowed_subtrahend( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + f: &[QubitId], +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + assert_eq!(f.len(), N); + + for i in 0..N { + b.ccx(ctrl, a[i], f[i]); + } + mod_sub_qq(b, acc, f, p); + for i in (0..N).rev() { + b.ccx(ctrl, a[i], f[i]); + } +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + f: &[QubitId], +) { + dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( + b, + acc, + a, + ctrl, + p, + f, + None, + ); +} + +pub(crate) fn dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( + b: &mut B, + acc: &[QubitId], + a: &[QubitId], + ctrl: QubitId, + p: U256, + f: &[QubitId], + step: Option, +) { + assert_eq!(acc.len(), N); + assert_eq!(a.len(), N); + assert_eq!(f.len(), N); + let c = U256::MAX.wrapping_sub(p).wrapping_add(U256::from(1u64)); + + b.set_phase("dialog_gcd_materialized_special_borrowed_load_subtrahend"); + for i in 0..N { + b.ccx(ctrl, a[i], f[i]); + } + + let (acc_ext, acc_ovf) = ext_reg(b, acc); + let f_ovf = b.alloc_qubit(); + let mut f_ext = f.to_vec(); + f_ext.push(f_ovf); + + b.set_phase("dialog_gcd_materialized_special_borrowed_raw_difference"); + sub_nbit_qq(b, &f_ext, &acc_ext); + b.free(f_ovf); + + b.set_phase("dialog_gcd_materialized_special_borrowed_underflow_fold"); + if let Some(w) = dialog_gcd_special_fold_carry_trunc_window(step) { + csub_nbit_const_direct_trunc_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf, w); + } else { + csub_nbit_const_fast(b, &acc[..DIALOG_GCD_SPECIAL_ADD_LSBS], c, acc_ovf); + } + + b.set_phase("dialog_gcd_materialized_special_borrowed_underflow_clean"); + if dialog_gcd_raw_apply_truncated_clean_enabled() { + dialog_gcd_clean_truncated_underflow(b, acc, a, ctrl, acc_ovf, step); + } else { + b.x(acc_ovf); + mod_neg_inplace_fast(b, f, p); + cmp_lt_into_fast(b, acc, f, acc_ovf); + mod_neg_inplace_fast(b, f, p); + } + unext_reg(b, acc_ovf); + + b.set_phase("dialog_gcd_materialized_special_borrowed_clear_subtrahend"); + for i in (0..N).rev() { + b.ccx(ctrl, a[i], f[i]); + } +} + +pub(crate) fn emit_dialog_gcd_raw_apply_bitvector_reverse_borrowed_subtrahend( + b: &mut B, + dialog_log: &[QubitId], + x: &[QubitId], + y: &[QubitId], + p: U256, + f: &[QubitId], +) { + assert!(dialog_log.len() >= 2 * dialog_gcd_active_iterations()); + assert_eq!(x.len(), N); + assert_eq!(y.len(), N); + assert_eq!(f.len(), N); + + for step in 0..dialog_gcd_active_iterations() { + let b0 = dialog_log[2 * step]; + let b0_and_b1 = dialog_log[2 * step + 1]; + + b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_cswap"); + for (&xi, &yi) in x.iter().zip(y.iter()) { + cswap(b, b0_and_b1, xi, yi); + } + + b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_csub"); + if dialog_gcd_raw_apply_reverse_materialized_special_sub_enabled() { + dialog_gcd_cmod_sub_materialized_pseudomersenne_borrowed_subtrahend_at_step( + b, + y, + x, + b0, + p, + f, + Some(step), + ); + } else { + cmod_sub_qq_lowq_borrowed_subtrahend(b, y, x, b0, p, f); + } + + b.set_phase("dialog_gcd_raw_apply_reverse_borrowed_halve_y"); + mod_halve_inplace_fast(b, y, p); + } +} + +pub(crate) fn emit_dialog_gcd_raw_ipmul(b: &mut B, factor: &[QubitId], target: &[QubitId], p: U256) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + if dialog_gcd_compressed_sidecar_log_enabled() { + emit_dialog_gcd_compressed_sidecar_ipmul(b, factor, target, p); + return; + } + + let dialog_log = b.alloc_qubits(DIALOG_GCD_RAW_LOG_BITS); + let u = b.alloc_qubits(N); + b.set_phase("dialog_gcd_raw_ipmul_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_raw_ipmul_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps(b, &u, factor, &dialog_log); + + if dialog_gcd_raw_ipmul_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_raw_ipmul_release_terminal_u"); + b.x(u[0]); + b.free_vec(&u); + + b.set_phase("dialog_gcd_raw_ipmul_apply_bitvector_reuse_factor_zero"); + emit_dialog_gcd_raw_apply_bitvector(b, &dialog_log, target, factor, p); + + if dialog_gcd_raw_ipmul_clear_p_residual_enabled() { + b.set_phase("dialog_gcd_raw_ipmul_clear_p_residual_source_lane"); + for i in 0..N { + if bit(p, i) { + b.x(target[i]); + } + } + } + + b.set_phase("dialog_gcd_raw_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + b.set_phase("dialog_gcd_raw_ipmul_reacquire_terminal_u"); + b.reacquire_vec(&u); + b.set_phase("dialog_gcd_raw_ipmul_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_raw_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); + + b.set_phase("dialog_gcd_raw_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free_vec(&dialog_log); + return; + } + + let tmp = b.alloc_qubits(N); + b.set_phase("dialog_gcd_raw_ipmul_apply_bitvector"); + emit_dialog_gcd_raw_apply_bitvector(b, &dialog_log, target, &tmp, p); + + b.set_phase("dialog_gcd_raw_ipmul_swap_product_into_target"); + for i in 0..N { + b.swap(target[i], tmp[i]); + } + + b.set_phase("dialog_gcd_raw_ipmul_free_zero_tmp"); + b.free_vec(&tmp); + + b.set_phase("dialog_gcd_raw_ipmul_uncompute_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); + + b.set_phase("dialog_gcd_raw_ipmul_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free_vec(&dialog_log); +} + +pub(crate) fn emit_dialog_gcd_raw_quotient(b: &mut B, factor: &[QubitId], target: &[QubitId], p: U256) { + assert_eq!(factor.len(), N); + assert_eq!(target.len(), N); + + if dialog_gcd_compressed_sidecar_log_enabled() { + emit_dialog_gcd_compressed_sidecar_quotient(b, factor, target, p); + return; + } + + let dialog_log = b.alloc_qubits(DIALOG_GCD_RAW_LOG_BITS); + let u = b.alloc_qubits(N); + b.set_phase("dialog_gcd_raw_quotient_load_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + + b.set_phase("dialog_gcd_raw_quotient_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps(b, &u, factor, &dialog_log); + + if dialog_gcd_raw_quotient_keep_terminal_u_enabled() { + b.set_phase("dialog_gcd_raw_quotient_zero_terminal_u_for_borrow"); + b.x(u[0]); + + b.set_phase("dialog_gcd_raw_quotient_apply_reverse_reuse_factor_zero_keep_u"); + emit_dialog_gcd_raw_apply_bitvector_reverse_borrowed_subtrahend( + b, + &dialog_log, + factor, + target, + p, + &u, + ); + + b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target_keep_u"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + b.set_phase("dialog_gcd_raw_quotient_restore_terminal_u_after_borrow"); + b.x(u[0]); + + b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector_keep_u"); + emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); + + b.set_phase("dialog_gcd_raw_quotient_unload_p_keep_u"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free_vec(&dialog_log); + return; + } + + if dialog_gcd_raw_quotient_terminal_reuse_enabled() { + b.set_phase("dialog_gcd_raw_quotient_release_terminal_u"); + b.x(u[0]); + b.free_vec(&u); + + b.set_phase("dialog_gcd_raw_quotient_apply_reverse_reuse_factor_zero"); + emit_dialog_gcd_raw_apply_bitvector_reverse_exact(b, &dialog_log, factor, target, p); + + b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target"); + for i in 0..N { + b.swap(target[i], factor[i]); + } + + b.set_phase("dialog_gcd_raw_quotient_reacquire_terminal_u"); + b.reacquire_vec(&u); + b.set_phase("dialog_gcd_raw_quotient_seed_terminal_u"); + b.x(u[0]); + + b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); + + b.set_phase("dialog_gcd_raw_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free_vec(&dialog_log); + return; + } + + let tmp = b.alloc_qubits(N); + b.set_phase("dialog_gcd_raw_quotient_apply_reverse"); + emit_dialog_gcd_raw_apply_bitvector_reverse_exact(b, &dialog_log, &tmp, target, p); + + b.set_phase("dialog_gcd_raw_quotient_swap_quotient_into_target"); + for i in 0..N { + b.swap(target[i], tmp[i]); + } + + b.set_phase("dialog_gcd_raw_quotient_free_zero_tmp"); + b.free_vec(&tmp); + + b.set_phase("dialog_gcd_raw_quotient_uncompute_tobitvector"); + emit_dialog_gcd_raw_tobitvector_steps_reverse(b, &u, factor, &dialog_log); + + b.set_phase("dialog_gcd_raw_quotient_unload_p"); + for i in 0..N { + if bit(p, i) { + b.x(u[i]); + } + } + b.free_vec(&u); + b.free_vec(&dialog_log); +} + +pub(crate) fn emit_dialog_gcd_raw_pa( + b: &mut B, + tx: &[QubitId], + ty: &[QubitId], + ox: &[BitId], + oy: &[BitId], + p: U256, +) { + assert_eq!(tx.len(), N); + assert_eq!(ty.len(), N); + assert_eq!(ox.len(), N); + assert_eq!(oy.len(), N); + + b.set_phase("dialog_gcd_raw_pa_pair1_quotient"); + emit_dialog_gcd_raw_quotient(b, tx, ty, p); + if dialog_gcd_raw_pa_stop_after_quotient_enabled() { + return; + } + + round84_emit_fused_square_xtail(b, tx, ty, ox, p); + if dialog_gcd_raw_pa_stop_after_xtail_enabled() { + return; + } + + b.set_phase("dialog_gcd_raw_pa_c_ox_minus_rx"); + if dialog_fuse_c_form_enabled() { + mod_add_triple_qb(b, tx, ox, p); + } else { + mod_sub_qb(b, tx, ox, p); + mod_neg_inplace_fast(b, tx, p); + } + if dialog_gcd_raw_pa_stop_after_c_enabled() { + return; + } + + b.set_phase("dialog_gcd_raw_pa_pair2_product"); + emit_dialog_gcd_raw_ipmul(b, tx, ty, p); + if dialog_gcd_raw_pa_stop_after_pair2_enabled() { + return; + } + + b.set_phase("dialog_gcd_raw_pa_y_output"); + mod_sub_qb(b, ty, oy, p); + + b.set_phase("dialog_gcd_raw_pa_x_restore"); + if dialog_fuse_x_restore_enabled() { + mod_const_minus_reg_qb(b, tx, ox, p); + } else { + mod_neg_inplace_fast(b, tx, p); + mod_add_qb(b, tx, ox, p); + } +} diff --git a/src/point_add/rounds/mod.rs b/src/point_add/rounds/mod.rs index ef5f502f..940ffbe4 100644 --- a/src/point_add/rounds/mod.rs +++ b/src/point_add/rounds/mod.rs @@ -1,6 +1,6 @@ - -use super::*; - -mod dialog; - -pub(crate) use dialog::*; + +use super::*; + +mod dialog; + +pub(crate) use dialog::*; diff --git a/src/point_add/single_ccx_fanout.rs b/src/point_add/single_ccx_fanout.rs index aafd488f..23730093 100644 --- a/src/point_add/single_ccx_fanout.rs +++ b/src/point_add/single_ccx_fanout.rs @@ -1,368 +1,368 @@ -use crate::circuit::{Op, OperationType, NO_BIT, NO_QUBIT}; -use std::collections::HashMap; - -const NO_INDEX: usize = usize::MAX; - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(crate) struct FanoutWitness { - pub(crate) first_index: usize, - pub(crate) blocker_index: usize, - pub(crate) second_index: usize, - pub(crate) control_a: u64, - pub(crate) control_b: u64, - pub(crate) old_target: u64, - pub(crate) new_target: u64, - pub(crate) condition: u64, -} - -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] -struct GateKey { - control_a: u64, - control_b: u64, - target: u64, -} - -#[derive(Clone, Copy, Debug)] -struct Candidate { - index: usize, - snapshot: [u64; 8], -} - -struct Epochs { - x_targets: Vec, - x_controls: Vec, - z_touches: Vec, - hard_touches: Vec, - swap_touches: Vec, - swap_pairs: HashMap<(u64, u64), u64>, - last_x_control: Vec, -} - -impl Epochs { - fn new(wire_count: usize) -> Self { - Self { - x_targets: vec![0; wire_count], - x_controls: vec![0; wire_count], - z_touches: vec![0; wire_count], - hard_touches: vec![0; wire_count], - swap_touches: vec![0; wire_count], - swap_pairs: HashMap::new(), - last_x_control: vec![NO_INDEX; wire_count], - } - } - - fn swap_pair(&self, a: u64, b: u64) -> u64 { - *self.swap_pairs.get(&sorted_pair(a, b)).unwrap_or(&0) - } -} - -fn sorted_pair(a: u64, b: u64) -> (u64, u64) { - if a <= b { - (a, b) - } else { - (b, a) - } -} - -fn ccx_key(op: &Op) -> Option { - if op.kind != OperationType::CCX || op.c_condition != NO_BIT { - return None; - } - let (control_a, control_b) = sorted_pair(op.q_control1.0, op.q_control2.0); - Some(GateKey { - control_a, - control_b, - target: op.q_target.0, - }) -} - -fn x_controls(op: &Op) -> Option<([u64; 2], usize)> { - match op.kind { - OperationType::X => Some(([NO_QUBIT.0; 2], 0)), - OperationType::CX => Some(([op.q_control1.0, NO_QUBIT.0], 1)), - OperationType::CCX => Some(([op.q_control1.0, op.q_control2.0], 2)), - _ => None, - } -} - -fn quantum_support(op: &Op) -> ([u64; 3], usize) { - match op.kind { - OperationType::X | OperationType::Z | OperationType::R | OperationType::Hmr => { - ([op.q_target.0, NO_QUBIT.0, NO_QUBIT.0], 1) - } - OperationType::CX | OperationType::CZ | OperationType::Swap => { - ([op.q_control1.0, op.q_target.0, NO_QUBIT.0], 2) - } - OperationType::CCX | OperationType::CCZ => { - ([op.q_control2.0, op.q_control1.0, op.q_target.0], 3) - } - _ => ([NO_QUBIT.0; 3], 0), - } -} - -fn max_wire(ops: &[Op]) -> usize { - ops.iter() - .flat_map(|op| { - let (support, count) = quantum_support(op); - support.into_iter().take(count) - }) - .max() - .unwrap_or(0) as usize -} - -fn snapshot(key: GateKey, epochs: &Epochs) -> [u64; 8] { - let swap_touches = epochs.swap_touches[key.control_a as usize] - + epochs.swap_touches[key.control_b as usize] - + epochs.swap_touches[key.target as usize]; - let swap_blockers = swap_touches - 2 * epochs.swap_pair(key.control_a, key.control_b); - [ - epochs.x_targets[key.control_a as usize], - epochs.x_targets[key.control_b as usize], - epochs.x_controls[key.target as usize], - epochs.z_touches[key.target as usize], - epochs.hard_touches[key.control_a as usize], - epochs.hard_touches[key.control_b as usize], - epochs.hard_touches[key.target as usize], - swap_blockers, - ] -} - -fn advance_epochs(op: &Op, index: usize, epochs: &mut Epochs) -> bool { - if matches!( - op.kind, - OperationType::PushCondition | OperationType::PopCondition - ) { - return true; - } - if let Some((controls, count)) = x_controls(op) { - epochs.x_targets[op.q_target.0 as usize] += 1; - for &control in &controls[..count] { - epochs.x_controls[control as usize] += 1; - epochs.last_x_control[control as usize] = index; - } - return false; - } - match op.kind { - OperationType::Z | OperationType::CZ | OperationType::CCZ => { - let (support, count) = quantum_support(op); - for &wire in &support[..count] { - epochs.z_touches[wire as usize] += 1; - } - } - OperationType::Swap => { - let (a, b) = sorted_pair(op.q_control1.0, op.q_target.0); - epochs.swap_touches[a as usize] += 1; - epochs.swap_touches[b as usize] += 1; - *epochs.swap_pairs.entry((a, b)).or_insert(0) += 1; - } - OperationType::R | OperationType::Hmr => { - epochs.hard_touches[op.q_target.0 as usize] += 1; - } - _ => {} - } - false -} - -fn validate_protected_tail(ops: &[Op], protected: usize) -> Result, String> { - if protected > ops.len() || protected % 2 != 0 { - return Err("invalid protected-tail length".to_owned()); - } - let tail = &ops[ops.len() - protected..]; - for (pair_index, pair) in tail.chunks_exact(2).enumerate() { - if pair[0] != pair[1] - || pair[0].kind != OperationType::X - || pair[0].c_condition != NO_BIT - { - return Err(format!( - "protected nonce pair {pair_index} is not unconditional X/X" - )); - } - } - Ok(tail.to_vec()) -} - -pub(crate) fn rewrite_first_target_fanout( - ops: Vec, - protected_tail_ops: usize, -) -> Result<(Vec, FanoutWitness), String> { - let protected_tail = validate_protected_tail(&ops, protected_tail_ops)?; - let prefix_len = ops.len() - protected_tail_ops; - let mut epochs = Epochs::new(max_wire(&ops) + 1); - let mut candidates = HashMap::::new(); - - for index in 0..prefix_len { - let op = ops[index]; - if let Some(key) = ccx_key(&op) { - let current_snapshot = snapshot(key, &epochs); - if let Some(prior) = candidates.get(&key).copied() { - let mut deltas = [0u64; 8]; - let monotonic = deltas - .iter_mut() - .zip(current_snapshot.into_iter().zip(prior.snapshot)) - .all(|(delta, (current, old))| { - if let Some(value) = current.checked_sub(old) { - *delta = value; - true - } else { - false - } - }); - let blocker_index = epochs.last_x_control[key.target as usize]; - let blocker = (blocker_index != NO_INDEX).then(|| ops[blocker_index]); - if monotonic - && deltas == [0, 0, 1, 0, 0, 0, 0, 0] - && prior.index < blocker_index - && blocker_index < index - && blocker.is_some_and(|blocker| { - blocker.kind == OperationType::CX - && blocker.q_control1.0 == key.target - && blocker.q_target.0 != key.control_a - && blocker.q_target.0 != key.control_b - && blocker.q_target.0 != key.target - }) - { - let blocker = blocker.unwrap(); - let mut replacement = Op::empty(); - replacement.kind = OperationType::CCX; - replacement.q_control2.0 = key.control_a; - replacement.q_control1.0 = key.control_b; - replacement.q_target = blocker.q_target; - replacement.c_condition = blocker.c_condition; - let witness = FanoutWitness { - first_index: prior.index, - blocker_index, - second_index: index, - control_a: key.control_a, - control_b: key.control_b, - old_target: key.target, - new_target: blocker.q_target.0, - condition: blocker.c_condition.0, - }; - let mut rewritten = Vec::with_capacity(ops.len() - 1); - for (op_index, stream_op) in ops.into_iter().enumerate() { - if op_index == prior.index || op_index == index { - continue; - } - rewritten.push(stream_op); - if op_index == blocker_index { - rewritten.push(replacement); - } - } - if rewritten.len() + 1 != prefix_len + protected_tail_ops { - return Err("single-fanout rewrite changed the wrong op count".to_owned()); - } - if rewritten[rewritten.len() - protected_tail_ops..] != protected_tail { - return Err("single-fanout rewrite changed the nonce suffix".to_owned()); - } - return Ok((rewritten, witness)); - } - } - candidates.insert( - key, - Candidate { - index, - snapshot: current_snapshot, - }, - ); - } - if advance_epochs(&op, index, &mut epochs) { - candidates.clear(); - } - } - Err("no target-fanout conjugation found".to_owned()) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::circuit::{BitId, QubitId}; - - fn x(target: u64) -> Op { - let mut op = Op::empty(); - op.kind = OperationType::X; - op.q_target = QubitId(target); - op - } - - fn cx(control: u64, target: u64) -> Op { - let mut op = Op::empty(); - op.kind = OperationType::CX; - op.q_control1 = QubitId(control); - op.q_target = QubitId(target); - op - } - - fn ccx(a: u64, b: u64, target: u64) -> Op { - let mut op = Op::empty(); - op.kind = OperationType::CCX; - op.q_control2 = QubitId(a); - op.q_control1 = QubitId(b); - op.q_target = QubitId(target); - op - } - - fn nonce_tail() -> Vec { - (0..48).flat_map(|_| [x(0), x(0)]).collect() - } - - fn eval(ops: &[Op], mut state: u8, condition: bool) -> u8 { - for op in ops { - if op.c_condition != NO_BIT && !condition { - continue; - } - match op.kind { - OperationType::CX => { - if ((state >> op.q_control1.0) & 1) != 0 { - state ^= 1 << op.q_target.0; - } - } - OperationType::CCX => { - if ((state >> op.q_control1.0) & 1) != 0 - && ((state >> op.q_control2.0) & 1) != 0 - { - state ^= 1 << op.q_target.0; - } - } - OperationType::X => state ^= 1 << op.q_target.0, - _ => {} - } - } - state - } - - #[test] - fn first_fanout_rewrite_is_exact_and_tail_stable() { - let mut blocker = cx(2, 3); - blocker.c_condition = BitId(7); - let before_prefix = vec![ccx(0, 1, 2), blocker, ccx(1, 0, 2)]; - let mut before = before_prefix.clone(); - let tail = nonce_tail(); - before.extend(tail.clone()); - let (after, witness) = rewrite_first_target_fanout(before, 96).unwrap(); - assert_eq!(witness.first_index, 0); - assert_eq!(witness.blocker_index, 1); - assert_eq!(witness.second_index, 2); - assert_eq!(witness.condition, 7); - assert_eq!(&after[after.len() - 96..], tail.as_slice()); - for condition in [false, true] { - for state in 0..16 { - assert_eq!( - eval(&before_prefix, state, condition), - eval(&after[..2], state, condition) - ); - } - } - } - - #[test] - fn condition_stack_is_a_hard_barrier() { - let mut push = Op::empty(); - push.kind = OperationType::PushCondition; - push.c_condition = BitId(9); - let mut pop = Op::empty(); - pop.kind = OperationType::PopCondition; - let mut ops = vec![ccx(0, 1, 2), push, cx(2, 3), pop, ccx(0, 1, 2)]; - ops.extend(nonce_tail()); - assert!(rewrite_first_target_fanout(ops, 96).is_err()); - } -} +use crate::circuit::{Op, OperationType, NO_BIT, NO_QUBIT}; +use std::collections::HashMap; + +const NO_INDEX: usize = usize::MAX; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(crate) struct FanoutWitness { + pub(crate) first_index: usize, + pub(crate) blocker_index: usize, + pub(crate) second_index: usize, + pub(crate) control_a: u64, + pub(crate) control_b: u64, + pub(crate) old_target: u64, + pub(crate) new_target: u64, + pub(crate) condition: u64, +} + +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +struct GateKey { + control_a: u64, + control_b: u64, + target: u64, +} + +#[derive(Clone, Copy, Debug)] +struct Candidate { + index: usize, + snapshot: [u64; 8], +} + +struct Epochs { + x_targets: Vec, + x_controls: Vec, + z_touches: Vec, + hard_touches: Vec, + swap_touches: Vec, + swap_pairs: HashMap<(u64, u64), u64>, + last_x_control: Vec, +} + +impl Epochs { + fn new(wire_count: usize) -> Self { + Self { + x_targets: vec![0; wire_count], + x_controls: vec![0; wire_count], + z_touches: vec![0; wire_count], + hard_touches: vec![0; wire_count], + swap_touches: vec![0; wire_count], + swap_pairs: HashMap::new(), + last_x_control: vec![NO_INDEX; wire_count], + } + } + + fn swap_pair(&self, a: u64, b: u64) -> u64 { + *self.swap_pairs.get(&sorted_pair(a, b)).unwrap_or(&0) + } +} + +fn sorted_pair(a: u64, b: u64) -> (u64, u64) { + if a <= b { + (a, b) + } else { + (b, a) + } +} + +fn ccx_key(op: &Op) -> Option { + if op.kind != OperationType::CCX || op.c_condition != NO_BIT { + return None; + } + let (control_a, control_b) = sorted_pair(op.q_control1.0, op.q_control2.0); + Some(GateKey { + control_a, + control_b, + target: op.q_target.0, + }) +} + +fn x_controls(op: &Op) -> Option<([u64; 2], usize)> { + match op.kind { + OperationType::X => Some(([NO_QUBIT.0; 2], 0)), + OperationType::CX => Some(([op.q_control1.0, NO_QUBIT.0], 1)), + OperationType::CCX => Some(([op.q_control1.0, op.q_control2.0], 2)), + _ => None, + } +} + +fn quantum_support(op: &Op) -> ([u64; 3], usize) { + match op.kind { + OperationType::X | OperationType::Z | OperationType::R | OperationType::Hmr => { + ([op.q_target.0, NO_QUBIT.0, NO_QUBIT.0], 1) + } + OperationType::CX | OperationType::CZ | OperationType::Swap => { + ([op.q_control1.0, op.q_target.0, NO_QUBIT.0], 2) + } + OperationType::CCX | OperationType::CCZ => { + ([op.q_control2.0, op.q_control1.0, op.q_target.0], 3) + } + _ => ([NO_QUBIT.0; 3], 0), + } +} + +fn max_wire(ops: &[Op]) -> usize { + ops.iter() + .flat_map(|op| { + let (support, count) = quantum_support(op); + support.into_iter().take(count) + }) + .max() + .unwrap_or(0) as usize +} + +fn snapshot(key: GateKey, epochs: &Epochs) -> [u64; 8] { + let swap_touches = epochs.swap_touches[key.control_a as usize] + + epochs.swap_touches[key.control_b as usize] + + epochs.swap_touches[key.target as usize]; + let swap_blockers = swap_touches - 2 * epochs.swap_pair(key.control_a, key.control_b); + [ + epochs.x_targets[key.control_a as usize], + epochs.x_targets[key.control_b as usize], + epochs.x_controls[key.target as usize], + epochs.z_touches[key.target as usize], + epochs.hard_touches[key.control_a as usize], + epochs.hard_touches[key.control_b as usize], + epochs.hard_touches[key.target as usize], + swap_blockers, + ] +} + +fn advance_epochs(op: &Op, index: usize, epochs: &mut Epochs) -> bool { + if matches!( + op.kind, + OperationType::PushCondition | OperationType::PopCondition + ) { + return true; + } + if let Some((controls, count)) = x_controls(op) { + epochs.x_targets[op.q_target.0 as usize] += 1; + for &control in &controls[..count] { + epochs.x_controls[control as usize] += 1; + epochs.last_x_control[control as usize] = index; + } + return false; + } + match op.kind { + OperationType::Z | OperationType::CZ | OperationType::CCZ => { + let (support, count) = quantum_support(op); + for &wire in &support[..count] { + epochs.z_touches[wire as usize] += 1; + } + } + OperationType::Swap => { + let (a, b) = sorted_pair(op.q_control1.0, op.q_target.0); + epochs.swap_touches[a as usize] += 1; + epochs.swap_touches[b as usize] += 1; + *epochs.swap_pairs.entry((a, b)).or_insert(0) += 1; + } + OperationType::R | OperationType::Hmr => { + epochs.hard_touches[op.q_target.0 as usize] += 1; + } + _ => {} + } + false +} + +fn validate_protected_tail(ops: &[Op], protected: usize) -> Result, String> { + if protected > ops.len() || protected % 2 != 0 { + return Err("invalid protected-tail length".to_owned()); + } + let tail = &ops[ops.len() - protected..]; + for (pair_index, pair) in tail.chunks_exact(2).enumerate() { + if pair[0] != pair[1] + || pair[0].kind != OperationType::X + || pair[0].c_condition != NO_BIT + { + return Err(format!( + "protected nonce pair {pair_index} is not unconditional X/X" + )); + } + } + Ok(tail.to_vec()) +} + +pub(crate) fn rewrite_first_target_fanout( + ops: Vec, + protected_tail_ops: usize, +) -> Result<(Vec, FanoutWitness), String> { + let protected_tail = validate_protected_tail(&ops, protected_tail_ops)?; + let prefix_len = ops.len() - protected_tail_ops; + let mut epochs = Epochs::new(max_wire(&ops) + 1); + let mut candidates = HashMap::::new(); + + for index in 0..prefix_len { + let op = ops[index]; + if let Some(key) = ccx_key(&op) { + let current_snapshot = snapshot(key, &epochs); + if let Some(prior) = candidates.get(&key).copied() { + let mut deltas = [0u64; 8]; + let monotonic = deltas + .iter_mut() + .zip(current_snapshot.into_iter().zip(prior.snapshot)) + .all(|(delta, (current, old))| { + if let Some(value) = current.checked_sub(old) { + *delta = value; + true + } else { + false + } + }); + let blocker_index = epochs.last_x_control[key.target as usize]; + let blocker = (blocker_index != NO_INDEX).then(|| ops[blocker_index]); + if monotonic + && deltas == [0, 0, 1, 0, 0, 0, 0, 0] + && prior.index < blocker_index + && blocker_index < index + && blocker.is_some_and(|blocker| { + blocker.kind == OperationType::CX + && blocker.q_control1.0 == key.target + && blocker.q_target.0 != key.control_a + && blocker.q_target.0 != key.control_b + && blocker.q_target.0 != key.target + }) + { + let blocker = blocker.unwrap(); + let mut replacement = Op::empty(); + replacement.kind = OperationType::CCX; + replacement.q_control2.0 = key.control_a; + replacement.q_control1.0 = key.control_b; + replacement.q_target = blocker.q_target; + replacement.c_condition = blocker.c_condition; + let witness = FanoutWitness { + first_index: prior.index, + blocker_index, + second_index: index, + control_a: key.control_a, + control_b: key.control_b, + old_target: key.target, + new_target: blocker.q_target.0, + condition: blocker.c_condition.0, + }; + let mut rewritten = Vec::with_capacity(ops.len() - 1); + for (op_index, stream_op) in ops.into_iter().enumerate() { + if op_index == prior.index || op_index == index { + continue; + } + rewritten.push(stream_op); + if op_index == blocker_index { + rewritten.push(replacement); + } + } + if rewritten.len() + 1 != prefix_len + protected_tail_ops { + return Err("single-fanout rewrite changed the wrong op count".to_owned()); + } + if rewritten[rewritten.len() - protected_tail_ops..] != protected_tail { + return Err("single-fanout rewrite changed the nonce suffix".to_owned()); + } + return Ok((rewritten, witness)); + } + } + candidates.insert( + key, + Candidate { + index, + snapshot: current_snapshot, + }, + ); + } + if advance_epochs(&op, index, &mut epochs) { + candidates.clear(); + } + } + Err("no target-fanout conjugation found".to_owned()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::circuit::{BitId, QubitId}; + + fn x(target: u64) -> Op { + let mut op = Op::empty(); + op.kind = OperationType::X; + op.q_target = QubitId(target); + op + } + + fn cx(control: u64, target: u64) -> Op { + let mut op = Op::empty(); + op.kind = OperationType::CX; + op.q_control1 = QubitId(control); + op.q_target = QubitId(target); + op + } + + fn ccx(a: u64, b: u64, target: u64) -> Op { + let mut op = Op::empty(); + op.kind = OperationType::CCX; + op.q_control2 = QubitId(a); + op.q_control1 = QubitId(b); + op.q_target = QubitId(target); + op + } + + fn nonce_tail() -> Vec { + (0..48).flat_map(|_| [x(0), x(0)]).collect() + } + + fn eval(ops: &[Op], mut state: u8, condition: bool) -> u8 { + for op in ops { + if op.c_condition != NO_BIT && !condition { + continue; + } + match op.kind { + OperationType::CX => { + if ((state >> op.q_control1.0) & 1) != 0 { + state ^= 1 << op.q_target.0; + } + } + OperationType::CCX => { + if ((state >> op.q_control1.0) & 1) != 0 + && ((state >> op.q_control2.0) & 1) != 0 + { + state ^= 1 << op.q_target.0; + } + } + OperationType::X => state ^= 1 << op.q_target.0, + _ => {} + } + } + state + } + + #[test] + fn first_fanout_rewrite_is_exact_and_tail_stable() { + let mut blocker = cx(2, 3); + blocker.c_condition = BitId(7); + let before_prefix = vec![ccx(0, 1, 2), blocker, ccx(1, 0, 2)]; + let mut before = before_prefix.clone(); + let tail = nonce_tail(); + before.extend(tail.clone()); + let (after, witness) = rewrite_first_target_fanout(before, 96).unwrap(); + assert_eq!(witness.first_index, 0); + assert_eq!(witness.blocker_index, 1); + assert_eq!(witness.second_index, 2); + assert_eq!(witness.condition, 7); + assert_eq!(&after[after.len() - 96..], tail.as_slice()); + for condition in [false, true] { + for state in 0..16 { + assert_eq!( + eval(&before_prefix, state, condition), + eval(&after[..2], state, condition) + ); + } + } + } + + #[test] + fn condition_stack_is_a_hard_barrier() { + let mut push = Op::empty(); + push.kind = OperationType::PushCondition; + push.c_condition = BitId(9); + let mut pop = Op::empty(); + pop.kind = OperationType::PopCondition; + let mut ops = vec![ccx(0, 1, 2), push, cx(2, 3), pop, ccx(0, 1, 2)]; + ops.extend(nonce_tail()); + assert!(rewrite_first_target_fanout(ops, 96).is_err()); + } +} diff --git a/src/point_add/trailmix_ludicrous/arith.rs b/src/point_add/trailmix_ludicrous/arith.rs index cca0ce7d..2c3a34b4 100644 --- a/src/point_add/trailmix_ludicrous/arith.rs +++ b/src/point_add/trailmix_ludicrous/arith.rs @@ -1,2091 +1,2068 @@ - -use super::{B, BExt}; -use crate::circuit::{BitId, QubitId}; -use std::cell::Cell; - -thread_local! { - static FFG_CALL_INDEX: Cell = const { Cell::new(0) }; - static FFG_SHIFTED_SQUARE_PREFIX_SCOPE: Cell = const { Cell::new(0) }; - static CUCCARO_CALL_INDEX: Cell = const { Cell::new(0) }; - static CONST_CHUNK_CALL_INDEX: Cell = const { Cell::new(0) }; - static ADD_CONST_CALL_INDEX: Cell = const { Cell::new(0) }; -} - -pub(super) fn reset_ffg_call_index() { - FFG_CALL_INDEX.with(|index| index.set(0)); - CUCCARO_CALL_INDEX.with(|index| index.set(0)); - CONST_CHUNK_CALL_INDEX.with(|index| index.set(0)); - ADD_CONST_CALL_INDEX.with(|index| index.set(0)); -} - -fn next_ffg_call_index() -> usize { - FFG_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -pub(super) fn with_shifted_square_ffg_prefix_scope(body: impl FnOnce() -> R) -> R { - FFG_SHIFTED_SQUARE_PREFIX_SCOPE.with(|scope| { - let prior = scope.get(); - scope.set(prior + 1); - let result = body(); - scope.set(prior); - result - }) -} - -fn shifted_square_ffg_prefix_scope_enabled() -> bool { - std::env::var_os("TLM_SQUARE_SHIFTED_FFG_PREFIX_SKIP").is_some() - && FFG_SHIFTED_SQUARE_PREFIX_SCOPE.with(|scope| scope.get() > 0) -} - -fn next_cuccaro_call_index() -> usize { - CUCCARO_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_const_chunk_call_index() -> usize { - CONST_CHUNK_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_add_const_call_index() -> usize { - ADD_CONST_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn env_index_value(name: &str, index: usize) -> Option { - std::env::var(name) - .ok() - .and_then(|value| { - value - .split(',') - .filter_map(|item| item.trim().split_once(':')) - .find_map(|(call, value)| { - (call.parse::().ok()? == index) - .then(|| value.parse::().ok()) - .flatten() - }) - }) -} - -fn env_index_list_contains(name: &str, index: usize) -> bool { - std::env::var(name) - .ok() - .map(|value| { - value - .split(',') - .filter_map(|item| item.trim().parse::().ok()) - .any(|candidate| candidate == index) - }) - .unwrap_or(false) -} - -const FFG_DEAD_HYBRID_CARRY_RANGES: &[(usize, usize, usize)] = &[ - (264, 1, 46), - (265, 1, 46), - (266, 1, 46), - (267, 1, 46), - (268, 1, 46), - (271, 1, 46), - (272, 1, 46), - (273, 1, 46), - (274, 1, 46), - (275, 1, 46), - (277, 1, 46), - (278, 1, 46), - (279, 1, 46), - (280, 1, 46), - (281, 1, 46), - (596, 21, 24), - (596, 26, 31), - (596, 42, 46), - (2, 1, 3), - (2, 28, 31), - (598, 1, 3), - (598, 27, 27), - (598, 30, 31), - (3, 1, 3), - (3, 29, 29), - (3, 31, 31), - (340, 1, 5), - (51, 28, 31), - (131, 28, 31), - (198, 28, 31), - (201, 28, 31), - (597, 1, 3), - (597, 29, 29), - (13, 29, 31), - (37, 29, 31), - (50, 29, 31), - (60, 29, 31), - (64, 28, 28), - (64, 30, 31), - (73, 29, 31), - (75, 29, 31), - (80, 29, 31), - (105, 29, 31), - (113, 29, 31), - (115, 28, 28), - (115, 30, 31), - (116, 29, 31), - (119, 29, 31), - (126, 29, 31), - (137, 29, 31), - (139, 28, 29), - (139, 31, 31), - (140, 29, 31), - (147, 29, 31), - (178, 29, 31), - (190, 29, 31), - (199, 29, 31), - (209, 28, 28), - (209, 30, 31), - (284, 29, 31), - (288, 29, 31), - (293, 29, 31), - (295, 29, 31), - (318, 29, 31), - (405, 29, 31), - (409, 28, 28), - (409, 30, 31), - (416, 29, 31), - (424, 28, 28), - (424, 30, 31), - (433, 28, 28), - (433, 30, 31), - (434, 29, 31), - (444, 29, 31), - (464, 29, 31), - (471, 29, 31), - (478, 28, 28), - (478, 30, 31), - (487, 28, 28), - (487, 30, 31), - (498, 29, 31), - (516, 29, 31), - (518, 29, 31), - (548, 28, 28), - (548, 30, 31), - (553, 29, 31), - (559, 29, 31), - (560, 29, 31), - (568, 29, 31), - (570, 29, 31), - (575, 29, 31), - (580, 29, 31), - (586, 29, 31), - (592, 29, 31), -]; - -fn ffg_call_has_structurally_dead_hybrid_carry(call_index: usize, bit: usize, phase: &str) -> bool { - if super::drops_off_family("FFG") { - return false; - } - - if shifted_square_ffg_prefix_scope_enabled() && bit > 0 { - return true; - } - if std::env::var_os("TLM_FFG_SKIP_TOP_CARRY31").is_some() && bit == 31 { - return true; - } - if std::env::var_os("TLM_FFG_SKIP_TOP_CARRY30").is_some() && bit == 30 { - return true; - } - if std::env::var_os("TLM_FFG_SKIP_INVERSE_MOD_SUB_TOP29").is_some() - && bit == 29 - && phase == "tlm_apply_inverse_mod_sub_fold" - && call_index - <= std::env::var("TLM_FFG_INVERSE_TOP29_MAX_CALL") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(usize::MAX) - { - return true; - } - if std::env::var_os("TLM_FFG_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { - return false; - } - if std::env::var_os("TLM_FFG_SKIP_EXACT_TOP29_REMAINDER").is_some() { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if FFG_TOP29_REMAINDER_KEYS.binary_search(&key).is_ok() { - return true; - } - } - FFG_DEAD_HYBRID_CARRY_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -const FFG_TOP29_REMAINDER_KEYS: &[u32] = &[ - 1821, 2333, 3869, 6685, 7197, 7453, 13341, 15901, 19741, 19997, 20253, 22044, - 25885, 26397, 27933, 31517, 32796, 34077, 36125, 36380, 38173, 38941, 40989, - 41757, 42525, 44316, 46621, 50205, 54045, 54557, 68893, 72221, 74781, 79133, - 85277, 85789, 86557, 102685, 103453, 104989, 108061, 110365, 112669, 115741, - 117789, 120861, 121117, 123165, 126493, 126749, 127260, 128797, 129053, - 130844, 131101, 137245, 144157, 144669, 147741, 149021, 149533, 151069, -]; - -const CONST_CHUNK_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (879, 0, 9), - (880, 0, 8), - (700, 0, 7), - (881, 0, 7), - (887, 0, 7), - (900, 0, 7), - (678, 0, 6), - (686, 0, 6), - (707, 0, 6), - (882, 0, 6), - (894, 0, 6), - (906, 0, 6), - (649, 2, 7), - (654, 2, 7), - (692, 1, 6), - (715, 0, 4), - (715, 7, 7), - (883, 0, 5), - (638, 0, 1), - (638, 3, 5), - (689, 0, 4), - (691, 3, 7), - (706, 2, 2), - (706, 4, 7), - (718, 0, 4), - (884, 0, 4), - (890, 0, 4), - (897, 0, 4), - (903, 0, 4), - (909, 0, 4), - (912, 1, 5), - (919, 0, 4), - (626, 1, 4), - (659, 4, 7), - (666, 0, 3), - (671, 3, 3), - (671, 5, 7), - (672, 0, 3), - (685, 5, 8), - (703, 1, 4), - (704, 0, 3), - (714, 5, 8), - (717, 2, 5), - (891, 0, 3), - (893, 5, 8), - (926, 0, 3), - (941, 0, 3), - (949, 1, 1), - (949, 3, 4), - (949, 6, 6), - (956, 2, 5), - (481, 1, 3), - (485, 1, 3), - (520, 5, 7), - (579, 1, 2), - (579, 4, 4), - (590, 2, 4), - (636, 0, 2), - (644, 4, 5), - (644, 7, 7), - (663, 1, 3), - (665, 4, 4), - (665, 6, 7), - (669, 0, 0), - (669, 2, 3), - (675, 1, 3), - (677, 4, 5), - (677, 7, 7), - (682, 0, 2), - (696, 0, 2), - (710, 0, 1), - (710, 3, 3), - (711, 0, 2), - (723, 0, 2), - (725, 0, 2), - (727, 0, 2), - (729, 0, 2), - (731, 0, 2), - (737, 0, 2), - (739, 0, 2), - (741, 0, 2), - (743, 0, 2), - (745, 0, 2), - (749, 0, 2), - (751, 0, 2), - (753, 0, 2), - (755, 0, 2), - (757, 0, 2), - (896, 3, 5), - (905, 5, 5), - (905, 7, 8), - (911, 5, 7), - (916, 0, 2), - (918, 5, 7), - (923, 0, 2), - (931, 5, 7), - (932, 0, 2), - (935, 1, 3), - (937, 5, 7), - (944, 0, 2), - (962, 2, 4), - (968, 1, 3), - (973, 1, 3), - (978, 1, 3), - (983, 0, 2), - (1023, 1, 3), - (1039, 0, 2), - (1044, 1, 3), - (1109, 3, 5), - (1149, 1, 3), - (1622, 0, 2), -]; - -const CONST_CHUNK_REMAINDER_KEYS: &[u32] = &[ - 1281, 5376, 5377, 6913, 8449, 8960, 9473, 10496, 15616, 16641, 17153, 19201, - 19713, 20736, 22785, 23809, 27905, 29440, 38656, 40705, 43777, 49921, 51457, - 57089, 58113, 59649, 64257, 66305, 66816, 68865, 70400, 70401, 70913, 77569, - 79361, 80898, 99074, 113408, 116224, 117248, 118016, 118017, 119043, 120064, - 120065, 121090, 121091, 122115, 125189, 126467, 127492, 127493, 128772, 128774, - 130308, 130309, 131589, 131590, 135936, 136711, 136960, 136961, 137990, 137991, - 139015, 139264, 140035, 140545, 141315, 141575, 141824, 142855, 143105, 144385, - 144386, 145155, 145415, 145665, 146946, 149761, 149762, 152579, 152581, 153861, - 154112, 155137, 156166, 156417, 157447, 157696, 157697, 158466, 158978, 159746, - 161794, 161796, 164354, 165120, 166915, 167680, 168960, 168961, 169475, 174339, - 174848, 174849, 176132, 176133, 177922, 177923, 178432, 178433, 178952, 179456, - 179457, 181506, 181507, 182272, 182273, 185344, 185345, 185856, 185857, 186368, - 186369, 186880, 186881, 187392, 187393, 188928, 188929, 189440, 189441, 189952, - 189953, 190464, 190465, 190976, 190977, 192000, 192001, 192512, 192513, 193024, - 193025, 193536, 193537, 194048, 194049, 196609, 199680, 200192, 200193, 214017, - 217089, 223233, 226822, 226824, 227328, 227329, 230151, 232453, 234242, 234243, - 236035, 236806, 236807, 237826, 237827, 240128, 240129, 241414, 241415, 242435, - 244225, 245761, 245762, 247296, 248579, 252419, 252930, 254214, 255491, 255493, - 257027, 257028, 258050, 258566, 259840, 260354, 260355, 263172, 264707, 268546, - 269825, 271105, 271106, 272385, 273154, 273155, 273415, 273664, 274689, 275968, - 276743, 277767, 278016, 278789, 278791, 279812, 279814, 281089, 281348, 281350, - 282373, 282374, 285188, 285190, 286723, 286725, 288003, 288004, 289284, 289285, - 290306, 290562, 290564, 291842, 292865, 292868, 295170, 296195, 297217, 297218, - 299265, 299266, 300288, 301312, 302081, 303104, 304897, 305152, 323329, 328194, - 330499, 341761, 345857, 346369, 346881, 347905, 352512, 354049, 359168, 361217, - 361729, 362241, 367873, 368385, 369920, 371457, 374529, 375040, 375041, 376577, - 378625, 380672, 380673, 381697, 385281, 386817, 391937, 393985, 395008, 398593, - 400641, 402689, 405761, 407809, 411393, 415488, 415489, 416001, 416513, -]; - -fn const_chunk_call_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("CONSTCHUNK") { - return false; - } - - if std::env::var_os("TLM_CONST_CHUNK_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { - return false; - } - if std::env::var_os("TLM_CONST_CHUNK_SKIP_EXACT_REMAINDER").is_some() { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if CONST_CHUNK_REMAINDER_KEYS.binary_search(&key).is_ok() { - return true; - } - } - CONST_CHUNK_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn cuccaro_call_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("CUCCARO") { - return false; - } - - if std::env::var_os("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { - return false; - } - match call_index { - - 12 | 25 => (0..=127).contains(&bit), - 37 => bit <= 135, - 19 => (0..=127).contains(&bit), - 20 | 26 => bit >= 148, - 13 => bit >= 150, - 21 => matches!(bit, 147 | 148) || (150..=251).contains(&bit), - 27 => (148..=251).contains(&bit), - 22 => bit == 146 || (148..=249).contains(&bit), - 28 => (147..=249).contains(&bit), - 14 => matches!(bit, 150 | 151) || (153..=251).contains(&bit), - 15 => (151..=249).contains(&bit), - 29 => (147..=245).contains(&bit), - 23 => matches!(bit, 148 | 149) || (151..=245).contains(&bit), - 16 => (151..=245).contains(&bit), - 30 => (149..=223).contains(&bit), - 24 => (150..=223).contains(&bit), - 17 => bit == 149 || (152..=223).contains(&bit), - _ => false, - } -} - -fn add_const_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("ADDCONST") { - return false; - } - - if std::env::var_os("TLM_ADD_CONST_SKIP_STRUCTURAL_DEAD_CARRIES").is_none() { - return false; - } - call_index == 0 && (bit == 55 || bit >= 57) -} - -pub const F_SECP256K1: u64 = (1u64 << 32) + 977; - -pub const F_BITLEN: usize = 33; - -pub const PAD: usize = 19; - -pub const LSBS: usize = 20 + F_BITLEN; - -pub const MSBS: usize = PAD; - -#[inline] -pub fn msbs() -> usize { - static V: std::sync::OnceLock = std::sync::OnceLock::new(); - *V.get_or_init(|| { - std::env::var("TLM_MSBS").ok().and_then(|s| s.parse::().ok()).unwrap_or(PAD) - }) -} - -pub const APPLY_CHUNK: usize = 40; - -#[inline] -fn cbit(c: &[u8], i: usize) -> bool { - let byte = i / 8; - byte < c.len() && (c[byte] >> (i % 8)) & 1 == 1 -} - -pub fn cuccaro_carry( - circ: &mut B, - ctrl: Option<&QubitId>, - x: &[QubitId], - y: &[QubitId], - cin: Option<&QubitId>, - cout: Option<&QubitId>, -) { - let call_index = next_cuccaro_call_index(); - let ops_start = circ.current_ops_len(); - let s = y.len(); - assert_eq!(x.len(), s, "cuccaro_carry: x,y width mismatch"); - let fresh = if cin.is_none() { Some(circ.alloc_qubit()) } else { None }; - let c: &QubitId = cin.unwrap_or_else(|| fresh.as_ref().unwrap()); - let sum = |circ: &mut B, xi: &QubitId, yi: &QubitId| match ctrl { - Some(ct) => circ.ccx(*ct, *xi, *yi), - None => circ.cx(*xi, *yi), - }; - let gated_carry = |circ: &mut B, co: &QubitId| match ctrl { - Some(ct) => circ.ccx(*ct, *c, *co), - None => circ.cx(*c, *co), - }; - if s == 0 { - if let Some(co) = cout { - gated_carry(circ, co); - } - } else { - - for i in 0..s { - circ.cx(*c, y[i]); - circ.cx(*c, x[i]); - if !cuccaro_call_has_structurally_dead_carry(call_index, i) { - let old_context = crate::point_add::set_op_trace_context( - 0x0200_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(x[i], y[i], *c); - crate::point_add::restore_op_trace_context(old_context); - } - } - if let Some(co) = cout { - gated_carry(circ, co); - } - - for i in (0..s).rev() { - if !cuccaro_call_has_structurally_dead_carry(call_index, i) { - let old_context = crate::point_add::set_op_trace_context( - 0x0300_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(x[i], y[i], *c); - crate::point_add::restore_op_trace_context(old_context); - } - circ.cx(*c, y[i]); - sum(circ, &x[i], &y[i]); - circ.cx(*c, x[i]); - } - } - if let Some(f) = fresh { - circ.zero_and_free(f); - } - if std::env::var_os("TRACE_TLM_CUCCARO").is_some() { - eprintln!( - "TLM_CUCCARO call={} phase={} width={} ctrl={} cin={} cout={} ops_start={} ops_end={}", - call_index, - circ.phase, - s, - usize::from(ctrl.is_some()), - usize::from(cin.is_some()), - usize::from(cout.is_some()), - ops_start, - circ.current_ops_len(), - ); - } -} - -fn clean_add_threaded_opt( - circ: &mut B, - ctrl: Option<&QubitId>, - x: &[QubitId], - y: &[QubitId], - cin: Option<&QubitId>, - cout: Option<&QubitId>, -) { - let s = y.len(); - assert_eq!(x.len(), s, "vented add: x,y width mismatch"); - - let gated_sum = |circ: &mut B, xi: &QubitId, yi: &QubitId| match ctrl { - Some(ct) => circ.ccx(*ct, *xi, *yi), - None => circ.cx(*xi, *yi), - }; - if s == 0 { - if let (Some(ci), Some(co)) = (cin, cout) { - match ctrl { - Some(ct) => circ.ccx(*ct, *ci, *co), - None => circ.cx(*ci, *co), - } - } - return; - } - let n_inner = if cout.is_some() { s } else { s - 1 }; - let mut inner: Vec> = (0..n_inner).map(|_| Some(circ.alloc_qubit())).collect(); - let produces = |i: usize| cout.is_some() || i + 1 < s; - - for i in 0..s { - if !produces(i) { - continue; - } - let co = inner[i].as_ref().unwrap(); - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, x[i]); - circ.cx(*ci, y[i]); - circ.ccx(x[i], y[i], *co); - circ.cx(*ci, *co); - } else { - circ.ccx(x[i], y[i], *co); - } - } - if let Some(cout) = cout { - let top = inner[s - 1].as_ref().unwrap(); - match ctrl { - Some(ct) => circ.ccx(*ct, *top, *cout), - None => circ.cx(*top, *cout), - } - } - - for i in (0..s).rev() { - if !produces(i) { - - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, x[i]); - } - gated_sum(circ, &x[i], &y[i]); - if let Some(ci) = ci { - circ.cx(*ci, x[i]); - } - continue; - } - let co = inner[i].take().unwrap(); - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, co); - } - - let bit = circ.alloc_bit(); - circ.hmr(co, bit); - circ.zero_and_free(co); - circ.cz_if_bit(x[i], y[i], bit); - if let Some(ci) = ci { - circ.cx(*ci, y[i]); - } - gated_sum(circ, &x[i], &y[i]); - if let Some(ci) = ci { - circ.cx(*ci, x[i]); - } - } -} - -pub(crate) fn erase_carry_gated_opt( - circ: &mut B, - ctrl: Option<&QubitId>, - a: &[QubitId], - b: &[QubitId], - cin: &QubitId, - carry: &QubitId, - cap: Option, -) { - let s = a.len(); - let bit = circ.alloc_bit(); - circ.hmr(*carry, bit); - - circ.loan_zero_qubit(*carry); - circ.push_condition(bit); - let deposit = |c: &mut B, ta: &QubitId, tb: &QubitId, c_prev: &QubitId| match ctrl { - Some(ct) => { - c.z(*ct); - c.ccz(*ct, *ta, *tb); - c.cz(*ct, *c_prev); - } - None => { - c.neg(); - c.cz(*ta, *tb); - c.z(*c_prev); - } - }; - match cap { - Some(k) if k < s => { - - let lo = s - k; - let zcin = circ.alloc_qubit(); - super::comparator::compare_geq_cin_middle(circ, &a[lo..], &b[lo..], &zcin, deposit); - circ.zero_and_free(zcin); - } - _ => { - super::comparator::compare_geq_cin_middle(circ, a, b, cin, deposit); - } - } - circ.pop_condition(); -} - -pub(crate) fn erase_carry_gated_zero_cin_opt( - circ: &mut B, - ctrl: Option<&QubitId>, - a: &[QubitId], - b: &[QubitId], - carry: &QubitId, - cap: Option, -) { - let s = a.len(); - let bit = circ.alloc_bit(); - circ.hmr(*carry, bit); - circ.push_condition(bit); - let deposit = |c: &mut B, ta: &QubitId, tb: &QubitId, c_prev: &QubitId| match ctrl { - Some(ct) => { - c.z(*ct); - c.ccz(*ct, *ta, *tb); - c.cz(*ct, *c_prev); - } - None => { - c.neg(); - c.cz(*ta, *tb); - c.z(*c_prev); - } - }; - match cap { - Some(k) if k < s => { - let lo = s - k; - let zcin = circ.alloc_qubit(); - super::comparator::compare_geq_cin_middle(circ, &a[lo..], &b[lo..], &zcin, deposit); - circ.zero_and_free(zcin); - } - _ => { - super::comparator::compare_geq_cin_middle(circ, a, b, carry, deposit); - } - } - circ.pop_condition(); -} - -pub fn controlled_add_vented_chunked_cout( - circ: &mut B, - ctrl: &QubitId, - x: &[QubitId], - y: &[QubitId], - chunk: usize, - cout: Option<&QubitId>, -) { - add_vented_chunked_opt(circ, Some(ctrl), x, y, chunk, cout, None); -} - -pub const CEILING: usize = 1167; - -fn emit_chunked_capped( - circ: &mut B, - ctrl: Option<&QubitId>, - x: &[QubitId], - y: &[QubitId], - bounds: &[(usize, usize)], - plain_len: usize, - cout: Option<&QubitId>, - cap: Option, -) { - let n = y.len(); - let l = n - plain_len; - let cin0 = circ.alloc_qubit(); - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(lo, hi)) in bounds.iter().enumerate() { - let cy = circ.alloc_qubit(); - let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; - clean_add_threaded_opt(circ, ctrl, &x[lo..hi], &y[lo..hi], Some(cin), Some(&cy)); - carries.push(cy); - } - if l < n { - let top_cin: &QubitId = carries.last().unwrap_or(&cin0); - clean_add_threaded_opt(circ, ctrl, &x[l..n], &y[l..n], Some(top_cin), cout); - } else if let Some(co) = cout { - circ.cx(*carries.last().unwrap(), *co); - } - for j in (0..bounds.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; - erase_carry_gated_opt(circ, ctrl, &y[lo..hi], &x[lo..hi], cin, &carry, cap); - } - circ.zero_and_free(cin0); -} - -fn hybrid_add_plain(circ: &mut B, a: &[QubitId], b: &[QubitId], vents_budget: usize) { - let n = a.len(); - assert_eq!(b.len(), n, "hybrid_add: a,b width mismatch"); - if n == 0 { - return; - } - if n == 1 { - circ.cx(b[0], a[0]); - return; - } - let vents = vents_budget.min(n - 1); - for i in 1..n { - circ.cx(b[i], a[i]); - } - for i in (1..n - 1).rev() { - circ.cx(b[i], b[i + 1]); - } - let mut vent_ancs: Vec> = (0..n - 1).map(|_| None).collect(); - for i in 0..n - 1 { - if i < vents { - let anc = circ.alloc_qubit(); - circ.ccx(a[i], b[i], anc); - circ.cx(anc, b[i + 1]); - vent_ancs[i] = Some(anc); - } else { - circ.ccx(a[i], b[i], b[i + 1]); - } - } - for i in (0..n - 1).rev() { - circ.cx(b[i + 1], a[i + 1]); - if i < vents { - let anc = vent_ancs[i].take().unwrap(); - circ.cx(anc, b[i + 1]); - let bit = circ.alloc_bit(); - circ.hmr(anc, bit); - circ.zero_and_free(anc); - circ.cz_if_bit(a[i], b[i], bit); - } else { - circ.ccx(a[i], b[i], b[i + 1]); - } - } - for i in 1..n - 1 { - circ.cx(b[i], b[i + 1]); - } - circ.cx(b[0], a[0]); - for i in 1..n { - circ.cx(b[i], a[i]); - } -} - -pub(crate) fn hybrid_add_adaptive(circ: &mut B, a: &[QubitId], b: &[QubitId], k: usize) { - let n = a.len(); - assert_eq!(b.len(), n, "adaptive add: a,b width mismatch"); - if n == 0 { - return; - } - let c = ((n as f64).sqrt() as usize).clamp(1, n); - if n <= 4 || k.saturating_add(2 * c) >= n { - hybrid_add_plain(circ, a, b, k); - return; - } - if k < n.div_ceil(c) + c + super::gidney::ADAPTIVE_RES { - let cov = (k.saturating_mul(k.saturating_sub(1)) / 2).min(n); - if cov > 2 * k { - - unreachable!("square adaptive add hit the tight chunked_then_cuccaro branch (n={n}, k={k})"); - } - hybrid_add_plain(circ, a, b, k); - return; - } - let lay = super::gidney::adaptive_layout(n, k); - let l = lay.chunked_len; - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let mut lo = 0; - while lo < l { - let hi = (lo + lay.c).min(l); - bounds.push((lo, hi)); - lo = hi; - } - - emit_chunked_capped(circ, None, b, a, &bounds, lay.plain_len, None, None); -} - -fn add_vented_chunked_opt( - circ: &mut B, - ctrl: Option<&QubitId>, - x: &[QubitId], - y: &[QubitId], - chunk: usize, - cout: Option<&QubitId>, - cap: Option, -) { - add_vented_chunked_opt_capped(circ, ctrl, x, y, chunk, cout, cap, usize::MAX); -} - -#[allow(clippy::too_many_arguments)] -fn add_vented_chunked_opt_capped( - circ: &mut B, - ctrl: Option<&QubitId>, - x: &[QubitId], - y: &[QubitId], - chunk: usize, - cout: Option<&QubitId>, - cap: Option, - max_vents: usize, -) { - let n = y.len(); - assert_eq!(x.len(), n, "chunked add: x,y width mismatch"); - if n == 0 { - return; - } - - let c = chunk.clamp(1, n); - let live = circ.active_qubits as usize; - - let k = CEILING.saturating_sub(live).clamp(1, n).min(max_vents); - let plain_len = if k >= n { - n - } else if c <= 1 { - 0 - } else { - ((k * c).saturating_sub(n) / (c - 1)).min(n) - }; - let l = n - plain_len; - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let mut lo = 0; - while lo < l { - let hi = (lo + c).min(l); - bounds.push((lo, hi)); - lo = hi; - } - emit_chunked_capped(circ, ctrl, x, y, &bounds, plain_len, cout, cap); -} - -fn ccx_cond(circ: &mut B, ctrl: &QubitId, c1: &QubitId, c2: &QubitId, t: &QubitId, b0: bool, b1: bool) { - if b0 { circ.cx(*ctrl, *c1); } - if b1 { circ.cx(*ctrl, *c2); } - circ.ccx(*c1, *c2, *t); - if b0 { circ.cx(*ctrl, *c1); } - if b1 { circ.cx(*ctrl, *c2); } -} - -fn xor_carries_off_cin(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], off: usize, out: &[QubitId], cin: &QubitId) { - let n = a.len(); - for i in (1..n - 1).rev() { - ccx_cond(circ, ctrl, &a[i], &out[i - 1], &out[i], cbit(c, off + i), false); - } - for i in 0..n - 1 { - if cbit(c, off + i) { circ.cx(*ctrl, out[i]); } - } - ccx_cond(circ, ctrl, cin, &a[0], &out[0], cbit(c, off), cbit(c, off)); - for i in 1..n - 1 { - ccx_cond(circ, ctrl, &a[i], &out[i - 1], &out[i], cbit(c, off + i), cbit(c, off + i)); - } -} - -fn dirty_carryin(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], off: usize, dirty: &[QubitId], cin: &QubitId) { - let n = a.len(); - debug_assert!(n >= 2 && dirty.len() >= n - 1); - let mut bits: Vec = Vec::with_capacity(n - 1); - let mut cy_owned: Option = None; - for i in 0..(n - 1) { - let new = circ.alloc_qubit(); - let anc = circ.alloc_qubit(); - let on = cbit(c, off + i); - let cyref: QubitId = match cy_owned { Some(q) => q, None => *cin }; - if on { circ.cx(*ctrl, anc); } - circ.cx(cyref, anc); - circ.cx(cyref, a[i]); - circ.ccx(a[i], anc, new); - circ.cx(cyref, new); - circ.cx(new, dirty[i]); - circ.cx(cyref, anc); - if on { circ.cx(*ctrl, anc); circ.cx(*ctrl, a[i]); } - circ.zero_and_free(anc); - if let Some(old) = cy_owned.take() { - let b = circ.alloc_bit(); - circ.hmr(old, b); - bits.push(b); - circ.zero_and_free(old); - } - cy_owned = Some(new); - } - let cy_top = cy_owned.take().unwrap(); - if cbit(c, off + n - 1) { circ.cx(*ctrl, a[n - 1]); } - circ.cx(cy_top, a[n - 1]); - { - let b = circ.alloc_bit(); - circ.hmr(cy_top, b); - bits.push(b); - } - circ.zero_and_free(cy_top); - for i in 0..(n - 1) { circ.z_if_bit(dirty[i], bits[i]); } - for q in a { circ.x(*q); } - xor_carries_off_cin(circ, ctrl, a, c, off, dirty, cin); - for q in a { circ.x(*q); } - for i in 0..(n - 1) { circ.z_if_bit(dirty[i], bits[i]); } -} - -fn graduated_const_fits(n: usize, k: usize) -> bool { - k >= 4 && (k - 3) * (k - 2) / 2 >= n -} -fn graduated_const_kmin(n: usize) -> usize { - (4..).find(|&k| graduated_const_fits(n, k)).unwrap() -} - -fn const_chunk_add_clean(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, cout: &QubitId) { - let call_index = next_const_chunk_call_index(); - let s = a.len(); - if std::env::var_os("TRACE_TLM_CONST_CHUNK").is_some() { - eprintln!( - "CONST_CHUNK call={} phase={} width={} coff={} cin={} cout={}", - call_index, - circ.phase, - s, - coff, - cin.0, - cout.0, - ); - } - if s == 0 { - return; - } - let mut int: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); - for i in 0..s { - let on = cbit(c, coff + i); - let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; - let cout_ref: QubitId = if i == s - 1 { *cout } else { *int[i].as_ref().unwrap() }; - circ.cx(cin_ref, a[i]); - if on { - circ.cx(*ctrl, cin_ref); - } - let old_context = crate::point_add::set_op_trace_context( - 0x0800_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - if !const_chunk_call_has_structurally_dead_carry(call_index, i) { - circ.ccx(a[i], cin_ref, cout_ref); - } - crate::point_add::restore_op_trace_context(old_context); - if on { - circ.cx(*ctrl, cin_ref); - } - circ.cx(cin_ref, cout_ref); - } - for i in 0..s { - if cbit(c, coff + i) { - circ.cx(*ctrl, a[i]); - } - } - for i in (0..s - 1).rev() { - let on = cbit(c, coff + i); - let int_i = int[i].take().unwrap(); - let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; - if on { - circ.cx(*ctrl, a[i]); - } - circ.cx(cin_ref, int_i); - if on { - circ.cx(*ctrl, cin_ref); - } - let b = circ.alloc_bit(); - circ.hmr(int_i, b); - circ.zero_and_free(int_i); - circ.cz_if_bit(a[i], cin_ref, b); - if on { - circ.cx(*ctrl, cin_ref); - circ.cx(*ctrl, a[i]); - } - } -} - -fn const_chunk_add_clean_drop_cout(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId) { - let s = a.len(); - if s == 0 { - return; - } - if s == 1 { - if cbit(c, coff) { - circ.cx(*ctrl, a[0]); - } - circ.cx(*cin, a[0]); - return; - } - let mut int: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); - for i in 0..s - 1 { - let on = cbit(c, coff + i); - let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; - let cout_ref: QubitId = *int[i].as_ref().unwrap(); - circ.cx(cin_ref, a[i]); - if on { - circ.cx(*ctrl, cin_ref); - } - circ.ccx(a[i], cin_ref, cout_ref); - if on { - circ.cx(*ctrl, cin_ref); - } - circ.cx(cin_ref, cout_ref); - } - for i in 0..s - 1 { - if cbit(c, coff + i) { - circ.cx(*ctrl, a[i]); - } - } - if cbit(c, coff + s - 1) { - circ.cx(*ctrl, a[s - 1]); - } - circ.cx(*int[s - 2].as_ref().unwrap(), a[s - 1]); - for i in (0..s - 1).rev() { - let on = cbit(c, coff + i); - let int_i = int[i].take().unwrap(); - let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; - if on { - circ.cx(*ctrl, a[i]); - } - circ.cx(cin_ref, int_i); - if on { - circ.cx(*ctrl, cin_ref); - } - let b = circ.alloc_bit(); - circ.hmr(int_i, b); - circ.zero_and_free(int_i); - circ.cz_if_bit(a[i], cin_ref, b); - if on { - circ.cx(*ctrl, cin_ref); - circ.cx(*ctrl, a[i]); - } - } -} - -fn compare_geq_const_cin_middle(circ: &mut B, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, body: F) { - let s = a.len(); - let mut cy: Vec> = Vec::with_capacity(s); - let c0 = circ.alloc_qubit(); - circ.x(c0); - circ.cx(*cin, c0); - cy.push(Some(c0)); - for i in 0..s - 1 { - let on = cbit(c, coff + i); - let next = circ.alloc_qubit(); - let ci = *cy[i].as_ref().unwrap(); - circ.ccx(a[i], ci, next); - if !on { - circ.cx(a[i], next); - circ.cx(ci, next); - } - cy.push(Some(next)); - } - { - let i = s - 1; - let on = cbit(c, coff + i); - let ci = *cy[i].as_ref().unwrap(); - body(circ, &a[i], &ci, on); - } - for i in (0..s - 1).rev() { - let on = cbit(c, coff + i); - let next = cy[i + 1].take().unwrap(); - let ci = *cy[i].as_ref().unwrap(); - if !on { - circ.cx(ci, next); - circ.cx(a[i], next); - } - let b = circ.alloc_bit(); - circ.hmr(next, b); - circ.zero_and_free(next); - circ.cz_if_bit(a[i], ci, b); - } - let c0 = cy[0].take().unwrap(); - circ.cx(*cin, c0); - circ.x(c0); - circ.zero_and_free(c0); -} - -fn controlled_erase_carry_gated_const(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, carry: QubitId) { - let bit = circ.alloc_bit(); - circ.hmr(carry, bit); - - circ.loan_zero_qubit(carry); - circ.push_condition(bit); - compare_geq_const_cin_middle(circ, a, c, coff, cin, |cc, a_top, cy_top, ctop| { - - cc.z(*ctrl); - cc.ccz(*ctrl, *a_top, *cy_top); - if !ctop { - cc.cz(*ctrl, *a_top); - cc.cz(*ctrl, *cy_top); - } - }); - circ.pop_condition(); -} - -fn controlled_add_const_chunked_graduated_off(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, k: usize) { - let n = a.len(); - if n == 0 { - return; - } - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let (mut lo, mut i) = (0usize, 0usize); - while lo < n && k > i + 3 { - let cc = (k - 3 - i).min(n - lo); - bounds.push((lo, lo + cc)); - lo += cc; - i += 1; - } - assert_eq!(lo, n, "graduated staircase (k={k}) covers {lo} < n={n}"); - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(clo, chi)) in bounds.iter().enumerate() { - if std::env::var("TLM_GRAD_FINAL_NO_COUT").ok().as_deref() == Some("1") && j + 1 == bounds.len() { - let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; - const_chunk_add_clean_drop_cout(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref); - break; - } - let cout = circ.alloc_qubit(); - let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; - const_chunk_add_clean(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref, &cout); - carries.push(cout); - } - for j in (0..carries.len()).rev() { - let (clo, chi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; - controlled_erase_carry_gated_const(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref, carry); - } -} - -#[allow(clippy::needless_range_loop)] -fn add_f_window_hybrid( - circ: &mut B, - ctrl: &QubitId, - reg: &[QubitId], - lsbs: usize, - c: &[u8], - k: usize, - trace_call_index: usize, -) { - let n = lsbs; - let a: Vec = reg[..n].to_vec(); - let suf_dirty = n - k - 1; - assert!(reg.len() >= lsbs + suf_dirty, "+f hybrid: not enough high bits to borrow"); - let dirty: Vec = (lsbs..lsbs + suf_dirty).map(|i| reg[i]).collect(); - let mut cy: Vec> = (0..k).map(|_| Some(circ.alloc_qubit())).collect(); - - if cbit(c, 0) { circ.ccx(*ctrl, a[0], *cy[0].as_ref().unwrap()); } - for i in 1..k { - let ci = *cy[i - 1].as_ref().unwrap(); - let next = *cy[i].as_ref().unwrap(); - circ.cx(ci, a[i]); - if cbit(c, i) { circ.cx(*ctrl, ci); } - if !ffg_call_has_structurally_dead_hybrid_carry(trace_call_index, i, circ.phase) { - let old_context = crate::point_add::set_op_trace_context( - 0x0100_0000 | (((trace_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(a[i], ci, next); - crate::point_add::restore_op_trace_context(old_context); - } - if cbit(c, i) { circ.cx(*ctrl, ci); } - circ.cx(ci, next); - } - - for i in 0..k { if cbit(c, i) { circ.cx(*ctrl, a[i]); } } - let release_cy0_during_suffix = - std::env::var("TLM_FFG_RELEASE_CY0_DURING_SUFFIX") - .ok() - .as_deref() - == Some("1") - && (std::env::var_os("TLM_FFG_RELEASE_CY0_CALLS").is_none() - || env_index_list_contains("TLM_FFG_RELEASE_CY0_CALLS", trace_call_index)) - && k > 1 - && cbit(c, 0); - if release_cy0_during_suffix { - let cy0 = *cy[0].as_ref().unwrap(); - - circ.x(a[0]); - circ.ccx(*ctrl, a[0], cy0); - circ.x(a[0]); - circ.loan_zero_qubit(cy0); - } - - { - let a_hi: Vec = a[k..].to_vec(); - let cin = *cy[k - 1].as_ref().unwrap(); - let sn = n - k; - - if sn >= 2 { - controlled_add_const_chunked_graduated_off(circ, ctrl, &a_hi, c, k, &cin, graduated_const_kmin(sn)); - } else { - dirty_carryin(circ, ctrl, &a_hi, c, k, &dirty, &cin); - } - } - if release_cy0_during_suffix { - let cy0 = *cy[0].as_ref().unwrap(); - circ.reclaim_zero_qubit(cy0); - circ.x(a[0]); - circ.ccx(*ctrl, a[0], cy0); - circ.x(a[0]); - } - - for i in (1..k).rev() { - if cbit(c, i) { circ.cx(*ctrl, a[i]); } - let ci = *cy[i - 1].as_ref().unwrap(); - let next = *cy[i].as_ref().unwrap(); - circ.cx(ci, next); - if cbit(c, i) { circ.cx(*ctrl, ci); } - let nq = cy[i].take().unwrap(); - let b = circ.alloc_bit(); - circ.hmr(nq, b); - circ.zero_and_free(nq); - circ.cz_if_bit(a[i], ci, b); - if cbit(c, i) { circ.cx(*ctrl, ci); circ.cx(*ctrl, a[i]); } - } - - let cy0 = cy[0].take().unwrap(); - if cbit(c, 0) { - circ.cx(*ctrl, a[0]); - let b = circ.alloc_bit(); - circ.hmr(cy0, b); - circ.zero_and_free(cy0); - circ.cz_if_bit(a[0], *ctrl, b); - circ.cx(*ctrl, a[0]); - } else { - circ.zero_and_free(cy0); - } -} - -fn add_f_window(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8], g_sched: Option) { - let call_index = next_ffg_call_index(); - let timeline_start = circ.active_timeline.len(); - let n = lsbs; - assert!(n <= reg.len(), "register too short for +f window"); - if n == 0 { return; } - if n == 1 { - if cbit(c, 0) { circ.cx(*ctrl, reg[0]); } - return; - } - - let target_g = super::target_qubit_headroom(circ).map(|headroom| { - let mut reserve = std::env::var("TLM_TARGET_FFG_RESERVE") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(4); - if let Some(call_reserve) = - env_index_value("TLM_TARGET_FFG_CALL_RESERVES", call_index) - { - reserve = call_reserve; - } else if std::env::var("TLM_TARGET_FFG_RESERVE8_CALLS") - .ok() - .map(|value| { - value - .split(',') - .filter_map(|item| item.trim().parse::().ok()) - .any(|candidate| candidate == call_index) - }) - .unwrap_or(false) - { - reserve = 8; - } - if let Some(call_reserve) = - env_index_value("TLM_TARGET_FFG_CALL_RESERVE_OVERRIDES", call_index) - { - reserve = call_reserve; - } - headroom.saturating_sub(reserve) - }); - let scheduled_g = g_sched - .map_or_else(|| CEILING.saturating_sub(circ.active_qubits as usize), |g| g) - .min(target_g.unwrap_or(usize::MAX)) - .min(n - 1); - let capped_g = std::env::var("TLM_FFG_MAX_G") - .ok() - .and_then(|value| value.parse::().ok()) - .map_or(scheduled_g, |cap| scheduled_g.min(cap)); - let g = std::env::var("TLM_FFG_FORCE_G") - .ok() - .and_then(|value| value.parse::().ok()) - .map_or(capped_g, |forced| forced.min(n - 1)); - let trace_entry_active = circ.active_qubits; - if g >= n - 1 { - add_f_window_clean(circ, ctrl, reg, lsbs, c); - } else if g == 0 { - let cin = circ.alloc_qubit(); - let a_full: Vec = reg[..n].to_vec(); - let dirty: Vec = (lsbs..lsbs + (n - 1)).map(|i| reg[i]).collect(); - dirty_carryin(circ, ctrl, &a_full, c, 0, &dirty, &cin); - circ.zero_and_free(cin); - } else { - add_f_window_hybrid(circ, ctrl, reg, lsbs, c, g, call_index); - } - if std::env::var_os("TRACE_TLM_FFG").is_some() { - let local_peak = circ.active_timeline[timeline_start..] - .iter() - .map(|(_, active)| *active) - .max() - .unwrap_or(trace_entry_active); - eprintln!( - "TLM_FFG call={} phase={} g={} entry_active={} local_peak={} phase_max={} ops={}", - call_index, - circ.phase, - g, - trace_entry_active, - local_peak, - circ.current_phase_active_max, - circ.current_ops_len(), - ); - } -} - -fn add_f_window_clean(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8]) { - let n = lsbs; - assert!(n <= reg.len(), "register too short for +f window"); - if n == 0 { - return; - } - if n == 1 { - if cbit(c, 0) { - circ.cx(*ctrl, reg[0]); - } - return; - } - let a: Vec = reg[..n].to_vec(); - - let mut cy: Vec> = (0..n - 1).map(|_| Some(circ.alloc_qubit())).collect(); - - if cbit(c, 0) { - circ.ccx(*ctrl, a[0], *cy[0].as_ref().unwrap()); - } - - for i in 1..n - 1 { - let ci = cy[i - 1].take().unwrap(); - let next = cy[i].take().unwrap(); - circ.cx(ci, a[i]); - if cbit(c, i) { - circ.cx(*ctrl, ci); - } - circ.ccx(a[i], ci, next); - if cbit(c, i) { - circ.cx(*ctrl, ci); - } - circ.cx(ci, next); - cy[i - 1] = Some(ci); - cy[i] = Some(next); - } - - for i in 0..n - 1 { - if cbit(c, i) { - circ.cx(*ctrl, a[i]); - } - } - if cbit(c, n - 1) { - circ.cx(*ctrl, a[n - 1]); - } - circ.cx(*cy[n - 2].as_ref().unwrap(), a[n - 1]); - - for i in (1..n - 1).rev() { - if cbit(c, i) { - circ.cx(*ctrl, a[i]); - } - let next = cy[i].take().unwrap(); - let ci = cy[i - 1].take().unwrap(); - circ.cx(ci, next); - if cbit(c, i) { - circ.cx(*ctrl, ci); - } - - let mbit = circ.alloc_bit(); - circ.hmr(next, mbit); - circ.zero_and_free(next); - circ.cz_if_bit(a[i], ci, mbit); - if cbit(c, i) { - circ.cx(*ctrl, ci); - circ.cx(*ctrl, a[i]); - } - cy[i - 1] = Some(ci); - } - - let cy1 = cy[0].take().unwrap(); - if cbit(c, 0) { - circ.cx(*ctrl, a[0]); - let mbit = circ.alloc_bit(); - circ.hmr(cy1, mbit); - circ.zero_and_free(cy1); - - circ.cz_if_bit(a[0], *ctrl, mbit); - circ.cx(*ctrl, a[0]); - } else { - - circ.zero_and_free(cy1); - } -} - -fn sub_f_window(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8]) { - for q in ®[..lsbs] { - circ.x(*q); - } - add_f_window(circ, ctrl, reg, lsbs, c, None); - for q in ®[..lsbs] { - circ.x(*q); - } -} - -fn controlled_lt_msbs_conditional(circ: &mut B, ctrl: Option<&QubitId>, a: &[QubitId], b: &[QubitId], k: usize, target: QubitId) { - let a_top: Vec = a[a.len() - k..].to_vec(); - let b_top: Vec = b[b.len() - k..].to_vec(); - let bit = circ.alloc_bit(); - circ.hmr(target, bit); - - circ.zero_and_free(target); - let ctrl = ctrl.copied(); - circ.push_condition(bit); - - let lt_flag = circ.alloc_qubit(); - super::comparator::compare_geq_chunked_middle( - circ, - &a_top, - &b_top, - <_flag, - |c, flag| { - c.x(*flag); - match &ctrl { - Some(ct) => c.cz(*ct, *flag), - None => c.z(*flag), - } - c.x(*flag); - }, - k, - ); - circ.zero_and_free(lt_flag); - circ.pop_condition(); -} - -fn controlled_add_carry_msbs_conditional(circ: &mut B, ctrl: Option<&QubitId>, a: &[QubitId], b: &[QubitId], k: usize, target: &QubitId) { - let a_top: Vec = a[a.len() - k..].to_vec(); - let b_top: Vec = b[b.len() - k..].to_vec(); - let bit = circ.alloc_bit(); - circ.hmr(*target, bit); - circ.push_condition(bit); - for q in &b_top { - circ.x(*q); - } - - let ctrl = ctrl.copied(); - let lt_flag = circ.alloc_qubit(); - super::comparator::compare_geq_chunked_middle(circ, &b_top, &a_top, <_flag, |c, flag| { - c.x(*flag); - match &ctrl { - Some(ct) => c.cz(*ct, *flag), - None => c.z(*flag), - } - c.x(*flag); - }, k); - circ.zero_and_free(lt_flag); - for q in &b_top { - circ.x(*q); - } - circ.pop_condition(); -} - -pub fn controlled_mod_add_k(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], sched_k: Option, ffg_g: Option) { - let n = x.len(); - assert_eq!(y.len(), n, "x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 controlled_mod_add expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - - circ.set_phase("tlm_apply_forward_mod_add_register"); - match sched_k { - Some(k) => { - let yr: Vec<&QubitId> = y.iter().collect(); - let xr: Vec<&QubitId> = x.iter().collect(); - super::gidney::controlled_hybrid_add_cout_refs(circ, ctrl, &yr, &xr, &anc, k); - } - None => controlled_add_vented_chunked_cout(circ, ctrl, x, y, APPLY_CHUNK, Some(&anc)), - } - - circ.set_phase("tlm_apply_forward_mod_add_fold"); - add_f_window(circ, &anc, y, LSBS, &f_bytes, ffg_g); - - - circ.set_phase("tlm_apply_forward_mod_add_clean"); - controlled_lt_msbs_conditional(circ, Some(ctrl), &y[..n], &x[..n], msbs(), anc); -} - -pub fn mod_sub(circ: &mut B, x: &[QubitId], y: &[QubitId]) { - let n = x.len(); - assert_eq!(y.len(), n, "x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_sub expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - - for q in y { - circ.x(*q); - } - - if std::env::var("TLM_SQUARE_NO_VENT_REDUCE").ok().as_deref() == Some("1") { - cuccaro_carry(circ, None, x, y, None, Some(&anc)); - } else { - - let ci = next_cuccaro_call_index(); - add_cout_vented_skip_dead(circ, x, y, &anc, ci); - } - for q in y { - circ.x(*q); - } - - sub_f_window(circ, &anc, y, LSBS, &f_bytes); - - controlled_add_carry_msbs_conditional(circ, None, &y[..n], &x[..n], msbs(), &anc); - circ.zero_and_free(anc); -} - -fn add_cout_vented_unctrl(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId) { - let n = y.len(); - assert_eq!(x.len(), n, "add_cout_vented_unctrl: x,y width mismatch"); - let zpad = circ.alloc_qubit(); - let mut a: Vec = y.to_vec(); - a.push(*cout); - let mut b: Vec = x.to_vec(); - b.push(zpad); - hybrid_add_plain(circ, &a, &b, n); - circ.zero_and_free(zpad); -} - -pub fn mod_rsub_vented_loaded(circ: &mut B, t1: &[QubitId], y: &[QubitId]) { - let n = y.len(); - assert_eq!(t1.len(), n, "mod_rsub_vented_loaded: t1,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_rsub_vented_loaded expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - for q in y { - circ.x(*q); - } - add_cout_vented_unctrl(circ, t1, y, &anc); - circ.x(anc); - for q in &y[..LSBS] { - circ.x(*q); - } - add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); - for q in &y[..LSBS] { - circ.x(*q); - } - circ.x(anc); - controlled_lt_msbs_conditional(circ, None, &y[..n], &t1[..n], msbs(), anc); -} - -fn add_cout_vented_skip_dead(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId, call_index: usize) { - let n = y.len(); - assert_eq!(x.len(), n, "add_cout_vented_skip_dead: x,y width mismatch"); - let dead = |i: usize| cuccaro_call_has_structurally_dead_carry(call_index, i); - let zpad = circ.alloc_qubit(); - let live = circ.active_qubits as usize; - let margin = std::env::var("TLM_SQUARE_VENT_MARGIN") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(SQUARE_VENT_MARGIN); - let vents_budget = square_peak_hard_cap().saturating_sub(live).saturating_sub(margin); - - let mut a: Vec = y.to_vec(); - a.push(*cout); - let mut b: Vec = x.to_vec(); - b.push(zpad); - let m = a.len(); - - let mut vents_left = vents_budget; - for i in 1..m { - circ.cx(b[i], a[i]); - } - for i in (1..m - 1).rev() { - circ.cx(b[i], b[i + 1]); - } - let mut vent_ancs: Vec> = (0..m - 1).map(|_| None).collect(); - for i in 0..m - 1 { - if dead(i) { - continue; - } - if vents_left > 0 { - let anc = circ.alloc_qubit(); - circ.ccx(a[i], b[i], anc); - circ.cx(anc, b[i + 1]); - vent_ancs[i] = Some(anc); - vents_left -= 1; - } else { - circ.ccx(a[i], b[i], b[i + 1]); - } - } - for i in (0..m - 1).rev() { - circ.cx(b[i + 1], a[i + 1]); - if dead(i) { - continue; - } - if let Some(anc) = vent_ancs[i].take() { - circ.cx(anc, b[i + 1]); - let bit = circ.alloc_bit(); - circ.hmr(anc, bit); - circ.zero_and_free(anc); - circ.cz_if_bit(a[i], b[i], bit); - } else { - circ.ccx(a[i], b[i], b[i + 1]); - } - } - for i in 1..m - 1 { - circ.cx(b[i], b[i + 1]); - } - circ.cx(b[0], a[0]); - for i in 1..m { - circ.cx(b[i], a[i]); - } - circ.zero_and_free(zpad); -} - -fn add_cout_vented_unctrl_bounded(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId) { - let n = y.len(); - assert_eq!(x.len(), n, "add_cout_vented_unctrl_bounded: x,y width mismatch"); - let zpad = circ.alloc_qubit(); - - let live = circ.active_qubits as usize; - let margin = std::env::var("TLM_SQUARE_VENT_MARGIN") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(SQUARE_VENT_MARGIN); - let headroom = square_peak_hard_cap().saturating_sub(live).saturating_sub(margin); - let mut a: Vec = y.to_vec(); - a.push(*cout); - let mut b: Vec = x.to_vec(); - b.push(zpad); - hybrid_add_plain(circ, &a, &b, headroom); - circ.zero_and_free(zpad); -} - -pub const SQUARE_PEAK_HARD_CAP: usize = 1153; - -pub const SQUARE_VENT_MARGIN: usize = 30; - -fn square_peak_hard_cap() -> usize { - std::env::var("TLM_SQUARE_PEAK_CAP") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(SQUARE_PEAK_HARD_CAP) -} - -pub fn mod_add(circ: &mut B, x: &[QubitId], y: &[QubitId]) { - let n = x.len(); - assert_eq!(y.len(), n, "mod_add: x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_add expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - add_cout_vented_unctrl(circ, x, y, &anc); - - add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); - - controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], msbs(), anc); -} - -pub fn mod_add_exact(circ: &mut B, x: &[QubitId], y: &[QubitId]) { - let n = x.len(); - assert_eq!(y.len(), n, "mod_add_exact: x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_add_exact expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - add_cout_vented_unctrl(circ, x, y, &anc); - add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); - - controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], n, anc); -} - -pub fn mod_add_lowpeak(circ: &mut B, x: &[QubitId], y: &[QubitId]) { - let n = x.len(); - assert_eq!(y.len(), n, "mod_add_lowpeak: x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_add_lowpeak expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - - if std::env::var("TLM_SQUARE_NO_VENT_REDUCE").ok().as_deref() == Some("1") { - cuccaro_carry(circ, None, x, y, None, Some(&anc)); - } else { - let ci = next_cuccaro_call_index(); - add_cout_vented_skip_dead(circ, x, y, &anc, ci); - } - add_f_window(circ, &anc, y, LSBS, &f_bytes, None); - controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], msbs(), anc); -} - -pub fn mod_add_shifted_low(circ: &mut B, x: &[QubitId], y: &[QubitId], shift: usize) { - let n = y.len(); - assert_eq!(n, 256, "mod_add_shifted_low expects 256-bit y"); - assert!(shift < n, "shift must be less than 256"); - assert_eq!(x.len(), n - shift, "x must be the low shifted limb"); - if shift == 0 { - mod_add(circ, x, y); - return; - } - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - - if std::env::var("TLM_SQUARE_VENT_SHIFTED").ok().as_deref() == Some("1") { - let ci = next_cuccaro_call_index(); - add_cout_vented_skip_dead(circ, x, &y[shift..], &anc, ci); - } else { - cuccaro_carry(circ, None, x, &y[shift..], None, Some(&anc)); - } - add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); - controlled_lt_msbs_conditional(circ, None, &y[n - msbs()..], &x[x.len() - msbs()..], msbs(), anc); -} - -pub fn mod_sub_vented(circ: &mut B, x: &[QubitId], y: &[QubitId]) { - let n = x.len(); - assert_eq!(y.len(), n, "mod_sub_vented: x,y must both be n=256 bits"); - assert_eq!(n, 256, "secp256k1 mod_sub_vented expects n=256"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - for q in y { - circ.x(*q); - } - add_cout_vented_unctrl(circ, x, y, &anc); - for q in y { - circ.x(*q); - } - - for q in &y[..LSBS] { - circ.x(*q); - } - add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); - for q in &y[..LSBS] { - circ.x(*q); - } - controlled_add_carry_msbs_conditional(circ, None, &y[..n], &x[..n], msbs(), &anc); - circ.zero_and_free(anc); -} - -pub fn mod_sub_shifted_low(circ: &mut B, x: &[QubitId], y: &[QubitId], shift: usize) { - let n = y.len(); - assert_eq!(n, 256, "mod_sub_shifted_low expects 256-bit y"); - assert!(shift < n, "shift must be less than 256"); - assert_eq!(x.len(), n - shift, "x must be the low shifted limb"); - if shift == 0 { - mod_sub(circ, x, y); - return; - } - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - for q in &y[shift..] { - circ.x(*q); - } - if std::env::var("TLM_SQUARE_VENT_SHIFTED").ok().as_deref() == Some("1") { - let ci = next_cuccaro_call_index(); - add_cout_vented_skip_dead(circ, x, &y[shift..], &anc, ci); - } else { - cuccaro_carry(circ, None, x, &y[shift..], None, Some(&anc)); - } - for q in &y[shift..] { - circ.x(*q); - } - sub_f_window(circ, &anc, y, LSBS, &f_bytes); - controlled_add_carry_msbs_conditional(circ, None, &y[n - msbs()..], &x[x.len() - msbs()..], msbs(), &anc); - circ.zero_and_free(anc); -} - -fn toggle_pattern_mcx(circ: &mut B, pattern: &[(QubitId, bool)], target: &QubitId) { - for &(q, expected) in pattern { - if !expected { - circ.x(q); - } - } - let ctrls: Vec<&QubitId> = pattern.iter().map(|(q, _)| q).collect(); - super::mcx::mcx_clean_k(circ, &ctrls, target); - for &(q, expected) in pattern.iter().rev() { - if !expected { - circ.x(q); - } - } -} - -fn toggle_geq_small_const(circ: &mut B, a: &[QubitId], threshold: usize, target: &QubitId) { - assert!(threshold < (1usize << a.len())); - for j in (0..a.len()).rev() { - if (threshold >> j) & 1 != 0 { - continue; - } - let mut pattern = Vec::with_capacity(a.len() - j); - for k in (j + 1)..a.len() { - pattern.push((a[k], (threshold >> k) & 1 != 0)); - } - pattern.push((a[j], true)); - toggle_pattern_mcx(circ, &pattern, target); - } - let equality: Vec<(QubitId, bool)> = a - .iter() - .enumerate() - .map(|(i, &q)| (q, (threshold >> i) & 1 != 0)) - .collect(); - toggle_pattern_mcx(circ, &equality, target); -} - -fn toggle_geq_p_minus_low3(circ: &mut B, y: &[QubitId], c: &[QubitId], target: &QubitId) { - debug_assert_eq!(y.len(), 256); - debug_assert_eq!(c.len(), 3); - - let sum: Vec = (0..11).map(|_| circ.alloc_qubit()).collect(); - for i in 0..10 { - circ.cx(y[i], sum[i]); - } - let zeros: Vec = (0..8).map(|_| circ.alloc_qubit()).collect(); - let mut c11 = c.to_vec(); - c11.extend(zeros.iter().copied()); - cuccaro_carry(circ, None, &c11, &sum, None, None); - - let low_ge = circ.alloc_qubit(); - toggle_geq_small_const(circ, &sum, 47, &low_ge); - let lower = circ.alloc_qubit(); - circ.cx(y[32], lower); - let mut lower_pattern = Vec::with_capacity(24); - lower_pattern.push((y[32], false)); - lower_pattern.extend(y[10..32].iter().map(|&q| (q, true))); - lower_pattern.push((low_ge, true)); - toggle_pattern_mcx(circ, &lower_pattern, &lower); - - let mut full_pattern = Vec::with_capacity(224); - full_pattern.push((lower, true)); - full_pattern.extend(y[33..].iter().map(|&q| (q, true))); - toggle_pattern_mcx(circ, &full_pattern, target); - - toggle_pattern_mcx(circ, &lower_pattern, &lower); - circ.cx(y[32], lower); - circ.zero_and_free(lower); - toggle_geq_small_const(circ, &sum, 47, &low_ge); - circ.zero_and_free(low_ge); - - for q in &sum { - circ.x(*q); - } - cuccaro_carry(circ, None, &c11, &sum, None, None); - for q in &sum { - circ.x(*q); - } - for i in 0..10 { - circ.cx(y[i], sum[i]); - } - for q in sum { - circ.zero_and_free(q); - } - for q in zeros { - circ.zero_and_free(q); - } -} - -pub fn mod_sub_classical_low3(circ: &mut B, y: &[QubitId], c: &[BitId]) { - assert_eq!(y.len(), 256, "mod_sub_classical_low3 expects 256-bit y"); - assert_eq!(c.len(), 3, "mod_sub_classical_low3 expects three classical bits"); - - let cq: Vec = (0..3).map(|_| circ.alloc_qubit()).collect(); - for i in 0..3 { - circ.x_if_bit(cq[i], c[i]); - } - - let low_borrow = circ.alloc_qubit(); - for q in &y[..3] { - circ.x(*q); - } - cuccaro_carry(circ, None, &cq, &y[..3], None, Some(&low_borrow)); - for q in &y[..3] { - circ.x(*q); - } - - let full_borrow = circ.alloc_qubit(); - let mut borrow_pattern = Vec::with_capacity(254); - borrow_pattern.push((low_borrow, true)); - borrow_pattern.extend(y[3..].iter().map(|&q| (q, false))); - toggle_pattern_mcx(circ, &borrow_pattern, &full_borrow); - - for q in &y[3..] { - circ.x(*q); - } - super::mcx::cinc_khattar_gidney(circ, &y[3..], &low_borrow); - for q in &y[3..] { - circ.x(*q); - } - - let low_copy: Vec = (0..3).map(|_| circ.alloc_qubit()).collect(); - for i in 0..3 { - circ.cx(y[i], low_copy[i]); - } - cuccaro_carry(circ, None, &cq, &low_copy, None, Some(&low_borrow)); - for q in &low_copy { - circ.x(*q); - } - cuccaro_carry(circ, None, &cq, &low_copy, None, None); - for q in &low_copy { - circ.x(*q); - } - for i in 0..3 { - circ.cx(y[i], low_copy[i]); - } - for q in low_copy { - circ.zero_and_free(q); - } - circ.zero_and_free(low_borrow); - - let f_bytes = F_SECP256K1.to_le_bytes(); - sub_f_window(circ, &full_borrow, y, LSBS, &f_bytes); - toggle_geq_p_minus_low3(circ, y, &cq, &full_borrow); - circ.zero_and_free(full_borrow); - - for i in 0..3 { - circ.x_if_bit(cq[i], c[i]); - } - for q in cq { - circ.zero_and_free(q); - } -} - -pub fn mod_neg(circ: &mut B, x: &[QubitId]) { - let n = x.len(); - assert_eq!(n, 256, "secp256k1 mod_neg expects n=256"); - let f_minus_1 = (F_SECP256K1 - 1).to_le_bytes(); - add_const_window_clean(circ, x, n, &f_minus_1); - for q in x { - circ.x(*q); - } -} - -fn add_const_window_clean(circ: &mut B, reg: &[QubitId], lsbs: usize, c: &[u8]) { - let add_const_call_index = next_add_const_call_index(); - let n = lsbs; - assert!(n <= reg.len(), "register too short for const window"); - if n == 0 { - return; - } - if n == 1 { - if cbit(c, 0) { - circ.x(reg[0]); - } - return; - } - let a: Vec = reg[..n].to_vec(); - let mut cy: Vec> = (0..n - 1).map(|_| Some(circ.alloc_qubit())).collect(); - - if cbit(c, 0) { - circ.cx(a[0], *cy[0].as_ref().unwrap()); - } - - for i in 1..n - 1 { - let ci = cy[i - 1].take().unwrap(); - let next = cy[i].take().unwrap(); - circ.cx(ci, a[i]); - if cbit(c, i) { - circ.x(ci); - } - if !add_const_has_structurally_dead_carry(add_const_call_index, i) { - let old_context = crate::point_add::set_op_trace_context( - 0x1100_0000 | (((add_const_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(a[i], ci, next); - crate::point_add::restore_op_trace_context(old_context); - } - if cbit(c, i) { - circ.x(ci); - } - circ.cx(ci, next); - cy[i - 1] = Some(ci); - cy[i] = Some(next); - } - - for i in 0..n - 1 { - if cbit(c, i) { - circ.x(a[i]); - } - } - if cbit(c, n - 1) { - circ.x(a[n - 1]); - } - circ.cx(*cy[n - 2].as_ref().unwrap(), a[n - 1]); - - for i in (1..n - 1).rev() { - if cbit(c, i) { - circ.x(a[i]); - } - let next = cy[i].take().unwrap(); - let ci = cy[i - 1].take().unwrap(); - circ.cx(ci, next); - if cbit(c, i) { - circ.x(ci); - } - let mbit = circ.alloc_bit(); - circ.hmr(next, mbit); - circ.zero_and_free(next); - circ.cz_if_bit(a[i], ci, mbit); - if cbit(c, i) { - circ.x(ci); - circ.x(a[i]); - } - cy[i - 1] = Some(ci); - } - - let cy1 = cy[0].take().unwrap(); - if cbit(c, 0) { - circ.x(a[0]); - let mbit = circ.alloc_bit(); - circ.hmr(cy1, mbit); - circ.zero_and_free(cy1); - circ.z_if_bit(a[0], mbit); - circ.x(a[0]); - } else { - circ.zero_and_free(cy1); - } -} - -pub fn mod_double(circ: &mut B, a: &[QubitId]) { - let n = a.len() - 1; - assert_eq!(n, 256, "secp256k1 mod_double expects 257-bit a"); - let f_bytes = F_SECP256K1.to_le_bytes(); - - for i in (0..n).rev() { - circ.swap(a[i], a[i + 1]); - } - - add_f_window(circ, &a[n], a, LSBS, &f_bytes, None); - - circ.cx(a[0], a[n]); -} - -pub fn mod_double_reverse(circ: &mut B, a: &[QubitId]) { - let n = a.len() - 1; - assert_eq!(n, 256, "secp256k1 mod_double_reverse expects 257-bit a"); - let f_bytes = F_SECP256K1.to_le_bytes(); - - circ.cx(a[0], a[n]); - - sub_f_window(circ, &a[n], a, LSBS, &f_bytes); - - for i in 0..n { - circ.swap(a[i], a[i + 1]); - } -} - -pub fn add_f_window_pub(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8], g_sched: Option) { - add_f_window(circ, ctrl, reg, lsbs, c, g_sched); -} + +use super::{B, BExt}; +use crate::circuit::{BitId, QubitId}; +use std::cell::Cell; + +thread_local! { + static FFG_CALL_INDEX: Cell = const { Cell::new(0) }; + static FFG_SHIFTED_SQUARE_PREFIX_SCOPE: Cell = const { Cell::new(0) }; + static CUCCARO_CALL_INDEX: Cell = const { Cell::new(0) }; + static CONST_CHUNK_CALL_INDEX: Cell = const { Cell::new(0) }; + static ADD_CONST_CALL_INDEX: Cell = const { Cell::new(0) }; +} + +pub(super) fn reset_ffg_call_index() { + FFG_CALL_INDEX.with(|index| index.set(0)); + CUCCARO_CALL_INDEX.with(|index| index.set(0)); + CONST_CHUNK_CALL_INDEX.with(|index| index.set(0)); + ADD_CONST_CALL_INDEX.with(|index| index.set(0)); +} + +fn next_ffg_call_index() -> usize { + FFG_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +pub(super) fn with_shifted_square_ffg_prefix_scope(body: impl FnOnce() -> R) -> R { + FFG_SHIFTED_SQUARE_PREFIX_SCOPE.with(|scope| { + let prior = scope.get(); + scope.set(prior + 1); + let result = body(); + scope.set(prior); + result + }) +} + +fn shifted_square_ffg_prefix_scope_enabled() -> bool { + std::env::var_os("TLM_SQUARE_SHIFTED_FFG_PREFIX_SKIP").is_some() + && FFG_SHIFTED_SQUARE_PREFIX_SCOPE.with(|scope| scope.get() > 0) +} + +fn next_cuccaro_call_index() -> usize { + CUCCARO_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_const_chunk_call_index() -> usize { + CONST_CHUNK_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_add_const_call_index() -> usize { + ADD_CONST_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn env_index_value(name: &str, index: usize) -> Option { + std::env::var(name) + .ok() + .and_then(|value| { + value + .split(',') + .filter_map(|item| item.trim().split_once(':')) + .find_map(|(call, value)| { + (call.parse::().ok()? == index) + .then(|| value.parse::().ok()) + .flatten() + }) + }) +} + +fn env_index_list_contains(name: &str, index: usize) -> bool { + std::env::var(name) + .ok() + .map(|value| { + value + .split(',') + .filter_map(|item| item.trim().parse::().ok()) + .any(|candidate| candidate == index) + }) + .unwrap_or(false) +} + +const FFG_DEAD_HYBRID_CARRY_RANGES: &[(usize, usize, usize)] = &[ + (264, 1, 46), + (265, 1, 46), + (266, 1, 46), + (267, 1, 46), + (268, 1, 46), + (271, 1, 46), + (272, 1, 46), + (273, 1, 46), + (274, 1, 46), + (275, 1, 46), + (277, 1, 46), + (278, 1, 46), + (279, 1, 46), + (280, 1, 46), + (281, 1, 46), + (596, 21, 24), + (596, 26, 31), + (596, 42, 46), + (2, 1, 3), + (2, 28, 31), + (598, 1, 3), + (598, 27, 27), + (598, 30, 31), + (3, 1, 3), + (3, 29, 29), + (3, 31, 31), + (340, 1, 5), + (51, 28, 31), + (131, 28, 31), + (198, 28, 31), + (201, 28, 31), + (597, 1, 3), + (597, 29, 29), + (13, 29, 31), + (37, 29, 31), + (50, 29, 31), + (60, 29, 31), + (64, 28, 28), + (64, 30, 31), + (73, 29, 31), + (75, 29, 31), + (80, 29, 31), + (105, 29, 31), + (113, 29, 31), + (115, 28, 28), + (115, 30, 31), + (116, 29, 31), + (119, 29, 31), + (126, 29, 31), + (137, 29, 31), + (139, 28, 29), + (139, 31, 31), + (140, 29, 31), + (147, 29, 31), + (178, 29, 31), + (190, 29, 31), + (199, 29, 31), + (209, 28, 28), + (209, 30, 31), + (284, 29, 31), + (288, 29, 31), + (293, 29, 31), + (295, 29, 31), + (318, 29, 31), + (405, 29, 31), + (409, 28, 28), + (409, 30, 31), + (416, 29, 31), + (424, 28, 28), + (424, 30, 31), + (433, 28, 28), + (433, 30, 31), + (434, 29, 31), + (444, 29, 31), + (464, 29, 31), + (471, 29, 31), + (478, 28, 28), + (478, 30, 31), + (487, 28, 28), + (487, 30, 31), + (498, 29, 31), + (516, 29, 31), + (518, 29, 31), + (548, 28, 28), + (548, 30, 31), + (553, 29, 31), + (559, 29, 31), + (560, 29, 31), + (568, 29, 31), + (570, 29, 31), + (575, 29, 31), + (580, 29, 31), + (586, 29, 31), + (592, 29, 31), +]; + +fn ffg_call_has_structurally_dead_hybrid_carry(call_index: usize, bit: usize, phase: &str) -> bool { + if shifted_square_ffg_prefix_scope_enabled() && bit > 0 { + return true; + } + if std::env::var_os("TLM_FFG_SKIP_TOP_CARRY31").is_some() && bit == 31 { + return true; + } + if std::env::var_os("TLM_FFG_SKIP_TOP_CARRY30").is_some() && bit == 30 { + return true; + } + if std::env::var_os("TLM_FFG_SKIP_INVERSE_MOD_SUB_TOP29").is_some() + && bit == 29 + && phase == "tlm_apply_inverse_mod_sub_fold" + && call_index + <= std::env::var("TLM_FFG_INVERSE_TOP29_MAX_CALL") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(usize::MAX) + { + return true; + } + if std::env::var_os("TLM_FFG_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { + return false; + } + if std::env::var_os("TLM_FFG_SKIP_EXACT_TOP29_REMAINDER").is_some() { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if FFG_TOP29_REMAINDER_KEYS.binary_search(&key).is_ok() { + return true; + } + } + FFG_DEAD_HYBRID_CARRY_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +const FFG_TOP29_REMAINDER_KEYS: &[u32] = &[ + 1821, 2333, 3869, 6685, 7197, 7453, 13341, 15901, 19741, 19997, 20253, 22044, + 25885, 26397, 27933, 31517, 32796, 34077, 36125, 36380, 38173, 38941, 40989, + 41757, 42525, 44316, 46621, 50205, 54045, 54557, 68893, 72221, 74781, 79133, + 85277, 85789, 86557, 102685, 103453, 104989, 108061, 110365, 112669, 115741, + 117789, 120861, 121117, 123165, 126493, 126749, 127260, 128797, 129053, + 130844, 131101, 137245, 144157, 144669, 147741, 149021, 149533, 151069, +]; + +const CONST_CHUNK_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (879, 0, 9), + (880, 0, 8), + (700, 0, 7), + (881, 0, 7), + (887, 0, 7), + (900, 0, 7), + (678, 0, 6), + (686, 0, 6), + (707, 0, 6), + (882, 0, 6), + (894, 0, 6), + (906, 0, 6), + (649, 2, 7), + (654, 2, 7), + (692, 1, 6), + (715, 0, 4), + (715, 7, 7), + (883, 0, 5), + (638, 0, 1), + (638, 3, 5), + (689, 0, 4), + (691, 3, 7), + (706, 2, 2), + (706, 4, 7), + (718, 0, 4), + (884, 0, 4), + (890, 0, 4), + (897, 0, 4), + (903, 0, 4), + (909, 0, 4), + (912, 1, 5), + (919, 0, 4), + (626, 1, 4), + (659, 4, 7), + (666, 0, 3), + (671, 3, 3), + (671, 5, 7), + (672, 0, 3), + (685, 5, 8), + (703, 1, 4), + (704, 0, 3), + (714, 5, 8), + (717, 2, 5), + (891, 0, 3), + (893, 5, 8), + (926, 0, 3), + (941, 0, 3), + (949, 1, 1), + (949, 3, 4), + (949, 6, 6), + (956, 2, 5), + (481, 1, 3), + (485, 1, 3), + (520, 5, 7), + (579, 1, 2), + (579, 4, 4), + (590, 2, 4), + (636, 0, 2), + (644, 4, 5), + (644, 7, 7), + (663, 1, 3), + (665, 4, 4), + (665, 6, 7), + (669, 0, 0), + (669, 2, 3), + (675, 1, 3), + (677, 4, 5), + (677, 7, 7), + (682, 0, 2), + (696, 0, 2), + (710, 0, 1), + (710, 3, 3), + (711, 0, 2), + (723, 0, 2), + (725, 0, 2), + (727, 0, 2), + (729, 0, 2), + (731, 0, 2), + (737, 0, 2), + (739, 0, 2), + (741, 0, 2), + (743, 0, 2), + (745, 0, 2), + (749, 0, 2), + (751, 0, 2), + (753, 0, 2), + (755, 0, 2), + (757, 0, 2), + (896, 3, 5), + (905, 5, 5), + (905, 7, 8), + (911, 5, 7), + (916, 0, 2), + (918, 5, 7), + (923, 0, 2), + (931, 5, 7), + (932, 0, 2), + (935, 1, 3), + (937, 5, 7), + (944, 0, 2), + (962, 2, 4), + (968, 1, 3), + (973, 1, 3), + (978, 1, 3), + (983, 0, 2), + (1023, 1, 3), + (1039, 0, 2), + (1044, 1, 3), + (1109, 3, 5), + (1149, 1, 3), + (1622, 0, 2), +]; + +const CONST_CHUNK_REMAINDER_KEYS: &[u32] = &[ + 1281, 5376, 5377, 6913, 8449, 8960, 9473, 10496, 15616, 16641, 17153, 19201, + 19713, 20736, 22785, 23809, 27905, 29440, 38656, 40705, 43777, 49921, 51457, + 57089, 58113, 59649, 64257, 66305, 66816, 68865, 70400, 70401, 70913, 77569, + 79361, 80898, 99074, 113408, 116224, 117248, 118016, 118017, 119043, 120064, + 120065, 121090, 121091, 122115, 125189, 126467, 127492, 127493, 128772, 128774, + 130308, 130309, 131589, 131590, 135936, 136711, 136960, 136961, 137990, 137991, + 139015, 139264, 140035, 140545, 141315, 141575, 141824, 142855, 143105, 144385, + 144386, 145155, 145415, 145665, 146946, 149761, 149762, 152579, 152581, 153861, + 154112, 155137, 156166, 156417, 157447, 157696, 157697, 158466, 158978, 159746, + 161794, 161796, 164354, 165120, 166915, 167680, 168960, 168961, 169475, 174339, + 174848, 174849, 176132, 176133, 177922, 177923, 178432, 178433, 178952, 179456, + 179457, 181506, 181507, 182272, 182273, 185344, 185345, 185856, 185857, 186368, + 186369, 186880, 186881, 187392, 187393, 188928, 188929, 189440, 189441, 189952, + 189953, 190464, 190465, 190976, 190977, 192000, 192001, 192512, 192513, 193024, + 193025, 193536, 193537, 194048, 194049, 196609, 199680, 200192, 200193, 214017, + 217089, 223233, 226822, 226824, 227328, 227329, 230151, 232453, 234242, 234243, + 236035, 236806, 236807, 237826, 237827, 240128, 240129, 241414, 241415, 242435, + 244225, 245761, 245762, 247296, 248579, 252419, 252930, 254214, 255491, 255493, + 257027, 257028, 258050, 258566, 259840, 260354, 260355, 263172, 264707, 268546, + 269825, 271105, 271106, 272385, 273154, 273155, 273415, 273664, 274689, 275968, + 276743, 277767, 278016, 278789, 278791, 279812, 279814, 281089, 281348, 281350, + 282373, 282374, 285188, 285190, 286723, 286725, 288003, 288004, 289284, 289285, + 290306, 290562, 290564, 291842, 292865, 292868, 295170, 296195, 297217, 297218, + 299265, 299266, 300288, 301312, 302081, 303104, 304897, 305152, 323329, 328194, + 330499, 341761, 345857, 346369, 346881, 347905, 352512, 354049, 359168, 361217, + 361729, 362241, 367873, 368385, 369920, 371457, 374529, 375040, 375041, 376577, + 378625, 380672, 380673, 381697, 385281, 386817, 391937, 393985, 395008, 398593, + 400641, 402689, 405761, 407809, 411393, 415488, 415489, 416001, 416513, +]; + +fn const_chunk_call_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_CONST_CHUNK_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { + return false; + } + if std::env::var_os("TLM_CONST_CHUNK_SKIP_EXACT_REMAINDER").is_some() { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if CONST_CHUNK_REMAINDER_KEYS.binary_search(&key).is_ok() { + return true; + } + } + CONST_CHUNK_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn cuccaro_call_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_CUCCARO_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { + return false; + } + match call_index { + + 12 | 25 => (1..=127).contains(&bit), + 37 => bit <= 135, + 19 => (1..=127).contains(&bit), + 20 | 26 => bit >= 148, + 13 => bit >= 150, + 21 => matches!(bit, 147 | 148) || (150..=251).contains(&bit), + 27 => (148..=251).contains(&bit), + 22 => bit == 146 || (148..=249).contains(&bit), + 28 => (147..=249).contains(&bit), + 14 => matches!(bit, 150 | 151) || (153..=251).contains(&bit), + 15 => (151..=249).contains(&bit), + 29 => (147..=245).contains(&bit), + 23 => matches!(bit, 148 | 149) || (151..=245).contains(&bit), + 16 => (151..=245).contains(&bit), + 30 => (149..=223).contains(&bit), + 24 => (150..=223).contains(&bit), + 17 => bit == 149 || (152..=223).contains(&bit), + _ => false, + } +} + +fn add_const_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_ADD_CONST_SKIP_STRUCTURAL_DEAD_CARRIES").is_none() { + return false; + } + call_index == 0 && (bit == 55 || bit >= 57) +} + +pub const F_SECP256K1: u64 = (1u64 << 32) + 977; + +pub const F_BITLEN: usize = 33; + +pub const PAD: usize = 19; + +pub const LSBS: usize = 20 + F_BITLEN; + +pub const MSBS: usize = PAD; + +pub const APPLY_CHUNK: usize = 40; + +#[inline] +fn cbit(c: &[u8], i: usize) -> bool { + let byte = i / 8; + byte < c.len() && (c[byte] >> (i % 8)) & 1 == 1 +} + +pub fn cuccaro_carry( + circ: &mut B, + ctrl: Option<&QubitId>, + x: &[QubitId], + y: &[QubitId], + cin: Option<&QubitId>, + cout: Option<&QubitId>, +) { + let call_index = next_cuccaro_call_index(); + let ops_start = circ.current_ops_len(); + let s = y.len(); + assert_eq!(x.len(), s, "cuccaro_carry: x,y width mismatch"); + let fresh = if cin.is_none() { Some(circ.alloc_qubit()) } else { None }; + let c: &QubitId = cin.unwrap_or_else(|| fresh.as_ref().unwrap()); + let sum = |circ: &mut B, xi: &QubitId, yi: &QubitId| match ctrl { + Some(ct) => circ.ccx(*ct, *xi, *yi), + None => circ.cx(*xi, *yi), + }; + let gated_carry = |circ: &mut B, co: &QubitId| match ctrl { + Some(ct) => circ.ccx(*ct, *c, *co), + None => circ.cx(*c, *co), + }; + if s == 0 { + if let Some(co) = cout { + gated_carry(circ, co); + } + } else { + + for i in 0..s { + circ.cx(*c, y[i]); + circ.cx(*c, x[i]); + if !cuccaro_call_has_structurally_dead_carry(call_index, i) { + let old_context = crate::point_add::set_op_trace_context( + 0x0200_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(x[i], y[i], *c); + crate::point_add::restore_op_trace_context(old_context); + } + } + if let Some(co) = cout { + gated_carry(circ, co); + } + + for i in (0..s).rev() { + if !cuccaro_call_has_structurally_dead_carry(call_index, i) { + let old_context = crate::point_add::set_op_trace_context( + 0x0300_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(x[i], y[i], *c); + crate::point_add::restore_op_trace_context(old_context); + } + circ.cx(*c, y[i]); + sum(circ, &x[i], &y[i]); + circ.cx(*c, x[i]); + } + } + if let Some(f) = fresh { + circ.zero_and_free(f); + } + if std::env::var_os("TRACE_TLM_CUCCARO").is_some() { + eprintln!( + "TLM_CUCCARO call={} phase={} width={} ctrl={} cin={} cout={} ops_start={} ops_end={}", + call_index, + circ.phase, + s, + usize::from(ctrl.is_some()), + usize::from(cin.is_some()), + usize::from(cout.is_some()), + ops_start, + circ.current_ops_len(), + ); + } +} + +fn clean_add_threaded_opt( + circ: &mut B, + ctrl: Option<&QubitId>, + x: &[QubitId], + y: &[QubitId], + cin: Option<&QubitId>, + cout: Option<&QubitId>, +) { + let s = y.len(); + assert_eq!(x.len(), s, "vented add: x,y width mismatch"); + + let gated_sum = |circ: &mut B, xi: &QubitId, yi: &QubitId| match ctrl { + Some(ct) => circ.ccx(*ct, *xi, *yi), + None => circ.cx(*xi, *yi), + }; + if s == 0 { + if let (Some(ci), Some(co)) = (cin, cout) { + match ctrl { + Some(ct) => circ.ccx(*ct, *ci, *co), + None => circ.cx(*ci, *co), + } + } + return; + } + let n_inner = if cout.is_some() { s } else { s - 1 }; + let mut inner: Vec> = (0..n_inner).map(|_| Some(circ.alloc_qubit())).collect(); + let produces = |i: usize| cout.is_some() || i + 1 < s; + + for i in 0..s { + if !produces(i) { + continue; + } + let co = inner[i].as_ref().unwrap(); + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, x[i]); + circ.cx(*ci, y[i]); + circ.ccx(x[i], y[i], *co); + circ.cx(*ci, *co); + } else { + circ.ccx(x[i], y[i], *co); + } + } + if let Some(cout) = cout { + let top = inner[s - 1].as_ref().unwrap(); + match ctrl { + Some(ct) => circ.ccx(*ct, *top, *cout), + None => circ.cx(*top, *cout), + } + } + + for i in (0..s).rev() { + if !produces(i) { + + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, x[i]); + } + gated_sum(circ, &x[i], &y[i]); + if let Some(ci) = ci { + circ.cx(*ci, x[i]); + } + continue; + } + let co = inner[i].take().unwrap(); + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, co); + } + + let bit = circ.alloc_bit(); + circ.hmr(co, bit); + circ.zero_and_free(co); + circ.cz_if_bit(x[i], y[i], bit); + if let Some(ci) = ci { + circ.cx(*ci, y[i]); + } + gated_sum(circ, &x[i], &y[i]); + if let Some(ci) = ci { + circ.cx(*ci, x[i]); + } + } +} + +pub(crate) fn erase_carry_gated_opt( + circ: &mut B, + ctrl: Option<&QubitId>, + a: &[QubitId], + b: &[QubitId], + cin: &QubitId, + carry: &QubitId, + cap: Option, +) { + let s = a.len(); + let bit = circ.alloc_bit(); + circ.hmr(*carry, bit); + + circ.loan_zero_qubit(*carry); + circ.push_condition(bit); + let deposit = |c: &mut B, ta: &QubitId, tb: &QubitId, c_prev: &QubitId| match ctrl { + Some(ct) => { + c.z(*ct); + c.ccz(*ct, *ta, *tb); + c.cz(*ct, *c_prev); + } + None => { + c.neg(); + c.cz(*ta, *tb); + c.z(*c_prev); + } + }; + match cap { + Some(k) if k < s => { + + let lo = s - k; + let zcin = circ.alloc_qubit(); + super::comparator::compare_geq_cin_middle(circ, &a[lo..], &b[lo..], &zcin, deposit); + circ.zero_and_free(zcin); + } + _ => { + super::comparator::compare_geq_cin_middle(circ, a, b, cin, deposit); + } + } + circ.pop_condition(); +} + +pub(crate) fn erase_carry_gated_zero_cin_opt( + circ: &mut B, + ctrl: Option<&QubitId>, + a: &[QubitId], + b: &[QubitId], + carry: &QubitId, + cap: Option, +) { + let s = a.len(); + let bit = circ.alloc_bit(); + circ.hmr(*carry, bit); + circ.push_condition(bit); + let deposit = |c: &mut B, ta: &QubitId, tb: &QubitId, c_prev: &QubitId| match ctrl { + Some(ct) => { + c.z(*ct); + c.ccz(*ct, *ta, *tb); + c.cz(*ct, *c_prev); + } + None => { + c.neg(); + c.cz(*ta, *tb); + c.z(*c_prev); + } + }; + match cap { + Some(k) if k < s => { + let lo = s - k; + let zcin = circ.alloc_qubit(); + super::comparator::compare_geq_cin_middle(circ, &a[lo..], &b[lo..], &zcin, deposit); + circ.zero_and_free(zcin); + } + _ => { + super::comparator::compare_geq_cin_middle(circ, a, b, carry, deposit); + } + } + circ.pop_condition(); +} + +pub fn controlled_add_vented_chunked_cout( + circ: &mut B, + ctrl: &QubitId, + x: &[QubitId], + y: &[QubitId], + chunk: usize, + cout: Option<&QubitId>, +) { + add_vented_chunked_opt(circ, Some(ctrl), x, y, chunk, cout, None); +} + +pub const CEILING: usize = 1167; + +fn emit_chunked_capped( + circ: &mut B, + ctrl: Option<&QubitId>, + x: &[QubitId], + y: &[QubitId], + bounds: &[(usize, usize)], + plain_len: usize, + cout: Option<&QubitId>, + cap: Option, +) { + let n = y.len(); + let l = n - plain_len; + let cin0 = circ.alloc_qubit(); + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(lo, hi)) in bounds.iter().enumerate() { + let cy = circ.alloc_qubit(); + let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; + clean_add_threaded_opt(circ, ctrl, &x[lo..hi], &y[lo..hi], Some(cin), Some(&cy)); + carries.push(cy); + } + if l < n { + let top_cin: &QubitId = carries.last().unwrap_or(&cin0); + clean_add_threaded_opt(circ, ctrl, &x[l..n], &y[l..n], Some(top_cin), cout); + } else if let Some(co) = cout { + circ.cx(*carries.last().unwrap(), *co); + } + for j in (0..bounds.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; + erase_carry_gated_opt(circ, ctrl, &y[lo..hi], &x[lo..hi], cin, &carry, cap); + } + circ.zero_and_free(cin0); +} + +fn hybrid_add_plain(circ: &mut B, a: &[QubitId], b: &[QubitId], vents_budget: usize) { + let n = a.len(); + assert_eq!(b.len(), n, "hybrid_add: a,b width mismatch"); + if n == 0 { + return; + } + if n == 1 { + circ.cx(b[0], a[0]); + return; + } + let vents = vents_budget.min(n - 1); + for i in 1..n { + circ.cx(b[i], a[i]); + } + for i in (1..n - 1).rev() { + circ.cx(b[i], b[i + 1]); + } + let mut vent_ancs: Vec> = (0..n - 1).map(|_| None).collect(); + for i in 0..n - 1 { + if i < vents { + let anc = circ.alloc_qubit(); + circ.ccx(a[i], b[i], anc); + circ.cx(anc, b[i + 1]); + vent_ancs[i] = Some(anc); + } else { + circ.ccx(a[i], b[i], b[i + 1]); + } + } + for i in (0..n - 1).rev() { + circ.cx(b[i + 1], a[i + 1]); + if i < vents { + let anc = vent_ancs[i].take().unwrap(); + circ.cx(anc, b[i + 1]); + let bit = circ.alloc_bit(); + circ.hmr(anc, bit); + circ.zero_and_free(anc); + circ.cz_if_bit(a[i], b[i], bit); + } else { + circ.ccx(a[i], b[i], b[i + 1]); + } + } + for i in 1..n - 1 { + circ.cx(b[i], b[i + 1]); + } + circ.cx(b[0], a[0]); + for i in 1..n { + circ.cx(b[i], a[i]); + } +} + +pub(crate) fn hybrid_add_adaptive(circ: &mut B, a: &[QubitId], b: &[QubitId], k: usize) { + let n = a.len(); + assert_eq!(b.len(), n, "adaptive add: a,b width mismatch"); + if n == 0 { + return; + } + let c = ((n as f64).sqrt() as usize).clamp(1, n); + if n <= 4 || k.saturating_add(2 * c) >= n { + hybrid_add_plain(circ, a, b, k); + return; + } + if k < n.div_ceil(c) + c + super::gidney::ADAPTIVE_RES { + let cov = (k.saturating_mul(k.saturating_sub(1)) / 2).min(n); + if cov > 2 * k { + + unreachable!("square adaptive add hit the tight chunked_then_cuccaro branch (n={n}, k={k})"); + } + hybrid_add_plain(circ, a, b, k); + return; + } + let lay = super::gidney::adaptive_layout(n, k); + let l = lay.chunked_len; + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let mut lo = 0; + while lo < l { + let hi = (lo + lay.c).min(l); + bounds.push((lo, hi)); + lo = hi; + } + + emit_chunked_capped(circ, None, b, a, &bounds, lay.plain_len, None, None); +} + +fn add_vented_chunked_opt( + circ: &mut B, + ctrl: Option<&QubitId>, + x: &[QubitId], + y: &[QubitId], + chunk: usize, + cout: Option<&QubitId>, + cap: Option, +) { + add_vented_chunked_opt_capped(circ, ctrl, x, y, chunk, cout, cap, usize::MAX); +} + +#[allow(clippy::too_many_arguments)] +fn add_vented_chunked_opt_capped( + circ: &mut B, + ctrl: Option<&QubitId>, + x: &[QubitId], + y: &[QubitId], + chunk: usize, + cout: Option<&QubitId>, + cap: Option, + max_vents: usize, +) { + let n = y.len(); + assert_eq!(x.len(), n, "chunked add: x,y width mismatch"); + if n == 0 { + return; + } + + let c = chunk.clamp(1, n); + let live = circ.active_qubits as usize; + + let k = CEILING.saturating_sub(live).clamp(1, n).min(max_vents); + let plain_len = if k >= n { + n + } else if c <= 1 { + 0 + } else { + ((k * c).saturating_sub(n) / (c - 1)).min(n) + }; + let l = n - plain_len; + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let mut lo = 0; + while lo < l { + let hi = (lo + c).min(l); + bounds.push((lo, hi)); + lo = hi; + } + emit_chunked_capped(circ, ctrl, x, y, &bounds, plain_len, cout, cap); +} + +fn ccx_cond(circ: &mut B, ctrl: &QubitId, c1: &QubitId, c2: &QubitId, t: &QubitId, b0: bool, b1: bool) { + if b0 { circ.cx(*ctrl, *c1); } + if b1 { circ.cx(*ctrl, *c2); } + circ.ccx(*c1, *c2, *t); + if b0 { circ.cx(*ctrl, *c1); } + if b1 { circ.cx(*ctrl, *c2); } +} + +fn xor_carries_off_cin(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], off: usize, out: &[QubitId], cin: &QubitId) { + let n = a.len(); + for i in (1..n - 1).rev() { + ccx_cond(circ, ctrl, &a[i], &out[i - 1], &out[i], cbit(c, off + i), false); + } + for i in 0..n - 1 { + if cbit(c, off + i) { circ.cx(*ctrl, out[i]); } + } + ccx_cond(circ, ctrl, cin, &a[0], &out[0], cbit(c, off), cbit(c, off)); + for i in 1..n - 1 { + ccx_cond(circ, ctrl, &a[i], &out[i - 1], &out[i], cbit(c, off + i), cbit(c, off + i)); + } +} + +fn dirty_carryin(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], off: usize, dirty: &[QubitId], cin: &QubitId) { + let n = a.len(); + debug_assert!(n >= 2 && dirty.len() >= n - 1); + let mut bits: Vec = Vec::with_capacity(n - 1); + let mut cy_owned: Option = None; + for i in 0..(n - 1) { + let new = circ.alloc_qubit(); + let anc = circ.alloc_qubit(); + let on = cbit(c, off + i); + let cyref: QubitId = match cy_owned { Some(q) => q, None => *cin }; + if on { circ.cx(*ctrl, anc); } + circ.cx(cyref, anc); + circ.cx(cyref, a[i]); + circ.ccx(a[i], anc, new); + circ.cx(cyref, new); + circ.cx(new, dirty[i]); + circ.cx(cyref, anc); + if on { circ.cx(*ctrl, anc); circ.cx(*ctrl, a[i]); } + circ.zero_and_free(anc); + if let Some(old) = cy_owned.take() { + let b = circ.alloc_bit(); + circ.hmr(old, b); + bits.push(b); + circ.zero_and_free(old); + } + cy_owned = Some(new); + } + let cy_top = cy_owned.take().unwrap(); + if cbit(c, off + n - 1) { circ.cx(*ctrl, a[n - 1]); } + circ.cx(cy_top, a[n - 1]); + { + let b = circ.alloc_bit(); + circ.hmr(cy_top, b); + bits.push(b); + } + circ.zero_and_free(cy_top); + for i in 0..(n - 1) { circ.z_if_bit(dirty[i], bits[i]); } + for q in a { circ.x(*q); } + xor_carries_off_cin(circ, ctrl, a, c, off, dirty, cin); + for q in a { circ.x(*q); } + for i in 0..(n - 1) { circ.z_if_bit(dirty[i], bits[i]); } +} + +fn graduated_const_fits(n: usize, k: usize) -> bool { + k >= 4 && (k - 3) * (k - 2) / 2 >= n +} +fn graduated_const_kmin(n: usize) -> usize { + (4..).find(|&k| graduated_const_fits(n, k)).unwrap() +} + +fn const_chunk_add_clean(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, cout: &QubitId) { + let call_index = next_const_chunk_call_index(); + let s = a.len(); + if std::env::var_os("TRACE_TLM_CONST_CHUNK").is_some() { + eprintln!( + "CONST_CHUNK call={} phase={} width={} coff={} cin={} cout={}", + call_index, + circ.phase, + s, + coff, + cin.0, + cout.0, + ); + } + if s == 0 { + return; + } + let mut int: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); + for i in 0..s { + let on = cbit(c, coff + i); + let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; + let cout_ref: QubitId = if i == s - 1 { *cout } else { *int[i].as_ref().unwrap() }; + circ.cx(cin_ref, a[i]); + if on { + circ.cx(*ctrl, cin_ref); + } + let old_context = crate::point_add::set_op_trace_context( + 0x0800_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + if !const_chunk_call_has_structurally_dead_carry(call_index, i) { + circ.ccx(a[i], cin_ref, cout_ref); + } + crate::point_add::restore_op_trace_context(old_context); + if on { + circ.cx(*ctrl, cin_ref); + } + circ.cx(cin_ref, cout_ref); + } + for i in 0..s { + if cbit(c, coff + i) { + circ.cx(*ctrl, a[i]); + } + } + for i in (0..s - 1).rev() { + let on = cbit(c, coff + i); + let int_i = int[i].take().unwrap(); + let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; + if on { + circ.cx(*ctrl, a[i]); + } + circ.cx(cin_ref, int_i); + if on { + circ.cx(*ctrl, cin_ref); + } + let b = circ.alloc_bit(); + circ.hmr(int_i, b); + circ.zero_and_free(int_i); + circ.cz_if_bit(a[i], cin_ref, b); + if on { + circ.cx(*ctrl, cin_ref); + circ.cx(*ctrl, a[i]); + } + } +} + +fn const_chunk_add_clean_drop_cout(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId) { + let s = a.len(); + if s == 0 { + return; + } + if s == 1 { + if cbit(c, coff) { + circ.cx(*ctrl, a[0]); + } + circ.cx(*cin, a[0]); + return; + } + let mut int: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); + for i in 0..s - 1 { + let on = cbit(c, coff + i); + let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; + let cout_ref: QubitId = *int[i].as_ref().unwrap(); + circ.cx(cin_ref, a[i]); + if on { + circ.cx(*ctrl, cin_ref); + } + circ.ccx(a[i], cin_ref, cout_ref); + if on { + circ.cx(*ctrl, cin_ref); + } + circ.cx(cin_ref, cout_ref); + } + for i in 0..s - 1 { + if cbit(c, coff + i) { + circ.cx(*ctrl, a[i]); + } + } + if cbit(c, coff + s - 1) { + circ.cx(*ctrl, a[s - 1]); + } + circ.cx(*int[s - 2].as_ref().unwrap(), a[s - 1]); + for i in (0..s - 1).rev() { + let on = cbit(c, coff + i); + let int_i = int[i].take().unwrap(); + let cin_ref: QubitId = if i == 0 { *cin } else { *int[i - 1].as_ref().unwrap() }; + if on { + circ.cx(*ctrl, a[i]); + } + circ.cx(cin_ref, int_i); + if on { + circ.cx(*ctrl, cin_ref); + } + let b = circ.alloc_bit(); + circ.hmr(int_i, b); + circ.zero_and_free(int_i); + circ.cz_if_bit(a[i], cin_ref, b); + if on { + circ.cx(*ctrl, cin_ref); + circ.cx(*ctrl, a[i]); + } + } +} + +fn compare_geq_const_cin_middle(circ: &mut B, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, body: F) { + let s = a.len(); + let mut cy: Vec> = Vec::with_capacity(s); + let c0 = circ.alloc_qubit(); + circ.x(c0); + circ.cx(*cin, c0); + cy.push(Some(c0)); + for i in 0..s - 1 { + let on = cbit(c, coff + i); + let next = circ.alloc_qubit(); + let ci = *cy[i].as_ref().unwrap(); + circ.ccx(a[i], ci, next); + if !on { + circ.cx(a[i], next); + circ.cx(ci, next); + } + cy.push(Some(next)); + } + { + let i = s - 1; + let on = cbit(c, coff + i); + let ci = *cy[i].as_ref().unwrap(); + body(circ, &a[i], &ci, on); + } + for i in (0..s - 1).rev() { + let on = cbit(c, coff + i); + let next = cy[i + 1].take().unwrap(); + let ci = *cy[i].as_ref().unwrap(); + if !on { + circ.cx(ci, next); + circ.cx(a[i], next); + } + let b = circ.alloc_bit(); + circ.hmr(next, b); + circ.zero_and_free(next); + circ.cz_if_bit(a[i], ci, b); + } + let c0 = cy[0].take().unwrap(); + circ.cx(*cin, c0); + circ.x(c0); + circ.zero_and_free(c0); +} + +fn controlled_erase_carry_gated_const(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, carry: QubitId) { + let bit = circ.alloc_bit(); + circ.hmr(carry, bit); + + circ.loan_zero_qubit(carry); + circ.push_condition(bit); + compare_geq_const_cin_middle(circ, a, c, coff, cin, |cc, a_top, cy_top, ctop| { + + cc.z(*ctrl); + cc.ccz(*ctrl, *a_top, *cy_top); + if !ctop { + cc.cz(*ctrl, *a_top); + cc.cz(*ctrl, *cy_top); + } + }); + circ.pop_condition(); +} + +fn controlled_add_const_chunked_graduated_off(circ: &mut B, ctrl: &QubitId, a: &[QubitId], c: &[u8], coff: usize, cin: &QubitId, k: usize) { + let n = a.len(); + if n == 0 { + return; + } + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let (mut lo, mut i) = (0usize, 0usize); + while lo < n && k > i + 3 { + let cc = (k - 3 - i).min(n - lo); + bounds.push((lo, lo + cc)); + lo += cc; + i += 1; + } + assert_eq!(lo, n, "graduated staircase (k={k}) covers {lo} < n={n}"); + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(clo, chi)) in bounds.iter().enumerate() { + if std::env::var("TLM_GRAD_FINAL_NO_COUT").ok().as_deref() == Some("1") && j + 1 == bounds.len() { + let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; + const_chunk_add_clean_drop_cout(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref); + break; + } + let cout = circ.alloc_qubit(); + let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; + const_chunk_add_clean(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref, &cout); + carries.push(cout); + } + for j in (0..carries.len()).rev() { + let (clo, chi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + let cin_ref: QubitId = if j == 0 { *cin } else { carries[j - 1] }; + controlled_erase_carry_gated_const(circ, ctrl, &a[clo..chi], c, coff + clo, &cin_ref, carry); + } +} + +#[allow(clippy::needless_range_loop)] +fn add_f_window_hybrid( + circ: &mut B, + ctrl: &QubitId, + reg: &[QubitId], + lsbs: usize, + c: &[u8], + k: usize, + trace_call_index: usize, +) { + let n = lsbs; + let a: Vec = reg[..n].to_vec(); + let suf_dirty = n - k - 1; + assert!(reg.len() >= lsbs + suf_dirty, "+f hybrid: not enough high bits to borrow"); + let dirty: Vec = (lsbs..lsbs + suf_dirty).map(|i| reg[i]).collect(); + let mut cy: Vec> = (0..k).map(|_| Some(circ.alloc_qubit())).collect(); + + if cbit(c, 0) { circ.ccx(*ctrl, a[0], *cy[0].as_ref().unwrap()); } + for i in 1..k { + let ci = *cy[i - 1].as_ref().unwrap(); + let next = *cy[i].as_ref().unwrap(); + circ.cx(ci, a[i]); + if cbit(c, i) { circ.cx(*ctrl, ci); } + if !ffg_call_has_structurally_dead_hybrid_carry(trace_call_index, i, circ.phase) { + let old_context = crate::point_add::set_op_trace_context( + 0x0100_0000 | (((trace_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(a[i], ci, next); + crate::point_add::restore_op_trace_context(old_context); + } + if cbit(c, i) { circ.cx(*ctrl, ci); } + circ.cx(ci, next); + } + + for i in 0..k { if cbit(c, i) { circ.cx(*ctrl, a[i]); } } + let release_cy0_during_suffix = + std::env::var("TLM_FFG_RELEASE_CY0_DURING_SUFFIX") + .ok() + .as_deref() + == Some("1") + && (std::env::var_os("TLM_FFG_RELEASE_CY0_CALLS").is_none() + || env_index_list_contains("TLM_FFG_RELEASE_CY0_CALLS", trace_call_index)) + && k > 1 + && cbit(c, 0); + if release_cy0_during_suffix { + let cy0 = *cy[0].as_ref().unwrap(); + + circ.x(a[0]); + circ.ccx(*ctrl, a[0], cy0); + circ.x(a[0]); + circ.loan_zero_qubit(cy0); + } + + { + let a_hi: Vec = a[k..].to_vec(); + let cin = *cy[k - 1].as_ref().unwrap(); + let sn = n - k; + + if sn >= 2 { + controlled_add_const_chunked_graduated_off(circ, ctrl, &a_hi, c, k, &cin, graduated_const_kmin(sn)); + } else { + dirty_carryin(circ, ctrl, &a_hi, c, k, &dirty, &cin); + } + } + if release_cy0_during_suffix { + let cy0 = *cy[0].as_ref().unwrap(); + circ.reclaim_zero_qubit(cy0); + circ.x(a[0]); + circ.ccx(*ctrl, a[0], cy0); + circ.x(a[0]); + } + + for i in (1..k).rev() { + if cbit(c, i) { circ.cx(*ctrl, a[i]); } + let ci = *cy[i - 1].as_ref().unwrap(); + let next = *cy[i].as_ref().unwrap(); + circ.cx(ci, next); + if cbit(c, i) { circ.cx(*ctrl, ci); } + let nq = cy[i].take().unwrap(); + let b = circ.alloc_bit(); + circ.hmr(nq, b); + circ.zero_and_free(nq); + circ.cz_if_bit(a[i], ci, b); + if cbit(c, i) { circ.cx(*ctrl, ci); circ.cx(*ctrl, a[i]); } + } + + let cy0 = cy[0].take().unwrap(); + if cbit(c, 0) { + circ.cx(*ctrl, a[0]); + let b = circ.alloc_bit(); + circ.hmr(cy0, b); + circ.zero_and_free(cy0); + circ.cz_if_bit(a[0], *ctrl, b); + circ.cx(*ctrl, a[0]); + } else { + circ.zero_and_free(cy0); + } +} + +fn add_f_window(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8], g_sched: Option) { + let call_index = next_ffg_call_index(); + let timeline_start = circ.active_timeline.len(); + let n = lsbs; + assert!(n <= reg.len(), "register too short for +f window"); + if n == 0 { return; } + if n == 1 { + if cbit(c, 0) { circ.cx(*ctrl, reg[0]); } + return; + } + + let target_g = super::target_qubit_headroom(circ).map(|headroom| { + let mut reserve = std::env::var("TLM_TARGET_FFG_RESERVE") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(4); + if let Some(call_reserve) = + env_index_value("TLM_TARGET_FFG_CALL_RESERVES", call_index) + { + reserve = call_reserve; + } else if std::env::var("TLM_TARGET_FFG_RESERVE8_CALLS") + .ok() + .map(|value| { + value + .split(',') + .filter_map(|item| item.trim().parse::().ok()) + .any(|candidate| candidate == call_index) + }) + .unwrap_or(false) + { + reserve = 8; + } + if let Some(call_reserve) = + env_index_value("TLM_TARGET_FFG_CALL_RESERVE_OVERRIDES", call_index) + { + reserve = call_reserve; + } + headroom.saturating_sub(reserve) + }); + let scheduled_g = g_sched + .map_or_else(|| CEILING.saturating_sub(circ.active_qubits as usize), |g| g) + .min(target_g.unwrap_or(usize::MAX)) + .min(n - 1); + let capped_g = std::env::var("TLM_FFG_MAX_G") + .ok() + .and_then(|value| value.parse::().ok()) + .map_or(scheduled_g, |cap| scheduled_g.min(cap)); + let g = std::env::var("TLM_FFG_FORCE_G") + .ok() + .and_then(|value| value.parse::().ok()) + .map_or(capped_g, |forced| forced.min(n - 1)); + let trace_entry_active = circ.active_qubits; + if g >= n - 1 { + add_f_window_clean(circ, ctrl, reg, lsbs, c); + } else if g == 0 { + let cin = circ.alloc_qubit(); + let a_full: Vec = reg[..n].to_vec(); + let dirty: Vec = (lsbs..lsbs + (n - 1)).map(|i| reg[i]).collect(); + dirty_carryin(circ, ctrl, &a_full, c, 0, &dirty, &cin); + circ.zero_and_free(cin); + } else { + add_f_window_hybrid(circ, ctrl, reg, lsbs, c, g, call_index); + } + if std::env::var_os("TRACE_TLM_FFG").is_some() { + let local_peak = circ.active_timeline[timeline_start..] + .iter() + .map(|(_, active)| *active) + .max() + .unwrap_or(trace_entry_active); + eprintln!( + "TLM_FFG call={} phase={} g={} entry_active={} local_peak={} phase_max={} ops={}", + call_index, + circ.phase, + g, + trace_entry_active, + local_peak, + circ.current_phase_active_max, + circ.current_ops_len(), + ); + } +} + +fn add_f_window_clean(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8]) { + let n = lsbs; + assert!(n <= reg.len(), "register too short for +f window"); + if n == 0 { + return; + } + if n == 1 { + if cbit(c, 0) { + circ.cx(*ctrl, reg[0]); + } + return; + } + let a: Vec = reg[..n].to_vec(); + + let mut cy: Vec> = (0..n - 1).map(|_| Some(circ.alloc_qubit())).collect(); + + if cbit(c, 0) { + circ.ccx(*ctrl, a[0], *cy[0].as_ref().unwrap()); + } + + for i in 1..n - 1 { + let ci = cy[i - 1].take().unwrap(); + let next = cy[i].take().unwrap(); + circ.cx(ci, a[i]); + if cbit(c, i) { + circ.cx(*ctrl, ci); + } + circ.ccx(a[i], ci, next); + if cbit(c, i) { + circ.cx(*ctrl, ci); + } + circ.cx(ci, next); + cy[i - 1] = Some(ci); + cy[i] = Some(next); + } + + for i in 0..n - 1 { + if cbit(c, i) { + circ.cx(*ctrl, a[i]); + } + } + if cbit(c, n - 1) { + circ.cx(*ctrl, a[n - 1]); + } + circ.cx(*cy[n - 2].as_ref().unwrap(), a[n - 1]); + + for i in (1..n - 1).rev() { + if cbit(c, i) { + circ.cx(*ctrl, a[i]); + } + let next = cy[i].take().unwrap(); + let ci = cy[i - 1].take().unwrap(); + circ.cx(ci, next); + if cbit(c, i) { + circ.cx(*ctrl, ci); + } + + let mbit = circ.alloc_bit(); + circ.hmr(next, mbit); + circ.zero_and_free(next); + circ.cz_if_bit(a[i], ci, mbit); + if cbit(c, i) { + circ.cx(*ctrl, ci); + circ.cx(*ctrl, a[i]); + } + cy[i - 1] = Some(ci); + } + + let cy1 = cy[0].take().unwrap(); + if cbit(c, 0) { + circ.cx(*ctrl, a[0]); + let mbit = circ.alloc_bit(); + circ.hmr(cy1, mbit); + circ.zero_and_free(cy1); + + circ.cz_if_bit(a[0], *ctrl, mbit); + circ.cx(*ctrl, a[0]); + } else { + + circ.zero_and_free(cy1); + } +} + +fn sub_f_window(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8]) { + for q in ®[..lsbs] { + circ.x(*q); + } + add_f_window(circ, ctrl, reg, lsbs, c, None); + for q in ®[..lsbs] { + circ.x(*q); + } +} + +fn controlled_lt_msbs_conditional(circ: &mut B, ctrl: Option<&QubitId>, a: &[QubitId], b: &[QubitId], k: usize, target: QubitId) { + let a_top: Vec = a[a.len() - k..].to_vec(); + let b_top: Vec = b[b.len() - k..].to_vec(); + let bit = circ.alloc_bit(); + circ.hmr(target, bit); + + circ.zero_and_free(target); + let ctrl = ctrl.copied(); + circ.push_condition(bit); + + let lt_flag = circ.alloc_qubit(); + super::comparator::compare_geq_chunked_middle( + circ, + &a_top, + &b_top, + <_flag, + |c, flag| { + c.x(*flag); + match &ctrl { + Some(ct) => c.cz(*ct, *flag), + None => c.z(*flag), + } + c.x(*flag); + }, + k, + ); + circ.zero_and_free(lt_flag); + circ.pop_condition(); +} + +fn controlled_add_carry_msbs_conditional(circ: &mut B, ctrl: Option<&QubitId>, a: &[QubitId], b: &[QubitId], k: usize, target: &QubitId) { + let a_top: Vec = a[a.len() - k..].to_vec(); + let b_top: Vec = b[b.len() - k..].to_vec(); + let bit = circ.alloc_bit(); + circ.hmr(*target, bit); + circ.push_condition(bit); + for q in &b_top { + circ.x(*q); + } + + let ctrl = ctrl.copied(); + let lt_flag = circ.alloc_qubit(); + super::comparator::compare_geq_chunked_middle(circ, &b_top, &a_top, <_flag, |c, flag| { + c.x(*flag); + match &ctrl { + Some(ct) => c.cz(*ct, *flag), + None => c.z(*flag), + } + c.x(*flag); + }, k); + circ.zero_and_free(lt_flag); + for q in &b_top { + circ.x(*q); + } + circ.pop_condition(); +} + +pub fn controlled_mod_add_k(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], sched_k: Option, ffg_g: Option) { + let n = x.len(); + assert_eq!(y.len(), n, "x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 controlled_mod_add expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + + circ.set_phase("tlm_apply_forward_mod_add_register"); + match sched_k { + Some(k) => { + let yr: Vec<&QubitId> = y.iter().collect(); + let xr: Vec<&QubitId> = x.iter().collect(); + super::gidney::controlled_hybrid_add_cout_refs(circ, ctrl, &yr, &xr, &anc, k); + } + None => controlled_add_vented_chunked_cout(circ, ctrl, x, y, APPLY_CHUNK, Some(&anc)), + } + + circ.set_phase("tlm_apply_forward_mod_add_fold"); + add_f_window(circ, &anc, y, LSBS, &f_bytes, ffg_g); + + debug_assert_eq!(MSBS, PAD); + + circ.set_phase("tlm_apply_forward_mod_add_clean"); + controlled_lt_msbs_conditional(circ, Some(ctrl), &y[..n], &x[..n], MSBS, anc); +} + +pub fn mod_sub(circ: &mut B, x: &[QubitId], y: &[QubitId]) { + let n = x.len(); + assert_eq!(y.len(), n, "x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_sub expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + + for q in y { + circ.x(*q); + } + + if std::env::var("TLM_SQUARE_NO_VENT_REDUCE").ok().as_deref() == Some("1") { + cuccaro_carry(circ, None, x, y, None, Some(&anc)); + } else { + + let ci = next_cuccaro_call_index(); + add_cout_vented_skip_dead(circ, x, y, &anc, ci); + } + for q in y { + circ.x(*q); + } + + sub_f_window(circ, &anc, y, LSBS, &f_bytes); + + controlled_add_carry_msbs_conditional(circ, None, &y[..n], &x[..n], MSBS, &anc); + circ.zero_and_free(anc); +} + +fn add_cout_vented_unctrl(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId) { + let n = y.len(); + assert_eq!(x.len(), n, "add_cout_vented_unctrl: x,y width mismatch"); + let zpad = circ.alloc_qubit(); + let mut a: Vec = y.to_vec(); + a.push(*cout); + let mut b: Vec = x.to_vec(); + b.push(zpad); + hybrid_add_plain(circ, &a, &b, n); + circ.zero_and_free(zpad); +} + +pub fn mod_rsub_vented_loaded(circ: &mut B, t1: &[QubitId], y: &[QubitId]) { + let n = y.len(); + assert_eq!(t1.len(), n, "mod_rsub_vented_loaded: t1,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_rsub_vented_loaded expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + for q in y { + circ.x(*q); + } + add_cout_vented_unctrl(circ, t1, y, &anc); + circ.x(anc); + for q in &y[..LSBS] { + circ.x(*q); + } + add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); + for q in &y[..LSBS] { + circ.x(*q); + } + circ.x(anc); + controlled_lt_msbs_conditional(circ, None, &y[..n], &t1[..n], MSBS, anc); +} + +fn add_cout_vented_skip_dead(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId, call_index: usize) { + let n = y.len(); + assert_eq!(x.len(), n, "add_cout_vented_skip_dead: x,y width mismatch"); + let dead = |i: usize| cuccaro_call_has_structurally_dead_carry(call_index, i); + let zpad = circ.alloc_qubit(); + let live = circ.active_qubits as usize; + let margin = std::env::var("TLM_SQUARE_VENT_MARGIN") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(SQUARE_VENT_MARGIN); + let vents_budget = square_peak_hard_cap().saturating_sub(live).saturating_sub(margin); + + let mut a: Vec = y.to_vec(); + a.push(*cout); + let mut b: Vec = x.to_vec(); + b.push(zpad); + let m = a.len(); + + let mut vents_left = vents_budget; + for i in 1..m { + circ.cx(b[i], a[i]); + } + for i in (1..m - 1).rev() { + circ.cx(b[i], b[i + 1]); + } + let mut vent_ancs: Vec> = (0..m - 1).map(|_| None).collect(); + for i in 0..m - 1 { + if dead(i) { + continue; + } + if vents_left > 0 { + let anc = circ.alloc_qubit(); + circ.ccx(a[i], b[i], anc); + circ.cx(anc, b[i + 1]); + vent_ancs[i] = Some(anc); + vents_left -= 1; + } else { + circ.ccx(a[i], b[i], b[i + 1]); + } + } + for i in (0..m - 1).rev() { + circ.cx(b[i + 1], a[i + 1]); + if dead(i) { + continue; + } + if let Some(anc) = vent_ancs[i].take() { + circ.cx(anc, b[i + 1]); + let bit = circ.alloc_bit(); + circ.hmr(anc, bit); + circ.zero_and_free(anc); + circ.cz_if_bit(a[i], b[i], bit); + } else { + circ.ccx(a[i], b[i], b[i + 1]); + } + } + for i in 1..m - 1 { + circ.cx(b[i], b[i + 1]); + } + circ.cx(b[0], a[0]); + for i in 1..m { + circ.cx(b[i], a[i]); + } + circ.zero_and_free(zpad); +} + +fn add_cout_vented_unctrl_bounded(circ: &mut B, x: &[QubitId], y: &[QubitId], cout: &QubitId) { + let n = y.len(); + assert_eq!(x.len(), n, "add_cout_vented_unctrl_bounded: x,y width mismatch"); + let zpad = circ.alloc_qubit(); + + let live = circ.active_qubits as usize; + let margin = std::env::var("TLM_SQUARE_VENT_MARGIN") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(SQUARE_VENT_MARGIN); + let headroom = square_peak_hard_cap().saturating_sub(live).saturating_sub(margin); + let mut a: Vec = y.to_vec(); + a.push(*cout); + let mut b: Vec = x.to_vec(); + b.push(zpad); + hybrid_add_plain(circ, &a, &b, headroom); + circ.zero_and_free(zpad); +} + +pub const SQUARE_PEAK_HARD_CAP: usize = 1153; + +pub const SQUARE_VENT_MARGIN: usize = 30; + +fn square_peak_hard_cap() -> usize { + std::env::var("TLM_SQUARE_PEAK_CAP") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(SQUARE_PEAK_HARD_CAP) +} + +pub fn mod_add(circ: &mut B, x: &[QubitId], y: &[QubitId]) { + let n = x.len(); + assert_eq!(y.len(), n, "mod_add: x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_add expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + add_cout_vented_unctrl(circ, x, y, &anc); + + add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); + + controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], MSBS, anc); +} + +pub fn mod_add_exact(circ: &mut B, x: &[QubitId], y: &[QubitId]) { + let n = x.len(); + assert_eq!(y.len(), n, "mod_add_exact: x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_add_exact expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + add_cout_vented_unctrl(circ, x, y, &anc); + add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); + + controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], n, anc); +} + +pub fn mod_add_lowpeak(circ: &mut B, x: &[QubitId], y: &[QubitId]) { + let n = x.len(); + assert_eq!(y.len(), n, "mod_add_lowpeak: x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_add_lowpeak expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + + if std::env::var("TLM_SQUARE_NO_VENT_REDUCE").ok().as_deref() == Some("1") { + cuccaro_carry(circ, None, x, y, None, Some(&anc)); + } else { + let ci = next_cuccaro_call_index(); + add_cout_vented_skip_dead(circ, x, y, &anc, ci); + } + add_f_window(circ, &anc, y, LSBS, &f_bytes, None); + controlled_lt_msbs_conditional(circ, None, &y[..n], &x[..n], MSBS, anc); +} + +pub fn mod_add_shifted_low(circ: &mut B, x: &[QubitId], y: &[QubitId], shift: usize) { + let n = y.len(); + assert_eq!(n, 256, "mod_add_shifted_low expects 256-bit y"); + assert!(shift < n, "shift must be less than 256"); + assert_eq!(x.len(), n - shift, "x must be the low shifted limb"); + if shift == 0 { + mod_add(circ, x, y); + return; + } + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + + if std::env::var("TLM_SQUARE_VENT_SHIFTED").ok().as_deref() == Some("1") { + let ci = next_cuccaro_call_index(); + add_cout_vented_skip_dead(circ, x, &y[shift..], &anc, ci); + } else { + cuccaro_carry(circ, None, x, &y[shift..], None, Some(&anc)); + } + add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); + controlled_lt_msbs_conditional(circ, None, &y[n - MSBS..], &x[x.len() - MSBS..], MSBS, anc); +} + +pub fn mod_sub_vented(circ: &mut B, x: &[QubitId], y: &[QubitId]) { + let n = x.len(); + assert_eq!(y.len(), n, "mod_sub_vented: x,y must both be n=256 bits"); + assert_eq!(n, 256, "secp256k1 mod_sub_vented expects n=256"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + for q in y { + circ.x(*q); + } + add_cout_vented_unctrl(circ, x, y, &anc); + for q in y { + circ.x(*q); + } + + for q in &y[..LSBS] { + circ.x(*q); + } + add_f_window(circ, &anc, y, LSBS, &f_bytes, Some(LSBS - 1)); + for q in &y[..LSBS] { + circ.x(*q); + } + controlled_add_carry_msbs_conditional(circ, None, &y[..n], &x[..n], MSBS, &anc); + circ.zero_and_free(anc); +} + +pub fn mod_sub_shifted_low(circ: &mut B, x: &[QubitId], y: &[QubitId], shift: usize) { + let n = y.len(); + assert_eq!(n, 256, "mod_sub_shifted_low expects 256-bit y"); + assert!(shift < n, "shift must be less than 256"); + assert_eq!(x.len(), n - shift, "x must be the low shifted limb"); + if shift == 0 { + mod_sub(circ, x, y); + return; + } + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + for q in &y[shift..] { + circ.x(*q); + } + if std::env::var("TLM_SQUARE_VENT_SHIFTED").ok().as_deref() == Some("1") { + let ci = next_cuccaro_call_index(); + add_cout_vented_skip_dead(circ, x, &y[shift..], &anc, ci); + } else { + cuccaro_carry(circ, None, x, &y[shift..], None, Some(&anc)); + } + for q in &y[shift..] { + circ.x(*q); + } + sub_f_window(circ, &anc, y, LSBS, &f_bytes); + controlled_add_carry_msbs_conditional(circ, None, &y[n - MSBS..], &x[x.len() - MSBS..], MSBS, &anc); + circ.zero_and_free(anc); +} + +fn toggle_pattern_mcx(circ: &mut B, pattern: &[(QubitId, bool)], target: &QubitId) { + for &(q, expected) in pattern { + if !expected { + circ.x(q); + } + } + let ctrls: Vec<&QubitId> = pattern.iter().map(|(q, _)| q).collect(); + super::mcx::mcx_clean_k(circ, &ctrls, target); + for &(q, expected) in pattern.iter().rev() { + if !expected { + circ.x(q); + } + } +} + +fn toggle_geq_small_const(circ: &mut B, a: &[QubitId], threshold: usize, target: &QubitId) { + assert!(threshold < (1usize << a.len())); + for j in (0..a.len()).rev() { + if (threshold >> j) & 1 != 0 { + continue; + } + let mut pattern = Vec::with_capacity(a.len() - j); + for k in (j + 1)..a.len() { + pattern.push((a[k], (threshold >> k) & 1 != 0)); + } + pattern.push((a[j], true)); + toggle_pattern_mcx(circ, &pattern, target); + } + let equality: Vec<(QubitId, bool)> = a + .iter() + .enumerate() + .map(|(i, &q)| (q, (threshold >> i) & 1 != 0)) + .collect(); + toggle_pattern_mcx(circ, &equality, target); +} + +fn toggle_geq_p_minus_low3(circ: &mut B, y: &[QubitId], c: &[QubitId], target: &QubitId) { + debug_assert_eq!(y.len(), 256); + debug_assert_eq!(c.len(), 3); + + let sum: Vec = (0..11).map(|_| circ.alloc_qubit()).collect(); + for i in 0..10 { + circ.cx(y[i], sum[i]); + } + let zeros: Vec = (0..8).map(|_| circ.alloc_qubit()).collect(); + let mut c11 = c.to_vec(); + c11.extend(zeros.iter().copied()); + cuccaro_carry(circ, None, &c11, &sum, None, None); + + let low_ge = circ.alloc_qubit(); + toggle_geq_small_const(circ, &sum, 47, &low_ge); + let lower = circ.alloc_qubit(); + circ.cx(y[32], lower); + let mut lower_pattern = Vec::with_capacity(24); + lower_pattern.push((y[32], false)); + lower_pattern.extend(y[10..32].iter().map(|&q| (q, true))); + lower_pattern.push((low_ge, true)); + toggle_pattern_mcx(circ, &lower_pattern, &lower); + + let mut full_pattern = Vec::with_capacity(224); + full_pattern.push((lower, true)); + full_pattern.extend(y[33..].iter().map(|&q| (q, true))); + toggle_pattern_mcx(circ, &full_pattern, target); + + toggle_pattern_mcx(circ, &lower_pattern, &lower); + circ.cx(y[32], lower); + circ.zero_and_free(lower); + toggle_geq_small_const(circ, &sum, 47, &low_ge); + circ.zero_and_free(low_ge); + + for q in &sum { + circ.x(*q); + } + cuccaro_carry(circ, None, &c11, &sum, None, None); + for q in &sum { + circ.x(*q); + } + for i in 0..10 { + circ.cx(y[i], sum[i]); + } + for q in sum { + circ.zero_and_free(q); + } + for q in zeros { + circ.zero_and_free(q); + } +} + +pub fn mod_sub_classical_low3(circ: &mut B, y: &[QubitId], c: &[BitId]) { + assert_eq!(y.len(), 256, "mod_sub_classical_low3 expects 256-bit y"); + assert_eq!(c.len(), 3, "mod_sub_classical_low3 expects three classical bits"); + + let cq: Vec = (0..3).map(|_| circ.alloc_qubit()).collect(); + for i in 0..3 { + circ.x_if_bit(cq[i], c[i]); + } + + let low_borrow = circ.alloc_qubit(); + for q in &y[..3] { + circ.x(*q); + } + cuccaro_carry(circ, None, &cq, &y[..3], None, Some(&low_borrow)); + for q in &y[..3] { + circ.x(*q); + } + + let full_borrow = circ.alloc_qubit(); + let mut borrow_pattern = Vec::with_capacity(254); + borrow_pattern.push((low_borrow, true)); + borrow_pattern.extend(y[3..].iter().map(|&q| (q, false))); + toggle_pattern_mcx(circ, &borrow_pattern, &full_borrow); + + for q in &y[3..] { + circ.x(*q); + } + super::mcx::cinc_khattar_gidney(circ, &y[3..], &low_borrow); + for q in &y[3..] { + circ.x(*q); + } + + let low_copy: Vec = (0..3).map(|_| circ.alloc_qubit()).collect(); + for i in 0..3 { + circ.cx(y[i], low_copy[i]); + } + cuccaro_carry(circ, None, &cq, &low_copy, None, Some(&low_borrow)); + for q in &low_copy { + circ.x(*q); + } + cuccaro_carry(circ, None, &cq, &low_copy, None, None); + for q in &low_copy { + circ.x(*q); + } + for i in 0..3 { + circ.cx(y[i], low_copy[i]); + } + for q in low_copy { + circ.zero_and_free(q); + } + circ.zero_and_free(low_borrow); + + let f_bytes = F_SECP256K1.to_le_bytes(); + sub_f_window(circ, &full_borrow, y, LSBS, &f_bytes); + toggle_geq_p_minus_low3(circ, y, &cq, &full_borrow); + circ.zero_and_free(full_borrow); + + for i in 0..3 { + circ.x_if_bit(cq[i], c[i]); + } + for q in cq { + circ.zero_and_free(q); + } +} + +pub fn mod_neg(circ: &mut B, x: &[QubitId]) { + let n = x.len(); + assert_eq!(n, 256, "secp256k1 mod_neg expects n=256"); + let f_minus_1 = (F_SECP256K1 - 1).to_le_bytes(); + add_const_window_clean(circ, x, n, &f_minus_1); + for q in x { + circ.x(*q); + } +} + +fn add_const_window_clean(circ: &mut B, reg: &[QubitId], lsbs: usize, c: &[u8]) { + let add_const_call_index = next_add_const_call_index(); + let n = lsbs; + assert!(n <= reg.len(), "register too short for const window"); + if n == 0 { + return; + } + if n == 1 { + if cbit(c, 0) { + circ.x(reg[0]); + } + return; + } + let a: Vec = reg[..n].to_vec(); + let mut cy: Vec> = (0..n - 1).map(|_| Some(circ.alloc_qubit())).collect(); + + if cbit(c, 0) { + circ.cx(a[0], *cy[0].as_ref().unwrap()); + } + + for i in 1..n - 1 { + let ci = cy[i - 1].take().unwrap(); + let next = cy[i].take().unwrap(); + circ.cx(ci, a[i]); + if cbit(c, i) { + circ.x(ci); + } + if !add_const_has_structurally_dead_carry(add_const_call_index, i) { + let old_context = crate::point_add::set_op_trace_context( + 0x1100_0000 | (((add_const_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(a[i], ci, next); + crate::point_add::restore_op_trace_context(old_context); + } + if cbit(c, i) { + circ.x(ci); + } + circ.cx(ci, next); + cy[i - 1] = Some(ci); + cy[i] = Some(next); + } + + for i in 0..n - 1 { + if cbit(c, i) { + circ.x(a[i]); + } + } + if cbit(c, n - 1) { + circ.x(a[n - 1]); + } + circ.cx(*cy[n - 2].as_ref().unwrap(), a[n - 1]); + + for i in (1..n - 1).rev() { + if cbit(c, i) { + circ.x(a[i]); + } + let next = cy[i].take().unwrap(); + let ci = cy[i - 1].take().unwrap(); + circ.cx(ci, next); + if cbit(c, i) { + circ.x(ci); + } + let mbit = circ.alloc_bit(); + circ.hmr(next, mbit); + circ.zero_and_free(next); + circ.cz_if_bit(a[i], ci, mbit); + if cbit(c, i) { + circ.x(ci); + circ.x(a[i]); + } + cy[i - 1] = Some(ci); + } + + let cy1 = cy[0].take().unwrap(); + if cbit(c, 0) { + circ.x(a[0]); + let mbit = circ.alloc_bit(); + circ.hmr(cy1, mbit); + circ.zero_and_free(cy1); + circ.z_if_bit(a[0], mbit); + circ.x(a[0]); + } else { + circ.zero_and_free(cy1); + } +} + +pub fn mod_double(circ: &mut B, a: &[QubitId]) { + let n = a.len() - 1; + assert_eq!(n, 256, "secp256k1 mod_double expects 257-bit a"); + let f_bytes = F_SECP256K1.to_le_bytes(); + + for i in (0..n).rev() { + circ.swap(a[i], a[i + 1]); + } + + add_f_window(circ, &a[n], a, LSBS, &f_bytes, None); + + circ.cx(a[0], a[n]); +} + +pub fn mod_double_reverse(circ: &mut B, a: &[QubitId]) { + let n = a.len() - 1; + assert_eq!(n, 256, "secp256k1 mod_double_reverse expects 257-bit a"); + let f_bytes = F_SECP256K1.to_le_bytes(); + + circ.cx(a[0], a[n]); + + sub_f_window(circ, &a[n], a, LSBS, &f_bytes); + + for i in 0..n { + circ.swap(a[i], a[i + 1]); + } +} + +pub fn add_f_window_pub(circ: &mut B, ctrl: &QubitId, reg: &[QubitId], lsbs: usize, c: &[u8], g_sched: Option) { + add_f_window(circ, ctrl, reg, lsbs, c, g_sched); +} diff --git a/src/point_add/trailmix_ludicrous/codec.rs b/src/point_add/trailmix_ludicrous/codec.rs index 14f69629..f2cbeb94 100644 --- a/src/point_add/trailmix_ludicrous/codec.rs +++ b/src/point_add/trailmix_ludicrous/codec.rs @@ -1,482 +1,462 @@ - -use super::{B, BExt}; -use crate::circuit::{QubitId}; - -fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { - let bit = circ.alloc_bit(); - circ.hmr(*t, bit); - circ.cz_if_bit(*a, *b, bit); -} - -fn compress_2sym_fast(circ: &mut B, w: &[&QubitId; 6]) { - circ.x(*w[3]); - circ.cx(*w[5], *w[1]); - circ.cx(*w[4], *w[0]); - circ.x(*w[2]); - circ.ccx(*w[1], *w[3], *w[5]); - circ.cx(*w[3], *w[5]); - circ.cx(*w[3], *w[0]); - circ.cx(*w[1], *w[5]); - circ.cx(*w[5], *w[3]); - circ.ccx(*w[5], *w[0], *w[4]); - - clear_and(circ, w[5], w[3], w[4]); -} - -fn compress_2sym_fast_reverse(circ: &mut B, w: &[&QubitId; 6]) { - circ.ccx(*w[3], *w[4], *w[5]); - circ.ccx(*w[5], *w[0], *w[4]); - circ.cx(*w[5], *w[3]); - circ.cx(*w[1], *w[5]); - circ.cx(*w[3], *w[0]); - circ.cx(*w[3], *w[5]); - circ.ccx(*w[1], *w[3], *w[5]); - circ.x(*w[2]); - circ.cx(*w[4], *w[0]); - circ.cx(*w[5], *w[1]); - circ.x(*w[3]); -} - -pub const TRIPLE_DATA_WIRES: [usize; 7] = [0, 1, 2, 3, 4, 7, 8]; - -pub const TRIPLE_FREED_WIRES: [usize; 2] = [5, 6]; - -const TAIL4_TOP32_CODE_BITS: usize = 5; -const TAIL4_TOP32_CODE_CONSTANT: u8 = 22; -const TAIL4_TOP32_ENCODER_ANF: [&[u16]; TAIL4_TOP32_CODE_BITS] = [ - &[2, 4, 8, 16, 32, 1024, 65, 528], - &[1, 2, 4, 16, 32, 520], - &[1, 2, 4, 8, 1024, 72], - &[4, 16, 32, 256, 520], - &[1, 4, 1024, 10, 66], -]; -const TAIL4_TOP32_DECODER_ANF: [&[u16]; 12] = [ - &[0, 3, 7, 18, 20, 21, 25, 27, 29, 31], - &[5, 6, 7, 9, 11, 13, 16, 18, 19, 20, 21, 31], - &[0, 11, 15, 16, 18, 20, 23, 24, 26, 27, 28, 29, 31], - &[3, 4, 5, 6, 11, 18, 19, 20, 21, 24, 26, 27, 28, 30], - &[0, 2, 3, 5, 6, 9, 13, 18, 19, 20, 23, 25, 31], - &[30, 31], - &[3, 7, 9, 13, 19, 21, 25, 30], - &[], - &[2, 3, 5, 6, 8, 9, 11, 13, 16, 19, 25, 27, 29], - &[0, 1, 4, 9, 13, 18, 19, 20, 27, 29], - &[0, 3, 7, 9, 13, 19, 21, 25, 30], - &[0], -]; - -fn tail4_top32_enabled() -> bool { - std::env::var("TLM_TAIL4_TOP32").ok().as_deref() == Some("1") -} - -fn toggle_mcx_with_dirty( - circ: &mut B, - controls: &[QubitId], - dirty: &[QubitId], - target: QubitId, -) { - debug_assert!(!controls.contains(&target)); - match controls.len() { - 0 => circ.x(target), - 1 => circ.cx(controls[0], target), - 2 => circ.ccx(controls[0], controls[1], target), - count => { - let bridge = dirty - .iter() - .copied() - .find(|q| *q != target && !controls.contains(q)) - .expect("tail4 codec needs a disjoint dirty bridge"); - let rest: Vec = dirty.iter().copied().filter(|q| *q != bridge).collect(); - toggle_mcx_with_dirty(circ, &controls[..count - 1], &rest, bridge); - circ.ccx(bridge, controls[count - 1], target); - toggle_mcx_with_dirty(circ, &controls[..count - 1], &rest, bridge); - circ.ccx(bridge, controls[count - 1], target); - } - } -} - -fn toggle_anf_with_dirty( - circ: &mut B, - controls: &[QubitId], - target: QubitId, - dirty: &[QubitId], - terms: &[u16], -) { - for &mask in terms { - let term_controls: Vec = controls - .iter() - .enumerate() - .filter_map(|(i, q)| ((mask >> i) & 1 != 0).then_some(*q)) - .collect(); - toggle_mcx_with_dirty(circ, &term_controls, dirty, target); - } -} - -fn tail4_reordered_raw(raw: &[QubitId]) -> [QubitId; 12] { - assert_eq!(raw.len(), 12, "tail4 raw window must contain four symbols"); - [ - raw[0], raw[1], raw[3], raw[4], raw[6], raw[7], raw[9], raw[10], - raw[2], raw[5], raw[8], raw[11], - ] -} - -fn tail4_toggle_code_from_raw(circ: &mut B, code: &[QubitId], raw: &[QubitId]) { - assert_eq!(code.len(), TAIL4_TOP32_CODE_BITS); - let wires = tail4_reordered_raw(raw); - for (i, terms) in TAIL4_TOP32_ENCODER_ANF.iter().enumerate() { - if (TAIL4_TOP32_CODE_CONSTANT >> i) & 1 != 0 { - circ.x(code[i]); - } - for &mask in *terms { - let controls: Vec = wires - .iter() - .enumerate() - .filter_map(|(j, q)| ((mask >> j) & 1 != 0).then_some(*q)) - .collect(); - toggle_mcx_with_dirty(circ, &controls, &wires, code[i]); - } - } -} - -fn tail4_toggle_raw_from_code(circ: &mut B, code: &[QubitId], raw: &[QubitId]) { - assert_eq!(code.len(), TAIL4_TOP32_CODE_BITS); - let wires = tail4_reordered_raw(raw); - for (i, terms) in TAIL4_TOP32_DECODER_ANF.iter().enumerate() { - toggle_anf_with_dirty(circ, code, wires[i], &wires, terms); - } -} - -fn compress_tail4_top32_payload(circ: &mut B, raw: &[QubitId]) -> Vec { - let code: Vec = (0..TAIL4_TOP32_CODE_BITS) - .map(|_| circ.alloc_qubit()) - .collect(); - tail4_toggle_code_from_raw(circ, &code, raw); - tail4_toggle_raw_from_code(circ, &code, raw); - for &q in raw { - circ.zero_and_free(q); - } - code -} - -fn decompress_tail4_top32_payload(circ: &mut B, code: &[QubitId]) -> Vec { - let raw: Vec = (0..12).map(|_| circ.alloc_qubit()).collect(); - tail4_toggle_raw_from_code(circ, code, &raw); - tail4_toggle_code_from_raw(circ, code, &raw); - for &q in code { - circ.zero_and_free(q); - } - raw -} - -fn compress_tail4_top32(circ: &mut B, raw: &[QubitId]) -> Vec { - assert_eq!(raw.len(), 15, "tail4 hybrid window must contain five symbols"); - let mut data = raw[..3].to_vec(); - data.extend(compress_tail4_top32_payload(circ, &raw[3..])); - data -} - -fn decompress_tail4_top32(circ: &mut B, data: &[QubitId]) -> Vec { - assert_eq!(data.len(), 3 + TAIL4_TOP32_CODE_BITS); - let mut raw = data[..3].to_vec(); - raw.extend(decompress_tail4_top32_payload(circ, &data[3..])); - raw -} - -#[rustfmt::skip] -const NORMALIZER_OPS: &[(u8, u8, u8, u8)] = &[ - (1,10,9,0), (1,9,6,0), (1,10,6,0), (1,6,10,0), (1,10,6,0), (0,8,0,0), (0,9,0,0), (2,7,9,10), - (1,10,9,0), (1,10,7,0), (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,8,10,0), (1,9,8,0), (1,8,9,0), - (1,9,8,0), (1,8,7,0), (1,7,8,0), (1,8,7,0), (1,8,6,0), (1,6,8,0), (1,8,6,0), (2,6,8,10), - (1,9,7,0), (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,9,7,0), (1,7,9,0), (1,9,7,0), (1,7,6,0), - (1,6,7,0), (1,7,6,0), (1,10,9,0), (1,10,9,0), (1,10,8,0), (1,10,7,0), (1,9,10,0), (1,9,8,0), - (1,9,7,0), (1,10,8,0), (1,8,10,0), (1,10,8,0), (1,7,6,0), (1,6,10,0), (0,10,0,0), (2,6,7,8), - (1,10,9,0), (1,10,8,0), (1,10,7,0), (1,10,6,0), (1,8,10,0), (1,8,9,0), (1,8,7,0), (1,8,6,0), - (1,7,8,0), (1,6,9,0), (1,6,8,0), (0,8,0,0), (2,6,7,8), (1,10,9,0), (1,10,8,0), (1,10,7,0), - (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,8,10,0), (1,9,8,0), (1,8,9,0), (1,9,8,0), (1,7,6,0), - (1,6,10,0), (1,6,9,0), (0,9,0,0), (0,10,0,0), (2,6,10,8), (1,10,9,0), (1,9,8,0), (1,9,7,0), - (1,9,6,0), (1,8,7,0), (1,8,6,0), (1,10,8,0), (1,8,10,0), (1,10,8,0), (1,7,6,0), (1,6,9,0), - (1,7,6,0), (1,6,7,0), (1,7,6,0), (0,6,0,0), (0,8,0,0), (2,7,8,9), (1,6,8,0), (1,7,8,0), - (1,7,6,0), (1,6,8,0), (1,7,6,0), (1,6,7,0), (1,7,6,0), (0,6,0,0), (0,9,0,0), (0,10,0,0), -]; - -#[rustfmt::skip] -const MERGE25_OPS: &[(u8, u8, u8, u8)] = &[ - (1,12,9,0), (1,14,10,0), (2,10,12,14), (1,13,9,0), (2,9,12,13), (2,13,14,12), (1,12,6,0), (1,7,10,0), - (2,10,12,7), (1,6,9,0), (2,9,12,6), (1,12,8,0), (0,12,0,0), (1,14,12,0), (1,7,10,0), (0,10,0,0), - (1,6,9,0), (0,13,0,0), (2,8,13,15), (2,14,15,16), (2,8,13,15), (2,10,9,15), (2,16,15,12), (2,10,9,15), - (2,8,13,15), (2,14,15,16), (2,8,13,15), (0,13,0,0), (1,6,9,0), (0,10,0,0), (1,7,10,0), -]; - -const MERGE25_CLEAR_FWD: [usize; 5] = [20, 22, 23, 25, 26]; -const MERGE25_CLEAR_REV: [usize; 4] = [18, 19, 21, 24]; - -#[inline] -fn apply_op_off(circ: &mut B, w: &[&QubitId], op: (u8, u8, u8, u8), off: u8) { - let m = |i: u8| w[(i - off) as usize]; - match op.0 { - 0 => circ.x(*m(op.1)), - 1 => circ.cx(*m(op.1), *m(op.2)), - 2 => circ.ccx(*m(op.1), *m(op.2), *m(op.3)), - _ => unreachable!("bad codec op kind"), - } -} - -fn apply_merge25(circ: &mut B, w: &[&QubitId], off: u8, reverse: bool) { - let clear: &[usize] = if reverse { &MERGE25_CLEAR_REV } else { &MERGE25_CLEAR_FWD }; - let n = MERGE25_OPS.len(); - for step in 0..n { - let i = if reverse { n - 1 - step } else { step }; - // E208: ops 18..=26 form one 5-control Toffoli w12 ^= AND(w8,w9,w10,w13,w14), - // 9 Toffoli-class gates (2 clean anc). Replace with mcx_clean_k: 7 gates, 3 clean anc. - // 5-ctrl Toffoli is an involution => same call for forward and reverse. - if i == 18 { - super::mcx::mcx_clean_k( - circ, - &[ - w[(8 - off) as usize], - w[(9 - off) as usize], - w[(10 - off) as usize], - w[(13 - off) as usize], - w[(14 - off) as usize], - ], - w[(12 - off) as usize], - ); - continue; - } - if (19..=26).contains(&i) { - continue; - } - let op = MERGE25_OPS[i]; - if clear.contains(&i) { - clear_and( - circ, - w[(op.3 - off) as usize], - w[(op.1 - off) as usize], - w[(op.2 - off) as usize], - ); - } else { - apply_op_off(circ, w, op, off); - } - } -} - -fn compress_3sym(circ: &mut B, w: &[&QubitId; 11]) { - compress_2sym_fast(circ, &[w[0], w[1], w[2], w[3], w[4], w[5]]); - for &op in NORMALIZER_OPS { - apply_op_off(circ, &w[..], op, 6); - } - apply_merge25(circ, &w[..], 6, false); -} - -fn compress_3sym_reverse(circ: &mut B, w: &[&QubitId; 11]) { - apply_merge25(circ, &w[..], 6, true); - for &op in NORMALIZER_OPS.iter().rev() { - apply_op_off(circ, &w[..], op, 6); - } - compress_2sym_fast_reverse(circ, &[w[0], w[1], w[2], w[3], w[4], w[5]]); -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum DialogCodec { - - Pair, - - Triple, - - Raw, - - Step0, - - Tail4Top32, -} - -impl DialogCodec { - - pub fn syms(self) -> usize { - match self { - Self::Pair => 2, - Self::Triple => 3, - Self::Tail4Top32 => 5, - Self::Raw | Self::Step0 => 1, - } - } - - pub fn code_bits(self) -> usize { - match self { - Self::Pair => 5, - Self::Triple => 7, - Self::Tail4Top32 => 3 + TAIL4_TOP32_CODE_BITS, - Self::Raw => 3, - Self::Step0 => 2, - } - } - - fn clean_anc(self) -> usize { - match self { - Self::Pair | Self::Raw | Self::Step0 | Self::Tail4Top32 => 0, - Self::Triple => 2, - } - } - - fn data_wires(self) -> &'static [usize] { - match self { - Self::Pair => &[0, 1, 2, 3, 4], - Self::Triple => &TRIPLE_DATA_WIRES, - Self::Raw => &[0, 1, 2], - Self::Step0 => &[0, 2], - Self::Tail4Top32 => &[], - } - } - - fn freed_wires(self) -> &'static [usize] { - match self { - Self::Pair => &[5], - Self::Triple => &TRIPLE_FREED_WIRES, - Self::Raw => &[], - Self::Step0 => &[1], - Self::Tail4Top32 => &[], - } - } - - fn compress(self, circ: &mut B, win: &[&QubitId]) { - match self { - Self::Pair => compress_2sym_fast(circ, win.try_into().unwrap()), - Self::Triple => compress_3sym(circ, win.try_into().unwrap()), - Self::Raw => {} - - Self::Step0 => circ.cx(*win[0], *win[1]), - Self::Tail4Top32 => unreachable!("tail4 uses separate code wires"), - } - } - - fn decompress(self, circ: &mut B, win: &[&QubitId]) { - match self { - Self::Pair => compress_2sym_fast_reverse(circ, win.try_into().unwrap()), - Self::Triple => compress_3sym_reverse(circ, win.try_into().unwrap()), - Self::Raw => {} - - Self::Step0 => circ.cx(*win[0], *win[1]), - Self::Tail4Top32 => unreachable!("tail4 uses separate code wires"), - } - } - - #[must_use] - pub fn decompress_window(self, circ: &mut B, data: &[QubitId]) -> Vec { - assert_eq!(data.len(), self.code_bits(), "data len != code_bits"); - if self == Self::Tail4Top32 { - return decompress_tail4_top32(circ, data); - } - - let mut slots: Vec> = (0..self.syms() * 3).map(|_| None).collect(); - let mut it = data.iter(); - for &d in self.data_wires() { - slots[d] = Some(*it.next().expect("data bit")); - } - for &f in self.freed_wires() { - slots[f] = Some(circ.alloc_qubit()); - } - let raw: Vec = slots.into_iter().map(|s| s.expect("slot")).collect(); - let clean: Vec = (0..self.clean_anc()).map(|_| circ.alloc_qubit()).collect(); - let win: Vec<&QubitId> = raw.iter().chain(clean.iter()).collect(); - self.decompress(circ, &win); - for q in clean { - circ.zero_and_free(q); - } - raw - } - - #[must_use] - pub fn compress_window(self, circ: &mut B, raw: &[QubitId]) -> Vec { - assert_eq!(raw.len(), self.syms() * 3, "raw len != syms*3"); - if self == Self::Tail4Top32 { - return compress_tail4_top32(circ, raw); - } - let clean: Vec = (0..self.clean_anc()).map(|_| circ.alloc_qubit()).collect(); - let win: Vec<&QubitId> = raw.iter().chain(clean.iter()).collect(); - self.compress(circ, &win); - for q in clean { - circ.zero_and_free(q); - } - - let mut data: Vec = Vec::with_capacity(self.code_bits()); - let dset = self.data_wires(); - for (k, &q) in raw.iter().enumerate() { - if dset.contains(&k) { - data.push(q); - } else { - circ.zero_and_free(q); - } - } - data - } -} - -#[must_use] -pub fn compress_step0_with_t1(circ: &mut B, t1: QubitId, raw: &[QubitId]) -> Vec { - assert_eq!(raw.len(), 3, "step0 raw symbol is [sub, swap, s2]"); - let sub = raw[0]; - let swap = raw[1]; - let s2 = raw[2]; - circ.cx(sub, swap); - circ.cx(sub, t1); - circ.x(sub); - circ.ccx(t1, s2, sub); - circ.zero_and_free(sub); - circ.zero_and_free(swap); - vec![t1, s2] -} - -#[must_use] -pub fn decompress_step0_with_t1(circ: &mut B, data: &[QubitId]) -> (QubitId, Vec) { - assert_eq!(data.len(), 2, "step0+t1 code is two bits"); - let t1 = data[0]; - let s2 = data[1]; - let sub = circ.alloc_qubit(); - let swap = circ.alloc_qubit(); - circ.ccx(t1, s2, sub); - circ.x(sub); - circ.cx(sub, t1); - circ.cx(sub, swap); - (t1, vec![sub, swap, s2]) -} - -#[must_use] -pub fn jump_dialog_regions(n3: usize, iters: usize) -> Vec<(DialogCodec, usize)> { - - let tail4 = usize::from(tail4_top32_enabled() && iters >= 6) * 5; - let codec_syms = iters - 1 - tail4; - let mut n3 = n3; - while 3 * n3 > codec_syms { - n3 -= 1; - } - let rem = codec_syms - 3 * n3; - let mut r = vec![(DialogCodec::Step0, 1)]; - if n3 > 0 { - r.push((DialogCodec::Triple, n3)); - } - - let tight = n3 > 0; - match rem { - 3 if tight => r.push((DialogCodec::Triple, 1)), - _ => { - if rem / 2 > 0 { - r.push((DialogCodec::Pair, rem / 2)); - } - if rem % 2 == 1 { - r.push((DialogCodec::Raw, 1)); - } - } - } - if tail4 != 0 { - r.push((DialogCodec::Tail4Top32, 1)); - } - r -} - -#[must_use] -pub fn dialog_tape_qubits(n3: usize, iters: usize) -> usize { - jump_dialog_regions(n3, iters) - .into_iter() - .map(|(codec, count)| codec.code_bits() * count) - .sum::() -} + +use super::{B, BExt}; +use crate::circuit::{QubitId}; + +fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { + let bit = circ.alloc_bit(); + circ.hmr(*t, bit); + circ.cz_if_bit(*a, *b, bit); +} + +fn compress_2sym_fast(circ: &mut B, w: &[&QubitId; 6]) { + circ.x(*w[3]); + circ.cx(*w[5], *w[1]); + circ.cx(*w[4], *w[0]); + circ.x(*w[2]); + circ.ccx(*w[1], *w[3], *w[5]); + circ.cx(*w[3], *w[5]); + circ.cx(*w[3], *w[0]); + circ.cx(*w[1], *w[5]); + circ.cx(*w[5], *w[3]); + circ.ccx(*w[5], *w[0], *w[4]); + + clear_and(circ, w[5], w[3], w[4]); +} + +fn compress_2sym_fast_reverse(circ: &mut B, w: &[&QubitId; 6]) { + circ.ccx(*w[3], *w[4], *w[5]); + circ.ccx(*w[5], *w[0], *w[4]); + circ.cx(*w[5], *w[3]); + circ.cx(*w[1], *w[5]); + circ.cx(*w[3], *w[0]); + circ.cx(*w[3], *w[5]); + circ.ccx(*w[1], *w[3], *w[5]); + circ.x(*w[2]); + circ.cx(*w[4], *w[0]); + circ.cx(*w[5], *w[1]); + circ.x(*w[3]); +} + +pub const TRIPLE_DATA_WIRES: [usize; 7] = [0, 1, 2, 3, 4, 7, 8]; + +pub const TRIPLE_FREED_WIRES: [usize; 2] = [5, 6]; + +const TAIL4_TOP32_CODE_BITS: usize = 5; +const TAIL4_TOP32_CODE_CONSTANT: u8 = 22; +const TAIL4_TOP32_ENCODER_ANF: [&[u16]; TAIL4_TOP32_CODE_BITS] = [ + &[2, 4, 8, 16, 32, 1024, 65, 528], + &[1, 2, 4, 16, 32, 520], + &[1, 2, 4, 8, 1024, 72], + &[4, 16, 32, 256, 520], + &[1, 4, 1024, 10, 66], +]; +const TAIL4_TOP32_DECODER_ANF: [&[u16]; 12] = [ + &[0, 3, 7, 18, 20, 21, 25, 27, 29, 31], + &[5, 6, 7, 9, 11, 13, 16, 18, 19, 20, 21, 31], + &[0, 11, 15, 16, 18, 20, 23, 24, 26, 27, 28, 29, 31], + &[3, 4, 5, 6, 11, 18, 19, 20, 21, 24, 26, 27, 28, 30], + &[0, 2, 3, 5, 6, 9, 13, 18, 19, 20, 23, 25, 31], + &[30, 31], + &[3, 7, 9, 13, 19, 21, 25, 30], + &[], + &[2, 3, 5, 6, 8, 9, 11, 13, 16, 19, 25, 27, 29], + &[0, 1, 4, 9, 13, 18, 19, 20, 27, 29], + &[0, 3, 7, 9, 13, 19, 21, 25, 30], + &[0], +]; + +fn tail4_top32_enabled() -> bool { + std::env::var("TLM_TAIL4_TOP32").ok().as_deref() == Some("1") +} + +fn toggle_mcx_with_dirty( + circ: &mut B, + controls: &[QubitId], + dirty: &[QubitId], + target: QubitId, +) { + debug_assert!(!controls.contains(&target)); + match controls.len() { + 0 => circ.x(target), + 1 => circ.cx(controls[0], target), + 2 => circ.ccx(controls[0], controls[1], target), + count => { + let bridge = dirty + .iter() + .copied() + .find(|q| *q != target && !controls.contains(q)) + .expect("tail4 codec needs a disjoint dirty bridge"); + let rest: Vec = dirty.iter().copied().filter(|q| *q != bridge).collect(); + toggle_mcx_with_dirty(circ, &controls[..count - 1], &rest, bridge); + circ.ccx(bridge, controls[count - 1], target); + toggle_mcx_with_dirty(circ, &controls[..count - 1], &rest, bridge); + circ.ccx(bridge, controls[count - 1], target); + } + } +} + +fn toggle_anf_with_dirty( + circ: &mut B, + controls: &[QubitId], + target: QubitId, + dirty: &[QubitId], + terms: &[u16], +) { + for &mask in terms { + let term_controls: Vec = controls + .iter() + .enumerate() + .filter_map(|(i, q)| ((mask >> i) & 1 != 0).then_some(*q)) + .collect(); + toggle_mcx_with_dirty(circ, &term_controls, dirty, target); + } +} + +fn tail4_reordered_raw(raw: &[QubitId]) -> [QubitId; 12] { + assert_eq!(raw.len(), 12, "tail4 raw window must contain four symbols"); + [ + raw[0], raw[1], raw[3], raw[4], raw[6], raw[7], raw[9], raw[10], + raw[2], raw[5], raw[8], raw[11], + ] +} + +fn tail4_toggle_code_from_raw(circ: &mut B, code: &[QubitId], raw: &[QubitId]) { + assert_eq!(code.len(), TAIL4_TOP32_CODE_BITS); + let wires = tail4_reordered_raw(raw); + for (i, terms) in TAIL4_TOP32_ENCODER_ANF.iter().enumerate() { + if (TAIL4_TOP32_CODE_CONSTANT >> i) & 1 != 0 { + circ.x(code[i]); + } + for &mask in *terms { + let controls: Vec = wires + .iter() + .enumerate() + .filter_map(|(j, q)| ((mask >> j) & 1 != 0).then_some(*q)) + .collect(); + toggle_mcx_with_dirty(circ, &controls, &wires, code[i]); + } + } +} + +fn tail4_toggle_raw_from_code(circ: &mut B, code: &[QubitId], raw: &[QubitId]) { + assert_eq!(code.len(), TAIL4_TOP32_CODE_BITS); + let wires = tail4_reordered_raw(raw); + for (i, terms) in TAIL4_TOP32_DECODER_ANF.iter().enumerate() { + toggle_anf_with_dirty(circ, code, wires[i], &wires, terms); + } +} + +fn compress_tail4_top32_payload(circ: &mut B, raw: &[QubitId]) -> Vec { + let code: Vec = (0..TAIL4_TOP32_CODE_BITS) + .map(|_| circ.alloc_qubit()) + .collect(); + tail4_toggle_code_from_raw(circ, &code, raw); + tail4_toggle_raw_from_code(circ, &code, raw); + for &q in raw { + circ.zero_and_free(q); + } + code +} + +fn decompress_tail4_top32_payload(circ: &mut B, code: &[QubitId]) -> Vec { + let raw: Vec = (0..12).map(|_| circ.alloc_qubit()).collect(); + tail4_toggle_raw_from_code(circ, code, &raw); + tail4_toggle_code_from_raw(circ, code, &raw); + for &q in code { + circ.zero_and_free(q); + } + raw +} + +fn compress_tail4_top32(circ: &mut B, raw: &[QubitId]) -> Vec { + assert_eq!(raw.len(), 15, "tail4 hybrid window must contain five symbols"); + let mut data = raw[..3].to_vec(); + data.extend(compress_tail4_top32_payload(circ, &raw[3..])); + data +} + +fn decompress_tail4_top32(circ: &mut B, data: &[QubitId]) -> Vec { + assert_eq!(data.len(), 3 + TAIL4_TOP32_CODE_BITS); + let mut raw = data[..3].to_vec(); + raw.extend(decompress_tail4_top32_payload(circ, &data[3..])); + raw +} + +#[rustfmt::skip] +const NORMALIZER_OPS: &[(u8, u8, u8, u8)] = &[ + (1,10,9,0), (1,9,6,0), (1,10,6,0), (1,6,10,0), (1,10,6,0), (0,8,0,0), (0,9,0,0), (2,7,9,10), + (1,10,9,0), (1,10,7,0), (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,8,10,0), (1,9,8,0), (1,8,9,0), + (1,9,8,0), (1,8,7,0), (1,7,8,0), (1,8,7,0), (1,8,6,0), (1,6,8,0), (1,8,6,0), (2,6,8,10), + (1,9,7,0), (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,9,7,0), (1,7,9,0), (1,9,7,0), (1,7,6,0), + (1,6,7,0), (1,7,6,0), (2,6,10,9), (1,10,9,0), (1,10,8,0), (1,10,7,0), (1,9,10,0), (1,9,8,0), + (1,9,7,0), (1,10,8,0), (1,8,10,0), (1,10,8,0), (1,7,6,0), (1,6,10,0), (0,10,0,0), (2,6,7,8), + (1,10,9,0), (1,10,8,0), (1,10,7,0), (1,10,6,0), (1,8,10,0), (1,8,9,0), (1,8,7,0), (1,8,6,0), + (1,7,8,0), (1,6,9,0), (1,6,8,0), (0,8,0,0), (2,6,7,8), (1,10,9,0), (1,10,8,0), (1,10,7,0), + (1,10,9,0), (1,9,10,0), (1,10,9,0), (1,8,10,0), (1,9,8,0), (1,8,9,0), (1,9,8,0), (1,7,6,0), + (1,6,10,0), (1,6,9,0), (0,9,0,0), (0,10,0,0), (2,6,10,8), (1,10,9,0), (1,9,8,0), (1,9,7,0), + (1,9,6,0), (1,8,7,0), (1,8,6,0), (1,10,8,0), (1,8,10,0), (1,10,8,0), (1,7,6,0), (1,6,9,0), + (1,7,6,0), (1,6,7,0), (1,7,6,0), (0,6,0,0), (0,8,0,0), (2,7,8,9), (1,6,8,0), (1,7,8,0), + (1,7,6,0), (1,6,8,0), (1,7,6,0), (1,6,7,0), (1,7,6,0), (0,6,0,0), (0,9,0,0), (0,10,0,0), +]; + +#[rustfmt::skip] +const MERGE25_OPS: &[(u8, u8, u8, u8)] = &[ + (1,12,9,0), (1,14,10,0), (2,10,12,14), (1,13,9,0), (2,9,12,13), (2,13,14,12), (1,12,6,0), (1,7,10,0), + (2,10,12,7), (1,6,9,0), (2,9,12,6), (1,12,8,0), (0,12,0,0), (1,14,12,0), (1,7,10,0), (0,10,0,0), + (1,6,9,0), (0,13,0,0), (2,8,13,15), (2,14,15,16), (2,8,13,15), (2,10,9,15), (2,16,15,12), (2,10,9,15), + (2,8,13,15), (2,14,15,16), (2,8,13,15), (0,13,0,0), (1,6,9,0), (0,10,0,0), (1,7,10,0), +]; + +const MERGE25_CLEAR_FWD: [usize; 5] = [20, 22, 23, 25, 26]; +const MERGE25_CLEAR_REV: [usize; 4] = [18, 19, 21, 24]; + +#[inline] +fn apply_op_off(circ: &mut B, w: &[&QubitId], op: (u8, u8, u8, u8), off: u8) { + let m = |i: u8| w[(i - off) as usize]; + match op.0 { + 0 => circ.x(*m(op.1)), + 1 => circ.cx(*m(op.1), *m(op.2)), + 2 => circ.ccx(*m(op.1), *m(op.2), *m(op.3)), + _ => unreachable!("bad codec op kind"), + } +} + +fn apply_merge25(circ: &mut B, w: &[&QubitId], off: u8, reverse: bool) { + let clear: &[usize] = if reverse { &MERGE25_CLEAR_REV } else { &MERGE25_CLEAR_FWD }; + let n = MERGE25_OPS.len(); + for step in 0..n { + let i = if reverse { n - 1 - step } else { step }; + let op = MERGE25_OPS[i]; + if clear.contains(&i) { + clear_and( + circ, + w[(op.3 - off) as usize], + w[(op.1 - off) as usize], + w[(op.2 - off) as usize], + ); + } else { + apply_op_off(circ, w, op, off); + } + } +} + +fn compress_3sym(circ: &mut B, w: &[&QubitId; 11]) { + compress_2sym_fast(circ, &[w[0], w[1], w[2], w[3], w[4], w[5]]); + for &op in NORMALIZER_OPS { + apply_op_off(circ, &w[..], op, 6); + } + apply_merge25(circ, &w[..], 6, false); +} + +fn compress_3sym_reverse(circ: &mut B, w: &[&QubitId; 11]) { + apply_merge25(circ, &w[..], 6, true); + for &op in NORMALIZER_OPS.iter().rev() { + apply_op_off(circ, &w[..], op, 6); + } + compress_2sym_fast_reverse(circ, &[w[0], w[1], w[2], w[3], w[4], w[5]]); +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum DialogCodec { + + Pair, + + Triple, + + Raw, + + Step0, + + Tail4Top32, +} + +impl DialogCodec { + + pub fn syms(self) -> usize { + match self { + Self::Pair => 2, + Self::Triple => 3, + Self::Tail4Top32 => 5, + Self::Raw | Self::Step0 => 1, + } + } + + pub fn code_bits(self) -> usize { + match self { + Self::Pair => 5, + Self::Triple => 7, + Self::Tail4Top32 => 3 + TAIL4_TOP32_CODE_BITS, + Self::Raw => 3, + Self::Step0 => 2, + } + } + + fn clean_anc(self) -> usize { + match self { + Self::Pair | Self::Raw | Self::Step0 | Self::Tail4Top32 => 0, + Self::Triple => 2, + } + } + + fn data_wires(self) -> &'static [usize] { + match self { + Self::Pair => &[0, 1, 2, 3, 4], + Self::Triple => &TRIPLE_DATA_WIRES, + Self::Raw => &[0, 1, 2], + Self::Step0 => &[0, 2], + Self::Tail4Top32 => &[], + } + } + + fn freed_wires(self) -> &'static [usize] { + match self { + Self::Pair => &[5], + Self::Triple => &TRIPLE_FREED_WIRES, + Self::Raw => &[], + Self::Step0 => &[1], + Self::Tail4Top32 => &[], + } + } + + fn compress(self, circ: &mut B, win: &[&QubitId]) { + match self { + Self::Pair => compress_2sym_fast(circ, win.try_into().unwrap()), + Self::Triple => compress_3sym(circ, win.try_into().unwrap()), + Self::Raw => {} + + Self::Step0 => circ.cx(*win[0], *win[1]), + Self::Tail4Top32 => unreachable!("tail4 uses separate code wires"), + } + } + + fn decompress(self, circ: &mut B, win: &[&QubitId]) { + match self { + Self::Pair => compress_2sym_fast_reverse(circ, win.try_into().unwrap()), + Self::Triple => compress_3sym_reverse(circ, win.try_into().unwrap()), + Self::Raw => {} + + Self::Step0 => circ.cx(*win[0], *win[1]), + Self::Tail4Top32 => unreachable!("tail4 uses separate code wires"), + } + } + + #[must_use] + pub fn decompress_window(self, circ: &mut B, data: &[QubitId]) -> Vec { + assert_eq!(data.len(), self.code_bits(), "data len != code_bits"); + if self == Self::Tail4Top32 { + return decompress_tail4_top32(circ, data); + } + + let mut slots: Vec> = (0..self.syms() * 3).map(|_| None).collect(); + let mut it = data.iter(); + for &d in self.data_wires() { + slots[d] = Some(*it.next().expect("data bit")); + } + for &f in self.freed_wires() { + slots[f] = Some(circ.alloc_qubit()); + } + let raw: Vec = slots.into_iter().map(|s| s.expect("slot")).collect(); + let clean: Vec = (0..self.clean_anc()).map(|_| circ.alloc_qubit()).collect(); + let win: Vec<&QubitId> = raw.iter().chain(clean.iter()).collect(); + self.decompress(circ, &win); + for q in clean { + circ.zero_and_free(q); + } + raw + } + + #[must_use] + pub fn compress_window(self, circ: &mut B, raw: &[QubitId]) -> Vec { + assert_eq!(raw.len(), self.syms() * 3, "raw len != syms*3"); + if self == Self::Tail4Top32 { + return compress_tail4_top32(circ, raw); + } + let clean: Vec = (0..self.clean_anc()).map(|_| circ.alloc_qubit()).collect(); + let win: Vec<&QubitId> = raw.iter().chain(clean.iter()).collect(); + self.compress(circ, &win); + for q in clean { + circ.zero_and_free(q); + } + + let mut data: Vec = Vec::with_capacity(self.code_bits()); + let dset = self.data_wires(); + for (k, &q) in raw.iter().enumerate() { + if dset.contains(&k) { + data.push(q); + } else { + circ.zero_and_free(q); + } + } + data + } +} + +#[must_use] +pub fn compress_step0_with_t1(circ: &mut B, t1: QubitId, raw: &[QubitId]) -> Vec { + assert_eq!(raw.len(), 3, "step0 raw symbol is [sub, swap, s2]"); + let sub = raw[0]; + let swap = raw[1]; + let s2 = raw[2]; + circ.cx(sub, swap); + circ.cx(sub, t1); + circ.x(sub); + circ.ccx(t1, s2, sub); + circ.zero_and_free(sub); + circ.zero_and_free(swap); + vec![t1, s2] +} + +#[must_use] +pub fn decompress_step0_with_t1(circ: &mut B, data: &[QubitId]) -> (QubitId, Vec) { + assert_eq!(data.len(), 2, "step0+t1 code is two bits"); + let t1 = data[0]; + let s2 = data[1]; + let sub = circ.alloc_qubit(); + let swap = circ.alloc_qubit(); + circ.ccx(t1, s2, sub); + circ.x(sub); + circ.cx(sub, t1); + circ.cx(sub, swap); + (t1, vec![sub, swap, s2]) +} + +#[must_use] +pub fn jump_dialog_regions(n3: usize, iters: usize) -> Vec<(DialogCodec, usize)> { + + let tail4 = usize::from(tail4_top32_enabled() && iters >= 6) * 5; + let codec_syms = iters - 1 - tail4; + let mut n3 = n3; + while 3 * n3 > codec_syms { + n3 -= 1; + } + let rem = codec_syms - 3 * n3; + let mut r = vec![(DialogCodec::Step0, 1)]; + if n3 > 0 { + r.push((DialogCodec::Triple, n3)); + } + + let tight = n3 > 0; + match rem { + 3 if tight => r.push((DialogCodec::Triple, 1)), + _ => { + if rem / 2 > 0 { + r.push((DialogCodec::Pair, rem / 2)); + } + if rem % 2 == 1 { + r.push((DialogCodec::Raw, 1)); + } + } + } + if tail4 != 0 { + r.push((DialogCodec::Tail4Top32, 1)); + } + r +} + +#[must_use] +pub fn dialog_tape_qubits(n3: usize, iters: usize) -> usize { + jump_dialog_regions(n3, iters) + .into_iter() + .map(|(codec, count)| codec.code_bits() * count) + .sum::() +} diff --git a/src/point_add/trailmix_ludicrous/comparator.rs b/src/point_add/trailmix_ludicrous/comparator.rs index 1e61b572..b6c0e07a 100644 --- a/src/point_add/trailmix_ludicrous/comparator.rs +++ b/src/point_add/trailmix_ludicrous/comparator.rs @@ -1,1087 +1,1055 @@ - -use super::{B, BExt}; -use crate::circuit::QubitId; -use std::cell::Cell; - -thread_local! { - static COMPARE_DIRECT_CALL_INDEX: Cell = const { Cell::new(0) }; - static COMPARE_CIN_CALL_INDEX: Cell = const { Cell::new(0) }; -} - -pub(super) fn reset_compare_call_index() { - COMPARE_DIRECT_CALL_INDEX.with(|index| index.set(0)); - COMPARE_CIN_CALL_INDEX.with(|index| index.set(0)); -} - -fn next_compare_direct_call_index() -> usize { - COMPARE_DIRECT_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_compare_cin_call_index() -> usize { - COMPARE_CIN_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -const COMPARE_CIN_STRUCTURAL_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (3, 0, 64), - (4, 20, 21), - (4, 23, 64), - (105, 16, 18), - (1257, 0, 2), - (1279, 0, 2), - (1292, 0, 2), - (1305, 0, 2), - (1318, 0, 2), - (1331, 0, 2), - (1344, 0, 2), - (1356, 0, 2), - (1369, 0, 2), - (1382, 0, 2), - (1395, 0, 2), - (1408, 0, 2), - (1422, 0, 2), - (1435, 0, 2), - (1449, 0, 2), - (1463, 0, 2), - (1477, 0, 2), - (1491, 0, 2), - (1506, 0, 2), - (1520, 0, 2), - (1535, 0, 2), - (1551, 0, 2), - (1566, 0, 2), - (1582, 0, 2), - (1599, 0, 2), - (1615, 0, 2), - (1632, 0, 2), - (1652, 0, 2), - (1669, 0, 2), - (1689, 0, 2), - (1706, 0, 2), - (1726, 0, 2), - (1743, 0, 2), - (1760, 0, 2), - (1777, 0, 2), - (1794, 0, 2), - (1812, 0, 2), - (1829, 0, 2), - (1847, 0, 2), - (1866, 0, 2), - (1884, 0, 2), - (1903, 0, 2), - (1923, 0, 2), - (1942, 0, 2), - (1958, 0, 2), - (1974, 0, 2), - (1990, 0, 2), - (2006, 0, 2), - (2023, 0, 2), - (2041, 0, 2), - (2061, 0, 2), - (2086, 0, 2), - (2112, 0, 2), - (2137, 0, 2), - (2161, 0, 2), - (2184, 0, 2), - (2366, 0, 2), - (2389, 0, 2), - (2413, 0, 2), - (2438, 0, 2), - (2464, 0, 2), - (2489, 0, 2), - (2509, 0, 2), - (2527, 0, 2), - (2544, 0, 2), - (2560, 0, 2), - (2576, 0, 2), - (2592, 0, 2), - (2608, 0, 2), - (2627, 0, 2), - (2647, 0, 2), - (2666, 0, 2), - (2684, 0, 2), - (2703, 0, 2), - (2721, 0, 2), - (2738, 0, 2), - (2756, 0, 2), - (2773, 0, 2), - (2790, 0, 2), - (2807, 0, 2), - (2824, 0, 2), - (2844, 0, 2), - (2861, 0, 2), - (2881, 0, 2), - (2898, 0, 2), - (2918, 0, 2), - (2935, 0, 2), - (2951, 0, 2), - (2968, 0, 2), - (2984, 0, 2), - (2999, 0, 2), - (3015, 0, 2), - (3030, 0, 2), - (3044, 0, 2), - (3059, 0, 2), - (3073, 0, 2), - (3087, 0, 2), - (3101, 0, 2), - (3115, 0, 2), - (3128, 0, 2), - (3142, 0, 2), - (3155, 0, 2), - (3168, 0, 2), - (3181, 0, 2), - (3194, 0, 2), - (3206, 0, 2), - (3219, 0, 2), - (3232, 0, 2), - (3245, 0, 2), - (3258, 0, 2), - (3271, 0, 2), - (3293, 0, 2), -]; - -const COMPARE_CIN_REMAINDER_KEYS: &[u32] = &[ - 8, 274, 530, 12817, 12818, 14098, 15377, 15378, 16657, 16658, 17937, 17938, - 19217, 19218, 20497, 20498, 21777, 21778, 23057, 23058, 24337, 24338, 25617, 25618, - 28177, 28178, 29457, 29458, 30737, 30738, 32017, 32018, 33297, 33298, 34577, 34578, - 35857, 35858, 37137, 37138, 38417, 38418, 39697, 39698, 40978, 42257, 42258, 43537, - 43538, 44817, 44818, 46097, 46098, 47378, 48658, 49938, 51218, 52498, 53777, 53778, - 55058, 56337, 56338, 57618, 58898, 60178, 61458, 62738, 64018, 66578, 67858, 69138, - 70674, 71954, 73490, 75026, 76562, 78098, 79634, 81170, 82706, 84242, 87314, 90386, - 94994, 111890, 116498, 121106, 127250, 130322, 131858, 134930, 139538, 141074, - 144146, 145682, 147218, 150290, 151826, 154897, 154898, 156433, 156434, 158226, - 159762, 161554, 165138, 175634, 177426, 179218, 182802, 184594, 186386, 188178, - 189970, 191761, 191762, 193554, 200716, 202509, 209682, 211471, 213264, 216846, - 233734, 235783, 246020, 252163, 254212, 256261, 258306, 260355, 270592, 272641, - 281345, 283666, 288000, 300818, 306962, 311314, 313618, 323858, 326162, 329490, - 332818, 339474, 854546, 867090, 873490, 925704, 929798, 937738, 943115, 946702, - 950288, 952079, 964623, 966418, 970002, 971794, 977170, 1000210, 1002002, 1003794, - 1007122, 1022482, 1031698, 1033234, 1085458, 1091602, 1103378, 1112338, 1121298, - 1127698, 1132818, 1136658, 1148177, 1148178, 1149457, -]; - -fn compare_cin_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("CMPCIN") { - return false; - } - - if std::env::var_os("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { - return false; - } - if std::env::var_os("TLM_COMPARE_SKIP_EXACT_CIN_REMAINDER").is_some() { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if COMPARE_CIN_REMAINDER_KEYS.binary_search(&key).is_ok() { - return true; - } - } - COMPARE_CIN_STRUCTURAL_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -const COMPARE_STRUCTURAL_DEAD_TOP_RANGES: &[(usize, usize, usize)] = &[ - (775, 0, 18), - (776, 0, 18), - (777, 0, 18), - (778, 0, 18), - (779, 0, 18), - (782, 0, 18), - (783, 0, 18), - (784, 0, 18), - (785, 0, 18), - (786, 0, 18), - (788, 0, 18), - (789, 0, 18), - (790, 0, 18), - (791, 0, 18), - (792, 0, 18), - (516, 1, 10), - (1055, 1, 10), - (517, 3, 11), - (518, 5, 13), - (1057, 3, 11), - (1059, 5, 13), - (520, 8, 15), - (519, 7, 13), - (521, 9, 15), - (1061, 7, 13), - (1063, 9, 15), - (1065, 9, 15), - (511, 8, 13), - (522, 10, 15), - (523, 11, 16), - (1067, 10, 15), - (1069, 11, 16), - (507, 11, 15), - (515, 6, 10), - (525, 13, 17), - (526, 14, 18), - (527, 15, 19), - (808, 29, 33), - (1052, 9, 13), - (1071, 12, 16), - (1073, 13, 17), - (1075, 14, 18), - (21, 30, 33), - (23, 30, 33), - (25, 30, 33), - (27, 30, 33), - (29, 30, 33), - (31, 30, 33), - (33, 31, 34), - (505, 12, 15), - (509, 10, 13), - (524, 13, 16), - (537, 25, 28), - (539, 27, 30), - (541, 29, 32), - (543, 31, 34), - (807, 30, 33), - (809, 30, 33), - (810, 30, 33), - (811, 30, 33), - (812, 30, 33), - (813, 31, 34), - (819, 30, 33), - (1049, 12, 15), - (1050, 12, 15), - (1051, 10, 13), - (1053, 8, 11), - (1054, 7, 10), - (1077, 16, 19), - (1081, 17, 20), - (1095, 24, 27), - (1099, 26, 29), - (1101, 27, 30), - (1115, 34, 37), - (1121, 37, 40), - (19, 29, 31), - (35, 32, 34), - (37, 31, 33), - (39, 32, 34), - (41, 32, 34), - (43, 32, 34), - (45, 31, 33), - (47, 33, 35), - (49, 33, 35), - (51, 32, 34), - (53, 32, 34), - (55, 33, 35), - (57, 32, 34), - (61, 34, 36), - (501, 14, 16), - (503, 13, 15), - (513, 9, 11), - (528, 17, 19), - (529, 18, 20), - (533, 21, 23), - (538, 27, 29), - (540, 29, 31), - (542, 31, 33), - (544, 33, 35), - (545, 34, 36), - (546, 35, 37), - (547, 36, 38), - (548, 37, 39), - (550, 39, 41), - (551, 40, 42), - (553, 42, 44), - (555, 43, 45), - (805, 29, 31), - (806, 29, 31), - (814, 32, 34), - (815, 31, 33), - (817, 32, 34), - (818, 32, 34), - (820, 33, 35), - (821, 33, 35), - (822, 32, 34), - (823, 32, 34), - (824, 33, 35), - (825, 32, 34), - (826, 32, 34), - (827, 34, 36), - (829, 33, 35), - (832, 33, 35), - (833, 34, 36), - (1044, 16, 18), - (1047, 14, 16), - (1048, 13, 15), - (1079, 17, 19), - (1097, 26, 28), - (1103, 29, 31), - (1105, 30, 32), - (1109, 32, 34), - (1111, 33, 35), - (1113, 34, 36), - (1117, 36, 38), - (1119, 37, 39), - (1123, 39, 41), - (1125, 40, 42), - (1127, 41, 43), - (1129, 42, 44), - (1131, 43, 45), - (1133, 43, 45), - (1135, 44, 46), - (1137, 45, 47), - (15, 28, 29), - (17, 30, 31), - (59, 33, 34), - (63, 33, 34), - (65, 34, 35), - (67, 34, 35), - (69, 34, 35), - (71, 34, 35), - (73, 35, 36), - (75, 34, 35), - (77, 35, 36), - (79, 35, 36), - (81, 35, 36), - (83, 34, 35), - (85, 35, 36), - (87, 35, 36), - (89, 35, 36), - (91, 35, 36), - (93, 36, 37), - (95, 35, 36), - (97, 36, 37), - (99, 35, 36), - (101, 36, 37), - (105, 36, 37), - (107, 36, 37), - (109, 36, 37), - (111, 36, 37), - (113, 37, 38), - (121, 37, 38), - (123, 37, 38), - (129, 37, 38), - (133, 37, 38), - (137, 38, 39), - (143, 38, 39), - (165, 40, 41), - (177, 40, 41), - (189, 42, 43), - (191, 41, 42), - (203, 42, 43), - (207, 43, 44), - (211, 43, 44), - (213, 42, 43), - (215, 43, 44), - (217, 43, 44), - (221, 44, 45), - (223, 43, 44), - (225, 44, 45), - (227, 44, 45), - (229, 44, 45), - (233, 44, 45), - (245, 45, 46), - (247, 44, 45), - (249, 44, 45), - (255, 44, 45), - (257, 44, 45), - (259, 44, 45), - (261, 45, 46), - (263, 45, 46), - (265, 45, 46), - (285, 45, 46), - (287, 46, 47), - (291, 46, 47), - (299, 45, 46), - (321, 46, 47), - (327, 47, 48), - (333, 47, 48), - (359, 49, 50), - (361, 49, 50), - (395, 50, 51), - (411, 52, 53), - (415, 52, 53), - (421, 52, 53), - (431, 47, 48), - (433, 46, 47), - (439, 44, 45), - (441, 43, 44), - (447, 40, 41), - (449, 39, 40), - (451, 38, 39), - (459, 34, 35), - (461, 33, 34), - (465, 31, 32), - (467, 30, 31), - (471, 28, 29), - (475, 26, 27), - (493, 18, 19), - (495, 17, 18), - (497, 16, 17), - (499, 15, 16), - (530, 19, 20), - (532, 21, 22), - (534, 23, 24), - (536, 26, 27), - (549, 39, 40), - (552, 42, 43), - (554, 44, 45), - (556, 45, 46), - (557, 46, 47), - (558, 47, 48), - (559, 48, 49), - (563, 52, 53), - (568, 52, 53), - (570, 52, 53), - (575, 52, 53), - (592, 49, 50), - (595, 48, 49), - (613, 46, 47), - (621, 45, 46), - (628, 46, 47), - (630, 46, 47), - (631, 44, 44), - (631, 46, 46), - (635, 44, 45), - (639, 44, 45), - (640, 45, 46), - (642, 44, 44), - (642, 46, 46), - (643, 45, 46), - (644, 44, 45), - (645, 44, 45), - (647, 44, 45), - (650, 44, 45), - (651, 45, 46), - (661, 44, 45), - (678, 41, 42), - (679, 42, 43), - (706, 37, 38), - (719, 36, 37), - (721, 36, 37), - (722, 36, 37), - (723, 36, 37), - (742, 33, 34), - (744, 33, 34), - (804, 28, 29), - (816, 33, 34), - (828, 33, 34), - (830, 34, 35), - (831, 34, 35), - (834, 34, 35), - (835, 35, 36), - (836, 35, 36), - (837, 35, 36), - (838, 34, 35), - (839, 35, 36), - (840, 35, 36), - (841, 35, 36), - (842, 35, 36), - (844, 35, 36), - (845, 36, 37), - (846, 35, 36), - (847, 36, 37), - (849, 36, 37), - (850, 36, 37), - (851, 36, 37), - (856, 37, 38), - (858, 37, 38), - (860, 37, 38), - (864, 37, 38), - (865, 38, 39), - (891, 42, 43), - (892, 41, 42), - (898, 42, 43), - (900, 43, 44), - (901, 42, 43), - (904, 43, 44), - (905, 43, 44), - (907, 44, 45), - (908, 43, 44), - (909, 44, 45), - (911, 44, 45), - (912, 44, 45), - (913, 44, 45), - (919, 45, 46), - (920, 44, 45), - (921, 44, 45), - (923, 44, 45), - (924, 44, 45), - (925, 44, 45), - (926, 44, 45), - (927, 45, 46), - (928, 45, 46), - (930, 45, 46), - (931, 44, 45), - (938, 46, 47), - (940, 46, 47), - (941, 45, 46), - (942, 46, 47), - (973, 49, 50), - (979, 49, 50), - (980, 49, 50), - (981, 49, 50), - (983, 50, 51), - (985, 50, 51), - (988, 50, 51), - (992, 50, 51), - (996, 51, 52), - (997, 51, 52), - (1003, 52, 53), - (1004, 52, 53), - (1005, 52, 53), - (1008, 51, 52), - (1009, 50, 51), - (1012, 47, 48), - (1013, 46, 47), - (1016, 44, 45), - (1020, 40, 41), - (1022, 38, 39), - (1023, 37, 38), - (1026, 34, 35), - (1028, 32, 33), - (1030, 30, 31), - (1031, 29, 30), - (1032, 28, 29), - (1033, 27, 28), - (1034, 26, 27), - (1043, 18, 19), - (1045, 16, 17), - (1046, 15, 16), - (1083, 19, 20), - (1085, 20, 21), - (1087, 21, 22), - (1089, 22, 23), - (1091, 23, 24), - (1093, 24, 25), - (1107, 32, 33), - (1139, 46, 46), - (1139, 48, 48), - (1145, 50, 51), - (1155, 52, 53), - (1163, 52, 53), - (1169, 51, 52), - (1201, 49, 50), - (1245, 47, 48), - (1267, 46, 47), - (1281, 45, 46), - (1283, 46, 47), - (1301, 44, 45), - (1307, 45, 46), - (1309, 45, 46), - (1313, 44, 45), - (1317, 44, 45), - (1339, 44, 45), - (1341, 44, 45), - (1343, 44, 45), - (1379, 41, 42), - (1381, 42, 43), - (1461, 36, 37), - (1471, 35, 36), - (1493, 35, 36), - (1497, 35, 36), - (1525, 32, 33), - (1539, 32, 33), -]; - -const COMPARE_DIRECT_REMAINDER_KEYS: &[u32] = &[ - 530, 3356, 26405, 29478, 29990, 30502, 32038, 32550, 33574, 34598, 35623, 36135, - 37159, 37671, 38184, 38696, 39209, 39720, 40231, 40744, 41256, 41769, 42794, 43304, - 43816, 44329, 44841, 45865, 46377, 46889, 47402, 47913, 49449, 49961, 50475, 50986, - 51498, 52523, 53547, 56107, 59181, 60204, 61229, 61740, 62253, 64301, 64813, 68398, - 68909, 69422, 69934, 70957, 71470, 71981, 72495, 74030, 75054, 76079, 77103, 77615, - 78126, 78639, 79151, 79663, 80175, 80687, 81200, 81712, 82737, 84272, 84784, 85809, - 86320, 86832, 87345, 87857, 88369, 88882, 89393, 89905, 90418, 90929, 92978, 93490, - 94002, 94514, 95026, 95539, 96052, 96563, 97075, 97587, 98099, 98611, 99123, 99636, - 100147, 100659, 101685, 102196, 102708, 103220, 103731, 104245, 104756, 105781, 106805, 107317, - 108340, 108851, 109362, 109873, 111406, 111917, 113451, 113962, 116006, 116517, 117028, 118561, - 120094, 121116, 123159, 125204, 125715, 135957, 136985, 143410, 143667, 143924, 144437, 144693, - 144948, 145205, 145716, 146227, 146484, 146996, 147507, 147762, 148276, 148531, 148787, 149043, - 149299, 149555, 150068, 150578, 151090, 151346, 151858, 152624, 152882, 153137, 153393, 153650, - 153905, 154161, 154417, 154672, 154928, 155184, 155440, 155696, 155952, 156208, 156464, 156721, - 157232, 157488, 157743, 157999, 158255, 158511, 158767, 159279, 159790, 160047, 160302, 160558, - 161070, 161839, 162093, 163374, 164142, 165421, 166189, 166957, 167212, 167980, 168237, 168493, - 168749, 169005, 169515, 169773, 170284, 170540, 170795, 171052, 171307, 171564, 172075, 172586, - 172843, 173353, 174633, 175145, 175401, 175913, 176424, 176682, 177193, 177448, 177704, 177959, - 178215, 178473, 178728, 178984, 179239, 179495, 179751, 180007, 180263, 180519, 181030, 181542, - 181798, 182310, 182822, 183078, 183590, 183845, 185380, 185892, 186149, 186404, 187172, 187940, - 188196, 188451, 188708, 188963, 189219, 189475, 189731, 190244, 191266, 191522, 191779, 192287, - 192546, 192802, 193313, 193570, 194081, 194593, 194849, 195105, 205596, 215845, 217125, 218149, - 218406, 218662, 218918, 219430, 219942, 220454, 220710, 220966, 221735, 221991, 222247, 222503, - 222759, 223016, 223272, 223529, 223784, 224296, 224552, 224809, 225065, 225322, 225576, 225832, - 226089, 226345, 226601, 226857, 227113, 227369, 227626, 227881, 228649, 228905, 229163, 229418, - 229674, 230187, 230956, 231211, 231979, 233005, 234028, 234284, 234541, 234796, 235053, 236077, - 237870, 238638, 238894, 239149, 239405, 239662, 239917, 240430, 241454, 241710, 241967, 242222, - 242479, 242735, 243247, 243503, 243759, 244015, 244271, 244528, 244784, 245039, 245297, 245552, - 245808, 246064, 246320, 246576, 246833, 247088, 247344, 247601, 247857, 248112, 248370, 248625, - 248881, 249393, 249649, 249906, 250162, 250418, 251442, 251956, 252467, 252723, 253235, 253491, - 253748, 254259, 254515, 254773, 255540, 255795, 256053, 256308, 256565, 257589, 257845, 258610, - 258865, 259630, 259885, 260396, 260651, 260906, 261416, 262181, 262436, 262946, 263456, 265240, - 266005, 266516, 266771, 292145, 292658, 293684, 294197, 294709, 295221, 296245, 296757, 297268, - 299828, 300341, 300851, 301875, 302388, 302899, 303411, 304947, 305459, 305972, 306483, 306994, - 308018, 308530, 309042, 309554, 310577, 313138, 313649, 314161, 315184, 315696, 316209, 316720, - 317232, 317744, 318256, 319281, 319791, 320304, 320816, 321327, 321838, 322351, 323375, 325422, - 325935, 326446, 326958, 327471, 329006, 329519, 331565, 332590, 333614, 334126, 335661, 336685, - 338221, 338733, 339246, 341804, 342317, 344365, 345389, 346412, 346923, 347948, 348459, 348972, - 349995, 350506, 358184, 359210, 359721, 360233, 360744, 361256, 362280, 363304, 363816, 365351, - 365863, 366887, 367910, 368422, 369446, 369958, 370470, 370982, 372006, 372518, 374565, 375589, - 376101, 377125, 377635, 378149, 378660, 379171, 379684, 380196, 380707, 381220, 381732, 382755, - 383779, 384291, 384803, 385315, 385826, 386340, 386850, 387362, 387875, 388386, 388898, 389410, - 389923, 390946, 391970, 392481, 393506, 394529, 395553, 396065, -]; - -fn compare_call_has_structurally_dead_top(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("CMPTOP") { - return false; - } - - if std::env::var_os("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { - return false; - } - if std::env::var_os("TLM_COMPARE_SKIP_EXACT_REMAINDER").is_some() { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if COMPARE_DIRECT_REMAINDER_KEYS.binary_search(&key).is_ok() { - return true; - } - } - COMPARE_STRUCTURAL_DEAD_TOP_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn compare_geq_chunked_middle_direct( - circ: &mut B, - a: &[QubitId], - b: &[QubitId], - body: F, - k: usize, -) { - let call_index = next_compare_direct_call_index(); - let ops_start = circ.current_ops_len(); - let n = a.len(); - assert_eq!( - b.len(), - n, - "compare_geq_chunked_middle_direct: a,b equal width" - ); - assert!( - n > 0, - "compare_geq_chunked_middle_direct: nonempty operands" - ); - let k = super::target_qubit_headroom(circ) - .map_or(k, |headroom| k.min(headroom.saturating_sub(1))) - .min(n); - let split = n - k; - let mut cy: Vec> = (0..=n).map(|_| None).collect(); - let c = circ.alloc_qubit(); - circ.x(c); - - for i in 0..split { - circ.x(b[i]); - circ.cx(c, b[i]); - circ.cx(c, a[i]); - circ.ccx(a[i], b[i], c); - } - cy[split] = Some(c); - - for i in split..n { - let next = circ.alloc_qubit(); - { - let ci = cy[i].as_ref().unwrap(); - circ.x(b[i]); - circ.cx(*ci, b[i]); - circ.cx(*ci, a[i]); - if !compare_call_has_structurally_dead_top(call_index, i) { - let old_context = crate::point_add::set_op_trace_context( - 0x0400_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(a[i], b[i], next); - crate::point_add::restore_op_trace_context(old_context); - } - circ.cx(*ci, next); - } - cy[i + 1] = Some(next); - } - body(circ, cy[n].as_ref().unwrap()); - - for i in (split..n).rev() { - let next = cy[i + 1].take().unwrap(); - circ.cx(*cy[i].as_ref().unwrap(), next); - let bit = circ.alloc_bit(); - circ.hmr(next, bit); - circ.zero_and_free(next); - circ.cz_if_bit(a[i], b[i], bit); - circ.cx(*cy[i].as_ref().unwrap(), a[i]); - circ.cx(*cy[i].as_ref().unwrap(), b[i]); - circ.x(b[i]); - } - - let c = cy[split].take().unwrap(); - for i in (0..split).rev() { - circ.ccx(a[i], b[i], c); - circ.cx(c, a[i]); - circ.cx(c, b[i]); - circ.x(b[i]); - } - circ.x(c); - circ.zero_and_free(c); - if std::env::var_os("TRACE_TLM_COMPARE_DIRECT").is_some() { - eprintln!( - "TLM_COMPARE_DIRECT call={} phase={} n={} k={} split={} ops_start={} ops_end={}", - call_index, - circ.phase, - n, - k, - split, - ops_start, - circ.current_ops_len(), - ); - } -} - -pub fn compare_geq_chunked_middle( - circ: &mut B, - a: &[QubitId], - b: &[QubitId], - flag: &QubitId, - body: F, - k: usize, -) { - assert_eq!( - b.len(), - a.len(), - "compare_geq_chunked_middle: a,b equal width" - ); - if a.is_empty() { - circ.x(*flag); - body(circ, flag); - circ.x(*flag); - return; - } - compare_geq_chunked_middle_direct( - circ, - a, - b, - |c, carry| { - c.cx(*carry, *flag); - body(c, flag); - c.cx(*carry, *flag); - }, - k, - ); -} - -pub fn controlled_swap_decision_lt_truncated( - circ: &mut B, - ctrl: &QubitId, - u: &[QubitId], - v: &[QubitId], - k: usize, - target: &QubitId, -) { - assert!( - k > 0 && k <= u.len() && k <= v.len(), - "k must fit in both operands" - ); - let u_top: Vec = u[u.len() - k..].to_vec(); - let v_top: Vec = v[v.len() - k..].to_vec(); - - let ck = super::next_cmp_k().saturating_add(1); - compare_geq_chunked_middle_direct( - circ, - &u_top, - &v_top, - |c, carry| { - c.x(*carry); - c.ccx(*ctrl, *carry, *target); - c.x(*carry); - }, - ck, - ); -} - -pub fn compare_geq_cin_middle( - circ: &mut B, - a: &[QubitId], - b: &[QubitId], - cin: &QubitId, - body: F, -) { - compare_geq_cin_middle_keyed(circ, a, b, cin, body, Some(0)); -} - -/// Same as [`compare_geq_cin_middle`], but with explicit control over the census-derived -/// structural-dead-carry drops. -/// -/// `drops = Some(key_lo)` keys the lookup by `key_lo + i` instead of `i`, so that a caller passing -/// a *sub-slice* of a wider operand still names the same physical gate (`key_lo` is the index of -/// `a[0]` within the operand the tables were fitted against). `Some(0)` is bit-for-bit the original -/// behaviour. -/// -/// `drops = None` disables the drops entirely. A caller that changes the *value* of the carry chain -/// — e.g. by truncating the window, which forces carry-in 0 where the fitted circuit had a real -/// carry-in — MUST use `None`: the census established those gates never fire in the untruncated -/// chain, and that evidence does not transfer. -pub fn compare_geq_cin_middle_keyed( - circ: &mut B, - a: &[QubitId], - b: &[QubitId], - cin: &QubitId, - body: F, - drops: Option, -) { - let call_index = next_compare_cin_call_index(); - let n = a.len(); - assert_eq!(b.len(), n, "compare_geq_cin_middle: a,b equal width"); - assert!(n >= 1, "needs >= 1 bit"); - let mut cy: Vec> = Vec::with_capacity(n); - let c0 = circ.alloc_qubit(); - circ.x(c0); - circ.cx(*cin, c0); - cy.push(Some(c0)); - for i in 0..n - 1 { - let next = circ.alloc_qubit(); - let ci = cy[i].as_ref().unwrap(); - circ.x(b[i]); - circ.cx(*ci, b[i]); - circ.cx(*ci, a[i]); - let key_bit = drops.map_or(i, |key_lo| key_lo + i); - let old_context = crate::point_add::set_op_trace_context( - 0x1300_0000 | (((call_index as u32) & 0xffff) << 8) | (key_bit as u32 & 0xff), - ); - if drops.is_none() || !compare_cin_has_structurally_dead_carry(call_index, key_bit) { - circ.ccx(a[i], b[i], next); - } - crate::point_add::restore_op_trace_context(old_context); - circ.cx(*ci, next); - cy.push(Some(next)); - } - - { - let i = n - 1; - let ci = cy[i].as_ref().unwrap(); - circ.x(b[i]); - circ.cx(*ci, b[i]); - circ.cx(*ci, a[i]); - body(circ, &a[i], &b[i], ci); - circ.cx(*ci, a[i]); - circ.cx(*ci, b[i]); - circ.x(b[i]); - } - - for i in (0..n - 1).rev() { - let next = cy[i + 1].take().unwrap(); - let ci_raw = cy[i].as_ref().unwrap(); - circ.cx(*ci_raw, next); - let bit = circ.alloc_bit(); - circ.hmr(next, bit); - circ.zero_and_free(next); - circ.cz_if_bit(a[i], b[i], bit); - circ.cx(*cy[i].as_ref().unwrap(), a[i]); - circ.cx(*cy[i].as_ref().unwrap(), b[i]); - circ.x(b[i]); - } - let c0 = cy[0].take().unwrap(); - circ.cx(*cin, c0); - circ.x(c0); - circ.zero_and_free(c0); -} - -pub fn swap_decision_uncompute_vented( - circ: &mut B, - ctrl: &QubitId, - v: &[QubitId], - u: &[QubitId], - k: usize, - flag: &QubitId, -) { - assert!( - k > 0 && k <= v.len() && k <= u.len(), - "k must fit in both operands" - ); - let v_top: Vec = v[v.len() - k..].to_vec(); - let u_top: Vec = u[u.len() - k..].to_vec(); - - let ck = super::next_cmp_k().saturating_add(1); - let bit = circ.alloc_bit(); - circ.hmr(*flag, bit); - circ.push_condition(bit); - compare_geq_chunked_middle_direct( - circ, - &v_top, - &u_top, - |c, carry| { - - c.x(*carry); - c.cz(*ctrl, *carry); - c.x(*carry); - }, - ck, - ); - circ.pop_condition(); -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::circuit::OperationType; - use crate::sim::Simulator; - use sha3::{ - digest::{ExtendableOutput, Update}, - Shake256, - }; - - fn alloc_case(circ: &mut B, n: usize) -> (Vec, Vec, QubitId, QubitId) { - let a = (0..n).map(|_| circ.alloc_qubit()).collect(); - let b = (0..n).map(|_| circ.alloc_qubit()).collect(); - let ctrl = circ.alloc_qubit(); - let target = circ.alloc_qubit(); - (a, b, ctrl, target) - } - - fn xor_value(circ: &mut B, qs: &[QubitId], value: usize) { - for (i, &q) in qs.iter().enumerate() { - if (value >> i) & 1 != 0 { - circ.x(q); - } - } - } - - fn simulate(circ: &B) -> (Vec, u64) { - let mut shake = Shake256::default(); - shake.update(b"comparator-direct-final-carry-test"); - let mut xof = shake.finalize_xof(); - let mut sim = - Simulator::new(circ.next_qubit as usize, circ.next_bit as usize, &mut xof); - sim.apply_iter(circ.ops.iter()); - (sim.qubits, sim.phase) - } - - fn read_uniform(qs: &[QubitId], qubits: &[u64]) -> usize { - qs.iter().enumerate().fold(0usize, |value, (i, q)| { - let lane = qubits[q.0 as usize]; - assert!( - lane == 0 || lane == u64::MAX, - "nonuniform data lane q{}", - q.0 - ); - value | (usize::from(lane == u64::MAX) << i) - }) - } - - fn toffoli_count(circ: &B) -> usize { - circ.ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count() - } - - #[test] - fn direct_final_carry_is_exhaustive_for_small_widths() { - for n in 1..=4 { - let limit = 1usize << n; - for held in 0..=n { - for a_value in 0..limit { - for b_value in 0..limit { - for ctrl_value in 0..=1usize { - for target_value in 0..=1usize { - let mut circ = B::new(); - let (a, b, ctrl, target) = alloc_case(&mut circ, n); - xor_value(&mut circ, &a, a_value); - xor_value(&mut circ, &b, b_value); - if ctrl_value != 0 { - circ.x(ctrl); - } - if target_value != 0 { - circ.x(target); - } - compare_geq_chunked_middle_direct( - &mut circ, - &a, - &b, - |c, carry| { - c.x(*carry); - c.ccx(ctrl, *carry, target); - c.cz(ctrl, *carry); - c.x(*carry); - }, - held, - ); - - assert_eq!(circ.active_qubits as usize, 2 * n + 2); - let (qubits, phase) = simulate(&circ); - let predicate = ctrl_value != 0 && a_value < b_value; - assert_eq!(read_uniform(&a, &qubits), a_value); - assert_eq!(read_uniform(&b, &qubits), b_value); - assert_eq!( - qubits[ctrl.0 as usize], - if ctrl_value != 0 { u64::MAX } else { 0 } - ); - assert_eq!( - qubits[target.0 as usize], - if (target_value != 0) ^ predicate { - u64::MAX - } else { - 0 - }, - ); - assert_eq!(phase, if predicate { u64::MAX } else { 0 }); - assert!(qubits[2 * n + 2..].iter().all(|&q| q == 0)); - } - } - } - } - } - } - } - - #[test] - fn freed_predicate_lane_funds_one_held_carry() { - for n in 1..=8 { - for held in 0..n { - let mut legacy = B::new(); - let (a, b, ctrl, target) = alloc_case(&mut legacy, n); - let flag = legacy.alloc_qubit(); - compare_geq_chunked_middle( - &mut legacy, - &a, - &b, - &flag, - |c, flag| { - c.x(*flag); - c.ccx(ctrl, *flag, target); - c.x(*flag); - }, - held, - ); - legacy.zero_and_free(flag); - - let mut direct = B::new(); - let (a, b, ctrl, target) = alloc_case(&mut direct, n); - compare_geq_chunked_middle_direct( - &mut direct, - &a, - &b, - |c, carry| { - c.x(*carry); - c.ccx(ctrl, *carry, target); - c.x(*carry); - }, - held + 1, - ); - - assert_eq!( - direct.peak_qubits, legacy.peak_qubits, - "n={n} held={held}" - ); - assert_eq!( - toffoli_count(&direct) + 1, - toffoli_count(&legacy), - "n={n} held={held}", - ); - } - } - } -} + +use super::{B, BExt}; +use crate::circuit::QubitId; +use std::cell::Cell; + +thread_local! { + static COMPARE_DIRECT_CALL_INDEX: Cell = const { Cell::new(0) }; + static COMPARE_CIN_CALL_INDEX: Cell = const { Cell::new(0) }; +} + +pub(super) fn reset_compare_call_index() { + COMPARE_DIRECT_CALL_INDEX.with(|index| index.set(0)); + COMPARE_CIN_CALL_INDEX.with(|index| index.set(0)); +} + +fn next_compare_direct_call_index() -> usize { + COMPARE_DIRECT_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_compare_cin_call_index() -> usize { + COMPARE_CIN_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +const COMPARE_CIN_STRUCTURAL_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (3, 0, 64), + (4, 20, 21), + (4, 23, 64), + (105, 16, 18), + (1257, 0, 2), + (1279, 0, 2), + (1292, 0, 2), + (1305, 0, 2), + (1318, 0, 2), + (1331, 0, 2), + (1344, 0, 2), + (1356, 0, 2), + (1369, 0, 2), + (1382, 0, 2), + (1395, 0, 2), + (1408, 0, 2), + (1422, 0, 2), + (1435, 0, 2), + (1449, 0, 2), + (1463, 0, 2), + (1477, 0, 2), + (1491, 0, 2), + (1506, 0, 2), + (1520, 0, 2), + (1535, 0, 2), + (1551, 0, 2), + (1566, 0, 2), + (1582, 0, 2), + (1599, 0, 2), + (1615, 0, 2), + (1632, 0, 2), + (1652, 0, 2), + (1669, 0, 2), + (1689, 0, 2), + (1706, 0, 2), + (1726, 0, 2), + (1743, 0, 2), + (1760, 0, 2), + (1777, 0, 2), + (1794, 0, 2), + (1812, 0, 2), + (1829, 0, 2), + (1847, 0, 2), + (1866, 0, 2), + (1884, 0, 2), + (1903, 0, 2), + (1923, 0, 2), + (1942, 0, 2), + (1958, 0, 2), + (1974, 0, 2), + (1990, 0, 2), + (2006, 0, 2), + (2023, 0, 2), + (2041, 0, 2), + (2061, 0, 2), + (2086, 0, 2), + (2112, 0, 2), + (2137, 0, 2), + (2161, 0, 2), + (2184, 0, 2), + (2366, 0, 2), + (2389, 0, 2), + (2413, 0, 2), + (2438, 0, 2), + (2464, 0, 2), + (2489, 0, 2), + (2509, 0, 2), + (2527, 0, 2), + (2544, 0, 2), + (2560, 0, 2), + (2576, 0, 2), + (2592, 0, 2), + (2608, 0, 2), + (2627, 0, 2), + (2647, 0, 2), + (2666, 0, 2), + (2684, 0, 2), + (2703, 0, 2), + (2721, 0, 2), + (2738, 0, 2), + (2756, 0, 2), + (2773, 0, 2), + (2790, 0, 2), + (2807, 0, 2), + (2824, 0, 2), + (2844, 0, 2), + (2861, 0, 2), + (2881, 0, 2), + (2898, 0, 2), + (2918, 0, 2), + (2935, 0, 2), + (2951, 0, 2), + (2968, 0, 2), + (2984, 0, 2), + (2999, 0, 2), + (3015, 0, 2), + (3030, 0, 2), + (3044, 0, 2), + (3059, 0, 2), + (3073, 0, 2), + (3087, 0, 2), + (3101, 0, 2), + (3115, 0, 2), + (3128, 0, 2), + (3142, 0, 2), + (3155, 0, 2), + (3168, 0, 2), + (3181, 0, 2), + (3194, 0, 2), + (3206, 0, 2), + (3219, 0, 2), + (3232, 0, 2), + (3245, 0, 2), + (3258, 0, 2), + (3271, 0, 2), + (3293, 0, 2), +]; + +const COMPARE_CIN_REMAINDER_KEYS: &[u32] = &[ + 8, 274, 530, 12817, 12818, 14098, 15377, 15378, 16657, 16658, 17937, 17938, + 19217, 19218, 20497, 20498, 21777, 21778, 23057, 23058, 24337, 24338, 25617, 25618, + 28177, 28178, 29457, 29458, 30737, 30738, 32017, 32018, 33297, 33298, 34577, 34578, + 35857, 35858, 37137, 37138, 38417, 38418, 39697, 39698, 40978, 42257, 42258, 43537, + 43538, 44817, 44818, 46097, 46098, 47378, 48658, 49938, 51218, 52498, 53777, 53778, + 55058, 56337, 56338, 57618, 58898, 60178, 61458, 62738, 64018, 66578, 67858, 69138, + 70674, 71954, 73490, 75026, 76562, 78098, 79634, 81170, 82706, 84242, 87314, 90386, + 94994, 111890, 116498, 121106, 127250, 130322, 131858, 134930, 139538, 141074, + 144146, 145682, 147218, 150290, 151826, 154897, 154898, 156433, 156434, 158226, + 159762, 161554, 165138, 175634, 177426, 179218, 182802, 184594, 186386, 188178, + 189970, 191761, 191762, 193554, 200716, 202509, 209682, 211471, 213264, 216846, + 233734, 235783, 246020, 252163, 254212, 256261, 258306, 260355, 270592, 272641, + 281345, 283666, 288000, 300818, 306962, 311314, 313618, 323858, 326162, 329490, + 332818, 339474, 854546, 867090, 873490, 925704, 929798, 937738, 943115, 946702, + 950288, 952079, 964623, 966418, 970002, 971794, 977170, 1000210, 1002002, 1003794, + 1007122, 1022482, 1031698, 1033234, 1085458, 1091602, 1103378, 1112338, 1121298, + 1127698, 1132818, 1136658, 1148177, 1148178, 1149457, +]; + +fn compare_cin_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { + return false; + } + if std::env::var_os("TLM_COMPARE_SKIP_EXACT_CIN_REMAINDER").is_some() { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if COMPARE_CIN_REMAINDER_KEYS.binary_search(&key).is_ok() { + return true; + } + } + COMPARE_CIN_STRUCTURAL_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +const COMPARE_STRUCTURAL_DEAD_TOP_RANGES: &[(usize, usize, usize)] = &[ + (775, 0, 18), + (776, 0, 18), + (777, 0, 18), + (778, 0, 18), + (779, 0, 18), + (782, 0, 18), + (783, 0, 18), + (784, 0, 18), + (785, 0, 18), + (786, 0, 18), + (788, 0, 18), + (789, 0, 18), + (790, 0, 18), + (791, 0, 18), + (792, 0, 18), + (516, 1, 10), + (1055, 1, 10), + (517, 3, 11), + (518, 5, 13), + (1057, 3, 11), + (1059, 5, 13), + (520, 8, 15), + (519, 7, 13), + (521, 9, 15), + (1061, 7, 13), + (1063, 9, 15), + (1065, 9, 15), + (511, 8, 13), + (522, 10, 15), + (523, 11, 16), + (1067, 10, 15), + (1069, 11, 16), + (507, 11, 15), + (515, 6, 10), + (525, 13, 17), + (526, 14, 18), + (527, 15, 19), + (808, 29, 33), + (1052, 9, 13), + (1071, 12, 16), + (1073, 13, 17), + (1075, 14, 18), + (21, 30, 33), + (23, 30, 33), + (25, 30, 33), + (27, 30, 33), + (29, 30, 33), + (31, 30, 33), + (33, 31, 34), + (505, 12, 15), + (509, 10, 13), + (524, 13, 16), + (537, 25, 28), + (539, 27, 30), + (541, 29, 32), + (543, 31, 34), + (807, 30, 33), + (809, 30, 33), + (810, 30, 33), + (811, 30, 33), + (812, 30, 33), + (813, 31, 34), + (819, 30, 33), + (1049, 12, 15), + (1050, 12, 15), + (1051, 10, 13), + (1053, 8, 11), + (1054, 7, 10), + (1077, 16, 19), + (1081, 17, 20), + (1095, 24, 27), + (1099, 26, 29), + (1101, 27, 30), + (1115, 34, 37), + (1121, 37, 40), + (19, 29, 31), + (35, 32, 34), + (37, 31, 33), + (39, 32, 34), + (41, 32, 34), + (43, 32, 34), + (45, 31, 33), + (47, 33, 35), + (49, 33, 35), + (51, 32, 34), + (53, 32, 34), + (55, 33, 35), + (57, 32, 34), + (61, 34, 36), + (501, 14, 16), + (503, 13, 15), + (513, 9, 11), + (528, 17, 19), + (529, 18, 20), + (533, 21, 23), + (538, 27, 29), + (540, 29, 31), + (542, 31, 33), + (544, 33, 35), + (545, 34, 36), + (546, 35, 37), + (547, 36, 38), + (548, 37, 39), + (550, 39, 41), + (551, 40, 42), + (553, 42, 44), + (555, 43, 45), + (805, 29, 31), + (806, 29, 31), + (814, 32, 34), + (815, 31, 33), + (817, 32, 34), + (818, 32, 34), + (820, 33, 35), + (821, 33, 35), + (822, 32, 34), + (823, 32, 34), + (824, 33, 35), + (825, 32, 34), + (826, 32, 34), + (827, 34, 36), + (829, 33, 35), + (832, 33, 35), + (833, 34, 36), + (1044, 16, 18), + (1047, 14, 16), + (1048, 13, 15), + (1079, 17, 19), + (1097, 26, 28), + (1103, 29, 31), + (1105, 30, 32), + (1109, 32, 34), + (1111, 33, 35), + (1113, 34, 36), + (1117, 36, 38), + (1119, 37, 39), + (1123, 39, 41), + (1125, 40, 42), + (1127, 41, 43), + (1129, 42, 44), + (1131, 43, 45), + (1133, 43, 45), + (1135, 44, 46), + (1137, 45, 47), + (15, 28, 29), + (17, 30, 31), + (59, 33, 34), + (63, 33, 34), + (65, 34, 35), + (67, 34, 35), + (69, 34, 35), + (71, 34, 35), + (73, 35, 36), + (75, 34, 35), + (77, 35, 36), + (79, 35, 36), + (81, 35, 36), + (83, 34, 35), + (85, 35, 36), + (87, 35, 36), + (89, 35, 36), + (91, 35, 36), + (93, 36, 37), + (95, 35, 36), + (97, 36, 37), + (99, 35, 36), + (101, 36, 37), + (105, 36, 37), + (107, 36, 37), + (109, 36, 37), + (111, 36, 37), + (113, 37, 38), + (121, 37, 38), + (123, 37, 38), + (129, 37, 38), + (133, 37, 38), + (137, 38, 39), + (143, 38, 39), + (165, 40, 41), + (177, 40, 41), + (189, 42, 43), + (191, 41, 42), + (203, 42, 43), + (207, 43, 44), + (211, 43, 44), + (213, 42, 43), + (215, 43, 44), + (217, 43, 44), + (221, 44, 45), + (223, 43, 44), + (225, 44, 45), + (227, 44, 45), + (229, 44, 45), + (233, 44, 45), + (245, 45, 46), + (247, 44, 45), + (249, 44, 45), + (255, 44, 45), + (257, 44, 45), + (259, 44, 45), + (261, 45, 46), + (263, 45, 46), + (265, 45, 46), + (285, 45, 46), + (287, 46, 47), + (291, 46, 47), + (299, 45, 46), + (321, 46, 47), + (327, 47, 48), + (333, 47, 48), + (359, 49, 50), + (361, 49, 50), + (395, 50, 51), + (411, 52, 53), + (415, 52, 53), + (421, 52, 53), + (431, 47, 48), + (433, 46, 47), + (439, 44, 45), + (441, 43, 44), + (447, 40, 41), + (449, 39, 40), + (451, 38, 39), + (459, 34, 35), + (461, 33, 34), + (465, 31, 32), + (467, 30, 31), + (471, 28, 29), + (475, 26, 27), + (493, 18, 19), + (495, 17, 18), + (497, 16, 17), + (499, 15, 16), + (530, 19, 20), + (532, 21, 22), + (534, 23, 24), + (536, 26, 27), + (549, 39, 40), + (552, 42, 43), + (554, 44, 45), + (556, 45, 46), + (557, 46, 47), + (558, 47, 48), + (559, 48, 49), + (563, 52, 53), + (568, 52, 53), + (570, 52, 53), + (575, 52, 53), + (592, 49, 50), + (595, 48, 49), + (613, 46, 47), + (621, 45, 46), + (628, 46, 47), + (630, 46, 47), + (631, 44, 44), + (631, 46, 46), + (635, 44, 45), + (639, 44, 45), + (640, 45, 46), + (642, 44, 44), + (642, 46, 46), + (643, 45, 46), + (644, 44, 45), + (645, 44, 45), + (647, 44, 45), + (650, 44, 45), + (651, 45, 46), + (661, 44, 45), + (678, 41, 42), + (679, 42, 43), + (706, 37, 38), + (719, 36, 37), + (721, 36, 37), + (722, 36, 37), + (723, 36, 37), + (742, 33, 34), + (744, 33, 34), + (804, 28, 29), + (816, 33, 34), + (828, 33, 34), + (830, 34, 35), + (831, 34, 35), + (834, 34, 35), + (835, 35, 36), + (836, 35, 36), + (837, 35, 36), + (838, 34, 35), + (839, 35, 36), + (840, 35, 36), + (841, 35, 36), + (842, 35, 36), + (844, 35, 36), + (845, 36, 37), + (846, 35, 36), + (847, 36, 37), + (849, 36, 37), + (850, 36, 37), + (851, 36, 37), + (856, 37, 38), + (858, 37, 38), + (860, 37, 38), + (864, 37, 38), + (865, 38, 39), + (891, 42, 43), + (892, 41, 42), + (898, 42, 43), + (900, 43, 44), + (901, 42, 43), + (904, 43, 44), + (905, 43, 44), + (907, 44, 45), + (908, 43, 44), + (909, 44, 45), + (911, 44, 45), + (912, 44, 45), + (913, 44, 45), + (919, 45, 46), + (920, 44, 45), + (921, 44, 45), + (923, 44, 45), + (924, 44, 45), + (925, 44, 45), + (926, 44, 45), + (927, 45, 46), + (928, 45, 46), + (930, 45, 46), + (931, 44, 45), + (938, 46, 47), + (940, 46, 47), + (941, 45, 46), + (942, 46, 47), + (973, 49, 50), + (979, 49, 50), + (980, 49, 50), + (981, 49, 50), + (983, 50, 51), + (985, 50, 51), + (988, 50, 51), + (992, 50, 51), + (996, 51, 52), + (997, 51, 52), + (1003, 52, 53), + (1004, 52, 53), + (1005, 52, 53), + (1008, 51, 52), + (1009, 50, 51), + (1012, 47, 48), + (1013, 46, 47), + (1016, 44, 45), + (1020, 40, 41), + (1022, 38, 39), + (1023, 37, 38), + (1026, 34, 35), + (1028, 32, 33), + (1030, 30, 31), + (1031, 29, 30), + (1032, 28, 29), + (1033, 27, 28), + (1034, 26, 27), + (1043, 18, 19), + (1045, 16, 17), + (1046, 15, 16), + (1083, 19, 20), + (1085, 20, 21), + (1087, 21, 22), + (1089, 22, 23), + (1091, 23, 24), + (1093, 24, 25), + (1107, 32, 33), + (1139, 46, 46), + (1139, 48, 48), + (1145, 50, 51), + (1155, 52, 53), + (1163, 52, 53), + (1169, 51, 52), + (1201, 49, 50), + (1245, 47, 48), + (1267, 46, 47), + (1281, 45, 46), + (1283, 46, 47), + (1301, 44, 45), + (1307, 45, 46), + (1309, 45, 46), + (1313, 44, 45), + (1317, 44, 45), + (1339, 44, 45), + (1341, 44, 45), + (1343, 44, 45), + (1379, 41, 42), + (1381, 42, 43), + (1461, 36, 37), + (1471, 35, 36), + (1493, 35, 36), + (1497, 35, 36), + (1525, 32, 33), + (1539, 32, 33), +]; + +const COMPARE_DIRECT_REMAINDER_KEYS: &[u32] = &[ + 530, 3356, 26405, 29478, 29990, 30502, 32038, 32550, 33574, 34598, 35623, 36135, + 37159, 37671, 38184, 38696, 39209, 39720, 40231, 40744, 41256, 41769, 42794, 43304, + 43816, 44329, 44841, 45865, 46377, 46889, 47402, 47913, 49449, 49961, 50475, 50986, + 51498, 52523, 53547, 56107, 59181, 60204, 61229, 61740, 62253, 64301, 64813, 68398, + 68909, 69422, 69934, 70957, 71470, 71981, 72495, 74030, 75054, 76079, 77103, 77615, + 78126, 78639, 79151, 79663, 80175, 80687, 81200, 81712, 82737, 84272, 84784, 85809, + 86320, 86832, 87345, 87857, 88369, 88882, 89393, 89905, 90418, 90929, 92978, 93490, + 94002, 94514, 95026, 95539, 96052, 96563, 97075, 97587, 98099, 98611, 99123, 99636, + 100147, 100659, 101685, 102196, 102708, 103220, 103731, 104245, 104756, 105781, 106805, 107317, + 108340, 108851, 109362, 109873, 111406, 111917, 113451, 113962, 116006, 116517, 117028, 118561, + 120094, 121116, 123159, 125204, 125715, 135957, 136985, 143410, 143667, 143924, 144437, 144693, + 144948, 145205, 145716, 146227, 146484, 146996, 147507, 147762, 148276, 148531, 148787, 149043, + 149299, 149555, 150068, 150578, 151090, 151346, 151858, 152624, 152882, 153137, 153393, 153650, + 153905, 154161, 154417, 154672, 154928, 155184, 155440, 155696, 155952, 156208, 156464, 156721, + 157232, 157488, 157743, 157999, 158255, 158511, 158767, 159279, 159790, 160047, 160302, 160558, + 161070, 161839, 162093, 163374, 164142, 165421, 166189, 166957, 167212, 167980, 168237, 168493, + 168749, 169005, 169515, 169773, 170284, 170540, 170795, 171052, 171307, 171564, 172075, 172586, + 172843, 173353, 174633, 175145, 175401, 175913, 176424, 176682, 177193, 177448, 177704, 177959, + 178215, 178473, 178728, 178984, 179239, 179495, 179751, 180007, 180263, 180519, 181030, 181542, + 181798, 182310, 182822, 183078, 183590, 183845, 185380, 185892, 186149, 186404, 187172, 187940, + 188196, 188451, 188708, 188963, 189219, 189475, 189731, 190244, 191266, 191522, 191779, 192287, + 192546, 192802, 193313, 193570, 194081, 194593, 194849, 195105, 205596, 215845, 217125, 218149, + 218406, 218662, 218918, 219430, 219942, 220454, 220710, 220966, 221735, 221991, 222247, 222503, + 222759, 223016, 223272, 223529, 223784, 224296, 224552, 224809, 225065, 225322, 225576, 225832, + 226089, 226345, 226601, 226857, 227113, 227369, 227626, 227881, 228649, 228905, 229163, 229418, + 229674, 230187, 230956, 231211, 231979, 233005, 234028, 234284, 234541, 234796, 235053, 236077, + 237870, 238638, 238894, 239149, 239405, 239662, 239917, 240430, 241454, 241710, 241967, 242222, + 242479, 242735, 243247, 243503, 243759, 244015, 244271, 244528, 244784, 245039, 245297, 245552, + 245808, 246064, 246320, 246576, 246833, 247088, 247344, 247601, 247857, 248112, 248370, 248625, + 248881, 249393, 249649, 249906, 250162, 250418, 251442, 251956, 252467, 252723, 253235, 253491, + 253748, 254259, 254515, 254773, 255540, 255795, 256053, 256308, 256565, 257589, 257845, 258610, + 258865, 259630, 259885, 260396, 260651, 260906, 261416, 262181, 262436, 262946, 263456, 265240, + 266005, 266516, 266771, 292145, 292658, 293684, 294197, 294709, 295221, 296245, 296757, 297268, + 299828, 300341, 300851, 301875, 302388, 302899, 303411, 304947, 305459, 305972, 306483, 306994, + 308018, 308530, 309042, 309554, 310577, 313138, 313649, 314161, 315184, 315696, 316209, 316720, + 317232, 317744, 318256, 319281, 319791, 320304, 320816, 321327, 321838, 322351, 323375, 325422, + 325935, 326446, 326958, 327471, 329006, 329519, 331565, 332590, 333614, 334126, 335661, 336685, + 338221, 338733, 339246, 341804, 342317, 344365, 345389, 346412, 346923, 347948, 348459, 348972, + 349995, 350506, 358184, 359210, 359721, 360233, 360744, 361256, 362280, 363304, 363816, 365351, + 365863, 366887, 367910, 368422, 369446, 369958, 370470, 370982, 372006, 372518, 374565, 375589, + 376101, 377125, 377635, 378149, 378660, 379171, 379684, 380196, 380707, 381220, 381732, 382755, + 383779, 384291, 384803, 385315, 385826, 386340, 386850, 387362, 387875, 388386, 388898, 389410, + 389923, 390946, 391970, 392481, 393506, 394529, 395553, 396065, +]; + +fn compare_call_has_structurally_dead_top(call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_COMPARE_SKIP_STRUCTURAL_DEAD_CALLS").is_none() { + return false; + } + if std::env::var_os("TLM_COMPARE_SKIP_EXACT_REMAINDER").is_some() { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if COMPARE_DIRECT_REMAINDER_KEYS.binary_search(&key).is_ok() { + return true; + } + } + COMPARE_STRUCTURAL_DEAD_TOP_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn compare_geq_chunked_middle_direct( + circ: &mut B, + a: &[QubitId], + b: &[QubitId], + body: F, + k: usize, +) { + let call_index = next_compare_direct_call_index(); + let ops_start = circ.current_ops_len(); + let n = a.len(); + assert_eq!( + b.len(), + n, + "compare_geq_chunked_middle_direct: a,b equal width" + ); + assert!( + n > 0, + "compare_geq_chunked_middle_direct: nonempty operands" + ); + let k = super::target_qubit_headroom(circ) + .map_or(k, |headroom| k.min(headroom.saturating_sub(1))) + .min(n); + let split = n - k; + let mut cy: Vec> = (0..=n).map(|_| None).collect(); + let c = circ.alloc_qubit(); + circ.x(c); + + for i in 0..split { + circ.x(b[i]); + circ.cx(c, b[i]); + circ.cx(c, a[i]); + circ.ccx(a[i], b[i], c); + } + cy[split] = Some(c); + + for i in split..n { + let next = circ.alloc_qubit(); + { + let ci = cy[i].as_ref().unwrap(); + circ.x(b[i]); + circ.cx(*ci, b[i]); + circ.cx(*ci, a[i]); + if !compare_call_has_structurally_dead_top(call_index, i) { + let old_context = crate::point_add::set_op_trace_context( + 0x0400_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(a[i], b[i], next); + crate::point_add::restore_op_trace_context(old_context); + } + circ.cx(*ci, next); + } + cy[i + 1] = Some(next); + } + body(circ, cy[n].as_ref().unwrap()); + + for i in (split..n).rev() { + let next = cy[i + 1].take().unwrap(); + circ.cx(*cy[i].as_ref().unwrap(), next); + let bit = circ.alloc_bit(); + circ.hmr(next, bit); + circ.zero_and_free(next); + circ.cz_if_bit(a[i], b[i], bit); + circ.cx(*cy[i].as_ref().unwrap(), a[i]); + circ.cx(*cy[i].as_ref().unwrap(), b[i]); + circ.x(b[i]); + } + + let c = cy[split].take().unwrap(); + for i in (0..split).rev() { + circ.ccx(a[i], b[i], c); + circ.cx(c, a[i]); + circ.cx(c, b[i]); + circ.x(b[i]); + } + circ.x(c); + circ.zero_and_free(c); + if std::env::var_os("TRACE_TLM_COMPARE_DIRECT").is_some() { + eprintln!( + "TLM_COMPARE_DIRECT call={} phase={} n={} k={} split={} ops_start={} ops_end={}", + call_index, + circ.phase, + n, + k, + split, + ops_start, + circ.current_ops_len(), + ); + } +} + +pub fn compare_geq_chunked_middle( + circ: &mut B, + a: &[QubitId], + b: &[QubitId], + flag: &QubitId, + body: F, + k: usize, +) { + assert_eq!( + b.len(), + a.len(), + "compare_geq_chunked_middle: a,b equal width" + ); + if a.is_empty() { + circ.x(*flag); + body(circ, flag); + circ.x(*flag); + return; + } + compare_geq_chunked_middle_direct( + circ, + a, + b, + |c, carry| { + c.cx(*carry, *flag); + body(c, flag); + c.cx(*carry, *flag); + }, + k, + ); +} + +pub fn controlled_swap_decision_lt_truncated( + circ: &mut B, + ctrl: &QubitId, + u: &[QubitId], + v: &[QubitId], + k: usize, + target: &QubitId, +) { + assert!( + k > 0 && k <= u.len() && k <= v.len(), + "k must fit in both operands" + ); + let u_top: Vec = u[u.len() - k..].to_vec(); + let v_top: Vec = v[v.len() - k..].to_vec(); + + let ck = super::next_cmp_k().saturating_add(1); + compare_geq_chunked_middle_direct( + circ, + &u_top, + &v_top, + |c, carry| { + c.x(*carry); + c.ccx(*ctrl, *carry, *target); + c.x(*carry); + }, + ck, + ); +} + +pub fn compare_geq_cin_middle( + circ: &mut B, + a: &[QubitId], + b: &[QubitId], + cin: &QubitId, + body: F, +) { + let call_index = next_compare_cin_call_index(); + let n = a.len(); + assert_eq!(b.len(), n, "compare_geq_cin_middle: a,b equal width"); + assert!(n >= 1, "needs >= 1 bit"); + let mut cy: Vec> = Vec::with_capacity(n); + let c0 = circ.alloc_qubit(); + circ.x(c0); + circ.cx(*cin, c0); + cy.push(Some(c0)); + for i in 0..n - 1 { + let next = circ.alloc_qubit(); + let ci = cy[i].as_ref().unwrap(); + circ.x(b[i]); + circ.cx(*ci, b[i]); + circ.cx(*ci, a[i]); + let old_context = crate::point_add::set_op_trace_context( + 0x1300_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + if !compare_cin_has_structurally_dead_carry(call_index, i) { + circ.ccx(a[i], b[i], next); + } + crate::point_add::restore_op_trace_context(old_context); + circ.cx(*ci, next); + cy.push(Some(next)); + } + + { + let i = n - 1; + let ci = cy[i].as_ref().unwrap(); + circ.x(b[i]); + circ.cx(*ci, b[i]); + circ.cx(*ci, a[i]); + body(circ, &a[i], &b[i], ci); + circ.cx(*ci, a[i]); + circ.cx(*ci, b[i]); + circ.x(b[i]); + } + + for i in (0..n - 1).rev() { + let next = cy[i + 1].take().unwrap(); + let ci_raw = cy[i].as_ref().unwrap(); + circ.cx(*ci_raw, next); + let bit = circ.alloc_bit(); + circ.hmr(next, bit); + circ.zero_and_free(next); + circ.cz_if_bit(a[i], b[i], bit); + circ.cx(*cy[i].as_ref().unwrap(), a[i]); + circ.cx(*cy[i].as_ref().unwrap(), b[i]); + circ.x(b[i]); + } + let c0 = cy[0].take().unwrap(); + circ.cx(*cin, c0); + circ.x(c0); + circ.zero_and_free(c0); +} + +pub fn swap_decision_uncompute_vented( + circ: &mut B, + ctrl: &QubitId, + v: &[QubitId], + u: &[QubitId], + k: usize, + flag: &QubitId, +) { + assert!( + k > 0 && k <= v.len() && k <= u.len(), + "k must fit in both operands" + ); + let v_top: Vec = v[v.len() - k..].to_vec(); + let u_top: Vec = u[u.len() - k..].to_vec(); + + let ck = super::next_cmp_k().saturating_add(1); + let bit = circ.alloc_bit(); + circ.hmr(*flag, bit); + circ.push_condition(bit); + compare_geq_chunked_middle_direct( + circ, + &v_top, + &u_top, + |c, carry| { + + c.x(*carry); + c.cz(*ctrl, *carry); + c.x(*carry); + }, + ck, + ); + circ.pop_condition(); +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::circuit::OperationType; + use crate::sim::Simulator; + use sha3::{ + digest::{ExtendableOutput, Update}, + Shake256, + }; + + fn alloc_case(circ: &mut B, n: usize) -> (Vec, Vec, QubitId, QubitId) { + let a = (0..n).map(|_| circ.alloc_qubit()).collect(); + let b = (0..n).map(|_| circ.alloc_qubit()).collect(); + let ctrl = circ.alloc_qubit(); + let target = circ.alloc_qubit(); + (a, b, ctrl, target) + } + + fn xor_value(circ: &mut B, qs: &[QubitId], value: usize) { + for (i, &q) in qs.iter().enumerate() { + if (value >> i) & 1 != 0 { + circ.x(q); + } + } + } + + fn simulate(circ: &B) -> (Vec, u64) { + let mut shake = Shake256::default(); + shake.update(b"comparator-direct-final-carry-test"); + let mut xof = shake.finalize_xof(); + let mut sim = + Simulator::new(circ.next_qubit as usize, circ.next_bit as usize, &mut xof); + sim.apply_iter(circ.ops.iter()); + (sim.qubits, sim.phase) + } + + fn read_uniform(qs: &[QubitId], qubits: &[u64]) -> usize { + qs.iter().enumerate().fold(0usize, |value, (i, q)| { + let lane = qubits[q.0 as usize]; + assert!( + lane == 0 || lane == u64::MAX, + "nonuniform data lane q{}", + q.0 + ); + value | (usize::from(lane == u64::MAX) << i) + }) + } + + fn toffoli_count(circ: &B) -> usize { + circ.ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count() + } + + #[test] + fn direct_final_carry_is_exhaustive_for_small_widths() { + for n in 1..=4 { + let limit = 1usize << n; + for held in 0..=n { + for a_value in 0..limit { + for b_value in 0..limit { + for ctrl_value in 0..=1usize { + for target_value in 0..=1usize { + let mut circ = B::new(); + let (a, b, ctrl, target) = alloc_case(&mut circ, n); + xor_value(&mut circ, &a, a_value); + xor_value(&mut circ, &b, b_value); + if ctrl_value != 0 { + circ.x(ctrl); + } + if target_value != 0 { + circ.x(target); + } + compare_geq_chunked_middle_direct( + &mut circ, + &a, + &b, + |c, carry| { + c.x(*carry); + c.ccx(ctrl, *carry, target); + c.cz(ctrl, *carry); + c.x(*carry); + }, + held, + ); + + assert_eq!(circ.active_qubits as usize, 2 * n + 2); + let (qubits, phase) = simulate(&circ); + let predicate = ctrl_value != 0 && a_value < b_value; + assert_eq!(read_uniform(&a, &qubits), a_value); + assert_eq!(read_uniform(&b, &qubits), b_value); + assert_eq!( + qubits[ctrl.0 as usize], + if ctrl_value != 0 { u64::MAX } else { 0 } + ); + assert_eq!( + qubits[target.0 as usize], + if (target_value != 0) ^ predicate { + u64::MAX + } else { + 0 + }, + ); + assert_eq!(phase, if predicate { u64::MAX } else { 0 }); + assert!(qubits[2 * n + 2..].iter().all(|&q| q == 0)); + } + } + } + } + } + } + } + + #[test] + fn freed_predicate_lane_funds_one_held_carry() { + for n in 1..=8 { + for held in 0..n { + let mut legacy = B::new(); + let (a, b, ctrl, target) = alloc_case(&mut legacy, n); + let flag = legacy.alloc_qubit(); + compare_geq_chunked_middle( + &mut legacy, + &a, + &b, + &flag, + |c, flag| { + c.x(*flag); + c.ccx(ctrl, *flag, target); + c.x(*flag); + }, + held, + ); + legacy.zero_and_free(flag); + + let mut direct = B::new(); + let (a, b, ctrl, target) = alloc_case(&mut direct, n); + compare_geq_chunked_middle_direct( + &mut direct, + &a, + &b, + |c, carry| { + c.x(*carry); + c.ccx(ctrl, *carry, target); + c.x(*carry); + }, + held + 1, + ); + + assert_eq!( + direct.peak_qubits, legacy.peak_qubits, + "n={n} held={held}" + ); + assert_eq!( + toffoli_count(&direct) + 1, + toffoli_count(&legacy), + "n={n} held={held}", + ); + } + } + } +} diff --git a/src/point_add/trailmix_ludicrous/constprop.rs b/src/point_add/trailmix_ludicrous/constprop.rs index b8dbfd0b..47723159 100644 --- a/src/point_add/trailmix_ludicrous/constprop.rs +++ b/src/point_add/trailmix_ludicrous/constprop.rs @@ -1,1986 +1,1767 @@ - -use crate::circuit::{BitId, NO_BIT, NO_QUBIT, Op, OperationType, QubitId}; -use crate::point_add::OpSite; - -const NEVER: usize = usize::MAX; - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -enum Val { - Zero, - One, - Unknown, -} - -use Val::*; - -#[derive(Clone, Copy, Debug, Default)] -pub struct ConstPropStats { - pub ccx_total: usize, - pub dropped: usize, - pub folded_cx: usize, - pub folded_x: usize, -} - -#[derive(Clone, Copy, Debug)] -enum Decision { - - Keep, - - DropZeroCtrl { ctrl: QubitId }, - - FoldCx { one_ctrl: QubitId, keep_ctrl: QubitId }, - - FoldX { c1: QubitId, c2: QubitId }, - - DropComplementCtrls { a: QubitId, b: QubitId }, - - FoldEqualCtrls { a: QubitId, b: QubitId, keep_ctrl: QubitId }, -} - -struct Analyzer { - q: Vec, - b: Vec, - - cond_stack: Vec, -} - -impl Analyzer { - fn qv(&self, id: QubitId) -> Val { - if id == NO_QUBIT { Unknown } else { self.q[id.0 as usize] } - } - fn bv(&self, id: BitId) -> Val { - if id == NO_BIT { Unknown } else { self.b[id.0 as usize] } - } - fn set_q(&mut self, id: QubitId, v: Val) { - self.q[id.0 as usize] = v; - } - fn set_b(&mut self, id: BitId, v: Val) { - self.b[id.0 as usize] = v; - } - - fn cond_always_true(&self, op: &Op) -> bool { - for &c in &self.cond_stack { - if self.bv(c) != One { - return false; - } - } - if op.c_condition != NO_BIT && self.bv(op.c_condition) != One { - return false; - } - true - } - - fn cond_maybe_false(&self, op: &Op) -> bool { - !self.cond_always_true(op) - } -} - -fn xor_val(a: Val, b: Val) -> Val { - match (a, b) { - (Zero, x) | (x, Zero) => x, - (One, One) => Zero, - _ => Unknown, - } -} - -fn and_val(a: Val, b: Val) -> Val { - match (a, b) { - (Zero, _) | (_, Zero) => Zero, - (One, One) => One, - _ => Unknown, - } -} - -fn merge(old: Val, new: Val) -> Val { - if old == new { old } else { Unknown } -} - -fn analyze(ops: &[Op], num_q: usize, num_b: usize, input_qubits: &[QubitId]) -> (Vec, ConstPropStats) { - let mut a = Analyzer { - q: vec![Zero; num_q], - b: vec![Zero; num_b], - cond_stack: Vec::new(), - }; - for &q in input_qubits { - a.q[q.0 as usize] = Unknown; - } - - let mut decisions = vec![Decision::Keep; ops.len()]; - let mut stats = ConstPropStats::default(); - - for (i, op) in ops.iter().enumerate() { - match op.kind { - OperationType::PushCondition => { - a.cond_stack.push(op.c_condition); - } - OperationType::PopCondition => { - a.cond_stack.pop(); - } - OperationType::CCX => { - stats.ccx_total += 1; - let c1 = a.qv(op.q_control1); - let c2 = a.qv(op.q_control2); - - if c1 == Zero { - decisions[i] = Decision::DropZeroCtrl { ctrl: op.q_control1 }; - stats.dropped += 1; - - } else if c2 == Zero { - decisions[i] = Decision::DropZeroCtrl { ctrl: op.q_control2 }; - stats.dropped += 1; - - } else if c1 == One && c2 == One { - decisions[i] = Decision::FoldX { c1: op.q_control1, c2: op.q_control2 }; - stats.folded_x += 1; - - let tgt = a.qv(op.q_target); - let nv = xor_val(tgt, One); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } else if c1 == One { - decisions[i] = Decision::FoldCx { one_ctrl: op.q_control1, keep_ctrl: op.q_control2 }; - stats.folded_cx += 1; - - let tgt = a.qv(op.q_target); - let delta = c2; - let nv = xor_val(tgt, delta); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } else if c2 == One { - decisions[i] = Decision::FoldCx { one_ctrl: op.q_control2, keep_ctrl: op.q_control1 }; - stats.folded_cx += 1; - let tgt = a.qv(op.q_target); - let delta = c1; - let nv = xor_val(tgt, delta); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } else { - - let delta = and_val(c1, c2); - let tgt = a.qv(op.q_target); - let nv = xor_val(tgt, delta); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } - } - OperationType::CX => { - let ctrl = a.qv(op.q_control1); - let tgt = a.qv(op.q_target); - let nv = xor_val(tgt, ctrl); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } - OperationType::X => { - let tgt = a.qv(op.q_target); - let nv = xor_val(tgt, One); - let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; - a.set_q(op.q_target, res); - } - OperationType::Swap => { - - let va = a.qv(op.q_control1); - let vt = a.qv(op.q_target); - if a.cond_maybe_false(op) { - - a.set_q(op.q_control1, merge(va, vt)); - a.set_q(op.q_target, merge(vt, va)); - } else { - a.set_q(op.q_control1, vt); - a.set_q(op.q_target, va); - } - } - OperationType::R => { - - let tgt = a.qv(op.q_target); - let res = if a.cond_maybe_false(op) { merge(tgt, Zero) } else { Zero }; - a.set_q(op.q_target, res); - } - OperationType::Hmr => { - - let res = if a.cond_maybe_false(op) { - merge(a.bv(op.c_target), Unknown) - } else { - Unknown - }; - a.set_b(op.c_target, res); - let tgt = a.qv(op.q_target); - let qres = if a.cond_maybe_false(op) { merge(tgt, Zero) } else { Zero }; - a.set_q(op.q_target, qres); - } - OperationType::BitStore0 => { - let cur = a.bv(op.c_target); - let res = if a.cond_maybe_false(op) { merge(cur, Zero) } else { Zero }; - a.set_b(op.c_target, res); - } - OperationType::BitStore1 => { - let cur = a.bv(op.c_target); - let res = if a.cond_maybe_false(op) { merge(cur, One) } else { One }; - a.set_b(op.c_target, res); - } - OperationType::BitInvert => { - let cur = a.bv(op.c_target); - let nv = xor_val(cur, One); - let res = if a.cond_maybe_false(op) { merge(cur, nv) } else { nv }; - a.set_b(op.c_target, res); - } - - OperationType::Z - | OperationType::CZ - | OperationType::CCZ - | OperationType::Neg - | OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - } - } - - (decisions, stats) -} - -const CAP_SET: usize = 2048; - -struct Affine { - cst: Vec, - set: Vec>, - nextvar: u32, - cond_stack: Vec, - - b: Vec, -} - -fn xor_set(a: &[u32], b: &[u32]) -> Vec { - let mut out = Vec::with_capacity(a.len() + b.len()); - let (mut i, mut j) = (0usize, 0usize); - while i < a.len() && j < b.len() { - if a[i] < b[j] { - out.push(a[i]); - i += 1; - } else if a[i] > b[j] { - out.push(b[j]); - j += 1; - } else { - i += 1; - j += 1; - } - } - out.extend_from_slice(&a[i..]); - out.extend_from_slice(&b[j..]); - out -} - -impl Affine { - fn fresh(&mut self) -> Vec { - let v = self.nextvar; - self.nextvar += 1; - vec![v] - } - fn bv(&self, id: BitId) -> Val { - if id == NO_BIT { Unknown } else { self.b[id.0 as usize] } - } - - fn cond_maybe_false(&self, op: &Op) -> bool { - for &c in &self.cond_stack { - if self.bv(c) != One { - return true; - } - } - if op.c_condition != NO_BIT && self.bv(op.c_condition) != One { - return true; - } - false - } -} - -fn analyze_affine( - ops: &[Op], - num_q: usize, - num_b: usize, - input_qubits: &[QubitId], -) -> (Vec, usize, usize) { - - let mut af = Affine { - cst: vec![false; num_q], - set: vec![Vec::new(); num_q], - nextvar: 0, - cond_stack: Vec::new(), - b: vec![Unknown; num_b], - }; - for &q in input_qubits { - let v = af.fresh(); - af.set[q.0 as usize] = v; - } - - let mut decisions = vec![Decision::Keep; ops.len()]; - let mut fold_eq = 0usize; - let mut drop_comp = 0usize; - - for (i, op) in ops.iter().enumerate() { - match op.kind { - OperationType::PushCondition => af.cond_stack.push(op.c_condition), - OperationType::PopCondition => { - af.cond_stack.pop(); - } - OperationType::X => { - let t = op.q_target.0 as usize; - if af.cond_maybe_false(op) { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - af.cst[t] ^= true; - } - } - OperationType::CX => { - let c = op.q_control1.0 as usize; - let t = op.q_target.0 as usize; - if af.cond_maybe_false(op) { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - let ns = xor_set(&af.set[t], &af.set[c]); - af.cst[t] ^= af.cst[c]; - if ns.len() > CAP_SET { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - af.set[t] = ns; - } - } - } - OperationType::CCX => { - let a = op.q_control1.0 as usize; - let b = op.q_control2.0 as usize; - let t = op.q_target.0 as usize; - - if af.set[a] == af.set[b] { - if af.cst[a] == af.cst[b] { - decisions[i] = Decision::FoldEqualCtrls { - a: op.q_control1, - b: op.q_control2, - keep_ctrl: op.q_control1, - }; - fold_eq += 1; - - if af.cond_maybe_false(op) { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - let ns = xor_set(&af.set[t], &af.set[a]); - af.cst[t] ^= af.cst[a]; - if ns.len() > CAP_SET { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - af.set[t] = ns; - } - } - } else { - decisions[i] = Decision::DropComplementCtrls { - a: op.q_control1, - b: op.q_control2, - }; - drop_comp += 1; - - } - } else { - - af.set[t] = af.fresh(); - af.cst[t] = false; - } - } - OperationType::Swap => { - let x = op.q_control1.0 as usize; - let y = op.q_target.0 as usize; - if af.cond_maybe_false(op) { - af.set[x] = af.fresh(); - af.cst[x] = false; - af.set[y] = af.fresh(); - af.cst[y] = false; - } else { - af.set.swap(x, y); - af.cst.swap(x, y); - } - } - OperationType::R => { - let t = op.q_target.0 as usize; - if af.cond_maybe_false(op) { - af.set[t] = af.fresh(); - af.cst[t] = false; - } else { - af.set[t] = Vec::new(); - af.cst[t] = false; - } - } - OperationType::Hmr => { - let t = op.q_target.0 as usize; - af.set[t] = af.fresh(); - af.cst[t] = false; - if op.c_target != NO_BIT { - af.b[op.c_target.0 as usize] = Unknown; - } - } - - OperationType::BitStore0 => { - if op.c_target != NO_BIT { - let cur = af.bv(op.c_target); - af.b[op.c_target.0 as usize] = - if af.cond_maybe_false(op) { merge(cur, Zero) } else { Zero }; - } - } - OperationType::BitStore1 => { - if op.c_target != NO_BIT { - let cur = af.bv(op.c_target); - af.b[op.c_target.0 as usize] = - if af.cond_maybe_false(op) { merge(cur, One) } else { One }; - } - } - OperationType::BitInvert => { - if op.c_target != NO_BIT { - let cur = af.bv(op.c_target); - let nv = xor_val(cur, One); - af.b[op.c_target.0 as usize] = - if af.cond_maybe_false(op) { merge(cur, nv) } else { nv }; - } - } - - OperationType::Z - | OperationType::CZ - | OperationType::CCZ - | OperationType::Neg - | OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - } - } - - (decisions, fold_eq, drop_comp) -} - -fn apply_decisions(ops: &[Op], decisions: &[Decision]) -> Vec { - let mut out = Vec::with_capacity(ops.len()); - for (i, op) in ops.iter().enumerate() { - match decisions[i] { - Decision::Keep => out.push(*op), - Decision::DropZeroCtrl { .. } => { } - Decision::FoldCx { keep_ctrl, .. } => { - let mut nop = Op::empty(); - nop.kind = OperationType::CX; - nop.q_control1 = keep_ctrl; - nop.q_target = op.q_target; - nop.c_condition = op.c_condition; - out.push(nop); - } - Decision::FoldX { .. } => { - let mut nop = Op::empty(); - nop.kind = OperationType::X; - nop.q_target = op.q_target; - nop.c_condition = op.c_condition; - out.push(nop); - } - Decision::DropComplementCtrls { .. } => { } - Decision::FoldEqualCtrls { keep_ctrl, .. } => { - - let mut nop = Op::empty(); - nop.kind = OperationType::CX; - nop.q_control1 = keep_ctrl; - nop.q_target = op.q_target; - nop.c_condition = op.c_condition; - out.push(nop); - } - } - } - out -} - -fn apply_site_decisions(sites: &[OpSite], decisions: &[Decision]) -> Vec { - let mut out = Vec::with_capacity(sites.len()); - for (i, site) in sites.iter().copied().enumerate() { - match decisions[i] { - Decision::Keep - | Decision::FoldCx { .. } - | Decision::FoldX { .. } - | Decision::FoldEqualCtrls { .. } => out.push(site), - Decision::DropZeroCtrl { .. } | Decision::DropComplementCtrls { .. } => {} - } - } - out -} - -fn filter_sites(sites: &[OpSite], kill: &[bool]) -> Vec { - sites - .iter() - .copied() - .enumerate() - .filter_map(|(i, site)| (!kill[i]).then_some(site)) - .collect() -} - -#[derive(Clone, Copy, Debug)] -struct PairKill { - first: usize, - second: usize, -} - -#[derive(Clone, Copy)] -struct WEvent { - idx: u32, - src: u32, - cond: u32, - epoch: u32, -} - -#[inline] -fn wev_written_between(ev: &[WEvent], lo: u32, hi: u32) -> bool { - if hi <= lo + 1 { - return false; - } - let start = ev.partition_point(|e| e.idx <= lo); - start < ev.len() && ev[start].idx < hi -} - -#[inline] -fn bit_written_between(ev: &[u32], lo: u32, hi: u32) -> bool { - if hi <= lo + 1 { - return false; - } - let start = ev.partition_point(|&x| x <= lo); - start < ev.len() && ev[start] < hi -} - -fn control_net_restored( - ctrl: u64, - p_idx: usize, - cur_epoch: u64, - cond_stack: &[u64], - wev_q: &[Vec], - wev_b: &[Vec], -) -> bool { - let events = &wev_q[ctrl as usize]; - let p = p_idx as u32; - let start = events.partition_point(|e| e.idx <= p); - let suffix = &events[start..]; - if suffix.is_empty() { - return true; - } - let mut stack: Vec = Vec::new(); - for &e in suffix { - if e.src != u32::MAX { - if let Some(&top) = stack.last() { - - let same = top.src == e.src - && top.cond == e.cond - && top.epoch == e.epoch - && e.epoch as u64 == cur_epoch; - if same { - let src_ok = - !wev_written_between(&wev_q[e.src as usize], top.idx, e.idx); - let cond_ok = e.cond == u32::MAX - || !bit_written_between(&wev_b[e.cond as usize], top.idx, e.idx); - let stack_ok = cond_stack.iter().all(|&sb| { - sb == u64::MAX - || !bit_written_between(&wev_b[sb as usize], top.idx, e.idx) - }); - if src_ok && cond_ok && stack_ok { - stack.pop(); - continue; - } - } - } - } - stack.push(e); - } - stack.is_empty() -} - -fn find_inverse_pairs( - ops: &[Op], - num_q: usize, - num_b: usize, - straddle: bool, -) -> (Vec, usize) { - - let mut wlast_q = vec![usize::MAX; num_q]; - let mut rlast_q = vec![usize::MAX; num_q]; - let mut wlast_b = vec![usize::MAX; num_b]; - - for v in wlast_q.iter_mut() { *v = NEVER; } - for v in rlast_q.iter_mut() { *v = NEVER; } - for v in wlast_b.iter_mut() { *v = NEVER; } - - #[derive(Clone, Copy)] - struct Pending { - idx: usize, - a: u64, - b: u64, - cb: u64, - epoch: u64, - } - let mut pending: Vec> = vec![None; num_q]; - - let mut cond_epoch: u64 = 0; - - let mut cond_stack: Vec = Vec::new(); - let mut killed = vec![false; ops.len()]; - let mut pairs = Vec::new(); - - let mut wev_q: Vec> = if straddle { - vec![Vec::new(); num_q] - } else { - Vec::new() - }; - let mut wev_b: Vec> = if straddle { - vec![Vec::new(); num_b] - } else { - Vec::new() - }; - - let mut straddle_extra = 0usize; - - #[inline] - fn touched_after(s: usize, p: usize) -> bool { - s != NEVER && s > p - } - - for (i, op) in ops.iter().enumerate() { - match op.kind { - OperationType::PushCondition => { - cond_epoch += 1; - cond_stack.push(op.c_condition.0); - } - OperationType::PopCondition => { - cond_epoch += 1; - cond_stack.pop(); - } - OperationType::CCX => { - let c1 = op.q_control1.0; - let c2 = op.q_control2.0; - let t = op.q_target.0; - let (a, b) = if c1 <= c2 { (c1, c2) } else { (c2, c1) }; - let cb = op.c_condition.0; - - let mut cancelled = false; - if let Some(p) = pending[t as usize] { - let same_gate = p.a == a && p.b == b && p.cb == cb; - let same_epoch = p.epoch == cond_epoch; - - let ctrls_clean = !touched_after(wlast_q[a as usize], p.idx) - && !touched_after(wlast_q[b as usize], p.idx); - - let ctrls_ok = if ctrls_clean { - true - } else if straddle { - control_net_restored(a, p.idx, cond_epoch, &cond_stack, &wev_q, &wev_b) - && control_net_restored( - b, p.idx, cond_epoch, &cond_stack, &wev_q, &wev_b, - ) - } else { - false - }; - let tgt_clean = !touched_after(wlast_q[t as usize], p.idx) - && !touched_after(rlast_q[t as usize], p.idx); - let cond_clean = cb == u64::MAX - || !touched_after(wlast_b[cb as usize], p.idx); - - let stack_clean = same_epoch - && cond_stack - .iter() - .all(|&sb| sb == u64::MAX || !touched_after(wlast_b[sb as usize], p.idx)); - if same_gate && same_epoch && ctrls_ok && tgt_clean && cond_clean && stack_clean { - killed[p.idx] = true; - killed[i] = true; - pairs.push(PairKill { first: p.idx, second: i }); - pending[t as usize] = None; - cancelled = true; - if !ctrls_clean { - straddle_extra += 1; - } - } - } - - if !cancelled { - - rlast_q[a as usize] = i; - rlast_q[b as usize] = i; - wlast_q[t as usize] = i; - if cb != u64::MAX { - - } - if straddle { - - wev_q[t as usize].push(WEvent { - idx: i as u32, - src: u32::MAX, - cond: u32::MAX, - epoch: cond_epoch as u32, - }); - } - pending[t as usize] = Some(Pending { - idx: i, - a, - b, - cb, - epoch: cond_epoch, - }); - } else { - - } - } - OperationType::CX => { - rlast_q[op.q_control1.0 as usize] = i; - wlast_q[op.q_target.0 as usize] = i; - pending[op.q_target.0 as usize] = None; - if straddle { - - wev_q[op.q_target.0 as usize].push(WEvent { - idx: i as u32, - src: op.q_control1.0 as u32, - cond: op.c_condition.0 as u32, - epoch: cond_epoch as u32, - }); - } - } - OperationType::X => { - wlast_q[op.q_target.0 as usize] = i; - pending[op.q_target.0 as usize] = None; - if straddle { - - wev_q[op.q_target.0 as usize].push(WEvent { - idx: i as u32, - src: u32::MAX, - cond: u32::MAX, - epoch: cond_epoch as u32, - }); - } - } - OperationType::Swap => { - let x = op.q_control1.0 as usize; - let y = op.q_target.0 as usize; - rlast_q[x] = i; rlast_q[y] = i; - wlast_q[x] = i; wlast_q[y] = i; - pending[x] = None; - pending[y] = None; - if straddle { - wev_q[x].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); - wev_q[y].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); - } - } - OperationType::R => { - wlast_q[op.q_target.0 as usize] = i; - pending[op.q_target.0 as usize] = None; - if straddle { - wev_q[op.q_target.0 as usize].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); - } - } - OperationType::Hmr => { - wlast_q[op.q_target.0 as usize] = i; - if op.c_target.0 != u64::MAX { wlast_b[op.c_target.0 as usize] = i; } - pending[op.q_target.0 as usize] = None; - if straddle { - wev_q[op.q_target.0 as usize].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); - if op.c_target.0 != u64::MAX { wev_b[op.c_target.0 as usize].push(i as u32); } - } - } - OperationType::CCZ => { - - rlast_q[op.q_control1.0 as usize] = i; - rlast_q[op.q_control2.0 as usize] = i; - rlast_q[op.q_target.0 as usize] = i; - } - OperationType::CZ => { - rlast_q[op.q_control1.0 as usize] = i; - rlast_q[op.q_target.0 as usize] = i; - } - OperationType::Z => { - rlast_q[op.q_target.0 as usize] = i; - } - OperationType::BitInvert - | OperationType::BitStore0 - | OperationType::BitStore1 => { - if op.c_target.0 != u64::MAX { wlast_b[op.c_target.0 as usize] = i; } - if straddle && op.c_target.0 != u64::MAX { - wev_b[op.c_target.0 as usize].push(i as u32); - } - } - OperationType::Neg - | OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - } - } - - (pairs, straddle_extra) -} - -/// W018 / W044: straddle-aware CCZ self-inverse cancellation. -/// -/// CCZ is diagonal and fully symmetric in its three qubits. Two CCZ on the same -/// unordered triple {a,b,c} compose to identity **iff**, between them, all three -/// qubits are NET-RESTORED (their per-branch computational-basis values at the 2nd -/// CCZ equal those at the 1st) and the condition context is unchanged. Under that -/// premise CCZ.U.CCZ = U exactly -- an identity in value AND phase -- so removing the -/// pair is bit-exact by construction (no phase census needed; contrast the M-60 -/// never-fire census, which had no identity and broke on the phase channel). -/// -/// Net-restore is decided by the SAME sound analysis (`control_net_restored`) the CCX -/// straddle path uses, applied to each of the three qubits. This pass does NOT cancel -/// CCX -- it treats every CCX as an opaque write -- so it is a conservative lower -/// bound on the straddle-restorable CCZ pairs, but every cancellation it makes is -/// sound. Intended to run on the FINAL post-`apply_m60_dead_t10` stream, so it never -/// perturbs the dead_t10 absolute-index skip-set. -pub(crate) fn ccz_straddle_cancel(ops: Vec) -> Vec { - let (num_q, num_b) = dims(&ops); - const OPAQUE: u32 = u32::MAX; - - let mut wev_q: Vec> = vec![Vec::new(); num_q]; - let mut wev_b: Vec> = vec![Vec::new(); num_b]; - let mut cond_epoch: u64 = 0; - let mut cond_stack: Vec = Vec::new(); - - #[derive(Clone, Copy)] - struct PendCcz { - idx: usize, - cb: u64, - epoch: u64, - } - let mut pending: std::collections::HashMap<(u64, u64, u64), PendCcz> = - std::collections::HashMap::new(); - let mut killed = vec![false; ops.len()]; - - let mut total_ccz = 0usize; // real (3-distinct-qubit) CCZ seen - let mut candidates = 0usize; // same-triple, same cond/epoch (pre net-restore) - let mut cancelled = 0usize; - - let push_q = |wev_q: &mut Vec>, q: u64, ev: WEvent| { - if (q as usize) < wev_q.len() { - wev_q[q as usize].push(ev); - } - }; - let push_b = |wev_b: &mut Vec>, b: u64, i: u32| { - if (b as usize) < wev_b.len() { - wev_b[b as usize].push(i); - } - }; - - for (i, op) in ops.iter().enumerate() { - let iu = i as u32; - let ep = cond_epoch as u32; - match op.kind { - OperationType::PushCondition => { - cond_epoch += 1; - cond_stack.push(op.c_condition.0); - } - OperationType::PopCondition => { - cond_epoch += 1; - cond_stack.pop(); - } - OperationType::CCZ => { - let mut tri = [op.q_control1.0, op.q_control2.0, op.q_target.0]; - tri.sort_unstable(); - if tri[2] != u64::MAX && tri[0] != tri[1] && tri[1] != tri[2] { - total_ccz += 1; - let key = (tri[0], tri[1], tri[2]); - let cb = op.c_condition.0; - let pend = pending.get(&key).copied(); - let mut did_cancel = false; - if let Some(p) = pend { - if p.cb == cb && p.epoch == cond_epoch { - candidates += 1; - let lo = p.idx as u32; - let qs_restored = tri.iter().all(|&q| { - control_net_restored( - q, p.idx, cond_epoch, &cond_stack, &wev_q, &wev_b, - ) - }); - let cond_ok = cb == u64::MAX - || !bit_written_between(&wev_b[cb as usize], lo, iu); - let stack_ok = cond_stack.iter().all(|&sb| { - sb == u64::MAX - || !bit_written_between(&wev_b[sb as usize], lo, iu) - }); - if qs_restored && cond_ok && stack_ok { - killed[p.idx] = true; - killed[i] = true; - did_cancel = true; - cancelled += 1; - } - } - } - if did_cancel { - pending.remove(&key); - } else { - pending.insert( - key, - PendCcz { - idx: i, - cb, - epoch: cond_epoch, - }, - ); - } - } - // CCZ is diagonal: writes nothing, records no write-event. - } - OperationType::CX => { - push_q( - &mut wev_q, - op.q_target.0, - WEvent { - idx: iu, - src: op.q_control1.0 as u32, - cond: op.c_condition.0 as u32, - epoch: ep, - }, - ); - } - OperationType::CCX - | OperationType::X - | OperationType::R => { - push_q( - &mut wev_q, - op.q_target.0, - WEvent { idx: iu, src: OPAQUE, cond: OPAQUE, epoch: ep }, - ); - } - OperationType::Swap => { - push_q( - &mut wev_q, - op.q_control1.0, - WEvent { idx: iu, src: OPAQUE, cond: OPAQUE, epoch: ep }, - ); - push_q( - &mut wev_q, - op.q_target.0, - WEvent { idx: iu, src: OPAQUE, cond: OPAQUE, epoch: ep }, - ); - } - OperationType::Hmr => { - push_q( - &mut wev_q, - op.q_target.0, - WEvent { idx: iu, src: OPAQUE, cond: OPAQUE, epoch: ep }, - ); - push_b(&mut wev_b, op.c_target.0, iu); - } - OperationType::BitInvert - | OperationType::BitStore0 - | OperationType::BitStore1 => { - push_b(&mut wev_b, op.c_target.0, iu); - } - OperationType::CZ - | OperationType::Z - | OperationType::Neg - | OperationType::Register - | OperationType::AppendToRegister - | OperationType::DebugPrint => {} - } - } - - let n_before = ops.len(); - let kept: Vec = ops - .into_iter() - .enumerate() - .filter_map(|(i, op)| if killed[i] { None } else { Some(op) }) - .collect(); - eprintln!( - " [W018 CCZ straddle] total_ccz={} same_triple_candidates={} cancelled_pairs={} removed_ccz={} -> {} ops", - total_ccz, - candidates, - cancelled, - n_before - kept.len(), - kept.len() - ); - kept -} - -/// DIRECT MEASUREMENT (corpus-independent): run the shipped, sound CCX self-inverse -/// matcher on the FINAL post-fanout / post-dead_t10 stream. The production constprop -/// pass runs BEFORE `single_ccx_fanout` and `apply_m60_dead_t10`, both of which rewrite -/// the stream afterward -- so any self-inverse CCX adjacencies those two passes create -/// have never been seen by a canceller. Every pair `find_inverse_pairs` returns is a -/// proven self-inverse (same controls/target, clean or net-restored between) -> removing -/// it is bit-exact. Gated OFF by default (`TLM_CCX_FINAL_CANCEL=1` to enable) so the -/// baseline op-stream is unchanged for differential comparison. `straddle=false` by -/// default = strict clean case only (definitely bit-exact); `TLM_CCX_FINAL_STRADDLE=1` -/// widens to net-restore (reuses the CCX straddle path). -pub(crate) fn ccx_final_cancel(ops: Vec) -> Vec { - if std::env::var("TLM_CCX_FINAL_CANCEL").ok().as_deref() != Some("1") { - return ops; - } - let (nq, nb) = dims(&ops); - let straddle = std::env::var("TLM_CCX_FINAL_STRADDLE").ok().as_deref() == Some("1"); - let (pairs, straddle_extra) = find_inverse_pairs(&ops, nq, nb, straddle); - let mut killed = vec![false; ops.len()]; - for p in &pairs { - killed[p.first] = true; - killed[p.second] = true; - } - let kept: Vec = ops - .into_iter() - .enumerate() - .filter_map(|(i, o)| if killed[i] { None } else { Some(o) }) - .collect(); - eprintln!( - " [FINAL CCX cancel] straddle={} pairs={} straddle_extra={} removed_ccx={} -> {} ops", - straddle, - pairs.len(), - straddle_extra, - pairs.len() * 2, - kept.len() - ); - kept -} - -pub fn run(ops: Vec, input_qubits: &[QubitId]) -> Vec { - let (num_q, num_b) = dims(&ops); - let nonces_verify = std::env::var("CONSTPROP_VERIFY") - .ok() - .and_then(|s| s.parse::().ok()); - - let verify_new_only = std::env::var("CONSTPROP_VERIFY_NEW_ONLY").ok().as_deref() == Some("1"); - - let straddle = std::env::var("TLM_CONSTPROP_STRADDLE").ok().as_deref() == Some("1"); - - let mut cur_sites = crate::point_add::take_op_site_trace_for_constprop(ops.len()); - let mut cur = ops; - let mut iter = 0usize; - let mut tot_dropped = 0usize; - let mut tot_folded_cx = 0usize; - let mut tot_folded_x = 0usize; - let mut tot_pairs = 0usize; - let mut tot_aff_drop = 0usize; - let mut tot_aff_fold = 0usize; - let mut tot_straddle_extra = 0usize; - let affine_disabled = std::env::var("CONSTPROP_AFFINE_DISABLE").ok().as_deref() == Some("1"); - let max_iters = std::env::var("CONSTPROP_MAX_ITERS") - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(16); - - loop { - iter += 1; - - let (mut decisions, stats) = analyze(&cur, num_q, num_b, input_qubits); - - if let Some(nonces) = nonces_verify { - if stats.dropped + stats.folded_cx + stats.folded_x > 0 - && !(verify_new_only && iter == 1) - { - let surviving = verify_control_constancy(&cur, &decisions, num_q, num_b, nonces); - let mut kept = 0usize; - let mut killed = 0usize; - for (i, ok) in surviving.iter().enumerate() { - if !matches!(decisions[i], Decision::Keep) { - if *ok { - kept += 1; - } else { - killed += 1; - decisions[i] = Decision::Keep; - } - } - } - eprintln!( - "CONSTPROP_VERIFY iter={} nonces={} shots_each=9024 transforms_static={} passed_empirical={} REVERTED_unsound={}", - iter, - nonces, - stats.dropped + stats.folded_cx + stats.folded_x, - kept, - killed - ); - } - } - - let cp_transforms = stats.dropped + stats.folded_cx + stats.folded_x; - tot_dropped += stats.dropped; - tot_folded_cx += stats.folded_cx; - tot_folded_x += stats.folded_x; - if let Some(sites) = cur_sites.as_mut() { - *sites = apply_site_decisions(sites, &decisions); - } - cur = apply_decisions(&cur, &decisions); - - let (nq2, nb2) = dims(&cur); - let (pairs, straddle_extra) = find_inverse_pairs(&cur, nq2, nb2, straddle); - tot_straddle_extra += straddle_extra; - if straddle && straddle_extra > 0 { - eprintln!( - "CONSTPROP_STRADDLE iter={} extra_pairs={} (extra toffoli removed = {})", - iter, straddle_extra, 2 * straddle_extra - ); - } - - if let Some(nonces) = nonces_verify { - if !pairs.is_empty() { - let bad = verify_inverse_pairs(&cur, &pairs, nq2, nb2, nonces); - eprintln!( - "CONSTPROP_PAIR_VERIFY iter={} nonces={} pairs={} UNSOUND_pairs={}", - iter, - nonces, - pairs.len(), - bad - ); - if bad != 0 { - panic!( - "INVERSE-PAIR CANCELLATION UNSOUND: {} of {} pairs failed empirical check", - bad, - pairs.len() - ); - } - } - } - - let pair_transforms = pairs.len(); - tot_pairs += pair_transforms; - if pair_transforms > 0 { - let mut kill = vec![false; cur.len()]; - for p in &pairs { - kill[p.first] = true; - kill[p.second] = true; - } - let mut out = Vec::with_capacity(cur.len() - 2 * pair_transforms); - for (i, op) in cur.iter().enumerate() { - if !kill[i] { - out.push(*op); - } - } - if let Some(sites) = cur_sites.as_mut() { - *sites = filter_sites(sites, &kill); - } - cur = out; - } - - let (mut aff_drop, mut aff_fold) = (0usize, 0usize); - if !affine_disabled { - let (nq3, nb3) = dims(&cur); - let (mut adec, fold_eq, drop_comp) = - analyze_affine(&cur, nq3, nb3, input_qubits); - - if let Some(nonces) = nonces_verify { - if fold_eq + drop_comp > 0 { - let surviving = - verify_affine_relations(&cur, &adec, nq3, nb3, nonces); - let mut killed = 0usize; - for (i, ok) in surviving.iter().enumerate() { - if matches!( - adec[i], - Decision::DropComplementCtrls { .. } - | Decision::FoldEqualCtrls { .. } - ) && !*ok - { - killed += 1; - adec[i] = Decision::Keep; - } - } - eprintln!( - "CONSTPROP_AFFINE_VERIFY iter={} nonces={} fold_eq={} drop_comp={} REVERTED_unsound={}", - iter, nonces, fold_eq, drop_comp, killed - ); - if killed != 0 { - panic!( - "AFFINE RELATION CLAIM UNSOUND: {} flagged CCX failed empirical check", - killed - ); - } - } - } - - for d in &adec { - match d { - Decision::DropComplementCtrls { .. } => aff_drop += 1, - Decision::FoldEqualCtrls { .. } => aff_fold += 1, - _ => {} - } - } - if aff_drop + aff_fold > 0 { - if let Some(sites) = cur_sites.as_mut() { - *sites = apply_site_decisions(sites, &adec); - } - cur = apply_decisions(&cur, &adec); - } - let _ = (fold_eq, drop_comp); - } - tot_aff_drop += aff_drop; - tot_aff_fold += aff_fold; - - eprintln!( - "CONSTPROP iter={} ccx_total={} dropped={} folded_cx={} folded_x={} inverse_pairs={} aff_drop={} aff_fold={} (this-iter toffoli removed = {})", - iter, - stats.ccx_total, - stats.dropped, - stats.folded_cx, - stats.folded_x, - pair_transforms, - aff_drop, - aff_fold, - cp_transforms + 2 * pair_transforms + aff_drop + aff_fold, - ); - - if cp_transforms == 0 && pair_transforms == 0 && aff_drop + aff_fold == 0 { - break; - } - if iter >= max_iters { - eprintln!("CONSTPROP reached max_iters={}, stopping", max_iters); - break; - } - } - - eprintln!( - "CONSTPROP TOTAL iters={} dropped={} folded_cx={} folded_x={} inverse_pairs={} aff_drop={} aff_fold={} (toffoli removed = {})", - iter, - tot_dropped, - tot_folded_cx, - tot_folded_x, - tot_pairs, - tot_aff_drop, - tot_aff_fold, - tot_dropped + tot_folded_cx + tot_folded_x + 2 * tot_pairs + tot_aff_drop + tot_aff_fold, - ); - if straddle { - eprintln!( - "CONSTPROP_STRADDLE TOTAL straddle_extra_pairs={} (of inverse_pairs={})", - tot_straddle_extra, tot_pairs - ); - } - - if let Some(sites) = cur_sites { - crate::point_add::set_op_site_trace_from_constprop(sites); - } - - cur -} - -fn dims(ops: &[Op]) -> (usize, usize) { - let mut nq = 0u64; - let mut nb = 0u64; - for op in ops { - for q in [op.q_control2, op.q_control1, op.q_target] { - if q != NO_QUBIT { - nq = nq.max(q.0 + 1); - } - } - for b in [op.c_target, op.c_condition] { - if b != NO_BIT { - nb = nb.max(b.0 + 1); - } - } - } - (nq as usize, nb as usize) -} - -fn verify_control_constancy( - ops: &[Op], - decisions: &[Decision], - num_q: usize, - num_b: usize, - nonces: usize, -) -> Vec { - use crate::circuit::{analyze_ops, QubitOrBit}; - use crate::sim::Simulator; - use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; - use alloy_primitives::U256; - use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; - - let curve = WeierstrassEllipticCurve { - modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), - a: U256::from(0u64), - b: U256::from(7u64), - gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), - gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), - order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), - }; - - let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); - assert_eq!(regs.len(), 4, "expected 4 IO registers"); - - let mut flagged: Vec<(usize, Vec<(QubitId, u64)>)> = Vec::new(); - for (i, d) in decisions.iter().enumerate() { - match *d { - Decision::Keep => {} - Decision::DropZeroCtrl { ctrl } => flagged.push((i, vec![(ctrl, 0)])), - Decision::FoldCx { one_ctrl, .. } => flagged.push((i, vec![(one_ctrl, 1)])), - Decision::FoldX { c1, c2 } => flagged.push((i, vec![(c1, 1), (c2, 1)])), - - Decision::DropComplementCtrls { .. } | Decision::FoldEqualCtrls { .. } => {} - } - } - let mut ok = vec![true; ops.len()]; - if flagged.is_empty() { - return ok; - } - - let mut flag_pos = vec![u32::MAX; ops.len()]; - for (p, (i, _)) in flagged.iter().enumerate() { - flag_pos[*i] = p as u32; - } - - const NUM_TESTS: usize = 9024; - const BATCH: usize = 64; - - for nonce in 0..nonces { - - let mut hasher = Shake256::default(); - hasher.update(b"quantum_ecc-fiat-shamir-v2"); - hasher.update(&(ops.len() as u64).to_le_bytes()); - - hasher.update(b"CONSTPROP_VERIFY"); - hasher.update(&(nonce as u64).to_le_bytes()); - let mut xof = hasher.finalize_xof(); - - let mut targets = Vec::new(); - let mut offsets = Vec::new(); - for _ in 0..NUM_TESTS { - let mut rb = [[0u8; 32]; 2]; - xof.read(&mut rb[0]); - xof.read(&mut rb[1]); - let k1 = U256::from_le_bytes(rb[0]); - let k2 = U256::from_le_bytes(rb[1]); - let t = curve.mul(curve.gx, curve.gy, k1); - let o = curve.mul(curve.gx, curve.gy, k2); - if t.0 == o.0 { continue; } - if t.0.is_zero() && t.1.is_zero() { continue; } - if o.0.is_zero() && o.1.is_zero() { continue; } - targets.push(t); - offsets.push(o); - } - let n = targets.len(); - let num_batches = (n + BATCH - 1) / BATCH; - - let mut sim = Simulator::new(num_q, num_b, &mut xof); - for batch in 0..num_batches { - let bs = BATCH.min(n - batch * BATCH); - sim.clear_for_shot(); - for shot in 0..bs { - let i = batch * BATCH + shot; - sim.set_register(®s[0], targets[i].0, shot); - sim.set_register(®s[1], targets[i].1, shot); - sim.set_register(®s[2], offsets[i].0, shot); - sim.set_register(®s[3], offsets[i].1, shot); - } - let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; - - step_and_check(&mut sim, ops, &flag_pos, &flagged, &mut ok, cond_mask); - } - let bad = ok.iter().filter(|b| !**b).count(); - eprintln!( - "CONSTPROP_PROGRESS nonce={}/{} shots={} cumulative_failed_claims={}", - nonce + 1, nonces, n, bad - ); - } - let _ = QubitOrBit::Bit; - ok -} - -fn step_and_check( - sim: &mut crate::sim::Simulator, - ops: &[Op], - flag_pos: &[u32], - flagged: &[(usize, Vec<(QubitId, u64)>)], - ok: &mut [bool], - cond_mask: u64, -) { - - let mut condition_stack: Vec = Vec::new(); - let mut current_base_condition = u64::MAX; - - for (idx, op) in ops.iter().enumerate() { - - let fp = flag_pos[idx]; - if fp != u32::MAX { - let p = fp as usize; - for &(qid, expected) in &flagged[p].1 { - let live = sim.qubit(qid) & cond_mask; - let claim_ok = if expected == 0 { - - live == 0 - } else { - - live == cond_mask - }; - if !claim_ok { - ok[idx] = false; - } - } - } - - let mut cond = current_base_condition; - if op.c_condition != NO_BIT { - cond &= sim.bit(op.c_condition); - } - match op.kind { - OperationType::CCX => { - let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::CX => { - let v = cond & sim.qubit(op.q_control1); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::Swap => { - let mut q_c1 = sim.qubit(op.q_control1); - let mut q_t = sim.qubit(op.q_target); - q_c1 ^= q_t; - q_t ^= cond & q_c1; - q_c1 ^= q_t; - *sim.qubit_mut(op.q_control1) = q_c1; - *sim.qubit_mut(op.q_target) = q_t; - } - OperationType::X => { - *sim.qubit_mut(op.q_target) ^= cond; - } - OperationType::CCZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - sim.phase ^= v; - } - OperationType::CZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); - sim.phase ^= v; - } - OperationType::Z => { - let v = cond & sim.qubit(op.q_target); - sim.phase ^= v; - } - OperationType::Neg => { - sim.phase ^= cond; - } - OperationType::Hmr => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - *sim.bit_mut(op.c_target) &= !cond; - *sim.bit_mut(op.c_target) ^= rng_val & cond; - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::R => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::BitInvert => { - *sim.bit_mut(op.c_target) ^= cond; - } - OperationType::BitStore0 => { - *sim.bit_mut(op.c_target) &= !cond; - } - OperationType::BitStore1 => { - *sim.bit_mut(op.c_target) |= cond; - } - OperationType::AppendToRegister - | OperationType::Register - | OperationType::DebugPrint => {} - OperationType::PushCondition => { - condition_stack.push(current_base_condition); - current_base_condition &= sim.bit(op.c_condition); - } - OperationType::PopCondition => { - if let Some(val) = condition_stack.pop() { - current_base_condition = val; - } - } - } - } -} - -#[cfg(test)] -mod affine_transfer_tests { - use super::*; - - fn gate(kind: OperationType, c1: u64, c2: u64, target: u64) -> Op { - let mut op = Op::empty(); - op.kind = kind; - op.q_control1 = QubitId(c1); - op.q_control2 = QubitId(c2); - op.q_target = QubitId(target); - op - } - - #[test] - fn closes_equal_and_complementary_chains_conservatively() { - let equal_chain = vec![ - gate(OperationType::CX, 0, u64::MAX, 1), - gate(OperationType::CCX, 0, 1, 2), - gate(OperationType::CCX, 2, 0, 3), - ]; - let (decisions, fold_eq, drop_comp) = - analyze_affine(&equal_chain, 4, 0, &[QubitId(0)]); - assert_eq!((fold_eq, drop_comp), (2, 0)); - assert!(matches!(decisions[1], Decision::FoldEqualCtrls { .. })); - assert!(matches!(decisions[2], Decision::FoldEqualCtrls { .. })); - - let complement_chain = vec![ - gate(OperationType::CX, 0, u64::MAX, 1), - gate(OperationType::X, u64::MAX, u64::MAX, 1), - gate(OperationType::CX, 0, u64::MAX, 2), - gate(OperationType::CCX, 0, 1, 2), - gate(OperationType::CCX, 2, 0, 3), - ]; - let (decisions, fold_eq, drop_comp) = - analyze_affine(&complement_chain, 4, 0, &[QubitId(0)]); - assert_eq!((fold_eq, drop_comp), (1, 1)); - assert!(matches!(decisions[3], Decision::DropComplementCtrls { .. })); - assert!(matches!(decisions[4], Decision::FoldEqualCtrls { .. })); - - let mut conditional = gate(OperationType::CCX, 0, 1, 2); - conditional.c_condition = BitId(0); - let conditional_chain = vec![ - gate(OperationType::CX, 0, u64::MAX, 1), - conditional, - gate(OperationType::CCX, 2, 0, 3), - ]; - let (decisions, fold_eq, drop_comp) = - analyze_affine(&conditional_chain, 4, 1, &[QubitId(0)]); - assert_eq!((fold_eq, drop_comp), (1, 0)); - assert!(matches!(decisions[1], Decision::FoldEqualCtrls { .. })); - assert!(matches!(decisions[2], Decision::Keep)); - } -} - -fn verify_inverse_pairs( - ops: &[Op], - pairs: &[PairKill], - num_q: usize, - num_b: usize, - nonces: usize, -) -> usize { - use crate::circuit::analyze_ops; - use crate::sim::Simulator; - use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; - use alloy_primitives::U256; - use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; - - let curve = WeierstrassEllipticCurve { - modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), - a: U256::from(0u64), - b: U256::from(7u64), - gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), - gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), - order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), - }; - - let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); - assert_eq!(regs.len(), 4, "expected 4 IO registers"); - - let mut endpoint: Vec = vec![u32::MAX; ops.len()]; - let mut is_first_at: Vec = vec![false; ops.len()]; - for (p, pk) in pairs.iter().enumerate() { - endpoint[pk.first] = p as u32; - is_first_at[pk.first] = true; - endpoint[pk.second] = p as u32; - is_first_at[pk.second] = false; - } - - let mut bad_pair = vec![false; pairs.len()]; - - const NUM_TESTS: usize = 9024; - const BATCH: usize = 64; - - for nonce in 0..nonces { - let mut hasher = Shake256::default(); - hasher.update(b"quantum_ecc-fiat-shamir-v2"); - hasher.update(&(ops.len() as u64).to_le_bytes()); - hasher.update(b"CONSTPROP_PAIR_VERIFY"); - hasher.update(&(nonce as u64).to_le_bytes()); - let mut xof = hasher.finalize_xof(); - - let mut targets = Vec::new(); - let mut offsets = Vec::new(); - for _ in 0..NUM_TESTS { - let mut rb = [[0u8; 32]; 2]; - xof.read(&mut rb[0]); - xof.read(&mut rb[1]); - let k1 = U256::from_le_bytes(rb[0]); - let k2 = U256::from_le_bytes(rb[1]); - let t = curve.mul(curve.gx, curve.gy, k1); - let o = curve.mul(curve.gx, curve.gy, k2); - if t.0 == o.0 { continue; } - if t.0.is_zero() && t.1.is_zero() { continue; } - if o.0.is_zero() && o.1.is_zero() { continue; } - targets.push(t); - offsets.push(o); - } - let n = targets.len(); - let num_batches = (n + BATCH - 1) / BATCH; - - let mut sim = Simulator::new(num_q, num_b, &mut xof); - - let mut snap_contrib = vec![0u64; pairs.len()]; - let mut snap_tgt = vec![0u64; pairs.len()]; - let mut snap_seen = vec![false; pairs.len()]; - - for batch in 0..num_batches { - let bs = BATCH.min(n - batch * BATCH); - sim.clear_for_shot(); - for shot in 0..bs { - let i = batch * BATCH + shot; - sim.set_register(®s[0], targets[i].0, shot); - sim.set_register(®s[1], targets[i].1, shot); - sim.set_register(®s[2], offsets[i].0, shot); - sim.set_register(®s[3], offsets[i].1, shot); - } - let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; - for s in snap_seen.iter_mut() { *s = false; } - - step_and_check_pairs( - &mut sim, - ops, - pairs, - &endpoint, - &is_first_at, - &mut snap_contrib, - &mut snap_tgt, - &mut snap_seen, - &mut bad_pair, - cond_mask, - ); - } - let bad = bad_pair.iter().filter(|b| **b).count(); - eprintln!( - "CONSTPROP_PAIR_PROGRESS nonce={}/{} shots={} cumulative_unsound_pairs={}", - nonce + 1, nonces, n, bad - ); - } - - bad_pair.iter().filter(|b| **b).count() -} - -fn step_and_check_pairs( - sim: &mut crate::sim::Simulator, - ops: &[Op], - pairs: &[PairKill], - endpoint: &[u32], - is_first_at: &[bool], - snap_contrib: &mut [u64], - snap_tgt: &mut [u64], - snap_seen: &mut [bool], - bad_pair: &mut [bool], - cond_mask: u64, -) { - let mut condition_stack: Vec = Vec::new(); - let mut current_base_condition = u64::MAX; - - for (idx, op) in ops.iter().enumerate() { - - let pp = endpoint[idx]; - if pp != u32::MAX { - let p = pp as usize; - - let mut cond = current_base_condition; - if op.c_condition != NO_BIT { - cond &= sim.bit(op.c_condition); - } - let a = op.q_control1; - let b = op.q_control2; - let t = op.q_target; - let contrib = (cond & sim.qubit(a) & sim.qubit(b)) & cond_mask; - let tgt = sim.qubit(t) & cond_mask; - if is_first_at[idx] { - snap_contrib[p] = contrib; - - snap_tgt[p] = tgt ^ contrib; - snap_seen[p] = true; - } else if snap_seen[p] { - if contrib != snap_contrib[p] || tgt != snap_tgt[p] { - bad_pair[p] = true; - } - } else { - - bad_pair[p] = true; - } - } - - let mut cond = current_base_condition; - if op.c_condition != NO_BIT { - cond &= sim.bit(op.c_condition); - } - match op.kind { - OperationType::CCX => { - let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::CX => { - let v = cond & sim.qubit(op.q_control1); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::Swap => { - let mut q_c1 = sim.qubit(op.q_control1); - let mut q_t = sim.qubit(op.q_target); - q_c1 ^= q_t; - q_t ^= cond & q_c1; - q_c1 ^= q_t; - *sim.qubit_mut(op.q_control1) = q_c1; - *sim.qubit_mut(op.q_target) = q_t; - } - OperationType::X => { - *sim.qubit_mut(op.q_target) ^= cond; - } - OperationType::CCZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - sim.phase ^= v; - } - OperationType::CZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); - sim.phase ^= v; - } - OperationType::Z => { - let v = cond & sim.qubit(op.q_target); - sim.phase ^= v; - } - OperationType::Neg => { - sim.phase ^= cond; - } - OperationType::Hmr => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - *sim.bit_mut(op.c_target) &= !cond; - *sim.bit_mut(op.c_target) ^= rng_val & cond; - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::R => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::BitInvert => { - *sim.bit_mut(op.c_target) ^= cond; - } - OperationType::BitStore0 => { - *sim.bit_mut(op.c_target) &= !cond; - } - OperationType::BitStore1 => { - *sim.bit_mut(op.c_target) |= cond; - } - OperationType::AppendToRegister - | OperationType::Register - | OperationType::DebugPrint => {} - OperationType::PushCondition => { - condition_stack.push(current_base_condition); - current_base_condition &= sim.bit(op.c_condition); - } - OperationType::PopCondition => { - if let Some(val) = condition_stack.pop() { - current_base_condition = val; - } - } - } - } - let _ = pairs; -} - -fn verify_affine_relations( - ops: &[Op], - decisions: &[Decision], - num_q: usize, - num_b: usize, - nonces: usize, -) -> Vec { - use crate::circuit::analyze_ops; - use crate::sim::Simulator; - use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; - use alloy_primitives::U256; - use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; - - let curve = WeierstrassEllipticCurve { - modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), - a: U256::from(0u64), - b: U256::from(7u64), - gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), - gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), - order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), - }; - - let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); - assert_eq!(regs.len(), 4, "expected 4 IO registers"); - - let mut want_equal = vec![false; ops.len()]; - let mut flagged_idx: Vec = Vec::new(); - let mut is_flagged = vec![false; ops.len()]; - for (i, d) in decisions.iter().enumerate() { - match *d { - Decision::FoldEqualCtrls { .. } => { - want_equal[i] = true; - is_flagged[i] = true; - flagged_idx.push(i); - } - Decision::DropComplementCtrls { .. } => { - want_equal[i] = false; - is_flagged[i] = true; - flagged_idx.push(i); - } - _ => {} - } - } - let mut ok = vec![true; ops.len()]; - if flagged_idx.is_empty() { - return ok; - } - - const NUM_TESTS: usize = 9024; - const BATCH: usize = 64; - - for nonce in 0..nonces { - let mut hasher = Shake256::default(); - hasher.update(b"quantum_ecc-fiat-shamir-v2"); - hasher.update(&(ops.len() as u64).to_le_bytes()); - hasher.update(b"CONSTPROP_AFFINE_VERIFY"); - hasher.update(&(nonce as u64).to_le_bytes()); - let mut xof = hasher.finalize_xof(); - - let mut targets = Vec::new(); - let mut offsets = Vec::new(); - for _ in 0..NUM_TESTS { - let mut rb = [[0u8; 32]; 2]; - xof.read(&mut rb[0]); - xof.read(&mut rb[1]); - let k1 = U256::from_le_bytes(rb[0]); - let k2 = U256::from_le_bytes(rb[1]); - let t = curve.mul(curve.gx, curve.gy, k1); - let o = curve.mul(curve.gx, curve.gy, k2); - if t.0 == o.0 { continue; } - if t.0.is_zero() && t.1.is_zero() { continue; } - if o.0.is_zero() && o.1.is_zero() { continue; } - targets.push(t); - offsets.push(o); - } - let n = targets.len(); - let num_batches = (n + BATCH - 1) / BATCH; - - let mut sim = Simulator::new(num_q, num_b, &mut xof); - for batch in 0..num_batches { - let bs = BATCH.min(n - batch * BATCH); - sim.clear_for_shot(); - for shot in 0..bs { - let i = batch * BATCH + shot; - sim.set_register(®s[0], targets[i].0, shot); - sim.set_register(®s[1], targets[i].1, shot); - sim.set_register(®s[2], offsets[i].0, shot); - sim.set_register(®s[3], offsets[i].1, shot); - } - let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; - step_and_check_affine( - &mut sim, - ops, - &is_flagged, - &want_equal, - &mut ok, - cond_mask, - ); - } - let bad = flagged_idx.iter().filter(|&&i| !ok[i]).count(); - eprintln!( - "CONSTPROP_AFFINE_PROGRESS nonce={}/{} shots={} cumulative_failed_claims={}", - nonce + 1, nonces, n, bad - ); - } - ok -} - -fn step_and_check_affine( - sim: &mut crate::sim::Simulator, - ops: &[Op], - is_flagged: &[bool], - want_equal: &[bool], - ok: &mut [bool], - cond_mask: u64, -) { - let mut condition_stack: Vec = Vec::new(); - let mut current_base_condition = u64::MAX; - - for (idx, op) in ops.iter().enumerate() { - if is_flagged[idx] { - - let va = sim.qubit(op.q_control1) & cond_mask; - let vb = sim.qubit(op.q_control2) & cond_mask; - let claim_ok = if want_equal[idx] { - va == vb - } else { - (va ^ vb) == cond_mask - }; - if !claim_ok { - ok[idx] = false; - } - } - - let mut cond = current_base_condition; - if op.c_condition != NO_BIT { - cond &= sim.bit(op.c_condition); - } - match op.kind { - OperationType::CCX => { - let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::CX => { - let v = cond & sim.qubit(op.q_control1); - *sim.qubit_mut(op.q_target) ^= v; - } - OperationType::Swap => { - let mut q_c1 = sim.qubit(op.q_control1); - let mut q_t = sim.qubit(op.q_target); - q_c1 ^= q_t; - q_t ^= cond & q_c1; - q_c1 ^= q_t; - *sim.qubit_mut(op.q_control1) = q_c1; - *sim.qubit_mut(op.q_target) = q_t; - } - OperationType::X => { - *sim.qubit_mut(op.q_target) ^= cond; - } - OperationType::CCZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); - sim.phase ^= v; - } - OperationType::CZ => { - let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); - sim.phase ^= v; - } - OperationType::Z => { - let v = cond & sim.qubit(op.q_target); - sim.phase ^= v; - } - OperationType::Neg => { - sim.phase ^= cond; - } - OperationType::Hmr => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - *sim.bit_mut(op.c_target) &= !cond; - *sim.bit_mut(op.c_target) ^= rng_val & cond; - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::R => { - let mut buf = [0u8; 8]; - sim.xof.read(&mut buf); - let rng_val = u64::from_le_bytes(buf); - sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; - *sim.qubit_mut(op.q_target) &= !cond; - } - OperationType::BitInvert => { - *sim.bit_mut(op.c_target) ^= cond; - } - OperationType::BitStore0 => { - *sim.bit_mut(op.c_target) &= !cond; - } - OperationType::BitStore1 => { - *sim.bit_mut(op.c_target) |= cond; - } - OperationType::AppendToRegister - | OperationType::Register - | OperationType::DebugPrint => {} - OperationType::PushCondition => { - condition_stack.push(current_base_condition); - current_base_condition &= sim.bit(op.c_condition); - } - OperationType::PopCondition => { - if let Some(val) = condition_stack.pop() { - current_base_condition = val; - } - } - } - } -} + +use crate::circuit::{BitId, NO_BIT, NO_QUBIT, Op, OperationType, QubitId}; +use crate::point_add::OpSite; + +const NEVER: usize = usize::MAX; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum Val { + Zero, + One, + Unknown, +} + +use Val::*; + +#[derive(Clone, Copy, Debug, Default)] +pub struct ConstPropStats { + pub ccx_total: usize, + pub dropped: usize, + pub folded_cx: usize, + pub folded_x: usize, +} + +#[derive(Clone, Copy, Debug)] +enum Decision { + + Keep, + + DropZeroCtrl { ctrl: QubitId }, + + FoldCx { one_ctrl: QubitId, keep_ctrl: QubitId }, + + FoldX { c1: QubitId, c2: QubitId }, + + DropComplementCtrls { a: QubitId, b: QubitId }, + + FoldEqualCtrls { a: QubitId, b: QubitId, keep_ctrl: QubitId }, +} + +struct Analyzer { + q: Vec, + b: Vec, + + cond_stack: Vec, +} + +impl Analyzer { + fn qv(&self, id: QubitId) -> Val { + if id == NO_QUBIT { Unknown } else { self.q[id.0 as usize] } + } + fn bv(&self, id: BitId) -> Val { + if id == NO_BIT { Unknown } else { self.b[id.0 as usize] } + } + fn set_q(&mut self, id: QubitId, v: Val) { + self.q[id.0 as usize] = v; + } + fn set_b(&mut self, id: BitId, v: Val) { + self.b[id.0 as usize] = v; + } + + fn cond_always_true(&self, op: &Op) -> bool { + for &c in &self.cond_stack { + if self.bv(c) != One { + return false; + } + } + if op.c_condition != NO_BIT && self.bv(op.c_condition) != One { + return false; + } + true + } + + fn cond_maybe_false(&self, op: &Op) -> bool { + !self.cond_always_true(op) + } +} + +fn xor_val(a: Val, b: Val) -> Val { + match (a, b) { + (Zero, x) | (x, Zero) => x, + (One, One) => Zero, + _ => Unknown, + } +} + +fn and_val(a: Val, b: Val) -> Val { + match (a, b) { + (Zero, _) | (_, Zero) => Zero, + (One, One) => One, + _ => Unknown, + } +} + +fn merge(old: Val, new: Val) -> Val { + if old == new { old } else { Unknown } +} + +fn analyze(ops: &[Op], num_q: usize, num_b: usize, input_qubits: &[QubitId]) -> (Vec, ConstPropStats) { + let mut a = Analyzer { + q: vec![Zero; num_q], + b: vec![Zero; num_b], + cond_stack: Vec::new(), + }; + for &q in input_qubits { + a.q[q.0 as usize] = Unknown; + } + + let mut decisions = vec![Decision::Keep; ops.len()]; + let mut stats = ConstPropStats::default(); + + for (i, op) in ops.iter().enumerate() { + match op.kind { + OperationType::PushCondition => { + a.cond_stack.push(op.c_condition); + } + OperationType::PopCondition => { + a.cond_stack.pop(); + } + OperationType::CCX => { + stats.ccx_total += 1; + let c1 = a.qv(op.q_control1); + let c2 = a.qv(op.q_control2); + + if c1 == Zero { + decisions[i] = Decision::DropZeroCtrl { ctrl: op.q_control1 }; + stats.dropped += 1; + + } else if c2 == Zero { + decisions[i] = Decision::DropZeroCtrl { ctrl: op.q_control2 }; + stats.dropped += 1; + + } else if c1 == One && c2 == One { + decisions[i] = Decision::FoldX { c1: op.q_control1, c2: op.q_control2 }; + stats.folded_x += 1; + + let tgt = a.qv(op.q_target); + let nv = xor_val(tgt, One); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } else if c1 == One { + decisions[i] = Decision::FoldCx { one_ctrl: op.q_control1, keep_ctrl: op.q_control2 }; + stats.folded_cx += 1; + + let tgt = a.qv(op.q_target); + let delta = c2; + let nv = xor_val(tgt, delta); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } else if c2 == One { + decisions[i] = Decision::FoldCx { one_ctrl: op.q_control2, keep_ctrl: op.q_control1 }; + stats.folded_cx += 1; + let tgt = a.qv(op.q_target); + let delta = c1; + let nv = xor_val(tgt, delta); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } else { + + let delta = and_val(c1, c2); + let tgt = a.qv(op.q_target); + let nv = xor_val(tgt, delta); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } + } + OperationType::CX => { + let ctrl = a.qv(op.q_control1); + let tgt = a.qv(op.q_target); + let nv = xor_val(tgt, ctrl); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } + OperationType::X => { + let tgt = a.qv(op.q_target); + let nv = xor_val(tgt, One); + let res = if a.cond_maybe_false(op) { merge(tgt, nv) } else { nv }; + a.set_q(op.q_target, res); + } + OperationType::Swap => { + + let va = a.qv(op.q_control1); + let vt = a.qv(op.q_target); + if a.cond_maybe_false(op) { + + a.set_q(op.q_control1, merge(va, vt)); + a.set_q(op.q_target, merge(vt, va)); + } else { + a.set_q(op.q_control1, vt); + a.set_q(op.q_target, va); + } + } + OperationType::R => { + + let tgt = a.qv(op.q_target); + let res = if a.cond_maybe_false(op) { merge(tgt, Zero) } else { Zero }; + a.set_q(op.q_target, res); + } + OperationType::Hmr => { + + let res = if a.cond_maybe_false(op) { + merge(a.bv(op.c_target), Unknown) + } else { + Unknown + }; + a.set_b(op.c_target, res); + let tgt = a.qv(op.q_target); + let qres = if a.cond_maybe_false(op) { merge(tgt, Zero) } else { Zero }; + a.set_q(op.q_target, qres); + } + OperationType::BitStore0 => { + let cur = a.bv(op.c_target); + let res = if a.cond_maybe_false(op) { merge(cur, Zero) } else { Zero }; + a.set_b(op.c_target, res); + } + OperationType::BitStore1 => { + let cur = a.bv(op.c_target); + let res = if a.cond_maybe_false(op) { merge(cur, One) } else { One }; + a.set_b(op.c_target, res); + } + OperationType::BitInvert => { + let cur = a.bv(op.c_target); + let nv = xor_val(cur, One); + let res = if a.cond_maybe_false(op) { merge(cur, nv) } else { nv }; + a.set_b(op.c_target, res); + } + + OperationType::Z + | OperationType::CZ + | OperationType::CCZ + | OperationType::Neg + | OperationType::Register + | OperationType::AppendToRegister + | OperationType::DebugPrint => {} + } + } + + (decisions, stats) +} + +const CAP_SET: usize = 2048; + +struct Affine { + cst: Vec, + set: Vec>, + nextvar: u32, + cond_stack: Vec, + + b: Vec, +} + +fn xor_set(a: &[u32], b: &[u32]) -> Vec { + let mut out = Vec::with_capacity(a.len() + b.len()); + let (mut i, mut j) = (0usize, 0usize); + while i < a.len() && j < b.len() { + if a[i] < b[j] { + out.push(a[i]); + i += 1; + } else if a[i] > b[j] { + out.push(b[j]); + j += 1; + } else { + i += 1; + j += 1; + } + } + out.extend_from_slice(&a[i..]); + out.extend_from_slice(&b[j..]); + out +} + +impl Affine { + fn fresh(&mut self) -> Vec { + let v = self.nextvar; + self.nextvar += 1; + vec![v] + } + fn bv(&self, id: BitId) -> Val { + if id == NO_BIT { Unknown } else { self.b[id.0 as usize] } + } + + fn cond_maybe_false(&self, op: &Op) -> bool { + for &c in &self.cond_stack { + if self.bv(c) != One { + return true; + } + } + if op.c_condition != NO_BIT && self.bv(op.c_condition) != One { + return true; + } + false + } +} + +fn analyze_affine( + ops: &[Op], + num_q: usize, + num_b: usize, + input_qubits: &[QubitId], +) -> (Vec, usize, usize) { + + let mut af = Affine { + cst: vec![false; num_q], + set: vec![Vec::new(); num_q], + nextvar: 0, + cond_stack: Vec::new(), + b: vec![Unknown; num_b], + }; + for &q in input_qubits { + let v = af.fresh(); + af.set[q.0 as usize] = v; + } + + let mut decisions = vec![Decision::Keep; ops.len()]; + let mut fold_eq = 0usize; + let mut drop_comp = 0usize; + + for (i, op) in ops.iter().enumerate() { + match op.kind { + OperationType::PushCondition => af.cond_stack.push(op.c_condition), + OperationType::PopCondition => { + af.cond_stack.pop(); + } + OperationType::X => { + let t = op.q_target.0 as usize; + if af.cond_maybe_false(op) { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + af.cst[t] ^= true; + } + } + OperationType::CX => { + let c = op.q_control1.0 as usize; + let t = op.q_target.0 as usize; + if af.cond_maybe_false(op) { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + let ns = xor_set(&af.set[t], &af.set[c]); + af.cst[t] ^= af.cst[c]; + if ns.len() > CAP_SET { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + af.set[t] = ns; + } + } + } + OperationType::CCX => { + let a = op.q_control1.0 as usize; + let b = op.q_control2.0 as usize; + let t = op.q_target.0 as usize; + + if af.set[a] == af.set[b] { + if af.cst[a] == af.cst[b] { + decisions[i] = Decision::FoldEqualCtrls { + a: op.q_control1, + b: op.q_control2, + keep_ctrl: op.q_control1, + }; + fold_eq += 1; + + if af.cond_maybe_false(op) { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + let ns = xor_set(&af.set[t], &af.set[a]); + af.cst[t] ^= af.cst[a]; + if ns.len() > CAP_SET { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + af.set[t] = ns; + } + } + } else { + decisions[i] = Decision::DropComplementCtrls { + a: op.q_control1, + b: op.q_control2, + }; + drop_comp += 1; + + } + } else { + + af.set[t] = af.fresh(); + af.cst[t] = false; + } + } + OperationType::Swap => { + let x = op.q_control1.0 as usize; + let y = op.q_target.0 as usize; + if af.cond_maybe_false(op) { + af.set[x] = af.fresh(); + af.cst[x] = false; + af.set[y] = af.fresh(); + af.cst[y] = false; + } else { + af.set.swap(x, y); + af.cst.swap(x, y); + } + } + OperationType::R => { + let t = op.q_target.0 as usize; + if af.cond_maybe_false(op) { + af.set[t] = af.fresh(); + af.cst[t] = false; + } else { + af.set[t] = Vec::new(); + af.cst[t] = false; + } + } + OperationType::Hmr => { + let t = op.q_target.0 as usize; + af.set[t] = af.fresh(); + af.cst[t] = false; + if op.c_target != NO_BIT { + af.b[op.c_target.0 as usize] = Unknown; + } + } + + OperationType::BitStore0 => { + if op.c_target != NO_BIT { + let cur = af.bv(op.c_target); + af.b[op.c_target.0 as usize] = + if af.cond_maybe_false(op) { merge(cur, Zero) } else { Zero }; + } + } + OperationType::BitStore1 => { + if op.c_target != NO_BIT { + let cur = af.bv(op.c_target); + af.b[op.c_target.0 as usize] = + if af.cond_maybe_false(op) { merge(cur, One) } else { One }; + } + } + OperationType::BitInvert => { + if op.c_target != NO_BIT { + let cur = af.bv(op.c_target); + let nv = xor_val(cur, One); + af.b[op.c_target.0 as usize] = + if af.cond_maybe_false(op) { merge(cur, nv) } else { nv }; + } + } + + OperationType::Z + | OperationType::CZ + | OperationType::CCZ + | OperationType::Neg + | OperationType::Register + | OperationType::AppendToRegister + | OperationType::DebugPrint => {} + } + } + + (decisions, fold_eq, drop_comp) +} + +fn apply_decisions(ops: &[Op], decisions: &[Decision]) -> Vec { + let mut out = Vec::with_capacity(ops.len()); + for (i, op) in ops.iter().enumerate() { + match decisions[i] { + Decision::Keep => out.push(*op), + Decision::DropZeroCtrl { .. } => { } + Decision::FoldCx { keep_ctrl, .. } => { + let mut nop = Op::empty(); + nop.kind = OperationType::CX; + nop.q_control1 = keep_ctrl; + nop.q_target = op.q_target; + nop.c_condition = op.c_condition; + out.push(nop); + } + Decision::FoldX { .. } => { + let mut nop = Op::empty(); + nop.kind = OperationType::X; + nop.q_target = op.q_target; + nop.c_condition = op.c_condition; + out.push(nop); + } + Decision::DropComplementCtrls { .. } => { } + Decision::FoldEqualCtrls { keep_ctrl, .. } => { + + let mut nop = Op::empty(); + nop.kind = OperationType::CX; + nop.q_control1 = keep_ctrl; + nop.q_target = op.q_target; + nop.c_condition = op.c_condition; + out.push(nop); + } + } + } + out +} + +fn apply_site_decisions(sites: &[OpSite], decisions: &[Decision]) -> Vec { + let mut out = Vec::with_capacity(sites.len()); + for (i, site) in sites.iter().copied().enumerate() { + match decisions[i] { + Decision::Keep + | Decision::FoldCx { .. } + | Decision::FoldX { .. } + | Decision::FoldEqualCtrls { .. } => out.push(site), + Decision::DropZeroCtrl { .. } | Decision::DropComplementCtrls { .. } => {} + } + } + out +} + +fn filter_sites(sites: &[OpSite], kill: &[bool]) -> Vec { + sites + .iter() + .copied() + .enumerate() + .filter_map(|(i, site)| (!kill[i]).then_some(site)) + .collect() +} + +#[derive(Clone, Copy, Debug)] +struct PairKill { + first: usize, + second: usize, +} + +#[derive(Clone, Copy)] +struct WEvent { + idx: u32, + src: u32, + cond: u32, + epoch: u32, +} + +#[inline] +fn wev_written_between(ev: &[WEvent], lo: u32, hi: u32) -> bool { + if hi <= lo + 1 { + return false; + } + let start = ev.partition_point(|e| e.idx <= lo); + start < ev.len() && ev[start].idx < hi +} + +#[inline] +fn bit_written_between(ev: &[u32], lo: u32, hi: u32) -> bool { + if hi <= lo + 1 { + return false; + } + let start = ev.partition_point(|&x| x <= lo); + start < ev.len() && ev[start] < hi +} + +fn control_net_restored( + ctrl: u64, + p_idx: usize, + cur_epoch: u64, + cond_stack: &[u64], + wev_q: &[Vec], + wev_b: &[Vec], +) -> bool { + let events = &wev_q[ctrl as usize]; + let p = p_idx as u32; + let start = events.partition_point(|e| e.idx <= p); + let suffix = &events[start..]; + if suffix.is_empty() { + return true; + } + let mut stack: Vec = Vec::new(); + for &e in suffix { + if e.src != u32::MAX { + if let Some(&top) = stack.last() { + + let same = top.src == e.src + && top.cond == e.cond + && top.epoch == e.epoch + && e.epoch as u64 == cur_epoch; + if same { + let src_ok = + !wev_written_between(&wev_q[e.src as usize], top.idx, e.idx); + let cond_ok = e.cond == u32::MAX + || !bit_written_between(&wev_b[e.cond as usize], top.idx, e.idx); + let stack_ok = cond_stack.iter().all(|&sb| { + sb == u64::MAX + || !bit_written_between(&wev_b[sb as usize], top.idx, e.idx) + }); + if src_ok && cond_ok && stack_ok { + stack.pop(); + continue; + } + } + } + } + stack.push(e); + } + stack.is_empty() +} + +fn find_inverse_pairs( + ops: &[Op], + num_q: usize, + num_b: usize, + straddle: bool, +) -> (Vec, usize) { + + let mut wlast_q = vec![usize::MAX; num_q]; + let mut rlast_q = vec![usize::MAX; num_q]; + let mut wlast_b = vec![usize::MAX; num_b]; + + for v in wlast_q.iter_mut() { *v = NEVER; } + for v in rlast_q.iter_mut() { *v = NEVER; } + for v in wlast_b.iter_mut() { *v = NEVER; } + + #[derive(Clone, Copy)] + struct Pending { + idx: usize, + a: u64, + b: u64, + cb: u64, + epoch: u64, + } + let mut pending: Vec> = vec![None; num_q]; + + let mut cond_epoch: u64 = 0; + + let mut cond_stack: Vec = Vec::new(); + let mut killed = vec![false; ops.len()]; + let mut pairs = Vec::new(); + + let mut wev_q: Vec> = if straddle { + vec![Vec::new(); num_q] + } else { + Vec::new() + }; + let mut wev_b: Vec> = if straddle { + vec![Vec::new(); num_b] + } else { + Vec::new() + }; + + let mut straddle_extra = 0usize; + + #[inline] + fn touched_after(s: usize, p: usize) -> bool { + s != NEVER && s > p + } + + for (i, op) in ops.iter().enumerate() { + match op.kind { + OperationType::PushCondition => { + cond_epoch += 1; + cond_stack.push(op.c_condition.0); + } + OperationType::PopCondition => { + cond_epoch += 1; + cond_stack.pop(); + } + OperationType::CCX => { + let c1 = op.q_control1.0; + let c2 = op.q_control2.0; + let t = op.q_target.0; + let (a, b) = if c1 <= c2 { (c1, c2) } else { (c2, c1) }; + let cb = op.c_condition.0; + + let mut cancelled = false; + if let Some(p) = pending[t as usize] { + let same_gate = p.a == a && p.b == b && p.cb == cb; + let same_epoch = p.epoch == cond_epoch; + + let ctrls_clean = !touched_after(wlast_q[a as usize], p.idx) + && !touched_after(wlast_q[b as usize], p.idx); + + let ctrls_ok = if ctrls_clean { + true + } else if straddle { + control_net_restored(a, p.idx, cond_epoch, &cond_stack, &wev_q, &wev_b) + && control_net_restored( + b, p.idx, cond_epoch, &cond_stack, &wev_q, &wev_b, + ) + } else { + false + }; + let tgt_clean = !touched_after(wlast_q[t as usize], p.idx) + && !touched_after(rlast_q[t as usize], p.idx); + let cond_clean = cb == u64::MAX + || !touched_after(wlast_b[cb as usize], p.idx); + + let stack_clean = same_epoch + && cond_stack + .iter() + .all(|&sb| sb == u64::MAX || !touched_after(wlast_b[sb as usize], p.idx)); + if same_gate && same_epoch && ctrls_ok && tgt_clean && cond_clean && stack_clean { + killed[p.idx] = true; + killed[i] = true; + pairs.push(PairKill { first: p.idx, second: i }); + pending[t as usize] = None; + cancelled = true; + if !ctrls_clean { + straddle_extra += 1; + } + } + } + + if !cancelled { + + rlast_q[a as usize] = i; + rlast_q[b as usize] = i; + wlast_q[t as usize] = i; + if cb != u64::MAX { + + } + if straddle { + + wev_q[t as usize].push(WEvent { + idx: i as u32, + src: u32::MAX, + cond: u32::MAX, + epoch: cond_epoch as u32, + }); + } + pending[t as usize] = Some(Pending { + idx: i, + a, + b, + cb, + epoch: cond_epoch, + }); + } else { + + } + } + OperationType::CX => { + rlast_q[op.q_control1.0 as usize] = i; + wlast_q[op.q_target.0 as usize] = i; + pending[op.q_target.0 as usize] = None; + if straddle { + + wev_q[op.q_target.0 as usize].push(WEvent { + idx: i as u32, + src: op.q_control1.0 as u32, + cond: op.c_condition.0 as u32, + epoch: cond_epoch as u32, + }); + } + } + OperationType::X => { + wlast_q[op.q_target.0 as usize] = i; + pending[op.q_target.0 as usize] = None; + if straddle { + + wev_q[op.q_target.0 as usize].push(WEvent { + idx: i as u32, + src: u32::MAX, + cond: u32::MAX, + epoch: cond_epoch as u32, + }); + } + } + OperationType::Swap => { + let x = op.q_control1.0 as usize; + let y = op.q_target.0 as usize; + rlast_q[x] = i; rlast_q[y] = i; + wlast_q[x] = i; wlast_q[y] = i; + pending[x] = None; + pending[y] = None; + if straddle { + wev_q[x].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); + wev_q[y].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); + } + } + OperationType::R => { + wlast_q[op.q_target.0 as usize] = i; + pending[op.q_target.0 as usize] = None; + if straddle { + wev_q[op.q_target.0 as usize].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); + } + } + OperationType::Hmr => { + wlast_q[op.q_target.0 as usize] = i; + if op.c_target.0 != u64::MAX { wlast_b[op.c_target.0 as usize] = i; } + pending[op.q_target.0 as usize] = None; + if straddle { + wev_q[op.q_target.0 as usize].push(WEvent { idx: i as u32, src: u32::MAX, cond: u32::MAX, epoch: cond_epoch as u32 }); + if op.c_target.0 != u64::MAX { wev_b[op.c_target.0 as usize].push(i as u32); } + } + } + OperationType::CCZ => { + + rlast_q[op.q_control1.0 as usize] = i; + rlast_q[op.q_control2.0 as usize] = i; + rlast_q[op.q_target.0 as usize] = i; + } + OperationType::CZ => { + rlast_q[op.q_control1.0 as usize] = i; + rlast_q[op.q_target.0 as usize] = i; + } + OperationType::Z => { + rlast_q[op.q_target.0 as usize] = i; + } + OperationType::BitInvert + | OperationType::BitStore0 + | OperationType::BitStore1 => { + if op.c_target.0 != u64::MAX { wlast_b[op.c_target.0 as usize] = i; } + if straddle && op.c_target.0 != u64::MAX { + wev_b[op.c_target.0 as usize].push(i as u32); + } + } + OperationType::Neg + | OperationType::Register + | OperationType::AppendToRegister + | OperationType::DebugPrint => {} + } + } + + (pairs, straddle_extra) +} + +pub fn run(ops: Vec, input_qubits: &[QubitId]) -> Vec { + let (num_q, num_b) = dims(&ops); + let nonces_verify = std::env::var("CONSTPROP_VERIFY") + .ok() + .and_then(|s| s.parse::().ok()); + + let verify_new_only = std::env::var("CONSTPROP_VERIFY_NEW_ONLY").ok().as_deref() == Some("1"); + + let straddle = std::env::var("TLM_CONSTPROP_STRADDLE").ok().as_deref() == Some("1"); + + let mut cur_sites = crate::point_add::take_op_site_trace_for_constprop(ops.len()); + let mut cur = ops; + let mut iter = 0usize; + let mut tot_dropped = 0usize; + let mut tot_folded_cx = 0usize; + let mut tot_folded_x = 0usize; + let mut tot_pairs = 0usize; + let mut tot_aff_drop = 0usize; + let mut tot_aff_fold = 0usize; + let mut tot_straddle_extra = 0usize; + let affine_disabled = std::env::var("CONSTPROP_AFFINE_DISABLE").ok().as_deref() == Some("1"); + let max_iters = std::env::var("CONSTPROP_MAX_ITERS") + .ok() + .and_then(|s| s.parse::().ok()) + .unwrap_or(16); + + loop { + iter += 1; + + let (mut decisions, stats) = analyze(&cur, num_q, num_b, input_qubits); + + if let Some(nonces) = nonces_verify { + if stats.dropped + stats.folded_cx + stats.folded_x > 0 + && !(verify_new_only && iter == 1) + { + let surviving = verify_control_constancy(&cur, &decisions, num_q, num_b, nonces); + let mut kept = 0usize; + let mut killed = 0usize; + for (i, ok) in surviving.iter().enumerate() { + if !matches!(decisions[i], Decision::Keep) { + if *ok { + kept += 1; + } else { + killed += 1; + decisions[i] = Decision::Keep; + } + } + } + eprintln!( + "CONSTPROP_VERIFY iter={} nonces={} shots_each=9024 transforms_static={} passed_empirical={} REVERTED_unsound={}", + iter, + nonces, + stats.dropped + stats.folded_cx + stats.folded_x, + kept, + killed + ); + } + } + + let cp_transforms = stats.dropped + stats.folded_cx + stats.folded_x; + tot_dropped += stats.dropped; + tot_folded_cx += stats.folded_cx; + tot_folded_x += stats.folded_x; + if let Some(sites) = cur_sites.as_mut() { + *sites = apply_site_decisions(sites, &decisions); + } + cur = apply_decisions(&cur, &decisions); + + let (nq2, nb2) = dims(&cur); + let (pairs, straddle_extra) = find_inverse_pairs(&cur, nq2, nb2, straddle); + tot_straddle_extra += straddle_extra; + if straddle && straddle_extra > 0 { + eprintln!( + "CONSTPROP_STRADDLE iter={} extra_pairs={} (extra toffoli removed = {})", + iter, straddle_extra, 2 * straddle_extra + ); + } + + if let Some(nonces) = nonces_verify { + if !pairs.is_empty() { + let bad = verify_inverse_pairs(&cur, &pairs, nq2, nb2, nonces); + eprintln!( + "CONSTPROP_PAIR_VERIFY iter={} nonces={} pairs={} UNSOUND_pairs={}", + iter, + nonces, + pairs.len(), + bad + ); + if bad != 0 { + panic!( + "INVERSE-PAIR CANCELLATION UNSOUND: {} of {} pairs failed empirical check", + bad, + pairs.len() + ); + } + } + } + + let pair_transforms = pairs.len(); + tot_pairs += pair_transforms; + if pair_transforms > 0 { + let mut kill = vec![false; cur.len()]; + for p in &pairs { + kill[p.first] = true; + kill[p.second] = true; + } + let mut out = Vec::with_capacity(cur.len() - 2 * pair_transforms); + for (i, op) in cur.iter().enumerate() { + if !kill[i] { + out.push(*op); + } + } + if let Some(sites) = cur_sites.as_mut() { + *sites = filter_sites(sites, &kill); + } + cur = out; + } + + let (mut aff_drop, mut aff_fold) = (0usize, 0usize); + if !affine_disabled { + let (nq3, nb3) = dims(&cur); + let (mut adec, fold_eq, drop_comp) = + analyze_affine(&cur, nq3, nb3, input_qubits); + + if let Some(nonces) = nonces_verify { + if fold_eq + drop_comp > 0 { + let surviving = + verify_affine_relations(&cur, &adec, nq3, nb3, nonces); + let mut killed = 0usize; + for (i, ok) in surviving.iter().enumerate() { + if matches!( + adec[i], + Decision::DropComplementCtrls { .. } + | Decision::FoldEqualCtrls { .. } + ) && !*ok + { + killed += 1; + adec[i] = Decision::Keep; + } + } + eprintln!( + "CONSTPROP_AFFINE_VERIFY iter={} nonces={} fold_eq={} drop_comp={} REVERTED_unsound={}", + iter, nonces, fold_eq, drop_comp, killed + ); + if killed != 0 { + panic!( + "AFFINE RELATION CLAIM UNSOUND: {} flagged CCX failed empirical check", + killed + ); + } + } + } + + for d in &adec { + match d { + Decision::DropComplementCtrls { .. } => aff_drop += 1, + Decision::FoldEqualCtrls { .. } => aff_fold += 1, + _ => {} + } + } + if aff_drop + aff_fold > 0 { + if let Some(sites) = cur_sites.as_mut() { + *sites = apply_site_decisions(sites, &adec); + } + cur = apply_decisions(&cur, &adec); + } + let _ = (fold_eq, drop_comp); + } + tot_aff_drop += aff_drop; + tot_aff_fold += aff_fold; + + eprintln!( + "CONSTPROP iter={} ccx_total={} dropped={} folded_cx={} folded_x={} inverse_pairs={} aff_drop={} aff_fold={} (this-iter toffoli removed = {})", + iter, + stats.ccx_total, + stats.dropped, + stats.folded_cx, + stats.folded_x, + pair_transforms, + aff_drop, + aff_fold, + cp_transforms + 2 * pair_transforms + aff_drop + aff_fold, + ); + + if cp_transforms == 0 && pair_transforms == 0 && aff_drop + aff_fold == 0 { + break; + } + if iter >= max_iters { + eprintln!("CONSTPROP reached max_iters={}, stopping", max_iters); + break; + } + } + + eprintln!( + "CONSTPROP TOTAL iters={} dropped={} folded_cx={} folded_x={} inverse_pairs={} aff_drop={} aff_fold={} (toffoli removed = {})", + iter, + tot_dropped, + tot_folded_cx, + tot_folded_x, + tot_pairs, + tot_aff_drop, + tot_aff_fold, + tot_dropped + tot_folded_cx + tot_folded_x + 2 * tot_pairs + tot_aff_drop + tot_aff_fold, + ); + if straddle { + eprintln!( + "CONSTPROP_STRADDLE TOTAL straddle_extra_pairs={} (of inverse_pairs={})", + tot_straddle_extra, tot_pairs + ); + } + + if let Some(sites) = cur_sites { + crate::point_add::set_op_site_trace_from_constprop(sites); + } + + cur +} + +fn dims(ops: &[Op]) -> (usize, usize) { + let mut nq = 0u64; + let mut nb = 0u64; + for op in ops { + for q in [op.q_control2, op.q_control1, op.q_target] { + if q != NO_QUBIT { + nq = nq.max(q.0 + 1); + } + } + for b in [op.c_target, op.c_condition] { + if b != NO_BIT { + nb = nb.max(b.0 + 1); + } + } + } + (nq as usize, nb as usize) +} + +fn verify_control_constancy( + ops: &[Op], + decisions: &[Decision], + num_q: usize, + num_b: usize, + nonces: usize, +) -> Vec { + use crate::circuit::{analyze_ops, QubitOrBit}; + use crate::sim::Simulator; + use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; + use alloy_primitives::U256; + use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; + + let curve = WeierstrassEllipticCurve { + modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), + a: U256::from(0u64), + b: U256::from(7u64), + gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), + gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), + order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), + }; + + let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); + assert_eq!(regs.len(), 4, "expected 4 IO registers"); + + let mut flagged: Vec<(usize, Vec<(QubitId, u64)>)> = Vec::new(); + for (i, d) in decisions.iter().enumerate() { + match *d { + Decision::Keep => {} + Decision::DropZeroCtrl { ctrl } => flagged.push((i, vec![(ctrl, 0)])), + Decision::FoldCx { one_ctrl, .. } => flagged.push((i, vec![(one_ctrl, 1)])), + Decision::FoldX { c1, c2 } => flagged.push((i, vec![(c1, 1), (c2, 1)])), + + Decision::DropComplementCtrls { .. } | Decision::FoldEqualCtrls { .. } => {} + } + } + let mut ok = vec![true; ops.len()]; + if flagged.is_empty() { + return ok; + } + + let mut flag_pos = vec![u32::MAX; ops.len()]; + for (p, (i, _)) in flagged.iter().enumerate() { + flag_pos[*i] = p as u32; + } + + const NUM_TESTS: usize = 9024; + const BATCH: usize = 64; + + for nonce in 0..nonces { + + let mut hasher = Shake256::default(); + hasher.update(b"quantum_ecc-fiat-shamir-v2"); + hasher.update(&(ops.len() as u64).to_le_bytes()); + + hasher.update(b"CONSTPROP_VERIFY"); + hasher.update(&(nonce as u64).to_le_bytes()); + let mut xof = hasher.finalize_xof(); + + let mut targets = Vec::new(); + let mut offsets = Vec::new(); + for _ in 0..NUM_TESTS { + let mut rb = [[0u8; 32]; 2]; + xof.read(&mut rb[0]); + xof.read(&mut rb[1]); + let k1 = U256::from_le_bytes(rb[0]); + let k2 = U256::from_le_bytes(rb[1]); + let t = curve.mul(curve.gx, curve.gy, k1); + let o = curve.mul(curve.gx, curve.gy, k2); + if t.0 == o.0 { continue; } + if t.0.is_zero() && t.1.is_zero() { continue; } + if o.0.is_zero() && o.1.is_zero() { continue; } + targets.push(t); + offsets.push(o); + } + let n = targets.len(); + let num_batches = (n + BATCH - 1) / BATCH; + + let mut sim = Simulator::new(num_q, num_b, &mut xof); + for batch in 0..num_batches { + let bs = BATCH.min(n - batch * BATCH); + sim.clear_for_shot(); + for shot in 0..bs { + let i = batch * BATCH + shot; + sim.set_register(®s[0], targets[i].0, shot); + sim.set_register(®s[1], targets[i].1, shot); + sim.set_register(®s[2], offsets[i].0, shot); + sim.set_register(®s[3], offsets[i].1, shot); + } + let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; + + step_and_check(&mut sim, ops, &flag_pos, &flagged, &mut ok, cond_mask); + } + let bad = ok.iter().filter(|b| !**b).count(); + eprintln!( + "CONSTPROP_PROGRESS nonce={}/{} shots={} cumulative_failed_claims={}", + nonce + 1, nonces, n, bad + ); + } + let _ = QubitOrBit::Bit; + ok +} + +fn step_and_check( + sim: &mut crate::sim::Simulator, + ops: &[Op], + flag_pos: &[u32], + flagged: &[(usize, Vec<(QubitId, u64)>)], + ok: &mut [bool], + cond_mask: u64, +) { + + let mut condition_stack: Vec = Vec::new(); + let mut current_base_condition = u64::MAX; + + for (idx, op) in ops.iter().enumerate() { + + let fp = flag_pos[idx]; + if fp != u32::MAX { + let p = fp as usize; + for &(qid, expected) in &flagged[p].1 { + let live = sim.qubit(qid) & cond_mask; + let claim_ok = if expected == 0 { + + live == 0 + } else { + + live == cond_mask + }; + if !claim_ok { + ok[idx] = false; + } + } + } + + let mut cond = current_base_condition; + if op.c_condition != NO_BIT { + cond &= sim.bit(op.c_condition); + } + match op.kind { + OperationType::CCX => { + let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::CX => { + let v = cond & sim.qubit(op.q_control1); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::Swap => { + let mut q_c1 = sim.qubit(op.q_control1); + let mut q_t = sim.qubit(op.q_target); + q_c1 ^= q_t; + q_t ^= cond & q_c1; + q_c1 ^= q_t; + *sim.qubit_mut(op.q_control1) = q_c1; + *sim.qubit_mut(op.q_target) = q_t; + } + OperationType::X => { + *sim.qubit_mut(op.q_target) ^= cond; + } + OperationType::CCZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + sim.phase ^= v; + } + OperationType::CZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); + sim.phase ^= v; + } + OperationType::Z => { + let v = cond & sim.qubit(op.q_target); + sim.phase ^= v; + } + OperationType::Neg => { + sim.phase ^= cond; + } + OperationType::Hmr => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + *sim.bit_mut(op.c_target) &= !cond; + *sim.bit_mut(op.c_target) ^= rng_val & cond; + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::R => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::BitInvert => { + *sim.bit_mut(op.c_target) ^= cond; + } + OperationType::BitStore0 => { + *sim.bit_mut(op.c_target) &= !cond; + } + OperationType::BitStore1 => { + *sim.bit_mut(op.c_target) |= cond; + } + OperationType::AppendToRegister + | OperationType::Register + | OperationType::DebugPrint => {} + OperationType::PushCondition => { + condition_stack.push(current_base_condition); + current_base_condition &= sim.bit(op.c_condition); + } + OperationType::PopCondition => { + if let Some(val) = condition_stack.pop() { + current_base_condition = val; + } + } + } + } +} + +#[cfg(test)] +mod affine_transfer_tests { + use super::*; + + fn gate(kind: OperationType, c1: u64, c2: u64, target: u64) -> Op { + let mut op = Op::empty(); + op.kind = kind; + op.q_control1 = QubitId(c1); + op.q_control2 = QubitId(c2); + op.q_target = QubitId(target); + op + } + + #[test] + fn closes_equal_and_complementary_chains_conservatively() { + let equal_chain = vec![ + gate(OperationType::CX, 0, u64::MAX, 1), + gate(OperationType::CCX, 0, 1, 2), + gate(OperationType::CCX, 2, 0, 3), + ]; + let (decisions, fold_eq, drop_comp) = + analyze_affine(&equal_chain, 4, 0, &[QubitId(0)]); + assert_eq!((fold_eq, drop_comp), (2, 0)); + assert!(matches!(decisions[1], Decision::FoldEqualCtrls { .. })); + assert!(matches!(decisions[2], Decision::FoldEqualCtrls { .. })); + + let complement_chain = vec![ + gate(OperationType::CX, 0, u64::MAX, 1), + gate(OperationType::X, u64::MAX, u64::MAX, 1), + gate(OperationType::CX, 0, u64::MAX, 2), + gate(OperationType::CCX, 0, 1, 2), + gate(OperationType::CCX, 2, 0, 3), + ]; + let (decisions, fold_eq, drop_comp) = + analyze_affine(&complement_chain, 4, 0, &[QubitId(0)]); + assert_eq!((fold_eq, drop_comp), (1, 1)); + assert!(matches!(decisions[3], Decision::DropComplementCtrls { .. })); + assert!(matches!(decisions[4], Decision::FoldEqualCtrls { .. })); + + let mut conditional = gate(OperationType::CCX, 0, 1, 2); + conditional.c_condition = BitId(0); + let conditional_chain = vec![ + gate(OperationType::CX, 0, u64::MAX, 1), + conditional, + gate(OperationType::CCX, 2, 0, 3), + ]; + let (decisions, fold_eq, drop_comp) = + analyze_affine(&conditional_chain, 4, 1, &[QubitId(0)]); + assert_eq!((fold_eq, drop_comp), (1, 0)); + assert!(matches!(decisions[1], Decision::FoldEqualCtrls { .. })); + assert!(matches!(decisions[2], Decision::Keep)); + } +} + +fn verify_inverse_pairs( + ops: &[Op], + pairs: &[PairKill], + num_q: usize, + num_b: usize, + nonces: usize, +) -> usize { + use crate::circuit::analyze_ops; + use crate::sim::Simulator; + use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; + use alloy_primitives::U256; + use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; + + let curve = WeierstrassEllipticCurve { + modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), + a: U256::from(0u64), + b: U256::from(7u64), + gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), + gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), + order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), + }; + + let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); + assert_eq!(regs.len(), 4, "expected 4 IO registers"); + + let mut endpoint: Vec = vec![u32::MAX; ops.len()]; + let mut is_first_at: Vec = vec![false; ops.len()]; + for (p, pk) in pairs.iter().enumerate() { + endpoint[pk.first] = p as u32; + is_first_at[pk.first] = true; + endpoint[pk.second] = p as u32; + is_first_at[pk.second] = false; + } + + let mut bad_pair = vec![false; pairs.len()]; + + const NUM_TESTS: usize = 9024; + const BATCH: usize = 64; + + for nonce in 0..nonces { + let mut hasher = Shake256::default(); + hasher.update(b"quantum_ecc-fiat-shamir-v2"); + hasher.update(&(ops.len() as u64).to_le_bytes()); + hasher.update(b"CONSTPROP_PAIR_VERIFY"); + hasher.update(&(nonce as u64).to_le_bytes()); + let mut xof = hasher.finalize_xof(); + + let mut targets = Vec::new(); + let mut offsets = Vec::new(); + for _ in 0..NUM_TESTS { + let mut rb = [[0u8; 32]; 2]; + xof.read(&mut rb[0]); + xof.read(&mut rb[1]); + let k1 = U256::from_le_bytes(rb[0]); + let k2 = U256::from_le_bytes(rb[1]); + let t = curve.mul(curve.gx, curve.gy, k1); + let o = curve.mul(curve.gx, curve.gy, k2); + if t.0 == o.0 { continue; } + if t.0.is_zero() && t.1.is_zero() { continue; } + if o.0.is_zero() && o.1.is_zero() { continue; } + targets.push(t); + offsets.push(o); + } + let n = targets.len(); + let num_batches = (n + BATCH - 1) / BATCH; + + let mut sim = Simulator::new(num_q, num_b, &mut xof); + + let mut snap_contrib = vec![0u64; pairs.len()]; + let mut snap_tgt = vec![0u64; pairs.len()]; + let mut snap_seen = vec![false; pairs.len()]; + + for batch in 0..num_batches { + let bs = BATCH.min(n - batch * BATCH); + sim.clear_for_shot(); + for shot in 0..bs { + let i = batch * BATCH + shot; + sim.set_register(®s[0], targets[i].0, shot); + sim.set_register(®s[1], targets[i].1, shot); + sim.set_register(®s[2], offsets[i].0, shot); + sim.set_register(®s[3], offsets[i].1, shot); + } + let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; + for s in snap_seen.iter_mut() { *s = false; } + + step_and_check_pairs( + &mut sim, + ops, + pairs, + &endpoint, + &is_first_at, + &mut snap_contrib, + &mut snap_tgt, + &mut snap_seen, + &mut bad_pair, + cond_mask, + ); + } + let bad = bad_pair.iter().filter(|b| **b).count(); + eprintln!( + "CONSTPROP_PAIR_PROGRESS nonce={}/{} shots={} cumulative_unsound_pairs={}", + nonce + 1, nonces, n, bad + ); + } + + bad_pair.iter().filter(|b| **b).count() +} + +fn step_and_check_pairs( + sim: &mut crate::sim::Simulator, + ops: &[Op], + pairs: &[PairKill], + endpoint: &[u32], + is_first_at: &[bool], + snap_contrib: &mut [u64], + snap_tgt: &mut [u64], + snap_seen: &mut [bool], + bad_pair: &mut [bool], + cond_mask: u64, +) { + let mut condition_stack: Vec = Vec::new(); + let mut current_base_condition = u64::MAX; + + for (idx, op) in ops.iter().enumerate() { + + let pp = endpoint[idx]; + if pp != u32::MAX { + let p = pp as usize; + + let mut cond = current_base_condition; + if op.c_condition != NO_BIT { + cond &= sim.bit(op.c_condition); + } + let a = op.q_control1; + let b = op.q_control2; + let t = op.q_target; + let contrib = (cond & sim.qubit(a) & sim.qubit(b)) & cond_mask; + let tgt = sim.qubit(t) & cond_mask; + if is_first_at[idx] { + snap_contrib[p] = contrib; + + snap_tgt[p] = tgt ^ contrib; + snap_seen[p] = true; + } else if snap_seen[p] { + if contrib != snap_contrib[p] || tgt != snap_tgt[p] { + bad_pair[p] = true; + } + } else { + + bad_pair[p] = true; + } + } + + let mut cond = current_base_condition; + if op.c_condition != NO_BIT { + cond &= sim.bit(op.c_condition); + } + match op.kind { + OperationType::CCX => { + let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::CX => { + let v = cond & sim.qubit(op.q_control1); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::Swap => { + let mut q_c1 = sim.qubit(op.q_control1); + let mut q_t = sim.qubit(op.q_target); + q_c1 ^= q_t; + q_t ^= cond & q_c1; + q_c1 ^= q_t; + *sim.qubit_mut(op.q_control1) = q_c1; + *sim.qubit_mut(op.q_target) = q_t; + } + OperationType::X => { + *sim.qubit_mut(op.q_target) ^= cond; + } + OperationType::CCZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + sim.phase ^= v; + } + OperationType::CZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); + sim.phase ^= v; + } + OperationType::Z => { + let v = cond & sim.qubit(op.q_target); + sim.phase ^= v; + } + OperationType::Neg => { + sim.phase ^= cond; + } + OperationType::Hmr => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + *sim.bit_mut(op.c_target) &= !cond; + *sim.bit_mut(op.c_target) ^= rng_val & cond; + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::R => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::BitInvert => { + *sim.bit_mut(op.c_target) ^= cond; + } + OperationType::BitStore0 => { + *sim.bit_mut(op.c_target) &= !cond; + } + OperationType::BitStore1 => { + *sim.bit_mut(op.c_target) |= cond; + } + OperationType::AppendToRegister + | OperationType::Register + | OperationType::DebugPrint => {} + OperationType::PushCondition => { + condition_stack.push(current_base_condition); + current_base_condition &= sim.bit(op.c_condition); + } + OperationType::PopCondition => { + if let Some(val) = condition_stack.pop() { + current_base_condition = val; + } + } + } + } + let _ = pairs; +} + +fn verify_affine_relations( + ops: &[Op], + decisions: &[Decision], + num_q: usize, + num_b: usize, + nonces: usize, +) -> Vec { + use crate::circuit::analyze_ops; + use crate::sim::Simulator; + use crate::weierstrass_elliptic_curve::WeierstrassEllipticCurve; + use alloy_primitives::U256; + use sha3::{digest::{ExtendableOutput, Update, XofReader}, Shake256}; + + let curve = WeierstrassEllipticCurve { + modulus: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16).unwrap(), + a: U256::from(0u64), + b: U256::from(7u64), + gx: U256::from_str_radix("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16).unwrap(), + gy: U256::from_str_radix("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16).unwrap(), + order: U256::from_str_radix("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16).unwrap(), + }; + + let (_tq, _tb, _nr, regs) = analyze_ops(ops.iter()); + assert_eq!(regs.len(), 4, "expected 4 IO registers"); + + let mut want_equal = vec![false; ops.len()]; + let mut flagged_idx: Vec = Vec::new(); + let mut is_flagged = vec![false; ops.len()]; + for (i, d) in decisions.iter().enumerate() { + match *d { + Decision::FoldEqualCtrls { .. } => { + want_equal[i] = true; + is_flagged[i] = true; + flagged_idx.push(i); + } + Decision::DropComplementCtrls { .. } => { + want_equal[i] = false; + is_flagged[i] = true; + flagged_idx.push(i); + } + _ => {} + } + } + let mut ok = vec![true; ops.len()]; + if flagged_idx.is_empty() { + return ok; + } + + const NUM_TESTS: usize = 9024; + const BATCH: usize = 64; + + for nonce in 0..nonces { + let mut hasher = Shake256::default(); + hasher.update(b"quantum_ecc-fiat-shamir-v2"); + hasher.update(&(ops.len() as u64).to_le_bytes()); + hasher.update(b"CONSTPROP_AFFINE_VERIFY"); + hasher.update(&(nonce as u64).to_le_bytes()); + let mut xof = hasher.finalize_xof(); + + let mut targets = Vec::new(); + let mut offsets = Vec::new(); + for _ in 0..NUM_TESTS { + let mut rb = [[0u8; 32]; 2]; + xof.read(&mut rb[0]); + xof.read(&mut rb[1]); + let k1 = U256::from_le_bytes(rb[0]); + let k2 = U256::from_le_bytes(rb[1]); + let t = curve.mul(curve.gx, curve.gy, k1); + let o = curve.mul(curve.gx, curve.gy, k2); + if t.0 == o.0 { continue; } + if t.0.is_zero() && t.1.is_zero() { continue; } + if o.0.is_zero() && o.1.is_zero() { continue; } + targets.push(t); + offsets.push(o); + } + let n = targets.len(); + let num_batches = (n + BATCH - 1) / BATCH; + + let mut sim = Simulator::new(num_q, num_b, &mut xof); + for batch in 0..num_batches { + let bs = BATCH.min(n - batch * BATCH); + sim.clear_for_shot(); + for shot in 0..bs { + let i = batch * BATCH + shot; + sim.set_register(®s[0], targets[i].0, shot); + sim.set_register(®s[1], targets[i].1, shot); + sim.set_register(®s[2], offsets[i].0, shot); + sim.set_register(®s[3], offsets[i].1, shot); + } + let cond_mask: u64 = if bs == 64 { u64::MAX } else { (1u64 << bs) - 1 }; + step_and_check_affine( + &mut sim, + ops, + &is_flagged, + &want_equal, + &mut ok, + cond_mask, + ); + } + let bad = flagged_idx.iter().filter(|&&i| !ok[i]).count(); + eprintln!( + "CONSTPROP_AFFINE_PROGRESS nonce={}/{} shots={} cumulative_failed_claims={}", + nonce + 1, nonces, n, bad + ); + } + ok +} + +fn step_and_check_affine( + sim: &mut crate::sim::Simulator, + ops: &[Op], + is_flagged: &[bool], + want_equal: &[bool], + ok: &mut [bool], + cond_mask: u64, +) { + let mut condition_stack: Vec = Vec::new(); + let mut current_base_condition = u64::MAX; + + for (idx, op) in ops.iter().enumerate() { + if is_flagged[idx] { + + let va = sim.qubit(op.q_control1) & cond_mask; + let vb = sim.qubit(op.q_control2) & cond_mask; + let claim_ok = if want_equal[idx] { + va == vb + } else { + (va ^ vb) == cond_mask + }; + if !claim_ok { + ok[idx] = false; + } + } + + let mut cond = current_base_condition; + if op.c_condition != NO_BIT { + cond &= sim.bit(op.c_condition); + } + match op.kind { + OperationType::CCX => { + let v = cond & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::CX => { + let v = cond & sim.qubit(op.q_control1); + *sim.qubit_mut(op.q_target) ^= v; + } + OperationType::Swap => { + let mut q_c1 = sim.qubit(op.q_control1); + let mut q_t = sim.qubit(op.q_target); + q_c1 ^= q_t; + q_t ^= cond & q_c1; + q_c1 ^= q_t; + *sim.qubit_mut(op.q_control1) = q_c1; + *sim.qubit_mut(op.q_target) = q_t; + } + OperationType::X => { + *sim.qubit_mut(op.q_target) ^= cond; + } + OperationType::CCZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1) & sim.qubit(op.q_control2); + sim.phase ^= v; + } + OperationType::CZ => { + let v = cond & sim.qubit(op.q_target) & sim.qubit(op.q_control1); + sim.phase ^= v; + } + OperationType::Z => { + let v = cond & sim.qubit(op.q_target); + sim.phase ^= v; + } + OperationType::Neg => { + sim.phase ^= cond; + } + OperationType::Hmr => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + *sim.bit_mut(op.c_target) &= !cond; + *sim.bit_mut(op.c_target) ^= rng_val & cond; + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::R => { + let mut buf = [0u8; 8]; + sim.xof.read(&mut buf); + let rng_val = u64::from_le_bytes(buf); + sim.phase ^= sim.qubit(op.q_target) & rng_val & cond; + *sim.qubit_mut(op.q_target) &= !cond; + } + OperationType::BitInvert => { + *sim.bit_mut(op.c_target) ^= cond; + } + OperationType::BitStore0 => { + *sim.bit_mut(op.c_target) &= !cond; + } + OperationType::BitStore1 => { + *sim.bit_mut(op.c_target) |= cond; + } + OperationType::AppendToRegister + | OperationType::Register + | OperationType::DebugPrint => {} + OperationType::PushCondition => { + condition_stack.push(current_base_condition); + current_base_condition &= sim.bit(op.c_condition); + } + OperationType::PopCondition => { + if let Some(val) = condition_stack.pop() { + current_base_condition = val; + } + } + } + } +} diff --git a/src/point_add/trailmix_ludicrous/ec_add.rs b/src/point_add/trailmix_ludicrous/ec_add.rs index f42f740c..5392def8 100644 --- a/src/point_add/trailmix_ludicrous/ec_add.rs +++ b/src/point_add/trailmix_ludicrous/ec_add.rs @@ -1,361 +1,361 @@ - -use super::arith::{ - mod_add, mod_add_exact, mod_neg, mod_rsub_vented_loaded, mod_sub_classical_low3, - mod_sub_shifted_low, mod_sub_vented, -}; -use super::gcd::{mod_mul_inverse_in_place, Direction}; -use super::square::mod_square_sub_pm_secp256k1_symmetric; -use super::{B, BExt}; -use crate::point_add::{arith::mod_const_minus_reg_qb, SECP256K1_P}; -use crate::circuit::{BitId, QubitId}; - -const N: usize = 256; - -fn coord_addsub(circ: &mut B, dst: &[QubitId], coord: &[BitId], subtract: bool) { - debug_assert_eq!(dst.len(), N); - debug_assert_eq!(coord.len(), N); - let split_low3 = subtract - && std::env::var("TLM_COORD_SPLIT_LOW3") - .ok() - .as_deref() - .unwrap_or("0") - != "0"; - if split_low3 { - let temp = circ.alloc_qubits(N - 3); - for i in 3..N { - circ.x_if_bit(temp[i - 3], coord[i]); - } - mod_sub_shifted_low(circ, &temp, dst, 3); - for i in 3..N { - circ.x_if_bit(temp[i - 3], coord[i]); - } - for q in temp { - circ.zero_and_free(q); - } - mod_sub_classical_low3(circ, dst, &coord[..3]); - return; - } - let temp = circ.alloc_qubits(N); - for i in 0..N { - circ.x_if_bit(temp[i], coord[i]); - } - - if subtract { - mod_sub_vented(circ, &temp, dst); - } else { - mod_add(circ, &temp, dst); - } - for i in 0..N { - circ.x_if_bit(temp[i], coord[i]); - } - for q in temp { - circ.zero_and_free(q); - } -} - -fn coord_add3x(circ: &mut B, dst: &[QubitId], coord: &[BitId]) { - debug_assert_eq!(dst.len(), N); - debug_assert_eq!(coord.len(), N); - - let three_coord = classical_times3_mod_q(circ, coord); - - let temp = circ.alloc_qubits(N); - for i in 0..N { - circ.x_if_bit(temp[i], three_coord[i]); - } - - if std::env::var("TLM_COORD_ADD3X_TRUNC").ok().as_deref() == Some("1") { - mod_add(circ, &temp, dst); - } else { - mod_add_exact(circ, &temp, dst); - } - for i in 0..N { - circ.x_if_bit(temp[i], three_coord[i]); - } - for q in temp { - circ.zero_and_free(q); - } - - for &b in &three_coord { - circ.bit_store0(b); - } -} - -fn classical_times3_mod_q(circ: &mut B, coord: &[BitId]) -> Vec { - debug_assert_eq!(coord.len(), N); - const C: u128 = (1u128 << 32) + 977; - - let s: Vec = circ.alloc_bits(N + 2); - for &b in &s { - circ.bit_store0(b); - } - classical_add_into(circ, &s, coord); - classical_add_into(circ, &s, coord); - classical_add_into(circ, &s, coord); - - let r: Vec = circ.alloc_bits(N + 1); - for i in 0..N { - circ.bit_copy(r[i], s[i]); - } - circ.bit_store0(r[N]); - - let av_bits = 35usize; - let av: Vec = circ.alloc_bits(av_bits); - classical_set_const_times_bit(circ, &av, C, s[N], false); - classical_add_const_times_bit(circ, &av, 2 * C, s[N + 1]); - classical_add_into(circ, &r, &av); - - let tmp: Vec = circ.alloc_bits(N + 2); - for i in 0..(N + 1) { - circ.bit_copy(tmp[i], r[i]); - } - circ.bit_store0(tmp[N + 1]); - { - - let cbits: Vec = circ.alloc_bits(av_bits); - classical_set_const(circ, &cbits, C); - classical_add_into(circ, &tmp, &cbits); - for &b in &cbits { - circ.bit_store0(b); - } - } - - let geflag = circ.alloc_bit(); - circ.bit_store0(geflag); - circ.push_condition(tmp[N]); - circ.bit_store1(geflag); - circ.pop_condition(); - circ.push_condition(tmp[N + 1]); - circ.bit_store1(geflag); - circ.pop_condition(); - - let result: Vec = circ.alloc_bits(N); - for i in 0..N { - circ.bit_store0(result[i]); - circ.push_condition(geflag); - circ.push_condition(tmp[i]); - circ.bit_store1(result[i]); - circ.pop_condition(); - circ.pop_condition(); - circ.bit_invert(geflag); - circ.push_condition(geflag); - circ.push_condition(r[i]); - circ.bit_store1(result[i]); - circ.pop_condition(); - circ.pop_condition(); - circ.bit_invert(geflag); - } - - circ.bit_store0(geflag); - for &b in tmp.iter().chain(av.iter()).chain(r.iter()).chain(s.iter()) { - circ.bit_store0(b); - } - result -} - -fn classical_set_const(circ: &mut B, dst: &[BitId], k: u128) { - for (i, &b) in dst.iter().enumerate() { - let bit = i < 128 && ((k >> i) & 1) == 1; - if bit { - circ.bit_store0(b); - circ.bit_invert(b); - } else { - circ.bit_store0(b); - } - } -} - -fn classical_set_const_times_bit(circ: &mut B, dst: &[BitId], k: u128, gate: BitId, _accumulate: bool) { - for (i, &b) in dst.iter().enumerate() { - circ.bit_store0(b); - let bit = i < 128 && ((k >> i) & 1) == 1; - if bit { - circ.push_condition(gate); - circ.bit_store1(b); - circ.pop_condition(); - } - } -} - -fn classical_add_const_times_bit(circ: &mut B, dst: &[BitId], k: u128, gate: BitId) { - let w = dst.len(); - let addend: Vec = circ.alloc_bits(w); - classical_set_const_times_bit(circ, &addend, k, gate, false); - classical_add_into(circ, dst, &addend); - for &b in &addend { - circ.bit_store0(b); - } -} - -fn classical_add_into(circ: &mut B, acc: &[BitId], addend: &[BitId]) { - let carry = circ.alloc_bit(); - circ.bit_store0(carry); - let newcarry = circ.alloc_bit(); - for i in 0..acc.len() { - let a_i = addend.get(i).copied(); - - circ.bit_store0(newcarry); - if let Some(a) = a_i { - circ.bit_and_xor_into(newcarry, acc[i], a); - circ.bit_and_xor_into(newcarry, acc[i], carry); - circ.bit_and_xor_into(newcarry, a, carry); - } else { - circ.bit_and_xor_into(newcarry, acc[i], carry); - } - - if let Some(a) = a_i { - circ.bit_xor_into(acc[i], a); - } - circ.bit_xor_into(acc[i], carry); - - circ.bit_copy(carry, newcarry); - } - circ.bit_store0(newcarry); - circ.bit_store0(carry); -} - -fn classical_plus1_mod_2n(circ: &mut B, coord: &[BitId]) -> Vec { - debug_assert_eq!(coord.len(), N); - let s: Vec = circ.alloc_bits(N); - for i in 0..N { - circ.bit_copy(s[i], coord[i]); - } - let one: Vec = circ.alloc_bits(1); - circ.bit_store0(one[0]); - circ.bit_invert(one[0]); - classical_add_into(circ, &s, &one); - circ.bit_store0(one[0]); - s -} - -fn coord_rsub(circ: &mut B, x: &[QubitId], coord: &[BitId]) { - debug_assert_eq!(x.len(), N); - debug_assert_eq!(coord.len(), N); - - if std::env::var("TLM_COORD_RSUB_FUSED").ok().as_deref() == Some("1") { - let coord_p1 = classical_plus1_mod_2n(circ, coord); - let t: Vec = (0..N).map(|_| circ.alloc_qubit()).collect(); - for i in 0..N { - circ.x_if_bit(t[i], coord_p1[i]); - } - mod_rsub_vented_loaded(circ, &t, x); - for i in 0..N { - circ.x_if_bit(t[i], coord_p1[i]); - } - for q in t { - circ.zero_and_free(q); - } - for &b in &coord_p1 { - circ.bit_store0(b); - } - return; - } - if std::env::var("TLM_FUSE_X_RESTORE") - .ok() - .as_deref() - == Some("1") - { - mod_const_minus_reg_qb(circ, x, coord, SECP256K1_P); - return; - } - let t: Vec = (0..N).map(|_| circ.alloc_qubit()).collect(); - for i in 0..N { - circ.x_if_bit(t[i], coord[i]); - } - mod_sub_vented(circ, &t, x); - for i in 0..N { - circ.x_if_bit(t[i], coord[i]); - } - for q in t { - circ.zero_and_free(q); - } - mod_neg(circ, x); -} - -pub fn ec_add( - circ: &mut B, - x2: &mut Vec, - y2: &[QubitId], - ox: &[BitId], - oy: &[BitId], -) { - assert_eq!(x2.len(), N, "x2 is 256 bits"); - assert_eq!(y2.len(), N, "y2 is 256 bits"); - assert_eq!(ox.len(), N, "ox is 256 classical bits"); - assert_eq!(oy.len(), N, "oy is 256 classical bits"); - - circ.set_phase("tlm_coord_x_sub"); - coord_addsub(circ, x2, ox, true); - circ.set_phase("tlm_coord_y_sub"); - coord_addsub(circ, &y2[..N], oy, true); - - circ.set_phase("tlm_inverse"); - let xv = std::mem::take(x2); - *x2 = mod_mul_inverse_in_place(circ, xv, y2, Direction::Inverse); - - circ.set_phase("tlm_coord_add3x"); - coord_add3x(circ, x2, ox); - - circ.set_phase("tlm_square"); - mod_square_sub_pm_secp256k1_symmetric(circ, &y2[..N], x2); - - circ.set_phase("tlm_forward_multiply"); - let xv = std::mem::take(x2); - *x2 = mod_mul_inverse_in_place(circ, xv, y2, Direction::Forward); - - circ.set_phase("tlm_coord_y_sub_final"); - coord_addsub(circ, &y2[..N], oy, true); - circ.set_phase("tlm_coord_rsub_final"); - coord_rsub(circ, x2, ox); -} - -pub fn build_times3_test() -> (Vec, Vec, Vec) { - let mut circ = B::new_for_test(); - let ox = circ.alloc_bits(N); - let t = classical_times3_mod_q(&mut circ, &ox); - - let tout = circ.alloc_bits(N); - for i in 0..N { - circ.bit_copy(tout[i], t[i]); - } - circ.declare_bit_register(&ox); - circ.declare_bit_register(&tout); - (circ.take_ops(), ox, tout) -} - -pub fn build_add3x_test() -> (Vec, Vec, Vec) { - let mut circ = B::new_for_test(); - let dst: Vec = circ.alloc_qubits(N); - let ox = circ.alloc_bits(N); - coord_add3x(&mut circ, &dst, &ox); - circ.declare_qubit_register(&dst); - circ.declare_bit_register(&ox); - (circ.take_ops(), ox, dst) -} - -fn coord_add3x_orig(circ: &mut B, dst: &[QubitId], coord: &[BitId]) { - let temp: Vec = (0..=N).map(|_| circ.alloc_qubit()).collect(); - for i in 0..N { - circ.x_if_bit(temp[i], coord[i]); - } - mod_add(circ, &temp[..N], dst); - super::arith::mod_double(circ, &temp); - mod_add(circ, &temp[..N], dst); - super::arith::mod_double_reverse(circ, &temp); - for i in 0..N { - circ.x_if_bit(temp[i], coord[i]); - } - for q in temp { - circ.zero_and_free(q); - } -} - -pub fn build_add3x_test_orig() -> (Vec, Vec, Vec) { - let mut circ = B::new_for_test(); - let dst: Vec = circ.alloc_qubits(N); - let ox = circ.alloc_bits(N); - coord_add3x_orig(&mut circ, &dst, &ox); - circ.declare_qubit_register(&dst); - circ.declare_bit_register(&ox); - (circ.take_ops(), ox, dst) -} + +use super::arith::{ + mod_add, mod_add_exact, mod_neg, mod_rsub_vented_loaded, mod_sub_classical_low3, + mod_sub_shifted_low, mod_sub_vented, +}; +use super::gcd::{mod_mul_inverse_in_place, Direction}; +use super::square::mod_square_sub_pm_secp256k1_symmetric; +use super::{B, BExt}; +use crate::point_add::{arith::mod_const_minus_reg_qb, SECP256K1_P}; +use crate::circuit::{BitId, QubitId}; + +const N: usize = 256; + +fn coord_addsub(circ: &mut B, dst: &[QubitId], coord: &[BitId], subtract: bool) { + debug_assert_eq!(dst.len(), N); + debug_assert_eq!(coord.len(), N); + let split_low3 = subtract + && std::env::var("TLM_COORD_SPLIT_LOW3") + .ok() + .as_deref() + .unwrap_or("0") + != "0"; + if split_low3 { + let temp = circ.alloc_qubits(N - 3); + for i in 3..N { + circ.x_if_bit(temp[i - 3], coord[i]); + } + mod_sub_shifted_low(circ, &temp, dst, 3); + for i in 3..N { + circ.x_if_bit(temp[i - 3], coord[i]); + } + for q in temp { + circ.zero_and_free(q); + } + mod_sub_classical_low3(circ, dst, &coord[..3]); + return; + } + let temp = circ.alloc_qubits(N); + for i in 0..N { + circ.x_if_bit(temp[i], coord[i]); + } + + if subtract { + mod_sub_vented(circ, &temp, dst); + } else { + mod_add(circ, &temp, dst); + } + for i in 0..N { + circ.x_if_bit(temp[i], coord[i]); + } + for q in temp { + circ.zero_and_free(q); + } +} + +fn coord_add3x(circ: &mut B, dst: &[QubitId], coord: &[BitId]) { + debug_assert_eq!(dst.len(), N); + debug_assert_eq!(coord.len(), N); + + let three_coord = classical_times3_mod_q(circ, coord); + + let temp = circ.alloc_qubits(N); + for i in 0..N { + circ.x_if_bit(temp[i], three_coord[i]); + } + + if std::env::var("TLM_COORD_ADD3X_TRUNC").ok().as_deref() == Some("1") { + mod_add(circ, &temp, dst); + } else { + mod_add_exact(circ, &temp, dst); + } + for i in 0..N { + circ.x_if_bit(temp[i], three_coord[i]); + } + for q in temp { + circ.zero_and_free(q); + } + + for &b in &three_coord { + circ.bit_store0(b); + } +} + +fn classical_times3_mod_q(circ: &mut B, coord: &[BitId]) -> Vec { + debug_assert_eq!(coord.len(), N); + const C: u128 = (1u128 << 32) + 977; + + let s: Vec = circ.alloc_bits(N + 2); + for &b in &s { + circ.bit_store0(b); + } + classical_add_into(circ, &s, coord); + classical_add_into(circ, &s, coord); + classical_add_into(circ, &s, coord); + + let r: Vec = circ.alloc_bits(N + 1); + for i in 0..N { + circ.bit_copy(r[i], s[i]); + } + circ.bit_store0(r[N]); + + let av_bits = 35usize; + let av: Vec = circ.alloc_bits(av_bits); + classical_set_const_times_bit(circ, &av, C, s[N], false); + classical_add_const_times_bit(circ, &av, 2 * C, s[N + 1]); + classical_add_into(circ, &r, &av); + + let tmp: Vec = circ.alloc_bits(N + 2); + for i in 0..(N + 1) { + circ.bit_copy(tmp[i], r[i]); + } + circ.bit_store0(tmp[N + 1]); + { + + let cbits: Vec = circ.alloc_bits(av_bits); + classical_set_const(circ, &cbits, C); + classical_add_into(circ, &tmp, &cbits); + for &b in &cbits { + circ.bit_store0(b); + } + } + + let geflag = circ.alloc_bit(); + circ.bit_store0(geflag); + circ.push_condition(tmp[N]); + circ.bit_store1(geflag); + circ.pop_condition(); + circ.push_condition(tmp[N + 1]); + circ.bit_store1(geflag); + circ.pop_condition(); + + let result: Vec = circ.alloc_bits(N); + for i in 0..N { + circ.bit_store0(result[i]); + circ.push_condition(geflag); + circ.push_condition(tmp[i]); + circ.bit_store1(result[i]); + circ.pop_condition(); + circ.pop_condition(); + circ.bit_invert(geflag); + circ.push_condition(geflag); + circ.push_condition(r[i]); + circ.bit_store1(result[i]); + circ.pop_condition(); + circ.pop_condition(); + circ.bit_invert(geflag); + } + + circ.bit_store0(geflag); + for &b in tmp.iter().chain(av.iter()).chain(r.iter()).chain(s.iter()) { + circ.bit_store0(b); + } + result +} + +fn classical_set_const(circ: &mut B, dst: &[BitId], k: u128) { + for (i, &b) in dst.iter().enumerate() { + let bit = i < 128 && ((k >> i) & 1) == 1; + if bit { + circ.bit_store0(b); + circ.bit_invert(b); + } else { + circ.bit_store0(b); + } + } +} + +fn classical_set_const_times_bit(circ: &mut B, dst: &[BitId], k: u128, gate: BitId, _accumulate: bool) { + for (i, &b) in dst.iter().enumerate() { + circ.bit_store0(b); + let bit = i < 128 && ((k >> i) & 1) == 1; + if bit { + circ.push_condition(gate); + circ.bit_store1(b); + circ.pop_condition(); + } + } +} + +fn classical_add_const_times_bit(circ: &mut B, dst: &[BitId], k: u128, gate: BitId) { + let w = dst.len(); + let addend: Vec = circ.alloc_bits(w); + classical_set_const_times_bit(circ, &addend, k, gate, false); + classical_add_into(circ, dst, &addend); + for &b in &addend { + circ.bit_store0(b); + } +} + +fn classical_add_into(circ: &mut B, acc: &[BitId], addend: &[BitId]) { + let carry = circ.alloc_bit(); + circ.bit_store0(carry); + let newcarry = circ.alloc_bit(); + for i in 0..acc.len() { + let a_i = addend.get(i).copied(); + + circ.bit_store0(newcarry); + if let Some(a) = a_i { + circ.bit_and_xor_into(newcarry, acc[i], a); + circ.bit_and_xor_into(newcarry, acc[i], carry); + circ.bit_and_xor_into(newcarry, a, carry); + } else { + circ.bit_and_xor_into(newcarry, acc[i], carry); + } + + if let Some(a) = a_i { + circ.bit_xor_into(acc[i], a); + } + circ.bit_xor_into(acc[i], carry); + + circ.bit_copy(carry, newcarry); + } + circ.bit_store0(newcarry); + circ.bit_store0(carry); +} + +fn classical_plus1_mod_2n(circ: &mut B, coord: &[BitId]) -> Vec { + debug_assert_eq!(coord.len(), N); + let s: Vec = circ.alloc_bits(N); + for i in 0..N { + circ.bit_copy(s[i], coord[i]); + } + let one: Vec = circ.alloc_bits(1); + circ.bit_store0(one[0]); + circ.bit_invert(one[0]); + classical_add_into(circ, &s, &one); + circ.bit_store0(one[0]); + s +} + +fn coord_rsub(circ: &mut B, x: &[QubitId], coord: &[BitId]) { + debug_assert_eq!(x.len(), N); + debug_assert_eq!(coord.len(), N); + + if std::env::var("TLM_COORD_RSUB_FUSED").ok().as_deref() == Some("1") { + let coord_p1 = classical_plus1_mod_2n(circ, coord); + let t: Vec = (0..N).map(|_| circ.alloc_qubit()).collect(); + for i in 0..N { + circ.x_if_bit(t[i], coord_p1[i]); + } + mod_rsub_vented_loaded(circ, &t, x); + for i in 0..N { + circ.x_if_bit(t[i], coord_p1[i]); + } + for q in t { + circ.zero_and_free(q); + } + for &b in &coord_p1 { + circ.bit_store0(b); + } + return; + } + if std::env::var("TLM_FUSE_X_RESTORE") + .ok() + .as_deref() + == Some("1") + { + mod_const_minus_reg_qb(circ, x, coord, SECP256K1_P); + return; + } + let t: Vec = (0..N).map(|_| circ.alloc_qubit()).collect(); + for i in 0..N { + circ.x_if_bit(t[i], coord[i]); + } + mod_sub_vented(circ, &t, x); + for i in 0..N { + circ.x_if_bit(t[i], coord[i]); + } + for q in t { + circ.zero_and_free(q); + } + mod_neg(circ, x); +} + +pub fn ec_add( + circ: &mut B, + x2: &mut Vec, + y2: &[QubitId], + ox: &[BitId], + oy: &[BitId], +) { + assert_eq!(x2.len(), N, "x2 is 256 bits"); + assert_eq!(y2.len(), N, "y2 is 256 bits"); + assert_eq!(ox.len(), N, "ox is 256 classical bits"); + assert_eq!(oy.len(), N, "oy is 256 classical bits"); + + circ.set_phase("tlm_coord_x_sub"); + coord_addsub(circ, x2, ox, true); + circ.set_phase("tlm_coord_y_sub"); + coord_addsub(circ, &y2[..N], oy, true); + + circ.set_phase("tlm_inverse"); + let xv = std::mem::take(x2); + *x2 = mod_mul_inverse_in_place(circ, xv, y2, Direction::Inverse); + + circ.set_phase("tlm_coord_add3x"); + coord_add3x(circ, x2, ox); + + circ.set_phase("tlm_square"); + mod_square_sub_pm_secp256k1_symmetric(circ, &y2[..N], x2); + + circ.set_phase("tlm_forward_multiply"); + let xv = std::mem::take(x2); + *x2 = mod_mul_inverse_in_place(circ, xv, y2, Direction::Forward); + + circ.set_phase("tlm_coord_y_sub_final"); + coord_addsub(circ, &y2[..N], oy, true); + circ.set_phase("tlm_coord_rsub_final"); + coord_rsub(circ, x2, ox); +} + +pub fn build_times3_test() -> (Vec, Vec, Vec) { + let mut circ = B::new_for_test(); + let ox = circ.alloc_bits(N); + let t = classical_times3_mod_q(&mut circ, &ox); + + let tout = circ.alloc_bits(N); + for i in 0..N { + circ.bit_copy(tout[i], t[i]); + } + circ.declare_bit_register(&ox); + circ.declare_bit_register(&tout); + (circ.take_ops(), ox, tout) +} + +pub fn build_add3x_test() -> (Vec, Vec, Vec) { + let mut circ = B::new_for_test(); + let dst: Vec = circ.alloc_qubits(N); + let ox = circ.alloc_bits(N); + coord_add3x(&mut circ, &dst, &ox); + circ.declare_qubit_register(&dst); + circ.declare_bit_register(&ox); + (circ.take_ops(), ox, dst) +} + +fn coord_add3x_orig(circ: &mut B, dst: &[QubitId], coord: &[BitId]) { + let temp: Vec = (0..=N).map(|_| circ.alloc_qubit()).collect(); + for i in 0..N { + circ.x_if_bit(temp[i], coord[i]); + } + mod_add(circ, &temp[..N], dst); + super::arith::mod_double(circ, &temp); + mod_add(circ, &temp[..N], dst); + super::arith::mod_double_reverse(circ, &temp); + for i in 0..N { + circ.x_if_bit(temp[i], coord[i]); + } + for q in temp { + circ.zero_and_free(q); + } +} + +pub fn build_add3x_test_orig() -> (Vec, Vec, Vec) { + let mut circ = B::new_for_test(); + let dst: Vec = circ.alloc_qubits(N); + let ox = circ.alloc_bits(N); + coord_add3x_orig(&mut circ, &dst, &ox); + circ.declare_qubit_register(&dst); + circ.declare_bit_register(&ox); + (circ.take_ops(), ox, dst) +} diff --git a/src/point_add/trailmix_ludicrous/fused.rs b/src/point_add/trailmix_ludicrous/fused.rs index 035330b3..c4a118f6 100644 --- a/src/point_add/trailmix_ludicrous/fused.rs +++ b/src/point_add/trailmix_ludicrous/fused.rs @@ -1,2082 +1,2062 @@ - -use super::arith::{F_SECP256K1, LSBS}; -use super::{B, BExt}; -use crate::circuit::{BitId, QubitId}; -use std::cell::Cell; - -thread_local! { - static FOLD_CALL_INDEX: Cell = const { Cell::new(0) }; - static ACTIVE_FOLD_CALL_INDEX: Cell = const { Cell::new(usize::MAX) }; - static FOLD_CHUNK_CALL_INDEX: Cell = const { Cell::new(0) }; - static FOLD_DIRTY_CALL_INDEX: Cell = const { Cell::new(0) }; - static FOLD_CLEAN_WINDOW_CALL_INDEX: Cell = const { Cell::new(0) }; - static FOLD_BOUNDARY_ZERO_CALL_INDEX: Cell = const { Cell::new(0) }; - static FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; - static FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; -} - -pub(super) fn reset_fold_call_index() { - FOLD_CALL_INDEX.with(|index| index.set(0)); - ACTIVE_FOLD_CALL_INDEX.with(|index| index.set(usize::MAX)); - FOLD_CHUNK_CALL_INDEX.with(|index| index.set(0)); - FOLD_DIRTY_CALL_INDEX.with(|index| index.set(0)); - FOLD_CLEAN_WINDOW_CALL_INDEX.with(|index| index.set(0)); - FOLD_BOUNDARY_ZERO_CALL_INDEX.with(|index| index.set(0)); - FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX.with(|index| index.set(0)); - FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX.with(|index| index.set(0)); -} - -fn next_fold_call_index() -> usize { - FOLD_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn active_fold_call_index() -> usize { - ACTIVE_FOLD_CALL_INDEX.with(|index| index.get()) -} - -fn enter_fold_call_index(index: usize) -> usize { - ACTIVE_FOLD_CALL_INDEX.with(|slot| { - let prior = slot.get(); - slot.set(index); - prior - }) -} - -fn restore_fold_call_index(prior: usize) { - ACTIVE_FOLD_CALL_INDEX.with(|slot| slot.set(prior)); -} - -fn next_fold_chunk_call_index() -> usize { - FOLD_CHUNK_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_fold_dirty_call_index() -> usize { - FOLD_DIRTY_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_fold_clean_window_call_index() -> usize { - FOLD_CLEAN_WINDOW_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_fold_boundary_zero_call_index() -> usize { - FOLD_BOUNDARY_ZERO_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_fused_cdouble_fwd_shift_call_index() -> usize { - FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_fused_cdouble_rev_shift_call_index() -> usize { - FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn env_index_value(name: &str, index: usize) -> Option { - std::env::var(name) - .ok() - .and_then(|value| { - value - .split(',') - .filter_map(|item| item.trim().split_once(':')) - .find_map(|(call, value)| { - (call.parse::().ok()? == index) - .then(|| value.parse::().ok()) - .flatten() - }) - }) -} - -fn skip_structural_dead_fused_carries() -> bool { - std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CARRIES").is_some() -} - -fn skip_structural_dead_fused_cdouble_shift0() -> bool { - std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_SHIFT0").is_some() -} - -fn skip_structural_dead_fused_dirty_fold() -> bool { - skip_structural_dead_fused_carries() - && std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_DIRTY_FOLD").is_some() -} - -fn skip_structural_dead_fused_clean_window() -> bool { - skip_structural_dead_fused_carries() - && std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CLEAN_WINDOW").is_some() -} - -fn skip_exact_fused_clean_fold() -> bool { - skip_structural_dead_fused_carries() - && (std::env::var_os("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER").is_some() - || std::env::var_os("TLM_FUSED_SKIP_EXACT_CLEAN_FOLD").is_some()) -} - -fn skip_exact_fused_chunk_fold() -> bool { - skip_structural_dead_fused_carries() - && (std::env::var_os("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER").is_some() - || std::env::var_os("TLM_FUSED_SKIP_EXACT_CHUNK_FOLD").is_some()) -} - -fn skip_fused_clean_fold_top31() -> bool { - skip_structural_dead_fused_carries() - && std::env::var_os("TLM_FUSED_CLEAN_FOLD_SKIP_TOP31").is_some() -} - -const FUSED_CLEAN_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (345, 0, 3), - (345, 29, 31), - (327, 0, 3), - (327, 30, 31), - (353, 0, 3), - (353, 30, 31), - (355, 0, 3), - (355, 30, 31), - (377, 0, 3), - (377, 30, 31), - (419, 0, 3), - (419, 29, 30), - (431, 0, 3), - (431, 30, 31), - (432, 0, 3), - (432, 29, 29), - (432, 31, 31), - (438, 0, 3), - (438, 30, 31), - (440, 0, 3), - (440, 30, 31), - (446, 0, 3), - (446, 30, 31), - (456, 0, 3), - (456, 30, 31), - (484, 0, 3), - (484, 30, 31), - (491, 0, 3), - (491, 30, 31), - (511, 0, 3), - (511, 30, 31), - (0, 1, 3), - (0, 29, 30), - (101, 1, 3), - (101, 30, 31), - (12, 1, 3), - (12, 30, 31), - (121, 1, 3), - (121, 29, 29), - (121, 31, 31), - (148, 1, 3), - (148, 30, 31), - (156, 1, 3), - (156, 30, 31), - (167, 1, 3), - (167, 29, 29), - (167, 31, 31), - (191, 1, 3), - (191, 30, 31), - (192, 1, 3), - (192, 30, 31), - (318, 0, 3), - (318, 31, 31), - (320, 0, 3), - (320, 31, 31), - (321, 0, 3), - (321, 31, 31), - (323, 0, 3), - (323, 31, 31), - (324, 0, 3), - (324, 31, 31), - (325, 0, 3), - (325, 31, 31), - (329, 0, 3), - (329, 30, 30), - (333, 0, 3), - (333, 31, 31), - (337, 0, 3), - (337, 30, 30), - (338, 0, 3), - (338, 31, 31), - (340, 0, 3), - (340, 31, 31), - (343, 0, 3), - (343, 31, 31), - (344, 0, 3), - (344, 31, 31), - (346, 0, 3), - (346, 31, 31), - (347, 0, 3), - (347, 30, 30), - (348, 0, 3), - (348, 31, 31), - (349, 0, 3), - (349, 31, 31), - (350, 0, 3), - (350, 31, 31), - (354, 0, 3), - (354, 30, 30), - (360, 0, 3), - (360, 31, 31), - (362, 0, 3), - (362, 31, 31), - (363, 0, 3), - (363, 31, 31), - (365, 0, 3), - (365, 31, 31), - (366, 0, 3), - (366, 31, 31), - (368, 0, 3), - (368, 31, 31), - (370, 0, 3), - (370, 31, 31), - (371, 0, 3), - (371, 30, 30), - (372, 0, 3), - (372, 31, 31), - (373, 0, 3), - (373, 31, 31), - (376, 0, 3), - (376, 31, 31), - (378, 0, 3), - (378, 31, 31), - (379, 0, 3), - (379, 31, 31), - (380, 0, 3), - (380, 31, 31), - (381, 0, 3), - (381, 31, 31), - (385, 0, 3), - (385, 31, 31), - (387, 0, 3), - (387, 31, 31), - (393, 0, 3), - (393, 30, 30), - (394, 0, 3), - (394, 31, 31), - (399, 0, 3), - (399, 31, 31), - (400, 0, 3), - (400, 31, 31), - (402, 0, 3), - (402, 31, 31), - (403, 0, 3), - (403, 31, 31), - (406, 0, 3), - (406, 30, 30), - (410, 0, 3), - (410, 31, 31), - (411, 0, 3), - (411, 31, 31), - (414, 0, 3), - (414, 31, 31), - (415, 0, 3), - (415, 31, 31), - (420, 0, 3), - (420, 31, 31), - (425, 0, 3), - (425, 31, 31), - (429, 0, 3), - (429, 31, 31), - (434, 0, 3), - (434, 31, 31), - (435, 0, 3), - (435, 31, 31), - (436, 0, 3), - (436, 31, 31), - (437, 0, 3), - (437, 31, 31), - (447, 0, 3), - (447, 31, 31), - (449, 0, 3), - (449, 31, 31), - (452, 0, 3), - (452, 31, 31), - (454, 0, 3), - (454, 31, 31), - (455, 0, 3), - (455, 30, 30), - (457, 0, 3), - (457, 31, 31), - (461, 0, 3), - (461, 31, 31), - (463, 0, 3), - (463, 31, 31), - (465, 0, 3), - (465, 31, 31), - (466, 0, 3), - (466, 31, 31), - (475, 0, 3), - (475, 30, 30), - (479, 0, 3), - (479, 31, 31), - (480, 0, 3), - (480, 31, 31), - (485, 0, 3), - (485, 31, 31), - (486, 0, 3), - (486, 30, 30), - (493, 0, 3), - (493, 31, 31), - (496, 0, 3), - (496, 31, 31), - (497, 0, 3), - (497, 31, 31), - (500, 0, 3), - (500, 31, 31), - (501, 0, 3), - (501, 31, 31), - (502, 0, 3), - (502, 31, 31), - (503, 0, 3), - (503, 30, 30), - (507, 0, 3), - (507, 31, 31), - (508, 0, 3), - (508, 30, 30), - (509, 0, 3), - (509, 31, 31), - (51, 1, 3), - (51, 30, 31), - (510, 0, 3), - (510, 31, 31), - (513, 0, 3), - (513, 31, 31), - (54, 1, 3), - (54, 30, 31), - (64, 1, 3), - (64, 30, 31), - (10, 1, 3), - (10, 31, 31), - (100, 1, 3), - (100, 31, 31), - (104, 1, 3), - (104, 30, 30), - (105, 1, 3), - (105, 31, 31), - (107, 1, 3), - (107, 31, 31), - (108, 1, 3), - (108, 31, 31), - (111, 1, 3), - (111, 31, 31), - (112, 1, 3), - (112, 31, 31), - (115, 1, 3), - (115, 31, 31), - (116, 1, 3), - (116, 31, 31), - (117, 1, 3), - (117, 31, 31), - (124, 1, 3), - (124, 31, 31), - (125, 1, 3), - (125, 30, 30), - (126, 1, 3), - (126, 31, 31), - (127, 1, 3), - (127, 30, 30), - (128, 1, 3), - (128, 31, 31), - (13, 1, 3), - (13, 30, 30), - (131, 1, 3), - (131, 31, 31), - (132, 1, 3), - (132, 31, 31), - (134, 1, 3), - (134, 31, 31), - (135, 1, 3), - (135, 31, 31), - (137, 1, 3), - (137, 31, 31), - (14, 1, 3), - (14, 31, 31), - (142, 1, 3), - (142, 31, 31), - (144, 1, 3), - (144, 31, 31), - (15, 1, 3), - (15, 31, 31), - (154, 1, 3), - (154, 30, 30), - (157, 1, 3), - (157, 31, 31), - (158, 1, 3), - (158, 31, 31), - (160, 1, 3), - (160, 31, 31), - (161, 1, 3), - (161, 31, 31), - (162, 1, 3), - (162, 31, 31), - (164, 1, 3), - (164, 31, 31), - (166, 1, 3), - (166, 31, 31), - (169, 1, 3), - (169, 31, 31), - (171, 1, 3), - (171, 31, 31), - (172, 1, 3), - (172, 31, 31), - (174, 1, 3), - (174, 31, 31), - (175, 1, 3), - (175, 31, 31), - (178, 1, 3), - (178, 30, 30), - (179, 1, 3), - (179, 31, 31), - (18, 1, 3), - (18, 31, 31), - (180, 1, 3), - (180, 31, 31), - (181, 1, 3), - (181, 31, 31), - (182, 1, 3), - (182, 31, 31), - (189, 1, 3), - (189, 31, 31), - (2, 1, 3), - (2, 31, 31), - (23, 1, 3), - (23, 31, 31), - (24, 1, 3), - (24, 31, 31), - (26, 1, 3), - (26, 31, 31), - (29, 1, 3), - (29, 31, 31), - (31, 1, 3), - (31, 31, 31), - (322, 0, 3), - (326, 0, 3), - (328, 0, 3), - (330, 0, 3), - (331, 0, 3), - (332, 0, 3), - (334, 0, 3), - (335, 0, 3), - (336, 0, 3), - (339, 0, 3), - (341, 0, 3), - (342, 0, 3), - (351, 0, 3), - (352, 0, 3), - (356, 0, 3), - (357, 0, 3), - (358, 0, 3), - (359, 0, 3), - (361, 0, 3), - (364, 0, 3), - (367, 0, 3), - (369, 0, 3), - (37, 1, 3), - (37, 31, 31), - (374, 0, 3), - (375, 0, 3), - (38, 1, 3), - (38, 31, 31), - (382, 0, 3), - (383, 0, 3), - (384, 0, 3), - (386, 0, 3), - (388, 0, 3), - (389, 0, 3), - (390, 0, 3), - (391, 0, 3), - (392, 0, 3), - (395, 0, 3), - (396, 0, 3), - (397, 0, 3), - (398, 0, 3), - (4, 1, 3), - (4, 31, 31), - (40, 1, 3), - (40, 31, 31), - (401, 0, 3), - (404, 0, 3), - (405, 0, 3), - (407, 0, 3), - (408, 0, 3), - (409, 0, 3), - (412, 0, 3), - (413, 0, 3), - (416, 0, 3), - (417, 0, 3), - (418, 0, 3), - (421, 0, 3), - (422, 0, 3), - (423, 0, 3), - (424, 0, 3), - (426, 0, 3), - (427, 0, 3), - (428, 0, 3), - (43, 1, 3), - (43, 31, 31), - (430, 0, 3), - (433, 0, 3), - (439, 0, 3), - (44, 1, 3), - (44, 31, 31), - (441, 0, 3), - (442, 0, 3), - (443, 0, 3), - (444, 0, 3), - (445, 0, 3), - (448, 0, 3), - (45, 1, 3), - (45, 31, 31), - (450, 0, 3), - (451, 0, 3), - (453, 0, 3), - (458, 0, 3), - (459, 0, 3), - (46, 1, 3), - (46, 31, 31), - (460, 0, 3), - (462, 0, 3), - (464, 0, 3), - (467, 0, 3), - (468, 0, 3), - (469, 0, 3), - (470, 0, 3), - (471, 0, 3), - (472, 0, 3), - (473, 0, 3), - (474, 0, 3), - (476, 0, 3), - (477, 0, 3), - (478, 0, 3), - (481, 0, 3), - (482, 0, 3), - (483, 0, 3), - (487, 0, 3), - (488, 0, 3), - (489, 0, 3), - (490, 0, 3), - (492, 0, 3), - (494, 0, 3), - (495, 0, 3), - (498, 0, 3), - (499, 0, 3), - (504, 0, 3), - (505, 0, 3), - (506, 0, 3), - (512, 0, 3), - (53, 1, 3), - (53, 31, 31), - (56, 1, 3), - (56, 31, 31), - (57, 1, 3), - (57, 31, 31), - (59, 1, 3), - (59, 31, 31), - (6, 1, 3), - (6, 31, 31), - (61, 1, 3), - (61, 31, 31), - (65, 1, 3), - (65, 31, 31), - (67, 1, 3), - (67, 31, 31), - (7, 1, 3), - (7, 31, 31), - (71, 1, 3), - (71, 31, 31), - (74, 1, 3), - (74, 31, 31), - (75, 1, 3), - (75, 31, 31), - (78, 1, 3), - (78, 31, 31), - (79, 1, 3), - (79, 31, 31), - (85, 1, 3), - (85, 30, 30), - (86, 1, 3), - (86, 31, 31), - (87, 1, 3), - (87, 31, 31), - (88, 1, 3), - (88, 31, 31), - (89, 1, 3), - (89, 31, 31), - (9, 1, 3), - (9, 31, 31), - (90, 1, 3), - (90, 31, 31), - (91, 1, 3), - (91, 30, 30), - (94, 1, 3), - (94, 29, 29), - (95, 1, 3), - (95, 31, 31), - (96, 1, 3), - (96, 31, 31), - (98, 1, 3), - (98, 31, 31), - (99, 1, 3), - (99, 31, 31), -]; - -const FUSED_CHUNK_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (1008, 0, 3), - (1022, 0, 3), - (1036, 0, 3), - (1050, 0, 3), - (1064, 0, 3), - (1078, 0, 3), - (1092, 0, 3), - (1106, 0, 3), - (112, 0, 3), - (1120, 0, 3), - (1134, 0, 3), - (1148, 0, 3), - (1162, 0, 3), - (1176, 0, 3), - (1190, 0, 3), - (1204, 0, 3), - (1218, 0, 3), - (1232, 0, 3), - (1246, 0, 3), - (126, 0, 3), - (1260, 0, 3), - (1274, 0, 3), - (1288, 0, 3), - (1302, 0, 3), - (1316, 0, 3), - (1330, 0, 3), - (1344, 0, 3), - (1358, 0, 3), - (1372, 0, 3), - (1386, 0, 3), - (140, 0, 3), - (1400, 0, 3), - (1414, 0, 3), - (1428, 0, 3), - (1442, 0, 3), - (1456, 0, 3), - (1470, 0, 3), - (1484, 0, 3), - (1498, 0, 3), - (1512, 0, 3), - (1526, 0, 3), - (154, 0, 3), - (1540, 0, 3), - (1554, 0, 3), - (168, 0, 3), - (182, 0, 3), - (196, 0, 3), - (210, 0, 3), - (224, 0, 3), - (238, 0, 3), - (252, 0, 3), - (266, 0, 3), - (280, 0, 3), - (294, 0, 3), - (308, 0, 3), - (322, 0, 3), - (336, 0, 3), - (350, 0, 3), - (364, 0, 3), - (378, 0, 3), - (392, 0, 3), - (406, 0, 3), - (420, 0, 3), - (434, 0, 3), - (448, 0, 3), - (462, 0, 3), - (476, 0, 3), - (490, 0, 3), - (504, 0, 3), - (518, 0, 3), - (532, 0, 3), - (546, 0, 3), - (560, 0, 3), - (574, 0, 3), - (763, 0, 3), - (777, 0, 3), - (784, 0, 3), - (791, 0, 3), - (796, 0, 3), - (798, 0, 3), - (805, 0, 3), - (812, 0, 3), - (819, 0, 3), - (826, 0, 3), - (833, 0, 3), - (84, 0, 3), - (840, 0, 3), - (847, 0, 3), - (854, 0, 3), - (868, 0, 3), - (882, 0, 3), - (896, 0, 3), - (910, 0, 3), - (924, 0, 3), - (938, 0, 3), - (952, 0, 3), - (966, 0, 3), - (98, 0, 3), - (980, 0, 3), - (994, 0, 3), -]; - -const FUSED_DIRTY_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (6, 0, 3), - (6, 21, 24), - (6, 26, 31), - (6, 43, 45), - (6, 47, 51), - (5, 7, 18), - (5, 32, 38), - (4, 9, 18), - (4, 30, 30), - (4, 32, 38), - (3, 15, 23), - (3, 36, 42), - (1, 11, 19), - (1, 34, 39), - (7, 10, 18), - (7, 32, 32), - (7, 34, 38), - (2, 10, 18), - (2, 33, 37), - (8, 11, 19), - (8, 35, 36), - (8, 38, 39), - (0, 11, 17), - (0, 34, 34), - (0, 36, 38), - (9, 12, 18), - (9, 35, 38), -]; - -const FUSED_CLEAN_WINDOW_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (0, 1, 3), - (1, 1, 3), - (2, 1, 3), - (3, 1, 3), - (4, 1, 3), - (5, 0, 3), - (6, 0, 3), - (7, 0, 3), - (8, 0, 3), -]; - -const FUSED_CLEAN_FOLD_REMAINDER_KEYS: &[u32] = &[ - 257, 258, 259, 769, 770, 771, 1281, 1282, 1283, 2049, 2050, 2051, 2817, 2818, - 2819, 4097, 4098, 4099, 4353, 4354, 4355, 4865, 4866, 4867, 5121, 5122, 5123, - 5377, 5378, 5379, 5633, 5634, 5635, 6401, 6402, 6403, 6913, 6914, 6915, 7169, - 7170, 7171, 7681, 7682, 7683, 8193, 8194, 8195, 8449, 8450, 8451, 8705, 8706, - 8707, 8961, 8962, 8963, 9217, 9218, 9219, 9985, 9986, 9987, 10497, 10498, - 10499, 10753, 10754, 10755, 12033, 12034, 12035, 12289, 12290, 12291, 12545, - 12546, 12547, 12801, 12802, 12803, 13313, 13314, 13315, 14081, 14082, 14083, - 14849, 14850, 14851, 15361, 15362, 15363, 15873, 15874, 15875, 16129, 16130, - 16131, 16897, 16898, 16899, 17409, 17410, 17411, 17665, 17666, 17667, 17921, - 17922, 17923, 18433, 18434, 18435, 18689, 18690, 18691, 19457, 19458, 19459, - 19713, 19714, 19715, 20481, 20482, 20483, 20737, 20738, 20739, 20993, 20994, - 20995, 21249, 21250, 21251, 21505, 21506, 21507, 23553, 23554, 23555, 23809, - 23810, 23811, 24833, 24834, 24835, 26113, 26114, 26115, 26369, 26370, 26371, - 27137, 27138, 27139, 27905, 27906, 27907, 28161, 28162, 28163, 28929, 28930, - 28931, 29185, 29186, 29187, 30209, 30210, 30211, 30465, 30466, 30467, 30721, - 30722, 30723, 31233, 31234, 31235, 31489, 31490, 31491, 33025, 33026, 33027, - 33281, 33282, 33283, 34049, 34050, 34051, 34817, 34818, 34819, 35329, 35330, - 35331, 35585, 35586, 35587, 35841, 35842, 35843, 36097, 36098, 36099, 36609, - 36610, 36611, 37121, 37122, 37123, 37377, 37378, 37379, 37633, 37634, 37635, - 38145, 38146, 38147, 38401, 38402, 38403, 38657, 38658, 38659, 38913, 38914, - 38915, 39169, 39170, 39171, 39681, 39682, 39683, 40705, 40706, 40707, 41729, - 41730, 41731, 42241, 42242, 42243, 43009, 43010, 43011, 43521, 43522, 43523, - 44289, 44290, 44291, 45057, 45058, 45059, 45313, 45314, 45315, 46849, 46850, - 46851, 47105, 47106, 47107, 47361, 47362, 47363, 47617, 47618, 47619, 47873, - 47874, 47875, 48129, 48130, 48131, 48641, 48642, 48643, 49409, 49410, 49411, - 49921, 49922, 49923, -]; - -const FUSED_CHUNK_FOLD_REMAINDER_KEYS: &[u32] = &[ - 1, 2, 3, 1795, 3585, 3586, 3587, 5378, 7169, 7170, 7171, 8962, 10753, 10754, - 10755, 12547, 14337, 14338, 14339, 17921, 17922, 17923, 23299, 30466, 34051, - 37635, 41219, 44801, 44803, 48387, 55555, 62723, 66306, 77059, 84227, 87810, - 87811, 89344, 92928, 112899, 116482, 116483, 120066, 123651, 134403, 141571, - 145155, 148737, 148739, 150529, 150530, 150531, 152322, 154113, 154114, 154115, - 155907, 157697, 157698, 157699, 159489, 159490, 159491, 161024, 161281, 161282, - 161283, 163075, 164608, 164865, 164866, 164867, 166658, 166659, 167939, 168449, - 168450, 168451, 170240, 170242, 170243, 171523, 171776, 172033, 172034, 172035, - 173571, 173825, 173827, 175360, 175617, 175618, 175619, 177409, 177410, 177411, - 178691, 178944, 179201, 179202, 179203, 180993, 180994, 180995, 182275, 182528, - 182785, 182786, 182787, 184578, 184579, 185859, 186112, 186369, 186370, 186371, - 187907, 188161, 188162, 188163, 189441, 189443, 189696, 189953, 189954, 189955, - 191491, 191744, 191746, 191747, 193025, 193027, 193537, 193538, 193539, 195075, - 195328, 196609, 196610, 196611, 196864, 197121, 197122, 197123, 198657, 198658, - 198659, 198912, 200192, 200194, 200195, 200448, 202241, 202243, 202496, 203776, - 204032, 205826, 206080, 207361, 207362, 207363, 207616, 209410, 209411, 209664, - 210946, 210947, 213248, 214529, 214530, 214531, 214784, 216832, 218115, 218368, - 220419, 221699, 221952, 224001, 224002, 225283, 225536, 227586, 227587, 231170, - 231171, 232704, 234754, 236288, 238339, 239872, 241922, 245506, 245507, 247040, - 263426, 263427, 264960, 267011, 277762, 288515, 290048, 292098, 295683, 299267, - 304384, 306435, 313603, 320771, 322304, 324354, 324355, 329472, 331522, 345859, - 349442, 349443, 353027, 356611, 367362, 367363, 378115, 379648, 381699, 386816, - 392450, 396035, 399619, -]; - -fn fused_range_contains(ranges: &[(usize, usize, usize)], call_index: usize, bit: usize) -> bool { - skip_structural_dead_fused_carries() - && ranges - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn fused_key_contains(keys: &[u32], call_index: usize, bit: usize) -> bool { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - keys.binary_search(&key).is_ok() -} - -const FUSED_BOUNDARY_ZERO_REMAINDER_KEYS: &[u32] = &[ - 1282, 3842, 6402, 8962, 14082, 16642, 21762, 24322, 32001, 39682, 42242, - 47361, 47362, 49922, 51458, 52482, 55040, 55042, 57601, 62722, 70402, - 75521, 83202, 85761, 85762, 90882, 93442, 96002, 106241, 108802, 111362, - 113921, 113922, 116482, 118018, 119041, 119042, 121600, 121602, 124161, - 126721, 126722, 128256, 128258, 129281, 129282, 130818, 131840, 131841, - 131842, 132098, 133376, 133377, 133378, 134400, 134401, 134402, 135937, - 135938, 136960, 136962, 138497, 138498, 139520, 139521, 139522, 139777, - 141056, 141058, 141314, 142080, 142081, 142082, 142337, 142338, 143616, - 143617, 143618, 144640, 144641, 144642, 144897, 146177, 146178, 147200, - 147201, 147202, 147458, 148738, 149760, 149761, 149762, 150016, 150017, - 150018, 151297, 151298, 152320, 152321, 152322, 152578, 153857, 154880, - 154881, 154882, 156418, 158976, 158978, 160001, 160002, 160258, 162560, - 162561, 164096, 164098, 165122, 167682, 170241, 172801, 172802, 175362, - 177922, 180482, 183041, 183042, 185602, 188162, 190722, 193281, 193282, - 198402, 203521, 206082, 208641, 208642, 211201, 211202, 216322, 218882, - 226561, 229122, 231682, 234241, 236802, 244481, 249601, 249602, 252161, - 253698, 259842, 262402, 267521, 270082, 275202, 277762, 280322, 285442, -]; - -fn fused_boundary_zero_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("FUSEDBZ") { - return false; - } - - std::env::var_os("TLM_FUSED_SKIP_EXACT_BOUNDARY_ZERO").is_some() - && fused_key_contains(FUSED_BOUNDARY_ZERO_REMAINDER_KEYS, call_index, bit) -} - -fn fused_clean_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("FUSEDCF") { - return false; - } - - fused_range_contains(FUSED_CLEAN_FOLD_DEAD_RANGES, call_index, bit) - || (skip_fused_clean_fold_top31() && bit == 31) - || (skip_exact_fused_clean_fold() - && fused_key_contains(FUSED_CLEAN_FOLD_REMAINDER_KEYS, call_index, bit)) -} - -fn fused_chunk_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("FUSEDKF") { - return false; - } - - fused_range_contains(FUSED_CHUNK_FOLD_DEAD_RANGES, call_index, bit) - || (skip_exact_fused_chunk_fold() - && fused_key_contains(FUSED_CHUNK_FOLD_REMAINDER_KEYS, call_index, bit)) -} - -fn fused_dirty_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("FUSEDDF") { - return false; - } - - skip_structural_dead_fused_dirty_fold() - && FUSED_DIRTY_FOLD_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn fused_clean_window_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { - if super::drops_off_family("FUSEDCW") { - return false; - } - - skip_structural_dead_fused_clean_window() - && FUSED_CLEAN_WINDOW_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn fold_call_reserve(index: usize, default: usize) -> usize { - let base = env_index_value("TLM_TARGET_FOLD_CALL_RESERVES", index).unwrap_or(default); - env_index_value("TLM_TARGET_FOLD_CALL_RESERVE_OVERRIDES", index).unwrap_or(base) -} - -fn fold_ctl(p: usize) -> u8 { - match p { - 0 | 4 | 6 | 32 => 1, - 1 | 5 | 33 => 2, - 7 => 3, - 8 | 9 => 4, - 10 => 5, - 11 => 6, - _ => 0, - } -} - -fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { - let bit = circ.alloc_bit(); - circ.hmr(*t, bit); - circ.cz_if_bit(*a, *b, bit); -} - -fn toggle_dnot_e_from_intersection( - circ: &mut B, - d: &QubitId, - cc: &QubitId, - dne: &QubitId, -) { - circ.cx(*d, *dne); - circ.cx(*cc, *dne); -} - -fn add_carry_into_tail_prefix(circ: &mut B, y: &[QubitId], c: &QubitId) { - if std::env::var("TLM_FOLD_TAIL_CINC").ok().as_deref() == Some("1") { - - let yv: Vec = y.to_vec(); - super::mcx::cinc_khattar_gidney(circ, &yv, c); - return; - } - - let t = y.len(); - for k in (1..t).rev() { - let mut ctrls: Vec<&QubitId> = Vec::with_capacity(k + 1); - ctrls.push(c); - ctrls.extend(y[..k].iter()); - super::mcx::mcx_clean_k(circ, &ctrls, &y[k]); - } - circ.cx(*c, y[0]); -} - -fn add_mf_fold_clean(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId]) { - add_mf_fold_clean_tail(circ, e, d, y, None); -} - -fn add_mf_fold_clean_tail(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], tail_from: Option) { - let l = y.len(); - assert!(l >= 2, "fold needs L >= 2"); - let loop_end = tail_from.unwrap_or(l - 1); - const LAST_DERIVED: usize = 9; - const LAST_AND: usize = 11; - - let mut cc = Some(circ.alloc_qubit()); - circ.ccx(*e, *d, *cc.as_ref().unwrap()); - let mut dne = Some(circ.alloc_qubit()); - toggle_dnot_e_from_intersection( - circ, - d, - cc.as_ref().unwrap(), - dne.as_ref().unwrap(), - ); - let mut sxor = Some(circ.alloc_qubit()); - circ.cx(*e, *sxor.as_ref().unwrap()); - circ.cx(*d, *sxor.as_ref().unwrap()); - let mut sor = Some(circ.alloc_qubit()); - circ.cx(*sxor.as_ref().unwrap(), *sor.as_ref().unwrap()); - circ.cx(*cc.as_ref().unwrap(), *sor.as_ref().unwrap()); - - fn fc<'a>(p: usize, e: &'a QubitId, d: &'a QubitId, cc: Option<&'a QubitId>, dne: Option<&'a QubitId>, sx: Option<&'a QubitId>, so: Option<&'a QubitId>) -> Option<&'a QubitId> { - match fold_ctl(p) { - 1 => Some(e), - 2 => Some(d), - 3 => sx, - 4 => so, - 5 => dne, - 6 => cc, - _ => None, - } - } - - let mut cy: Vec> = Vec::with_capacity(l - 1); - let c1 = circ.alloc_qubit(); - if let Some(a0) = fc(0, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - if !skip_structural_dead_fused_carries() { - let old_context = crate::point_add::set_op_trace_context( - 0x0d00_0000 | (((active_fold_call_index() as u32) & 0xffff) << 8), - ); - circ.ccx(*a0, y[0], c1); - crate::point_add::restore_op_trace_context(old_context); - } - circ.cx(*a0, y[0]); - } - cy.push(Some(c1)); - for i in 1..loop_end { - let next = circ.alloc_qubit(); - { - let ci = cy[i - 1].as_ref().unwrap(); - circ.cx(*ci, y[i]); - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, *ci); - } - if !fused_clean_fold_has_structurally_dead_carry(active_fold_call_index(), i) { - let old_context = crate::point_add::set_op_trace_context( - 0x0d00_0000 | (((active_fold_call_index() as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(y[i], *ci, next); - crate::point_add::restore_op_trace_context(old_context); - } - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, *ci); - } - circ.cx(*ci, next); - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, y[i]); - } - } - cy.push(Some(next)); - if i == LAST_DERIVED { - let so = sor.take().unwrap(); - circ.cx(*sxor.as_ref().unwrap(), so); - circ.cx(*cc.as_ref().unwrap(), so); - circ.zero_and_free(so); - let sx = sxor.take().unwrap(); - circ.cx(*e, sx); - circ.cx(*d, sx); - circ.zero_and_free(sx); - } - if i == LAST_AND { - let dn = dne.take().unwrap(); - toggle_dnot_e_from_intersection(circ, d, cc.as_ref().unwrap(), &dn); - circ.zero_and_free(dn); - let c = cc.take().unwrap(); - clear_and(circ, &c, e, d); - circ.zero_and_free(c); - } - } - match tail_from { - None => { - - if let Some(at) = fc(l - 1, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*at, y[l - 1]); - } - circ.cx(*cy[l - 2].as_ref().unwrap(), y[l - 1]); - } - Some(nv) => { - - add_carry_into_tail_prefix(circ, &y[nv..], cy[nv - 1].as_ref().unwrap()); - } - } - - for i in (1..loop_end).rev() { - if i == LAST_AND { - let c = circ.alloc_qubit(); - circ.ccx(*e, *d, c); - cc = Some(c); - let dn = circ.alloc_qubit(); - toggle_dnot_e_from_intersection(circ, d, cc.as_ref().unwrap(), &dn); - dne = Some(dn); - } - if i == LAST_DERIVED { - let sx = circ.alloc_qubit(); - circ.cx(*e, sx); - circ.cx(*d, sx); - let so = circ.alloc_qubit(); - circ.cx(sx, so); - circ.cx(*cc.as_ref().unwrap(), so); - sxor = Some(sx); - sor = Some(so); - } - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, y[i]); - } - let next = cy[i].take().unwrap(); - let ci = cy[i - 1].take().unwrap(); - circ.cx(ci, next); - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, ci); - } - - let bit = circ.alloc_bit(); - circ.hmr(next, bit); - circ.zero_and_free(next); - circ.cz_if_bit(y[i], ci, bit); - if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*ai, ci); - circ.cx(*ai, y[i]); - } - cy[i - 1] = Some(ci); - } - - let cy1 = cy[0].take().unwrap(); - if let Some(a0) = fc(0, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { - circ.cx(*a0, y[0]); - let bit = circ.alloc_bit(); - circ.hmr(cy1, bit); - circ.zero_and_free(cy1); - circ.cz_if_bit(y[0], *a0, bit); - circ.cx(*a0, y[0]); - } else { - circ.zero_and_free(cy1); - } - - let sx = sxor.take().unwrap(); - let so = sor.take().unwrap(); - let cc = cc.take().unwrap(); - let dne = dne.take().unwrap(); - toggle_dnot_e_from_intersection(circ, d, &cc, &dne); - circ.zero_and_free(dne); - circ.cx(sx, so); - circ.cx(cc, so); - circ.zero_and_free(so); - circ.cx(*e, sx); - circ.cx(*d, sx); - circ.zero_and_free(sx); - clear_and(circ, &cc, e, d); - circ.zero_and_free(cc); -} - -fn build_fold_controls(circ: &mut B, e: &QubitId, d: &QubitId) -> (QubitId, QubitId, QubitId, QubitId) { - let cc = circ.alloc_qubit(); - circ.ccx(*e, *d, cc); - let sxor = circ.alloc_qubit(); - circ.cx(*e, sxor); - circ.cx(*d, sxor); - let sor = circ.alloc_qubit(); - circ.cx(sxor, sor); - circ.cx(cc, sor); - let dne = circ.alloc_qubit(); - toggle_dnot_e_from_intersection(circ, d, &cc, &dne); - (cc, sxor, sor, dne) -} - -fn uncompute_fold_controls(circ: &mut B, e: &QubitId, d: &QubitId, cc: QubitId, sxor: QubitId, sor: QubitId, dne: QubitId) { - toggle_dnot_e_from_intersection(circ, d, &cc, &dne); - circ.zero_and_free(dne); - circ.cx(sxor, sor); - circ.cx(cc, sor); - circ.zero_and_free(sor); - circ.cx(*e, sxor); - circ.cx(*d, sxor); - circ.zero_and_free(sxor); - clear_and(circ, &cc, e, d); - circ.zero_and_free(cc); -} - -fn fold_ctl_map(e: QubitId, d: QubitId, cc: QubitId, sxor: QubitId, sor: QubitId, dne: QubitId, l: usize) -> Vec> { - (0..l).map(|p| match fold_ctl(p) { 1 => Some(e), 2 => Some(d), 3 => Some(sxor), 4 => Some(sor), 5 => Some(dne), 6 => Some(cc), _ => None }).collect() -} - -fn fold_chunk_clean(circ: &mut B, ctl: &[Option], y: &[QubitId], cin: Option<&QubitId>, cout: &QubitId) { - let chunk_call_index = next_fold_chunk_call_index(); - let s = y.len(); - if s == 0 { - if let Some(c) = cin { circ.cx(*c, *cout); } - return; - } - let mut cy: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); - for i in 0..s { - let on = ctl[i].as_ref(); - if i == 0 { - let dst: QubitId = if s == 1 { *cout } else { *cy[0].as_ref().unwrap() }; - match cin { - Some(c) => { - circ.cx(*c, y[0]); - if let Some(a) = on { circ.cx(*a, *c); } - let old_context = crate::point_add::set_op_trace_context( - 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8), - ); - circ.ccx(y[0], *c, dst); - crate::point_add::restore_op_trace_context(old_context); - if let Some(a) = on { circ.cx(*a, *c); } - circ.cx(*c, dst); - } - None => { - if let Some(a) = on { - if !skip_structural_dead_fused_carries() { - let old_context = crate::point_add::set_op_trace_context( - 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8), - ); - circ.ccx(*a, y[0], dst); - crate::point_add::restore_op_trace_context(old_context); - } - } - } - } - } else { - let ci: QubitId = *cy[i - 1].as_ref().unwrap(); - let dst: QubitId = if i == s - 1 { *cout } else { *cy[i].as_ref().unwrap() }; - circ.cx(ci, y[i]); - if let Some(a) = on { circ.cx(*a, ci); } - if !fused_chunk_fold_has_structurally_dead_carry(chunk_call_index, i) { - let old_context = crate::point_add::set_op_trace_context( - 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(y[i], ci, dst); - crate::point_add::restore_op_trace_context(old_context); - } - if let Some(a) = on { circ.cx(*a, ci); } - circ.cx(ci, dst); - } - } - for i in 0..s { - if let Some(a) = ctl[i].as_ref() { circ.cx(*a, y[i]); } - } - for i in (0..s - 1).rev() { - let on = ctl[i].as_ref(); - if let Some(a) = on { circ.cx(*a, y[i]); } - let next = cy[i].take().unwrap(); - if i == 0 { - match cin { - Some(c) => { - circ.cx(*c, next); - if let Some(a) = on { circ.cx(*a, *c); } - let bit = circ.alloc_bit(); - circ.hmr(next, bit); circ.zero_and_free(next); - circ.cz_if_bit(y[0], *c, bit); - if let Some(a) = on { circ.cx(*a, *c); circ.cx(*a, y[0]); } - } - None => { - let bit = circ.alloc_bit(); - circ.hmr(next, bit); circ.zero_and_free(next); - if let Some(a) = on { circ.cz_if_bit(y[0], *a, bit); } - if let Some(a) = on { circ.cx(*a, y[0]); } - } - } - } else { - let ci: QubitId = *cy[i - 1].as_ref().unwrap(); - circ.cx(ci, next); - if let Some(a) = on { circ.cx(*a, ci); } - let bit = circ.alloc_bit(); - circ.hmr(next, bit); circ.zero_and_free(next); - circ.cz_if_bit(y[i], ci, bit); - if let Some(a) = on { circ.cx(*a, ci); circ.cx(*a, y[i]); } - } - } -} - -fn fold_boundary_erase(circ: &mut B, ctl: &[Option], y: &[QubitId], cin: Option<&QubitId>, carry: QubitId) { - if std::env::var("TLM_FOLD_BOUNDARY_ZERO_DIRECT") - .ok() - .as_deref() - == Some("1") - && cin.is_some() - && ctl.iter().all(Option::is_none) - { - fold_boundary_erase_zero_direct(circ, y, cin.expect("cin checked"), carry); - return; - } - let s = y.len(); - let temp: Vec = (0..s).map(|_| circ.alloc_qubit()).collect(); - for (i, c) in ctl.iter().enumerate() { - if let Some(a) = c { circ.cx(*a, temp[i]); } - } - match cin { - Some(cin) => super::arith::erase_carry_gated_opt(circ, None, y, &temp, cin, &carry, None), - None => { - super::arith::erase_carry_gated_zero_cin_opt(circ, None, y, &temp, &carry, None); - circ.zero_and_free(carry); - } - } - for (i, c) in ctl.iter().enumerate() { - if let Some(a) = c { circ.cx(*a, temp[i]); } - } - for q in temp { circ.zero_and_free(q); } -} - -fn fold_boundary_erase_zero_direct(circ: &mut B, y: &[QubitId], cin: &QubitId, carry: QubitId) { - let boundary_call_index = next_fold_boundary_zero_call_index(); - let n = y.len(); - assert!(n >= 1, "zero boundary erase needs >= 1 bit"); - let bit = circ.alloc_bit(); - circ.hmr(carry, bit); - circ.zero_and_free(carry); - circ.push_condition(bit); - - let mut cy: Vec> = Vec::with_capacity(n); - let c0 = circ.alloc_qubit(); - circ.x(c0); - circ.cx(*cin, c0); - cy.push(Some(c0)); - for i in 0..n - 1 { - let next = circ.alloc_qubit(); - let ci = cy[i].as_ref().unwrap(); - circ.cx(*ci, y[i]); - circ.x(*ci); - let old_context = crate::point_add::set_op_trace_context( - 0x1c00_0000 | (((boundary_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - if !fused_boundary_zero_has_structurally_dead_carry(boundary_call_index, i) { - circ.ccx(y[i], *ci, next); - } - crate::point_add::restore_op_trace_context(old_context); - circ.x(*ci); - circ.cx(*ci, next); - cy.push(Some(next)); - } - { - let i = n - 1; - let ci = cy[i].as_ref().unwrap(); - circ.cx(*ci, y[i]); - circ.neg(); - circ.x(*ci); - circ.cz(y[i], *ci); - circ.x(*ci); - circ.z(*ci); - circ.cx(*ci, y[i]); - } - for i in (0..n - 1).rev() { - let next = cy[i + 1].take().unwrap(); - let ci = cy[i].as_ref().unwrap(); - circ.cx(*ci, next); - let mbit = circ.alloc_bit(); - circ.hmr(next, mbit); - circ.zero_and_free(next); - circ.x(*ci); - circ.cz_if_bit(y[i], *ci, mbit); - circ.x(*ci); - circ.cx(*ci, y[i]); - } - let c0 = cy[0].take().unwrap(); - circ.cx(*cin, c0); - circ.x(c0); - circ.zero_and_free(c0); - circ.pop_condition(); -} - -fn add_mf_fold_chunked(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], s_chunk: usize) { - let l = y.len(); - let release_controls = std::env::var("TLM_FOLD_RELEASE_CONTROLS") - .ok() - .as_deref() - == Some("1"); - let zero_cin = std::env::var("TLM_FOLD_CHUNK_ZERO_CIN") - .ok() - .as_deref() - == Some("1"); - let mut controls = Some(build_fold_controls(circ, e, d)); - let (cc, sxor, sor, dne) = controls.expect("fold controls present"); - let mut ctl = fold_ctl_map(*e, *d, cc, sxor, sor, dne, l); - let cin0 = (!zero_cin).then(|| circ.alloc_qubit()); - let nch = l.div_ceil(s_chunk); - let last_control_chunk = 11usize.min(l - 1) / s_chunk; - let mut boundary: Vec = Vec::with_capacity(nch); - for j in 0..nch { - let lo = j * s_chunk; - let hi = ((j + 1) * s_chunk).min(l); - let cout = circ.alloc_qubit(); - let cin = if j == 0 { - cin0.as_ref() - } else { - Some(&boundary[j - 1]) - }; - fold_chunk_clean(circ, &ctl[lo..hi], &y[lo..hi], cin, &cout); - boundary.push(cout); - if release_controls && j == last_control_chunk && j + 1 < nch { - let (cc, sxor, sor, dne) = controls.take().expect("fold controls present"); - uncompute_fold_controls(circ, e, d, cc, sxor, sor, dne); - } - } - for j in (0..nch).rev() { - if release_controls && j == last_control_chunk && controls.is_none() { - let rebuilt = build_fold_controls(circ, e, d); - ctl = fold_ctl_map(*e, *d, rebuilt.0, rebuilt.1, rebuilt.2, rebuilt.3, l); - controls = Some(rebuilt); - } - let lo = j * s_chunk; - let hi = ((j + 1) * s_chunk).min(l); - let bnd = boundary.pop().expect("boundary present"); - let cin = if j == 0 { - cin0.as_ref() - } else { - Some(&boundary[j - 1]) - }; - fold_boundary_erase(circ, &ctl[lo..hi], &y[lo..hi], cin, bnd); - } - if let Some(cin0) = cin0 { - circ.zero_and_free(cin0); - } - let (cc, sxor, sor, dne) = controls.take().expect("fold controls restored"); - uncompute_fold_controls(circ, e, d, cc, sxor, sor, dne); -} - -enum OnCtl { - None, - E, - D, - Owned(QubitId), -} - -fn on_ctl_apply(circ: &mut B, e: &QubitId, d: &QubitId, k: u8, q: &QubitId) { - match k { - 3 => { - circ.cx(*e, *q); - circ.cx(*d, *q); - } - 4 => { - circ.x(*e); - circ.x(*d); - circ.ccx(*e, *d, *q); - circ.x(*q); - circ.x(*e); - circ.x(*d); - } - 5 => { - circ.x(*e); - circ.ccx(*e, *d, *q); - circ.x(*e); - } - 6 => circ.ccx(*e, *d, *q), - _ => {} - } -} - -fn on_ctl(circ: &mut B, e: &QubitId, d: &QubitId, p: usize) -> OnCtl { - match fold_ctl(p) { - 1 => OnCtl::E, - 2 => OnCtl::D, - k @ (3 | 4 | 5 | 6) => { - let q = circ.alloc_qubit(); - on_ctl_apply(circ, e, d, k, &q); - OnCtl::Owned(q) - } - _ => OnCtl::None, - } -} - -fn on_ctl_ref(c: &OnCtl, e: &QubitId, d: &QubitId) -> Option { - match c { - OnCtl::None => None, - OnCtl::E => Some(*e), - OnCtl::D => Some(*d), - OnCtl::Owned(q) => Some(*q), - } -} - -fn on_ctl_clear_nonlinear_hmr( - circ: &mut B, - e: &QubitId, - d: &QubitId, - k: u8, - q: &QubitId, -) { - let bit = circ.alloc_bit(); - circ.hmr(*q, bit); - match k { - 4 => { - circ.z_if_bit(*e, bit); - circ.z_if_bit(*d, bit); - circ.cz_if_bit(*e, *d, bit); - } - 5 => { - circ.z_if_bit(*d, bit); - circ.cz_if_bit(*e, *d, bit); - } - 6 => circ.cz_if_bit(*e, *d, bit), - _ => unreachable!("HMR clear requires a nonlinear fold control"), - } -} - -fn on_ctl_free(circ: &mut B, e: &QubitId, d: &QubitId, p: usize, c: OnCtl) { - if let OnCtl::Owned(q) = c { - let k = fold_ctl(p); - let hmr_disabled = std::env::var("TLM_FOLD_HMR_CONTROL_CLEANUP_DISABLE") - .ok() - .as_deref() - == Some("1"); - if k == 3 || hmr_disabled { - - on_ctl_apply(circ, e, d, k, &q); - } else { - on_ctl_clear_nonlinear_hmr(circ, e, d, k, &q); - } - circ.zero_and_free(q); - } -} - -fn xor_carries_perpos(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], out: &[QubitId], carry_in: Option<&QubitId>) { - let n = y.len(); - fn ccx_cond(circ: &mut B, aq: Option<&QubitId>, c1: &QubitId, c2: &QubitId, t: &QubitId, g0: bool, g1: bool) { - if let Some(a) = aq { - if g0 { - circ.cx(*a, *c1); - } - if g1 { - circ.cx(*a, *c2); - } - } - circ.ccx(*c1, *c2, *t); - if let Some(a) = aq { - if g0 { - circ.cx(*a, *c1); - } - if g1 { - circ.cx(*a, *c2); - } - } - } - for i in (1..n - 1).rev() { - let c = on_ctl(circ, e, d, base + i); - let aq = on_ctl_ref(&c, e, d); - let g0 = aq.is_some(); - ccx_cond(circ, aq.as_ref(), &y[i], &out[i - 1], &out[i], g0, false); - on_ctl_free(circ, e, d, base + i, c); - } - for i in 0..n - 1 { - let c = on_ctl(circ, e, d, base + i); - if let Some(a) = on_ctl_ref(&c, e, d) { - circ.cx(a, out[i]); - } - on_ctl_free(circ, e, d, base + i, c); - } - { - let c = on_ctl(circ, e, d, base); - let aq = on_ctl_ref(&c, e, d); - let g = aq.is_some(); - match carry_in { - Some(cy) => ccx_cond(circ, aq.as_ref(), cy, &y[0], &out[0], g, g), - None => { - let cin = circ.alloc_qubit(); - ccx_cond(circ, aq.as_ref(), &cin, &y[0], &out[0], g, g); - circ.zero_and_free(cin); - } - } - on_ctl_free(circ, e, d, base, c); - } - for i in 1..n - 1 { - let c = on_ctl(circ, e, d, base + i); - let aq = on_ctl_ref(&c, e, d); - let gi = aq.is_some(); - ccx_cond(circ, aq.as_ref(), &y[i], &out[i - 1], &out[i], gi, gi); - on_ctl_free(circ, e, d, base + i, c); - } -} - -fn dirty_body(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], dirty: &[QubitId], carry_in: Option<&QubitId>) { - let dirty_call_index = next_fold_dirty_call_index(); - let l = y.len(); - assert!(l >= 2); - assert!(dirty.len() >= l - 1, "need L-1 borrowed dirty bits"); - let mut cin_owned = if carry_in.is_none() { Some(circ.alloc_qubit()) } else { None }; - let mut bits: Vec = Vec::with_capacity(l - 1); - let mut prev_new: Option = None; - for i in 0..l - 1 { - let new = circ.alloc_qubit(); - let anc = circ.alloc_qubit(); - let ctlh = on_ctl(circ, e, d, base + i); - { - let cyi: QubitId = if i == 0 { - carry_in.copied().unwrap_or_else(|| *cin_owned.as_ref().unwrap()) - } else { - *prev_new.as_ref().unwrap() - }; - if let Some(ai) = on_ctl_ref(&ctlh, e, d) { - circ.cx(ai, anc); - } - circ.cx(cyi, anc); - circ.cx(cyi, y[i]); - let old_context = crate::point_add::set_op_trace_context( - 0x0f00_0000 | (((dirty_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - if !fused_dirty_fold_has_structurally_dead_carry(dirty_call_index, i) { - circ.ccx(y[i], anc, new); - } - crate::point_add::restore_op_trace_context(old_context); - circ.cx(cyi, new); - circ.cx(new, dirty[i]); - circ.cx(cyi, anc); - if let Some(ai) = on_ctl_ref(&ctlh, e, d) { - circ.cx(ai, anc); - circ.cx(ai, y[i]); - } - } - on_ctl_free(circ, e, d, base + i, ctlh); - circ.zero_and_free(anc); - if i == 0 { - if let Some(c) = cin_owned.take() { - circ.zero_and_free(c); - } - } else { - let b = circ.alloc_bit(); - circ.hmr(*prev_new.as_ref().unwrap(), b); - circ.zero_and_free(prev_new.take().unwrap()); - bits.push(b); - } - prev_new = Some(new); - } - let cy_top = prev_new.take().unwrap(); - { - let topc = on_ctl(circ, e, d, base + l - 1); - if let Some(at) = on_ctl_ref(&topc, e, d) { - circ.cx(at, y[l - 1]); - } - on_ctl_free(circ, e, d, base + l - 1, topc); - } - circ.cx(cy_top, y[l - 1]); - let b = circ.alloc_bit(); - circ.hmr(cy_top, b); - circ.zero_and_free(cy_top); - bits.push(b); - - for i in 0..l - 1 { - circ.z_if_bit(dirty[i], bits[i]); - } - for q in y { - circ.x(*q); - } - xor_carries_perpos(circ, e, d, base, y, dirty, carry_in); - for q in y { - circ.x(*q); - } - for i in 0..l - 1 { - circ.z_if_bit(dirty[i], bits[i]); - } -} - -fn clean_window_fwd(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], carries: &[QubitId]) { - let clean_window_call_index = next_fold_clean_window_call_index(); - let b = y.len(); - assert_eq!(carries.len(), b); - { - let c0 = on_ctl(circ, e, d, base); - if let Some(a0) = on_ctl_ref(&c0, e, d) { - let old_context = crate::point_add::set_op_trace_context( - 0x1000_0000 | (((clean_window_call_index as u32) & 0xffff) << 8), - ); - if !fused_clean_window_has_structurally_dead_carry(clean_window_call_index, 0) { - circ.ccx(a0, y[0], carries[0]); - } - crate::point_add::restore_op_trace_context(old_context); - } - on_ctl_free(circ, e, d, base, c0); - } - for i in 1..b { - let ci = on_ctl(circ, e, d, base + i); - let ai = on_ctl_ref(&ci, e, d); - circ.cx(carries[i - 1], y[i]); - if let Some(a) = &ai { - circ.cx(*a, carries[i - 1]); - } - let old_context = crate::point_add::set_op_trace_context( - 0x1000_0000 | (((clean_window_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - if !fused_clean_window_has_structurally_dead_carry(clean_window_call_index, i) { - circ.ccx(y[i], carries[i - 1], carries[i]); - } - crate::point_add::restore_op_trace_context(old_context); - if let Some(a) = &ai { - circ.cx(*a, carries[i - 1]); - } - circ.cx(carries[i - 1], carries[i]); - on_ctl_free(circ, e, d, base + i, ci); - } - for i in 0..b { - let ci = on_ctl(circ, e, d, base + i); - if let Some(a) = on_ctl_ref(&ci, e, d) { - circ.cx(a, y[i]); - } - on_ctl_free(circ, e, d, base + i, ci); - } -} - -fn clean_window_rev(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], carries: Vec) { - let b = y.len(); - let mut cy: Vec> = carries.into_iter().map(Some).collect(); - for i in (1..b).rev() { - let ci_ctl = on_ctl(circ, e, d, base + i); - let actl = on_ctl_ref(&ci_ctl, e, d); - if let Some(ai) = &actl { - circ.cx(*ai, y[i]); - } - let next = cy[i].take().unwrap(); - let ci = cy[i - 1].take().unwrap(); - circ.cx(ci, next); - if let Some(ai) = &actl { - circ.cx(*ai, ci); - } - let bit = circ.alloc_bit(); - circ.hmr(next, bit); - circ.zero_and_free(next); - circ.cz_if_bit(y[i], ci, bit); - if let Some(ai) = &actl { - circ.cx(*ai, ci); - circ.cx(*ai, y[i]); - } - on_ctl_free(circ, e, d, base + i, ci_ctl); - cy[i - 1] = Some(ci); - } - let cy0 = cy[0].take().unwrap(); - let c0 = on_ctl(circ, e, d, base); - if let Some(a0) = on_ctl_ref(&c0, e, d) { - circ.cx(a0, y[0]); - let bit = circ.alloc_bit(); - circ.hmr(cy0, bit); - circ.zero_and_free(cy0); - circ.cz_if_bit(y[0], a0, bit); - circ.cx(a0, y[0]); - } else { - circ.zero_and_free(cy0); - } - on_ctl_free(circ, e, d, base, c0); -} - -fn build_fold_at(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], dirty: &[QubitId], nv: usize) { - let l = y.len(); - if nv >= l - 1 { - - add_mf_fold_clean(circ, e, d, y); - return; - } - - const PROP_FROM: usize = 34; - if nv >= 1 && nv >= PROP_FROM { - add_mf_fold_clean_tail(circ, e, d, y, Some(nv)); - return; - } - if nv == 0 { - dirty_body(circ, e, d, 0, y, dirty, None); - } else { - let carries: Vec = (0..nv).map(|_| circ.alloc_qubit()).collect(); - clean_window_fwd(circ, e, d, 0, &y[..nv], &carries); - let cin = carries[nv - 1]; - dirty_body(circ, e, d, nv, &y[nv..], &dirty[nv..], Some(&cin)); - clean_window_rev(circ, e, d, 0, &y[..nv], carries); - } -} - -fn fused_fold(circ: &mut B, e: &QubitId, d: &QubitId, ylow: &[QubitId], dirty: &[QubitId]) { - let call_index = next_fold_call_index(); - let prior_fold_call_index = enter_fold_call_index(call_index); - let timeline_start = circ.active_timeline.len(); - let entry_active = circ.active_qubits; - let code = super::next_fold(); - let mut selected_nv = None; - if code < 0 { - let chunk = std::env::var("TLM_FOLD_CHUNK_FORCE") - .ok() - .and_then(|value| value.parse::().ok()) - .filter(|&value| value > 0) - .unwrap_or((-code) as usize); - add_mf_fold_chunked(circ, e, d, ylow, chunk); - } else { - let default_reserve = std::env::var("TLM_TARGET_FOLD_RESERVE") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(4); - let reserve = fold_call_reserve(call_index, default_reserve); - let nv = super::target_qubit_headroom(circ) - .map_or(code as usize, |headroom| { - (code as usize).min(headroom.saturating_sub(reserve)) - }); - selected_nv = Some(nv); - build_fold_at(circ, e, d, ylow, dirty, nv); - } - restore_fold_call_index(prior_fold_call_index); - if std::env::var_os("TRACE_TLM_FOLD").is_some() { - let local_peak = circ.active_timeline[timeline_start..] - .iter() - .map(|(_, active)| *active) - .max() - .unwrap_or(circ.active_qubits); - eprintln!( - "TLM_FOLD call={} phase={} code={} nv={} entry_active={} local_peak={} ops={}", - call_index, - circ.phase, - code, - selected_nv.map_or(-1, |value| value as i32), - entry_active, - local_peak, - circ.current_ops_len(), - ); - } -} - -fn fused_fold_e_only(circ: &mut B, e: &QubitId, y: &[QubitId]) { - let call_index = next_fold_call_index(); - let prior_fold_call_index = enter_fold_call_index(call_index); - let timeline_start = circ.active_timeline.len(); - let entry_active = circ.active_qubits; - let code = super::next_fold(); - let default_reserve = std::env::var("TLM_TARGET_FOLD_RESERVE") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(4); - let reserve = fold_call_reserve(call_index, default_reserve); - let g = if code < 0 { - 0 - } else { - super::target_qubit_headroom(circ) - .map_or(code as usize, |headroom| { - (code as usize).min(headroom.saturating_sub(reserve)) - }) - .min(LSBS - 1) - }; - let f_bytes = F_SECP256K1.to_le_bytes(); - super::arith::add_f_window_pub(circ, e, y, LSBS, &f_bytes, Some(g)); - restore_fold_call_index(prior_fold_call_index); - if std::env::var_os("TRACE_TLM_FOLD").is_some() { - let local_peak = circ.active_timeline[timeline_start..] - .iter() - .map(|(_, active)| *active) - .max() - .unwrap_or(circ.active_qubits); - eprintln!( - "TLM_FOLD call={} phase={} code={} nv={} entry_active={} local_peak={} ops={}", - call_index, - circ.phase, - code, - g as i32, - entry_active, - local_peak, - circ.current_ops_len(), - ); - } -} - -fn trace_fold_alloc(circ: &B, name: &str, stage: &str, i: usize) { - if std::env::var_os("TRACE_TLM_FOLD_ALLOC").is_some() { - eprintln!( - "TLM_FOLD_ALLOC name={name} stage={stage} i={i} active={} ops={}", - circ.active_qubits, - circ.current_ops_len(), - ); - } -} - -pub fn fused_double_cdouble(circ: &mut B, s2: &QubitId, y: &[QubitId]) { - let shift_call_index = next_fused_cdouble_fwd_shift_call_index(); - maybe_run_gradual_fold_nonlinear_control_hmr_selftest(); - let n = 256usize; - assert_eq!(y.len(), n, "fused double expects 256-bit y (transient overflow)"); - let _ = F_SECP256K1; - trace_fold_alloc(circ, "fwd_cdouble", "entry", usize::MAX); - let hi = circ.alloc_qubit(); - trace_fold_alloc(circ, "fwd_cdouble", "after_hi", usize::MAX); - let hi2 = circ.alloc_qubit(); - trace_fold_alloc(circ, "fwd_cdouble", "after_hi2", usize::MAX); - - let mut w: Vec = y.to_vec(); - w.push(hi); - w.push(hi2); - - for i in (1..w.len()).rev() { - circ.swap(w[i], w[i - 1]); - } - - for i in (1..w.len()).rev() { - let bit = i - 1; - let old_context = crate::point_add::set_op_trace_context( - 0x1400_0000 | (((shift_call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff), - ); - if !(bit == 0 && skip_structural_dead_fused_cdouble_shift0()) { - circ.cswap(*s2, w[i], w[i - 1]); - } - crate::point_add::restore_op_trace_context(old_context); - } - - let borrow: Vec = y[LSBS..2 * LSBS - 1].to_vec(); - fused_fold(circ, &w[n], &w[n + 1], &y[..LSBS], &borrow); - - circ.cx(y[0], w[n]); - clear_and(circ, &w[n + 1], s2, &y[1]); - circ.zero_and_free(hi); - circ.zero_and_free(hi2); -} - -pub fn fused_double_only(circ: &mut B, y: &[QubitId]) { - let n = 256usize; - assert_eq!(y.len(), n, "fused double expects 256-bit y"); - trace_fold_alloc(circ, "fwd_only", "entry", usize::MAX); - let hi = circ.alloc_qubit(); - trace_fold_alloc(circ, "fwd_only", "after_hi", usize::MAX); - let mut w: Vec = y.to_vec(); - w.push(hi); - for i in (1..w.len()).rev() { - circ.swap(w[i], w[i - 1]); - } - fused_fold_e_only(circ, &w[n], y); - circ.cx(y[0], w[n]); - circ.zero_and_free(hi); -} - -pub fn fused_double_cdouble_reverse(circ: &mut B, s2: &QubitId, y: &[QubitId]) { - let shift_call_index = next_fused_cdouble_rev_shift_call_index(); - maybe_run_gradual_fold_nonlinear_control_hmr_selftest(); - let n = 256usize; - assert_eq!(y.len(), n, "fused halve expects 256-bit y (transient overflow)"); - trace_fold_alloc(circ, "rev_cdouble", "entry", usize::MAX); - let hi = circ.alloc_qubit(); - trace_fold_alloc(circ, "rev_cdouble", "after_hi", usize::MAX); - let hi2 = circ.alloc_qubit(); - trace_fold_alloc(circ, "rev_cdouble", "after_hi2", usize::MAX); - let mut w: Vec = y.to_vec(); - w.push(hi); - w.push(hi2); - - circ.ccx(*s2, y[1], w[n + 1]); - circ.cx(y[0], w[n]); - - let borrow: Vec = y[LSBS..2 * LSBS - 1].to_vec(); - for q in &y[..LSBS] { - circ.x(*q); - } - fused_fold(circ, &w[n], &w[n + 1], &y[..LSBS], &borrow); - for q in &y[..LSBS] { - circ.x(*q); - } - - for i in 1..w.len() { - let bit = i - 1; - let old_context = crate::point_add::set_op_trace_context( - 0x1500_0000 | (((shift_call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff), - ); - if !(bit == 0 && skip_structural_dead_fused_cdouble_shift0()) { - circ.cswap(*s2, w[i], w[i - 1]); - } - crate::point_add::restore_op_trace_context(old_context); - } - for i in 1..w.len() { - circ.swap(w[i], w[i - 1]); - } - circ.zero_and_free(hi); - circ.zero_and_free(hi2); -} - -pub fn fused_double_only_reverse(circ: &mut B, y: &[QubitId]) { - let n = 256usize; - assert_eq!(y.len(), n, "fused halve expects 256-bit y"); - trace_fold_alloc(circ, "rev_only", "entry", usize::MAX); - let hi = circ.alloc_qubit(); - trace_fold_alloc(circ, "rev_only", "after_hi", usize::MAX); - let mut w: Vec = y.to_vec(); - w.push(hi); - circ.cx(y[0], w[n]); - for q in &y[..LSBS] { - circ.x(*q); - } - fused_fold_e_only(circ, &w[n], y); - for q in &y[..LSBS] { - circ.x(*q); - } - for i in 1..w.len() { - circ.swap(w[i], w[i - 1]); - } - circ.zero_and_free(hi); -} - -fn gradual_fold_nonlinear_control_hmr_selftest() { - use crate::circuit::OperationType; - use crate::sim::Simulator; - use sha3::{ - digest::{ExtendableOutput, Update}, - Shake128, - }; - - for &(position, kind) in &[(8usize, 4u8), (10, 5), (11, 6)] { - assert_eq!(fold_ctl(position), kind); - - let mut circ = B::new(); - let e = circ.alloc_qubit(); - let d = circ.alloc_qubit(); - let q = circ.alloc_qubit(); - on_ctl_apply(&mut circ, &e, &d, kind, &q); - on_ctl_free(&mut circ, &e, &d, position, OnCtl::Owned(q)); - - assert_eq!(circ.active_qubits, 2, "owned control was not released"); - assert_eq!(circ.peak_qubits, 3, "cleanup increased peak width"); - assert_eq!(circ.next_bit, 1, "expected one HMR result bit"); - assert_eq!( - circ.ops - .iter() - .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) - .count(), - 1, - "cleanup must add no Toffoli-class gate", - ); - assert_eq!( - circ.ops - .iter() - .filter(|op| op.kind == OperationType::Hmr) - .count(), - 1, - ); - - let mut e_mask = 0u64; - let mut d_mask = 0u64; - for shot in 0..64usize { - let state = shot & 3; - e_mask |= ((state & 1) as u64) << shot; - d_mask |= (((state >> 1) & 1) as u64) << shot; - } - - let mut seed = Shake128::default(); - seed.update(b"gradual-fold-derived-control-hmr"); - seed.update(&[kind]); - let mut xof = seed.finalize_xof(); - let mut sim = Simulator::new( - circ.next_qubit as usize, - circ.next_bit as usize, - &mut xof, - ); - *sim.qubit_mut(e) = e_mask; - *sim.qubit_mut(d) = d_mask; - sim.apply_iter(circ.ops.iter()); - - assert_eq!(sim.qubit(e), e_mask, "e changed for control kind {kind}"); - assert_eq!(sim.qubit(d), d_mask, "d changed for control kind {kind}"); - assert_eq!(sim.qubit(q), 0, "owned control remained dirty for kind {kind}"); - assert_eq!(sim.phase, 0, "phase feedback failed for control kind {kind}"); - - let measured = sim.bits[0]; - for state in 0..4usize { - let mut outcomes = 0u8; - for shot in (state..64usize).step_by(4) { - outcomes |= 1 << ((measured >> shot) & 1); - } - assert_eq!( - outcomes, 0b11, - "HMR outcomes not exhaustive for kind {kind}, state {state}", - ); - } - } -} - -fn maybe_run_gradual_fold_nonlinear_control_hmr_selftest() { - if std::env::var_os("TLM_FOLD_HMR_CONTROL_SELFTEST").is_none() { - return; - } - static SELFTEST: std::sync::Once = std::sync::Once::new(); - SELFTEST.call_once(|| { - gradual_fold_nonlinear_control_hmr_selftest(); - eprintln!("TLM_FOLD_HMR_CONTROL_SELFTEST_OK"); - }); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn gradual_fold_nonlinear_control_hmr_cleanup_is_exact() { - gradual_fold_nonlinear_control_hmr_selftest(); - } -} + +use super::arith::{F_SECP256K1, LSBS}; +use super::{B, BExt}; +use crate::circuit::{BitId, QubitId}; +use std::cell::Cell; + +thread_local! { + static FOLD_CALL_INDEX: Cell = const { Cell::new(0) }; + static ACTIVE_FOLD_CALL_INDEX: Cell = const { Cell::new(usize::MAX) }; + static FOLD_CHUNK_CALL_INDEX: Cell = const { Cell::new(0) }; + static FOLD_DIRTY_CALL_INDEX: Cell = const { Cell::new(0) }; + static FOLD_CLEAN_WINDOW_CALL_INDEX: Cell = const { Cell::new(0) }; + static FOLD_BOUNDARY_ZERO_CALL_INDEX: Cell = const { Cell::new(0) }; + static FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; + static FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; +} + +pub(super) fn reset_fold_call_index() { + FOLD_CALL_INDEX.with(|index| index.set(0)); + ACTIVE_FOLD_CALL_INDEX.with(|index| index.set(usize::MAX)); + FOLD_CHUNK_CALL_INDEX.with(|index| index.set(0)); + FOLD_DIRTY_CALL_INDEX.with(|index| index.set(0)); + FOLD_CLEAN_WINDOW_CALL_INDEX.with(|index| index.set(0)); + FOLD_BOUNDARY_ZERO_CALL_INDEX.with(|index| index.set(0)); + FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX.with(|index| index.set(0)); + FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX.with(|index| index.set(0)); +} + +fn next_fold_call_index() -> usize { + FOLD_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn active_fold_call_index() -> usize { + ACTIVE_FOLD_CALL_INDEX.with(|index| index.get()) +} + +fn enter_fold_call_index(index: usize) -> usize { + ACTIVE_FOLD_CALL_INDEX.with(|slot| { + let prior = slot.get(); + slot.set(index); + prior + }) +} + +fn restore_fold_call_index(prior: usize) { + ACTIVE_FOLD_CALL_INDEX.with(|slot| slot.set(prior)); +} + +fn next_fold_chunk_call_index() -> usize { + FOLD_CHUNK_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_fold_dirty_call_index() -> usize { + FOLD_DIRTY_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_fold_clean_window_call_index() -> usize { + FOLD_CLEAN_WINDOW_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_fold_boundary_zero_call_index() -> usize { + FOLD_BOUNDARY_ZERO_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_fused_cdouble_fwd_shift_call_index() -> usize { + FUSED_CDOUBLE_FWD_SHIFT_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_fused_cdouble_rev_shift_call_index() -> usize { + FUSED_CDOUBLE_REV_SHIFT_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn env_index_value(name: &str, index: usize) -> Option { + std::env::var(name) + .ok() + .and_then(|value| { + value + .split(',') + .filter_map(|item| item.trim().split_once(':')) + .find_map(|(call, value)| { + (call.parse::().ok()? == index) + .then(|| value.parse::().ok()) + .flatten() + }) + }) +} + +fn skip_structural_dead_fused_carries() -> bool { + std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CARRIES").is_some() +} + +fn skip_structural_dead_fused_cdouble_shift0() -> bool { + std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_SHIFT0").is_some() +} + +fn skip_structural_dead_fused_dirty_fold() -> bool { + skip_structural_dead_fused_carries() + && std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_DIRTY_FOLD").is_some() +} + +fn skip_structural_dead_fused_clean_window() -> bool { + skip_structural_dead_fused_carries() + && std::env::var_os("TLM_FUSED_SKIP_STRUCTURAL_DEAD_CLEAN_WINDOW").is_some() +} + +fn skip_exact_fused_clean_fold() -> bool { + skip_structural_dead_fused_carries() + && (std::env::var_os("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER").is_some() + || std::env::var_os("TLM_FUSED_SKIP_EXACT_CLEAN_FOLD").is_some()) +} + +fn skip_exact_fused_chunk_fold() -> bool { + skip_structural_dead_fused_carries() + && (std::env::var_os("TLM_FUSED_SKIP_EXACT_FOLD_REMAINDER").is_some() + || std::env::var_os("TLM_FUSED_SKIP_EXACT_CHUNK_FOLD").is_some()) +} + +fn skip_fused_clean_fold_top31() -> bool { + skip_structural_dead_fused_carries() + && std::env::var_os("TLM_FUSED_CLEAN_FOLD_SKIP_TOP31").is_some() +} + +const FUSED_CLEAN_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (345, 0, 3), + (345, 29, 31), + (327, 0, 3), + (327, 30, 31), + (353, 0, 3), + (353, 30, 31), + (355, 0, 3), + (355, 30, 31), + (377, 0, 3), + (377, 30, 31), + (419, 0, 3), + (419, 29, 30), + (431, 0, 3), + (431, 30, 31), + (432, 0, 3), + (432, 29, 29), + (432, 31, 31), + (438, 0, 3), + (438, 30, 31), + (440, 0, 3), + (440, 30, 31), + (446, 0, 3), + (446, 30, 31), + (456, 0, 3), + (456, 30, 31), + (484, 0, 3), + (484, 30, 31), + (491, 0, 3), + (491, 30, 31), + (511, 0, 3), + (511, 30, 31), + (0, 1, 3), + (0, 29, 30), + (101, 1, 3), + (101, 30, 31), + (12, 1, 3), + (12, 30, 31), + (121, 1, 3), + (121, 29, 29), + (121, 31, 31), + (148, 1, 3), + (148, 30, 31), + (156, 1, 3), + (156, 30, 31), + (167, 1, 3), + (167, 29, 29), + (167, 31, 31), + (191, 1, 3), + (191, 30, 31), + (192, 1, 3), + (192, 30, 31), + (318, 0, 3), + (318, 31, 31), + (320, 0, 3), + (320, 31, 31), + (321, 0, 3), + (321, 31, 31), + (323, 0, 3), + (323, 31, 31), + (324, 0, 3), + (324, 31, 31), + (325, 0, 3), + (325, 31, 31), + (329, 0, 3), + (329, 30, 30), + (333, 0, 3), + (333, 31, 31), + (337, 0, 3), + (337, 30, 30), + (338, 0, 3), + (338, 31, 31), + (340, 0, 3), + (340, 31, 31), + (343, 0, 3), + (343, 31, 31), + (344, 0, 3), + (344, 31, 31), + (346, 0, 3), + (346, 31, 31), + (347, 0, 3), + (347, 30, 30), + (348, 0, 3), + (348, 31, 31), + (349, 0, 3), + (349, 31, 31), + (350, 0, 3), + (350, 31, 31), + (354, 0, 3), + (354, 30, 30), + (360, 0, 3), + (360, 31, 31), + (362, 0, 3), + (362, 31, 31), + (363, 0, 3), + (363, 31, 31), + (365, 0, 3), + (365, 31, 31), + (366, 0, 3), + (366, 31, 31), + (368, 0, 3), + (368, 31, 31), + (370, 0, 3), + (370, 31, 31), + (371, 0, 3), + (371, 30, 30), + (372, 0, 3), + (372, 31, 31), + (373, 0, 3), + (373, 31, 31), + (376, 0, 3), + (376, 31, 31), + (378, 0, 3), + (378, 31, 31), + (379, 0, 3), + (379, 31, 31), + (380, 0, 3), + (380, 31, 31), + (381, 0, 3), + (381, 31, 31), + (385, 0, 3), + (385, 31, 31), + (387, 0, 3), + (387, 31, 31), + (393, 0, 3), + (393, 30, 30), + (394, 0, 3), + (394, 31, 31), + (399, 0, 3), + (399, 31, 31), + (400, 0, 3), + (400, 31, 31), + (402, 0, 3), + (402, 31, 31), + (403, 0, 3), + (403, 31, 31), + (406, 0, 3), + (406, 30, 30), + (410, 0, 3), + (410, 31, 31), + (411, 0, 3), + (411, 31, 31), + (414, 0, 3), + (414, 31, 31), + (415, 0, 3), + (415, 31, 31), + (420, 0, 3), + (420, 31, 31), + (425, 0, 3), + (425, 31, 31), + (429, 0, 3), + (429, 31, 31), + (434, 0, 3), + (434, 31, 31), + (435, 0, 3), + (435, 31, 31), + (436, 0, 3), + (436, 31, 31), + (437, 0, 3), + (437, 31, 31), + (447, 0, 3), + (447, 31, 31), + (449, 0, 3), + (449, 31, 31), + (452, 0, 3), + (452, 31, 31), + (454, 0, 3), + (454, 31, 31), + (455, 0, 3), + (455, 30, 30), + (457, 0, 3), + (457, 31, 31), + (461, 0, 3), + (461, 31, 31), + (463, 0, 3), + (463, 31, 31), + (465, 0, 3), + (465, 31, 31), + (466, 0, 3), + (466, 31, 31), + (475, 0, 3), + (475, 30, 30), + (479, 0, 3), + (479, 31, 31), + (480, 0, 3), + (480, 31, 31), + (485, 0, 3), + (485, 31, 31), + (486, 0, 3), + (486, 30, 30), + (493, 0, 3), + (493, 31, 31), + (496, 0, 3), + (496, 31, 31), + (497, 0, 3), + (497, 31, 31), + (500, 0, 3), + (500, 31, 31), + (501, 0, 3), + (501, 31, 31), + (502, 0, 3), + (502, 31, 31), + (503, 0, 3), + (503, 30, 30), + (507, 0, 3), + (507, 31, 31), + (508, 0, 3), + (508, 30, 30), + (509, 0, 3), + (509, 31, 31), + (51, 1, 3), + (51, 30, 31), + (510, 0, 3), + (510, 31, 31), + (513, 0, 3), + (513, 31, 31), + (54, 1, 3), + (54, 30, 31), + (64, 1, 3), + (64, 30, 31), + (10, 1, 3), + (10, 31, 31), + (100, 1, 3), + (100, 31, 31), + (104, 1, 3), + (104, 30, 30), + (105, 1, 3), + (105, 31, 31), + (107, 1, 3), + (107, 31, 31), + (108, 1, 3), + (108, 31, 31), + (111, 1, 3), + (111, 31, 31), + (112, 1, 3), + (112, 31, 31), + (115, 1, 3), + (115, 31, 31), + (116, 1, 3), + (116, 31, 31), + (117, 1, 3), + (117, 31, 31), + (124, 1, 3), + (124, 31, 31), + (125, 1, 3), + (125, 30, 30), + (126, 1, 3), + (126, 31, 31), + (127, 1, 3), + (127, 30, 30), + (128, 1, 3), + (128, 31, 31), + (13, 1, 3), + (13, 30, 30), + (131, 1, 3), + (131, 31, 31), + (132, 1, 3), + (132, 31, 31), + (134, 1, 3), + (134, 31, 31), + (135, 1, 3), + (135, 31, 31), + (137, 1, 3), + (137, 31, 31), + (14, 1, 3), + (14, 31, 31), + (142, 1, 3), + (142, 31, 31), + (144, 1, 3), + (144, 31, 31), + (15, 1, 3), + (15, 31, 31), + (154, 1, 3), + (154, 30, 30), + (157, 1, 3), + (157, 31, 31), + (158, 1, 3), + (158, 31, 31), + (160, 1, 3), + (160, 31, 31), + (161, 1, 3), + (161, 31, 31), + (162, 1, 3), + (162, 31, 31), + (164, 1, 3), + (164, 31, 31), + (166, 1, 3), + (166, 31, 31), + (169, 1, 3), + (169, 31, 31), + (171, 1, 3), + (171, 31, 31), + (172, 1, 3), + (172, 31, 31), + (174, 1, 3), + (174, 31, 31), + (175, 1, 3), + (175, 31, 31), + (178, 1, 3), + (178, 30, 30), + (179, 1, 3), + (179, 31, 31), + (18, 1, 3), + (18, 31, 31), + (180, 1, 3), + (180, 31, 31), + (181, 1, 3), + (181, 31, 31), + (182, 1, 3), + (182, 31, 31), + (189, 1, 3), + (189, 31, 31), + (2, 1, 3), + (2, 31, 31), + (23, 1, 3), + (23, 31, 31), + (24, 1, 3), + (24, 31, 31), + (26, 1, 3), + (26, 31, 31), + (29, 1, 3), + (29, 31, 31), + (31, 1, 3), + (31, 31, 31), + (322, 0, 3), + (326, 0, 3), + (328, 0, 3), + (330, 0, 3), + (331, 0, 3), + (332, 0, 3), + (334, 0, 3), + (335, 0, 3), + (336, 0, 3), + (339, 0, 3), + (341, 0, 3), + (342, 0, 3), + (351, 0, 3), + (352, 0, 3), + (356, 0, 3), + (357, 0, 3), + (358, 0, 3), + (359, 0, 3), + (361, 0, 3), + (364, 0, 3), + (367, 0, 3), + (369, 0, 3), + (37, 1, 3), + (37, 31, 31), + (374, 0, 3), + (375, 0, 3), + (38, 1, 3), + (38, 31, 31), + (382, 0, 3), + (383, 0, 3), + (384, 0, 3), + (386, 0, 3), + (388, 0, 3), + (389, 0, 3), + (390, 0, 3), + (391, 0, 3), + (392, 0, 3), + (395, 0, 3), + (396, 0, 3), + (397, 0, 3), + (398, 0, 3), + (4, 1, 3), + (4, 31, 31), + (40, 1, 3), + (40, 31, 31), + (401, 0, 3), + (404, 0, 3), + (405, 0, 3), + (407, 0, 3), + (408, 0, 3), + (409, 0, 3), + (412, 0, 3), + (413, 0, 3), + (416, 0, 3), + (417, 0, 3), + (418, 0, 3), + (421, 0, 3), + (422, 0, 3), + (423, 0, 3), + (424, 0, 3), + (426, 0, 3), + (427, 0, 3), + (428, 0, 3), + (43, 1, 3), + (43, 31, 31), + (430, 0, 3), + (433, 0, 3), + (439, 0, 3), + (44, 1, 3), + (44, 31, 31), + (441, 0, 3), + (442, 0, 3), + (443, 0, 3), + (444, 0, 3), + (445, 0, 3), + (448, 0, 3), + (45, 1, 3), + (45, 31, 31), + (450, 0, 3), + (451, 0, 3), + (453, 0, 3), + (458, 0, 3), + (459, 0, 3), + (46, 1, 3), + (46, 31, 31), + (460, 0, 3), + (462, 0, 3), + (464, 0, 3), + (467, 0, 3), + (468, 0, 3), + (469, 0, 3), + (470, 0, 3), + (471, 0, 3), + (472, 0, 3), + (473, 0, 3), + (474, 0, 3), + (476, 0, 3), + (477, 0, 3), + (478, 0, 3), + (481, 0, 3), + (482, 0, 3), + (483, 0, 3), + (487, 0, 3), + (488, 0, 3), + (489, 0, 3), + (490, 0, 3), + (492, 0, 3), + (494, 0, 3), + (495, 0, 3), + (498, 0, 3), + (499, 0, 3), + (504, 0, 3), + (505, 0, 3), + (506, 0, 3), + (512, 0, 3), + (53, 1, 3), + (53, 31, 31), + (56, 1, 3), + (56, 31, 31), + (57, 1, 3), + (57, 31, 31), + (59, 1, 3), + (59, 31, 31), + (6, 1, 3), + (6, 31, 31), + (61, 1, 3), + (61, 31, 31), + (65, 1, 3), + (65, 31, 31), + (67, 1, 3), + (67, 31, 31), + (7, 1, 3), + (7, 31, 31), + (71, 1, 3), + (71, 31, 31), + (74, 1, 3), + (74, 31, 31), + (75, 1, 3), + (75, 31, 31), + (78, 1, 3), + (78, 31, 31), + (79, 1, 3), + (79, 31, 31), + (85, 1, 3), + (85, 30, 30), + (86, 1, 3), + (86, 31, 31), + (87, 1, 3), + (87, 31, 31), + (88, 1, 3), + (88, 31, 31), + (89, 1, 3), + (89, 31, 31), + (9, 1, 3), + (9, 31, 31), + (90, 1, 3), + (90, 31, 31), + (91, 1, 3), + (91, 30, 30), + (94, 1, 3), + (94, 29, 29), + (95, 1, 3), + (95, 31, 31), + (96, 1, 3), + (96, 31, 31), + (98, 1, 3), + (98, 31, 31), + (99, 1, 3), + (99, 31, 31), +]; + +const FUSED_CHUNK_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (1008, 0, 3), + (1022, 0, 3), + (1036, 0, 3), + (1050, 0, 3), + (1064, 0, 3), + (1078, 0, 3), + (1092, 0, 3), + (1106, 0, 3), + (112, 0, 3), + (1120, 0, 3), + (1134, 0, 3), + (1148, 0, 3), + (1162, 0, 3), + (1176, 0, 3), + (1190, 0, 3), + (1204, 0, 3), + (1218, 0, 3), + (1232, 0, 3), + (1246, 0, 3), + (126, 0, 3), + (1260, 0, 3), + (1274, 0, 3), + (1288, 0, 3), + (1302, 0, 3), + (1316, 0, 3), + (1330, 0, 3), + (1344, 0, 3), + (1358, 0, 3), + (1372, 0, 3), + (1386, 0, 3), + (140, 0, 3), + (1400, 0, 3), + (1414, 0, 3), + (1428, 0, 3), + (1442, 0, 3), + (1456, 0, 3), + (1470, 0, 3), + (1484, 0, 3), + (1498, 0, 3), + (1512, 0, 3), + (1526, 0, 3), + (154, 0, 3), + (1540, 0, 3), + (1554, 0, 3), + (168, 0, 3), + (182, 0, 3), + (196, 0, 3), + (210, 0, 3), + (224, 0, 3), + (238, 0, 3), + (252, 0, 3), + (266, 0, 3), + (280, 0, 3), + (294, 0, 3), + (308, 0, 3), + (322, 0, 3), + (336, 0, 3), + (350, 0, 3), + (364, 0, 3), + (378, 0, 3), + (392, 0, 3), + (406, 0, 3), + (420, 0, 3), + (434, 0, 3), + (448, 0, 3), + (462, 0, 3), + (476, 0, 3), + (490, 0, 3), + (504, 0, 3), + (518, 0, 3), + (532, 0, 3), + (546, 0, 3), + (560, 0, 3), + (574, 0, 3), + (763, 0, 3), + (777, 0, 3), + (784, 0, 3), + (791, 0, 3), + (796, 0, 3), + (798, 0, 3), + (805, 0, 3), + (812, 0, 3), + (819, 0, 3), + (826, 0, 3), + (833, 0, 3), + (84, 0, 3), + (840, 0, 3), + (847, 0, 3), + (854, 0, 3), + (868, 0, 3), + (882, 0, 3), + (896, 0, 3), + (910, 0, 3), + (924, 0, 3), + (938, 0, 3), + (952, 0, 3), + (966, 0, 3), + (98, 0, 3), + (980, 0, 3), + (994, 0, 3), +]; + +const FUSED_DIRTY_FOLD_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (6, 0, 3), + (6, 21, 24), + (6, 26, 31), + (6, 43, 45), + (6, 47, 51), + (5, 7, 18), + (5, 32, 38), + (4, 9, 18), + (4, 30, 30), + (4, 32, 38), + (3, 15, 23), + (3, 36, 42), + (1, 11, 19), + (1, 34, 39), + (7, 10, 18), + (7, 32, 32), + (7, 34, 38), + (2, 10, 18), + (2, 33, 37), + (8, 11, 19), + (8, 35, 36), + (8, 38, 39), + (0, 11, 17), + (0, 34, 34), + (0, 36, 38), + (9, 12, 18), + (9, 35, 38), +]; + +const FUSED_CLEAN_WINDOW_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (0, 1, 3), + (1, 1, 3), + (2, 1, 3), + (3, 1, 3), + (4, 1, 3), + (5, 0, 3), + (6, 0, 3), + (7, 0, 3), + (8, 0, 3), +]; + +const FUSED_CLEAN_FOLD_REMAINDER_KEYS: &[u32] = &[ + 257, 258, 259, 769, 770, 771, 1281, 1282, 1283, 2049, 2050, 2051, 2817, 2818, + 2819, 4097, 4098, 4099, 4353, 4354, 4355, 4865, 4866, 4867, 5121, 5122, 5123, + 5377, 5378, 5379, 5633, 5634, 5635, 6401, 6402, 6403, 6913, 6914, 6915, 7169, + 7170, 7171, 7681, 7682, 7683, 8193, 8194, 8195, 8449, 8450, 8451, 8705, 8706, + 8707, 8961, 8962, 8963, 9217, 9218, 9219, 9985, 9986, 9987, 10497, 10498, + 10499, 10753, 10754, 10755, 12033, 12034, 12035, 12289, 12290, 12291, 12545, + 12546, 12547, 12801, 12802, 12803, 13313, 13314, 13315, 14081, 14082, 14083, + 14849, 14850, 14851, 15361, 15362, 15363, 15873, 15874, 15875, 16129, 16130, + 16131, 16897, 16898, 16899, 17409, 17410, 17411, 17665, 17666, 17667, 17921, + 17922, 17923, 18433, 18434, 18435, 18689, 18690, 18691, 19457, 19458, 19459, + 19713, 19714, 19715, 20481, 20482, 20483, 20737, 20738, 20739, 20993, 20994, + 20995, 21249, 21250, 21251, 21505, 21506, 21507, 23553, 23554, 23555, 23809, + 23810, 23811, 24833, 24834, 24835, 26113, 26114, 26115, 26369, 26370, 26371, + 27137, 27138, 27139, 27905, 27906, 27907, 28161, 28162, 28163, 28929, 28930, + 28931, 29185, 29186, 29187, 30209, 30210, 30211, 30465, 30466, 30467, 30721, + 30722, 30723, 31233, 31234, 31235, 31489, 31490, 31491, 33025, 33026, 33027, + 33281, 33282, 33283, 34049, 34050, 34051, 34817, 34818, 34819, 35329, 35330, + 35331, 35585, 35586, 35587, 35841, 35842, 35843, 36097, 36098, 36099, 36609, + 36610, 36611, 37121, 37122, 37123, 37377, 37378, 37379, 37633, 37634, 37635, + 38145, 38146, 38147, 38401, 38402, 38403, 38657, 38658, 38659, 38913, 38914, + 38915, 39169, 39170, 39171, 39681, 39682, 39683, 40705, 40706, 40707, 41729, + 41730, 41731, 42241, 42242, 42243, 43009, 43010, 43011, 43521, 43522, 43523, + 44289, 44290, 44291, 45057, 45058, 45059, 45313, 45314, 45315, 46849, 46850, + 46851, 47105, 47106, 47107, 47361, 47362, 47363, 47617, 47618, 47619, 47873, + 47874, 47875, 48129, 48130, 48131, 48641, 48642, 48643, 49409, 49410, 49411, + 49921, 49922, 49923, +]; + +const FUSED_CHUNK_FOLD_REMAINDER_KEYS: &[u32] = &[ + 1, 2, 3, 1795, 3585, 3586, 3587, 5378, 7169, 7170, 7171, 8962, 10753, 10754, + 10755, 12547, 14337, 14338, 14339, 17921, 17922, 17923, 23299, 30466, 34051, + 37635, 41219, 44801, 44803, 48387, 55555, 62723, 66306, 77059, 84227, 87810, + 87811, 89344, 92928, 112899, 116482, 116483, 120066, 123651, 134403, 141571, + 145155, 148737, 148739, 150529, 150530, 150531, 152322, 154113, 154114, 154115, + 155907, 157697, 157698, 157699, 159489, 159490, 159491, 161024, 161281, 161282, + 161283, 163075, 164608, 164865, 164866, 164867, 166658, 166659, 167939, 168449, + 168450, 168451, 170240, 170242, 170243, 171523, 171776, 172033, 172034, 172035, + 173571, 173825, 173827, 175360, 175617, 175618, 175619, 177409, 177410, 177411, + 178691, 178944, 179201, 179202, 179203, 180993, 180994, 180995, 182275, 182528, + 182785, 182786, 182787, 184578, 184579, 185859, 186112, 186369, 186370, 186371, + 187907, 188161, 188162, 188163, 189441, 189443, 189696, 189953, 189954, 189955, + 191491, 191744, 191746, 191747, 193025, 193027, 193537, 193538, 193539, 195075, + 195328, 196609, 196610, 196611, 196864, 197121, 197122, 197123, 198657, 198658, + 198659, 198912, 200192, 200194, 200195, 200448, 202241, 202243, 202496, 203776, + 204032, 205826, 206080, 207361, 207362, 207363, 207616, 209410, 209411, 209664, + 210946, 210947, 213248, 214529, 214530, 214531, 214784, 216832, 218115, 218368, + 220419, 221699, 221952, 224001, 224002, 225283, 225536, 227586, 227587, 231170, + 231171, 232704, 234754, 236288, 238339, 239872, 241922, 245506, 245507, 247040, + 263426, 263427, 264960, 267011, 277762, 288515, 290048, 292098, 295683, 299267, + 304384, 306435, 313603, 320771, 322304, 324354, 324355, 329472, 331522, 345859, + 349442, 349443, 353027, 356611, 367362, 367363, 378115, 379648, 381699, 386816, + 392450, 396035, 399619, +]; + +fn fused_range_contains(ranges: &[(usize, usize, usize)], call_index: usize, bit: usize) -> bool { + skip_structural_dead_fused_carries() + && ranges + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn fused_key_contains(keys: &[u32], call_index: usize, bit: usize) -> bool { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + keys.binary_search(&key).is_ok() +} + +const FUSED_BOUNDARY_ZERO_REMAINDER_KEYS: &[u32] = &[ + 1282, 3842, 6402, 8962, 14082, 16642, 21762, 24322, 32001, 39682, 42242, + 47361, 47362, 49922, 51458, 52482, 55040, 55042, 57601, 62722, 70402, + 75521, 83202, 85761, 85762, 90882, 93442, 96002, 106241, 108802, 111362, + 113921, 113922, 116482, 118018, 119041, 119042, 121600, 121602, 124161, + 126721, 126722, 128256, 128258, 129281, 129282, 130818, 131840, 131841, + 131842, 132098, 133376, 133377, 133378, 134400, 134401, 134402, 135937, + 135938, 136960, 136962, 138497, 138498, 139520, 139521, 139522, 139777, + 141056, 141058, 141314, 142080, 142081, 142082, 142337, 142338, 143616, + 143617, 143618, 144640, 144641, 144642, 144897, 146177, 146178, 147200, + 147201, 147202, 147458, 148738, 149760, 149761, 149762, 150016, 150017, + 150018, 151297, 151298, 152320, 152321, 152322, 152578, 153857, 154880, + 154881, 154882, 156418, 158976, 158978, 160001, 160002, 160258, 162560, + 162561, 164096, 164098, 165122, 167682, 170241, 172801, 172802, 175362, + 177922, 180482, 183041, 183042, 185602, 188162, 190722, 193281, 193282, + 198402, 203521, 206082, 208641, 208642, 211201, 211202, 216322, 218882, + 226561, 229122, 231682, 234241, 236802, 244481, 249601, 249602, 252161, + 253698, 259842, 262402, 267521, 270082, 275202, 277762, 280322, 285442, +]; + +fn fused_boundary_zero_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + std::env::var_os("TLM_FUSED_SKIP_EXACT_BOUNDARY_ZERO").is_some() + && fused_key_contains(FUSED_BOUNDARY_ZERO_REMAINDER_KEYS, call_index, bit) +} + +fn fused_clean_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + fused_range_contains(FUSED_CLEAN_FOLD_DEAD_RANGES, call_index, bit) + || (skip_fused_clean_fold_top31() && bit == 31) + || (skip_exact_fused_clean_fold() + && fused_key_contains(FUSED_CLEAN_FOLD_REMAINDER_KEYS, call_index, bit)) +} + +fn fused_chunk_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + fused_range_contains(FUSED_CHUNK_FOLD_DEAD_RANGES, call_index, bit) + || (skip_exact_fused_chunk_fold() + && fused_key_contains(FUSED_CHUNK_FOLD_REMAINDER_KEYS, call_index, bit)) +} + +fn fused_dirty_fold_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + skip_structural_dead_fused_dirty_fold() + && FUSED_DIRTY_FOLD_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn fused_clean_window_has_structurally_dead_carry(call_index: usize, bit: usize) -> bool { + skip_structural_dead_fused_clean_window() + && FUSED_CLEAN_WINDOW_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn fold_call_reserve(index: usize, default: usize) -> usize { + let base = env_index_value("TLM_TARGET_FOLD_CALL_RESERVES", index).unwrap_or(default); + env_index_value("TLM_TARGET_FOLD_CALL_RESERVE_OVERRIDES", index).unwrap_or(base) +} + +fn fold_ctl(p: usize) -> u8 { + match p { + 0 | 4 | 6 | 32 => 1, + 1 | 5 | 33 => 2, + 7 => 3, + 8 | 9 => 4, + 10 => 5, + 11 => 6, + _ => 0, + } +} + +fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { + let bit = circ.alloc_bit(); + circ.hmr(*t, bit); + circ.cz_if_bit(*a, *b, bit); +} + +fn toggle_dnot_e_from_intersection( + circ: &mut B, + d: &QubitId, + cc: &QubitId, + dne: &QubitId, +) { + circ.cx(*d, *dne); + circ.cx(*cc, *dne); +} + +fn add_carry_into_tail_prefix(circ: &mut B, y: &[QubitId], c: &QubitId) { + if std::env::var("TLM_FOLD_TAIL_CINC").ok().as_deref() == Some("1") { + + let yv: Vec = y.to_vec(); + super::mcx::cinc_khattar_gidney(circ, &yv, c); + return; + } + + let t = y.len(); + for k in (1..t).rev() { + let mut ctrls: Vec<&QubitId> = Vec::with_capacity(k + 1); + ctrls.push(c); + ctrls.extend(y[..k].iter()); + super::mcx::mcx_clean_k(circ, &ctrls, &y[k]); + } + circ.cx(*c, y[0]); +} + +fn add_mf_fold_clean(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId]) { + add_mf_fold_clean_tail(circ, e, d, y, None); +} + +fn add_mf_fold_clean_tail(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], tail_from: Option) { + let l = y.len(); + assert!(l >= 2, "fold needs L >= 2"); + let loop_end = tail_from.unwrap_or(l - 1); + const LAST_DERIVED: usize = 9; + const LAST_AND: usize = 11; + + let mut cc = Some(circ.alloc_qubit()); + circ.ccx(*e, *d, *cc.as_ref().unwrap()); + let mut dne = Some(circ.alloc_qubit()); + toggle_dnot_e_from_intersection( + circ, + d, + cc.as_ref().unwrap(), + dne.as_ref().unwrap(), + ); + let mut sxor = Some(circ.alloc_qubit()); + circ.cx(*e, *sxor.as_ref().unwrap()); + circ.cx(*d, *sxor.as_ref().unwrap()); + let mut sor = Some(circ.alloc_qubit()); + circ.cx(*sxor.as_ref().unwrap(), *sor.as_ref().unwrap()); + circ.cx(*cc.as_ref().unwrap(), *sor.as_ref().unwrap()); + + fn fc<'a>(p: usize, e: &'a QubitId, d: &'a QubitId, cc: Option<&'a QubitId>, dne: Option<&'a QubitId>, sx: Option<&'a QubitId>, so: Option<&'a QubitId>) -> Option<&'a QubitId> { + match fold_ctl(p) { + 1 => Some(e), + 2 => Some(d), + 3 => sx, + 4 => so, + 5 => dne, + 6 => cc, + _ => None, + } + } + + let mut cy: Vec> = Vec::with_capacity(l - 1); + let c1 = circ.alloc_qubit(); + if let Some(a0) = fc(0, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + if !skip_structural_dead_fused_carries() { + let old_context = crate::point_add::set_op_trace_context( + 0x0d00_0000 | (((active_fold_call_index() as u32) & 0xffff) << 8), + ); + circ.ccx(*a0, y[0], c1); + crate::point_add::restore_op_trace_context(old_context); + } + circ.cx(*a0, y[0]); + } + cy.push(Some(c1)); + for i in 1..loop_end { + let next = circ.alloc_qubit(); + { + let ci = cy[i - 1].as_ref().unwrap(); + circ.cx(*ci, y[i]); + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, *ci); + } + if !fused_clean_fold_has_structurally_dead_carry(active_fold_call_index(), i) { + let old_context = crate::point_add::set_op_trace_context( + 0x0d00_0000 | (((active_fold_call_index() as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(y[i], *ci, next); + crate::point_add::restore_op_trace_context(old_context); + } + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, *ci); + } + circ.cx(*ci, next); + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, y[i]); + } + } + cy.push(Some(next)); + if i == LAST_DERIVED { + let so = sor.take().unwrap(); + circ.cx(*sxor.as_ref().unwrap(), so); + circ.cx(*cc.as_ref().unwrap(), so); + circ.zero_and_free(so); + let sx = sxor.take().unwrap(); + circ.cx(*e, sx); + circ.cx(*d, sx); + circ.zero_and_free(sx); + } + if i == LAST_AND { + let dn = dne.take().unwrap(); + toggle_dnot_e_from_intersection(circ, d, cc.as_ref().unwrap(), &dn); + circ.zero_and_free(dn); + let c = cc.take().unwrap(); + clear_and(circ, &c, e, d); + circ.zero_and_free(c); + } + } + match tail_from { + None => { + + if let Some(at) = fc(l - 1, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*at, y[l - 1]); + } + circ.cx(*cy[l - 2].as_ref().unwrap(), y[l - 1]); + } + Some(nv) => { + + add_carry_into_tail_prefix(circ, &y[nv..], cy[nv - 1].as_ref().unwrap()); + } + } + + for i in (1..loop_end).rev() { + if i == LAST_AND { + let c = circ.alloc_qubit(); + circ.ccx(*e, *d, c); + cc = Some(c); + let dn = circ.alloc_qubit(); + toggle_dnot_e_from_intersection(circ, d, cc.as_ref().unwrap(), &dn); + dne = Some(dn); + } + if i == LAST_DERIVED { + let sx = circ.alloc_qubit(); + circ.cx(*e, sx); + circ.cx(*d, sx); + let so = circ.alloc_qubit(); + circ.cx(sx, so); + circ.cx(*cc.as_ref().unwrap(), so); + sxor = Some(sx); + sor = Some(so); + } + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, y[i]); + } + let next = cy[i].take().unwrap(); + let ci = cy[i - 1].take().unwrap(); + circ.cx(ci, next); + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, ci); + } + + let bit = circ.alloc_bit(); + circ.hmr(next, bit); + circ.zero_and_free(next); + circ.cz_if_bit(y[i], ci, bit); + if let Some(ai) = fc(i, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*ai, ci); + circ.cx(*ai, y[i]); + } + cy[i - 1] = Some(ci); + } + + let cy1 = cy[0].take().unwrap(); + if let Some(a0) = fc(0, e, d, cc.as_ref(), dne.as_ref(), sxor.as_ref(), sor.as_ref()) { + circ.cx(*a0, y[0]); + let bit = circ.alloc_bit(); + circ.hmr(cy1, bit); + circ.zero_and_free(cy1); + circ.cz_if_bit(y[0], *a0, bit); + circ.cx(*a0, y[0]); + } else { + circ.zero_and_free(cy1); + } + + let sx = sxor.take().unwrap(); + let so = sor.take().unwrap(); + let cc = cc.take().unwrap(); + let dne = dne.take().unwrap(); + toggle_dnot_e_from_intersection(circ, d, &cc, &dne); + circ.zero_and_free(dne); + circ.cx(sx, so); + circ.cx(cc, so); + circ.zero_and_free(so); + circ.cx(*e, sx); + circ.cx(*d, sx); + circ.zero_and_free(sx); + clear_and(circ, &cc, e, d); + circ.zero_and_free(cc); +} + +fn build_fold_controls(circ: &mut B, e: &QubitId, d: &QubitId) -> (QubitId, QubitId, QubitId, QubitId) { + let cc = circ.alloc_qubit(); + circ.ccx(*e, *d, cc); + let sxor = circ.alloc_qubit(); + circ.cx(*e, sxor); + circ.cx(*d, sxor); + let sor = circ.alloc_qubit(); + circ.cx(sxor, sor); + circ.cx(cc, sor); + let dne = circ.alloc_qubit(); + toggle_dnot_e_from_intersection(circ, d, &cc, &dne); + (cc, sxor, sor, dne) +} + +fn uncompute_fold_controls(circ: &mut B, e: &QubitId, d: &QubitId, cc: QubitId, sxor: QubitId, sor: QubitId, dne: QubitId) { + toggle_dnot_e_from_intersection(circ, d, &cc, &dne); + circ.zero_and_free(dne); + circ.cx(sxor, sor); + circ.cx(cc, sor); + circ.zero_and_free(sor); + circ.cx(*e, sxor); + circ.cx(*d, sxor); + circ.zero_and_free(sxor); + clear_and(circ, &cc, e, d); + circ.zero_and_free(cc); +} + +fn fold_ctl_map(e: QubitId, d: QubitId, cc: QubitId, sxor: QubitId, sor: QubitId, dne: QubitId, l: usize) -> Vec> { + (0..l).map(|p| match fold_ctl(p) { 1 => Some(e), 2 => Some(d), 3 => Some(sxor), 4 => Some(sor), 5 => Some(dne), 6 => Some(cc), _ => None }).collect() +} + +fn fold_chunk_clean(circ: &mut B, ctl: &[Option], y: &[QubitId], cin: Option<&QubitId>, cout: &QubitId) { + let chunk_call_index = next_fold_chunk_call_index(); + let s = y.len(); + if s == 0 { + if let Some(c) = cin { circ.cx(*c, *cout); } + return; + } + let mut cy: Vec> = (0..s - 1).map(|_| Some(circ.alloc_qubit())).collect(); + for i in 0..s { + let on = ctl[i].as_ref(); + if i == 0 { + let dst: QubitId = if s == 1 { *cout } else { *cy[0].as_ref().unwrap() }; + match cin { + Some(c) => { + circ.cx(*c, y[0]); + if let Some(a) = on { circ.cx(*a, *c); } + let old_context = crate::point_add::set_op_trace_context( + 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8), + ); + circ.ccx(y[0], *c, dst); + crate::point_add::restore_op_trace_context(old_context); + if let Some(a) = on { circ.cx(*a, *c); } + circ.cx(*c, dst); + } + None => { + if let Some(a) = on { + if !skip_structural_dead_fused_carries() { + let old_context = crate::point_add::set_op_trace_context( + 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8), + ); + circ.ccx(*a, y[0], dst); + crate::point_add::restore_op_trace_context(old_context); + } + } + } + } + } else { + let ci: QubitId = *cy[i - 1].as_ref().unwrap(); + let dst: QubitId = if i == s - 1 { *cout } else { *cy[i].as_ref().unwrap() }; + circ.cx(ci, y[i]); + if let Some(a) = on { circ.cx(*a, ci); } + if !fused_chunk_fold_has_structurally_dead_carry(chunk_call_index, i) { + let old_context = crate::point_add::set_op_trace_context( + 0x0e00_0000 | (((chunk_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(y[i], ci, dst); + crate::point_add::restore_op_trace_context(old_context); + } + if let Some(a) = on { circ.cx(*a, ci); } + circ.cx(ci, dst); + } + } + for i in 0..s { + if let Some(a) = ctl[i].as_ref() { circ.cx(*a, y[i]); } + } + for i in (0..s - 1).rev() { + let on = ctl[i].as_ref(); + if let Some(a) = on { circ.cx(*a, y[i]); } + let next = cy[i].take().unwrap(); + if i == 0 { + match cin { + Some(c) => { + circ.cx(*c, next); + if let Some(a) = on { circ.cx(*a, *c); } + let bit = circ.alloc_bit(); + circ.hmr(next, bit); circ.zero_and_free(next); + circ.cz_if_bit(y[0], *c, bit); + if let Some(a) = on { circ.cx(*a, *c); circ.cx(*a, y[0]); } + } + None => { + let bit = circ.alloc_bit(); + circ.hmr(next, bit); circ.zero_and_free(next); + if let Some(a) = on { circ.cz_if_bit(y[0], *a, bit); } + if let Some(a) = on { circ.cx(*a, y[0]); } + } + } + } else { + let ci: QubitId = *cy[i - 1].as_ref().unwrap(); + circ.cx(ci, next); + if let Some(a) = on { circ.cx(*a, ci); } + let bit = circ.alloc_bit(); + circ.hmr(next, bit); circ.zero_and_free(next); + circ.cz_if_bit(y[i], ci, bit); + if let Some(a) = on { circ.cx(*a, ci); circ.cx(*a, y[i]); } + } + } +} + +fn fold_boundary_erase(circ: &mut B, ctl: &[Option], y: &[QubitId], cin: Option<&QubitId>, carry: QubitId) { + if std::env::var("TLM_FOLD_BOUNDARY_ZERO_DIRECT") + .ok() + .as_deref() + == Some("1") + && cin.is_some() + && ctl.iter().all(Option::is_none) + { + fold_boundary_erase_zero_direct(circ, y, cin.expect("cin checked"), carry); + return; + } + let s = y.len(); + let temp: Vec = (0..s).map(|_| circ.alloc_qubit()).collect(); + for (i, c) in ctl.iter().enumerate() { + if let Some(a) = c { circ.cx(*a, temp[i]); } + } + match cin { + Some(cin) => super::arith::erase_carry_gated_opt(circ, None, y, &temp, cin, &carry, None), + None => { + super::arith::erase_carry_gated_zero_cin_opt(circ, None, y, &temp, &carry, None); + circ.zero_and_free(carry); + } + } + for (i, c) in ctl.iter().enumerate() { + if let Some(a) = c { circ.cx(*a, temp[i]); } + } + for q in temp { circ.zero_and_free(q); } +} + +fn fold_boundary_erase_zero_direct(circ: &mut B, y: &[QubitId], cin: &QubitId, carry: QubitId) { + let boundary_call_index = next_fold_boundary_zero_call_index(); + let n = y.len(); + assert!(n >= 1, "zero boundary erase needs >= 1 bit"); + let bit = circ.alloc_bit(); + circ.hmr(carry, bit); + circ.zero_and_free(carry); + circ.push_condition(bit); + + let mut cy: Vec> = Vec::with_capacity(n); + let c0 = circ.alloc_qubit(); + circ.x(c0); + circ.cx(*cin, c0); + cy.push(Some(c0)); + for i in 0..n - 1 { + let next = circ.alloc_qubit(); + let ci = cy[i].as_ref().unwrap(); + circ.cx(*ci, y[i]); + circ.x(*ci); + let old_context = crate::point_add::set_op_trace_context( + 0x1c00_0000 | (((boundary_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + if !fused_boundary_zero_has_structurally_dead_carry(boundary_call_index, i) { + circ.ccx(y[i], *ci, next); + } + crate::point_add::restore_op_trace_context(old_context); + circ.x(*ci); + circ.cx(*ci, next); + cy.push(Some(next)); + } + { + let i = n - 1; + let ci = cy[i].as_ref().unwrap(); + circ.cx(*ci, y[i]); + circ.neg(); + circ.x(*ci); + circ.cz(y[i], *ci); + circ.x(*ci); + circ.z(*ci); + circ.cx(*ci, y[i]); + } + for i in (0..n - 1).rev() { + let next = cy[i + 1].take().unwrap(); + let ci = cy[i].as_ref().unwrap(); + circ.cx(*ci, next); + let mbit = circ.alloc_bit(); + circ.hmr(next, mbit); + circ.zero_and_free(next); + circ.x(*ci); + circ.cz_if_bit(y[i], *ci, mbit); + circ.x(*ci); + circ.cx(*ci, y[i]); + } + let c0 = cy[0].take().unwrap(); + circ.cx(*cin, c0); + circ.x(c0); + circ.zero_and_free(c0); + circ.pop_condition(); +} + +fn add_mf_fold_chunked(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], s_chunk: usize) { + let l = y.len(); + let release_controls = std::env::var("TLM_FOLD_RELEASE_CONTROLS") + .ok() + .as_deref() + == Some("1"); + let zero_cin = std::env::var("TLM_FOLD_CHUNK_ZERO_CIN") + .ok() + .as_deref() + == Some("1"); + let mut controls = Some(build_fold_controls(circ, e, d)); + let (cc, sxor, sor, dne) = controls.expect("fold controls present"); + let mut ctl = fold_ctl_map(*e, *d, cc, sxor, sor, dne, l); + let cin0 = (!zero_cin).then(|| circ.alloc_qubit()); + let nch = l.div_ceil(s_chunk); + let last_control_chunk = 11usize.min(l - 1) / s_chunk; + let mut boundary: Vec = Vec::with_capacity(nch); + for j in 0..nch { + let lo = j * s_chunk; + let hi = ((j + 1) * s_chunk).min(l); + let cout = circ.alloc_qubit(); + let cin = if j == 0 { + cin0.as_ref() + } else { + Some(&boundary[j - 1]) + }; + fold_chunk_clean(circ, &ctl[lo..hi], &y[lo..hi], cin, &cout); + boundary.push(cout); + if release_controls && j == last_control_chunk && j + 1 < nch { + let (cc, sxor, sor, dne) = controls.take().expect("fold controls present"); + uncompute_fold_controls(circ, e, d, cc, sxor, sor, dne); + } + } + for j in (0..nch).rev() { + if release_controls && j == last_control_chunk && controls.is_none() { + let rebuilt = build_fold_controls(circ, e, d); + ctl = fold_ctl_map(*e, *d, rebuilt.0, rebuilt.1, rebuilt.2, rebuilt.3, l); + controls = Some(rebuilt); + } + let lo = j * s_chunk; + let hi = ((j + 1) * s_chunk).min(l); + let bnd = boundary.pop().expect("boundary present"); + let cin = if j == 0 { + cin0.as_ref() + } else { + Some(&boundary[j - 1]) + }; + fold_boundary_erase(circ, &ctl[lo..hi], &y[lo..hi], cin, bnd); + } + if let Some(cin0) = cin0 { + circ.zero_and_free(cin0); + } + let (cc, sxor, sor, dne) = controls.take().expect("fold controls restored"); + uncompute_fold_controls(circ, e, d, cc, sxor, sor, dne); +} + +enum OnCtl { + None, + E, + D, + Owned(QubitId), +} + +fn on_ctl_apply(circ: &mut B, e: &QubitId, d: &QubitId, k: u8, q: &QubitId) { + match k { + 3 => { + circ.cx(*e, *q); + circ.cx(*d, *q); + } + 4 => { + circ.x(*e); + circ.x(*d); + circ.ccx(*e, *d, *q); + circ.x(*q); + circ.x(*e); + circ.x(*d); + } + 5 => { + circ.x(*e); + circ.ccx(*e, *d, *q); + circ.x(*e); + } + 6 => circ.ccx(*e, *d, *q), + _ => {} + } +} + +fn on_ctl(circ: &mut B, e: &QubitId, d: &QubitId, p: usize) -> OnCtl { + match fold_ctl(p) { + 1 => OnCtl::E, + 2 => OnCtl::D, + k @ (3 | 4 | 5 | 6) => { + let q = circ.alloc_qubit(); + on_ctl_apply(circ, e, d, k, &q); + OnCtl::Owned(q) + } + _ => OnCtl::None, + } +} + +fn on_ctl_ref(c: &OnCtl, e: &QubitId, d: &QubitId) -> Option { + match c { + OnCtl::None => None, + OnCtl::E => Some(*e), + OnCtl::D => Some(*d), + OnCtl::Owned(q) => Some(*q), + } +} + +fn on_ctl_clear_nonlinear_hmr( + circ: &mut B, + e: &QubitId, + d: &QubitId, + k: u8, + q: &QubitId, +) { + let bit = circ.alloc_bit(); + circ.hmr(*q, bit); + match k { + 4 => { + circ.z_if_bit(*e, bit); + circ.z_if_bit(*d, bit); + circ.cz_if_bit(*e, *d, bit); + } + 5 => { + circ.z_if_bit(*d, bit); + circ.cz_if_bit(*e, *d, bit); + } + 6 => circ.cz_if_bit(*e, *d, bit), + _ => unreachable!("HMR clear requires a nonlinear fold control"), + } +} + +fn on_ctl_free(circ: &mut B, e: &QubitId, d: &QubitId, p: usize, c: OnCtl) { + if let OnCtl::Owned(q) = c { + let k = fold_ctl(p); + let hmr_disabled = std::env::var("TLM_FOLD_HMR_CONTROL_CLEANUP_DISABLE") + .ok() + .as_deref() + == Some("1"); + if k == 3 || hmr_disabled { + + on_ctl_apply(circ, e, d, k, &q); + } else { + on_ctl_clear_nonlinear_hmr(circ, e, d, k, &q); + } + circ.zero_and_free(q); + } +} + +fn xor_carries_perpos(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], out: &[QubitId], carry_in: Option<&QubitId>) { + let n = y.len(); + fn ccx_cond(circ: &mut B, aq: Option<&QubitId>, c1: &QubitId, c2: &QubitId, t: &QubitId, g0: bool, g1: bool) { + if let Some(a) = aq { + if g0 { + circ.cx(*a, *c1); + } + if g1 { + circ.cx(*a, *c2); + } + } + circ.ccx(*c1, *c2, *t); + if let Some(a) = aq { + if g0 { + circ.cx(*a, *c1); + } + if g1 { + circ.cx(*a, *c2); + } + } + } + for i in (1..n - 1).rev() { + let c = on_ctl(circ, e, d, base + i); + let aq = on_ctl_ref(&c, e, d); + let g0 = aq.is_some(); + ccx_cond(circ, aq.as_ref(), &y[i], &out[i - 1], &out[i], g0, false); + on_ctl_free(circ, e, d, base + i, c); + } + for i in 0..n - 1 { + let c = on_ctl(circ, e, d, base + i); + if let Some(a) = on_ctl_ref(&c, e, d) { + circ.cx(a, out[i]); + } + on_ctl_free(circ, e, d, base + i, c); + } + { + let c = on_ctl(circ, e, d, base); + let aq = on_ctl_ref(&c, e, d); + let g = aq.is_some(); + match carry_in { + Some(cy) => ccx_cond(circ, aq.as_ref(), cy, &y[0], &out[0], g, g), + None => { + let cin = circ.alloc_qubit(); + ccx_cond(circ, aq.as_ref(), &cin, &y[0], &out[0], g, g); + circ.zero_and_free(cin); + } + } + on_ctl_free(circ, e, d, base, c); + } + for i in 1..n - 1 { + let c = on_ctl(circ, e, d, base + i); + let aq = on_ctl_ref(&c, e, d); + let gi = aq.is_some(); + ccx_cond(circ, aq.as_ref(), &y[i], &out[i - 1], &out[i], gi, gi); + on_ctl_free(circ, e, d, base + i, c); + } +} + +fn dirty_body(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], dirty: &[QubitId], carry_in: Option<&QubitId>) { + let dirty_call_index = next_fold_dirty_call_index(); + let l = y.len(); + assert!(l >= 2); + assert!(dirty.len() >= l - 1, "need L-1 borrowed dirty bits"); + let mut cin_owned = if carry_in.is_none() { Some(circ.alloc_qubit()) } else { None }; + let mut bits: Vec = Vec::with_capacity(l - 1); + let mut prev_new: Option = None; + for i in 0..l - 1 { + let new = circ.alloc_qubit(); + let anc = circ.alloc_qubit(); + let ctlh = on_ctl(circ, e, d, base + i); + { + let cyi: QubitId = if i == 0 { + carry_in.copied().unwrap_or_else(|| *cin_owned.as_ref().unwrap()) + } else { + *prev_new.as_ref().unwrap() + }; + if let Some(ai) = on_ctl_ref(&ctlh, e, d) { + circ.cx(ai, anc); + } + circ.cx(cyi, anc); + circ.cx(cyi, y[i]); + let old_context = crate::point_add::set_op_trace_context( + 0x0f00_0000 | (((dirty_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + if !fused_dirty_fold_has_structurally_dead_carry(dirty_call_index, i) { + circ.ccx(y[i], anc, new); + } + crate::point_add::restore_op_trace_context(old_context); + circ.cx(cyi, new); + circ.cx(new, dirty[i]); + circ.cx(cyi, anc); + if let Some(ai) = on_ctl_ref(&ctlh, e, d) { + circ.cx(ai, anc); + circ.cx(ai, y[i]); + } + } + on_ctl_free(circ, e, d, base + i, ctlh); + circ.zero_and_free(anc); + if i == 0 { + if let Some(c) = cin_owned.take() { + circ.zero_and_free(c); + } + } else { + let b = circ.alloc_bit(); + circ.hmr(*prev_new.as_ref().unwrap(), b); + circ.zero_and_free(prev_new.take().unwrap()); + bits.push(b); + } + prev_new = Some(new); + } + let cy_top = prev_new.take().unwrap(); + { + let topc = on_ctl(circ, e, d, base + l - 1); + if let Some(at) = on_ctl_ref(&topc, e, d) { + circ.cx(at, y[l - 1]); + } + on_ctl_free(circ, e, d, base + l - 1, topc); + } + circ.cx(cy_top, y[l - 1]); + let b = circ.alloc_bit(); + circ.hmr(cy_top, b); + circ.zero_and_free(cy_top); + bits.push(b); + + for i in 0..l - 1 { + circ.z_if_bit(dirty[i], bits[i]); + } + for q in y { + circ.x(*q); + } + xor_carries_perpos(circ, e, d, base, y, dirty, carry_in); + for q in y { + circ.x(*q); + } + for i in 0..l - 1 { + circ.z_if_bit(dirty[i], bits[i]); + } +} + +fn clean_window_fwd(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], carries: &[QubitId]) { + let clean_window_call_index = next_fold_clean_window_call_index(); + let b = y.len(); + assert_eq!(carries.len(), b); + { + let c0 = on_ctl(circ, e, d, base); + if let Some(a0) = on_ctl_ref(&c0, e, d) { + let old_context = crate::point_add::set_op_trace_context( + 0x1000_0000 | (((clean_window_call_index as u32) & 0xffff) << 8), + ); + if !fused_clean_window_has_structurally_dead_carry(clean_window_call_index, 0) { + circ.ccx(a0, y[0], carries[0]); + } + crate::point_add::restore_op_trace_context(old_context); + } + on_ctl_free(circ, e, d, base, c0); + } + for i in 1..b { + let ci = on_ctl(circ, e, d, base + i); + let ai = on_ctl_ref(&ci, e, d); + circ.cx(carries[i - 1], y[i]); + if let Some(a) = &ai { + circ.cx(*a, carries[i - 1]); + } + let old_context = crate::point_add::set_op_trace_context( + 0x1000_0000 | (((clean_window_call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + if !fused_clean_window_has_structurally_dead_carry(clean_window_call_index, i) { + circ.ccx(y[i], carries[i - 1], carries[i]); + } + crate::point_add::restore_op_trace_context(old_context); + if let Some(a) = &ai { + circ.cx(*a, carries[i - 1]); + } + circ.cx(carries[i - 1], carries[i]); + on_ctl_free(circ, e, d, base + i, ci); + } + for i in 0..b { + let ci = on_ctl(circ, e, d, base + i); + if let Some(a) = on_ctl_ref(&ci, e, d) { + circ.cx(a, y[i]); + } + on_ctl_free(circ, e, d, base + i, ci); + } +} + +fn clean_window_rev(circ: &mut B, e: &QubitId, d: &QubitId, base: usize, y: &[QubitId], carries: Vec) { + let b = y.len(); + let mut cy: Vec> = carries.into_iter().map(Some).collect(); + for i in (1..b).rev() { + let ci_ctl = on_ctl(circ, e, d, base + i); + let actl = on_ctl_ref(&ci_ctl, e, d); + if let Some(ai) = &actl { + circ.cx(*ai, y[i]); + } + let next = cy[i].take().unwrap(); + let ci = cy[i - 1].take().unwrap(); + circ.cx(ci, next); + if let Some(ai) = &actl { + circ.cx(*ai, ci); + } + let bit = circ.alloc_bit(); + circ.hmr(next, bit); + circ.zero_and_free(next); + circ.cz_if_bit(y[i], ci, bit); + if let Some(ai) = &actl { + circ.cx(*ai, ci); + circ.cx(*ai, y[i]); + } + on_ctl_free(circ, e, d, base + i, ci_ctl); + cy[i - 1] = Some(ci); + } + let cy0 = cy[0].take().unwrap(); + let c0 = on_ctl(circ, e, d, base); + if let Some(a0) = on_ctl_ref(&c0, e, d) { + circ.cx(a0, y[0]); + let bit = circ.alloc_bit(); + circ.hmr(cy0, bit); + circ.zero_and_free(cy0); + circ.cz_if_bit(y[0], a0, bit); + circ.cx(a0, y[0]); + } else { + circ.zero_and_free(cy0); + } + on_ctl_free(circ, e, d, base, c0); +} + +fn build_fold_at(circ: &mut B, e: &QubitId, d: &QubitId, y: &[QubitId], dirty: &[QubitId], nv: usize) { + let l = y.len(); + if nv >= l - 1 { + + add_mf_fold_clean(circ, e, d, y); + return; + } + + const PROP_FROM: usize = 34; + if nv >= 1 && nv >= PROP_FROM { + add_mf_fold_clean_tail(circ, e, d, y, Some(nv)); + return; + } + if nv == 0 { + dirty_body(circ, e, d, 0, y, dirty, None); + } else { + let carries: Vec = (0..nv).map(|_| circ.alloc_qubit()).collect(); + clean_window_fwd(circ, e, d, 0, &y[..nv], &carries); + let cin = carries[nv - 1]; + dirty_body(circ, e, d, nv, &y[nv..], &dirty[nv..], Some(&cin)); + clean_window_rev(circ, e, d, 0, &y[..nv], carries); + } +} + +fn fused_fold(circ: &mut B, e: &QubitId, d: &QubitId, ylow: &[QubitId], dirty: &[QubitId]) { + let call_index = next_fold_call_index(); + let prior_fold_call_index = enter_fold_call_index(call_index); + let timeline_start = circ.active_timeline.len(); + let entry_active = circ.active_qubits; + let code = super::next_fold(); + let mut selected_nv = None; + if code < 0 { + let chunk = std::env::var("TLM_FOLD_CHUNK_FORCE") + .ok() + .and_then(|value| value.parse::().ok()) + .filter(|&value| value > 0) + .unwrap_or((-code) as usize); + add_mf_fold_chunked(circ, e, d, ylow, chunk); + } else { + let default_reserve = std::env::var("TLM_TARGET_FOLD_RESERVE") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(4); + let reserve = fold_call_reserve(call_index, default_reserve); + let nv = super::target_qubit_headroom(circ) + .map_or(code as usize, |headroom| { + (code as usize).min(headroom.saturating_sub(reserve)) + }); + selected_nv = Some(nv); + build_fold_at(circ, e, d, ylow, dirty, nv); + } + restore_fold_call_index(prior_fold_call_index); + if std::env::var_os("TRACE_TLM_FOLD").is_some() { + let local_peak = circ.active_timeline[timeline_start..] + .iter() + .map(|(_, active)| *active) + .max() + .unwrap_or(circ.active_qubits); + eprintln!( + "TLM_FOLD call={} phase={} code={} nv={} entry_active={} local_peak={} ops={}", + call_index, + circ.phase, + code, + selected_nv.map_or(-1, |value| value as i32), + entry_active, + local_peak, + circ.current_ops_len(), + ); + } +} + +fn fused_fold_e_only(circ: &mut B, e: &QubitId, y: &[QubitId]) { + let call_index = next_fold_call_index(); + let prior_fold_call_index = enter_fold_call_index(call_index); + let timeline_start = circ.active_timeline.len(); + let entry_active = circ.active_qubits; + let code = super::next_fold(); + let default_reserve = std::env::var("TLM_TARGET_FOLD_RESERVE") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(4); + let reserve = fold_call_reserve(call_index, default_reserve); + let g = if code < 0 { + 0 + } else { + super::target_qubit_headroom(circ) + .map_or(code as usize, |headroom| { + (code as usize).min(headroom.saturating_sub(reserve)) + }) + .min(LSBS - 1) + }; + let f_bytes = F_SECP256K1.to_le_bytes(); + super::arith::add_f_window_pub(circ, e, y, LSBS, &f_bytes, Some(g)); + restore_fold_call_index(prior_fold_call_index); + if std::env::var_os("TRACE_TLM_FOLD").is_some() { + let local_peak = circ.active_timeline[timeline_start..] + .iter() + .map(|(_, active)| *active) + .max() + .unwrap_or(circ.active_qubits); + eprintln!( + "TLM_FOLD call={} phase={} code={} nv={} entry_active={} local_peak={} ops={}", + call_index, + circ.phase, + code, + g as i32, + entry_active, + local_peak, + circ.current_ops_len(), + ); + } +} + +fn trace_fold_alloc(circ: &B, name: &str, stage: &str, i: usize) { + if std::env::var_os("TRACE_TLM_FOLD_ALLOC").is_some() { + eprintln!( + "TLM_FOLD_ALLOC name={name} stage={stage} i={i} active={} ops={}", + circ.active_qubits, + circ.current_ops_len(), + ); + } +} + +pub fn fused_double_cdouble(circ: &mut B, s2: &QubitId, y: &[QubitId]) { + let shift_call_index = next_fused_cdouble_fwd_shift_call_index(); + maybe_run_gradual_fold_nonlinear_control_hmr_selftest(); + let n = 256usize; + assert_eq!(y.len(), n, "fused double expects 256-bit y (transient overflow)"); + let _ = F_SECP256K1; + trace_fold_alloc(circ, "fwd_cdouble", "entry", usize::MAX); + let hi = circ.alloc_qubit(); + trace_fold_alloc(circ, "fwd_cdouble", "after_hi", usize::MAX); + let hi2 = circ.alloc_qubit(); + trace_fold_alloc(circ, "fwd_cdouble", "after_hi2", usize::MAX); + + let mut w: Vec = y.to_vec(); + w.push(hi); + w.push(hi2); + + for i in (1..w.len()).rev() { + circ.swap(w[i], w[i - 1]); + } + + for i in (1..w.len()).rev() { + let bit = i - 1; + let old_context = crate::point_add::set_op_trace_context( + 0x1400_0000 | (((shift_call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff), + ); + if !(bit == 0 && skip_structural_dead_fused_cdouble_shift0()) { + circ.cswap(*s2, w[i], w[i - 1]); + } + crate::point_add::restore_op_trace_context(old_context); + } + + let borrow: Vec = y[LSBS..2 * LSBS - 1].to_vec(); + fused_fold(circ, &w[n], &w[n + 1], &y[..LSBS], &borrow); + + circ.cx(y[0], w[n]); + clear_and(circ, &w[n + 1], s2, &y[1]); + circ.zero_and_free(hi); + circ.zero_and_free(hi2); +} + +pub fn fused_double_only(circ: &mut B, y: &[QubitId]) { + let n = 256usize; + assert_eq!(y.len(), n, "fused double expects 256-bit y"); + trace_fold_alloc(circ, "fwd_only", "entry", usize::MAX); + let hi = circ.alloc_qubit(); + trace_fold_alloc(circ, "fwd_only", "after_hi", usize::MAX); + let mut w: Vec = y.to_vec(); + w.push(hi); + for i in (1..w.len()).rev() { + circ.swap(w[i], w[i - 1]); + } + fused_fold_e_only(circ, &w[n], y); + circ.cx(y[0], w[n]); + circ.zero_and_free(hi); +} + +pub fn fused_double_cdouble_reverse(circ: &mut B, s2: &QubitId, y: &[QubitId]) { + let shift_call_index = next_fused_cdouble_rev_shift_call_index(); + maybe_run_gradual_fold_nonlinear_control_hmr_selftest(); + let n = 256usize; + assert_eq!(y.len(), n, "fused halve expects 256-bit y (transient overflow)"); + trace_fold_alloc(circ, "rev_cdouble", "entry", usize::MAX); + let hi = circ.alloc_qubit(); + trace_fold_alloc(circ, "rev_cdouble", "after_hi", usize::MAX); + let hi2 = circ.alloc_qubit(); + trace_fold_alloc(circ, "rev_cdouble", "after_hi2", usize::MAX); + let mut w: Vec = y.to_vec(); + w.push(hi); + w.push(hi2); + + circ.ccx(*s2, y[1], w[n + 1]); + circ.cx(y[0], w[n]); + + let borrow: Vec = y[LSBS..2 * LSBS - 1].to_vec(); + for q in &y[..LSBS] { + circ.x(*q); + } + fused_fold(circ, &w[n], &w[n + 1], &y[..LSBS], &borrow); + for q in &y[..LSBS] { + circ.x(*q); + } + + for i in 1..w.len() { + let bit = i - 1; + let old_context = crate::point_add::set_op_trace_context( + 0x1500_0000 | (((shift_call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff), + ); + if !(bit == 0 && skip_structural_dead_fused_cdouble_shift0()) { + circ.cswap(*s2, w[i], w[i - 1]); + } + crate::point_add::restore_op_trace_context(old_context); + } + for i in 1..w.len() { + circ.swap(w[i], w[i - 1]); + } + circ.zero_and_free(hi); + circ.zero_and_free(hi2); +} + +pub fn fused_double_only_reverse(circ: &mut B, y: &[QubitId]) { + let n = 256usize; + assert_eq!(y.len(), n, "fused halve expects 256-bit y"); + trace_fold_alloc(circ, "rev_only", "entry", usize::MAX); + let hi = circ.alloc_qubit(); + trace_fold_alloc(circ, "rev_only", "after_hi", usize::MAX); + let mut w: Vec = y.to_vec(); + w.push(hi); + circ.cx(y[0], w[n]); + for q in &y[..LSBS] { + circ.x(*q); + } + fused_fold_e_only(circ, &w[n], y); + for q in &y[..LSBS] { + circ.x(*q); + } + for i in 1..w.len() { + circ.swap(w[i], w[i - 1]); + } + circ.zero_and_free(hi); +} + +fn gradual_fold_nonlinear_control_hmr_selftest() { + use crate::circuit::OperationType; + use crate::sim::Simulator; + use sha3::{ + digest::{ExtendableOutput, Update}, + Shake128, + }; + + for &(position, kind) in &[(8usize, 4u8), (10, 5), (11, 6)] { + assert_eq!(fold_ctl(position), kind); + + let mut circ = B::new(); + let e = circ.alloc_qubit(); + let d = circ.alloc_qubit(); + let q = circ.alloc_qubit(); + on_ctl_apply(&mut circ, &e, &d, kind, &q); + on_ctl_free(&mut circ, &e, &d, position, OnCtl::Owned(q)); + + assert_eq!(circ.active_qubits, 2, "owned control was not released"); + assert_eq!(circ.peak_qubits, 3, "cleanup increased peak width"); + assert_eq!(circ.next_bit, 1, "expected one HMR result bit"); + assert_eq!( + circ.ops + .iter() + .filter(|op| matches!(op.kind, OperationType::CCX | OperationType::CCZ)) + .count(), + 1, + "cleanup must add no Toffoli-class gate", + ); + assert_eq!( + circ.ops + .iter() + .filter(|op| op.kind == OperationType::Hmr) + .count(), + 1, + ); + + let mut e_mask = 0u64; + let mut d_mask = 0u64; + for shot in 0..64usize { + let state = shot & 3; + e_mask |= ((state & 1) as u64) << shot; + d_mask |= (((state >> 1) & 1) as u64) << shot; + } + + let mut seed = Shake128::default(); + seed.update(b"gradual-fold-derived-control-hmr"); + seed.update(&[kind]); + let mut xof = seed.finalize_xof(); + let mut sim = Simulator::new( + circ.next_qubit as usize, + circ.next_bit as usize, + &mut xof, + ); + *sim.qubit_mut(e) = e_mask; + *sim.qubit_mut(d) = d_mask; + sim.apply_iter(circ.ops.iter()); + + assert_eq!(sim.qubit(e), e_mask, "e changed for control kind {kind}"); + assert_eq!(sim.qubit(d), d_mask, "d changed for control kind {kind}"); + assert_eq!(sim.qubit(q), 0, "owned control remained dirty for kind {kind}"); + assert_eq!(sim.phase, 0, "phase feedback failed for control kind {kind}"); + + let measured = sim.bits[0]; + for state in 0..4usize { + let mut outcomes = 0u8; + for shot in (state..64usize).step_by(4) { + outcomes |= 1 << ((measured >> shot) & 1); + } + assert_eq!( + outcomes, 0b11, + "HMR outcomes not exhaustive for kind {kind}, state {state}", + ); + } + } +} + +fn maybe_run_gradual_fold_nonlinear_control_hmr_selftest() { + if std::env::var_os("TLM_FOLD_HMR_CONTROL_SELFTEST").is_none() { + return; + } + static SELFTEST: std::sync::Once = std::sync::Once::new(); + SELFTEST.call_once(|| { + gradual_fold_nonlinear_control_hmr_selftest(); + eprintln!("TLM_FOLD_HMR_CONTROL_SELFTEST_OK"); + }); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn gradual_fold_nonlinear_control_hmr_cleanup_is_exact() { + gradual_fold_nonlinear_control_hmr_selftest(); + } +} diff --git a/src/point_add/trailmix_ludicrous/gcd.rs b/src/point_add/trailmix_ludicrous/gcd.rs index 1b789fab..0c297169 100644 --- a/src/point_add/trailmix_ludicrous/gcd.rs +++ b/src/point_add/trailmix_ludicrous/gcd.rs @@ -1,1937 +1,1461 @@ - -use super::arith::{self, F_SECP256K1}; -use super::schedule::{GAP_J2, ITERS, JUMP, SCHED_J2}; - -fn gap_j2_delta() -> usize { - std::env::var("TLM_GAP_J2_DELTA") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(0) -} - -fn gap_j2_mask_trunc_only() -> bool { - std::env::var("TLM_GAP_J2_TRUNC_ONLY").ok().as_deref() == Some("1") -} - -// cmp window for step i: baseline is min(GAP_J2[i], current_n). -// Delta narrows it; TRUNC_ONLY restricts narrowing to steps where the -// baseline window is ALREADY a strict truncation (GAP_J2[i] < current_n), -// leaving the exact-comparison tail steps untouched. -fn cmp_window(i: usize, current_n: usize) -> usize { - let g = GAP_J2[i] as usize; - let base = g.min(current_n).max(1); - let d = gap_j2_delta(); - if d == 0 { - return base; - } - if gap_j2_mask_trunc_only() && g >= current_n { - return base; - } - let lo = std::env::var("TLM_GAP_J2_LO").ok().and_then(|v| v.parse::().ok()).unwrap_or(0); - let hi = std::env::var("TLM_GAP_J2_HI").ok().and_then(|v| v.parse::().ok()).unwrap_or(usize::MAX); - if i < lo || i >= hi { - return base; - } - base.saturating_sub(d).max(1) -} - -use super::{B, BExt}; -use crate::circuit::{QubitId}; -use std::cell::Cell; - -thread_local! { - static RIGHT_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; - static LEFT_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; -} - -pub(super) fn reset_gcd_trace_call_index() { - RIGHT_SHIFT_CALL_INDEX.with(|index| index.set(0)); - LEFT_SHIFT_CALL_INDEX.with(|index| index.set(0)); -} - -fn next_right_shift_call_index() -> usize { - RIGHT_SHIFT_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_left_shift_call_index() -> usize { - LEFT_SHIFT_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum Direction { - - Inverse, - - Forward, -} - -#[must_use] -pub fn q_secp256k1_le() -> [u8; 32] { - let mut b = [0xFFu8; 32]; - b[0] = 0x2F; - b[1] = 0xFC; - b[4] = 0xFE; - b -} - -#[must_use] -pub fn n3_for_iters(iters: usize) -> usize { - iters / 3 -} - -fn env_i32(name: &str, default: i32) -> i32 { - std::env::var(name) - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(default) -} - -fn env_usize(name: &str, default: usize) -> usize { - std::env::var(name) - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(default) -} - -fn adjust_gcd_k(prefix: &str, i: usize, k: usize) -> usize { - if k == usize::MAX { - return k; - } - let adjust = env_i32(&format!("{prefix}_ADJUST"), 0); - let after = env_usize(&format!("{prefix}_ADJUST_AFTER"), 0); - let before = env_usize(&format!("{prefix}_ADJUST_BEFORE"), usize::MAX); - if i >= after && i < before && adjust != 0 { - (k as i32).saturating_add(adjust).max(0) as usize - } else { - k - } -} - -fn maybe_adjust_late_gcd_k(i: usize, k: usize) -> usize { - let k = adjust_gcd_k("TLM_GCD_K", i, k); - adjust_gcd_k("TLM_GCD_K_EXTRA", i, k) -} - -fn trace_step_regions(circ: &mut B, direction: &str, i: usize, region_start: usize) { - if std::env::var("TRACE_TLM_GCD_STEPS").is_err() { - return; - } - let threshold = std::env::var("TRACE_TLM_GCD_MIN_Q") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(1150); - let step_max = circ.phase_active_regions[region_start..] - .iter() - .map(|(_, _, active)| *active) - .max() - .unwrap_or(circ.active_qubits); - if step_max >= threshold { - eprintln!( - "TLM_GCD_STEP direction={direction} i={i} active_max={step_max} global_peak={} ops={}", - circ.peak_qubits, - circ.current_ops_len(), - ); - for (_, phase, active) in &circ.phase_active_regions[region_start..] { - if *active >= threshold { - eprintln!( - "TLM_GCD_STAGE direction={direction} i={i} active_max={active} phase={phase}", - ); - } - } - } -} - -fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { - let bit = circ.alloc_bit(); - circ.hmr(*t, bit); - circ.cz_if_bit(*a, *b, bit); -} - -fn park_odd_u0_enabled(i: usize, side: &str) -> bool { - let all = std::env::var("TLM_PARK_ODD_U0").ok().as_deref() == Some("1"); - let side_on = std::env::var(format!("TLM_PARK_ODD_U0_{side}")) - .ok() - .as_deref() - == Some("1"); - if !all && !side_on { - return false; - } - let limit = std::env::var("TLM_PARK_ODD_U0_LIMIT") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(usize::MAX); - i < limit -} - -fn loan_odd_u0_enabled() -> bool { - std::env::var("TLM_LOAN_ODD_U0").ok().as_deref() == Some("1") -} - -fn park_even_v0_enabled() -> bool { - std::env::var("TLM_PARK_EVEN_V0").ok().as_deref() == Some("1") -} - -fn loan_even_v0_enabled() -> bool { - std::env::var("TLM_LOAN_EVEN_V0").ok().as_deref() == Some("1") -} - -fn loan_gcd_y0_enabled() -> bool { - std::env::var("TLM_LOAN_GCD_Y0").ok().as_deref() == Some("1") -} - -fn apply_fwd_cswap_skip(i: usize) -> bool { - let legacy_first_skip = - std::env::var("TLM_APPLY_FWD_FIRST_CSWAP_SKIP").ok().as_deref() == Some("1") - && i + 1 == ITERS; - let last_n = std::env::var("TLM_APPLY_FWD_CSWAP_SKIP_LAST") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0); - legacy_first_skip || (last_n != 0 && i + last_n >= ITERS) -} - -fn apply_inv_cswap_skip(i: usize) -> bool { - let last_n = std::env::var("TLM_APPLY_INV_CSWAP_SKIP_LAST") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0); - last_n != 0 && i + last_n >= ITERS -} - -fn apply_fwd_s2_zero(i: usize) -> bool { - let last_n = std::env::var("TLM_APPLY_FWD_S2_ZERO_LAST") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0); - last_n != 0 && i + last_n >= ITERS -} - -fn apply_inv_s2_zero(i: usize) -> bool { - let last_n = std::env::var("TLM_APPLY_INV_S2_ZERO_LAST") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0); - last_n != 0 && i + last_n >= ITERS -} - -fn apply_add_skip(i: usize, fwd: bool) -> bool { - if let Some(k) = std::env::var("TLM_APPLY_ADD_SKIP_LASTK") - .ok() - .and_then(|value| value.parse::().ok()) - { - if k != 0 && i + k >= ITERS { - return true; - } - } - let var = if fwd { - "TLM_APPLY_ADD_SKIP_FWD" - } else { - "TLM_APPLY_ADD_SKIP_INV" - }; - let k = std::env::var(var) - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0); - k != 0 && i + k >= ITERS -} - -fn park_known_one(circ: &mut B, q: QubitId) -> QubitId { - circ.x(q); - if loan_odd_u0_enabled() { - circ.loan_zero_qubit(q); - } else { - circ.zero_and_free(q); - } - q -} - -fn restore_known_one(circ: &mut B, parked: QubitId) -> QubitId { - let q = if loan_odd_u0_enabled() { - circ.reclaim_zero_qubit(parked); - parked - } else { - circ.alloc_qubit() - }; - circ.x(q); - q -} - -fn park_known_zero(circ: &mut B, q: QubitId) -> QubitId { - if loan_even_v0_enabled() { - circ.loan_zero_qubit(q); - } else { - circ.zero_and_free(q); - } - q -} - -fn restore_known_zero(circ: &mut B, parked: QubitId) -> QubitId { - if loan_even_v0_enabled() { - circ.reclaim_zero_qubit(parked); - parked - } else { - circ.alloc_qubit() - } -} - -fn loan_known_one_gcd_y0(circ: &mut B, q: QubitId) { - circ.x(q); - circ.loan_zero_qubit(q); -} - -fn reclaim_known_one_gcd_y0(circ: &mut B, q: QubitId) { - circ.reclaim_zero_qubit(q); - circ.x(q); -} - -fn loan_known_zero_gcd_y0(circ: &mut B, q: QubitId) { - circ.loan_zero_qubit(q); -} - -fn reclaim_known_zero_gcd_y0(circ: &mut B, q: QubitId) { - circ.reclaim_zero_qubit(q); -} - -const GCD_REVERSE_CSWAP_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (255, 5, 13), - (256, 3, 11), - (253, 8, 15), - (254, 7, 13), - (252, 10, 15), - (250, 13, 16), - (251, 12, 15), - (249, 13, 16), - (236, 27, 29), - (248, 15, 17), - (234, 29, 31), - (235, 28, 30), - (237, 26, 28), - (244, 18, 20), - (246, 17, 19), - (247, 16, 18), - (101, 164, 165), - (143, 122, 123), - (145, 120, 121), - (219, 45, 46), - (220, 44, 45), - (221, 43, 44), - (224, 40, 41), - (226, 38, 39), - (228, 36, 37), - (229, 35, 36), - (231, 33, 34), - (232, 32, 33), - (233, 31, 32), - (245, 18, 19), - (257, 7, 10), - (95, 170, 171), - (116, 149, 150), - (134, 131, 132), - (218, 46, 47), - (222, 42, 43), - (223, 41, 42), - (225, 39, 40), - (227, 37, 38), - (230, 34, 35), - (240, 22, 23), - (11, 254, 254), - (12, 253, 253), - (19, 246, 246), - (21, 244, 244), - (30, 235, 235), - (31, 234, 234), - (33, 232, 232), - (35, 230, 230), - (36, 229, 229), - (37, 228, 228), - (39, 226, 226), - (40, 225, 225), - (42, 223, 223), - (43, 222, 222), - (46, 219, 219), - (47, 218, 218), - (48, 217, 217), - (49, 216, 216), - (50, 215, 215), - (51, 214, 214), - (53, 212, 212), - (54, 211, 211), - (56, 209, 209), - (63, 202, 202), - (68, 197, 197), - (70, 195, 195), - (75, 190, 190), - (76, 189, 189), - (79, 186, 186), - (80, 185, 185), - (81, 184, 184), - (87, 178, 178), - (94, 172, 172), - (103, 163, 163), - (105, 161, 161), - (107, 159, 159), - (108, 158, 158), - (110, 156, 156), - (112, 154, 154), - (113, 153, 153), - (114, 152, 152), - (115, 151, 151), - (123, 143, 143), - (124, 142, 142), - (126, 140, 140), - (127, 139, 139), - (128, 138, 138), - (129, 137, 137), - (130, 136, 136), - (131, 135, 135), - (132, 134, 134), - (133, 133, 133), - (141, 125, 125), - (142, 124, 124), - (146, 119, 119), - (147, 118, 118), - (148, 117, 117), - (149, 116, 116), - (153, 112, 112), - (157, 108, 108), - (159, 106, 106), - (161, 104, 104), - (162, 103, 103), - (163, 102, 102), - (164, 101, 101), - (167, 98, 98), - (168, 97, 97), - (169, 96, 96), - (170, 95, 95), - (171, 94, 94), - (180, 85, 85), - (182, 83, 83), - (183, 82, 82), - (187, 78, 78), - (188, 77, 77), - (189, 76, 76), - (190, 75, 75), - (192, 73, 73), - (193, 72, 72), - (194, 71, 71), - (195, 70, 70), - (197, 68, 68), - (198, 67, 67), - (199, 66, 66), - (203, 62, 62), - (204, 61, 61), - (205, 60, 60), - (206, 59, 59), - (207, 58, 58), - (208, 57, 57), - (210, 55, 55), - (211, 54, 54), - (212, 53, 53), - (213, 52, 52), - (214, 51, 51), - (215, 50, 50), - (216, 49, 49), - (217, 48, 48), - (238, 25, 25), - (239, 24, 24), - (241, 22, 22), - (242, 21, 21), -]; - -const GCD_FORWARD_CSWAP_REMAINDER_KEYS: &[u32] = &[ - 3325, 4345, 8935, 9955, 17860, 24236, 26021, 26531, 26786, 27551, 28316, 28571, - 29846, 31631, 31886, 32906, 33161, 33416, 33671, 33926, 34181, 34436, 35710, - 36221, 36476, 36985, 37241, 38260, 40810, 41575, 41830, 43360, 44380, 45145, - 46165, 46675, 47185, 47950, 48205, 48715, 49225, 50755, 51010, 51520, 51775, - 52030, 52285, 52540, 53305, 53560, 54070, 54580, 54835, 55090, 55600, 56110, - 56620, 56875, 57130, 57385, 57895, 58149, 58405, 58660, 58915, 59170, 59425, - 59680, 59935, 60190, 60444, 60445, 60700, 62484, 62995, 63250, 63505, 63759, - 63760, 64014, 64015, 64016, 64270, 64271, 64524, 64525, 64526, 64527, 64779, - 64780, 64781, 64782, 64783, 65035, 65036, 65037, 65290, 65291, 65292, 65293, - 65545, 65546, 65547, 65800, 65801, 65802, -]; - -const GCD_REVERSE_CSWAP_REMAINDER_KEYS: &[u32] = &[ - 3580, 3835, 4090, 4345, 4600, 4855, 5365, 5875, 6130, 6640, 6895, 7150, - 7405, 7660, 8425, 8935, 9955, 10720, 11740, 13525, 14290, 15055, 15310, - 15565, 15820, 16075, 16585, 16840, 17095, 17350, 18370, 18625, 18880, - 19135, 19900, 20155, 21175, 21685, 22195, 22705, 22960, 23215, 23470, - 23725, 24745, 25255, 25510, 26786, 31376, 34690, 34945, 35200, 35455, - 38515, 38770, 39025, 39790, 40045, 40555, 41065, 42340, 42595, 44125, - 44635, 44890, 45145, 45400, 45655, 45910, 46420, 47185, 47440, 48970, - 50245, 51265, 53560, -]; - -fn gcd_reverse_cswap_has_structurally_dead_gate(step: usize, bit: usize) -> bool { - if super::drops_off_family("GCDRSW") { - return false; - } - - if std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS").is_none() { - return false; - } - if std::env::var_os("TLM_GCD_SKIP_REVERSE_DIAGONAL_EDGE").is_some() - && step + bit - >= std::env::var("TLM_GCD_REVERSE_DIAGONAL_MIN") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(265) - && step - >= std::env::var("TLM_GCD_REVERSE_DIAGONAL_STEP_MIN") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0) - && step - <= std::env::var("TLM_GCD_REVERSE_DIAGONAL_STEP_MAX") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(usize::MAX) - { - return true; - } - if std::env::var_os("TLM_GCD_SKIP_EXACT_REVERSE_CSWAPS").is_some() { - let key = (((step as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if GCD_REVERSE_CSWAP_REMAINDER_KEYS.binary_search(&key).is_ok() { - return true; - } - } - GCD_REVERSE_CSWAP_DEAD_RANGES - .iter() - .any(|&(range_step, lo, hi)| range_step == step && (lo..=hi).contains(&bit)) -} - -fn gcd_forward_cswap_has_structurally_dead_gate(step: usize, bit: usize) -> bool { - if super::drops_off_family("GCDFSW") { - return false; - } - - // W1155: forward structurally-dead-cswap predicate := reverse predicate (bit-exact, - // the forward pass shares the reverse pass's provably-dead structure). - if std::env::var_os("W1155_FWD_EQ_REV").is_some() { - return gcd_reverse_cswap_has_structurally_dead_gate(step, bit); - } - if std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS").is_none() - || std::env::var_os("TLM_GCD_SKIP_EXACT_FORWARD_CSWAPS").is_none() - { - return false; - } - let key = (((step as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - GCD_FORWARD_CSWAP_REMAINDER_KEYS.binary_search(&key).is_ok() -} - -const GCD_SHIFT_DEAD_RANGES: &[(u8, usize, usize, usize)] = &[ - (12, 0, 1, 9), - (12, 259, 1, 9), - (12, 1, 3, 10), - (12, 2, 5, 12), - (12, 260, 3, 10), - (12, 261, 5, 12), - (12, 262, 7, 12), - (12, 263, 9, 14), - (12, 264, 9, 14), - (12, 3, 7, 12), - (12, 4, 9, 14), - (12, 5, 10, 14), - (11, 254, 11, 14), - (11, 515, 8, 8), - (11, 515, 10, 12), - (11, 516, 7, 10), - (12, 265, 11, 14), - (12, 266, 12, 15), - (12, 6, 11, 14), - (12, 7, 12, 15), - (11, 252, 12, 14), - (11, 253, 12, 14), - (11, 255, 10, 12), - (11, 256, 10, 12), - (11, 257, 8, 10), - (11, 258, 7, 9), - (11, 510, 13, 15), - (11, 512, 12, 14), - (11, 513, 12, 14), - (11, 514, 10, 12), - (12, 20, 25, 27), - (12, 267, 13, 15), - (12, 269, 15, 17), - (12, 270, 16, 18), - (12, 279, 25, 27), - (12, 280, 26, 28), - (12, 287, 33, 35), - (12, 8, 13, 15), - (12, 9, 14, 16), - (11, 250, 14, 15), - (11, 251, 14, 15), - (11, 391, 133, 134), - (11, 405, 119, 120), - (11, 511, 12, 12), - (11, 511, 14, 14), - (11, 517, 8, 9), - (12, 10, 16, 17), - (12, 11, 17, 18), - (12, 12, 17, 18), - (12, 13, 18, 19), - (12, 21, 27, 28), - (12, 22, 28, 29), - (12, 23, 29, 30), - (12, 24, 30, 31), - (12, 25, 31, 32), - (12, 26, 32, 33), - (12, 268, 15, 16), - (12, 27, 33, 34), - (12, 271, 17, 18), - (12, 28, 34, 35), - (12, 281, 28, 29), - (12, 283, 30, 31), - (12, 286, 33, 34), - (12, 288, 35, 36), - (12, 289, 36, 37), - (12, 290, 37, 38), - (12, 293, 40, 41), - (12, 294, 41, 42), - (12, 295, 42, 43), - (12, 31, 37, 38), - (12, 32, 38, 39), - (12, 33, 39, 40), - (12, 34, 40, 41), - (12, 35, 41, 42), - (12, 36, 42, 43), - // E251: 376 additional structurally-dead gcd-shift ranges (audit-recovered). - (12, 39, 46, 46), - (12, 40, 47, 47), - (12, 41, 48, 48), - (12, 42, 49, 49), - (12, 43, 50, 50), - (12, 44, 51, 51), - (12, 45, 52, 52), - (12, 46, 53, 53), - (12, 48, 55, 55), - (12, 50, 57, 57), - (12, 52, 59, 59), - (12, 53, 60, 60), - (12, 54, 61, 61), - (12, 55, 62, 62), - (12, 56, 63, 63), - (12, 57, 64, 64), - (12, 58, 65, 65), - (12, 59, 66, 66), - (12, 61, 68, 68), - (12, 62, 69, 69), - (12, 63, 70, 70), - (12, 64, 71, 71), - (12, 65, 72, 72), - (12, 66, 73, 73), - (12, 67, 74, 74), - (12, 68, 75, 75), - (12, 70, 77, 77), - (12, 71, 78, 78), - (12, 72, 79, 79), - (12, 73, 80, 80), - (12, 74, 81, 81), - (12, 75, 82, 82), - (12, 76, 83, 83), - (12, 77, 84, 84), - (12, 78, 85, 85), - (12, 79, 86, 86), - (12, 80, 87, 87), - (12, 81, 88, 88), - (12, 82, 89, 89), - (12, 83, 90, 90), - (12, 84, 91, 91), - (12, 85, 92, 92), - (12, 86, 93, 93), - (12, 87, 94, 94), - (12, 88, 95, 95), - (12, 89, 96, 96), - (12, 90, 97, 97), - (12, 91, 98, 98), - (12, 92, 99, 99), - (12, 93, 100, 100), - (12, 94, 101, 101), - (12, 95, 102, 102), - (12, 96, 103, 103), - (12, 97, 104, 104), - (12, 98, 105, 105), - (12, 99, 106, 106), - (12, 101, 108, 108), - (12, 102, 109, 109), - (12, 103, 110, 110), - (12, 104, 111, 111), - (12, 105, 112, 112), - (12, 106, 113, 113), - (12, 107, 114, 114), - (12, 108, 115, 115), - (12, 109, 116, 116), - (12, 110, 117, 117), - (12, 111, 118, 118), - (12, 113, 120, 120), - (12, 115, 122, 122), - (12, 117, 124, 124), - (12, 118, 125, 125), - (12, 119, 126, 126), - (12, 121, 128, 128), - (12, 124, 131, 131), - (12, 125, 132, 132), - (12, 126, 133, 133), - (12, 127, 134, 134), - (12, 129, 136, 136), - (12, 130, 137, 137), - (12, 131, 138, 138), - (12, 132, 139, 139), - (12, 134, 141, 141), - (12, 135, 142, 142), - (12, 136, 143, 143), - (12, 137, 144, 144), - (12, 138, 145, 145), - (12, 139, 146, 146), - (12, 140, 147, 147), - (12, 142, 149, 149), - (12, 143, 150, 150), - (12, 144, 151, 151), - (12, 146, 153, 153), - (12, 147, 154, 154), - (12, 148, 155, 155), - (12, 149, 156, 156), - (12, 150, 157, 157), - (12, 151, 158, 158), - (12, 152, 159, 159), - (12, 153, 160, 160), - (12, 154, 161, 161), - (12, 155, 162, 162), - (12, 156, 163, 163), - (12, 157, 164, 164), - (12, 158, 165, 165), - (12, 159, 166, 166), - (12, 160, 167, 167), - (12, 161, 168, 168), - (12, 163, 170, 170), - (12, 164, 171, 171), - (12, 165, 172, 172), - (12, 166, 173, 173), - (12, 167, 174, 174), - (12, 168, 175, 175), - (12, 169, 176, 176), - (12, 170, 177, 177), - (12, 171, 178, 178), - (12, 172, 179, 179), - (12, 173, 180, 180), - (12, 174, 181, 181), - (12, 175, 182, 182), - (12, 176, 183, 183), - (12, 177, 184, 184), - (12, 178, 185, 185), - (12, 179, 186, 186), - (12, 180, 187, 187), - (12, 181, 188, 188), - (12, 182, 189, 189), - (12, 184, 191, 191), - (12, 185, 192, 192), - (12, 186, 193, 193), - (12, 187, 194, 194), - (12, 188, 195, 195), - (12, 189, 196, 196), - (12, 190, 197, 197), - (12, 191, 198, 198), - (12, 192, 199, 199), - (12, 193, 200, 200), - (12, 194, 201, 201), - (12, 195, 202, 202), - (12, 196, 203, 203), - (12, 197, 204, 204), - (12, 198, 205, 205), - (12, 199, 206, 206), - (12, 200, 207, 207), - (12, 201, 208, 208), - (12, 202, 209, 209), - (12, 203, 210, 210), - (12, 204, 211, 211), - (12, 205, 212, 212), - (12, 206, 213, 213), - (12, 207, 214, 214), - (12, 209, 216, 216), - (12, 210, 217, 217), - (12, 211, 218, 218), - (12, 212, 219, 219), - (12, 213, 220, 220), - (12, 214, 221, 221), - (12, 215, 222, 222), - (12, 216, 223, 223), - (12, 217, 224, 224), - (12, 218, 225, 225), - (12, 219, 226, 226), - (12, 220, 227, 227), - (12, 221, 228, 228), - (12, 222, 229, 229), - (12, 223, 230, 230), - (12, 224, 231, 231), - (12, 225, 232, 232), - (12, 226, 233, 233), - (12, 227, 234, 234), - (12, 228, 235, 235), - (12, 229, 236, 236), - (12, 230, 237, 237), - (12, 231, 238, 238), - (12, 232, 239, 239), - (12, 233, 240, 240), - (12, 234, 241, 241), - (12, 235, 242, 242), - (12, 236, 243, 243), - (12, 237, 244, 244), - (12, 238, 245, 245), - (12, 239, 246, 246), - (12, 240, 247, 247), - (12, 241, 248, 248), - (12, 242, 249, 249), - (12, 243, 250, 250), - (12, 245, 252, 252), - (12, 246, 253, 253), - (12, 247, 254, 254), - (12, 248, 255, 255), - (12, 249, 256, 256), - (12, 250, 257, 257), - (12, 298, 46, 46), - (12, 299, 47, 47), - (12, 300, 48, 48), - (12, 301, 49, 49), - (12, 302, 50, 50), - (12, 303, 51, 51), - (12, 304, 52, 52), - (12, 305, 53, 53), - (12, 306, 54, 54), - (12, 307, 55, 55), - (12, 308, 56, 56), - (12, 309, 57, 57), - (12, 310, 58, 58), - (12, 311, 59, 59), - (12, 312, 60, 60), - (12, 313, 61, 61), - (12, 315, 63, 63), - (12, 316, 64, 64), - (12, 317, 65, 65), - (12, 318, 66, 66), - (12, 319, 67, 67), - (12, 320, 68, 68), - (12, 321, 69, 69), - (12, 322, 70, 70), - (12, 323, 71, 71), - (12, 324, 72, 72), - (12, 325, 73, 73), - (12, 326, 74, 74), - (12, 327, 75, 75), - (12, 328, 76, 76), - (12, 329, 77, 77), - (12, 330, 78, 78), - (12, 331, 79, 79), - (12, 332, 80, 80), - (12, 333, 81, 81), - (12, 334, 82, 82), - (12, 335, 83, 83), - (12, 336, 84, 84), - (12, 337, 85, 85), - (12, 338, 86, 86), - (12, 339, 87, 87), - (12, 340, 88, 88), - (12, 342, 90, 90), - (12, 343, 91, 91), - (12, 344, 92, 92), - (12, 345, 93, 93), - (12, 346, 94, 94), - (12, 347, 95, 95), - (12, 348, 96, 96), - (12, 350, 98, 98), - (12, 351, 99, 99), - (12, 352, 100, 100), - (12, 353, 101, 101), - (12, 354, 102, 102), - (12, 355, 103, 103), - (12, 356, 104, 104), - (12, 357, 105, 105), - (12, 358, 106, 106), - (12, 359, 107, 107), - (12, 360, 108, 108), - (12, 361, 109, 109), - (12, 362, 110, 110), - (12, 363, 111, 111), - (12, 364, 112, 112), - (12, 365, 113, 113), - (12, 366, 114, 114), - (12, 367, 115, 115), - (12, 368, 116, 116), - (12, 369, 117, 117), - (12, 370, 118, 118), - (12, 372, 120, 120), - (12, 376, 124, 124), - (12, 377, 125, 125), - (12, 378, 126, 126), - (12, 379, 127, 127), - (12, 380, 128, 128), - (12, 381, 129, 129), - (12, 382, 130, 130), - (12, 383, 131, 131), - (12, 384, 132, 132), - (12, 385, 133, 133), - (12, 386, 134, 134), - (12, 387, 135, 135), - (12, 388, 136, 136), - (12, 389, 137, 137), - (12, 391, 139, 139), - (12, 393, 141, 141), - (12, 394, 142, 142), - (12, 395, 143, 143), - (12, 396, 144, 144), - (12, 397, 145, 145), - (12, 398, 146, 146), - (12, 399, 147, 147), - (12, 401, 149, 149), - (12, 402, 150, 150), - (12, 404, 152, 152), - (12, 405, 153, 153), - (12, 406, 154, 154), - (12, 407, 155, 155), - (12, 409, 157, 157), - (12, 410, 158, 158), - (12, 412, 160, 160), - (12, 414, 162, 162), - (12, 415, 163, 163), - (12, 416, 164, 164), - (12, 417, 165, 165), - (12, 418, 166, 166), - (12, 419, 167, 167), - (12, 420, 168, 168), - (12, 422, 170, 170), - (12, 423, 171, 171), - (12, 424, 172, 172), - (12, 425, 173, 173), - (12, 426, 174, 174), - (12, 427, 175, 175), - (12, 428, 176, 176), - (12, 429, 177, 177), - (12, 430, 178, 178), - (12, 431, 179, 179), - (12, 433, 181, 181), - (12, 434, 182, 182), - (12, 435, 183, 183), - (12, 436, 184, 184), - (12, 437, 185, 185), - (12, 438, 186, 186), - (12, 439, 187, 187), - (12, 440, 188, 188), - (12, 441, 189, 189), - (12, 442, 190, 190), - (12, 443, 191, 191), - (12, 444, 192, 192), - (12, 445, 193, 193), - (12, 446, 194, 194), - (12, 447, 195, 195), - (12, 448, 196, 196), - (12, 449, 197, 197), - (12, 450, 198, 198), - (12, 451, 199, 199), - (12, 452, 200, 200), - (12, 453, 201, 201), - (12, 454, 202, 202), - (12, 455, 203, 203), - (12, 456, 204, 204), - (12, 457, 205, 205), - (12, 458, 206, 206), - (12, 459, 207, 207), - (12, 460, 208, 208), - (12, 461, 209, 209), - (12, 462, 210, 210), - (12, 463, 211, 211), - (12, 464, 212, 212), - (12, 465, 213, 213), - (12, 467, 215, 215), - (12, 468, 216, 216), - (12, 469, 217, 217), - (12, 470, 218, 218), - (12, 471, 219, 219), - (12, 472, 220, 220), - (12, 473, 221, 221), - (12, 474, 222, 222), - (12, 475, 223, 223), - (12, 476, 224, 224), - (12, 477, 225, 225), - (12, 478, 226, 226), - (12, 479, 227, 227), - (12, 480, 228, 228), - (12, 481, 229, 229), - (12, 482, 230, 230), - (12, 483, 231, 231), - (12, 484, 232, 232), - (12, 485, 233, 233), - (12, 486, 234, 234), - (12, 487, 235, 235), - (12, 488, 236, 236), - (12, 489, 237, 237), - (12, 490, 238, 238), - (12, 491, 239, 239), - (12, 492, 240, 240), - (12, 493, 241, 241), - (12, 494, 242, 242), - (12, 496, 244, 244), - (12, 497, 245, 245), - (12, 498, 246, 246), - (12, 499, 247, 247), -]; - -const GCD_RIGHT_SHIFT_REMAINDER_KEYS: &[u32] = &[ - 510, 766, 1022, 1278, 1534, 1790, 2046, 2302, 2558, 2814, 3070, 3325, - 3580, 3835, 4090, 4345, 4600, 4855, 5110, 5365, 5620, 5875, 6130, 6385, - 6640, 6895, 7150, 7405, 7660, 7915, 8170, 8425, 8680, 8935, 9190, 9445, - 9700, 9955, 10210, 10465, 10720, 10975, 11230, 11485, 11740, 11995, 12250, 12505, - 12760, 13015, 13270, 13525, 13780, 14035, 14290, 14545, 14800, 15055, 15310, 15565, - 15820, 16075, 16330, 16585, 16840, 17095, 17350, 17605, 17860, 18115, 18370, 18625, - 18880, 19135, 19390, 19645, 19900, 20155, 20410, 20665, 20920, 21175, 21430, 21685, - 21940, 22195, 22450, 22705, 22960, 23215, 23470, 23725, 23980, 24235, 24491, 24746, - 25000, 25255, 25510, 25765, 26020, 26276, 26530, 26786, 27041, 27296, 27550, 27806, - 28061, 28315, 28571, 28826, 29081, 29336, 29591, 29846, 30101, 30355, 30610, 30865, - 31120, 31375, 31631, 31886, 32141, 32395, 32651, 32906, 33161, 33416, 33671, 33926, - 34181, 34436, 34691, 34945, 35200, 35455, 35710, 35965, 36220, 36476, 36731, 36986, - 37240, 37496, 37750, 38005, 38260, 38515, 38770, 39025, 39280, 39535, 39790, 40045, - 40300, 40555, 40810, 41065, 41320, 41575, 41830, 42085, 42340, 42595, 42850, 43105, - 43360, 43615, 43870, 44125, 44380, 44635, 44890, 45145, 45400, 45655, 45910, 46165, - 46420, 46675, 46930, 47185, 47440, 47695, 47950, 48205, 48460, 48715, 48970, 49225, - 49480, 49735, 49990, 50245, 50500, 50755, 51010, 51265, 51520, 51775, 52030, 52285, - 52540, 52795, 53050, 53305, 53560, 53815, 54070, 54325, 54580, 54835, 55090, 55345, - 55600, 55855, 56110, 56365, 56620, 56875, 57130, 57385, 57640, 57895, 58150, 58405, - 58660, 58915, 59170, 59425, 59680, 59935, 60190, 60445, 60700, 60955, 61208, 61463, - 61718, 61973, 62228, 62483, 62739, 62994, 63250, 63505, 63760, 66814, 67070, 67326, - 67582, 67838, 68094, 68350, 68606, 68862, 69118, 69374, 69629, 69884, 70139, 70394, - 70649, 70904, 71159, 71414, 71669, 71924, 72179, 72434, 72689, 72944, 73199, 73454, - 73709, 73964, 74219, 74474, 74729, 74984, 75239, 75494, 75749, 76004, 76259, 76514, - 76769, 77024, 77279, 77534, 77789, 78044, 78299, 78554, 78809, 79064, 79319, 79574, - 79829, 80084, 80339, 80594, 80849, 81104, 81359, 81614, 81869, 82124, 82379, 82634, - 82889, 83144, 83399, 83654, 83909, 84164, 84419, 84674, 84929, 85184, 85439, 85694, - 85949, 86204, 86459, 86714, 86969, 87224, 87479, 87734, 87989, 88244, 88499, 88754, - 89009, 89264, 89519, 89774, 90029, 90284, 90539, 90795, 91050, 91304, 91559, 91814, - 92069, 92324, 92580, 92834, 93090, 93345, 93600, 93854, 94110, 94365, 94619, 94875, - 95130, 95385, 95640, 95895, 96150, 96405, 96659, 96914, 97169, 97424, 97679, 97935, - 98190, 98445, 98699, 98955, 99210, 99465, 99720, 99975, 100485, 100740, 100995, 101249, - 101504, 101759, 102014, 102269, 102524, 102780, 103035, 103290, 103544, 104054, 104309, 104564, - 104819, 105074, 105329, 105584, 105839, 106094, 106349, 106604, 106859, 107114, 107369, 107624, - 107879, 108134, 108389, 108644, 108899, 109154, 109409, 109664, 109919, 110174, 110429, 110684, - 110939, 111194, 111449, 111704, 111959, 112214, 112469, 112724, 112979, 113234, 113489, 113744, - 113999, 114254, 114509, 114764, 115019, 115274, 115529, 115784, 116039, 116294, 116549, 116804, - 117059, 117314, 117569, 117824, 118079, 118334, 118589, 118844, 119099, 119354, 119609, 119864, - 120119, 120374, 120629, 120884, 121139, 121394, 121649, 121904, 122159, 122414, 122669, 122924, - 123179, 123434, 123689, 123944, 124199, 124454, 124709, 124964, 125219, 125474, 125729, 125984, - 126239, 126494, 126749, 127004, 127259, 127512, 127767, 128022, 128277, 128532, 128787, 129043, - 129298, 129554, 129809, 130064, 130319, -]; - -const GCD_LEFT_SHIFT_REMAINDER_KEYS: &[u32] = &[ - 3603, 3860, 4117, 4374, 4631, 4888, 7460, 7717, 9516, 9773, 12086, 12600, - 13114, 15427, 17740, 25707, 28792, 29306, 29820, 30847, 31361, 31619, 32903, 34189, - 36245, 37273, 41642, 47038, 53463, 62715, 69651, 69907, 70164, 70421, 70678, 70935, - 71192, 72222, 72736, 72993, 74535, 74792, 75820, 76077, 80446, 87385, 89441, 95096, - 95610, 95867, 96124, 99979, 100493, 102549, 103320, 104605, 105376, 105890, 107946, 110772, - 119510, 126963, 128248, -]; - -fn gcd_shift_has_structurally_dead_gate(tag: u8, call_index: usize, bit: usize) -> bool { - if super::drops_off_family("GCDSHIFT") { - return false; - } - - if std::env::var_os("TLM_GCD_SKIP_EXACT_SHIFT_REMAINDER").is_some() { - let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); - if (tag == 11 && GCD_RIGHT_SHIFT_REMAINDER_KEYS.binary_search(&key).is_ok()) - || (tag == 12 && GCD_LEFT_SHIFT_REMAINDER_KEYS.binary_search(&key).is_ok()) - { - return true; - } - } - std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_SHIFTS").is_some() - && GCD_SHIFT_DEAD_RANGES.iter().any(|&(range_tag, call, lo, hi)| { - range_tag == tag && call == call_index && (lo..=hi).contains(&bit) - }) -} - -/// One Fredkin at the top of every controlled-shift ladder is structurally dead. -/// -/// The ladder realises a `w`-wire cyclic rotation as `w-1` Fredkins; the last one to be -/// emitted exchanges the bit rotated out of the register with the bit sitting at the far -/// end. Conditioned on the control being 1, both of those bits are known zero: -/// * `v[0] == 0`, because the control is `!v[0]` - we only ever halve an even `v`; and -/// * `v[w-1] == 0`, because the *unconditional* first halving of the same step already -/// rotated that (also zero) `v[0]` into the top position. -/// Exchanging two zeros is the identity, so the Fredkin is exactly removable: no census, -/// no magnitude assumption, no added failure probability. -/// -/// The sole exception is the step-0 `t1` shift, which *is* the first halving: nothing has -/// zeroed the top bit yet and `v[w-1]` is a live bit of the raw 256-bit input. That call is -/// the first right-shift of a forward walk and the last left-shift of a reverse walk. -/// `TLM_GCD_SKIP_TOP_ZERO_SHIFT_EDGE=0` puts the redundant gates back for A/B measurement. -fn skip_top_zero_controlled_shift_edge(tag: u8, call_index: usize) -> bool { - if std::env::var("TLM_GCD_SKIP_TOP_ZERO_SHIFT_EDGE").ok().as_deref() == Some("0") { - return false; - } - const CALLS_PER_WALK: usize = ITERS + 1; - let rel = call_index % CALLS_PER_WALK; - let step0_t1 = if tag == 11 { rel == 0 } else { rel == CALLS_PER_WALK - 1 }; - !step0_t1 -} - -/// Diagnostic: of the 1176 shift Fredkins suppressed by the two census tables -/// (`GCD_*_SHIFT_REMAINDER_KEYS` + `GCD_SHIFT_DEAD_RANGES`), 964 coincide with the -/// provably-dead top-zero edge above. The other 212 rest only on "never observed to fire" -/// and cluster at walk iterations 249..257, i.e. exactly where the walk is *assumed* to -/// have converged (v == 0). They are therefore candidate contributors to the intrinsic -/// mismatch rate. `TLM_GCD_SHIFT_PROVEN_ONLY=1` re-emits just those 212 for A/B. -fn gcd_shift_census_enabled() -> bool { - std::env::var("TLM_GCD_SHIFT_PROVEN_ONLY").ok().as_deref() != Some("1") -} - -fn controlled_right_shift(circ: &mut B, ctrl: &QubitId, v: &[QubitId]) { - let call_index = next_right_shift_call_index(); - for i in 0..v.len().saturating_sub(1) { - let old_context = crate::point_add::set_op_trace_context( - 0x0b00_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - let top_zero_edge = - i + 2 == v.len() && skip_top_zero_controlled_shift_edge(11, call_index); - if !top_zero_edge - && !(gcd_shift_census_enabled() - && gcd_shift_has_structurally_dead_gate(11, call_index, i)) - { - circ.cswap(*ctrl, v[i], v[i + 1]); - } - crate::point_add::restore_op_trace_context(old_context); - } -} - -fn controlled_left_shift(circ: &mut B, ctrl: &QubitId, v: &[QubitId]) { - let call_index = next_left_shift_call_index(); - for i in (1..v.len()).rev() { - let old_context = crate::point_add::set_op_trace_context( - 0x0c00_0000 | (((call_index as u32) & 0xffff) << 8) | ((i - 1) as u32 & 0xff), - ); - let top_zero_edge = - i + 1 == v.len() && skip_top_zero_controlled_shift_edge(12, call_index); - if !top_zero_edge - && !(gcd_shift_census_enabled() - && gcd_shift_has_structurally_dead_gate(12, call_index, i - 1)) - { - circ.cswap(*ctrl, v[i], v[i - 1]); - } - crate::point_add::restore_op_trace_context(old_context); - } -} - -fn right_shift(circ: &mut B, v: &[QubitId]) { - for i in 0..v.len().saturating_sub(1) { - circ.swap(v[i], v[i + 1]); - } -} - -fn left_shift(circ: &mut B, v: &[QubitId]) { - for i in (1..v.len()).rev() { - circ.swap(v[i], v[i - 1]); - } -} - -fn controlled_mod_double(circ: &mut B, ctrl: &QubitId, a: &[QubitId]) { - let n = a.len(); - assert_eq!(n, 256, "controlled_mod_double expects 256-bit a"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let ovf = circ.alloc_qubit(); - - let w: Vec<&QubitId> = a.iter().chain(std::iter::once(&ovf)).collect(); - for i in (0..n).rev() { - circ.cswap(*ctrl, *w[i], *w[i + 1]); - } - - arith::add_f_window_pub(circ, &ovf, a, arith::LSBS, &f_bytes, None); - - clear_and(circ, &ovf, ctrl, &a[0]); - circ.zero_and_free(ovf); -} - -fn controlled_mod_double_reverse(circ: &mut B, ctrl: &QubitId, a: &[QubitId]) { - let n = a.len(); - assert_eq!(n, 256, "controlled_mod_double_reverse expects 256-bit a"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let ovf = circ.alloc_qubit(); - - circ.ccx(*ctrl, a[0], ovf); - - for q in &a[..arith::LSBS] { - circ.x(*q); - } - arith::add_f_window_pub(circ, &ovf, a, arith::LSBS, &f_bytes, None); - for q in &a[..arith::LSBS] { - circ.x(*q); - } - - let w: Vec<&QubitId> = a.iter().chain(std::iter::once(&ovf)).collect(); - for i in 0..n { - circ.cswap(*ctrl, *w[i], *w[i + 1]); - } - circ.zero_and_free(ovf); -} - -#[must_use] -pub fn forward_gcd_jump(circ: &mut B, v: &mut Vec, apply_inv: Option<(&[QubitId], &[QubitId])>) -> Vec { - let n = 256usize; - assert_eq!(JUMP, 2, "ludicrous apply/codec are jump=2 specific"); - assert!(v.len() >= n, "v must be at least n=256 bits"); - let iters = ITERS; - let sym_bits = 3; - - let mut u: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); - let q_bytes = q_secp256k1_le(); - for (i, qb) in u.iter().enumerate() { - if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { - circ.x(*qb); - } - } - - let subtracted = circ.alloc_qubit(); - let mut swap_flag: Option = None; - let s2 = circ.alloc_qubit(); - let t1 = circ.alloc_qubit(); - - let n3 = n3_for_iters(iters); - let mut window_plan: Vec = Vec::new(); - for (codec, count) in super::codec::jump_dialog_regions(n3, iters) { - for _ in 0..count { - window_plan.push(codec); - } - } - let mut tape: Vec = Vec::with_capacity(super::codec::dialog_tape_qubits(n3, iters)); - let mut win_idx = 0usize; - let mut pending: Vec = Vec::new(); - let mut tail4_prefix_encoded = false; - for i in 0..iters { - let trace_region_start = circ.phase_active_regions.len(); - // DIAGNOSTIC (TRACE_OP_SITES): stamp every op emitted by this divstep with - // its pass and iteration index so a dirty `free` can be attributed to a - // specific i. Overwritten and restored by the inner cswap tags. - crate::point_add::set_op_trace_context( - 0xa000_0000 | (u32::from(apply_inv.is_none()) << 24) | ((i as u32) & 0xffff), - ); - circ.set_phase(if apply_inv.is_some() { - "tlm_inverse_gcd_forward_shift" - } else { - "tlm_multiply_gcd_forward_shift" - }); - let current_n = (SCHED_J2[i] as usize).max(1); - while u.len() > current_n { - let q = u.pop().expect("u nonempty"); - circ.zero_and_free(q); - } - while v.len() > current_n { - let q = v.pop().expect("v nonempty"); - circ.zero_and_free(q); - } - - let cmp_eff = cmp_window(i, current_n); - - if i == 0 { - circ.cx(v[0], t1); - circ.x(t1); - controlled_right_shift(circ, &t1, &v[..current_n]); - } else { - right_shift(circ, &v[..current_n]); - } - - circ.cx(v[0], s2); - circ.x(s2); - controlled_right_shift(circ, &s2, &v[..current_n]); - - circ.cx(v[0], subtracted); - - circ.set_phase(if apply_inv.is_some() { - "tlm_inverse_gcd_forward_compare" - } else { - "tlm_multiply_gcd_forward_compare" - }); - let swp = if i == 0 { - subtracted - } else { - let sf = *swap_flag.get_or_insert_with(|| circ.alloc_qubit()); - controlled_swap_decision_v_lt_u( - circ, - &subtracted, - &v[..current_n], - &u[..current_n], - cmp_eff, - &sf, - ); - sf - }; - - for j in 1..current_n { - if !gcd_forward_cswap_has_structurally_dead_gate(i, j) { - let old_context = crate::point_add::set_op_trace_context( - 0x1b00_0000 | (((i as u32) & 0xffff) << 8) | (j as u32 & 0xff), - ); - circ.cswap(swp, u[j], v[j]); - crate::point_add::restore_op_trace_context(old_context); - } - } - let parked_u0 = if park_odd_u0_enabled(i, "FWD") { - let q = u[0]; - Some(park_known_one(circ, q)) - } else { - None - }; - - circ.set_phase(if apply_inv.is_some() { - "tlm_inverse_gcd_forward_body" - } else { - "tlm_multiply_gcd_forward_body" - }); - for q in &v[..current_n] { - circ.x(*q); - } - controlled_add_active( - circ, - i, - &subtracted, - &u[..current_n], - &v[..current_n], - GcdBit0Mode::ForwardKnownOneAfterCx, - apply_inv.map_or(&[], |(xr, _)| &xr[..3]), - ); - for q in &v[..current_n] { - circ.x(*q); - } - - circ.set_phase(if apply_inv.is_some() { - "tlm_inverse_gcd_forward_apply" - } else { - "tlm_multiply_gcd_forward_apply" - }); - if i >= 250 && std::env::var_os("TRACE_TLM_TAIL").is_some() { - eprintln!( - "TLM_TAIL direction=forward i={i} active={} tape={} pending={} encoded={tail4_prefix_encoded}", - circ.active_qubits, - tape.len(), - pending.len(), - ); - } - let parked_v0 = if apply_inv.is_some() && park_even_v0_enabled() { - let q = v[0]; - Some(park_known_zero(circ, q)) - } else { - None - }; - if let Some((xr, yr)) = apply_inv { - apply_step_reverse( - circ, - i, - &subtracted, - &swp, - &s2, - &t1, - xr, - yr, - &u[1..4], - ); - } - if let Some(q) = parked_v0 { - v[0] = restore_known_zero(circ, q); - } - if let Some(q) = parked_u0 { - u[0] = restore_known_one(circ, q); - } - - circ.set_phase(if apply_inv.is_some() { - "tlm_inverse_gcd_forward_codec" - } else { - "tlm_multiply_gcd_forward_codec" - }); - let slots: Vec = (0..sym_bits).map(|_| circ.alloc_qubit()).collect(); - circ.swap(subtracted, slots[0]); - if i == 0 { - circ.cx(slots[0], slots[1]); - } else { - circ.swap(swp, slots[1]); - } - circ.swap(s2, slots[2]); - if i == 0 { - debug_assert_eq!(window_plan[win_idx], super::codec::DialogCodec::Step0); - let data = super::codec::compress_step0_with_t1(circ, t1, &slots); - tape.extend(data); - win_idx += 1; - circ.set_phase("tlm_gcd_step_end"); - trace_step_regions( - circ, - if apply_inv.is_some() { - "inverse-forward" - } else { - "multiply-forward" - }, - i, - trace_region_start, - ); - continue; - } - pending.extend(slots); - - let codec = window_plan[win_idx]; - if codec == super::codec::DialogCodec::Tail4Top32 { - if !tail4_prefix_encoded && pending.len() == 3 * sym_bits { - pending = super::codec::DialogCodec::Triple.compress_window(circ, &pending); - tail4_prefix_encoded = true; - } else if tail4_prefix_encoded - && pending.len() == super::codec::DialogCodec::Triple.code_bits() + 2 * sym_bits - { - let last = pending.split_off(super::codec::DialogCodec::Triple.code_bits()); - let mut raw = super::codec::DialogCodec::Triple.decompress_window(circ, &pending); - raw.extend(last); - let data = codec.compress_window(circ, &raw); - tape.extend(data); - pending.clear(); - tail4_prefix_encoded = false; - win_idx += 1; - } - } else if pending.len() == codec.syms() * sym_bits { - let data = codec.compress_window(circ, &pending); - tape.extend(data); - pending.clear(); - win_idx += 1; - } - circ.set_phase("tlm_gcd_step_end"); - trace_step_regions( - circ, - if apply_inv.is_some() { - "inverse-forward" - } else { - "multiply-forward" - }, - i, - trace_region_start, - ); - } - assert_eq!(win_idx, window_plan.len(), "all windows compressed"); - assert!(pending.is_empty(), "no leftover symbols"); - - circ.x(u[0]); - while let Some(q) = v.pop() { - circ.zero_and_free(q); - } - for q in u { - circ.zero_and_free(q); - } - circ.zero_and_free(subtracted); - if let Some(swap_flag) = swap_flag { - circ.zero_and_free(swap_flag); - } - circ.zero_and_free(s2); - assert_eq!(tape.len(), super::codec::dialog_tape_qubits(n3, iters)); - tape -} - -pub fn reverse_gcd_jump(circ: &mut B, v: &mut Vec, tape: &mut Vec, apply_fwd: Option<(&[QubitId], &[QubitId])>) { - let n = 256usize; - let iters = ITERS; - let n3 = n3_for_iters(iters); - assert_eq!( - tape.len(), - super::codec::dialog_tape_qubits(n3, iters), - "tape must be the compressed dialog" - ); - - let mut window_plan: Vec = Vec::new(); - for (codec, count) in super::codec::jump_dialog_regions(n3, iters) { - for _ in 0..count { - window_plan.push(codec); - } - } - let mut win_idx = window_plan.len(); - - let mut pending: Vec = Vec::new(); - let mut pending_tail4 = false; - let mut tail4_prefix_encoded = false; - - let mut u: Vec = vec![circ.alloc_qubit()]; - circ.x(u[0]); - - let subtracted = circ.alloc_qubit(); - let mut swap_flag: Option = Some(circ.alloc_qubit()); - let s2 = circ.alloc_qubit(); - let mut step0_t1: Option = None; - - for i in (0..iters).rev() { - let trace_region_start = circ.phase_active_regions.len(); - crate::point_add::set_op_trace_context( - 0xa200_0000 | (u32::from(apply_fwd.is_none()) << 24) | ((i as u32) & 0xffff), - ); - circ.set_phase(if apply_fwd.is_some() { - "tlm_multiply_gcd_reverse_decode" - } else { - "tlm_inverse_gcd_reverse_decode" - }); - let current_n = (SCHED_J2[i] as usize).max(1); - while u.len() < current_n { - u.push(circ.alloc_qubit()); - } - while v.len() < current_n { - v.push(circ.alloc_qubit()); - } - let cmp_eff = cmp_window(i, current_n); - - if pending.is_empty() { - win_idx -= 1; - let codec = window_plan[win_idx]; - let cb = codec.code_bits(); - let tlen = tape.len(); - let data: Vec = tape.split_off(tlen - cb); - if codec == super::codec::DialogCodec::Step0 { - let (t1, raw) = super::codec::decompress_step0_with_t1(circ, &data); - step0_t1 = Some(t1); - pending = raw; - } else { - pending = codec.decompress_window(circ, &data); - } - pending_tail4 = codec == super::codec::DialogCodec::Tail4Top32; - } else if tail4_prefix_encoded { - let suffix = pending.split_off(super::codec::DialogCodec::Triple.code_bits()); - pending = super::codec::DialogCodec::Triple.decompress_window(circ, &pending); - pending.extend(suffix); - tail4_prefix_encoded = false; - } - - let plen = pending.len(); - let cur: Vec = pending.split_off(plen - 3); - if pending_tail4 && pending.len() == 12 { - let suffix = pending.split_off(9); - pending = super::codec::DialogCodec::Triple.compress_window(circ, &pending); - pending.extend(suffix); - tail4_prefix_encoded = true; - } else if pending_tail4 && pending.is_empty() { - pending_tail4 = false; - } - if i >= 250 && std::env::var_os("TRACE_TLM_TAIL").is_some() { - eprintln!( - "TLM_TAIL direction=reverse i={i} active={} tape={} pending={} encoded={tail4_prefix_encoded}", - circ.active_qubits, - tape.len(), - pending.len(), - ); - } - circ.swap(subtracted, cur[0]); - let swp = if i == 0 { - circ.cx(subtracted, cur[1]); - subtracted - } else { - let sf = *swap_flag - .as_ref() - .expect("swap flag live for non-step0 replay"); - circ.swap(sf, cur[1]); - sf - }; - circ.swap(s2, cur[2]); - - for q in cur { - circ.zero_and_free(q); - } - - circ.set_phase(if apply_fwd.is_some() { - "tlm_multiply_gcd_reverse_apply" - } else { - "tlm_inverse_gcd_reverse_apply" - }); - let parked_u0 = if park_odd_u0_enabled(i, "REV") { - let q = u[0]; - Some(park_known_one(circ, q)) - } else { - None - }; - - let parked_v0 = if apply_fwd.is_some() && park_even_v0_enabled() { - let q = v[0]; - Some(park_known_zero(circ, q)) - } else { - None - }; - if let Some((xr, yr)) = apply_fwd { - let t1 = step0_t1.unwrap_or(subtracted); - apply_step_forward( - circ, - i, - &subtracted, - &swp, - &s2, - &t1, - xr, - yr, - &u[1..4], - ); - } - if let Some(q) = parked_v0 { - v[0] = restore_known_zero(circ, q); - } - - circ.set_phase(if apply_fwd.is_some() { - "tlm_multiply_gcd_reverse_body" - } else { - "tlm_inverse_gcd_reverse_body" - }); - controlled_add_active( - circ, - i, - &subtracted, - &u[..current_n], - &v[..current_n], - GcdBit0Mode::ReverseKnownZeroBeforeCx, - apply_fwd.map_or(&[], |(xr, _)| &xr[..3]), - ); - if let Some(q) = parked_u0 { - u[0] = restore_known_one(circ, q); - } - - for j in 1..current_n { - let old_context = crate::point_add::set_op_trace_context( - 0x1200_0000 | (((i as u32) & 0xffff) << 8) | (j as u32 & 0xff), - ); - if !gcd_reverse_cswap_has_structurally_dead_gate(i, j) { - circ.cswap(swp, u[j], v[j]); - } - crate::point_add::restore_op_trace_context(old_context); - } - - if i != 0 { - super::comparator::swap_decision_uncompute_vented( - circ, - &subtracted, - &v[..current_n], - &u[..current_n], - cmp_eff, - &swp, - ); - } - - circ.cx(v[0], subtracted); - - controlled_left_shift(circ, &s2, &v[..current_n]); - circ.x(s2); - circ.cx(v[0], s2); - - if i == 0 { - let t1 = step0_t1.expect("step0 t1 decompressed"); - controlled_left_shift(circ, &t1, &v[..current_n]); - circ.x(t1); - circ.cx(v[0], t1); - } else { - left_shift(circ, &v[..current_n]); - } - - if i == 0 { - let t1 = step0_t1.take().expect("step0 t1 present"); - circ.zero_and_free(t1); - } - if i == 1 { - let sf = swap_flag.take().expect("swap flag still allocated"); - circ.zero_and_free(sf); - } - circ.set_phase("tlm_gcd_step_end"); - trace_step_regions( - circ, - if apply_fwd.is_some() { - "multiply-reverse" - } else { - "inverse-reverse" - }, - i, - trace_region_start, - ); - } - assert!(tape.is_empty(), "tape not fully drained"); - - let q_bytes = q_secp256k1_le(); - for (i, qb) in u.iter().enumerate().take(n) { - if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { - circ.x(*qb); - } - } - for q in u { - circ.zero_and_free(q); - } - circ.zero_and_free(subtracted); - if let Some(swap_flag) = swap_flag { - circ.zero_and_free(swap_flag); - } - circ.zero_and_free(s2); -} - -fn controlled_swap_decision_v_lt_u( - circ: &mut B, - ctrl: &QubitId, - v: &[QubitId], - u: &[QubitId], - k: usize, - target: &QubitId, -) { - super::comparator::controlled_swap_decision_lt_truncated(circ, ctrl, v, u, k, target); -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum GcdBit0Mode { - ForwardKnownOneAfterCx, - ReverseKnownZeroBeforeCx, -} - -fn controlled_add_active( - circ: &mut B, - i: usize, - ctrl: &QubitId, - x: &[QubitId], - y: &[QubitId], - bit0_mode: GcdBit0Mode, - dirty_vents: &[QubitId], -) { - - let k = maybe_adjust_late_gcd_k(i, super::next_gcd_k()); - let branch = super::next_gcd_branch(); - let loan_y0 = loan_gcd_y0_enabled() && x.len() > 1; - match bit0_mode { - GcdBit0Mode::ForwardKnownOneAfterCx => { - circ.cx(*ctrl, y[0]); - if loan_y0 { - loan_known_one_gcd_y0(circ, y[0]); - } - } - GcdBit0Mode::ReverseKnownZeroBeforeCx => { - - if loan_y0 { - loan_known_zero_gcd_y0(circ, y[0]); - } - } - } - if x.len() > 1 { - let yr: Vec<&QubitId> = y[1..].iter().collect(); - let xr: Vec<&QubitId> = x[1..].iter().collect(); - super::gidney::with_dirty_vent_pool(dirty_vents, || { - super::gidney::controlled_hybrid_add_capped_branch( - circ, - ctrl, - &yr, - &xr, - k, - super::PAD, - branch, - ); - }); - } - if loan_y0 { - match bit0_mode { - GcdBit0Mode::ForwardKnownOneAfterCx => reclaim_known_one_gcd_y0(circ, y[0]), - GcdBit0Mode::ReverseKnownZeroBeforeCx => reclaim_known_zero_gcd_y0(circ, y[0]), - } - } - if bit0_mode == GcdBit0Mode::ReverseKnownZeroBeforeCx { - circ.cx(*ctrl, y[0]); - } -} - -fn apply_step_forward( - circ: &mut B, - i: usize, - sub: &QubitId, - swp: &QubitId, - s2: &QubitId, - t1: &QubitId, - x_reg: &[QubitId], - y_reg: &[QubitId], - dirty_vents: &[QubitId], -) { - let n = 256usize; - let s2_known_zero = i != 0 && apply_fwd_s2_zero(i); - - circ.set_phase("tlm_apply_forward_mod_add"); - let k = super::next_cout_k(); - let ffg = super::next_ffg(); - if !apply_add_skip(i, true) { - super::gidney::with_dirty_vent_pool(dirty_vents, || { - arith::controlled_mod_add_k( - circ, - sub, - &x_reg[..n], - &y_reg[..n], - Some(k), - Some(ffg), - ); - }); - } - - circ.set_phase("tlm_apply_forward_swap"); - if !apply_fwd_cswap_skip(i) { - for j in 0..n { - circ.cswap(*swp, x_reg[j], y_reg[j]); - } - } - - circ.set_phase("tlm_apply_forward_fold"); - if i == 0 { - controlled_mod_double(circ, t1, y_reg); - controlled_mod_double(circ, s2, y_reg); - } else if s2_known_zero { - super::fused::fused_double_only(circ, y_reg); - } else { - super::fused::fused_double_cdouble(circ, s2, y_reg); - } -} - -fn apply_step_reverse( - circ: &mut B, - i: usize, - sub: &QubitId, - swp: &QubitId, - s2: &QubitId, - t1: &QubitId, - x_reg: &[QubitId], - y_reg: &[QubitId], - dirty_vents: &[QubitId], -) { - let n = 256usize; - let s2_known_zero = i != 0 && apply_inv_s2_zero(i); - - circ.set_phase("tlm_apply_inverse_fold"); - if i == 0 { - controlled_mod_double_reverse(circ, s2, y_reg); - controlled_mod_double_reverse(circ, t1, y_reg); - } else if s2_known_zero { - super::fused::fused_double_only_reverse(circ, y_reg); - } else { - super::fused::fused_double_cdouble_reverse(circ, s2, y_reg); - } - - circ.set_phase("tlm_apply_inverse_swap"); - if !apply_inv_cswap_skip(i) { - for j in 0..n { - circ.cswap(*swp, x_reg[j], y_reg[j]); - } - } - - circ.set_phase("tlm_apply_inverse_mod_sub"); - let k = super::next_cout_k(); - if !apply_add_skip(i, false) { - super::gidney::with_dirty_vent_pool(dirty_vents, || { - controlled_mod_sub_vented(circ, sub, &x_reg[..n], &y_reg[..n], Some(k)); - }); - } -} - -fn controlled_mod_sub_vented(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], sched_k: Option) { - let n = x.len(); - assert_eq!(y.len(), n, "x,y equal width"); - let f_bytes = F_SECP256K1.to_le_bytes(); - let anc = circ.alloc_qubit(); - - circ.set_phase("tlm_apply_inverse_mod_sub_register"); - for q in y { - circ.x(*q); - } - controlled_add_active_cout(circ, ctrl, x, y, &anc, sched_k); - for q in y { - circ.x(*q); - } - - circ.set_phase("tlm_apply_inverse_mod_sub_fold"); - for q in &y[..arith::LSBS] { - circ.x(*q); - } - let ffg = super::next_ffg(); - arith::add_f_window_pub(circ, &anc, y, arith::LSBS, &f_bytes, Some(ffg)); - for q in &y[..arith::LSBS] { - circ.x(*q); - } - - circ.set_phase("tlm_apply_inverse_mod_sub_clean"); - let k = arith::msbs().min(n); - let lo = n - k; - let ctrl = *ctrl; - let bit = circ.alloc_bit(); - circ.hmr(anc, bit); - circ.zero_and_free(anc); - circ.push_condition(bit); - let yt: Vec = y[lo..n].to_vec(); - let xt: Vec = x[lo..n].to_vec(); - for q in &xt { - circ.x(*q); - } - - let flag = circ.alloc_qubit(); - super::comparator::compare_geq_chunked_middle(circ, &yt, &xt, &flag, |c, fl| { - c.cz(ctrl, *fl); - }, k); - circ.zero_and_free(flag); - for q in &xt { - circ.x(*q); - } - circ.pop_condition(); -} - -fn controlled_add_active_cout(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], cout: &QubitId, sched_k: Option) { - match sched_k { - Some(k) => { - - let yr: Vec<&QubitId> = y.iter().collect(); - let xr: Vec<&QubitId> = x.iter().collect(); - super::gidney::controlled_hybrid_add_cout_refs(circ, ctrl, &yr, &xr, cout, k); - } - None => arith::controlled_add_vented_chunked_cout(circ, ctrl, x, y, arith::APPLY_CHUNK, Some(cout)), - } -} - -#[must_use] -pub fn mod_mul_inverse_in_place( - circ: &mut B, - mut xv: Vec, - y: &[QubitId], - dir: Direction, -) -> Vec { - let n = 256usize; - assert_eq!(xv.len(), n, "xv must be 256 bits"); - assert_eq!(y.len(), n, "y must be 256 bits"); - - match dir { - Direction::Inverse => { - - let tmp: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); - for j in 0..n { - circ.swap(y[j], tmp[j]); - } - let mut tape = forward_gcd_jump(circ, &mut xv, Some((y, &tmp))); - for q in tmp { - circ.zero_and_free(q); - } - reverse_gcd_jump(circ, &mut xv, &mut tape, None); - xv - } - Direction::Forward => { - - let mut tape = forward_gcd_jump(circ, &mut xv, None); - let tmp: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); - for j in 0..n { - circ.swap(y[j], tmp[j]); - } - reverse_gcd_jump(circ, &mut xv, &mut tape, Some((&tmp, y))); - clear_zeroed_drift(circ, &tmp[..n]); - for q in tmp { - circ.zero_and_free(q); - } - xv - } - } -} - -fn clear_zeroed_drift(circ: &mut B, reg: &[QubitId]) { - let q_bytes = q_secp256k1_le(); - for (i, qb) in reg.iter().enumerate() { - if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { - circ.x(*qb); - } - } -} + +use super::arith::{self, F_SECP256K1}; +use super::schedule::{GAP_J2, ITERS, JUMP, SCHED_J2}; +use super::{B, BExt}; +use crate::circuit::{QubitId}; +use std::cell::Cell; + +thread_local! { + static RIGHT_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; + static LEFT_SHIFT_CALL_INDEX: Cell = const { Cell::new(0) }; +} + +pub(super) fn reset_gcd_trace_call_index() { + RIGHT_SHIFT_CALL_INDEX.with(|index| index.set(0)); + LEFT_SHIFT_CALL_INDEX.with(|index| index.set(0)); +} + +fn next_right_shift_call_index() -> usize { + RIGHT_SHIFT_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_left_shift_call_index() -> usize { + LEFT_SHIFT_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Direction { + + Inverse, + + Forward, +} + +#[must_use] +pub fn q_secp256k1_le() -> [u8; 32] { + let mut b = [0xFFu8; 32]; + b[0] = 0x2F; + b[1] = 0xFC; + b[4] = 0xFE; + b +} + +#[must_use] +pub fn n3_for_iters(iters: usize) -> usize { + iters / 3 +} + +fn env_i32(name: &str, default: i32) -> i32 { + std::env::var(name) + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(default) +} + +fn env_usize(name: &str, default: usize) -> usize { + std::env::var(name) + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(default) +} + +fn adjust_gcd_k(prefix: &str, i: usize, k: usize) -> usize { + if k == usize::MAX { + return k; + } + let adjust = env_i32(&format!("{prefix}_ADJUST"), 0); + let after = env_usize(&format!("{prefix}_ADJUST_AFTER"), 0); + let before = env_usize(&format!("{prefix}_ADJUST_BEFORE"), usize::MAX); + if i >= after && i < before && adjust != 0 { + (k as i32).saturating_add(adjust).max(0) as usize + } else { + k + } +} + +fn maybe_adjust_late_gcd_k(i: usize, k: usize) -> usize { + let k = adjust_gcd_k("TLM_GCD_K", i, k); + adjust_gcd_k("TLM_GCD_K_EXTRA", i, k) +} + +fn trace_step_regions(circ: &mut B, direction: &str, i: usize, region_start: usize) { + if std::env::var("TRACE_TLM_GCD_STEPS").is_err() { + return; + } + let threshold = std::env::var("TRACE_TLM_GCD_MIN_Q") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(1150); + let step_max = circ.phase_active_regions[region_start..] + .iter() + .map(|(_, _, active)| *active) + .max() + .unwrap_or(circ.active_qubits); + if step_max >= threshold { + eprintln!( + "TLM_GCD_STEP direction={direction} i={i} active_max={step_max} global_peak={} ops={}", + circ.peak_qubits, + circ.current_ops_len(), + ); + for (_, phase, active) in &circ.phase_active_regions[region_start..] { + if *active >= threshold { + eprintln!( + "TLM_GCD_STAGE direction={direction} i={i} active_max={active} phase={phase}", + ); + } + } + } +} + +fn clear_and(circ: &mut B, t: &QubitId, a: &QubitId, b: &QubitId) { + let bit = circ.alloc_bit(); + circ.hmr(*t, bit); + circ.cz_if_bit(*a, *b, bit); +} + +fn park_odd_u0_enabled(i: usize, side: &str) -> bool { + let all = std::env::var("TLM_PARK_ODD_U0").ok().as_deref() == Some("1"); + let side_on = std::env::var(format!("TLM_PARK_ODD_U0_{side}")) + .ok() + .as_deref() + == Some("1"); + if !all && !side_on { + return false; + } + let limit = std::env::var("TLM_PARK_ODD_U0_LIMIT") + .ok() + .and_then(|v| v.parse::().ok()) + .unwrap_or(usize::MAX); + i < limit +} + +fn loan_odd_u0_enabled() -> bool { + std::env::var("TLM_LOAN_ODD_U0").ok().as_deref() == Some("1") +} + +fn park_even_v0_enabled() -> bool { + std::env::var("TLM_PARK_EVEN_V0").ok().as_deref() == Some("1") +} + +fn loan_even_v0_enabled() -> bool { + std::env::var("TLM_LOAN_EVEN_V0").ok().as_deref() == Some("1") +} + +fn loan_gcd_y0_enabled() -> bool { + std::env::var("TLM_LOAN_GCD_Y0").ok().as_deref() == Some("1") +} + +fn apply_fwd_cswap_skip(i: usize) -> bool { + let legacy_first_skip = + std::env::var("TLM_APPLY_FWD_FIRST_CSWAP_SKIP").ok().as_deref() == Some("1") + && i + 1 == ITERS; + let last_n = std::env::var("TLM_APPLY_FWD_CSWAP_SKIP_LAST") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0); + legacy_first_skip || (last_n != 0 && i + last_n >= ITERS) +} + +fn apply_inv_cswap_skip(i: usize) -> bool { + let last_n = std::env::var("TLM_APPLY_INV_CSWAP_SKIP_LAST") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0); + last_n != 0 && i + last_n >= ITERS +} + +fn apply_fwd_s2_zero(i: usize) -> bool { + let last_n = std::env::var("TLM_APPLY_FWD_S2_ZERO_LAST") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0); + last_n != 0 && i + last_n >= ITERS +} + +fn apply_inv_s2_zero(i: usize) -> bool { + let last_n = std::env::var("TLM_APPLY_INV_S2_ZERO_LAST") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0); + last_n != 0 && i + last_n >= ITERS +} + +fn apply_add_skip(i: usize, fwd: bool) -> bool { + if let Some(k) = std::env::var("TLM_APPLY_ADD_SKIP_LASTK") + .ok() + .and_then(|value| value.parse::().ok()) + { + if k != 0 && i + k >= ITERS { + return true; + } + } + let var = if fwd { + "TLM_APPLY_ADD_SKIP_FWD" + } else { + "TLM_APPLY_ADD_SKIP_INV" + }; + let k = std::env::var(var) + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0); + k != 0 && i + k >= ITERS +} + +fn park_known_one(circ: &mut B, q: QubitId) -> QubitId { + circ.x(q); + if loan_odd_u0_enabled() { + circ.loan_zero_qubit(q); + } else { + circ.zero_and_free(q); + } + q +} + +fn restore_known_one(circ: &mut B, parked: QubitId) -> QubitId { + let q = if loan_odd_u0_enabled() { + circ.reclaim_zero_qubit(parked); + parked + } else { + circ.alloc_qubit() + }; + circ.x(q); + q +} + +fn park_known_zero(circ: &mut B, q: QubitId) -> QubitId { + if loan_even_v0_enabled() { + circ.loan_zero_qubit(q); + } else { + circ.zero_and_free(q); + } + q +} + +fn restore_known_zero(circ: &mut B, parked: QubitId) -> QubitId { + if loan_even_v0_enabled() { + circ.reclaim_zero_qubit(parked); + parked + } else { + circ.alloc_qubit() + } +} + +fn loan_known_one_gcd_y0(circ: &mut B, q: QubitId) { + circ.x(q); + circ.loan_zero_qubit(q); +} + +fn reclaim_known_one_gcd_y0(circ: &mut B, q: QubitId) { + circ.reclaim_zero_qubit(q); + circ.x(q); +} + +fn loan_known_zero_gcd_y0(circ: &mut B, q: QubitId) { + circ.loan_zero_qubit(q); +} + +fn reclaim_known_zero_gcd_y0(circ: &mut B, q: QubitId) { + circ.reclaim_zero_qubit(q); +} + +const GCD_REVERSE_CSWAP_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (255, 5, 13), + (256, 3, 11), + (253, 8, 15), + (254, 7, 13), + (252, 10, 15), + (250, 13, 16), + (251, 12, 15), + (249, 13, 16), + (236, 27, 29), + (248, 15, 17), + (234, 29, 31), + (235, 28, 30), + (237, 26, 28), + (244, 18, 20), + (246, 17, 19), + (247, 16, 18), + (101, 164, 165), + (143, 122, 123), + (145, 120, 121), + (219, 45, 46), + (220, 44, 45), + (221, 43, 44), + (224, 40, 41), + (226, 38, 39), + (228, 36, 37), + (229, 35, 36), + (231, 33, 34), + (232, 32, 33), + (233, 31, 32), + (245, 18, 19), + (257, 7, 10), + (95, 170, 171), + (116, 149, 150), + (134, 131, 132), + (218, 46, 47), + (222, 42, 43), + (223, 41, 42), + (225, 39, 40), + (227, 37, 38), + (230, 34, 35), + (240, 22, 23), + (11, 254, 254), + (12, 253, 253), + (19, 246, 246), + (21, 244, 244), + (30, 235, 235), + (31, 234, 234), + (33, 232, 232), + (35, 230, 230), + (36, 229, 229), + (37, 228, 228), + (39, 226, 226), + (40, 225, 225), + (42, 223, 223), + (43, 222, 222), + (46, 219, 219), + (47, 218, 218), + (48, 217, 217), + (49, 216, 216), + (50, 215, 215), + (51, 214, 214), + (53, 212, 212), + (54, 211, 211), + (56, 209, 209), + (63, 202, 202), + (68, 197, 197), + (70, 195, 195), + (75, 190, 190), + (76, 189, 189), + (79, 186, 186), + (80, 185, 185), + (81, 184, 184), + (87, 178, 178), + (94, 172, 172), + (103, 163, 163), + (105, 161, 161), + (107, 159, 159), + (108, 158, 158), + (110, 156, 156), + (112, 154, 154), + (113, 153, 153), + (114, 152, 152), + (115, 151, 151), + (123, 143, 143), + (124, 142, 142), + (126, 140, 140), + (127, 139, 139), + (128, 138, 138), + (129, 137, 137), + (130, 136, 136), + (131, 135, 135), + (132, 134, 134), + (133, 133, 133), + (141, 125, 125), + (142, 124, 124), + (146, 119, 119), + (147, 118, 118), + (148, 117, 117), + (149, 116, 116), + (153, 112, 112), + (157, 108, 108), + (159, 106, 106), + (161, 104, 104), + (162, 103, 103), + (163, 102, 102), + (164, 101, 101), + (167, 98, 98), + (168, 97, 97), + (169, 96, 96), + (170, 95, 95), + (171, 94, 94), + (180, 85, 85), + (182, 83, 83), + (183, 82, 82), + (187, 78, 78), + (188, 77, 77), + (189, 76, 76), + (190, 75, 75), + (192, 73, 73), + (193, 72, 72), + (194, 71, 71), + (195, 70, 70), + (197, 68, 68), + (198, 67, 67), + (199, 66, 66), + (203, 62, 62), + (204, 61, 61), + (205, 60, 60), + (206, 59, 59), + (207, 58, 58), + (208, 57, 57), + (210, 55, 55), + (211, 54, 54), + (212, 53, 53), + (213, 52, 52), + (214, 51, 51), + (215, 50, 50), + (216, 49, 49), + (217, 48, 48), + (238, 25, 25), + (239, 24, 24), + (241, 22, 22), + (242, 21, 21), +]; + +const GCD_FORWARD_CSWAP_REMAINDER_KEYS: &[u32] = &[ + 3325, 4345, 8935, 9955, 17860, 24236, 26021, 26531, 26786, 27551, 28316, 28571, + 29846, 31631, 31886, 32906, 33161, 33416, 33671, 33926, 34181, 34436, 35710, + 36221, 36476, 36985, 37241, 38260, 40810, 41575, 41830, 43360, 44380, 45145, + 46165, 46675, 47185, 47950, 48205, 48715, 49225, 50755, 51010, 51520, 51775, + 52030, 52285, 52540, 53305, 53560, 54070, 54580, 54835, 55090, 55600, 56110, + 56620, 56875, 57130, 57385, 57895, 58149, 58405, 58660, 58915, 59170, 59425, + 59680, 59935, 60190, 60444, 60445, 60700, 62484, 62995, 63250, 63505, 63759, + 63760, 64014, 64015, 64016, 64270, 64271, 64524, 64525, 64526, 64527, 64779, + 64780, 64781, 64782, 64783, 65035, 65036, 65037, 65290, 65291, 65292, 65293, + 65545, 65546, 65547, 65800, 65801, 65802, +]; + +const GCD_REVERSE_CSWAP_REMAINDER_KEYS: &[u32] = &[ + 3580, 3835, 4090, 4345, 4600, 4855, 5365, 5875, 6130, 6640, 6895, 7150, + 7405, 7660, 8425, 8935, 9955, 10720, 11740, 13525, 14290, 15055, 15310, + 15565, 15820, 16075, 16585, 16840, 17095, 17350, 18370, 18625, 18880, + 19135, 19900, 20155, 21175, 21685, 22195, 22705, 22960, 23215, 23470, + 23725, 24745, 25255, 25510, 26786, 31376, 34690, 34945, 35200, 35455, + 38515, 38770, 39025, 39790, 40045, 40555, 41065, 42340, 42595, 44125, + 44635, 44890, 45145, 45400, 45655, 45910, 46420, 47185, 47440, 48970, + 50245, 51265, 53560, +]; + +fn gcd_reverse_cswap_has_structurally_dead_gate(step: usize, bit: usize) -> bool { + if std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS").is_none() { + return false; + } + if std::env::var_os("TLM_GCD_SKIP_REVERSE_DIAGONAL_EDGE").is_some() + && step + bit + >= std::env::var("TLM_GCD_REVERSE_DIAGONAL_MIN") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(265) + && step + >= std::env::var("TLM_GCD_REVERSE_DIAGONAL_STEP_MIN") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0) + && step + <= std::env::var("TLM_GCD_REVERSE_DIAGONAL_STEP_MAX") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(usize::MAX) + { + return true; + } + if std::env::var_os("TLM_GCD_SKIP_EXACT_REVERSE_CSWAPS").is_some() { + let key = (((step as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if GCD_REVERSE_CSWAP_REMAINDER_KEYS.binary_search(&key).is_ok() { + return true; + } + } + GCD_REVERSE_CSWAP_DEAD_RANGES + .iter() + .any(|&(range_step, lo, hi)| range_step == step && (lo..=hi).contains(&bit)) +} + +fn gcd_forward_cswap_has_structurally_dead_gate(step: usize, bit: usize) -> bool { + if std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_CSWAPS").is_none() + || std::env::var_os("TLM_GCD_SKIP_EXACT_FORWARD_CSWAPS").is_none() + { + return false; + } + let key = (((step as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + GCD_FORWARD_CSWAP_REMAINDER_KEYS.binary_search(&key).is_ok() +} + +const GCD_SHIFT_DEAD_RANGES: &[(u8, usize, usize, usize)] = &[ + (12, 0, 1, 9), + (12, 259, 1, 9), + (12, 1, 3, 10), + (12, 2, 5, 12), + (12, 260, 3, 10), + (12, 261, 5, 12), + (12, 262, 7, 12), + (12, 263, 9, 14), + (12, 264, 9, 14), + (12, 3, 7, 12), + (12, 4, 9, 14), + (12, 5, 10, 14), + (11, 254, 11, 14), + (11, 515, 8, 8), + (11, 515, 10, 12), + (11, 516, 7, 10), + (12, 265, 11, 14), + (12, 266, 12, 15), + (12, 6, 11, 14), + (12, 7, 12, 15), + (11, 252, 12, 14), + (11, 253, 12, 14), + (11, 255, 10, 12), + (11, 256, 10, 12), + (11, 257, 8, 10), + (11, 258, 7, 9), + (11, 510, 13, 15), + (11, 512, 12, 14), + (11, 513, 12, 14), + (11, 514, 10, 12), + (12, 20, 25, 27), + (12, 267, 13, 15), + (12, 269, 15, 17), + (12, 270, 16, 18), + (12, 279, 25, 27), + (12, 280, 26, 28), + (12, 287, 33, 35), + (12, 8, 13, 15), + (12, 9, 14, 16), + (11, 250, 14, 15), + (11, 251, 14, 15), + (11, 391, 133, 134), + (11, 405, 119, 120), + (11, 511, 12, 12), + (11, 511, 14, 14), + (11, 517, 8, 9), + (12, 10, 16, 17), + (12, 11, 17, 18), + (12, 12, 17, 18), + (12, 13, 18, 19), + (12, 21, 27, 28), + (12, 22, 28, 29), + (12, 23, 29, 30), + (12, 24, 30, 31), + (12, 25, 31, 32), + (12, 26, 32, 33), + (12, 268, 15, 16), + (12, 27, 33, 34), + (12, 271, 17, 18), + (12, 28, 34, 35), + (12, 281, 28, 29), + (12, 283, 30, 31), + (12, 286, 33, 34), + (12, 288, 35, 36), + (12, 289, 36, 37), + (12, 290, 37, 38), + (12, 293, 40, 41), + (12, 294, 41, 42), + (12, 295, 42, 43), + (12, 31, 37, 38), + (12, 32, 38, 39), + (12, 33, 39, 40), + (12, 34, 40, 41), + (12, 35, 41, 42), + (12, 36, 42, 43), +]; + +const GCD_RIGHT_SHIFT_REMAINDER_KEYS: &[u32] = &[ + 510, 766, 1022, 1278, 1534, 1790, 2046, 2302, 2558, 2814, 3070, 3325, + 3580, 3835, 4090, 4345, 4600, 4855, 5110, 5365, 5620, 5875, 6130, 6385, + 6640, 6895, 7150, 7405, 7660, 7915, 8170, 8425, 8680, 8935, 9190, 9445, + 9700, 9955, 10210, 10465, 10720, 10975, 11230, 11485, 11740, 11995, 12250, 12505, + 12760, 13015, 13270, 13525, 13780, 14035, 14290, 14545, 14800, 15055, 15310, 15565, + 15820, 16075, 16330, 16585, 16840, 17095, 17350, 17605, 17860, 18115, 18370, 18625, + 18880, 19135, 19390, 19645, 19900, 20155, 20410, 20665, 20920, 21175, 21430, 21685, + 21940, 22195, 22450, 22705, 22960, 23215, 23470, 23725, 23980, 24235, 24491, 24746, + 25000, 25255, 25510, 25765, 26020, 26276, 26530, 26786, 27041, 27296, 27550, 27806, + 28061, 28315, 28571, 28826, 29081, 29336, 29591, 29846, 30101, 30355, 30610, 30865, + 31120, 31375, 31631, 31886, 32141, 32395, 32651, 32906, 33161, 33416, 33671, 33926, + 34181, 34436, 34691, 34945, 35200, 35455, 35710, 35965, 36220, 36476, 36731, 36986, + 37240, 37496, 37750, 38005, 38260, 38515, 38770, 39025, 39280, 39535, 39790, 40045, + 40300, 40555, 40810, 41065, 41320, 41575, 41830, 42085, 42340, 42595, 42850, 43105, + 43360, 43615, 43870, 44125, 44380, 44635, 44890, 45145, 45400, 45655, 45910, 46165, + 46420, 46675, 46930, 47185, 47440, 47695, 47950, 48205, 48460, 48715, 48970, 49225, + 49480, 49735, 49990, 50245, 50500, 50755, 51010, 51265, 51520, 51775, 52030, 52285, + 52540, 52795, 53050, 53305, 53560, 53815, 54070, 54325, 54580, 54835, 55090, 55345, + 55600, 55855, 56110, 56365, 56620, 56875, 57130, 57385, 57640, 57895, 58150, 58405, + 58660, 58915, 59170, 59425, 59680, 59935, 60190, 60445, 60700, 60955, 61208, 61463, + 61718, 61973, 62228, 62483, 62739, 62994, 63250, 63505, 63760, 66814, 67070, 67326, + 67582, 67838, 68094, 68350, 68606, 68862, 69118, 69374, 69629, 69884, 70139, 70394, + 70649, 70904, 71159, 71414, 71669, 71924, 72179, 72434, 72689, 72944, 73199, 73454, + 73709, 73964, 74219, 74474, 74729, 74984, 75239, 75494, 75749, 76004, 76259, 76514, + 76769, 77024, 77279, 77534, 77789, 78044, 78299, 78554, 78809, 79064, 79319, 79574, + 79829, 80084, 80339, 80594, 80849, 81104, 81359, 81614, 81869, 82124, 82379, 82634, + 82889, 83144, 83399, 83654, 83909, 84164, 84419, 84674, 84929, 85184, 85439, 85694, + 85949, 86204, 86459, 86714, 86969, 87224, 87479, 87734, 87989, 88244, 88499, 88754, + 89009, 89264, 89519, 89774, 90029, 90284, 90539, 90795, 91050, 91304, 91559, 91814, + 92069, 92324, 92580, 92834, 93090, 93345, 93600, 93854, 94110, 94365, 94619, 94875, + 95130, 95385, 95640, 95895, 96150, 96405, 96659, 96914, 97169, 97424, 97679, 97935, + 98190, 98445, 98699, 98955, 99210, 99465, 99720, 99975, 100485, 100740, 100995, 101249, + 101504, 101759, 102014, 102269, 102524, 102780, 103035, 103290, 103544, 104054, 104309, 104564, + 104819, 105074, 105329, 105584, 105839, 106094, 106349, 106604, 106859, 107114, 107369, 107624, + 107879, 108134, 108389, 108644, 108899, 109154, 109409, 109664, 109919, 110174, 110429, 110684, + 110939, 111194, 111449, 111704, 111959, 112214, 112469, 112724, 112979, 113234, 113489, 113744, + 113999, 114254, 114509, 114764, 115019, 115274, 115529, 115784, 116039, 116294, 116549, 116804, + 117059, 117314, 117569, 117824, 118079, 118334, 118589, 118844, 119099, 119354, 119609, 119864, + 120119, 120374, 120629, 120884, 121139, 121394, 121649, 121904, 122159, 122414, 122669, 122924, + 123179, 123434, 123689, 123944, 124199, 124454, 124709, 124964, 125219, 125474, 125729, 125984, + 126239, 126494, 126749, 127004, 127259, 127512, 127767, 128022, 128277, 128532, 128787, 129043, + 129298, 129554, 129809, 130064, 130319, +]; + +const GCD_LEFT_SHIFT_REMAINDER_KEYS: &[u32] = &[ + 3603, 3860, 4117, 4374, 4631, 4888, 7460, 7717, 9516, 9773, 12086, 12600, + 13114, 15427, 17740, 25707, 28792, 29306, 29820, 30847, 31361, 31619, 32903, 34189, + 36245, 37273, 41642, 47038, 53463, 62715, 69651, 69907, 70164, 70421, 70678, 70935, + 71192, 72222, 72736, 72993, 74535, 74792, 75820, 76077, 80446, 87385, 89441, 95096, + 95610, 95867, 96124, 99979, 100493, 102549, 103320, 104605, 105376, 105890, 107946, 110772, + 119510, 126963, 128248, +]; + +fn gcd_shift_has_structurally_dead_gate(tag: u8, call_index: usize, bit: usize) -> bool { + if std::env::var_os("TLM_GCD_SKIP_EXACT_SHIFT_REMAINDER").is_some() { + let key = (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff); + if (tag == 11 && GCD_RIGHT_SHIFT_REMAINDER_KEYS.binary_search(&key).is_ok()) + || (tag == 12 && GCD_LEFT_SHIFT_REMAINDER_KEYS.binary_search(&key).is_ok()) + { + return true; + } + } + std::env::var_os("TLM_GCD_SKIP_STRUCTURAL_DEAD_SHIFTS").is_some() + && GCD_SHIFT_DEAD_RANGES.iter().any(|&(range_tag, call, lo, hi)| { + range_tag == tag && call == call_index && (lo..=hi).contains(&bit) + }) +} + +fn skip_top_zero_controlled_shift_edge() -> bool { + std::env::var_os("TLM_GCD_SKIP_TOP_ZERO_SHIFT_EDGE").is_some() +} + +fn controlled_right_shift(circ: &mut B, ctrl: &QubitId, v: &[QubitId]) { + let call_index = next_right_shift_call_index(); + for i in 0..v.len().saturating_sub(1) { + let old_context = crate::point_add::set_op_trace_context( + 0x0b00_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + let top_zero_edge = skip_top_zero_controlled_shift_edge() && i + 2 == v.len(); + if !top_zero_edge && !gcd_shift_has_structurally_dead_gate(11, call_index, i) { + circ.cswap(*ctrl, v[i], v[i + 1]); + } + crate::point_add::restore_op_trace_context(old_context); + } +} + +fn controlled_left_shift(circ: &mut B, ctrl: &QubitId, v: &[QubitId]) { + let call_index = next_left_shift_call_index(); + for i in (1..v.len()).rev() { + let old_context = crate::point_add::set_op_trace_context( + 0x0c00_0000 | (((call_index as u32) & 0xffff) << 8) | ((i - 1) as u32 & 0xff), + ); + let top_zero_edge = skip_top_zero_controlled_shift_edge() && i + 1 == v.len(); + if !top_zero_edge && !gcd_shift_has_structurally_dead_gate(12, call_index, i - 1) { + circ.cswap(*ctrl, v[i], v[i - 1]); + } + crate::point_add::restore_op_trace_context(old_context); + } +} + +fn right_shift(circ: &mut B, v: &[QubitId]) { + for i in 0..v.len().saturating_sub(1) { + circ.swap(v[i], v[i + 1]); + } +} + +fn left_shift(circ: &mut B, v: &[QubitId]) { + for i in (1..v.len()).rev() { + circ.swap(v[i], v[i - 1]); + } +} + +fn controlled_mod_double(circ: &mut B, ctrl: &QubitId, a: &[QubitId]) { + let n = a.len(); + assert_eq!(n, 256, "controlled_mod_double expects 256-bit a"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let ovf = circ.alloc_qubit(); + + let w: Vec<&QubitId> = a.iter().chain(std::iter::once(&ovf)).collect(); + for i in (0..n).rev() { + circ.cswap(*ctrl, *w[i], *w[i + 1]); + } + + arith::add_f_window_pub(circ, &ovf, a, arith::LSBS, &f_bytes, None); + + clear_and(circ, &ovf, ctrl, &a[0]); + circ.zero_and_free(ovf); +} + +fn controlled_mod_double_reverse(circ: &mut B, ctrl: &QubitId, a: &[QubitId]) { + let n = a.len(); + assert_eq!(n, 256, "controlled_mod_double_reverse expects 256-bit a"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let ovf = circ.alloc_qubit(); + + circ.ccx(*ctrl, a[0], ovf); + + for q in &a[..arith::LSBS] { + circ.x(*q); + } + arith::add_f_window_pub(circ, &ovf, a, arith::LSBS, &f_bytes, None); + for q in &a[..arith::LSBS] { + circ.x(*q); + } + + let w: Vec<&QubitId> = a.iter().chain(std::iter::once(&ovf)).collect(); + for i in 0..n { + circ.cswap(*ctrl, *w[i], *w[i + 1]); + } + circ.zero_and_free(ovf); +} + +#[must_use] +pub fn forward_gcd_jump(circ: &mut B, v: &mut Vec, apply_inv: Option<(&[QubitId], &[QubitId])>) -> Vec { + let n = 256usize; + assert_eq!(JUMP, 2, "ludicrous apply/codec are jump=2 specific"); + assert!(v.len() >= n, "v must be at least n=256 bits"); + let iters = ITERS; + let sym_bits = 3; + + let mut u: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); + let q_bytes = q_secp256k1_le(); + for (i, qb) in u.iter().enumerate() { + if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { + circ.x(*qb); + } + } + + let subtracted = circ.alloc_qubit(); + let mut swap_flag: Option = None; + let s2 = circ.alloc_qubit(); + let t1 = circ.alloc_qubit(); + + let n3 = n3_for_iters(iters); + let mut window_plan: Vec = Vec::new(); + for (codec, count) in super::codec::jump_dialog_regions(n3, iters) { + for _ in 0..count { + window_plan.push(codec); + } + } + let mut tape: Vec = Vec::with_capacity(super::codec::dialog_tape_qubits(n3, iters)); + let mut win_idx = 0usize; + let mut pending: Vec = Vec::new(); + let mut tail4_prefix_encoded = false; + for i in 0..iters { + let trace_region_start = circ.phase_active_regions.len(); + circ.set_phase(if apply_inv.is_some() { + "tlm_inverse_gcd_forward_shift" + } else { + "tlm_multiply_gcd_forward_shift" + }); + let current_n = (SCHED_J2[i] as usize).max(1); + while u.len() > current_n { + let q = u.pop().expect("u nonempty"); + circ.zero_and_free(q); + } + while v.len() > current_n { + let q = v.pop().expect("v nonempty"); + circ.zero_and_free(q); + } + + let cmp_eff = (GAP_J2[i] as usize).min(current_n).max(1); + + if i == 0 { + circ.cx(v[0], t1); + circ.x(t1); + controlled_right_shift(circ, &t1, &v[..current_n]); + } else { + right_shift(circ, &v[..current_n]); + } + + circ.cx(v[0], s2); + circ.x(s2); + controlled_right_shift(circ, &s2, &v[..current_n]); + + circ.cx(v[0], subtracted); + + circ.set_phase(if apply_inv.is_some() { + "tlm_inverse_gcd_forward_compare" + } else { + "tlm_multiply_gcd_forward_compare" + }); + let swp = if i == 0 { + subtracted + } else { + let sf = *swap_flag.get_or_insert_with(|| circ.alloc_qubit()); + controlled_swap_decision_v_lt_u( + circ, + &subtracted, + &v[..current_n], + &u[..current_n], + cmp_eff, + &sf, + ); + sf + }; + + for j in 1..current_n { + if !gcd_forward_cswap_has_structurally_dead_gate(i, j) { + let old_context = crate::point_add::set_op_trace_context( + 0x1b00_0000 | (((i as u32) & 0xffff) << 8) | (j as u32 & 0xff), + ); + circ.cswap(swp, u[j], v[j]); + crate::point_add::restore_op_trace_context(old_context); + } + } + let parked_u0 = if park_odd_u0_enabled(i, "FWD") { + let q = u[0]; + Some(park_known_one(circ, q)) + } else { + None + }; + + circ.set_phase(if apply_inv.is_some() { + "tlm_inverse_gcd_forward_body" + } else { + "tlm_multiply_gcd_forward_body" + }); + for q in &v[..current_n] { + circ.x(*q); + } + controlled_add_active( + circ, + i, + &subtracted, + &u[..current_n], + &v[..current_n], + GcdBit0Mode::ForwardKnownOneAfterCx, + apply_inv.map_or(&[], |(xr, _)| &xr[..3]), + ); + for q in &v[..current_n] { + circ.x(*q); + } + + circ.set_phase(if apply_inv.is_some() { + "tlm_inverse_gcd_forward_apply" + } else { + "tlm_multiply_gcd_forward_apply" + }); + if i >= 250 && std::env::var_os("TRACE_TLM_TAIL").is_some() { + eprintln!( + "TLM_TAIL direction=forward i={i} active={} tape={} pending={} encoded={tail4_prefix_encoded}", + circ.active_qubits, + tape.len(), + pending.len(), + ); + } + let parked_v0 = if apply_inv.is_some() && park_even_v0_enabled() { + let q = v[0]; + Some(park_known_zero(circ, q)) + } else { + None + }; + if let Some((xr, yr)) = apply_inv { + apply_step_reverse( + circ, + i, + &subtracted, + &swp, + &s2, + &t1, + xr, + yr, + &u[1..4], + ); + } + if let Some(q) = parked_v0 { + v[0] = restore_known_zero(circ, q); + } + if let Some(q) = parked_u0 { + u[0] = restore_known_one(circ, q); + } + + circ.set_phase(if apply_inv.is_some() { + "tlm_inverse_gcd_forward_codec" + } else { + "tlm_multiply_gcd_forward_codec" + }); + let slots: Vec = (0..sym_bits).map(|_| circ.alloc_qubit()).collect(); + circ.swap(subtracted, slots[0]); + if i == 0 { + circ.cx(slots[0], slots[1]); + } else { + circ.swap(swp, slots[1]); + } + circ.swap(s2, slots[2]); + if i == 0 { + debug_assert_eq!(window_plan[win_idx], super::codec::DialogCodec::Step0); + let data = super::codec::compress_step0_with_t1(circ, t1, &slots); + tape.extend(data); + win_idx += 1; + circ.set_phase("tlm_gcd_step_end"); + trace_step_regions( + circ, + if apply_inv.is_some() { + "inverse-forward" + } else { + "multiply-forward" + }, + i, + trace_region_start, + ); + continue; + } + pending.extend(slots); + + let codec = window_plan[win_idx]; + if codec == super::codec::DialogCodec::Tail4Top32 { + if !tail4_prefix_encoded && pending.len() == 3 * sym_bits { + pending = super::codec::DialogCodec::Triple.compress_window(circ, &pending); + tail4_prefix_encoded = true; + } else if tail4_prefix_encoded + && pending.len() == super::codec::DialogCodec::Triple.code_bits() + 2 * sym_bits + { + let last = pending.split_off(super::codec::DialogCodec::Triple.code_bits()); + let mut raw = super::codec::DialogCodec::Triple.decompress_window(circ, &pending); + raw.extend(last); + let data = codec.compress_window(circ, &raw); + tape.extend(data); + pending.clear(); + tail4_prefix_encoded = false; + win_idx += 1; + } + } else if pending.len() == codec.syms() * sym_bits { + let data = codec.compress_window(circ, &pending); + tape.extend(data); + pending.clear(); + win_idx += 1; + } + circ.set_phase("tlm_gcd_step_end"); + trace_step_regions( + circ, + if apply_inv.is_some() { + "inverse-forward" + } else { + "multiply-forward" + }, + i, + trace_region_start, + ); + } + assert_eq!(win_idx, window_plan.len(), "all windows compressed"); + assert!(pending.is_empty(), "no leftover symbols"); + + circ.x(u[0]); + while let Some(q) = v.pop() { + circ.zero_and_free(q); + } + for q in u { + circ.zero_and_free(q); + } + circ.zero_and_free(subtracted); + if let Some(swap_flag) = swap_flag { + circ.zero_and_free(swap_flag); + } + circ.zero_and_free(s2); + assert_eq!(tape.len(), super::codec::dialog_tape_qubits(n3, iters)); + tape +} + +pub fn reverse_gcd_jump(circ: &mut B, v: &mut Vec, tape: &mut Vec, apply_fwd: Option<(&[QubitId], &[QubitId])>) { + let n = 256usize; + let iters = ITERS; + let n3 = n3_for_iters(iters); + assert_eq!( + tape.len(), + super::codec::dialog_tape_qubits(n3, iters), + "tape must be the compressed dialog" + ); + + let mut window_plan: Vec = Vec::new(); + for (codec, count) in super::codec::jump_dialog_regions(n3, iters) { + for _ in 0..count { + window_plan.push(codec); + } + } + let mut win_idx = window_plan.len(); + + let mut pending: Vec = Vec::new(); + let mut pending_tail4 = false; + let mut tail4_prefix_encoded = false; + + let mut u: Vec = vec![circ.alloc_qubit()]; + circ.x(u[0]); + + let subtracted = circ.alloc_qubit(); + let mut swap_flag: Option = Some(circ.alloc_qubit()); + let s2 = circ.alloc_qubit(); + let mut step0_t1: Option = None; + + for i in (0..iters).rev() { + let trace_region_start = circ.phase_active_regions.len(); + circ.set_phase(if apply_fwd.is_some() { + "tlm_multiply_gcd_reverse_decode" + } else { + "tlm_inverse_gcd_reverse_decode" + }); + let current_n = (SCHED_J2[i] as usize).max(1); + while u.len() < current_n { + u.push(circ.alloc_qubit()); + } + while v.len() < current_n { + v.push(circ.alloc_qubit()); + } + let cmp_eff = (GAP_J2[i] as usize).min(current_n).max(1); + + if pending.is_empty() { + win_idx -= 1; + let codec = window_plan[win_idx]; + let cb = codec.code_bits(); + let tlen = tape.len(); + let data: Vec = tape.split_off(tlen - cb); + if codec == super::codec::DialogCodec::Step0 { + let (t1, raw) = super::codec::decompress_step0_with_t1(circ, &data); + step0_t1 = Some(t1); + pending = raw; + } else { + pending = codec.decompress_window(circ, &data); + } + pending_tail4 = codec == super::codec::DialogCodec::Tail4Top32; + } else if tail4_prefix_encoded { + let suffix = pending.split_off(super::codec::DialogCodec::Triple.code_bits()); + pending = super::codec::DialogCodec::Triple.decompress_window(circ, &pending); + pending.extend(suffix); + tail4_prefix_encoded = false; + } + + let plen = pending.len(); + let cur: Vec = pending.split_off(plen - 3); + if pending_tail4 && pending.len() == 12 { + let suffix = pending.split_off(9); + pending = super::codec::DialogCodec::Triple.compress_window(circ, &pending); + pending.extend(suffix); + tail4_prefix_encoded = true; + } else if pending_tail4 && pending.is_empty() { + pending_tail4 = false; + } + if i >= 250 && std::env::var_os("TRACE_TLM_TAIL").is_some() { + eprintln!( + "TLM_TAIL direction=reverse i={i} active={} tape={} pending={} encoded={tail4_prefix_encoded}", + circ.active_qubits, + tape.len(), + pending.len(), + ); + } + circ.swap(subtracted, cur[0]); + let swp = if i == 0 { + circ.cx(subtracted, cur[1]); + subtracted + } else { + let sf = *swap_flag + .as_ref() + .expect("swap flag live for non-step0 replay"); + circ.swap(sf, cur[1]); + sf + }; + circ.swap(s2, cur[2]); + + for q in cur { + circ.zero_and_free(q); + } + + circ.set_phase(if apply_fwd.is_some() { + "tlm_multiply_gcd_reverse_apply" + } else { + "tlm_inverse_gcd_reverse_apply" + }); + let parked_u0 = if park_odd_u0_enabled(i, "REV") { + let q = u[0]; + Some(park_known_one(circ, q)) + } else { + None + }; + + let parked_v0 = if apply_fwd.is_some() && park_even_v0_enabled() { + let q = v[0]; + Some(park_known_zero(circ, q)) + } else { + None + }; + if let Some((xr, yr)) = apply_fwd { + let t1 = step0_t1.unwrap_or(subtracted); + apply_step_forward( + circ, + i, + &subtracted, + &swp, + &s2, + &t1, + xr, + yr, + &u[1..4], + ); + } + if let Some(q) = parked_v0 { + v[0] = restore_known_zero(circ, q); + } + + circ.set_phase(if apply_fwd.is_some() { + "tlm_multiply_gcd_reverse_body" + } else { + "tlm_inverse_gcd_reverse_body" + }); + controlled_add_active( + circ, + i, + &subtracted, + &u[..current_n], + &v[..current_n], + GcdBit0Mode::ReverseKnownZeroBeforeCx, + apply_fwd.map_or(&[], |(xr, _)| &xr[..3]), + ); + if let Some(q) = parked_u0 { + u[0] = restore_known_one(circ, q); + } + + for j in 1..current_n { + let old_context = crate::point_add::set_op_trace_context( + 0x1200_0000 | (((i as u32) & 0xffff) << 8) | (j as u32 & 0xff), + ); + if !gcd_reverse_cswap_has_structurally_dead_gate(i, j) { + circ.cswap(swp, u[j], v[j]); + } + crate::point_add::restore_op_trace_context(old_context); + } + + if i != 0 { + super::comparator::swap_decision_uncompute_vented( + circ, + &subtracted, + &v[..current_n], + &u[..current_n], + cmp_eff, + &swp, + ); + } + + circ.cx(v[0], subtracted); + + controlled_left_shift(circ, &s2, &v[..current_n]); + circ.x(s2); + circ.cx(v[0], s2); + + if i == 0 { + let t1 = step0_t1.expect("step0 t1 decompressed"); + controlled_left_shift(circ, &t1, &v[..current_n]); + circ.x(t1); + circ.cx(v[0], t1); + } else { + left_shift(circ, &v[..current_n]); + } + + if i == 0 { + let t1 = step0_t1.take().expect("step0 t1 present"); + circ.zero_and_free(t1); + } + if i == 1 { + let sf = swap_flag.take().expect("swap flag still allocated"); + circ.zero_and_free(sf); + } + circ.set_phase("tlm_gcd_step_end"); + trace_step_regions( + circ, + if apply_fwd.is_some() { + "multiply-reverse" + } else { + "inverse-reverse" + }, + i, + trace_region_start, + ); + } + assert!(tape.is_empty(), "tape not fully drained"); + + let q_bytes = q_secp256k1_le(); + for (i, qb) in u.iter().enumerate().take(n) { + if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { + circ.x(*qb); + } + } + for q in u { + circ.zero_and_free(q); + } + circ.zero_and_free(subtracted); + if let Some(swap_flag) = swap_flag { + circ.zero_and_free(swap_flag); + } + circ.zero_and_free(s2); +} + +fn controlled_swap_decision_v_lt_u( + circ: &mut B, + ctrl: &QubitId, + v: &[QubitId], + u: &[QubitId], + k: usize, + target: &QubitId, +) { + super::comparator::controlled_swap_decision_lt_truncated(circ, ctrl, v, u, k, target); +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum GcdBit0Mode { + ForwardKnownOneAfterCx, + ReverseKnownZeroBeforeCx, +} + +fn controlled_add_active( + circ: &mut B, + i: usize, + ctrl: &QubitId, + x: &[QubitId], + y: &[QubitId], + bit0_mode: GcdBit0Mode, + dirty_vents: &[QubitId], +) { + + let k = maybe_adjust_late_gcd_k(i, super::next_gcd_k()); + let branch = super::next_gcd_branch(); + let loan_y0 = loan_gcd_y0_enabled() && x.len() > 1; + match bit0_mode { + GcdBit0Mode::ForwardKnownOneAfterCx => { + circ.cx(*ctrl, y[0]); + if loan_y0 { + loan_known_one_gcd_y0(circ, y[0]); + } + } + GcdBit0Mode::ReverseKnownZeroBeforeCx => { + + if loan_y0 { + loan_known_zero_gcd_y0(circ, y[0]); + } + } + } + if x.len() > 1 { + let yr: Vec<&QubitId> = y[1..].iter().collect(); + let xr: Vec<&QubitId> = x[1..].iter().collect(); + super::gidney::with_dirty_vent_pool(dirty_vents, || { + super::gidney::controlled_hybrid_add_capped_branch( + circ, + ctrl, + &yr, + &xr, + k, + super::PAD, + branch, + ); + }); + } + if loan_y0 { + match bit0_mode { + GcdBit0Mode::ForwardKnownOneAfterCx => reclaim_known_one_gcd_y0(circ, y[0]), + GcdBit0Mode::ReverseKnownZeroBeforeCx => reclaim_known_zero_gcd_y0(circ, y[0]), + } + } + if bit0_mode == GcdBit0Mode::ReverseKnownZeroBeforeCx { + circ.cx(*ctrl, y[0]); + } +} + +fn apply_step_forward( + circ: &mut B, + i: usize, + sub: &QubitId, + swp: &QubitId, + s2: &QubitId, + t1: &QubitId, + x_reg: &[QubitId], + y_reg: &[QubitId], + dirty_vents: &[QubitId], +) { + let n = 256usize; + let s2_known_zero = i != 0 && apply_fwd_s2_zero(i); + + circ.set_phase("tlm_apply_forward_mod_add"); + let k = super::next_cout_k(); + let ffg = super::next_ffg(); + if !apply_add_skip(i, true) { + super::gidney::with_dirty_vent_pool(dirty_vents, || { + arith::controlled_mod_add_k( + circ, + sub, + &x_reg[..n], + &y_reg[..n], + Some(k), + Some(ffg), + ); + }); + } + + circ.set_phase("tlm_apply_forward_swap"); + if !apply_fwd_cswap_skip(i) { + for j in 0..n { + circ.cswap(*swp, x_reg[j], y_reg[j]); + } + } + + circ.set_phase("tlm_apply_forward_fold"); + if i == 0 { + controlled_mod_double(circ, t1, y_reg); + controlled_mod_double(circ, s2, y_reg); + } else if s2_known_zero { + super::fused::fused_double_only(circ, y_reg); + } else { + super::fused::fused_double_cdouble(circ, s2, y_reg); + } +} + +fn apply_step_reverse( + circ: &mut B, + i: usize, + sub: &QubitId, + swp: &QubitId, + s2: &QubitId, + t1: &QubitId, + x_reg: &[QubitId], + y_reg: &[QubitId], + dirty_vents: &[QubitId], +) { + let n = 256usize; + let s2_known_zero = i != 0 && apply_inv_s2_zero(i); + + circ.set_phase("tlm_apply_inverse_fold"); + if i == 0 { + controlled_mod_double_reverse(circ, s2, y_reg); + controlled_mod_double_reverse(circ, t1, y_reg); + } else if s2_known_zero { + super::fused::fused_double_only_reverse(circ, y_reg); + } else { + super::fused::fused_double_cdouble_reverse(circ, s2, y_reg); + } + + circ.set_phase("tlm_apply_inverse_swap"); + if !apply_inv_cswap_skip(i) { + for j in 0..n { + circ.cswap(*swp, x_reg[j], y_reg[j]); + } + } + + circ.set_phase("tlm_apply_inverse_mod_sub"); + let k = super::next_cout_k(); + if !apply_add_skip(i, false) { + super::gidney::with_dirty_vent_pool(dirty_vents, || { + controlled_mod_sub_vented(circ, sub, &x_reg[..n], &y_reg[..n], Some(k)); + }); + } +} + +fn controlled_mod_sub_vented(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], sched_k: Option) { + let n = x.len(); + assert_eq!(y.len(), n, "x,y equal width"); + let f_bytes = F_SECP256K1.to_le_bytes(); + let anc = circ.alloc_qubit(); + + circ.set_phase("tlm_apply_inverse_mod_sub_register"); + for q in y { + circ.x(*q); + } + controlled_add_active_cout(circ, ctrl, x, y, &anc, sched_k); + for q in y { + circ.x(*q); + } + + circ.set_phase("tlm_apply_inverse_mod_sub_fold"); + for q in &y[..arith::LSBS] { + circ.x(*q); + } + let ffg = super::next_ffg(); + arith::add_f_window_pub(circ, &anc, y, arith::LSBS, &f_bytes, Some(ffg)); + for q in &y[..arith::LSBS] { + circ.x(*q); + } + + circ.set_phase("tlm_apply_inverse_mod_sub_clean"); + let k = arith::MSBS.min(n); + let lo = n - k; + let ctrl = *ctrl; + let bit = circ.alloc_bit(); + circ.hmr(anc, bit); + circ.zero_and_free(anc); + circ.push_condition(bit); + let yt: Vec = y[lo..n].to_vec(); + let xt: Vec = x[lo..n].to_vec(); + for q in &xt { + circ.x(*q); + } + + let flag = circ.alloc_qubit(); + super::comparator::compare_geq_chunked_middle(circ, &yt, &xt, &flag, |c, fl| { + c.cz(ctrl, *fl); + }, k); + circ.zero_and_free(flag); + for q in &xt { + circ.x(*q); + } + circ.pop_condition(); +} + +fn controlled_add_active_cout(circ: &mut B, ctrl: &QubitId, x: &[QubitId], y: &[QubitId], cout: &QubitId, sched_k: Option) { + match sched_k { + Some(k) => { + + let yr: Vec<&QubitId> = y.iter().collect(); + let xr: Vec<&QubitId> = x.iter().collect(); + super::gidney::controlled_hybrid_add_cout_refs(circ, ctrl, &yr, &xr, cout, k); + } + None => arith::controlled_add_vented_chunked_cout(circ, ctrl, x, y, arith::APPLY_CHUNK, Some(cout)), + } +} + +#[must_use] +pub fn mod_mul_inverse_in_place( + circ: &mut B, + mut xv: Vec, + y: &[QubitId], + dir: Direction, +) -> Vec { + let n = 256usize; + assert_eq!(xv.len(), n, "xv must be 256 bits"); + assert_eq!(y.len(), n, "y must be 256 bits"); + + match dir { + Direction::Inverse => { + + let tmp: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); + for j in 0..n { + circ.swap(y[j], tmp[j]); + } + let mut tape = forward_gcd_jump(circ, &mut xv, Some((y, &tmp))); + for q in tmp { + circ.zero_and_free(q); + } + reverse_gcd_jump(circ, &mut xv, &mut tape, None); + xv + } + Direction::Forward => { + + let mut tape = forward_gcd_jump(circ, &mut xv, None); + let tmp: Vec = (0..n).map(|_| circ.alloc_qubit()).collect(); + for j in 0..n { + circ.swap(y[j], tmp[j]); + } + reverse_gcd_jump(circ, &mut xv, &mut tape, Some((&tmp, y))); + clear_zeroed_drift(circ, &tmp[..n]); + for q in tmp { + circ.zero_and_free(q); + } + xv + } + } +} + +fn clear_zeroed_drift(circ: &mut B, reg: &[QubitId]) { + let q_bytes = q_secp256k1_le(); + for (i, qb) in reg.iter().enumerate() { + if (q_bytes.get(i / 8).copied().unwrap_or(0) >> (i % 8)) & 1 == 1 { + circ.x(*qb); + } + } +} diff --git a/src/point_add/trailmix_ludicrous/gidney.rs b/src/point_add/trailmix_ludicrous/gidney.rs index 6ef80d4e..5ea8d1a6 100644 --- a/src/point_add/trailmix_ludicrous/gidney.rs +++ b/src/point_add/trailmix_ludicrous/gidney.rs @@ -1,2017 +1,1943 @@ - -use super::comparator::{compare_geq_cin_middle, compare_geq_cin_middle_keyed}; -use super::{B, BExt}; -use crate::circuit::QubitId; -use std::cell::{Cell, RefCell}; - -thread_local! { - static DIRTY_VENT_POOL: RefCell> = const { RefCell::new(Vec::new()) }; - static THREADED_ADD_CALL_INDEX: Cell = const { Cell::new(0) }; - static HYBRID_ADD_CALL_INDEX: Cell = const { Cell::new(0) }; - static ERASE_GATED_CALL_INDEX: Cell = const { Cell::new(0) }; - static ERASE_GATED_CAPPED_CALL_INDEX: Cell = const { Cell::new(0) }; -} - -pub(super) fn reset_gidney_call_index() { - THREADED_ADD_CALL_INDEX.with(|index| index.set(0)); - HYBRID_ADD_CALL_INDEX.with(|index| index.set(0)); - ERASE_GATED_CALL_INDEX.with(|index| index.set(0)); - ERASE_GATED_CAPPED_CALL_INDEX.with(|index| index.set(0)); -} - -fn next_threaded_add_call_index() -> usize { - THREADED_ADD_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_hybrid_add_call_index() -> usize { - HYBRID_ADD_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_erase_gated_call_index() -> usize { - ERASE_GATED_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn next_erase_gated_capped_call_index() -> usize { - ERASE_GATED_CAPPED_CALL_INDEX.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -const GIDNEY_THREAD_FWD_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (2591, 30, 30), - (2591, 52, 52), - (2591, 54, 253), - (5, 0, 123), - (1, 18, 18), - (1, 20, 121), - (0, 53, 122), - (4, 0, 65), - (3, 21, 21), - (3, 23, 65), - (2850, 0, 14), - (2851, 0, 13), - (2852, 0, 12), - (2853, 0, 11), - (2854, 0, 10), - (2334, 0, 9), - (2855, 0, 9), - (2865, 0, 9), - (2335, 3, 11), - (2856, 0, 8), - (2878, 3, 11), - (2337, 6, 13), - (2857, 0, 7), - (2909, 6, 13), - (2336, 5, 11), - (2858, 0, 6), - (2894, 5, 11), - (2338, 8, 13), - (2859, 0, 5), - (2925, 8, 13), - (2303, 7, 11), - (2339, 9, 13), - (2340, 10, 14), - (2860, 0, 4), - (2944, 9, 13), - (2964, 10, 14), - (2272, 10, 13), - (2341, 11, 14), - (2344, 14, 17), - (2602, 249, 252), - (2844, 9, 9), - (2844, 11, 13), - (2846, 8, 11), - (2861, 0, 3), - (2985, 11, 14), - (3007, 12, 15), - (62, 52, 55), - (68, 53, 56), - (74, 54, 57), - (80, 51, 54), - (86, 52, 55), - (92, 53, 56), - (98, 50, 53), - (104, 52, 54), - (110, 53, 55), - (116, 50, 52), - (122, 51, 53), - (128, 52, 54), - (134, 49, 51), - (140, 50, 52), - (146, 51, 53), - (152, 48, 50), - (158, 49, 51), - (164, 50, 52), - (170, 47, 49), - (182, 49, 51), - (2256, 11, 13), - (2287, 9, 11), - (2316, 7, 9), - (2332, 6, 8), - (2342, 13, 15), - (2343, 14, 16), - (2358, 29, 31), - (2601, 251, 253), - (2603, 249, 251), - (2604, 248, 250), - (2605, 247, 249), - (2606, 246, 248), - (2607, 245, 247), - (2613, 239, 241), - (2843, 11, 13), - (2845, 9, 11), - (2847, 7, 9), - (2848, 6, 8), - (2862, 0, 2), - (3030, 14, 16), - (3052, 15, 17), - (56, 51, 53), -]; - -const GIDNEY_THREAD_SUM_DEAD_RANGES: &[(usize, usize, usize)] = &[ - (2334, 0, 10), - (2865, 0, 10), - (2335, 3, 12), - (2878, 3, 12), - (2337, 6, 14), - (2909, 6, 14), - (2336, 5, 12), - (2894, 5, 12), - (2338, 8, 14), - (2925, 8, 14), - (2339, 9, 14), - (2340, 10, 15), - (2844, 9, 14), - (2944, 9, 14), - (2964, 10, 15), - (2256, 10, 14), - (2272, 10, 14), - (2332, 5, 9), - (2341, 11, 15), - (2344, 14, 18), - (2602, 249, 253), - (2846, 8, 12), - (2985, 11, 15), - (3007, 12, 16), - (128, 51, 54), - (2287, 9, 12), - (2303, 9, 12), - (2316, 7, 10), - (2342, 13, 16), - (2343, 14, 17), - (2358, 29, 32), - (2601, 251, 254), - (2604, 248, 251), - (2605, 247, 250), - (2606, 246, 249), - (2607, 245, 248), - (2613, 239, 242), - (2843, 11, 14), - (2845, 9, 12), - (2847, 7, 10), - (2848, 6, 9), - (2849, 6, 9), - (3030, 14, 17), - (3052, 15, 18), - (3185, 22, 25), - (62, 52, 55), - (68, 53, 56), - (74, 54, 57), - (80, 51, 54), - (86, 52, 55), - (92, 53, 56), - (98, 50, 53), - (104, 52, 54), - (110, 53, 55), - (116, 50, 52), - (122, 51, 53), - (140, 50, 52), - (146, 51, 53), - (152, 48, 50), - (158, 49, 51), - (164, 50, 52), - (170, 47, 49), - (182, 49, 51), - (2217, 13, 15), - (2237, 12, 14), - (2345, 16, 18), - (2346, 17, 19), - (2354, 26, 28), - (2355, 27, 29), - (2356, 28, 30), - (2357, 29, 31), - (2359, 31, 33), - (2360, 32, 34), - (2361, 33, 35), - (2362, 34, 36), - (2363, 35, 37), - (2364, 36, 38), - (2365, 37, 39), - (2368, 40, 42), - (2370, 42, 44), - (2599, 252, 254), - (2600, 252, 254), - (2608, 245, 247), - (2609, 244, 246), - (2611, 242, 244), - (2612, 241, 243), - (2614, 239, 241), - (2615, 238, 240), - (2617, 236, 238), - (2618, 235, 237), - (2620, 233, 235), - (2621, 232, 234), - (2626, 227, 229), - (2627, 226, 228), - (2838, 15, 17), - (2839, 14, 16), - (2841, 13, 15), - (2842, 12, 14), - (3069, 16, 18), - (3084, 17, 19), - (3098, 17, 19), - (3201, 24, 26), - (3216, 25, 27), - (3232, 24, 26), - (3247, 25, 27), - (3261, 26, 28), - (3290, 26, 28), - (3304, 27, 29), - (3318, 26, 28), - (3332, 27, 29), - (3350, 28, 30), - (3364, 27, 29), - (3397, 29, 31), - (3415, 28, 30), - (3430, 29, 31), - (3444, 30, 32), - (3459, 29, 31), - (56, 51, 53), -]; - -const GIDNEY_THREAD_BOUNDARY_DEAD_CALLS: &[usize] = &[ - 0, - 1, - 1002, - 1010, - 1018, - 1026, - 1034, - 104, - 1043, - 1060, - 1069, - 1078, - 1087, - 1096, - 110, - 1105, - 1114, - 1123, - 1132, - 1141, - 1150, - 116, - 1168, - 1177, - 1186, - 1195, - 1204, - 1213, - 122, - 1222, - 1231, - 1240, - 1249, - 1258, - 1259, - 1268, - 1278, - 128, - 1287, - 1296, - 1297, - 1306, - 1307, - 1325, - 1334, - 1335, - 1344, - 1353, - 1362, - 1371, - 1380, - 1389, - 1399, - 14, - 140, - 1408, - 1418, - 1428, - 1438, - 1448, - 1458, - 146, - 1468, - 1478, - 1488, - 1498, - 1508, - 152, - 158, - 164, - 170, - 176, - 182, - 188, - 194, - 2, - 20, - 200, - 206, - 212, - 218, - 224, - 230, - 236, - 242, - 248, - 254, - 26, - 260, - 266, - 272, - 278, - 284, - 2850, - 2851, - 2852, - 2853, - 2854, - 2855, - 2856, - 2857, - 2858, - 2859, - 2860, - 2861, - 2862, - 2863, - 2864, - 290, - 296, - 302, - 308, - 314, - 32, - 320, - 326, - 333, - 339, - 346, - 353, - 360, - 367, - 3674, - 3684, - 3694, - 3704, - 3714, - 3724, - 3734, - 374, - 3744, - 3754, - 3764, - 3774, - 3783, - 3793, - 38, - 3802, - 381, - 3811, - 3820, - 3829, - 3838, - 3847, - 3848, - 3857, - 3866, - 3876, - 388, - 3886, - 3895, - 3905, - 3915, - 3924, - 3934, - 3943, - 395, - 3952, - 3961, - 3970, - 3979, - 3988, - 3997, - 4006, - 4015, - 402, - 4024, - 4033, - 4042, - 4051, - 4060, - 4069, - 4078, - 4087, - 409, - 4096, - 4105, - 4114, - 4123, - 4132, - 4140, - 4149, - 4157, - 416, - 4165, - 4173, - 4181, - 4189, - 4197, - 4205, - 4213, - 4221, - 4229, - 423, - 4237, - 4245, - 4253, - 4261, - 4269, - 4277, - 4285, - 4293, - 430, - 4301, - 4309, - 4317, - 4325, - 4333, - 4341, - 4349, - 4357, - 4365, - 437, - 4373, - 4389, - 4397, - 44, - 4404, - 4412, - 4420, - 4428, - 4436, - 444, - 4444, - 4451, - 4459, - 4466, - 4480, - 4487, - 4494, - 4501, - 4508, - 451, - 4515, - 4522, - 4529, - 4543, - 4550, - 4557, - 4564, - 4571, - 4578, - 458, - 4585, - 4592, - 4599, - 4606, - 4613, - 4620, - 4627, - 4634, - 4641, - 4648, - 465, - 4655, - 4662, - 4669, - 4676, - 4683, - 4690, - 4697, - 4704, - 4711, - 4718, - 472, - 4725, - 4732, - 4739, - 4746, - 4753, - 4760, - 4767, - 4774, - 4781, - 4788, - 479, - 4795, - 4802, - 4809, - 4816, - 4823, - 4830, - 4837, - 4844, - 4850, - 4857, - 486, - 4863, - 4869, - 4875, - 4881, - 4887, - 4893, - 4899, - 4905, - 4911, - 4917, - 4923, - 4929, - 493, - 4935, - 4941, - 4947, - 4953, - 4959, - 4965, - 4971, - 4977, - 4983, - 4989, - 4995, - 50, - 500, - 5001, - 5007, - 5013, - 5019, - 5025, - 5031, - 5037, - 5043, - 5049, - 5055, - 5061, - 5067, - 507, - 5073, - 5079, - 5085, - 5091, - 5097, - 5103, - 5109, - 5115, - 5121, - 514, - 521, - 528, - 535, - 542, - 549, - 556, - 56, - 563, - 570, - 577, - 584, - 591, - 598, - 605, - 612, - 619, - 62, - 626, - 633, - 640, - 647, - 654, - 661, - 668, - 675, - 68, - 682, - 689, - 696, - 703, - 710, - 717, - 724, - 732, - 739, - 74, - 747, - 755, - 763, - 771, - 779, - 786, - 794, - 8, - 80, - 802, - 810, - 818, - 826, - 834, - 842, - 850, - 86, - 866, - 874, - 882, - 890, - 898, - 906, - 914, - 92, - 922, - 930, - 938, - 946, - 954, - 962, - 970, - 978, - 98, - 986, - 994, -]; - -const GIDNEY_THREAD_FWD_REMAINDER_KEYS: &[u32] = &[ - 521, 9767, 11304, 11305, 12846, 12847, 45105, 45106, 48175, 48176, 49712, 49713, - 51249, 51250, 52782, 52783, 54319, 54320, 55856, 55857, 57389, 57390, 58926, 58927, - 60463, 60464, 61996, 61997, 63533, 63534, 65070, 65071, 66603, 66604, 68140, 68141, - 69677, 69678, 71210, 71211, 72747, 72748, 74284, 74285, 75817, 75818, 77354, 77355, - 78892, 80424, 80425, 81961, 81962, 83498, 83499, 85287, 85288, 86824, 86825, 88618, - 90407, 92200, 93992, 93993, 95781, 95782, 97575, 99368, 101156, 101157, 102950, 104742, - 104743, 106532, 108324, 108325, 110118, 111907, 113699, 113700, 115493, 117282, 119075, 120868, - 122657, 124450, 126243, 128032, 129825, 131618, 133406, 133407, 135200, 136993, 138782, 140575, - 142368, 144156, 144157, 145950, 147743, 149532, 151325, 153118, 154911, 154912, 156704, 156705, - 158493, 160282, 162075, 163868, 165657, 167454, 167455, 169243, 171036, 171037, 172830, 174622, - 174623, 176406, 176407, 178204, 178205, 179997, 179998, 181782, 183579, 183580, 185372, 185373, - 187417, 187418, 189210, 189211, 191259, 191260, 193305, 195353, 195354, 197398, 201236, 203285, - 205330, 207383, 207384, 209432, 209433, 211477, 211478, 213522, 215576, 217620, 217621, 219669, - 219670, 221718, 221719, 223763, 223764, 225812, 225813, 227861, 227862, 229907, 231956, 234000, - 236045, 240143, 242188, 244237, 246291, 248335, 248336, 250384, 250385, 252429, 254478, 254479, - 256523, 260617, 262665, 262666, 264715, 267016, 269065, 271370, 273671, 275976, 278281, 280582, - 282887, 285192, 287493, 289798, 294404, 296709, 299014, 301314, 301315, 303620, 305925, 308226, - 310531, 312836, 319747, 324609, 327170, 331817, 334593, 336936, 339240, 344102, 346406, 348710, - 351012, 353316, 355620, 358178, 360482, 363042, 365600, 368160, 370720, 373278, 375837, 375838, - 378398, 380956, 383516, 386076, 397092, 402722, 411681, 427296, 430623, 441118, 444959, 456990, - 460829, 465436, 480796, 484379, 491803, 495386, 503322, 511256, 545041, 550672, 556559, 562190, - 567565, 567566, 572684, 572685, 600336, 600337, 600593, 600594, 600850, 601364, 601621, 601878, - 602394, 602650, 602651, 602907, 602908, 603164, 603165, 603421, 603422, 603935, 603936, 604192, - 604193, 604449, 604450, 604706, 604707, 604963, 604964, 605220, 605221, 605478, 605735, 605992, - 606249, 606506, 608048, 626553, 638889, 665341, 665596, 665597, 665852, 665853, 667893, 667894, - 668148, 668149, 668404, 668658, 668659, 668913, 668914, 669423, 669424, 669678, 669679, 669933, - 669934, 670188, 670189, 670443, 670444, 670698, 670699, 670953, 670954, 671208, 671209, 671464, - 671718, 671719, 671974, 672229, 672483, 672484, 672738, 672739, 672994, 673249, 673504, 673759, - 674014, 674269, 674524, 674779, 675034, 675544, 675799, 676054, 676309, 676819, 677074, 677329, - 678604, 679114, 679624, 680644, 680899, 687530, 687785, 689315, 689825, 690080, 690845, 691100, - 691610, 691865, 692120, 692630, 692885, 693140, 694670, 694925, 695180, 695690, 695945, 696200, - 696455, 696710, 696965, 697475, 697730, 699515, 700025, 700279, 700535, 707419, 708439, 709969, - 710224, 710479, 710989, 711499, 712264, 713284, 714304, 714559, 716089, 716344, 716599, 717364, - 717619, 718384, 718639, 719404, 720424, 720934, 721189, 721954, 722464, 722974, 723229, 723484, - 723739, 723994, 726289, 726543, 726544, 726799, 727054, 727309, 727310, 727564, 727565, 785680, - 785681, 789521, 789522, 793105, 793106, 796435, 799764, 803093, 806422, 810775, 815383, 815384, - 819480, 819481, 823321, 823322, 827416, 827417, 831257, 831258, 834842, 834843, 838682, 842266, - 842267, 845851, 845852, 849434, 849435, 853019, 853020, 857628, 857629, 861211, 861212, 865821, - 869661, 869662, 874268, 874269, 878109, 878110, 881694, 885533, 885534, 889119, 892447, 892448, - 896030, 896031, 955936, 958496, 961056, 963618, 973348, 975652, 985088, 992257, 1020933, 1023236, - 1032452, 1043975, 1046278, 1055498, 1059848, 1070347, 1072399, 1074445, 1076496, 1076497, 1078544, 1080595, - 1092880, 1094932, 1096979, 1099030, 1101077, 1103124, 1105175, 1107222, 1109269, 1115414, 1117465, 1131546, - 1133593, 1135643, 1135644, 1137691, 1139482, 1143324, 1146910, 1152287, 1154078, 1155869, 1159455, 1170209, - 1172000, 1195298, 1198880, 1222183, 1223974, 1227560, 1229351, 1248044, 1251114, 1255723, 1257262, 1260332, - 1261871, 1263406, 1272624, 1274159, 1275698, 1278768, 1280307, 1284916, 1294134, 1298743, 1301813, 1303352, -]; - -const GIDNEY_THREAD_SUM_REMAINDER_KEYS: &[u32] = &[ - 9767, 11304, 11305, 12846, 12847, 45105, 45106, 48175, 48176, 49712, 49713, 51249, - 51250, 52782, 52783, 54319, 54320, 55856, 55857, 57389, 57390, 58926, 58927, 60463, - 60464, 61996, 61997, 63533, 63534, 65070, 65071, 66604, 68140, 68141, 69677, 69678, - 71210, 71211, 72747, 72748, 74284, 74285, 75817, 75818, 77354, 77355, 78892, 80424, - 80425, 81961, 81962, 83498, 83499, 85287, 85288, 86824, 86825, 88617, 88618, 90407, - 92200, 93993, 95781, 95782, 97575, 99368, 101156, 101157, 102950, 104742, 104743, 106532, - 108324, 108325, 110118, 111907, 113699, 113700, 117282, 120868, 122657, 124450, 126243, 128032, - 129825, 131618, 133406, 133407, 135200, 136993, 138782, 140575, 142368, 144156, 144157, 145950, - 147743, 149532, 151325, 153118, 154911, 154912, 156704, 156705, 158493, 160282, 162075, 163868, - 165657, 167454, 167455, 169243, 171036, 171037, 172830, 174622, 174623, 176406, 176407, 178204, - 178205, 179997, 179998, 181782, 183579, 183580, 185372, 185373, 187417, 187418, 189210, 189211, - 191259, 191260, 193305, 195353, 195354, 197398, 201236, 203285, 205330, 207383, 207384, 209433, - 211477, 211478, 213522, 215576, 217620, 217621, 221718, 221719, 223763, 223764, 225812, 225813, - 227861, 227862, 229907, 231956, 234000, 236045, 240143, 242188, 246291, 248336, 250384, 250385, - 252429, 254478, 254479, 256523, 260617, 262666, 264715, 267016, 271370, 273671, 275975, 275976, - 278281, 280582, 282887, 285192, 287492, 287493, 289798, 294403, 294404, 299014, 301314, 301315, - 305925, 308226, 310531, 312836, 315137, 317442, 319747, 322304, 324609, 327170, 331817, 332032, - 334592, 334593, 339240, 341760, 344102, 346406, 348710, 351012, 353316, 355620, 358178, 360482, - 363042, 365600, 368160, 370720, 373278, 375837, 375838, 378398, 380956, 383516, 386076, 388902, - 391461, 394276, 397093, 399907, 399908, 402722, 405796, 408610, 408611, 411682, 414755, 441118, - 441119, 444959, 444960, 448543, 452382, 456990, 456991, 460829, 460830, 465436, 465437, 469021, - 469022, 473629, 477212, 480796, 480797, 484379, 484380, 487963, 491803, 491804, 495386, 495387, - 499226, 503322, 503323, 507162, 511256, 511257, 523286, 536851, 540690, 545041, 545042, 550672, - 550673, 556559, 556560, 562190, 562191, 600850, 600851, 601108, 601364, 601365, 601621, 601622, - 601878, 601879, 602136, 602394, 602395, 605735, 605736, 605992, 605993, 606506, 606507, 607020, - 607021, 608820, 609077, 609333, 609334, 610362, 610619, 610876, 611133, 612161, 612418, 612675, - 613703, 613960, 614217, 614474, 614731, 615245, 615759, 616273, 616530, 616787, 617044, 618072, - 618329, 618586, 619100, 619614, 620128, 620642, 620899, 621413, 621670, 621927, 622184, 622441, - 622955, 623212, 623469, 623983, 625268, 625525, 625782, 626039, 626040, 626553, 626554, 627068, - 628867, 629123, 629124, 629381, 629638, 629895, 630152, 630409, 630666, 630923, 631437, 631693, - 631694, 633493, 633750, 634007, 634264, 634521, 635549, 635806, 636320, 636834, 637348, 638118, - 638889, 638890, 639147, 639917, 640431, 640688, 641202, 641716, 642487, 642744, 643001, 643258, - 643772, 644029, 644286, 644543, 645057, 645314, 645828, 646856, 647113, 647627, 648141, 648398, - 648912, 649169, 649426, 649939, 649940, 650197, 650454, 650711, 651225, 651482, 653281, 653538, - 653795, 654052, 654823, 655594, 656622, 656879, 657907, 660477, 665086, 665341, 665342, 668404, - 668405, 670699, 670700, 671464, 671465, 671719, 671720, 671974, 671975, 672229, 672230, 672994, - 672995, 673249, 673250, 673504, 673505, 673759, 673760, 674014, 674015, 674269, 674270, 674524, - 674525, 674779, 674780, 675034, 675035, 675290, 675544, 675545, 675799, 675800, 676054, 676055, - 676309, 676310, 676565, 676819, 676820, 677074, 677075, 677329, 677330, 677585, 677840, 678095, - 678350, 678604, 678605, 678860, 679114, 679115, 679370, 679624, 679625, 679880, 680135, 680390, - 680900, 681155, 681410, 681665, 681920, 682175, 682430, 682685, 682940, 683195, 683705, 683960, - 684214, 684215, 684470, 684980, 685235, 685490, 685745, 686000, 686255, 686510, 686765, 687020, - 687275, 687530, 687531, 687785, 687786, 688040, 688295, 688550, 688805, 689060, 689315, 689316, - 689570, 689825, 689826, 690080, 690081, 690336, 690590, 690845, 690846, 691100, 691101, 691355, - 691610, 691611, 691865, 691866, 692120, 692121, 692376, 692630, 692631, 692885, 692886, 693140, - 693141, 693395, 693650, 693905, 694160, 694415, 694671, 694925, 694926, 695180, 695181, 695435, - 695690, 695691, 695945, 695946, 696200, 696201, 696455, 696456, 696710, 696711, 696965, 696966, - 697475, 697476, 697730, 697984, 697985, 698495, 698750, 699005, 699260, 699515, 699516, 699770, - 699771, 700025, 700026, 700279, 700280, 700535, 700790, 701045, 701300, 701555, 701810, 702065, - 702575, 702830, 703085, 703340, 703595, 703850, 704105, 704360, 704615, 704869, 704870, 705125, - 705380, 705635, 706145, 706400, 706655, 706910, 707165, 707675, 707930, 708185, 708439, 708440, - 708950, 709205, 709460, 709715, 710224, 710225, 710479, 710480, 710735, 710989, 710990, 711245, - 711499, 711500, 711755, 712010, 712264, 712265, 712520, 712775, 713030, 713285, 713794, 713795, - 714050, 714305, 714560, 714815, 715070, 715325, 715580, 716089, 716090, 716344, 716345, 716599, - 716600, 716855, 717109, 717110, 717364, 717365, 717619, 717620, 717875, 719404, 719405, 719660, - 719915, 720170, 720424, 720425, 720680, 720934, 720935, 721189, 721190, 721445, 721700, 721954, - 721955, 722210, 722464, 722465, 722720, 722974, 722975, 723229, 723230, 723484, 723485, 723739, - 723740, 723994, 723995, 724503, 724758, 725013, 725268, 725779, 726034, 726289, 726290, 727054, - 727055, 796435, 796436, 799764, 799765, 803093, 803094, 806422, 806423, 810775, 810776, 838682, - 838683, 865821, 865822, 905761, 908834, 911907, 914978, 918051, 923939, 926756, 929573, 932388, - 935205, 950814, 955936, 958496, 961056, 963618, 973348, 975652, 985088, 987432, 992257, 997162, - 1014020, 1020933, 1023236, 1032452, 1041672, 1043975, 1046278, 1055498, 1059848, 1064202, 1068300, 1070347, - 1072399, 1074445, 1076496, 1076497, 1078544, 1080595, 1092880, 1094932, 1096979, 1099030, 1101076, 1101077, - 1103124, 1105175, 1107221, 1107222, 1109269, 1115414, 1117465, 1131546, 1133592, 1133593, 1135643, 1135644, - 1137690, 1137691, 1139482, 1143324, 1146910, 1152287, 1154078, 1155869, 1159455, 1170209, 1171999, 1172000, - 1193503, 1195298, 1197089, 1198880, 1222183, 1223974, 1227560, 1229351, 1244970, 1248044, 1251114, 1252653, - 1255723, 1257262, 1260332, 1261871, 1263406, 1272624, 1274159, 1275698, 1278768, 1280307, 1284916, 1292595, - 1294134, 1298743, 1301813, 1303352, 1304887, -]; - -fn gidney_structural_dead_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_STRUCTURAL_DEAD_CALLS").is_some() -} - -fn gidney_skip_top2_thread_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_TOP2_THREAD").is_some() -} - -fn gidney_skip_fullvent_top2_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_FULLVENT_TOP2").is_some() -} - -fn gidney_skip_exact_remainder_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_EXACT_REMAINDER").is_some() -} - -fn gidney_skip_exact_fwd_remainder_enabled() -> bool { - gidney_skip_exact_remainder_enabled() - || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_FWD_REMAINDER").is_some() -} - -fn gidney_skip_exact_sum_remainder_enabled() -> bool { - gidney_skip_exact_remainder_enabled() - || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_SUM_REMAINDER").is_some() -} - -fn gidney_skip_exact_erase_ccz_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_CCZ").is_some() - || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ").is_some() -} - -fn gidney_skip_exact_erase_capped_ccz_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ").is_some() - || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_CAPPED_CCZ").is_some() -} - -fn gidney_skip_small_residual_enabled() -> bool { - std::env::var_os("TLM_GIDNEY_SKIP_SMALL_RESIDUAL_DEAD").is_some() -} - -fn gidney_key(call_index: usize, bit: usize) -> u32 { - (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff) -} - -const GIDNEY_THREAD_BOUNDARY_RESIDUAL_CALLS: &[usize] = &[ - 134, 858, 1051, 1159, 1316, 3885, 3923, 4381, 4473, 4536, 5127, -]; - -const GIDNEY_ERASE_CCZ_RESIDUAL_CALLS: &[usize] = &[ - 2418, 2425, 2431, 2444, 2522, 2552, 2591, 2641, 2646, 2727, -]; - -const GIDNEY_ERASE_CAPPED_CCZ_RESIDUAL_CALLS: &[usize] = &[ - 15, 595, 605, 607, 626, 801, 807, 834, 849, 867, 870, 876, 888, 897, 903, - 909, 933, 939, 942, 957, 960, 975, 996, 999, 1002, 1035, 1047, 1056, 1071, - 1089, 1095, 1107, 1116, 1128, 1137, -]; - -const GIDNEY_ERASE_CCZ_REMAINDER_CALLS: &[usize] = &[ - 0, 1, 2, 308, 320, 337, 370, 379, 384, 389, 394, 399, 404, 409, 414, 419, - 424, 429, 434, 439, 444, 449, 454, 460, 465, 471, 477, 483, 489, 495, 501, 507, - 513, 519, 531, 537, 543, 549, 555, 561, 567, 573, 579, 585, 591, 597, 604, 610, - 617, 630, 637, 656, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, - 1528, 1529, 1530, 1531, 1532, 2379, 2398, 2405, 2450, 2456, 2462, 2468, 2474, - 2480, 2498, 2504, 2510, 2516, 2528, 2534, 2540, 2558, 2564, 2575, 2581, 2586, - 2596, 2601, 2606, 2611, 2616, 2621, 2626, 2651, 2656, 2665, -]; - -const GIDNEY_ERASE_CAPPED_CCZ_REMAINDER_CALLS: &[usize] = &[ - 1, 2, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, - 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, - 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, - 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, - 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, - 234, 237, 240, 243, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, - 276, 279, 282, 285, 288, 291, 294, 297, 300, 303, 306, 309, 312, 315, - 318, 321, 324, 327, 330, 333, 336, 339, 342, 345, 348, 351, 357, 360, - 366, 369, 372, 378, 381, 384, 387, 390, 393, 396, 402, 537, 542, 544, - 547, 549, 551, 553, 555, 557, 559, 561, 563, 565, 567, 569, 571, 573, - 575, 577, 579, 581, 583, 585, 587, 589, 591, 593, 597, 599, 601, 603, - 609, 611, 613, 615, 617, 619, 624, 634, 765, 771, 774, 777, 780, 783, - 786, 789, 795, 798, 816, 819, 822, 825, 828, 831, 837, 843, 846, 852, - 855, 858, 864, 879, 882, 885, 891, 900, 906, 912, 915, 921, 924, 927, - 930, 936, 945, 951, 954, 963, 969, 972, 978, 981, 984, 987, 990, 993, - 1005, 1008, 1011, 1014, 1017, 1020, 1023, 1026, 1029, 1032, 1038, 1041, - 1044, 1050, 1053, 1059, 1062, 1065, 1068, 1074, 1077, 1080, 1083, 1086, - 1092, 1098, 1101, 1104, 1110, 1113, 1119, 1122, 1125, 1131, -]; - -fn gidney_erase_ccz_has_exact_dead_call(call_index: usize) -> bool { - if super::drops_off_family("GIDERASE") { - return false; - } - - if gidney_skip_small_residual_enabled() - && GIDNEY_ERASE_CCZ_RESIDUAL_CALLS - .binary_search(&call_index) - .is_ok() - { - return true; - } - gidney_skip_exact_erase_ccz_enabled() - && GIDNEY_ERASE_CCZ_REMAINDER_CALLS - .binary_search(&call_index) - .is_ok() -} - -fn gidney_erase_capped_ccz_has_exact_dead_call(call_index: usize) -> bool { - if super::drops_off_family("GIDERASEC") { - return false; - } - - if gidney_skip_small_residual_enabled() - && GIDNEY_ERASE_CAPPED_CCZ_RESIDUAL_CALLS - .binary_search(&call_index) - .is_ok() - { - return true; - } - gidney_skip_exact_erase_capped_ccz_enabled() - && GIDNEY_ERASE_CAPPED_CCZ_REMAINDER_CALLS - .binary_search(&call_index) - .is_ok() -} - -fn threaded_add_call_has_structurally_dead_forward( - call_index: usize, - bit: usize, - total: usize, - width: usize, - vents: usize, -) -> bool { - if super::drops_off_family("THRFWD") { - return false; - } - - if gidney_skip_exact_fwd_remainder_enabled() - && GIDNEY_THREAD_FWD_REMAINDER_KEYS - .binary_search(&gidney_key(call_index, bit)) - .is_ok() - { - return true; - } - if gidney_skip_fullvent_top2_enabled() && vents >= width && bit + 2 >= width { - return true; - } - if gidney_skip_top2_thread_enabled() && bit + 2 >= total { - return true; - } - gidney_structural_dead_enabled() - && GIDNEY_THREAD_FWD_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -fn threaded_add_call_has_structurally_dead_boundary(call_index: usize) -> bool { - if super::drops_off_family("THRBND") { - return false; - } - - if gidney_skip_small_residual_enabled() - && GIDNEY_THREAD_BOUNDARY_RESIDUAL_CALLS - .binary_search(&call_index) - .is_ok() - { - return true; - } - gidney_structural_dead_enabled() && GIDNEY_THREAD_BOUNDARY_DEAD_CALLS.contains(&call_index) -} - -fn threaded_add_call_has_structurally_dead_sum( - call_index: usize, - bit: usize, - total: usize, - width: usize, - vents: usize, -) -> bool { - if super::drops_off_family("THRSUM") { - return false; - } - - if gidney_skip_exact_sum_remainder_enabled() - && GIDNEY_THREAD_SUM_REMAINDER_KEYS - .binary_search(&gidney_key(call_index, bit)) - .is_ok() - { - return true; - } - if gidney_skip_fullvent_top2_enabled() && vents >= width && bit + 2 >= width { - return true; - } - if gidney_skip_top2_thread_enabled() && bit + 2 >= total { - return true; - } - gidney_structural_dead_enabled() - && GIDNEY_THREAD_SUM_DEAD_RANGES - .iter() - .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) -} - -pub fn with_dirty_vent_pool(dirty: &[QubitId], body: impl FnOnce() -> R) -> R { - let count = std::env::var("TLM_DIRTY_VENTS") - .ok() - .and_then(|value| value.parse::().ok()) - .unwrap_or(0) - .min(dirty.len()); - let prior = DIRTY_VENT_POOL.with(|pool| { - std::mem::replace(&mut *pool.borrow_mut(), dirty[..count].to_vec()) - }); - let result = body(); - DIRTY_VENT_POOL.with(|pool| { - *pool.borrow_mut() = prior; - }); - result -} - -fn dirty_vent_pool() -> Vec { - DIRTY_VENT_POOL.with(|pool| pool.borrow().clone()) -} - -fn trace_schedule_fit( - trace_env: &str, - family: &str, - mode: &str, - fit: super::ScheduleFit, - effective: usize, - width: usize, - entry_active: u32, - timeline_start: usize, - ops_start: usize, - circ: &B, -) { - if std::env::var_os(trace_env).is_none() { - return; - } - let local_peak = circ.active_timeline[timeline_start..] - .iter() - .map(|(_, active)| *active) - .max() - .unwrap_or(entry_active); - eprintln!( - "TLM_{family} call={} phase={} mode={} width={} base={} selected={} effective={} entry_active={} local_peak={} ops_added={} ops={}", - fit.call_index, - circ.phase, - mode, - width, - fit.base, - fit.selected, - effective, - entry_active, - local_peak, - circ.current_ops_len().saturating_sub(ops_start), - circ.current_ops_len(), - ); -} - -pub fn controlled_hybrid_add_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId]) { - controlled_hybrid_add_refs_impl(circ, ctrl, a, b, false); -} - -fn controlled_hybrid_add_refs_skiplow(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId]) { - controlled_hybrid_add_refs_impl(circ, ctrl, a, b, true); -} - -fn controlled_hybrid_add_refs_impl(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], skip_low_ctrl_sum: bool) { - let n = a.len(); - assert_eq!(b.len(), n, "controlled_hybrid_add: a, b must match width"); - if n == 0 { - return; - } - if n == 1 { - circ.ccx(*ctrl, *b[0], *a[0]); - return; - } - let call_index = next_hybrid_add_call_index(); - - let fit = super::next_hyb_v_fit(); - let timeline_start = circ.active_timeline.len(); - let entry_active = circ.active_qubits; - let ops_start = circ.current_ops_len(); - let vents = super::target_qubit_headroom(circ) - .map_or(fit.selected, |headroom| fit.selected.min(headroom)); - - for i in 1..n { - circ.cx(*b[i], *a[i]); - } - for i in (1..n - 1).rev() { - circ.cx(*b[i], *b[i + 1]); - } - - #[derive(Clone, Copy)] - enum VentLane { - Clean(QubitId), - Dirty(QubitId), - } - let dirty_pool = dirty_vent_pool(); - let mut vent_ancs: Vec> = (0..n - 1).map(|_| None).collect(); - for i in 0..n - 1 { - if i < vents { - if let Some(&dirty) = dirty_pool.get(i) { - debug_assert_ne!(dirty, *a[i]); - debug_assert_ne!(dirty, *b[i]); - debug_assert_ne!(dirty, *b[i + 1]); - circ.cx(dirty, *b[i + 1]); - let old_context = crate::point_add::set_op_trace_context( - 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], dirty); - crate::point_add::restore_op_trace_context(old_context); - circ.cx(dirty, *b[i + 1]); - vent_ancs[i] = Some(VentLane::Dirty(dirty)); - } else { - let anc = circ.alloc_qubit(); - let old_context = crate::point_add::set_op_trace_context( - 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], anc); - crate::point_add::restore_op_trace_context(old_context); - circ.cx(anc, *b[i + 1]); - vent_ancs[i] = Some(VentLane::Clean(anc)); - } - } else { - let old_context = crate::point_add::set_op_trace_context( - 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], *b[i + 1]); - crate::point_add::restore_op_trace_context(old_context); - } - } - - for i in (0..n - 1).rev() { - let old_context = crate::point_add::set_op_trace_context( - 0x1700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*ctrl, *b[i + 1], *a[i + 1]); - crate::point_add::restore_op_trace_context(old_context); - if let Some(lane) = vent_ancs[i].take() { - match lane { - VentLane::Clean(anc) => { - circ.cx(anc, *b[i + 1]); - let bit = circ.alloc_bit(); - circ.hmr(anc, bit); - circ.zero_and_free(anc); - circ.cz_if_bit(*a[i], *b[i], bit); - } - VentLane::Dirty(dirty) => { - circ.cx(dirty, *b[i + 1]); - let old_context = crate::point_add::set_op_trace_context( - 0x1800_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], dirty); - crate::point_add::restore_op_trace_context(old_context); - circ.cx(dirty, *b[i + 1]); - } - } - } else { - let old_context = crate::point_add::set_op_trace_context( - 0x1900_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], *b[i + 1]); - crate::point_add::restore_op_trace_context(old_context); - } - } - - for i in 1..n - 1 { - circ.cx(*b[i], *b[i + 1]); - } - if !skip_low_ctrl_sum { - let old_context = crate::point_add::set_op_trace_context( - 0x1a00_0000 | (((call_index as u32) & 0xffff) << 8), - ); - circ.ccx(*ctrl, *b[0], *a[0]); - crate::point_add::restore_op_trace_context(old_context); - } - for i in 1..n { - circ.cx(*b[i], *a[i]); - } - trace_schedule_fit( - "TRACE_TLM_HYB", - "HYB", - if skip_low_ctrl_sum { "skiplow" } else { "plain" }, - fit, - vents, - n, - entry_active, - timeline_start, - ops_start, - circ, - ); -} - -fn controlled_clean_add_threaded( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - cin: Option<&QubitId>, - cout: Option<&QubitId>, - vents: usize, -) { - let call_index = next_threaded_add_call_index(); - let ops_start = circ.current_ops_len(); - let s = a.len(); - if s == 0 { - if let (Some(ci), Some(co)) = (cin, cout) { - circ.ccx(*ctrl, *ci, *co); - } - return; - } - let n_inner = if cout.is_some() { s } else { s - 1 }; - let mut inner: Vec> = (0..n_inner).map(|_| Some(circ.alloc_qubit())).collect(); - let produces = |i: usize| cout.is_some() || i + 1 < s; - - for i in 0..s { - if !produces(i) { - continue; - } - let co = inner[i].as_ref().unwrap(); - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, *a[i]); - circ.cx(*ci, *b[i]); - if !threaded_add_call_has_structurally_dead_forward(call_index, i, n_inner, s, vents) { - let old_context = crate::point_add::set_op_trace_context( - 0x0500_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], *co); - crate::point_add::restore_op_trace_context(old_context); - } - circ.cx(*ci, *co); - } else { - if !threaded_add_call_has_structurally_dead_forward(call_index, i, n_inner, s, vents) { - let old_context = crate::point_add::set_op_trace_context( - 0x0500_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*a[i], *b[i], *co); - crate::point_add::restore_op_trace_context(old_context); - } - } - } - - if let Some(cout) = cout { - let old_context = crate::point_add::set_op_trace_context( - 0x0600_0000 | (((call_index as u32) & 0xffff) << 8) | ((s.saturating_sub(1)) as u32 & 0xff), - ); - if !threaded_add_call_has_structurally_dead_boundary(call_index) { - circ.ccx(*ctrl, *inner[s - 1].as_ref().unwrap(), *cout); - } - crate::point_add::restore_op_trace_context(old_context); - } - - for i in (0..s).rev() { - if !produces(i) { - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, *b[i]); - } - if !threaded_add_call_has_structurally_dead_sum(call_index, i, s, s, vents) { - let old_context = crate::point_add::set_op_trace_context( - 0x0700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*ctrl, *b[i], *a[i]); - crate::point_add::restore_op_trace_context(old_context); - } - if let Some(ci) = ci { - circ.cx(*ci, *b[i]); - } - continue; - } - let co = inner[i].take().unwrap(); - let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; - if let Some(ci) = ci { - circ.cx(*ci, co); - } - if i < vents { - let bit = circ.alloc_bit(); - circ.hmr(co, bit); - circ.zero_and_free(co); - circ.cz_if_bit(*a[i], *b[i], bit); - } else { - circ.ccx(*a[i], *b[i], co); - circ.zero_and_free(co); - } - if let Some(ci) = ci { - circ.cx(*ci, *a[i]); - } - if !threaded_add_call_has_structurally_dead_sum(call_index, i, s, s, vents) { - let old_context = crate::point_add::set_op_trace_context( - 0x0700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), - ); - circ.ccx(*ctrl, *b[i], *a[i]); - crate::point_add::restore_op_trace_context(old_context); - } - if let Some(ci) = ci { - circ.cx(*ci, *b[i]); - } - } - if std::env::var_os("TRACE_TLM_GIDNEY_THREAD").is_some() { - eprintln!( - "TLM_GIDNEY_THREAD call={} phase={} width={} cin={} cout={} vents={} ops_start={} ops_end={}", - call_index, - circ.phase, - s, - usize::from(cin.is_some()), - usize::from(cout.is_some()), - vents, - ops_start, - circ.current_ops_len(), - ); - } -} - -fn deref(s: &[&QubitId]) -> Vec { - s.iter().map(|q| **q).collect() -} - -/// Width cap for the per-chunk carry-erase comparison, in top bits. -/// -/// A chunk carry-out is uncomputed by measuring it in the X basis and then, on the ~50% of shots -/// where the measurement comes back 1, re-deriving the carry predicate from the finished sum with a -/// `compare_geq` over the chunk. That comparison is the entire excess cost of the chunked adder -/// (`l` in the `2n + l + m + 1` objective at `searched_cout_layout`). Restricting it to the top `w` -/// bits of the chunk costs `w` emitted CCX instead of the chunk width, and is wrong only when the -/// top `w` bits of the sum and the addend coincide *and* the low part borrows: error ~2^-w, cost -/// linear in w. The same trade is already made unconditionally by the final reduction compare -/// (`controlled_lt_msbs_conditional`, MSBS = 19 of 256). -fn cout_erase_cap() -> Option { - std::env::var("TLM_COUT_ERASE_CAP") - .ok() - .and_then(|v| v.parse::().ok()) - .filter(|&w| w > 0) -} - -/// Restricts the erase cap to a window of erase call indices, `TLM_COUT_ERASE_CAP_CALLS="lo:hi"` -/// (half-open, unset = every call). The Bezout pair grows roughly one bit per divstep, so whether a -/// given chunk's operands carry any information at all is a function of where in the walk the call -/// sits; this is the dial that isolates that. -fn cout_erase_cap_call_in_window(call_index: usize) -> bool { - match std::env::var("TLM_COUT_ERASE_CAP_CALLS") { - Ok(spec) => { - let mut parts = spec.split(':'); - let lo = parts.next().and_then(|v| v.parse::().ok()).unwrap_or(0); - let hi = parts.next().and_then(|v| v.parse::().ok()).unwrap_or(usize::MAX); - (lo..hi).contains(&call_index) - } - Err(_) => true, - } -} - -fn controlled_erase_carry_gated_impl( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - cin: Option<&QubitId>, - carry: QubitId, -) { - let call_index = next_erase_gated_call_index(); - let s = a.len(); - let cap = cout_erase_cap() - .filter(|&w| w < s) - .filter(|_| cout_erase_cap_call_in_window(call_index)); - - let bit = circ.alloc_bit(); - circ.hmr(carry, bit); - circ.push_condition(bit); - let ctrl = *ctrl; - - let deposit = |c: &mut B, ta: &QubitId, tb: &QubitId, c_prev: &QubitId| { - c.z(ctrl); - let old_context = crate::point_add::set_op_trace_context( - 0x0900_0000 | (((call_index as u32) & 0xffff) << 8), - ); - - if cap.is_some() || !gidney_erase_ccz_has_exact_dead_call(call_index) { - c.ccz(ctrl, *ta, *tb); - } - crate::point_add::restore_op_trace_context(old_context); - c.cz(ctrl, *c_prev); - }; - match cap { - Some(w) => { - let lo = s - w; - let (av, bv) = (deref(&a[lo..]), deref(&b[lo..])); - - circ.loan_zero_qubit(carry); - let zcin = circ.alloc_qubit(); - compare_geq_cin_middle_keyed(circ, &av, &bv, &zcin, deposit, None); - circ.pop_condition(); - circ.zero_and_free(zcin); - } - None => { - let (av, bv) = (deref(a), deref(b)); - let cin = match cin { - Some(cin) => { - - circ.loan_zero_qubit(carry); - *cin - } - None => carry, - }; - compare_geq_cin_middle(circ, &av, &bv, &cin, deposit); - circ.pop_condition(); - if cin == carry { - circ.zero_and_free(carry); - } - } - } -} - -fn controlled_erase_carry_gated( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - cin: &QubitId, - carry: QubitId, -) { - controlled_erase_carry_gated_impl(circ, ctrl, a, b, Some(cin), carry); -} - -fn controlled_erase_carry_gated_zero_cin( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - carry: QubitId, -) { - controlled_erase_carry_gated_impl(circ, ctrl, a, b, None, carry); -} - -fn controlled_erase_carry_gated_capped( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - cin: &QubitId, - carry: QubitId, - cap: usize, -) { - let call_index = next_erase_gated_capped_call_index(); - let s = a.len(); - if s <= cap { - controlled_erase_carry_gated(circ, ctrl, a, b, cin, carry); - return; - } - let lo = s - cap; - let bit = circ.alloc_bit(); - circ.hmr(carry, bit); - circ.push_condition(bit); - let (av, bv) = (deref(&a[lo..]), deref(&b[lo..])); - let ctrl = *ctrl; - compare_geq_cin_middle(circ, &av, &bv, &carry, |c, ta, tb, c_prev| { - c.z(ctrl); - let old_context = crate::point_add::set_op_trace_context( - 0x0a00_0000 | (((call_index as u32) & 0xffff) << 8), - ); - if !gidney_erase_capped_ccz_has_exact_dead_call(call_index) { - c.ccz(ctrl, *ta, *tb); - } - crate::point_add::restore_op_trace_context(old_context); - c.cz(ctrl, *c_prev); - }); - circ.pop_condition(); - circ.zero_and_free(carry); -} - -fn controlled_erase_carry_gated_capped_zero_cin( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - carry: QubitId, - cap: usize, -) { - if a.len() <= cap { - controlled_erase_carry_gated_zero_cin(circ, ctrl, a, b, carry); - } else { - - controlled_erase_carry_gated_capped(circ, ctrl, a, b, &carry, carry, cap); - } -} - -fn controlled_vented_chunk_add(circ: &mut B, ctrl: &QubitId, a_chunk: &[&QubitId], b_chunk: &[&QubitId], cin: &QubitId, cout: &QubitId) { - let one = circ.alloc_qubit(); - circ.x(one); - let zero = circ.alloc_qubit(); - let mut aext: Vec<&QubitId> = Vec::with_capacity(a_chunk.len() + 2); - aext.push(&one); - aext.extend_from_slice(a_chunk); - aext.push(cout); - let mut bext: Vec<&QubitId> = Vec::with_capacity(b_chunk.len() + 2); - bext.push(cin); - bext.extend_from_slice(b_chunk); - bext.push(&zero); - - controlled_hybrid_add_refs_skiplow(circ, ctrl, &aext, &bext); - circ.x(one); - circ.zero_and_free(one); - circ.zero_and_free(zero); -} - -fn varchunk_schedule(n: usize, k: usize) -> Vec { - const RESERVE: usize = 4; - let mut sizes = Vec::new(); - let (mut covered, mut held) = (0usize, 0usize); - while covered < n { - let room = k.saturating_sub(held + RESERVE); - if room == 0 { - return Vec::new(); - } - let s = room.min(n - covered); - sizes.push(s); - covered += s; - held += 1; - } - sizes -} - -fn varchunk_cost(n: usize, k: usize, cap: usize) -> usize { - let sizes = varchunk_schedule(n, k); - if sizes.is_empty() { - return usize::MAX; - } - let erase: usize = sizes.iter().map(|&s| s.min(cap) / 2).sum(); - n + erase -} - -pub(crate) struct AdaptiveLayout { - pub(crate) c: usize, - pub(crate) chunked_len: usize, - pub(crate) plain_len: usize, -} -pub(crate) const ADAPTIVE_RES: usize = 5; - -fn adaptive_chunk_size(n: usize) -> usize { - std::env::var("TLM_ADAPTIVE_CHUNK") - .ok() - .and_then(|v| v.parse::().ok()) - .filter(|&v| v > 0) - .unwrap_or_else(|| (n as f64).sqrt() as usize) - .clamp(1, n) -} - -pub(crate) fn adaptive_layout(n: usize, k: usize) -> AdaptiveLayout { - let c = ((n as f64).sqrt() as usize).clamp(1, n); - adaptive_layout_for_chunk(n, k, c) -} - -fn adaptive_layout_for_chunk(n: usize, k: usize, c: usize) -> AdaptiveLayout { - let mut plain = 0usize; - while plain < n { - let l = n - (plain + 1); - let nch = l.div_ceil(c); - if nch + (plain + 1) <= k { - plain += 1; - } else { - break; - } - } - AdaptiveLayout { c, chunked_len: n - plain, plain_len: plain } -} - -fn searched_cout_layout(n: usize, k: usize) -> Option { - if std::env::var_os("TLM_COUT_LAYOUT_SEARCH").is_none() { - return None; - } - let mut margin = std::env::var("TLM_COUT_LAYOUT_MARGIN") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(1); - if margin == 0 - && std::env::var("TLM_COUT_LAYOUT_FORCE_M1_KS") - .ok() - .map(|s| { - s.split(',') - .filter_map(|part| part.trim().parse::().ok()) - .any(|force_k| force_k == k) - }) - .unwrap_or(false) - { - margin = 1; - } - let mut best: Option<(usize, AdaptiveLayout)> = None; - for c in 1..=n { - for plain_len in 0..=n { - let chunked_len = n - plain_len; - let nchunks = chunked_len.div_ceil(c); - if nchunks + plain_len + margin > k { - continue; - } - if nchunks + c.min(chunked_len.max(1)) + margin > k { - continue; - } - let cost = 2 * n + chunked_len + nchunks + 1; - let layout = AdaptiveLayout { c, chunked_len, plain_len }; - match best { - Some((best_cost, _)) if best_cost <= cost => {} - _ => best = Some((cost, layout)), - } - } - } - best.map(|(_, layout)| layout) -} - -fn emit_cout_layout( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - cout: &QubitId, - layout: AdaptiveLayout, -) { - let n = a.len(); - let l = layout.chunked_len; - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let mut lo = 0; - while lo < l { - let hi = (lo + layout.c).min(l); - bounds.push((lo, hi)); - lo = hi; - } - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(lo, hi)) in bounds.iter().enumerate() { - let cy = circ.alloc_qubit(); - let cin: Option<&QubitId> = if j == 0 { None } else { Some(&carries[j - 1]) }; - controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, Some(&cy), hi - lo); - carries.push(cy); - } - controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], carries.last(), Some(cout), layout.plain_len); - for j in (0..bounds.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); - } else { - controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); - } - } -} - -fn searched_gcd_adaptive_layout(n: usize, k: usize) -> Option { - if std::env::var_os("TLM_GCD_ADAPTIVE_LAYOUT_SEARCH").is_none() { - return None; - } - let margin = std::env::var("TLM_GCD_ADAPTIVE_LAYOUT_MARGIN") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(1); - let mut best: Option<(usize, AdaptiveLayout)> = None; - for c in 1..=n { - for plain_len in 0..=n { - let chunked_len = n - plain_len; - let nchunks = chunked_len.div_ceil(c); - if nchunks + plain_len + margin > k { - continue; - } - if nchunks + c.min(chunked_len.max(1)) + margin > k { - continue; - } - let cost = 2 * n + chunked_len + nchunks - 1; - let layout = AdaptiveLayout { c, chunked_len, plain_len }; - match best { - Some((best_cost, _)) if best_cost <= cost => {} - _ => best = Some((cost, layout)), - } - } - } - best.map(|(_, layout)| layout) -} - -fn emit_adaptive_layout_no_cout( - circ: &mut B, - ctrl: &QubitId, - a: &[&QubitId], - b: &[&QubitId], - layout: AdaptiveLayout, -) { - let n = a.len(); - let l = layout.chunked_len; - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let mut lo = 0; - while lo < l { - let hi = (lo + layout.c).min(l); - bounds.push((lo, hi)); - lo = hi; - } - let cin0 = circ.alloc_qubit(); - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(lo, hi)) in bounds.iter().enumerate() { - let cout = circ.alloc_qubit(); - let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; - controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], Some(cin), Some(&cout), hi - lo); - carries.push(cout); - } - if layout.plain_len > 0 { - let cin: &QubitId = carries.last().unwrap_or(&cin0); - controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], Some(cin), None, layout.plain_len); - } - circ.zero_and_free(cin0); - for j in (0..bounds.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); - } else { - controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); - } - } -} - -fn adaptive_add_cost_tof(n: usize, k: usize, controlled: bool) -> u64 { - if n == 0 { - return 0; - } - let base = if controlled { 3 * n } else { 2 * n }; - let s2 = 2 * (n as f64).sqrt() as usize; - let saved = if k >= n { - n - } else if k < s2 { - (k * k) / 8 - } else { - n / 2 + (k - s2) / 2 - }; - (base.saturating_sub(saved)) as u64 -} - -fn controlled_chunked_then_cuccaro(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: Option<&QubitId>, k: usize) { - let n = a.len(); - if n == 0 { - return; - } - let cin0 = circ.alloc_qubit(); - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let (mut lo, mut i) = (0usize, 0usize); - while lo < n && k > i + 2 { - let cc = (k - 2 - i).min(n - lo); - bounds.push((lo, lo + cc)); - lo += cc; - i += 1; - } - let chunked_len = lo; - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(clo, chi)) in bounds.iter().enumerate() { - let cy = circ.alloc_qubit(); - let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; - controlled_clean_add_threaded(circ, ctrl, &a[clo..chi], &b[clo..chi], Some(cin), Some(&cy), chi - clo); - carries.push(cy); - } - if chunked_len < n { - let cin: &QubitId = carries.last().unwrap_or(&cin0); - - let at = deref(&a[chunked_len..n]); - let bt = deref(&b[chunked_len..n]); - super::arith::cuccaro_carry(circ, Some(ctrl), &bt, &at, Some(cin), cout); - } else if let Some(co) = cout { - circ.cx(*carries.last().unwrap_or(&cin0), *co); - } - circ.zero_and_free(cin0); - for j in (0..bounds.len()).rev() { - let (clo, chi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[clo..chi], &b[clo..chi], carry); - } else { - controlled_erase_carry_gated(circ, ctrl, &a[clo..chi], &b[clo..chi], &carries[j - 1], carry); - } - } -} - -fn controlled_hybrid_add_adaptive_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize) { - let n = a.len(); - assert_eq!(b.len(), n, "controlled adaptive add: a,b width mismatch"); - if n == 0 { - return; - } - if let Some(layout) = searched_gcd_adaptive_layout(n, k) { - emit_adaptive_layout_no_cout(circ, ctrl, a, b, layout); - return; - } - let c = ((n as f64).sqrt() as usize).clamp(1, n); - if n <= 4 || k.saturating_add(2 * c) >= n { - controlled_hybrid_add_refs(circ, ctrl, a, b); - return; - } - let tight = k < n.div_ceil(c) + c + ADAPTIVE_RES; - let cov = (k.saturating_sub(2).saturating_mul(k.saturating_sub(1)) / 2).min(n); - if tight && cov < n { - if cov > 2 * k { - controlled_chunked_then_cuccaro(circ, ctrl, a, b, None, k); - } else { - controlled_hybrid_add_refs(circ, ctrl, a, b); - } - return; - } - let cin0 = circ.alloc_qubit(); - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let (l, plain_len) = if tight { - let (mut lo, mut i) = (0usize, 0usize); - while lo < n && k > i + 2 { - let cc = (k - 2 - i).min(n - lo); - bounds.push((lo, lo + cc)); - lo += cc; - i += 1; - } - (n, 0) - } else { - let lay = adaptive_layout(n, k); - let mut lo = 0; - while lo < lay.chunked_len { - let hi = (lo + lay.c).min(lay.chunked_len); - bounds.push((lo, hi)); - lo = hi; - } - (lay.chunked_len, lay.plain_len) - }; - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(lo, hi)) in bounds.iter().enumerate() { - let cout = circ.alloc_qubit(); - let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; - controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], Some(cin), Some(&cout), hi - lo); - carries.push(cout); - } - if plain_len > 0 { - let cin: &QubitId = carries.last().unwrap_or(&cin0); - controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], Some(cin), None, plain_len); - } - circ.zero_and_free(cin0); - for j in (0..bounds.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); - } else { - controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); - } - } -} - -fn controlled_hybrid_add_varchunk_gated_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize) { - let n = a.len(); - assert_eq!(b.len(), n, "varchunk add: a,b width mismatch"); - if n == 0 { - return; - } - let sizes = varchunk_schedule(n, k); - assert!(!sizes.is_empty(), "varchunk infeasible at k={k} for n={n}"); - let direct = std::env::var("TLM_DIRECT_VARCHUNK") - .ok() - .as_deref() - == Some("1"); - let cin0 = (!direct).then(|| circ.alloc_qubit()); - let mut carries: Vec = Vec::with_capacity(sizes.len()); - let mut bounds: Vec<(usize, usize)> = Vec::with_capacity(sizes.len()); - let mut lo = 0usize; - for (j, &s) in sizes.iter().enumerate() { - let hi = lo + s; - let cout = circ.alloc_qubit(); - if direct { - - let fit = super::next_hyb_v_fit(); - let timeline_start = circ.active_timeline.len(); - let entry_active = circ.active_qubits; - let ops_start = circ.current_ops_len(); - let cin = (j != 0).then(|| &carries[j - 1]); - controlled_clean_add_threaded( - circ, - ctrl, - &a[lo..hi], - &b[lo..hi], - cin, - Some(&cout), - hi - lo, - ); - trace_schedule_fit( - "TRACE_TLM_HYB", - "HYB", - "direct-varchunk", - fit, - hi - lo, - hi - lo, - entry_active, - timeline_start, - ops_start, - circ, - ); - } else { - let cin: &QubitId = if j == 0 { - cin0.as_ref().expect("legacy cin0") - } else { - &carries[j - 1] - }; - controlled_vented_chunk_add(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, &cout); - } - carries.push(cout); - bounds.push((lo, hi)); - lo = hi; - } - if let Some(cin0) = cin0 { - circ.zero_and_free(cin0); - } - for j in (0..sizes.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_capped_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry, cap); - } else { - controlled_erase_carry_gated_capped(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry, cap); - } - } -} - -fn controlled_hybrid_add_knob_capped_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize) { - let n = a.len(); - if cap < n - && !varchunk_schedule(n, k).is_empty() - && (varchunk_cost(n, k, cap) as u64 + n as u64) < adaptive_add_cost_tof(n, k, true) - { - controlled_hybrid_add_varchunk_gated_refs(circ, ctrl, a, b, k, cap); - } else { - controlled_hybrid_add_adaptive_refs(circ, ctrl, a, b, k); - } -} - -pub fn controlled_hybrid_add_capped_branch(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize, branch: u8) { - let n = a.len(); - let k = super::target_qubit_headroom(circ).map_or(k, |headroom| k.min(headroom)); - if std::env::var("TLM_GCD_RESELECT_LAYOUT") - .ok() - .as_deref() - == Some("1") - { - controlled_hybrid_add_knob_capped_refs(circ, ctrl, a, b, k, cap); - return; - } - if branch == 1 && n > 0 && !varchunk_schedule(n, k).is_empty() { - controlled_hybrid_add_varchunk_gated_refs(circ, ctrl, a, b, k, cap); - } else if branch == 0 { - - controlled_hybrid_add_refs(circ, ctrl, a, b); - } else if branch == 255 { - - controlled_hybrid_add_knob_capped_refs(circ, ctrl, a, b, k, cap); - } else { - controlled_hybrid_add_adaptive_refs(circ, ctrl, a, b, k); - } -} - -pub fn controlled_hybrid_add_cout_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: &QubitId, k: usize) { - let fit = super::take_cout_fit(k); - let timeline_start = circ.active_timeline.len(); - let entry_active = circ.active_qubits; - let ops_start = circ.current_ops_len(); - let effective = super::target_qubit_headroom(circ) - .map_or(fit.selected, |headroom| fit.selected.min(headroom)); - controlled_hybrid_add_cout_refs_impl(circ, ctrl, a, b, cout, effective); - trace_schedule_fit( - "TRACE_TLM_COUT", - "COUT", - "dispatch", - fit, - effective, - a.len(), - entry_active, - timeline_start, - ops_start, - circ, - ); -} - -fn controlled_hybrid_add_cout_refs_impl(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: &QubitId, k: usize) { - let n = a.len(); - assert_eq!(b.len(), n, "controlled cout add: a,b width mismatch"); - assert!(n >= 1, "controlled cout add: empty operands"); - if let Some(layout) = searched_cout_layout(n, k) { - emit_cout_layout(circ, ctrl, a, b, cout, layout); - return; - } - let c = adaptive_chunk_size(n); - let lay = adaptive_layout_for_chunk(n, k, c); - let tight = k < n.div_ceil(c) + c + ADAPTIVE_RES; - let cov = (k.saturating_sub(2).saturating_mul(k.saturating_sub(1)) / 2).min(n); - if n > 4 && k.saturating_add(2 * c) < n && tight && cov > 2 * k { - controlled_chunked_then_cuccaro(circ, ctrl, a, b, Some(cout), k); - return; - } - if n <= 4 || k < n.div_ceil(c) + c + ADAPTIVE_RES || k.saturating_add(2 * c) >= n || lay.plain_len == 0 { - let zpad = circ.alloc_qubit(); - let mut aref: Vec<&QubitId> = a.to_vec(); - aref.push(cout); - let mut bref: Vec<&QubitId> = b.to_vec(); - bref.push(&zpad); - controlled_hybrid_add_refs(circ, ctrl, &aref, &bref); - circ.zero_and_free(zpad); - return; - } - let l = lay.chunked_len; - let mut bounds: Vec<(usize, usize)> = Vec::new(); - let mut lo = 0; - while lo < l { - let hi = (lo + lay.c).min(l); - bounds.push((lo, hi)); - lo = hi; - } - let mut carries: Vec = Vec::with_capacity(bounds.len()); - for (j, &(lo, hi)) in bounds.iter().enumerate() { - let cy = circ.alloc_qubit(); - let cin: Option<&QubitId> = if j == 0 { None } else { Some(&carries[j - 1]) }; - controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, Some(&cy), hi - lo); - carries.push(cy); - } - controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], carries.last(), Some(cout), lay.plain_len); - for j in (0..bounds.len()).rev() { - let (lo, hi) = bounds[j]; - let carry = carries.pop().expect("carry present"); - if j == 0 { - controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); - } else { - controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); - } - } -} + +use super::comparator::compare_geq_cin_middle; +use super::{B, BExt}; +use crate::circuit::QubitId; +use std::cell::{Cell, RefCell}; + +thread_local! { + static DIRTY_VENT_POOL: RefCell> = const { RefCell::new(Vec::new()) }; + static THREADED_ADD_CALL_INDEX: Cell = const { Cell::new(0) }; + static HYBRID_ADD_CALL_INDEX: Cell = const { Cell::new(0) }; + static ERASE_GATED_CALL_INDEX: Cell = const { Cell::new(0) }; + static ERASE_GATED_CAPPED_CALL_INDEX: Cell = const { Cell::new(0) }; +} + +pub(super) fn reset_gidney_call_index() { + THREADED_ADD_CALL_INDEX.with(|index| index.set(0)); + HYBRID_ADD_CALL_INDEX.with(|index| index.set(0)); + ERASE_GATED_CALL_INDEX.with(|index| index.set(0)); + ERASE_GATED_CAPPED_CALL_INDEX.with(|index| index.set(0)); +} + +fn next_threaded_add_call_index() -> usize { + THREADED_ADD_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_hybrid_add_call_index() -> usize { + HYBRID_ADD_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_erase_gated_call_index() -> usize { + ERASE_GATED_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +fn next_erase_gated_capped_call_index() -> usize { + ERASE_GATED_CAPPED_CALL_INDEX.with(|index| { + let current = index.get(); + index.set(current + 1); + current + }) +} + +const GIDNEY_THREAD_FWD_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (2591, 30, 30), + (2591, 52, 52), + (2591, 54, 253), + (5, 0, 123), + (1, 18, 18), + (1, 20, 121), + (0, 53, 122), + (4, 0, 65), + (3, 21, 21), + (3, 23, 65), + (2850, 0, 14), + (2851, 0, 13), + (2852, 0, 12), + (2853, 0, 11), + (2854, 0, 10), + (2334, 0, 9), + (2855, 0, 9), + (2865, 0, 9), + (2335, 3, 11), + (2856, 0, 8), + (2878, 3, 11), + (2337, 6, 13), + (2857, 0, 7), + (2909, 6, 13), + (2336, 5, 11), + (2858, 0, 6), + (2894, 5, 11), + (2338, 8, 13), + (2859, 0, 5), + (2925, 8, 13), + (2303, 7, 11), + (2339, 9, 13), + (2340, 10, 14), + (2860, 0, 4), + (2944, 9, 13), + (2964, 10, 14), + (2272, 10, 13), + (2341, 11, 14), + (2344, 14, 17), + (2602, 249, 252), + (2844, 9, 9), + (2844, 11, 13), + (2846, 8, 11), + (2861, 0, 3), + (2985, 11, 14), + (3007, 12, 15), + (62, 52, 55), + (68, 53, 56), + (74, 54, 57), + (80, 51, 54), + (86, 52, 55), + (92, 53, 56), + (98, 50, 53), + (104, 52, 54), + (110, 53, 55), + (116, 50, 52), + (122, 51, 53), + (128, 52, 54), + (134, 49, 51), + (140, 50, 52), + (146, 51, 53), + (152, 48, 50), + (158, 49, 51), + (164, 50, 52), + (170, 47, 49), + (182, 49, 51), + (2256, 11, 13), + (2287, 9, 11), + (2316, 7, 9), + (2332, 6, 8), + (2342, 13, 15), + (2343, 14, 16), + (2358, 29, 31), + (2601, 251, 253), + (2603, 249, 251), + (2604, 248, 250), + (2605, 247, 249), + (2606, 246, 248), + (2607, 245, 247), + (2613, 239, 241), + (2843, 11, 13), + (2845, 9, 11), + (2847, 7, 9), + (2848, 6, 8), + (2862, 0, 2), + (3030, 14, 16), + (3052, 15, 17), + (56, 51, 53), +]; + +const GIDNEY_THREAD_SUM_DEAD_RANGES: &[(usize, usize, usize)] = &[ + (2334, 0, 10), + (2865, 0, 10), + (2335, 3, 12), + (2878, 3, 12), + (2337, 6, 14), + (2909, 6, 14), + (2336, 5, 12), + (2894, 5, 12), + (2338, 8, 14), + (2925, 8, 14), + (2339, 9, 14), + (2340, 10, 15), + (2844, 9, 14), + (2944, 9, 14), + (2964, 10, 15), + (2256, 10, 14), + (2272, 10, 14), + (2332, 5, 9), + (2341, 11, 15), + (2344, 14, 18), + (2602, 249, 253), + (2846, 8, 12), + (2985, 11, 15), + (3007, 12, 16), + (128, 51, 54), + (2287, 9, 12), + (2303, 9, 12), + (2316, 7, 10), + (2342, 13, 16), + (2343, 14, 17), + (2358, 29, 32), + (2601, 251, 254), + (2604, 248, 251), + (2605, 247, 250), + (2606, 246, 249), + (2607, 245, 248), + (2613, 239, 242), + (2843, 11, 14), + (2845, 9, 12), + (2847, 7, 10), + (2848, 6, 9), + (2849, 6, 9), + (3030, 14, 17), + (3052, 15, 18), + (3185, 22, 25), + (62, 52, 55), + (68, 53, 56), + (74, 54, 57), + (80, 51, 54), + (86, 52, 55), + (92, 53, 56), + (98, 50, 53), + (104, 52, 54), + (110, 53, 55), + (116, 50, 52), + (122, 51, 53), + (140, 50, 52), + (146, 51, 53), + (152, 48, 50), + (158, 49, 51), + (164, 50, 52), + (170, 47, 49), + (182, 49, 51), + (2217, 13, 15), + (2237, 12, 14), + (2345, 16, 18), + (2346, 17, 19), + (2354, 26, 28), + (2355, 27, 29), + (2356, 28, 30), + (2357, 29, 31), + (2359, 31, 33), + (2360, 32, 34), + (2361, 33, 35), + (2362, 34, 36), + (2363, 35, 37), + (2364, 36, 38), + (2365, 37, 39), + (2368, 40, 42), + (2370, 42, 44), + (2599, 252, 254), + (2600, 252, 254), + (2608, 245, 247), + (2609, 244, 246), + (2611, 242, 244), + (2612, 241, 243), + (2614, 239, 241), + (2615, 238, 240), + (2617, 236, 238), + (2618, 235, 237), + (2620, 233, 235), + (2621, 232, 234), + (2626, 227, 229), + (2627, 226, 228), + (2838, 15, 17), + (2839, 14, 16), + (2841, 13, 15), + (2842, 12, 14), + (3069, 16, 18), + (3084, 17, 19), + (3098, 17, 19), + (3201, 24, 26), + (3216, 25, 27), + (3232, 24, 26), + (3247, 25, 27), + (3261, 26, 28), + (3290, 26, 28), + (3304, 27, 29), + (3318, 26, 28), + (3332, 27, 29), + (3350, 28, 30), + (3364, 27, 29), + (3397, 29, 31), + (3415, 28, 30), + (3430, 29, 31), + (3444, 30, 32), + (3459, 29, 31), + (56, 51, 53), +]; + +const GIDNEY_THREAD_BOUNDARY_DEAD_CALLS: &[usize] = &[ + 0, + 1, + 1002, + 1010, + 1018, + 1026, + 1034, + 104, + 1043, + 1060, + 1069, + 1078, + 1087, + 1096, + 110, + 1105, + 1114, + 1123, + 1132, + 1141, + 1150, + 116, + 1168, + 1177, + 1186, + 1195, + 1204, + 1213, + 122, + 1222, + 1231, + 1240, + 1249, + 1258, + 1259, + 1268, + 1278, + 128, + 1287, + 1296, + 1297, + 1306, + 1307, + 1325, + 1334, + 1335, + 1344, + 1353, + 1362, + 1371, + 1380, + 1389, + 1399, + 14, + 140, + 1408, + 1418, + 1428, + 1438, + 1448, + 1458, + 146, + 1468, + 1478, + 1488, + 1498, + 1508, + 152, + 158, + 164, + 170, + 176, + 182, + 188, + 194, + 2, + 20, + 200, + 206, + 212, + 218, + 224, + 230, + 236, + 242, + 248, + 254, + 26, + 260, + 266, + 272, + 278, + 284, + 2850, + 2851, + 2852, + 2853, + 2854, + 2855, + 2856, + 2857, + 2858, + 2859, + 2860, + 2861, + 2862, + 2863, + 2864, + 290, + 296, + 302, + 308, + 314, + 32, + 320, + 326, + 333, + 339, + 346, + 353, + 360, + 367, + 3674, + 3684, + 3694, + 3704, + 3714, + 3724, + 3734, + 374, + 3744, + 3754, + 3764, + 3774, + 3783, + 3793, + 38, + 3802, + 381, + 3811, + 3820, + 3829, + 3838, + 3847, + 3848, + 3857, + 3866, + 3876, + 388, + 3886, + 3895, + 3905, + 3915, + 3924, + 3934, + 3943, + 395, + 3952, + 3961, + 3970, + 3979, + 3988, + 3997, + 4006, + 4015, + 402, + 4024, + 4033, + 4042, + 4051, + 4060, + 4069, + 4078, + 4087, + 409, + 4096, + 4105, + 4114, + 4123, + 4132, + 4140, + 4149, + 4157, + 416, + 4165, + 4173, + 4181, + 4189, + 4197, + 4205, + 4213, + 4221, + 4229, + 423, + 4237, + 4245, + 4253, + 4261, + 4269, + 4277, + 4285, + 4293, + 430, + 4301, + 4309, + 4317, + 4325, + 4333, + 4341, + 4349, + 4357, + 4365, + 437, + 4373, + 4389, + 4397, + 44, + 4404, + 4412, + 4420, + 4428, + 4436, + 444, + 4444, + 4451, + 4459, + 4466, + 4480, + 4487, + 4494, + 4501, + 4508, + 451, + 4515, + 4522, + 4529, + 4543, + 4550, + 4557, + 4564, + 4571, + 4578, + 458, + 4585, + 4592, + 4599, + 4606, + 4613, + 4620, + 4627, + 4634, + 4641, + 4648, + 465, + 4655, + 4662, + 4669, + 4676, + 4683, + 4690, + 4697, + 4704, + 4711, + 4718, + 472, + 4725, + 4732, + 4739, + 4746, + 4753, + 4760, + 4767, + 4774, + 4781, + 4788, + 479, + 4795, + 4802, + 4809, + 4816, + 4823, + 4830, + 4837, + 4844, + 4850, + 4857, + 486, + 4863, + 4869, + 4875, + 4881, + 4887, + 4893, + 4899, + 4905, + 4911, + 4917, + 4923, + 4929, + 493, + 4935, + 4941, + 4947, + 4953, + 4959, + 4965, + 4971, + 4977, + 4983, + 4989, + 4995, + 50, + 500, + 5001, + 5007, + 5013, + 5019, + 5025, + 5031, + 5037, + 5043, + 5049, + 5055, + 5061, + 5067, + 507, + 5073, + 5079, + 5085, + 5091, + 5097, + 5103, + 5109, + 5115, + 5121, + 514, + 521, + 528, + 535, + 542, + 549, + 556, + 56, + 563, + 570, + 577, + 584, + 591, + 598, + 605, + 612, + 619, + 62, + 626, + 633, + 640, + 647, + 654, + 661, + 668, + 675, + 68, + 682, + 689, + 696, + 703, + 710, + 717, + 724, + 732, + 739, + 74, + 747, + 755, + 763, + 771, + 779, + 786, + 794, + 8, + 80, + 802, + 810, + 818, + 826, + 834, + 842, + 850, + 86, + 866, + 874, + 882, + 890, + 898, + 906, + 914, + 92, + 922, + 930, + 938, + 946, + 954, + 962, + 970, + 978, + 98, + 986, + 994, +]; + +const GIDNEY_THREAD_FWD_REMAINDER_KEYS: &[u32] = &[ + 521, 9767, 11304, 11305, 12846, 12847, 45105, 45106, 48175, 48176, 49712, 49713, + 51249, 51250, 52782, 52783, 54319, 54320, 55856, 55857, 57389, 57390, 58926, 58927, + 60463, 60464, 61996, 61997, 63533, 63534, 65070, 65071, 66603, 66604, 68140, 68141, + 69677, 69678, 71210, 71211, 72747, 72748, 74284, 74285, 75817, 75818, 77354, 77355, + 78892, 80424, 80425, 81961, 81962, 83498, 83499, 85287, 85288, 86824, 86825, 88618, + 90407, 92200, 93992, 93993, 95781, 95782, 97575, 99368, 101156, 101157, 102950, 104742, + 104743, 106532, 108324, 108325, 110118, 111907, 113699, 113700, 115493, 117282, 119075, 120868, + 122657, 124450, 126243, 128032, 129825, 131618, 133406, 133407, 135200, 136993, 138782, 140575, + 142368, 144156, 144157, 145950, 147743, 149532, 151325, 153118, 154911, 154912, 156704, 156705, + 158493, 160282, 162075, 163868, 165657, 167454, 167455, 169243, 171036, 171037, 172830, 174622, + 174623, 176406, 176407, 178204, 178205, 179997, 179998, 181782, 183579, 183580, 185372, 185373, + 187417, 187418, 189210, 189211, 191259, 191260, 193305, 195353, 195354, 197398, 201236, 203285, + 205330, 207383, 207384, 209432, 209433, 211477, 211478, 213522, 215576, 217620, 217621, 219669, + 219670, 221718, 221719, 223763, 223764, 225812, 225813, 227861, 227862, 229907, 231956, 234000, + 236045, 240143, 242188, 244237, 246291, 248335, 248336, 250384, 250385, 252429, 254478, 254479, + 256523, 260617, 262665, 262666, 264715, 267016, 269065, 271370, 273671, 275976, 278281, 280582, + 282887, 285192, 287493, 289798, 294404, 296709, 299014, 301314, 301315, 303620, 305925, 308226, + 310531, 312836, 319747, 324609, 327170, 331817, 334593, 336936, 339240, 344102, 346406, 348710, + 351012, 353316, 355620, 358178, 360482, 363042, 365600, 368160, 370720, 373278, 375837, 375838, + 378398, 380956, 383516, 386076, 397092, 402722, 411681, 427296, 430623, 441118, 444959, 456990, + 460829, 465436, 480796, 484379, 491803, 495386, 503322, 511256, 545041, 550672, 556559, 562190, + 567565, 567566, 572684, 572685, 600336, 600337, 600593, 600594, 600850, 601364, 601621, 601878, + 602394, 602650, 602651, 602907, 602908, 603164, 603165, 603421, 603422, 603935, 603936, 604192, + 604193, 604449, 604450, 604706, 604707, 604963, 604964, 605220, 605221, 605478, 605735, 605992, + 606249, 606506, 608048, 626553, 638889, 665341, 665596, 665597, 665852, 665853, 667893, 667894, + 668148, 668149, 668404, 668658, 668659, 668913, 668914, 669423, 669424, 669678, 669679, 669933, + 669934, 670188, 670189, 670443, 670444, 670698, 670699, 670953, 670954, 671208, 671209, 671464, + 671718, 671719, 671974, 672229, 672483, 672484, 672738, 672739, 672994, 673249, 673504, 673759, + 674014, 674269, 674524, 674779, 675034, 675544, 675799, 676054, 676309, 676819, 677074, 677329, + 678604, 679114, 679624, 680644, 680899, 687530, 687785, 689315, 689825, 690080, 690845, 691100, + 691610, 691865, 692120, 692630, 692885, 693140, 694670, 694925, 695180, 695690, 695945, 696200, + 696455, 696710, 696965, 697475, 697730, 699515, 700025, 700279, 700535, 707419, 708439, 709969, + 710224, 710479, 710989, 711499, 712264, 713284, 714304, 714559, 716089, 716344, 716599, 717364, + 717619, 718384, 718639, 719404, 720424, 720934, 721189, 721954, 722464, 722974, 723229, 723484, + 723739, 723994, 726289, 726543, 726544, 726799, 727054, 727309, 727310, 727564, 727565, 785680, + 785681, 789521, 789522, 793105, 793106, 796435, 799764, 803093, 806422, 810775, 815383, 815384, + 819480, 819481, 823321, 823322, 827416, 827417, 831257, 831258, 834842, 834843, 838682, 842266, + 842267, 845851, 845852, 849434, 849435, 853019, 853020, 857628, 857629, 861211, 861212, 865821, + 869661, 869662, 874268, 874269, 878109, 878110, 881694, 885533, 885534, 889119, 892447, 892448, + 896030, 896031, 955936, 958496, 961056, 963618, 973348, 975652, 985088, 992257, 1020933, 1023236, + 1032452, 1043975, 1046278, 1055498, 1059848, 1070347, 1072399, 1074445, 1076496, 1076497, 1078544, 1080595, + 1092880, 1094932, 1096979, 1099030, 1101077, 1103124, 1105175, 1107222, 1109269, 1115414, 1117465, 1131546, + 1133593, 1135643, 1135644, 1137691, 1139482, 1143324, 1146910, 1152287, 1154078, 1155869, 1159455, 1170209, + 1172000, 1195298, 1198880, 1222183, 1223974, 1227560, 1229351, 1248044, 1251114, 1255723, 1257262, 1260332, + 1261871, 1263406, 1272624, 1274159, 1275698, 1278768, 1280307, 1284916, 1294134, 1298743, 1301813, 1303352, +]; + +const GIDNEY_THREAD_SUM_REMAINDER_KEYS: &[u32] = &[ + 9767, 11304, 11305, 12846, 12847, 45105, 45106, 48175, 48176, 49712, 49713, 51249, + 51250, 52782, 52783, 54319, 54320, 55856, 55857, 57389, 57390, 58926, 58927, 60463, + 60464, 61996, 61997, 63533, 63534, 65070, 65071, 66604, 68140, 68141, 69677, 69678, + 71210, 71211, 72747, 72748, 74284, 74285, 75817, 75818, 77354, 77355, 78892, 80424, + 80425, 81961, 81962, 83498, 83499, 85287, 85288, 86824, 86825, 88617, 88618, 90407, + 92200, 93993, 95781, 95782, 97575, 99368, 101156, 101157, 102950, 104742, 104743, 106532, + 108324, 108325, 110118, 111907, 113699, 113700, 117282, 120868, 122657, 124450, 126243, 128032, + 129825, 131618, 133406, 133407, 135200, 136993, 138782, 140575, 142368, 144156, 144157, 145950, + 147743, 149532, 151325, 153118, 154911, 154912, 156704, 156705, 158493, 160282, 162075, 163868, + 165657, 167454, 167455, 169243, 171036, 171037, 172830, 174622, 174623, 176406, 176407, 178204, + 178205, 179997, 179998, 181782, 183579, 183580, 185372, 185373, 187417, 187418, 189210, 189211, + 191259, 191260, 193305, 195353, 195354, 197398, 201236, 203285, 205330, 207383, 207384, 209433, + 211477, 211478, 213522, 215576, 217620, 217621, 221718, 221719, 223763, 223764, 225812, 225813, + 227861, 227862, 229907, 231956, 234000, 236045, 240143, 242188, 246291, 248336, 250384, 250385, + 252429, 254478, 254479, 256523, 260617, 262666, 264715, 267016, 271370, 273671, 275975, 275976, + 278281, 280582, 282887, 285192, 287492, 287493, 289798, 294403, 294404, 299014, 301314, 301315, + 305925, 308226, 310531, 312836, 315137, 317442, 319747, 322304, 324609, 327170, 331817, 332032, + 334592, 334593, 339240, 341760, 344102, 346406, 348710, 351012, 353316, 355620, 358178, 360482, + 363042, 365600, 368160, 370720, 373278, 375837, 375838, 378398, 380956, 383516, 386076, 388902, + 391461, 394276, 397093, 399907, 399908, 402722, 405796, 408610, 408611, 411682, 414755, 441118, + 441119, 444959, 444960, 448543, 452382, 456990, 456991, 460829, 460830, 465436, 465437, 469021, + 469022, 473629, 477212, 480796, 480797, 484379, 484380, 487963, 491803, 491804, 495386, 495387, + 499226, 503322, 503323, 507162, 511256, 511257, 523286, 536851, 540690, 545041, 545042, 550672, + 550673, 556559, 556560, 562190, 562191, 600850, 600851, 601108, 601364, 601365, 601621, 601622, + 601878, 601879, 602136, 602394, 602395, 605735, 605736, 605992, 605993, 606506, 606507, 607020, + 607021, 608820, 609077, 609333, 609334, 610362, 610619, 610876, 611133, 612161, 612418, 612675, + 613703, 613960, 614217, 614474, 614731, 615245, 615759, 616273, 616530, 616787, 617044, 618072, + 618329, 618586, 619100, 619614, 620128, 620642, 620899, 621413, 621670, 621927, 622184, 622441, + 622955, 623212, 623469, 623983, 625268, 625525, 625782, 626039, 626040, 626553, 626554, 627068, + 628867, 629123, 629124, 629381, 629638, 629895, 630152, 630409, 630666, 630923, 631437, 631693, + 631694, 633493, 633750, 634007, 634264, 634521, 635549, 635806, 636320, 636834, 637348, 638118, + 638889, 638890, 639147, 639917, 640431, 640688, 641202, 641716, 642487, 642744, 643001, 643258, + 643772, 644029, 644286, 644543, 645057, 645314, 645828, 646856, 647113, 647627, 648141, 648398, + 648912, 649169, 649426, 649939, 649940, 650197, 650454, 650711, 651225, 651482, 653281, 653538, + 653795, 654052, 654823, 655594, 656622, 656879, 657907, 660477, 665086, 665341, 665342, 668404, + 668405, 670699, 670700, 671464, 671465, 671719, 671720, 671974, 671975, 672229, 672230, 672994, + 672995, 673249, 673250, 673504, 673505, 673759, 673760, 674014, 674015, 674269, 674270, 674524, + 674525, 674779, 674780, 675034, 675035, 675290, 675544, 675545, 675799, 675800, 676054, 676055, + 676309, 676310, 676565, 676819, 676820, 677074, 677075, 677329, 677330, 677585, 677840, 678095, + 678350, 678604, 678605, 678860, 679114, 679115, 679370, 679624, 679625, 679880, 680135, 680390, + 680900, 681155, 681410, 681665, 681920, 682175, 682430, 682685, 682940, 683195, 683705, 683960, + 684214, 684215, 684470, 684980, 685235, 685490, 685745, 686000, 686255, 686510, 686765, 687020, + 687275, 687530, 687531, 687785, 687786, 688040, 688295, 688550, 688805, 689060, 689315, 689316, + 689570, 689825, 689826, 690080, 690081, 690336, 690590, 690845, 690846, 691100, 691101, 691355, + 691610, 691611, 691865, 691866, 692120, 692121, 692376, 692630, 692631, 692885, 692886, 693140, + 693141, 693395, 693650, 693905, 694160, 694415, 694671, 694925, 694926, 695180, 695181, 695435, + 695690, 695691, 695945, 695946, 696200, 696201, 696455, 696456, 696710, 696711, 696965, 696966, + 697475, 697476, 697730, 697984, 697985, 698495, 698750, 699005, 699260, 699515, 699516, 699770, + 699771, 700025, 700026, 700279, 700280, 700535, 700790, 701045, 701300, 701555, 701810, 702065, + 702575, 702830, 703085, 703340, 703595, 703850, 704105, 704360, 704615, 704869, 704870, 705125, + 705380, 705635, 706145, 706400, 706655, 706910, 707165, 707675, 707930, 708185, 708439, 708440, + 708950, 709205, 709460, 709715, 710224, 710225, 710479, 710480, 710735, 710989, 710990, 711245, + 711499, 711500, 711755, 712010, 712264, 712265, 712520, 712775, 713030, 713285, 713794, 713795, + 714050, 714305, 714560, 714815, 715070, 715325, 715580, 716089, 716090, 716344, 716345, 716599, + 716600, 716855, 717109, 717110, 717364, 717365, 717619, 717620, 717875, 719404, 719405, 719660, + 719915, 720170, 720424, 720425, 720680, 720934, 720935, 721189, 721190, 721445, 721700, 721954, + 721955, 722210, 722464, 722465, 722720, 722974, 722975, 723229, 723230, 723484, 723485, 723739, + 723740, 723994, 723995, 724503, 724758, 725013, 725268, 725779, 726034, 726289, 726290, 727054, + 727055, 796435, 796436, 799764, 799765, 803093, 803094, 806422, 806423, 810775, 810776, 838682, + 838683, 865821, 865822, 905761, 908834, 911907, 914978, 918051, 923939, 926756, 929573, 932388, + 935205, 950814, 955936, 958496, 961056, 963618, 973348, 975652, 985088, 987432, 992257, 997162, + 1014020, 1020933, 1023236, 1032452, 1041672, 1043975, 1046278, 1055498, 1059848, 1064202, 1068300, 1070347, + 1072399, 1074445, 1076496, 1076497, 1078544, 1080595, 1092880, 1094932, 1096979, 1099030, 1101076, 1101077, + 1103124, 1105175, 1107221, 1107222, 1109269, 1115414, 1117465, 1131546, 1133592, 1133593, 1135643, 1135644, + 1137690, 1137691, 1139482, 1143324, 1146910, 1152287, 1154078, 1155869, 1159455, 1170209, 1171999, 1172000, + 1193503, 1195298, 1197089, 1198880, 1222183, 1223974, 1227560, 1229351, 1244970, 1248044, 1251114, 1252653, + 1255723, 1257262, 1260332, 1261871, 1263406, 1272624, 1274159, 1275698, 1278768, 1280307, 1284916, 1292595, + 1294134, 1298743, 1301813, 1303352, 1304887, +]; + +fn gidney_structural_dead_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_STRUCTURAL_DEAD_CALLS").is_some() +} + +fn gidney_skip_top2_thread_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_TOP2_THREAD").is_some() +} + +fn gidney_skip_fullvent_top2_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_FULLVENT_TOP2").is_some() +} + +fn gidney_skip_exact_remainder_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_EXACT_REMAINDER").is_some() +} + +fn gidney_skip_exact_fwd_remainder_enabled() -> bool { + gidney_skip_exact_remainder_enabled() + || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_FWD_REMAINDER").is_some() +} + +fn gidney_skip_exact_sum_remainder_enabled() -> bool { + gidney_skip_exact_remainder_enabled() + || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_SUM_REMAINDER").is_some() +} + +fn gidney_skip_exact_erase_ccz_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_CCZ").is_some() + || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ").is_some() +} + +fn gidney_skip_exact_erase_capped_ccz_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_ALL_CCZ").is_some() + || std::env::var_os("TLM_GIDNEY_SKIP_EXACT_ERASE_CAPPED_CCZ").is_some() +} + +fn gidney_skip_small_residual_enabled() -> bool { + std::env::var_os("TLM_GIDNEY_SKIP_SMALL_RESIDUAL_DEAD").is_some() +} + +fn gidney_key(call_index: usize, bit: usize) -> u32 { + (((call_index as u32) & 0xffff) << 8) | (bit as u32 & 0xff) +} + +const GIDNEY_THREAD_BOUNDARY_RESIDUAL_CALLS: &[usize] = &[ + 134, 858, 1051, 1159, 1316, 3885, 3923, 4381, 4473, 4536, 5127, +]; + +const GIDNEY_ERASE_CCZ_RESIDUAL_CALLS: &[usize] = &[ + 2418, 2425, 2431, 2444, 2522, 2552, 2591, 2641, 2646, 2727, +]; + +const GIDNEY_ERASE_CAPPED_CCZ_RESIDUAL_CALLS: &[usize] = &[ + 15, 595, 605, 607, 626, 801, 807, 834, 849, 867, 870, 876, 888, 897, 903, + 909, 933, 939, 942, 957, 960, 975, 996, 999, 1002, 1035, 1047, 1056, 1071, + 1089, 1095, 1107, 1116, 1128, 1137, +]; + +const GIDNEY_ERASE_CCZ_REMAINDER_CALLS: &[usize] = &[ + 0, 1, 2, 308, 320, 337, 370, 379, 384, 389, 394, 399, 404, 409, 414, 419, + 424, 429, 434, 439, 444, 449, 454, 460, 465, 471, 477, 483, 489, 495, 501, 507, + 513, 519, 531, 537, 543, 549, 555, 561, 567, 573, 579, 585, 591, 597, 604, 610, + 617, 630, 637, 656, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, + 1528, 1529, 1530, 1531, 1532, 2379, 2398, 2405, 2450, 2456, 2462, 2468, 2474, + 2480, 2498, 2504, 2510, 2516, 2528, 2534, 2540, 2558, 2564, 2575, 2581, 2586, + 2596, 2601, 2606, 2611, 2616, 2621, 2626, 2651, 2656, 2665, +]; + +const GIDNEY_ERASE_CAPPED_CCZ_REMAINDER_CALLS: &[usize] = &[ + 1, 2, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, + 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, + 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, + 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, + 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, + 234, 237, 240, 243, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, + 276, 279, 282, 285, 288, 291, 294, 297, 300, 303, 306, 309, 312, 315, + 318, 321, 324, 327, 330, 333, 336, 339, 342, 345, 348, 351, 357, 360, + 366, 369, 372, 378, 381, 384, 387, 390, 393, 396, 402, 537, 542, 544, + 547, 549, 551, 553, 555, 557, 559, 561, 563, 565, 567, 569, 571, 573, + 575, 577, 579, 581, 583, 585, 587, 589, 591, 593, 597, 599, 601, 603, + 609, 611, 613, 615, 617, 619, 624, 634, 765, 771, 774, 777, 780, 783, + 786, 789, 795, 798, 816, 819, 822, 825, 828, 831, 837, 843, 846, 852, + 855, 858, 864, 879, 882, 885, 891, 900, 906, 912, 915, 921, 924, 927, + 930, 936, 945, 951, 954, 963, 969, 972, 978, 981, 984, 987, 990, 993, + 1005, 1008, 1011, 1014, 1017, 1020, 1023, 1026, 1029, 1032, 1038, 1041, + 1044, 1050, 1053, 1059, 1062, 1065, 1068, 1074, 1077, 1080, 1083, 1086, + 1092, 1098, 1101, 1104, 1110, 1113, 1119, 1122, 1125, 1131, +]; + +fn gidney_erase_ccz_has_exact_dead_call(call_index: usize) -> bool { + if gidney_skip_small_residual_enabled() + && GIDNEY_ERASE_CCZ_RESIDUAL_CALLS + .binary_search(&call_index) + .is_ok() + { + return true; + } + gidney_skip_exact_erase_ccz_enabled() + && GIDNEY_ERASE_CCZ_REMAINDER_CALLS + .binary_search(&call_index) + .is_ok() +} + +fn gidney_erase_capped_ccz_has_exact_dead_call(call_index: usize) -> bool { + if gidney_skip_small_residual_enabled() + && GIDNEY_ERASE_CAPPED_CCZ_RESIDUAL_CALLS + .binary_search(&call_index) + .is_ok() + { + return true; + } + gidney_skip_exact_erase_capped_ccz_enabled() + && GIDNEY_ERASE_CAPPED_CCZ_REMAINDER_CALLS + .binary_search(&call_index) + .is_ok() +} + +fn threaded_add_call_has_structurally_dead_forward( + call_index: usize, + bit: usize, + total: usize, + width: usize, + vents: usize, +) -> bool { + if gidney_skip_exact_fwd_remainder_enabled() + && GIDNEY_THREAD_FWD_REMAINDER_KEYS + .binary_search(&gidney_key(call_index, bit)) + .is_ok() + { + return true; + } + if gidney_skip_fullvent_top2_enabled() && vents >= width && bit + 2 >= width { + return true; + } + if gidney_skip_top2_thread_enabled() && bit + 2 >= total { + return true; + } + gidney_structural_dead_enabled() + && GIDNEY_THREAD_FWD_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +fn threaded_add_call_has_structurally_dead_boundary(call_index: usize) -> bool { + if gidney_skip_small_residual_enabled() + && GIDNEY_THREAD_BOUNDARY_RESIDUAL_CALLS + .binary_search(&call_index) + .is_ok() + { + return true; + } + gidney_structural_dead_enabled() && GIDNEY_THREAD_BOUNDARY_DEAD_CALLS.contains(&call_index) +} + +fn threaded_add_call_has_structurally_dead_sum( + call_index: usize, + bit: usize, + total: usize, + width: usize, + vents: usize, +) -> bool { + if gidney_skip_exact_sum_remainder_enabled() + && GIDNEY_THREAD_SUM_REMAINDER_KEYS + .binary_search(&gidney_key(call_index, bit)) + .is_ok() + { + return true; + } + if gidney_skip_fullvent_top2_enabled() && vents >= width && bit + 2 >= width { + return true; + } + if gidney_skip_top2_thread_enabled() && bit + 2 >= total { + return true; + } + gidney_structural_dead_enabled() + && GIDNEY_THREAD_SUM_DEAD_RANGES + .iter() + .any(|&(call, lo, hi)| call == call_index && (lo..=hi).contains(&bit)) +} + +pub fn with_dirty_vent_pool(dirty: &[QubitId], body: impl FnOnce() -> R) -> R { + let count = std::env::var("TLM_DIRTY_VENTS") + .ok() + .and_then(|value| value.parse::().ok()) + .unwrap_or(0) + .min(dirty.len()); + let prior = DIRTY_VENT_POOL.with(|pool| { + std::mem::replace(&mut *pool.borrow_mut(), dirty[..count].to_vec()) + }); + let result = body(); + DIRTY_VENT_POOL.with(|pool| { + *pool.borrow_mut() = prior; + }); + result +} + +fn dirty_vent_pool() -> Vec { + DIRTY_VENT_POOL.with(|pool| pool.borrow().clone()) +} + +fn trace_schedule_fit( + trace_env: &str, + family: &str, + mode: &str, + fit: super::ScheduleFit, + effective: usize, + width: usize, + entry_active: u32, + timeline_start: usize, + ops_start: usize, + circ: &B, +) { + if std::env::var_os(trace_env).is_none() { + return; + } + let local_peak = circ.active_timeline[timeline_start..] + .iter() + .map(|(_, active)| *active) + .max() + .unwrap_or(entry_active); + eprintln!( + "TLM_{family} call={} phase={} mode={} width={} base={} selected={} effective={} entry_active={} local_peak={} ops_added={} ops={}", + fit.call_index, + circ.phase, + mode, + width, + fit.base, + fit.selected, + effective, + entry_active, + local_peak, + circ.current_ops_len().saturating_sub(ops_start), + circ.current_ops_len(), + ); +} + +pub fn controlled_hybrid_add_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId]) { + controlled_hybrid_add_refs_impl(circ, ctrl, a, b, false); +} + +fn controlled_hybrid_add_refs_skiplow(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId]) { + controlled_hybrid_add_refs_impl(circ, ctrl, a, b, true); +} + +fn controlled_hybrid_add_refs_impl(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], skip_low_ctrl_sum: bool) { + let n = a.len(); + assert_eq!(b.len(), n, "controlled_hybrid_add: a, b must match width"); + if n == 0 { + return; + } + if n == 1 { + circ.ccx(*ctrl, *b[0], *a[0]); + return; + } + let call_index = next_hybrid_add_call_index(); + + let fit = super::next_hyb_v_fit(); + let timeline_start = circ.active_timeline.len(); + let entry_active = circ.active_qubits; + let ops_start = circ.current_ops_len(); + let vents = super::target_qubit_headroom(circ) + .map_or(fit.selected, |headroom| fit.selected.min(headroom)); + + for i in 1..n { + circ.cx(*b[i], *a[i]); + } + for i in (1..n - 1).rev() { + circ.cx(*b[i], *b[i + 1]); + } + + #[derive(Clone, Copy)] + enum VentLane { + Clean(QubitId), + Dirty(QubitId), + } + let dirty_pool = dirty_vent_pool(); + let mut vent_ancs: Vec> = (0..n - 1).map(|_| None).collect(); + for i in 0..n - 1 { + if i < vents { + if let Some(&dirty) = dirty_pool.get(i) { + debug_assert_ne!(dirty, *a[i]); + debug_assert_ne!(dirty, *b[i]); + debug_assert_ne!(dirty, *b[i + 1]); + circ.cx(dirty, *b[i + 1]); + let old_context = crate::point_add::set_op_trace_context( + 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], dirty); + crate::point_add::restore_op_trace_context(old_context); + circ.cx(dirty, *b[i + 1]); + vent_ancs[i] = Some(VentLane::Dirty(dirty)); + } else { + let anc = circ.alloc_qubit(); + let old_context = crate::point_add::set_op_trace_context( + 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], anc); + crate::point_add::restore_op_trace_context(old_context); + circ.cx(anc, *b[i + 1]); + vent_ancs[i] = Some(VentLane::Clean(anc)); + } + } else { + let old_context = crate::point_add::set_op_trace_context( + 0x1600_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], *b[i + 1]); + crate::point_add::restore_op_trace_context(old_context); + } + } + + for i in (0..n - 1).rev() { + let old_context = crate::point_add::set_op_trace_context( + 0x1700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*ctrl, *b[i + 1], *a[i + 1]); + crate::point_add::restore_op_trace_context(old_context); + if let Some(lane) = vent_ancs[i].take() { + match lane { + VentLane::Clean(anc) => { + circ.cx(anc, *b[i + 1]); + let bit = circ.alloc_bit(); + circ.hmr(anc, bit); + circ.zero_and_free(anc); + circ.cz_if_bit(*a[i], *b[i], bit); + } + VentLane::Dirty(dirty) => { + circ.cx(dirty, *b[i + 1]); + let old_context = crate::point_add::set_op_trace_context( + 0x1800_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], dirty); + crate::point_add::restore_op_trace_context(old_context); + circ.cx(dirty, *b[i + 1]); + } + } + } else { + let old_context = crate::point_add::set_op_trace_context( + 0x1900_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], *b[i + 1]); + crate::point_add::restore_op_trace_context(old_context); + } + } + + for i in 1..n - 1 { + circ.cx(*b[i], *b[i + 1]); + } + if !skip_low_ctrl_sum { + let old_context = crate::point_add::set_op_trace_context( + 0x1a00_0000 | (((call_index as u32) & 0xffff) << 8), + ); + circ.ccx(*ctrl, *b[0], *a[0]); + crate::point_add::restore_op_trace_context(old_context); + } + for i in 1..n { + circ.cx(*b[i], *a[i]); + } + trace_schedule_fit( + "TRACE_TLM_HYB", + "HYB", + if skip_low_ctrl_sum { "skiplow" } else { "plain" }, + fit, + vents, + n, + entry_active, + timeline_start, + ops_start, + circ, + ); +} + +fn controlled_clean_add_threaded( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + cin: Option<&QubitId>, + cout: Option<&QubitId>, + vents: usize, +) { + let call_index = next_threaded_add_call_index(); + let ops_start = circ.current_ops_len(); + let s = a.len(); + if s == 0 { + if let (Some(ci), Some(co)) = (cin, cout) { + circ.ccx(*ctrl, *ci, *co); + } + return; + } + let n_inner = if cout.is_some() { s } else { s - 1 }; + let mut inner: Vec> = (0..n_inner).map(|_| Some(circ.alloc_qubit())).collect(); + let produces = |i: usize| cout.is_some() || i + 1 < s; + + for i in 0..s { + if !produces(i) { + continue; + } + let co = inner[i].as_ref().unwrap(); + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, *a[i]); + circ.cx(*ci, *b[i]); + if !threaded_add_call_has_structurally_dead_forward(call_index, i, n_inner, s, vents) { + let old_context = crate::point_add::set_op_trace_context( + 0x0500_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], *co); + crate::point_add::restore_op_trace_context(old_context); + } + circ.cx(*ci, *co); + } else { + if !threaded_add_call_has_structurally_dead_forward(call_index, i, n_inner, s, vents) { + let old_context = crate::point_add::set_op_trace_context( + 0x0500_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*a[i], *b[i], *co); + crate::point_add::restore_op_trace_context(old_context); + } + } + } + + if let Some(cout) = cout { + let old_context = crate::point_add::set_op_trace_context( + 0x0600_0000 | (((call_index as u32) & 0xffff) << 8) | ((s.saturating_sub(1)) as u32 & 0xff), + ); + if !threaded_add_call_has_structurally_dead_boundary(call_index) { + circ.ccx(*ctrl, *inner[s - 1].as_ref().unwrap(), *cout); + } + crate::point_add::restore_op_trace_context(old_context); + } + + for i in (0..s).rev() { + if !produces(i) { + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, *b[i]); + } + if !threaded_add_call_has_structurally_dead_sum(call_index, i, s, s, vents) { + let old_context = crate::point_add::set_op_trace_context( + 0x0700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*ctrl, *b[i], *a[i]); + crate::point_add::restore_op_trace_context(old_context); + } + if let Some(ci) = ci { + circ.cx(*ci, *b[i]); + } + continue; + } + let co = inner[i].take().unwrap(); + let ci: Option<&QubitId> = if i == 0 { cin } else { inner[i - 1].as_ref() }; + if let Some(ci) = ci { + circ.cx(*ci, co); + } + if i < vents { + let bit = circ.alloc_bit(); + circ.hmr(co, bit); + circ.zero_and_free(co); + circ.cz_if_bit(*a[i], *b[i], bit); + } else { + circ.ccx(*a[i], *b[i], co); + circ.zero_and_free(co); + } + if let Some(ci) = ci { + circ.cx(*ci, *a[i]); + } + if !threaded_add_call_has_structurally_dead_sum(call_index, i, s, s, vents) { + let old_context = crate::point_add::set_op_trace_context( + 0x0700_0000 | (((call_index as u32) & 0xffff) << 8) | (i as u32 & 0xff), + ); + circ.ccx(*ctrl, *b[i], *a[i]); + crate::point_add::restore_op_trace_context(old_context); + } + if let Some(ci) = ci { + circ.cx(*ci, *b[i]); + } + } + if std::env::var_os("TRACE_TLM_GIDNEY_THREAD").is_some() { + eprintln!( + "TLM_GIDNEY_THREAD call={} phase={} width={} cin={} cout={} vents={} ops_start={} ops_end={}", + call_index, + circ.phase, + s, + usize::from(cin.is_some()), + usize::from(cout.is_some()), + vents, + ops_start, + circ.current_ops_len(), + ); + } +} + +fn deref(s: &[&QubitId]) -> Vec { + s.iter().map(|q| **q).collect() +} + +fn controlled_erase_carry_gated_impl( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + cin: Option<&QubitId>, + carry: QubitId, +) { + let call_index = next_erase_gated_call_index(); + let bit = circ.alloc_bit(); + circ.hmr(carry, bit); + circ.push_condition(bit); + let (av, bv) = (deref(a), deref(b)); + let ctrl = *ctrl; + let cin = match cin { + Some(cin) => { + + circ.loan_zero_qubit(carry); + *cin + } + None => carry, + }; + compare_geq_cin_middle(circ, &av, &bv, &cin, |c, ta, tb, c_prev| { + + c.z(ctrl); + let old_context = crate::point_add::set_op_trace_context( + 0x0900_0000 | (((call_index as u32) & 0xffff) << 8), + ); + if !gidney_erase_ccz_has_exact_dead_call(call_index) { + c.ccz(ctrl, *ta, *tb); + } + crate::point_add::restore_op_trace_context(old_context); + c.cz(ctrl, *c_prev); + }); + circ.pop_condition(); + if cin == carry { + circ.zero_and_free(carry); + } +} + +fn controlled_erase_carry_gated( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + cin: &QubitId, + carry: QubitId, +) { + controlled_erase_carry_gated_impl(circ, ctrl, a, b, Some(cin), carry); +} + +fn controlled_erase_carry_gated_zero_cin( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + carry: QubitId, +) { + controlled_erase_carry_gated_impl(circ, ctrl, a, b, None, carry); +} + +fn controlled_erase_carry_gated_capped( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + cin: &QubitId, + carry: QubitId, + cap: usize, +) { + let call_index = next_erase_gated_capped_call_index(); + let s = a.len(); + if s <= cap { + controlled_erase_carry_gated(circ, ctrl, a, b, cin, carry); + return; + } + let lo = s - cap; + let bit = circ.alloc_bit(); + circ.hmr(carry, bit); + circ.push_condition(bit); + let (av, bv) = (deref(&a[lo..]), deref(&b[lo..])); + let ctrl = *ctrl; + compare_geq_cin_middle(circ, &av, &bv, &carry, |c, ta, tb, c_prev| { + c.z(ctrl); + let old_context = crate::point_add::set_op_trace_context( + 0x0a00_0000 | (((call_index as u32) & 0xffff) << 8), + ); + if !gidney_erase_capped_ccz_has_exact_dead_call(call_index) { + c.ccz(ctrl, *ta, *tb); + } + crate::point_add::restore_op_trace_context(old_context); + c.cz(ctrl, *c_prev); + }); + circ.pop_condition(); + circ.zero_and_free(carry); +} + +fn controlled_erase_carry_gated_capped_zero_cin( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + carry: QubitId, + cap: usize, +) { + if a.len() <= cap { + controlled_erase_carry_gated_zero_cin(circ, ctrl, a, b, carry); + } else { + + controlled_erase_carry_gated_capped(circ, ctrl, a, b, &carry, carry, cap); + } +} + +fn controlled_vented_chunk_add(circ: &mut B, ctrl: &QubitId, a_chunk: &[&QubitId], b_chunk: &[&QubitId], cin: &QubitId, cout: &QubitId) { + let one = circ.alloc_qubit(); + circ.x(one); + let zero = circ.alloc_qubit(); + let mut aext: Vec<&QubitId> = Vec::with_capacity(a_chunk.len() + 2); + aext.push(&one); + aext.extend_from_slice(a_chunk); + aext.push(cout); + let mut bext: Vec<&QubitId> = Vec::with_capacity(b_chunk.len() + 2); + bext.push(cin); + bext.extend_from_slice(b_chunk); + bext.push(&zero); + + controlled_hybrid_add_refs_skiplow(circ, ctrl, &aext, &bext); + circ.x(one); + circ.zero_and_free(one); + circ.zero_and_free(zero); +} + +fn varchunk_schedule(n: usize, k: usize) -> Vec { + const RESERVE: usize = 4; + let mut sizes = Vec::new(); + let (mut covered, mut held) = (0usize, 0usize); + while covered < n { + let room = k.saturating_sub(held + RESERVE); + if room == 0 { + return Vec::new(); + } + let s = room.min(n - covered); + sizes.push(s); + covered += s; + held += 1; + } + sizes +} + +fn varchunk_cost(n: usize, k: usize, cap: usize) -> usize { + let sizes = varchunk_schedule(n, k); + if sizes.is_empty() { + return usize::MAX; + } + let erase: usize = sizes.iter().map(|&s| s.min(cap) / 2).sum(); + n + erase +} + +pub(crate) struct AdaptiveLayout { + pub(crate) c: usize, + pub(crate) chunked_len: usize, + pub(crate) plain_len: usize, +} +pub(crate) const ADAPTIVE_RES: usize = 5; + +fn adaptive_chunk_size(n: usize) -> usize { + std::env::var("TLM_ADAPTIVE_CHUNK") + .ok() + .and_then(|v| v.parse::().ok()) + .filter(|&v| v > 0) + .unwrap_or_else(|| (n as f64).sqrt() as usize) + .clamp(1, n) +} + +pub(crate) fn adaptive_layout(n: usize, k: usize) -> AdaptiveLayout { + let c = ((n as f64).sqrt() as usize).clamp(1, n); + adaptive_layout_for_chunk(n, k, c) +} + +fn adaptive_layout_for_chunk(n: usize, k: usize, c: usize) -> AdaptiveLayout { + let mut plain = 0usize; + while plain < n { + let l = n - (plain + 1); + let nch = l.div_ceil(c); + if nch + (plain + 1) <= k { + plain += 1; + } else { + break; + } + } + AdaptiveLayout { c, chunked_len: n - plain, plain_len: plain } +} + +fn searched_cout_layout(n: usize, k: usize) -> Option { + if std::env::var_os("TLM_COUT_LAYOUT_SEARCH").is_none() { + return None; + } + let mut margin = std::env::var("TLM_COUT_LAYOUT_MARGIN") + .ok() + .and_then(|v| v.parse::().ok()) + .unwrap_or(1); + if margin == 0 + && std::env::var("TLM_COUT_LAYOUT_FORCE_M1_KS") + .ok() + .map(|s| { + s.split(',') + .filter_map(|part| part.trim().parse::().ok()) + .any(|force_k| force_k == k) + }) + .unwrap_or(false) + { + margin = 1; + } + let mut best: Option<(usize, AdaptiveLayout)> = None; + for c in 1..=n { + for plain_len in 0..=n { + let chunked_len = n - plain_len; + let nchunks = chunked_len.div_ceil(c); + if nchunks + plain_len + margin > k { + continue; + } + if nchunks + c.min(chunked_len.max(1)) + margin > k { + continue; + } + let cost = 2 * n + chunked_len + nchunks + 1; + let layout = AdaptiveLayout { c, chunked_len, plain_len }; + match best { + Some((best_cost, _)) if best_cost <= cost => {} + _ => best = Some((cost, layout)), + } + } + } + best.map(|(_, layout)| layout) +} + +fn emit_cout_layout( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + cout: &QubitId, + layout: AdaptiveLayout, +) { + let n = a.len(); + let l = layout.chunked_len; + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let mut lo = 0; + while lo < l { + let hi = (lo + layout.c).min(l); + bounds.push((lo, hi)); + lo = hi; + } + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(lo, hi)) in bounds.iter().enumerate() { + let cy = circ.alloc_qubit(); + let cin: Option<&QubitId> = if j == 0 { None } else { Some(&carries[j - 1]) }; + controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, Some(&cy), hi - lo); + carries.push(cy); + } + controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], carries.last(), Some(cout), layout.plain_len); + for j in (0..bounds.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); + } else { + controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); + } + } +} + +fn searched_gcd_adaptive_layout(n: usize, k: usize) -> Option { + if std::env::var_os("TLM_GCD_ADAPTIVE_LAYOUT_SEARCH").is_none() { + return None; + } + let margin = std::env::var("TLM_GCD_ADAPTIVE_LAYOUT_MARGIN") + .ok() + .and_then(|v| v.parse::().ok()) + .unwrap_or(1); + let mut best: Option<(usize, AdaptiveLayout)> = None; + for c in 1..=n { + for plain_len in 0..=n { + let chunked_len = n - plain_len; + let nchunks = chunked_len.div_ceil(c); + if nchunks + plain_len + margin > k { + continue; + } + if nchunks + c.min(chunked_len.max(1)) + margin > k { + continue; + } + let cost = 2 * n + chunked_len + nchunks - 1; + let layout = AdaptiveLayout { c, chunked_len, plain_len }; + match best { + Some((best_cost, _)) if best_cost <= cost => {} + _ => best = Some((cost, layout)), + } + } + } + best.map(|(_, layout)| layout) +} + +fn emit_adaptive_layout_no_cout( + circ: &mut B, + ctrl: &QubitId, + a: &[&QubitId], + b: &[&QubitId], + layout: AdaptiveLayout, +) { + let n = a.len(); + let l = layout.chunked_len; + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let mut lo = 0; + while lo < l { + let hi = (lo + layout.c).min(l); + bounds.push((lo, hi)); + lo = hi; + } + let cin0 = circ.alloc_qubit(); + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(lo, hi)) in bounds.iter().enumerate() { + let cout = circ.alloc_qubit(); + let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; + controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], Some(cin), Some(&cout), hi - lo); + carries.push(cout); + } + if layout.plain_len > 0 { + let cin: &QubitId = carries.last().unwrap_or(&cin0); + controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], Some(cin), None, layout.plain_len); + } + circ.zero_and_free(cin0); + for j in (0..bounds.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); + } else { + controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); + } + } +} + +fn adaptive_add_cost_tof(n: usize, k: usize, controlled: bool) -> u64 { + if n == 0 { + return 0; + } + let base = if controlled { 3 * n } else { 2 * n }; + let s2 = 2 * (n as f64).sqrt() as usize; + let saved = if k >= n { + n + } else if k < s2 { + (k * k) / 8 + } else { + n / 2 + (k - s2) / 2 + }; + (base.saturating_sub(saved)) as u64 +} + +fn controlled_chunked_then_cuccaro(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: Option<&QubitId>, k: usize) { + let n = a.len(); + if n == 0 { + return; + } + let cin0 = circ.alloc_qubit(); + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let (mut lo, mut i) = (0usize, 0usize); + while lo < n && k > i + 2 { + let cc = (k - 2 - i).min(n - lo); + bounds.push((lo, lo + cc)); + lo += cc; + i += 1; + } + let chunked_len = lo; + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(clo, chi)) in bounds.iter().enumerate() { + let cy = circ.alloc_qubit(); + let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; + controlled_clean_add_threaded(circ, ctrl, &a[clo..chi], &b[clo..chi], Some(cin), Some(&cy), chi - clo); + carries.push(cy); + } + if chunked_len < n { + let cin: &QubitId = carries.last().unwrap_or(&cin0); + + let at = deref(&a[chunked_len..n]); + let bt = deref(&b[chunked_len..n]); + super::arith::cuccaro_carry(circ, Some(ctrl), &bt, &at, Some(cin), cout); + } else if let Some(co) = cout { + circ.cx(*carries.last().unwrap_or(&cin0), *co); + } + circ.zero_and_free(cin0); + for j in (0..bounds.len()).rev() { + let (clo, chi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[clo..chi], &b[clo..chi], carry); + } else { + controlled_erase_carry_gated(circ, ctrl, &a[clo..chi], &b[clo..chi], &carries[j - 1], carry); + } + } +} + +fn controlled_hybrid_add_adaptive_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize) { + let n = a.len(); + assert_eq!(b.len(), n, "controlled adaptive add: a,b width mismatch"); + if n == 0 { + return; + } + if let Some(layout) = searched_gcd_adaptive_layout(n, k) { + emit_adaptive_layout_no_cout(circ, ctrl, a, b, layout); + return; + } + let c = ((n as f64).sqrt() as usize).clamp(1, n); + if n <= 4 || k.saturating_add(2 * c) >= n { + controlled_hybrid_add_refs(circ, ctrl, a, b); + return; + } + let tight = k < n.div_ceil(c) + c + ADAPTIVE_RES; + let cov = (k.saturating_sub(2).saturating_mul(k.saturating_sub(1)) / 2).min(n); + if tight && cov < n { + if cov > 2 * k { + controlled_chunked_then_cuccaro(circ, ctrl, a, b, None, k); + } else { + controlled_hybrid_add_refs(circ, ctrl, a, b); + } + return; + } + let cin0 = circ.alloc_qubit(); + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let (l, plain_len) = if tight { + let (mut lo, mut i) = (0usize, 0usize); + while lo < n && k > i + 2 { + let cc = (k - 2 - i).min(n - lo); + bounds.push((lo, lo + cc)); + lo += cc; + i += 1; + } + (n, 0) + } else { + let lay = adaptive_layout(n, k); + let mut lo = 0; + while lo < lay.chunked_len { + let hi = (lo + lay.c).min(lay.chunked_len); + bounds.push((lo, hi)); + lo = hi; + } + (lay.chunked_len, lay.plain_len) + }; + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(lo, hi)) in bounds.iter().enumerate() { + let cout = circ.alloc_qubit(); + let cin: &QubitId = if j == 0 { &cin0 } else { &carries[j - 1] }; + controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], Some(cin), Some(&cout), hi - lo); + carries.push(cout); + } + if plain_len > 0 { + let cin: &QubitId = carries.last().unwrap_or(&cin0); + controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], Some(cin), None, plain_len); + } + circ.zero_and_free(cin0); + for j in (0..bounds.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); + } else { + controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); + } + } +} + +fn controlled_hybrid_add_varchunk_gated_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize) { + let n = a.len(); + assert_eq!(b.len(), n, "varchunk add: a,b width mismatch"); + if n == 0 { + return; + } + let sizes = varchunk_schedule(n, k); + assert!(!sizes.is_empty(), "varchunk infeasible at k={k} for n={n}"); + let direct = std::env::var("TLM_DIRECT_VARCHUNK") + .ok() + .as_deref() + == Some("1"); + let cin0 = (!direct).then(|| circ.alloc_qubit()); + let mut carries: Vec = Vec::with_capacity(sizes.len()); + let mut bounds: Vec<(usize, usize)> = Vec::with_capacity(sizes.len()); + let mut lo = 0usize; + for (j, &s) in sizes.iter().enumerate() { + let hi = lo + s; + let cout = circ.alloc_qubit(); + if direct { + + let fit = super::next_hyb_v_fit(); + let timeline_start = circ.active_timeline.len(); + let entry_active = circ.active_qubits; + let ops_start = circ.current_ops_len(); + let cin = (j != 0).then(|| &carries[j - 1]); + controlled_clean_add_threaded( + circ, + ctrl, + &a[lo..hi], + &b[lo..hi], + cin, + Some(&cout), + hi - lo, + ); + trace_schedule_fit( + "TRACE_TLM_HYB", + "HYB", + "direct-varchunk", + fit, + hi - lo, + hi - lo, + entry_active, + timeline_start, + ops_start, + circ, + ); + } else { + let cin: &QubitId = if j == 0 { + cin0.as_ref().expect("legacy cin0") + } else { + &carries[j - 1] + }; + controlled_vented_chunk_add(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, &cout); + } + carries.push(cout); + bounds.push((lo, hi)); + lo = hi; + } + if let Some(cin0) = cin0 { + circ.zero_and_free(cin0); + } + for j in (0..sizes.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_capped_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry, cap); + } else { + controlled_erase_carry_gated_capped(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry, cap); + } + } +} + +fn controlled_hybrid_add_knob_capped_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize) { + let n = a.len(); + if cap < n + && !varchunk_schedule(n, k).is_empty() + && (varchunk_cost(n, k, cap) as u64 + n as u64) < adaptive_add_cost_tof(n, k, true) + { + controlled_hybrid_add_varchunk_gated_refs(circ, ctrl, a, b, k, cap); + } else { + controlled_hybrid_add_adaptive_refs(circ, ctrl, a, b, k); + } +} + +pub fn controlled_hybrid_add_capped_branch(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], k: usize, cap: usize, branch: u8) { + let n = a.len(); + let k = super::target_qubit_headroom(circ).map_or(k, |headroom| k.min(headroom)); + if std::env::var("TLM_GCD_RESELECT_LAYOUT") + .ok() + .as_deref() + == Some("1") + { + controlled_hybrid_add_knob_capped_refs(circ, ctrl, a, b, k, cap); + return; + } + if branch == 1 && n > 0 && !varchunk_schedule(n, k).is_empty() { + controlled_hybrid_add_varchunk_gated_refs(circ, ctrl, a, b, k, cap); + } else if branch == 0 { + + controlled_hybrid_add_refs(circ, ctrl, a, b); + } else if branch == 255 { + + controlled_hybrid_add_knob_capped_refs(circ, ctrl, a, b, k, cap); + } else { + controlled_hybrid_add_adaptive_refs(circ, ctrl, a, b, k); + } +} + +pub fn controlled_hybrid_add_cout_refs(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: &QubitId, k: usize) { + let fit = super::take_cout_fit(k); + let timeline_start = circ.active_timeline.len(); + let entry_active = circ.active_qubits; + let ops_start = circ.current_ops_len(); + let effective = super::target_qubit_headroom(circ) + .map_or(fit.selected, |headroom| fit.selected.min(headroom)); + controlled_hybrid_add_cout_refs_impl(circ, ctrl, a, b, cout, effective); + trace_schedule_fit( + "TRACE_TLM_COUT", + "COUT", + "dispatch", + fit, + effective, + a.len(), + entry_active, + timeline_start, + ops_start, + circ, + ); +} + +fn controlled_hybrid_add_cout_refs_impl(circ: &mut B, ctrl: &QubitId, a: &[&QubitId], b: &[&QubitId], cout: &QubitId, k: usize) { + let n = a.len(); + assert_eq!(b.len(), n, "controlled cout add: a,b width mismatch"); + assert!(n >= 1, "controlled cout add: empty operands"); + if let Some(layout) = searched_cout_layout(n, k) { + emit_cout_layout(circ, ctrl, a, b, cout, layout); + return; + } + let c = adaptive_chunk_size(n); + let lay = adaptive_layout_for_chunk(n, k, c); + let tight = k < n.div_ceil(c) + c + ADAPTIVE_RES; + let cov = (k.saturating_sub(2).saturating_mul(k.saturating_sub(1)) / 2).min(n); + if n > 4 && k.saturating_add(2 * c) < n && tight && cov > 2 * k { + controlled_chunked_then_cuccaro(circ, ctrl, a, b, Some(cout), k); + return; + } + if n <= 4 || k < n.div_ceil(c) + c + ADAPTIVE_RES || k.saturating_add(2 * c) >= n || lay.plain_len == 0 { + let zpad = circ.alloc_qubit(); + let mut aref: Vec<&QubitId> = a.to_vec(); + aref.push(cout); + let mut bref: Vec<&QubitId> = b.to_vec(); + bref.push(&zpad); + controlled_hybrid_add_refs(circ, ctrl, &aref, &bref); + circ.zero_and_free(zpad); + return; + } + let l = lay.chunked_len; + let mut bounds: Vec<(usize, usize)> = Vec::new(); + let mut lo = 0; + while lo < l { + let hi = (lo + lay.c).min(l); + bounds.push((lo, hi)); + lo = hi; + } + let mut carries: Vec = Vec::with_capacity(bounds.len()); + for (j, &(lo, hi)) in bounds.iter().enumerate() { + let cy = circ.alloc_qubit(); + let cin: Option<&QubitId> = if j == 0 { None } else { Some(&carries[j - 1]) }; + controlled_clean_add_threaded(circ, ctrl, &a[lo..hi], &b[lo..hi], cin, Some(&cy), hi - lo); + carries.push(cy); + } + controlled_clean_add_threaded(circ, ctrl, &a[l..n], &b[l..n], carries.last(), Some(cout), lay.plain_len); + for j in (0..bounds.len()).rev() { + let (lo, hi) = bounds[j]; + let carry = carries.pop().expect("carry present"); + if j == 0 { + controlled_erase_carry_gated_zero_cin(circ, ctrl, &a[lo..hi], &b[lo..hi], carry); + } else { + controlled_erase_carry_gated(circ, ctrl, &a[lo..hi], &b[lo..hi], &carries[j - 1], carry); + } + } +} diff --git a/src/point_add/trailmix_ludicrous/mcx.rs b/src/point_add/trailmix_ludicrous/mcx.rs index e96d2c49..72b3c03f 100644 --- a/src/point_add/trailmix_ludicrous/mcx.rs +++ b/src/point_add/trailmix_ludicrous/mcx.rs @@ -1,440 +1,330 @@ - -use super::{B, BExt}; -use crate::circuit::{QubitId}; -use std::sync::atomic::{AtomicU8, Ordering}; - -fn mbu_clear_and(circ: &mut B, t: &QubitId, c0: &QubitId, c1: &QubitId) { - let bit = circ.alloc_bit(); - circ.hmr(*t, bit); - circ.cz_if_bit(*c0, *c1, bit); - circ.zero_and_free(*t); -} - -// E284 (TLM_KG_INC_VENT=1): replace the reverse-pass AND-uncompute Toffolis in the KG -// increment with Gidney measurement-based uncomputation (mbu_clear_and, Clifford), bit-exact. -// Only ancillae dead after their uncompute are vented; live recursive temp_target toggles stay Ccx. -static KG_INC_VENT_FLAG: AtomicU8 = AtomicU8::new(2); -fn kg_inc_vent_enabled() -> bool { - let c = KG_INC_VENT_FLAG.load(Ordering::Relaxed); - if c != 2 { - return c == 1; - } - let on = matches!(std::env::var("TLM_KG_INC_VENT").ok().as_deref(), Some("1")); - KG_INC_VENT_FLAG.store(u8::from(on), Ordering::Relaxed); - on -} - -fn kg_get_layer_id(x: usize) -> usize { - let mut layer_id = 0usize; - let mut s = 0usize; - while s <= x { - s += (1usize << layer_id) + 1; - layer_id += 1; - } - layer_id - 1 -} - -fn kg_start_layer(layer_id: usize) -> usize { - let mut s = 0usize; - for i in 0..layer_id { - s += (1usize << i) + 1; - } - s -} - -#[must_use] -pub fn kg_prefix_ancilla_count(n: usize) -> usize { - if n <= 1 { - return 0; - } - let targets_len = kg_get_layer_id(n - 1) + 1; - if targets_len <= 2 { - 1 - } else { - 2 + kg_prefix_ancilla_count(targets_len) - } -} - -fn kg_apply_prefix_controlled_x(circ: &mut B, ctrls: &[&QubitId], target: &QubitId) { - match ctrls { - [] => circ.x(*target), - [c] => circ.cx(**c, *target), - [a, b] => circ.ccx(**a, **b, *target), - _ => panic!("kg_apply_prefix_controlled_x: expected <=2 ctrls, got {}", ctrls.len()), - } -} - -fn kg_anc_index(len: usize, idx: isize) -> usize { - if idx >= 0 { - idx as usize - } else { - (len as isize + idx) as usize - } -} - -#[derive(Clone, Copy)] -enum KgPrefixOp<'a> { - X(&'a QubitId), - Ccx(&'a QubitId, &'a QubitId, &'a QubitId), -} - -impl KgPrefixOp<'_> { - fn emit(self, circ: &mut B) { - match self { - KgPrefixOp::X(q) => circ.x(*q), - KgPrefixOp::Ccx(a, b, t) => circ.ccx(*a, *b, *t), - } - } -} - -#[derive(Clone)] -struct KgPrefixLayer<'a> { - ctrls: Vec<&'a QubitId>, - ops: Vec>, -} - -fn kg_get_layers_for_prefix_and<'a>( - q: &[&'a QubitId], - inp_anc: &[&'a QubitId], -) -> Vec> { - assert!(!q.is_empty(), "kg_get_layers_for_prefix_and: q must be non-empty"); - if q.len() == 1 { - return vec![ - KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }, - KgPrefixLayer { ctrls: vec![q[0]], ops: Vec::new() }, - ]; - } - assert!( - inp_anc.len() >= kg_prefix_ancilla_count(q.len()), - "kg_get_layers_for_prefix_and: need {} ancillae for n={}, got {}", - kg_prefix_ancilla_count(q.len()), - q.len(), - inp_anc.len(), - ); - - let n = q.len(); - let n_layers = kg_get_layer_id(q.len() - 1); - let mut ret = vec![KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }]; - let mut targets: Vec<&'a QubitId> = Vec::new(); - let mut anc: Vec<&'a QubitId> = vec![inp_anc[0]]; - - for layer_id in 0..=n_layers { - let st = kg_start_layer(layer_id); - let en = n.min(kg_start_layer(layer_id + 1)); - - let mut layer_ctrls = targets.clone(); - layer_ctrls.push(q[st]); - ret.push(KgPrefixLayer { ctrls: layer_ctrls, ops: Vec::new() }); - - for i in (st + 1)..en { - let offset = i - st; - let anc_len = anc.len(); - let q0 = q[i]; - let (q1, t) = if offset == 1 { - (q[i - 1], anc[kg_anc_index(anc_len, -1)]) - } else { - ( - anc[kg_anc_index(anc_len, -(offset as isize - 1))], - anc[kg_anc_index(anc_len, -(offset as isize))], - ) - }; - let mut ops = Vec::new(); - if std::ptr::eq(t, inp_anc[0]) { - ops.push(KgPrefixOp::Ccx(q0, q1, t)); - } else { - ops.push(KgPrefixOp::X(t)); - ops.push(KgPrefixOp::Ccx(q0, q1, t)); - } - let mut ctrls = targets.clone(); - ctrls.push(t); - ret.push(KgPrefixLayer { ctrls, ops }); - } - - let layer_len = en - st; - let push_idx = kg_anc_index(anc.len(), 1 - layer_len as isize); - targets.push(anc[push_idx]); - - let slice_start = kg_anc_index(anc.len(), 2 - layer_len as isize); - let mut next_anc = anc[slice_start..].to_vec(); - next_anc.extend(q[st..en].iter()); - anc = next_anc; - } - - if targets.len() <= 2 { - return ret; - } - - ret.push(KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }); - let target_prefix_layers = kg_get_layers_for_prefix_and(&targets, &inp_anc[2..]); - for layer_id in 1..=n_layers { - let st = kg_start_layer(layer_id); - let en = n.min(kg_start_layer(layer_id + 1)); - let target_prefix_targets = target_prefix_layers[layer_id].ctrls.clone(); - let ops_to_add = target_prefix_layers[layer_id].ops.clone(); - ret[st + 1].ops.extend_from_slice(&ops_to_add); - - let temp_target = if target_prefix_targets.len() == 1 { - target_prefix_targets[0] - } else { - assert_eq!(target_prefix_targets.len(), 2); - ret[st + 1].ops.push(KgPrefixOp::Ccx( - target_prefix_targets[0], - target_prefix_targets[1], - inp_anc[1], - )); - inp_anc[1] - }; - - for i in st..en { - let local = *ret[i + 1].ctrls.last().expect("empty local ctrl"); - ret[i + 1].ctrls = vec![temp_target, local]; - } - - if target_prefix_targets.len() == 2 { - ret[en + 1].ops.push(KgPrefixOp::Ccx( - target_prefix_targets[0], - target_prefix_targets[1], - temp_target, - )); - } - } - - ret -} - -fn xor_and_of_khattar_gidney_refs(circ: &mut B, bits: &[&QubitId], target: &QubitId) { - match bits.len() { - 0 => { - circ.x(*target); - return; - } - 1 => { - circ.cx(*bits[0], *target); - return; - } - 2 => { - circ.ccx(*bits[0], *bits[1], *target); - return; - } - _ => {} - } - - let anc_owned: Vec = (0..kg_prefix_ancilla_count(bits.len())) - .map(|_| circ.alloc_qubit()) - .collect(); - let anc_refs: Vec<&QubitId> = anc_owned.iter().collect(); - let layers = kg_get_layers_for_prefix_and(bits, &anc_refs); - - for (i, layer) in layers.iter().enumerate() { - if i > bits.len() { - break; - } - for &op in &layer.ops { - op.emit(circ); - } - } - - for (i, layer) in layers.iter().enumerate().rev() { - if i > bits.len() { - continue; - } - if i == bits.len() { - kg_apply_prefix_controlled_x(circ, &layer.ctrls, target); - } - for &op in layer.ops.iter().rev() { - op.emit(circ); - } - } - drop(layers); - drop(anc_refs); - for q in anc_owned { - circ.zero_and_free(q); - } -} - -pub fn mcx_clean_k(circ: &mut B, ctrls: &[&QubitId], target: &QubitId) { - match ctrls.len() { - 0 => circ.x(*target), - 1 => circ.cx(*ctrls[0], *target), - 2 => circ.ccx(*ctrls[0], *ctrls[1], *target), - 3 => { - let t = circ.alloc_qubit(); - circ.ccx(*ctrls[0], *ctrls[1], t); - circ.ccx(t, *ctrls[2], *target); - mbu_clear_and(circ, &t, ctrls[0], ctrls[1]); - } - 4 => { - let t01 = circ.alloc_qubit(); - let t23 = circ.alloc_qubit(); - circ.ccx(*ctrls[0], *ctrls[1], t01); - circ.ccx(*ctrls[2], *ctrls[3], t23); - circ.ccx(t01, t23, *target); - mbu_clear_and(circ, &t23, ctrls[2], ctrls[3]); - mbu_clear_and(circ, &t01, ctrls[0], ctrls[1]); - } - 5 => { - let t01 = circ.alloc_qubit(); - let t23 = circ.alloc_qubit(); - let t0123 = circ.alloc_qubit(); - circ.ccx(*ctrls[0], *ctrls[1], t01); - circ.ccx(*ctrls[2], *ctrls[3], t23); - circ.ccx(t01, t23, t0123); - circ.ccx(t0123, *ctrls[4], *target); - mbu_clear_and(circ, &t0123, &t01, &t23); - mbu_clear_and(circ, &t23, ctrls[2], ctrls[3]); - mbu_clear_and(circ, &t01, ctrls[0], ctrls[1]); - } - _ => { - xor_and_of_khattar_gidney_refs(circ, ctrls, target); - } - } -} - -pub fn inc_khattar_gidney(circ: &mut B, a: &[QubitId]) { - let refs: Vec<&QubitId> = a.iter().collect(); - inc_khattar_gidney_refs_inner(circ, &refs, false); -} - -pub fn cinc_khattar_gidney(circ: &mut B, a: &[QubitId], ctrl: &QubitId) { - if a.is_empty() { - return; - } - let mut combined: Vec<&QubitId> = Vec::with_capacity(a.len() + 1); - combined.push(ctrl); - combined.extend(a.iter()); - inc_khattar_gidney_refs_inner(circ, &combined, true); -} - -fn inc_khattar_gidney_refs_inner(circ: &mut B, a: &[&QubitId], skip_lsb_x: bool) { - let n = a.len(); - if n == 0 { - return; - } - if n == 1 { - if !skip_lsb_x { - circ.x(*a[0]); - } - return; - } - - let anc_owned: Vec = (0..kg_prefix_ancilla_count(n - 1)) - .map(|_| circ.alloc_qubit()) - .collect(); - let anc_refs: Vec<&QubitId> = anc_owned.iter().collect(); - let layers = kg_get_layers_for_prefix_and(&a[..n - 1], &anc_refs); - - for layer in &layers { - for &op in &layer.ops { - op.emit(circ); - } - } - if !kg_inc_vent_enabled() { - for (i, layer) in layers.iter().enumerate().rev() { - if i < n && !(i == 0 && skip_lsb_x) { - kg_apply_prefix_controlled_x(circ, &layer.ctrls, a[i]); - } - for &op in layer.ops.iter().rev() { - op.emit(circ); - } - } - drop(layers); - drop(anc_refs); - for q in anc_owned { - circ.zero_and_free(q); - } - return; - } - - // --- Vented reverse pass (E284, TLM_KG_INC_VENT=1) --- - #[derive(Clone, Copy)] - enum Step { - X0(QubitId), - X1(QubitId, QubitId), - X2(QubitId, QubitId, QubitId), - Xanc(QubitId), - Uncmp(QubitId, QubitId, QubitId), - } - let mut plan: Vec = Vec::new(); - for (i, layer) in layers.iter().enumerate().rev() { - if i < n && !(i == 0 && skip_lsb_x) { - match layer.ctrls.as_slice() { - [] => plan.push(Step::X0(*a[i])), - [c] => plan.push(Step::X1(**c, *a[i])), - [x, y] => plan.push(Step::X2(**x, **y, *a[i])), - _ => panic!("inc_khattar_gidney vent: >2 prefix ctrls"), - } - } - for &op in layer.ops.iter().rev() { - match op { - KgPrefixOp::X(t) => plan.push(Step::Xanc(*t)), - KgPrefixOp::Ccx(x, y, t) => plan.push(Step::Uncmp(*x, *y, *t)), - } - } - } - drop(layers); - drop(anc_refs); - - fn touches(s: &Step) -> [Option; 3] { - match *s { - Step::X0(t) => [Some(t.0), None, None], - Step::X1(c, t) => [Some(c.0), Some(t.0), None], - Step::X2(x, y, t) => [Some(x.0), Some(y.0), Some(t.0)], - Step::Xanc(t) => [Some(t.0), None, None], - Step::Uncmp(x, y, t) => [Some(x.0), Some(y.0), Some(t.0)], - } - } - let mut occ: std::collections::HashMap> = std::collections::HashMap::new(); - for (idx, s) in plan.iter().enumerate() { - for q in touches(s).into_iter().flatten() { - occ.entry(q).or_default().push(idx); - } - } - let mut skip = vec![false; plan.len()]; - let mut vent_pure = vec![false; plan.len()]; - let mut vent_xc = vec![false; plan.len()]; - let mut vented_anc: std::collections::HashSet = std::collections::HashSet::new(); - for k in 0..plan.len() { - if let Step::Uncmp(_, _, t) = plan[k] { - let after: Vec = occ - .get(&t.0) - .map(|v| v.iter().copied().filter(|&j| j > k).collect()) - .unwrap_or_default(); - if after.is_empty() { - vent_pure[k] = true; - vented_anc.insert(t.0); - } else if after.len() == 1 - && matches!(plan[after[0]], Step::Xanc(tt) if tt.0 == t.0) - { - vent_xc[k] = true; - skip[after[0]] = true; - vented_anc.insert(t.0); - } - } - } - for k in 0..plan.len() { - if skip[k] { - continue; - } - match plan[k] { - Step::X0(t) => circ.x(t), - Step::X1(c, t) => circ.cx(c, t), - Step::X2(x, y, t) => circ.ccx(x, y, t), - Step::Xanc(t) => circ.x(t), - Step::Uncmp(x, y, t) => { - if vent_pure[k] { - mbu_clear_and(circ, &t, &x, &y); - } else if vent_xc[k] { - circ.x(t); - mbu_clear_and(circ, &t, &x, &y); - } else { - circ.ccx(x, y, t); - } - } - } - } - for q in anc_owned { - if !vented_anc.contains(&q.0) { - circ.zero_and_free(q); - } - } -} + +use super::{B, BExt}; +use crate::circuit::{QubitId}; + +fn mbu_clear_and(circ: &mut B, t: &QubitId, c0: &QubitId, c1: &QubitId) { + let bit = circ.alloc_bit(); + circ.hmr(*t, bit); + circ.cz_if_bit(*c0, *c1, bit); + circ.zero_and_free(*t); +} + +fn kg_get_layer_id(x: usize) -> usize { + let mut layer_id = 0usize; + let mut s = 0usize; + while s <= x { + s += (1usize << layer_id) + 1; + layer_id += 1; + } + layer_id - 1 +} + +fn kg_start_layer(layer_id: usize) -> usize { + let mut s = 0usize; + for i in 0..layer_id { + s += (1usize << i) + 1; + } + s +} + +#[must_use] +pub fn kg_prefix_ancilla_count(n: usize) -> usize { + if n <= 1 { + return 0; + } + let targets_len = kg_get_layer_id(n - 1) + 1; + if targets_len <= 2 { + 1 + } else { + 2 + kg_prefix_ancilla_count(targets_len) + } +} + +fn kg_apply_prefix_controlled_x(circ: &mut B, ctrls: &[&QubitId], target: &QubitId) { + match ctrls { + [] => circ.x(*target), + [c] => circ.cx(**c, *target), + [a, b] => circ.ccx(**a, **b, *target), + _ => panic!("kg_apply_prefix_controlled_x: expected <=2 ctrls, got {}", ctrls.len()), + } +} + +fn kg_anc_index(len: usize, idx: isize) -> usize { + if idx >= 0 { + idx as usize + } else { + (len as isize + idx) as usize + } +} + +#[derive(Clone, Copy)] +enum KgPrefixOp<'a> { + X(&'a QubitId), + Ccx(&'a QubitId, &'a QubitId, &'a QubitId), +} + +impl KgPrefixOp<'_> { + fn emit(self, circ: &mut B) { + match self { + KgPrefixOp::X(q) => circ.x(*q), + KgPrefixOp::Ccx(a, b, t) => circ.ccx(*a, *b, *t), + } + } +} + +#[derive(Clone)] +struct KgPrefixLayer<'a> { + ctrls: Vec<&'a QubitId>, + ops: Vec>, +} + +fn kg_get_layers_for_prefix_and<'a>( + q: &[&'a QubitId], + inp_anc: &[&'a QubitId], +) -> Vec> { + assert!(!q.is_empty(), "kg_get_layers_for_prefix_and: q must be non-empty"); + if q.len() == 1 { + return vec![ + KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }, + KgPrefixLayer { ctrls: vec![q[0]], ops: Vec::new() }, + ]; + } + assert!( + inp_anc.len() >= kg_prefix_ancilla_count(q.len()), + "kg_get_layers_for_prefix_and: need {} ancillae for n={}, got {}", + kg_prefix_ancilla_count(q.len()), + q.len(), + inp_anc.len(), + ); + + let n = q.len(); + let n_layers = kg_get_layer_id(q.len() - 1); + let mut ret = vec![KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }]; + let mut targets: Vec<&'a QubitId> = Vec::new(); + let mut anc: Vec<&'a QubitId> = vec![inp_anc[0]]; + + for layer_id in 0..=n_layers { + let st = kg_start_layer(layer_id); + let en = n.min(kg_start_layer(layer_id + 1)); + + let mut layer_ctrls = targets.clone(); + layer_ctrls.push(q[st]); + ret.push(KgPrefixLayer { ctrls: layer_ctrls, ops: Vec::new() }); + + for i in (st + 1)..en { + let offset = i - st; + let anc_len = anc.len(); + let q0 = q[i]; + let (q1, t) = if offset == 1 { + (q[i - 1], anc[kg_anc_index(anc_len, -1)]) + } else { + ( + anc[kg_anc_index(anc_len, -(offset as isize - 1))], + anc[kg_anc_index(anc_len, -(offset as isize))], + ) + }; + let mut ops = Vec::new(); + if std::ptr::eq(t, inp_anc[0]) { + ops.push(KgPrefixOp::Ccx(q0, q1, t)); + } else { + ops.push(KgPrefixOp::X(t)); + ops.push(KgPrefixOp::Ccx(q0, q1, t)); + } + let mut ctrls = targets.clone(); + ctrls.push(t); + ret.push(KgPrefixLayer { ctrls, ops }); + } + + let layer_len = en - st; + let push_idx = kg_anc_index(anc.len(), 1 - layer_len as isize); + targets.push(anc[push_idx]); + + let slice_start = kg_anc_index(anc.len(), 2 - layer_len as isize); + let mut next_anc = anc[slice_start..].to_vec(); + next_anc.extend(q[st..en].iter()); + anc = next_anc; + } + + if targets.len() <= 2 { + return ret; + } + + ret.push(KgPrefixLayer { ctrls: Vec::new(), ops: Vec::new() }); + let target_prefix_layers = kg_get_layers_for_prefix_and(&targets, &inp_anc[2..]); + for layer_id in 1..=n_layers { + let st = kg_start_layer(layer_id); + let en = n.min(kg_start_layer(layer_id + 1)); + let target_prefix_targets = target_prefix_layers[layer_id].ctrls.clone(); + let ops_to_add = target_prefix_layers[layer_id].ops.clone(); + ret[st + 1].ops.extend_from_slice(&ops_to_add); + + let temp_target = if target_prefix_targets.len() == 1 { + target_prefix_targets[0] + } else { + assert_eq!(target_prefix_targets.len(), 2); + ret[st + 1].ops.push(KgPrefixOp::Ccx( + target_prefix_targets[0], + target_prefix_targets[1], + inp_anc[1], + )); + inp_anc[1] + }; + + for i in st..en { + let local = *ret[i + 1].ctrls.last().expect("empty local ctrl"); + ret[i + 1].ctrls = vec![temp_target, local]; + } + + if target_prefix_targets.len() == 2 { + ret[en + 1].ops.push(KgPrefixOp::Ccx( + target_prefix_targets[0], + target_prefix_targets[1], + temp_target, + )); + } + } + + ret +} + +fn xor_and_of_khattar_gidney_refs(circ: &mut B, bits: &[&QubitId], target: &QubitId) { + match bits.len() { + 0 => { + circ.x(*target); + return; + } + 1 => { + circ.cx(*bits[0], *target); + return; + } + 2 => { + circ.ccx(*bits[0], *bits[1], *target); + return; + } + _ => {} + } + + let anc_owned: Vec = (0..kg_prefix_ancilla_count(bits.len())) + .map(|_| circ.alloc_qubit()) + .collect(); + let anc_refs: Vec<&QubitId> = anc_owned.iter().collect(); + let layers = kg_get_layers_for_prefix_and(bits, &anc_refs); + + for (i, layer) in layers.iter().enumerate() { + if i > bits.len() { + break; + } + for &op in &layer.ops { + op.emit(circ); + } + } + + for (i, layer) in layers.iter().enumerate().rev() { + if i > bits.len() { + continue; + } + if i == bits.len() { + kg_apply_prefix_controlled_x(circ, &layer.ctrls, target); + } + for &op in layer.ops.iter().rev() { + op.emit(circ); + } + } + drop(layers); + drop(anc_refs); + for q in anc_owned { + circ.zero_and_free(q); + } +} + +pub fn mcx_clean_k(circ: &mut B, ctrls: &[&QubitId], target: &QubitId) { + match ctrls.len() { + 0 => circ.x(*target), + 1 => circ.cx(*ctrls[0], *target), + 2 => circ.ccx(*ctrls[0], *ctrls[1], *target), + 3 => { + let t = circ.alloc_qubit(); + circ.ccx(*ctrls[0], *ctrls[1], t); + circ.ccx(t, *ctrls[2], *target); + mbu_clear_and(circ, &t, ctrls[0], ctrls[1]); + } + 4 => { + let t01 = circ.alloc_qubit(); + let t23 = circ.alloc_qubit(); + circ.ccx(*ctrls[0], *ctrls[1], t01); + circ.ccx(*ctrls[2], *ctrls[3], t23); + circ.ccx(t01, t23, *target); + mbu_clear_and(circ, &t23, ctrls[2], ctrls[3]); + mbu_clear_and(circ, &t01, ctrls[0], ctrls[1]); + } + 5 => { + let t01 = circ.alloc_qubit(); + let t23 = circ.alloc_qubit(); + let t0123 = circ.alloc_qubit(); + circ.ccx(*ctrls[0], *ctrls[1], t01); + circ.ccx(*ctrls[2], *ctrls[3], t23); + circ.ccx(t01, t23, t0123); + circ.ccx(t0123, *ctrls[4], *target); + mbu_clear_and(circ, &t0123, &t01, &t23); + mbu_clear_and(circ, &t23, ctrls[2], ctrls[3]); + mbu_clear_and(circ, &t01, ctrls[0], ctrls[1]); + } + _ => { + xor_and_of_khattar_gidney_refs(circ, ctrls, target); + } + } +} + +pub fn inc_khattar_gidney(circ: &mut B, a: &[QubitId]) { + let refs: Vec<&QubitId> = a.iter().collect(); + inc_khattar_gidney_refs_inner(circ, &refs, false); +} + +pub fn cinc_khattar_gidney(circ: &mut B, a: &[QubitId], ctrl: &QubitId) { + if a.is_empty() { + return; + } + let mut combined: Vec<&QubitId> = Vec::with_capacity(a.len() + 1); + combined.push(ctrl); + combined.extend(a.iter()); + inc_khattar_gidney_refs_inner(circ, &combined, true); +} + +fn inc_khattar_gidney_refs_inner(circ: &mut B, a: &[&QubitId], skip_lsb_x: bool) { + let n = a.len(); + if n == 0 { + return; + } + if n == 1 { + if !skip_lsb_x { + circ.x(*a[0]); + } + return; + } + + let anc_owned: Vec = (0..kg_prefix_ancilla_count(n - 1)) + .map(|_| circ.alloc_qubit()) + .collect(); + let anc_refs: Vec<&QubitId> = anc_owned.iter().collect(); + let layers = kg_get_layers_for_prefix_and(&a[..n - 1], &anc_refs); + + for layer in &layers { + for &op in &layer.ops { + op.emit(circ); + } + } + for (i, layer) in layers.iter().enumerate().rev() { + if i < n && !(i == 0 && skip_lsb_x) { + kg_apply_prefix_controlled_x(circ, &layer.ctrls, a[i]); + } + for &op in layer.ops.iter().rev() { + op.emit(circ); + } + } + + drop(layers); + drop(anc_refs); + for q in anc_owned { + circ.zero_and_free(q); + } +} diff --git a/src/point_add/trailmix_ludicrous/mod.rs b/src/point_add/trailmix_ludicrous/mod.rs index 1ef074ee..08fda4b0 100644 --- a/src/point_add/trailmix_ludicrous/mod.rs +++ b/src/point_add/trailmix_ludicrous/mod.rs @@ -1,677 +1,500 @@ - -mod arith; -mod codec; -mod comparator; -pub(crate) mod constprop; -pub mod ec_add; -mod fused; -mod gcd; -mod gidney; -mod mcx; -pub mod schedule; -mod square; - -pub use schedule::PAD; - -use super::B; -use crate::circuit::{BitId, Op, OperationType, QubitId}; -use schedule::BAKED_ITERS; -use std::cell::{Cell, RefCell}; -use std::collections::HashMap; - -const N: usize = 256; - -pub(super) trait BExt { - fn loan_zero_qubit(&mut self, q: QubitId); - fn reclaim_zero_qubit(&mut self, q: QubitId); - fn z(&mut self, q: QubitId); - #[track_caller] - fn ccz(&mut self, a: QubitId, b: QubitId, c: QubitId); - fn neg(&mut self); - #[track_caller] - fn cswap(&mut self, ctrl: QubitId, a: QubitId, b: QubitId); - fn x_if_bit(&mut self, q: QubitId, c: BitId); - fn z_if_bit(&mut self, q: QubitId, c: BitId); - fn cz_if_bit(&mut self, a: QubitId, b: QubitId, c: BitId); - - fn zero_and_free(&mut self, q: QubitId); -} - -impl BExt for B { - fn loan_zero_qubit(&mut self, q: QubitId) { - self.free_qubits - .push(q.0.try_into().expect("qubit id fits in u32")); - if self.active_qubits > 0 { - self.active_qubits -= 1; - } - self.record_active_timeline(); - self.b0_on_free(q.0); - } - - fn reclaim_zero_qubit(&mut self, q: QubitId) { - self.reacquire(q); - } - - fn z(&mut self, q: QubitId) { - let mut op = Op::empty(); - op.kind = OperationType::Z; - op.q_target = q; - self.push_op(op); - } - #[track_caller] - fn ccz(&mut self, a: QubitId, b: QubitId, c: QubitId) { - let mut op = Op::empty(); - op.kind = OperationType::CCZ; - op.q_control2 = a; - op.q_control1 = b; - op.q_target = c; - self.push_op(op); - } - fn neg(&mut self) { - let mut op = Op::empty(); - op.kind = OperationType::Neg; - self.push_op(op); - } - #[track_caller] - fn cswap(&mut self, ctrl: QubitId, a: QubitId, b: QubitId) { - self.cx(b, a); - self.ccx(ctrl, a, b); - self.cx(b, a); - } - fn x_if_bit(&mut self, q: QubitId, c: BitId) { - self.push_condition(c); - self.x(q); - self.pop_condition(); - } - fn z_if_bit(&mut self, q: QubitId, c: BitId) { - self.push_condition(c); - self.z(q); - self.pop_condition(); - } - fn cz_if_bit(&mut self, a: QubitId, b: QubitId, c: BitId) { - self.push_condition(c); - self.cz(a, b); - self.pop_condition(); - } - fn zero_and_free(&mut self, q: QubitId) { - self.free(q); - } -} - -#[derive(Default)] -struct Sched { - gcd_k: (Vec, usize), - cout_k: (Vec, usize), - fold: (Vec, usize), - gcd_branch: (Vec, usize), - cmp_k: (Vec, usize), - ffg: (Vec, usize), - hyb_v: (Vec, usize), - sqrow_k: (Vec, usize), -} - -thread_local!(static SCHED: RefCell = RefCell::new(Sched::default())); - -#[derive(Clone, Copy, Debug)] -pub(super) struct ScheduleFit { - pub call_index: usize, - pub base: usize, - pub selected: usize, -} - -thread_local! { - static HYB_CALL_INDEX: Cell = const { Cell::new(0) }; - static COUT_CALL_INDEX: Cell = const { Cell::new(0) }; - static PENDING_COUT_FIT: Cell> = const { Cell::new(None) }; -} - -fn step(slot: &mut (Vec, usize), exhausted: T) -> T { - let v = slot.0.get(slot.1).copied().unwrap_or(exhausted); - slot.1 += 1; - v -} - -fn env_delta(name: &str) -> usize { - std::env::var(name) - .ok() - .and_then(|s| s.parse::().ok()) - .unwrap_or(0) -} - -fn sub_delta(v: usize, name: &str) -> usize { - if v == usize::MAX { - v - } else { - v.saturating_sub(env_delta(name)) - } -} - -fn env_call_value(name: &str, call_index: usize) -> Option { - std::env::var(name).ok().and_then(|value| { - value - .split(',') - .filter_map(|item| item.trim().split_once(':')) - .find_map(|(call, value)| { - (call.parse::().ok()? == call_index) - .then(|| value.parse::().ok()) - .flatten() - }) - }) -} - -fn next_call_index(counter: &'static std::thread::LocalKey>) -> usize { - counter.with(|index| { - let current = index.get(); - index.set(current + 1); - current - }) -} - -fn fit_schedule_value( - base: usize, - call_index: usize, - global_delta: &str, - call_deltas: &str, - call_overrides: &str, -) -> ScheduleFit { - let selected = env_call_value(call_overrides, call_index).unwrap_or_else(|| { - let globally_adjusted = sub_delta(base, global_delta); - match env_call_value(call_deltas, call_index) { - Some(delta) if globally_adjusted != usize::MAX => { - globally_adjusted.saturating_sub(delta) - } - _ => globally_adjusted, - } - }); - ScheduleFit { - call_index, - base, - selected, - } -} - -fn reset_schedule_fit_call_indices() { - HYB_CALL_INDEX.with(|index| index.set(0)); - COUT_CALL_INDEX.with(|index| index.set(0)); - PENDING_COUT_FIT.with(|pending| pending.set(None)); -} - -/// Master kill-switch for every census-derived gate-drop certificate. -/// -/// The `*_has_structurally_dead_*` predicates are keyed by `(call_index, bit)` and were -/// certified against ONE circuit geometry. Widening a comparator, changing a reserve, or -/// shifting a call count repoints those keys onto gates that are live in the new geometry, -/// which silently deletes a required Toffoli. They cannot be disabled via their own env -/// vars: each tests `var_os(..).is_none()` and `set_default_env` only sets when absent, -/// so `NAME=0` leaves them active. -pub(crate) fn drops_off_family(fam: &str) -> bool { - // Raising `schedule::ITERS` adds whole divsteps to each of the four gcd walk - // passes, which renumbers every per-helper call counter these tables are keyed - // by, so a key that named a dead gate now names a LIVE one. Retire the family - // automatically rather than relying on an env var nobody remembers to set. - if !schedule::baked_artifacts_valid() { - return true; - } - if std::env::var_os("TLM_DROPS_OFF").is_some() { - return true; - } - match std::env::var("TLM_DROPS_OFF_ONLY") { - Ok(list) => list.split(',').any(|t| t.trim() == fam), - Err(_) => false, - } -} - -fn target_qubit_headroom(circ: &B) -> Option { - std::env::var("TLM_TARGET_Q") - .ok() - .and_then(|value| value.parse::().ok()) - .map(|target| target.saturating_sub(circ.active_qubits as usize)) -} - -fn next_gcd_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().gcd_k, usize::MAX)) } -fn next_cout_k() -> usize { - let base = SCHED.with(|s| step(&mut s.borrow_mut().cout_k, usize::MAX)); - let fit = fit_schedule_value( - base, - next_call_index(&COUT_CALL_INDEX), - "TLM_COUT_K_DELTA", - "TLM_COUT_K_CALL_DELTAS", - "TLM_COUT_K_CALL_OVERRIDES", - ); - PENDING_COUT_FIT.with(|pending| { - debug_assert!(pending.get().is_none(), "previous COUT schedule call was not consumed"); - pending.set(Some(fit)); - }); - fit.selected -} -fn next_fold() -> i32 { - SCHED.with(|s| { - let v = step(&mut s.borrow_mut().fold, i32::MAX); - let d = env_delta("TLM_FOLD_DELTA") as i32; - if v == i32::MAX || v < 0 || d == 0 { - v - } else { - v.saturating_sub(d) - } - }) -} -fn next_gcd_branch() -> u8 { SCHED.with(|s| step(&mut s.borrow_mut().gcd_branch, 255)) } -fn next_cmp_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().cmp_k, usize::MAX)) } -fn next_ffg() -> usize { SCHED.with(|s| sub_delta(step(&mut s.borrow_mut().ffg, usize::MAX), "TLM_FFG_DELTA")) } -fn next_hyb_v_fit() -> ScheduleFit { - let base = SCHED.with(|s| step(&mut s.borrow_mut().hyb_v, usize::MAX)); - fit_schedule_value( - base, - next_call_index(&HYB_CALL_INDEX), - "TLM_HYB_V_DELTA", - "TLM_HYB_V_CALL_DELTAS", - "TLM_HYB_V_CALL_OVERRIDES", - ) -} - -fn take_cout_fit(selected: usize) -> ScheduleFit { - PENDING_COUT_FIT.with(|pending| { - pending.take().unwrap_or_else(|| { - fit_schedule_value( - selected, - next_call_index(&COUT_CALL_INDEX), - "TLM_COUT_K_DELTA", - "TLM_COUT_K_CALL_DELTAS", - "TLM_COUT_K_CALL_OVERRIDES", - ) - }) - }) -} -fn next_sqrow_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().sqrow_k, usize::MAX)) } - -/// A baked vector is a concatenation of one contiguous block per gcd walk pass, -/// each block being `len` entries long; `forward` says whether the pass walks -/// the divstep index UP from the start of its block (forward walks) or DOWN -/// from it (reverse walks, which are indexed from the top and are therefore -/// anchored to the constant `BAKED_ITERS - 1`). -type SchedBlocks = [(usize, bool)]; - -const BLOCKS_4: &SchedBlocks = &[ - (BAKED_ITERS, true), - (BAKED_ITERS, false), - (BAKED_ITERS, true), - (BAKED_ITERS, false), -]; -const BLOCKS_2: &SchedBlocks = &[(BAKED_ITERS, true), (BAKED_ITERS, false)]; -const BLOCKS_4_SHORT: &SchedBlocks = &[ - (BAKED_ITERS - 1, true), - (BAKED_ITERS - 1, false), - (BAKED_ITERS - 1, true), - (BAKED_ITERS - 1, false), -]; -const BLOCKS_2_SHORT: &SchedBlocks = &[(BAKED_ITERS - 1, true), (BAKED_ITERS - 1, false)]; -const BLOCKS_FFG: &SchedBlocks = &[(BAKED_ITERS - 1, true), (BAKED_ITERS, false)]; - -/// Re-fit a baked vector to the current `ITERS`. -/// -/// The vectors are read through a single sequential cursor per vector, so the -/// start of every pass's block is implicitly `sum of earlier block lengths`. -/// Those lengths are `BAKED_ITERS`(-1), and a reverse pass additionally indexes -/// its block from the top. Both anchors are hard-wired to the fitted schedule. -/// Raising `ITERS` therefore slides every block boundary: pass 0 overruns its -/// block into pass 1's, pass 1 starts mid-block, and each pass ends up reading -/// values fitted for a *different* divstep, so the reverse walk stops being the -/// exact inverse of the forward walk it has to undo. -/// -/// Widening each block in place restores the (pass, divstep) keying. The added -/// divsteps run at the terminal register width (`SCHED_J2` holds at 11), so they -/// take the terminal entry of their block: the last for a forward block, the -/// first for a reverse block -- which is the same divstep's value from either -/// end. Measured worth 2 qubits of peak (1155 -> 1153) for 214 CCX at -/// `ITERS = 261`. With `ITERS == BAKED_ITERS` it is the identity, so the -/// shipped op stream stays byte-identical. -fn widen_sched_blocks(base: &[T], blocks: &SchedBlocks) -> Vec { - let extra = schedule::ITERS.saturating_sub(BAKED_ITERS); - if extra == 0 { - return base.to_vec(); - } - let mut out = Vec::with_capacity(base.len() + extra * blocks.len()); - let mut at = 0usize; - for &(len, forward) in blocks { - let block = &base[at..at + len]; - let fill = if forward { block[len - 1] } else { block[0] }; - if !forward { - out.extend(std::iter::repeat_n(fill, extra)); - } - out.extend_from_slice(block); - if forward { - out.extend(std::iter::repeat_n(fill, extra)); - } - at += len; - } - // Trailing entries no pass reads (FFG_G carries one spare). - out.extend_from_slice(&base[at..]); - out -} -fn load_schedule() { - reset_schedule_fit_call_indices(); - arith::reset_ffg_call_index(); - comparator::reset_compare_call_index(); - fused::reset_fold_call_index(); - gcd::reset_gcd_trace_call_index(); - gidney::reset_gidney_call_index(); - SCHED.with(|s| { - let mut s = s.borrow_mut(); - *s = Sched::default(); - let extra_fold_vents = std::env::var("LUD_EXTRA_FOLD_VENTS") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(0); - let extra_fold_min_g = std::env::var("LUD_EXTRA_FOLD_MIN_G") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(0); - let extra_fold_max_g = std::env::var("LUD_EXTRA_FOLD_MAX_G") - .ok() - .and_then(|v| v.parse::().ok()) - .unwrap_or(usize::MAX); - let fold_g = |v: &[usize]| -> Vec { - v.iter() - .map(|&x| { - if extra_fold_vents > 0 - && x >= extra_fold_min_g - && x <= extra_fold_max_g - { - x.saturating_add(extra_fold_vents).min(53) - } else { - x - } - }) - .collect() - }; - s.gcd_k.0 = widen_sched_blocks(&schedule::GCD_SUB_K, BLOCKS_4); - s.gcd_branch.0 = widen_sched_blocks(&schedule::GCD_BRANCH, BLOCKS_4); - s.cout_k.0 = widen_sched_blocks(&schedule::APPLY_COUT_K, BLOCKS_2); - s.fold.0 = widen_sched_blocks(&schedule::FOLD_SCHED, BLOCKS_2_SHORT); - s.cmp_k.0 = widen_sched_blocks(schedule::CMP_K, BLOCKS_4_SHORT); - s.ffg.0 = widen_sched_blocks(&fold_g(schedule::FFG_G), BLOCKS_FFG); - // HYB_V is consumed only for divsteps i <= 201, so both of its blocks are - // 585 entries at any ITERS > 202 and its boundary does not move. - s.hyb_v.0 = schedule::HYB_V.to_vec(); - s.sqrow_k.0 = schedule::SQ_ROW_K.to_vec(); - }); -} - -fn route_swaps(src: &[QubitId], dst: &[QubitId]) -> Vec<(QubitId, QubitId)> { - let mut loc: Vec = src.to_vec(); - let mut at: HashMap = HashMap::new(); - for (i, q) in src.iter().enumerate() { - at.insert(q.0, i); - } - let mut swaps = Vec::new(); - for i in 0..dst.len() { - let target = dst[i]; - let cur = loc[i]; - if cur == target { - continue; - } - swaps.push((target, cur)); - let displaced = at.get(&target.0).copied(); - at.insert(target.0, i); - loc[i] = target; - match displaced { - Some(b) => { - at.insert(cur.0, b); - loc[b] = cur; - } - None => { - at.remove(&cur.0); - } - } - } - swaps -} - -fn install_q1153_submission_defaults() { - for (name, value) in [ - ("TLM_TARGET_Q", "1150"), - ("TLM_FOLD_CHUNK_ZERO_CIN", "1"), - ("TLM_FFG_MAX_G", "47"), - ("TLM_APPLY_ADD_SKIP_LASTK", "1"), - ("DIALOG_TAIL_NONCE", "2430844"), - ] { - - if (name == "DIALOG_TAIL_NONCE" - || name == "TLM_TARGET_Q" - || name == "TLM_APPLY_ADD_SKIP_LASTK" - || name == "TLM_FFG_MAX_G" - || name == "TLM_FOLD_CHUNK_ZERO_CIN") - && std::env::var_os(name).is_some() - { - continue; - } else { - std::env::set_var(name, value); - } - } -} - -pub fn build_trailmix_ludicrous_ops() -> Vec { - install_q1153_submission_defaults(); - let mut circ = B::new(); - load_schedule(); - - let x2 = circ.alloc_qubits(N); - let y2 = circ.alloc_qubits(N); - let ox = circ.alloc_bits(N); - let oy = circ.alloc_bits(N); - - let x2_init = x2.clone(); - let mut x2m = x2; - ec_add::ec_add(&mut circ, &mut x2m, &y2, &ox, &oy); - - circ.declare_qubit_register(&x2_init); - circ.declare_qubit_register(&y2); - circ.declare_bit_register(&ox); - circ.declare_bit_register(&oy); - - for (a, b) in route_swaps(&x2m, &x2_init) { - circ.swap(a, b); - } - - if let Some(nonce) = std::env::var("DIALOG_TAIL_NONCE") - .ok() - .and_then(|s| s.parse::().ok()) - { - for i in 0..48u32 { - let q = if (nonce >> i) & 1 == 1 { x2_init[1] } else { x2_init[0] }; - circ.x(q); - circ.x(q); - } - } - - circ.b0_finalize(); - - if std::env::var("TRACE_TLM_PROFILE").is_ok() { - circ.close_phase_active_region(); - eprintln!( - "TLM_PROFILE peak_qubits={} peak_phase={} peak_ops_idx={} emitted_ops={}", - circ.peak_qubits, - circ.peak_phase, - circ.peak_ops_idx, - circ.current_ops_len(), - ); - let mut phases: Vec<_> = circ.phase_active_max.iter().collect(); - phases.sort_by(|left, right| right.1.cmp(left.1).then_with(|| left.0.cmp(right.0))); - for (phase, active) in phases.into_iter().take(24) { - eprintln!("TLM_PHASE active_max={active} phase={phase}"); - } - } - - if std::env::var("TLM_TIMELINE_DUMP").is_ok() { - let trans = &circ.phase_transitions; - let phase_at = |op: usize| -> &'static str { - - let mut lo = 0usize; - let mut hi = trans.len(); - let mut ans = "init"; - while lo < hi { - let mid = (lo + hi) / 2; - if trans[mid].0 <= op { - ans = trans[mid].1; - lo = mid + 1; - } else { - hi = mid; - } - } - ans - }; - let minq: u32 = std::env::var("TLM_TIMELINE_MIN") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(1136); - - use std::collections::BTreeMap; - let mut census: BTreeMap<&'static str, (u32, usize, usize)> = BTreeMap::new(); - for &(op, active) in &circ.active_timeline { - if active >= minq { - let ph = phase_at(op); - let e = census.entry(ph).or_insert((0, 0, op)); - if active > e.0 { - e.0 = active; - e.2 = op; - } - e.1 += 1; - } - } - let mut rows: Vec<_> = census.into_iter().collect(); - rows.sort_by(|a, b| b.1 .0.cmp(&a.1 .0).then_with(|| a.0.cmp(b.0))); - eprintln!("TLM_TIMELINE census (samples with active>={minq}), phase: max_active n_samples example_op"); - for (ph, (mx, n, ex)) in &rows { - eprintln!("TL_CENSUS phase={ph} max_active={mx} n_samples={n} example_op={ex}"); - } - - if let (Ok(lo), Ok(hi)) = ( - std::env::var("TLM_WIN_LO").map(|s| s.parse::().unwrap_or(0)), - std::env::var("TLM_WIN_HI").map(|s| s.parse::().unwrap_or(usize::MAX)), - ) { - eprintln!("TLM_TIMELINE raw window [{lo},{hi}] : op active phase"); - for &(op, active) in &circ.active_timeline { - if op >= lo && op <= hi { - eprintln!("TL_RAW op={op} active={active} phase={}", phase_at(op)); - } - } - } - } - - if std::env::var("TRACE_TLM_CCX").is_ok() { - use std::collections::BTreeMap; - let mut bounds = circ.phase_transitions.clone(); - bounds.sort_by_key(|(i, _)| *i); - let total = circ.ops.len(); - let mut by: BTreeMap<&'static str, usize> = BTreeMap::new(); - for w in 0..bounds.len() { - let s = bounds[w].0.min(total); - let e = if w + 1 < bounds.len() { bounds[w + 1].0.min(total) } else { total }; - let c = circ.ops[s..e].iter().filter(|op| op.kind as u32 == 13).count(); - *by.entry(bounds[w].1).or_insert(0) += c; - } - let grand: usize = by.values().sum(); - let mut v: Vec<_> = by.into_iter().collect(); - v.sort_by(|a, b| b.1.cmp(&a.1)); - let mut cum = 0usize; - for (phase, c) in v.iter().take(30) { - cum += *c; - eprintln!( - "TLM_CCX phase={phase} ccx={c} pct={:.2} cum={:.2}", - 100.0 * *c as f64 / grand as f64, - 100.0 * cum as f64 / grand as f64 - ); - } - eprintln!("TLM_CCX_TOTAL {grand} phases={}", v.len()); - } - - if std::env::var("TRACE_TLM_TOF").is_ok() { - use std::collections::BTreeMap; - let mut bounds = circ.phase_transitions.clone(); - bounds.sort_by_key(|(i, _)| *i); - let total = circ.ops.len(); - let mut phase_of: Vec<&'static str> = Vec::with_capacity(total); - for w in 0..bounds.len() { - let s = bounds[w].0.min(total); - let e = if w + 1 < bounds.len() { bounds[w + 1].0.min(total) } else { total }; - while phase_of.len() < s { - phase_of.push("
");
-            }
-            for _ in s..e {
-                phase_of.push(bounds[w].1);
-            }
-        }
-        while phase_of.len() < total {
-            phase_of.push("");
-        }
-        // p1[bit] = P(bit == 1). hmr/r -> 1/2, store0 -> 0, store1 -> 1, invert -> 1-p.
-        let mut p1: std::collections::HashMap = std::collections::HashMap::new();
-        let mut stack: Vec = Vec::new();
-        let mut cur = 1.0f64;
-        // (emitted, expected_executed)
-        let mut by: BTreeMap<&'static str, (usize, f64)> = BTreeMap::new();
-        for (i, op) in circ.ops.iter().enumerate() {
-            let k = op.kind as u32;
-            let local = if op.c_condition == crate::circuit::NO_BIT {
-                cur
-            } else {
-                cur * p1.get(&op.c_condition.0).copied().unwrap_or(1.0)
-            };
-            match k {
-                12 => {
-                    p1.insert(op.c_target.0, 0.5 * local + p1.get(&op.c_target.0).copied().unwrap_or(0.0) * (1.0 - local));
-                }
-                4 => {
-                    let prev = p1.get(&op.c_target.0).copied().unwrap_or(0.0);
-                    p1.insert(op.c_target.0, prev * (1.0 - local));
-                }
-                5 => {
-                    let prev = p1.get(&op.c_target.0).copied().unwrap_or(0.0);
-                    p1.insert(op.c_target.0, local + prev * (1.0 - local));
-                }
-                3 => {
-                    let prev = p1.get(&op.c_target.0).copied().unwrap_or(0.0);
-                    p1.insert(op.c_target.0, local * (1.0 - prev) + (1.0 - local) * prev);
-                }
-                15 => {
-                    stack.push(cur);
-                    cur = local;
-                }
-                16 => {
-                    cur = stack.pop().unwrap_or(1.0);
-                }
-                13 | 14 => {
-                    let e = by.entry(phase_of[i]).or_insert((0, 0.0));
-                    e.0 += 1;
-                    e.1 += local;
-                }
-                _ => {}
-            }
-        }
-        let ge: usize = by.values().map(|v| v.0).sum();
-        let gx: f64 = by.values().map(|v| v.1).sum();
-        let mut v: Vec<_> = by.into_iter().collect();
-        v.sort_by(|a, b| b.1 .1.partial_cmp(&a.1 .1).unwrap());
-        for (phase, (em, ex)) in v.iter() {
-            eprintln!(
-                "TLM_TOF phase={phase} emitted={em} expected={:.1} discount={:.3}",
-                ex,
-                1.0 - ex / *em as f64
-            );
-        }
-        eprintln!("TLM_TOF_TOTAL emitted={ge} expected={gx:.1} discount={:.4}", 1.0 - gx / ge as f64);
-    }
-
-    let ops = std::mem::take(&mut circ.ops);
-
-    if std::env::var_os("TLM_DIRTY_SCAN").is_some() {
-        crate::point_add::dirtyscan::scan(&ops, &circ.phase_transitions);
-    }
-
-    if std::env::var("CONSTPROP_DISABLE").ok().as_deref() == Some("1") {
-        return ops;
-    }
-    let mut input_qubits = x2_init.clone();
-    input_qubits.extend_from_slice(&y2);
-    constprop::run(ops, &input_qubits)
-}
+
+mod arith;
+mod codec;
+mod comparator;
+mod constprop;
+pub mod ec_add;
+mod fused;
+mod gcd;
+mod gidney;
+mod mcx;
+pub mod schedule;
+mod square;
+
+pub use schedule::PAD;
+
+use super::B;
+use crate::circuit::{BitId, Op, OperationType, QubitId};
+use std::cell::{Cell, RefCell};
+use std::collections::HashMap;
+
+const N: usize = 256;
+
+pub(super) trait BExt {
+    fn loan_zero_qubit(&mut self, q: QubitId);
+    fn reclaim_zero_qubit(&mut self, q: QubitId);
+    fn z(&mut self, q: QubitId);
+    #[track_caller]
+    fn ccz(&mut self, a: QubitId, b: QubitId, c: QubitId);
+    fn neg(&mut self);
+    #[track_caller]
+    fn cswap(&mut self, ctrl: QubitId, a: QubitId, b: QubitId);
+    fn x_if_bit(&mut self, q: QubitId, c: BitId);
+    fn z_if_bit(&mut self, q: QubitId, c: BitId);
+    fn cz_if_bit(&mut self, a: QubitId, b: QubitId, c: BitId);
+
+    fn zero_and_free(&mut self, q: QubitId);
+}
+
+impl BExt for B {
+    fn loan_zero_qubit(&mut self, q: QubitId) {
+        self.free_qubits
+            .push(q.0.try_into().expect("qubit id fits in u32"));
+        if self.active_qubits > 0 {
+            self.active_qubits -= 1;
+        }
+        self.record_active_timeline();
+        self.b0_on_free(q.0);
+    }
+
+    fn reclaim_zero_qubit(&mut self, q: QubitId) {
+        self.reacquire(q);
+    }
+
+    fn z(&mut self, q: QubitId) {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q;
+        self.push_op(op);
+    }
+    #[track_caller]
+    fn ccz(&mut self, a: QubitId, b: QubitId, c: QubitId) {
+        let mut op = Op::empty();
+        op.kind = OperationType::CCZ;
+        op.q_control2 = a;
+        op.q_control1 = b;
+        op.q_target = c;
+        self.push_op(op);
+    }
+    fn neg(&mut self) {
+        let mut op = Op::empty();
+        op.kind = OperationType::Neg;
+        self.push_op(op);
+    }
+    #[track_caller]
+    fn cswap(&mut self, ctrl: QubitId, a: QubitId, b: QubitId) {
+        self.cx(b, a);
+        self.ccx(ctrl, a, b);
+        self.cx(b, a);
+    }
+    fn x_if_bit(&mut self, q: QubitId, c: BitId) {
+        self.push_condition(c);
+        self.x(q);
+        self.pop_condition();
+    }
+    fn z_if_bit(&mut self, q: QubitId, c: BitId) {
+        self.push_condition(c);
+        self.z(q);
+        self.pop_condition();
+    }
+    fn cz_if_bit(&mut self, a: QubitId, b: QubitId, c: BitId) {
+        self.push_condition(c);
+        self.cz(a, b);
+        self.pop_condition();
+    }
+    fn zero_and_free(&mut self, q: QubitId) {
+        self.free(q);
+    }
+}
+
+#[derive(Default)]
+struct Sched {
+    gcd_k: (Vec, usize),
+    cout_k: (Vec, usize),
+    fold: (Vec, usize),
+    gcd_branch: (Vec, usize),
+    cmp_k: (Vec, usize),
+    ffg: (Vec, usize),
+    hyb_v: (Vec, usize),
+    sqrow_k: (Vec, usize),
+}
+
+thread_local!(static SCHED: RefCell = RefCell::new(Sched::default()));
+
+#[derive(Clone, Copy, Debug)]
+pub(super) struct ScheduleFit {
+    pub call_index: usize,
+    pub base: usize,
+    pub selected: usize,
+}
+
+thread_local! {
+    static HYB_CALL_INDEX: Cell = const { Cell::new(0) };
+    static COUT_CALL_INDEX: Cell = const { Cell::new(0) };
+    static PENDING_COUT_FIT: Cell> = const { Cell::new(None) };
+}
+
+fn step(slot: &mut (Vec, usize), exhausted: T) -> T {
+    let v = slot.0.get(slot.1).copied().unwrap_or(exhausted);
+    slot.1 += 1;
+    v
+}
+
+fn env_delta(name: &str) -> usize {
+    std::env::var(name)
+        .ok()
+        .and_then(|s| s.parse::().ok())
+        .unwrap_or(0)
+}
+
+fn sub_delta(v: usize, name: &str) -> usize {
+    if v == usize::MAX {
+        v
+    } else {
+        v.saturating_sub(env_delta(name))
+    }
+}
+
+fn env_call_value(name: &str, call_index: usize) -> Option {
+    std::env::var(name).ok().and_then(|value| {
+        value
+            .split(',')
+            .filter_map(|item| item.trim().split_once(':'))
+            .find_map(|(call, value)| {
+                (call.parse::().ok()? == call_index)
+                    .then(|| value.parse::().ok())
+                    .flatten()
+            })
+    })
+}
+
+fn next_call_index(counter: &'static std::thread::LocalKey>) -> usize {
+    counter.with(|index| {
+        let current = index.get();
+        index.set(current + 1);
+        current
+    })
+}
+
+fn fit_schedule_value(
+    base: usize,
+    call_index: usize,
+    global_delta: &str,
+    call_deltas: &str,
+    call_overrides: &str,
+) -> ScheduleFit {
+    let selected = env_call_value(call_overrides, call_index).unwrap_or_else(|| {
+        let globally_adjusted = sub_delta(base, global_delta);
+        match env_call_value(call_deltas, call_index) {
+            Some(delta) if globally_adjusted != usize::MAX => {
+                globally_adjusted.saturating_sub(delta)
+            }
+            _ => globally_adjusted,
+        }
+    });
+    ScheduleFit {
+        call_index,
+        base,
+        selected,
+    }
+}
+
+fn reset_schedule_fit_call_indices() {
+    HYB_CALL_INDEX.with(|index| index.set(0));
+    COUT_CALL_INDEX.with(|index| index.set(0));
+    PENDING_COUT_FIT.with(|pending| pending.set(None));
+}
+
+fn target_qubit_headroom(circ: &B) -> Option {
+    std::env::var("TLM_TARGET_Q")
+        .ok()
+        .and_then(|value| value.parse::().ok())
+        .map(|target| target.saturating_sub(circ.active_qubits as usize))
+}
+
+fn next_gcd_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().gcd_k, usize::MAX)) }
+fn next_cout_k() -> usize {
+    let base = SCHED.with(|s| step(&mut s.borrow_mut().cout_k, usize::MAX));
+    let fit = fit_schedule_value(
+        base,
+        next_call_index(&COUT_CALL_INDEX),
+        "TLM_COUT_K_DELTA",
+        "TLM_COUT_K_CALL_DELTAS",
+        "TLM_COUT_K_CALL_OVERRIDES",
+    );
+    PENDING_COUT_FIT.with(|pending| {
+        debug_assert!(pending.get().is_none(), "previous COUT schedule call was not consumed");
+        pending.set(Some(fit));
+    });
+    fit.selected
+}
+fn next_fold() -> i32 {
+    SCHED.with(|s| {
+        let v = step(&mut s.borrow_mut().fold, i32::MAX);
+        let d = env_delta("TLM_FOLD_DELTA") as i32;
+        if v == i32::MAX || v < 0 || d == 0 {
+            v
+        } else {
+            v.saturating_sub(d)
+        }
+    })
+}
+fn next_gcd_branch() -> u8 { SCHED.with(|s| step(&mut s.borrow_mut().gcd_branch, 255)) }
+fn next_cmp_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().cmp_k, usize::MAX)) }
+fn next_ffg() -> usize { SCHED.with(|s| sub_delta(step(&mut s.borrow_mut().ffg, usize::MAX), "TLM_FFG_DELTA")) }
+fn next_hyb_v_fit() -> ScheduleFit {
+    let base = SCHED.with(|s| step(&mut s.borrow_mut().hyb_v, usize::MAX));
+    fit_schedule_value(
+        base,
+        next_call_index(&HYB_CALL_INDEX),
+        "TLM_HYB_V_DELTA",
+        "TLM_HYB_V_CALL_DELTAS",
+        "TLM_HYB_V_CALL_OVERRIDES",
+    )
+}
+
+fn take_cout_fit(selected: usize) -> ScheduleFit {
+    PENDING_COUT_FIT.with(|pending| {
+        pending.take().unwrap_or_else(|| {
+            fit_schedule_value(
+                selected,
+                next_call_index(&COUT_CALL_INDEX),
+                "TLM_COUT_K_DELTA",
+                "TLM_COUT_K_CALL_DELTAS",
+                "TLM_COUT_K_CALL_OVERRIDES",
+            )
+        })
+    })
+}
+fn next_sqrow_k() -> usize { SCHED.with(|s| step(&mut s.borrow_mut().sqrow_k, usize::MAX)) }
+
+fn load_schedule() {
+    reset_schedule_fit_call_indices();
+    arith::reset_ffg_call_index();
+    comparator::reset_compare_call_index();
+    fused::reset_fold_call_index();
+    gcd::reset_gcd_trace_call_index();
+    gidney::reset_gidney_call_index();
+    SCHED.with(|s| {
+        let mut s = s.borrow_mut();
+        *s = Sched::default();
+        let extra_fold_vents = std::env::var("LUD_EXTRA_FOLD_VENTS")
+            .ok()
+            .and_then(|v| v.parse::().ok())
+            .unwrap_or(0);
+        let extra_fold_min_g = std::env::var("LUD_EXTRA_FOLD_MIN_G")
+            .ok()
+            .and_then(|v| v.parse::().ok())
+            .unwrap_or(0);
+        let extra_fold_max_g = std::env::var("LUD_EXTRA_FOLD_MAX_G")
+            .ok()
+            .and_then(|v| v.parse::().ok())
+            .unwrap_or(usize::MAX);
+        let fold_g = |v: &[usize]| -> Vec {
+            v.iter()
+                .map(|&x| {
+                    if extra_fold_vents > 0
+                        && x >= extra_fold_min_g
+                        && x <= extra_fold_max_g
+                    {
+                        x.saturating_add(extra_fold_vents).min(53)
+                    } else {
+                        x
+                    }
+                })
+                .collect()
+        };
+        s.gcd_k.0 = schedule::GCD_SUB_K.to_vec();
+        s.gcd_branch.0 = schedule::GCD_BRANCH.to_vec();
+        s.cout_k.0 = schedule::APPLY_COUT_K.to_vec();
+        s.fold.0 = schedule::FOLD_SCHED.to_vec();
+        s.cmp_k.0 = schedule::CMP_K.to_vec();
+        s.ffg.0 = fold_g(schedule::FFG_G);
+        s.hyb_v.0 = schedule::HYB_V.to_vec();
+        s.sqrow_k.0 = schedule::SQ_ROW_K.to_vec();
+    });
+}
+
+fn route_swaps(src: &[QubitId], dst: &[QubitId]) -> Vec<(QubitId, QubitId)> {
+    let mut loc: Vec = src.to_vec();
+    let mut at: HashMap = HashMap::new();
+    for (i, q) in src.iter().enumerate() {
+        at.insert(q.0, i);
+    }
+    let mut swaps = Vec::new();
+    for i in 0..dst.len() {
+        let target = dst[i];
+        let cur = loc[i];
+        if cur == target {
+            continue;
+        }
+        swaps.push((target, cur));
+        let displaced = at.get(&target.0).copied();
+        at.insert(target.0, i);
+        loc[i] = target;
+        match displaced {
+            Some(b) => {
+                at.insert(cur.0, b);
+                loc[b] = cur;
+            }
+            None => {
+                at.remove(&cur.0);
+            }
+        }
+    }
+    swaps
+}
+
+fn install_q1153_submission_defaults() {
+    for (name, value) in [
+        ("TLM_TARGET_Q", "1152"),
+        ("TLM_FOLD_CHUNK_ZERO_CIN", "1"),
+        ("TLM_FFG_MAX_G", "47"),
+        ("TLM_APPLY_ADD_SKIP_LASTK", "1"),
+        ("DIALOG_TAIL_NONCE", "2430844"),
+    ] {
+
+        if (name == "DIALOG_TAIL_NONCE" || name == "TLM_TARGET_Q")
+            && std::env::var_os(name).is_some()
+        {
+            continue;
+        } else {
+            std::env::set_var(name, value);
+        }
+    }
+}
+
+pub fn build_trailmix_ludicrous_ops() -> Vec {
+    install_q1153_submission_defaults();
+    let mut circ = B::new();
+    load_schedule();
+
+    let x2 = circ.alloc_qubits(N);
+    let y2 = circ.alloc_qubits(N);
+    let ox = circ.alloc_bits(N);
+    let oy = circ.alloc_bits(N);
+
+    let x2_init = x2.clone();
+    let mut x2m = x2;
+    ec_add::ec_add(&mut circ, &mut x2m, &y2, &ox, &oy);
+
+    circ.declare_qubit_register(&x2_init);
+    circ.declare_qubit_register(&y2);
+    circ.declare_bit_register(&ox);
+    circ.declare_bit_register(&oy);
+
+    for (a, b) in route_swaps(&x2m, &x2_init) {
+        circ.swap(a, b);
+    }
+
+    if let Some(nonce) = std::env::var("DIALOG_TAIL_NONCE")
+        .ok()
+        .and_then(|s| s.parse::().ok())
+    {
+        for i in 0..48u32 {
+            let q = if (nonce >> i) & 1 == 1 { x2_init[1] } else { x2_init[0] };
+            circ.x(q);
+            circ.x(q);
+        }
+    }
+
+    circ.b0_finalize();
+
+    if std::env::var("TRACE_TLM_PROFILE").is_ok() {
+        circ.close_phase_active_region();
+        eprintln!(
+            "TLM_PROFILE peak_qubits={} peak_phase={} peak_ops_idx={} emitted_ops={}",
+            circ.peak_qubits,
+            circ.peak_phase,
+            circ.peak_ops_idx,
+            circ.current_ops_len(),
+        );
+        let mut phases: Vec<_> = circ.phase_active_max.iter().collect();
+        phases.sort_by(|left, right| right.1.cmp(left.1).then_with(|| left.0.cmp(right.0)));
+        for (phase, active) in phases.into_iter().take(24) {
+            eprintln!("TLM_PHASE active_max={active} phase={phase}");
+        }
+    }
+
+    if std::env::var("TLM_TIMELINE_DUMP").is_ok() {
+        let trans = &circ.phase_transitions;
+        let phase_at = |op: usize| -> &'static str {
+
+            let mut lo = 0usize;
+            let mut hi = trans.len();
+            let mut ans = "init";
+            while lo < hi {
+                let mid = (lo + hi) / 2;
+                if trans[mid].0 <= op {
+                    ans = trans[mid].1;
+                    lo = mid + 1;
+                } else {
+                    hi = mid;
+                }
+            }
+            ans
+        };
+        let minq: u32 = std::env::var("TLM_TIMELINE_MIN")
+            .ok()
+            .and_then(|s| s.parse().ok())
+            .unwrap_or(1136);
+
+        use std::collections::BTreeMap;
+        let mut census: BTreeMap<&'static str, (u32, usize, usize)> = BTreeMap::new();
+        for &(op, active) in &circ.active_timeline {
+            if active >= minq {
+                let ph = phase_at(op);
+                let e = census.entry(ph).or_insert((0, 0, op));
+                if active > e.0 {
+                    e.0 = active;
+                    e.2 = op;
+                }
+                e.1 += 1;
+            }
+        }
+        let mut rows: Vec<_> = census.into_iter().collect();
+        rows.sort_by(|a, b| b.1 .0.cmp(&a.1 .0).then_with(|| a.0.cmp(b.0)));
+        eprintln!("TLM_TIMELINE census (samples with active>={minq}), phase: max_active n_samples example_op");
+        for (ph, (mx, n, ex)) in &rows {
+            eprintln!("TL_CENSUS phase={ph} max_active={mx} n_samples={n} example_op={ex}");
+        }
+
+        if let (Ok(lo), Ok(hi)) = (
+            std::env::var("TLM_WIN_LO").map(|s| s.parse::().unwrap_or(0)),
+            std::env::var("TLM_WIN_HI").map(|s| s.parse::().unwrap_or(usize::MAX)),
+        ) {
+            eprintln!("TLM_TIMELINE raw window [{lo},{hi}] : op active phase");
+            for &(op, active) in &circ.active_timeline {
+                if op >= lo && op <= hi {
+                    eprintln!("TL_RAW op={op} active={active} phase={}", phase_at(op));
+                }
+            }
+        }
+    }
+
+    if std::env::var("TRACE_TLM_CCX").is_ok() {
+        use std::collections::BTreeMap;
+        let mut bounds = circ.phase_transitions.clone();
+        bounds.sort_by_key(|(i, _)| *i);
+        let total = circ.ops.len();
+        let mut by: BTreeMap<&'static str, usize> = BTreeMap::new();
+        for w in 0..bounds.len() {
+            let s = bounds[w].0.min(total);
+            let e = if w + 1 < bounds.len() { bounds[w + 1].0.min(total) } else { total };
+            let c = circ.ops[s..e].iter().filter(|op| op.kind as u32 == 13).count();
+            *by.entry(bounds[w].1).or_insert(0) += c;
+        }
+        let grand: usize = by.values().sum();
+        let mut v: Vec<_> = by.into_iter().collect();
+        v.sort_by(|a, b| b.1.cmp(&a.1));
+        let mut cum = 0usize;
+        for (phase, c) in v.iter().take(30) {
+            cum += *c;
+            eprintln!(
+                "TLM_CCX phase={phase} ccx={c} pct={:.2} cum={:.2}",
+                100.0 * *c as f64 / grand as f64,
+                100.0 * cum as f64 / grand as f64
+            );
+        }
+        eprintln!("TLM_CCX_TOTAL {grand} phases={}", v.len());
+    }
+
+    let ops = std::mem::take(&mut circ.ops);
+
+    if std::env::var("CONSTPROP_DISABLE").ok().as_deref() == Some("1") {
+        return ops;
+    }
+    let mut input_qubits = x2_init.clone();
+    input_qubits.extend_from_slice(&y2);
+    constprop::run(ops, &input_qubits)
+}
diff --git a/src/point_add/trailmix_ludicrous/schedule.rs b/src/point_add/trailmix_ludicrous/schedule.rs
index c6c57d04..543a576c 100644
--- a/src/point_add/trailmix_ludicrous/schedule.rs
+++ b/src/point_add/trailmix_ludicrous/schedule.rs
@@ -1,73 +1,86 @@
-
-pub const JUMP: usize = 2;
-
-pub const ITERS: usize = 261;
-
-/// The divstep count that every baked artefact in this crate was fitted
-/// against: the eight schedule vectors below, and every census-mined dead-gate
-/// certificate (those are keyed by bare per-helper call counters or by absolute
-/// op ordinals). `ITERS` may move; this constant may not. When the two differ
-/// the schedule vectors are re-blocked (`widen_sched_blocks`) and the
-/// certificates are retired (`apply_drops_off`, and the deep strip in `build`).
-pub const BAKED_ITERS: usize = 258;
-
-#[must_use]
-pub fn baked_artifacts_valid() -> bool {
-    ITERS == BAKED_ITERS
-}
-
-pub const PAD: usize = 20;
-
-pub static SCHED_J2: &[u16] = &[256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 173, 172, 170, 169, 168, 167, 166, 164, 162, 162, 161, 160, 158, 158, 157, 155, 155, 154, 153, 152, 151, 150, 149, 147, 146, 145, 144, 143, 143, 142, 141, 139, 139, 138, 137, 136, 135, 134, 133, 132, 131, 129, 128, 127, 126, 125, 124, 124, 123, 122, 120, 120, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 24, 23, 22, 21, 20, 19, 19, 18, 18, 17, 16, 15, 15, 14, 14, 14, 12, 12, 10, 9, 9, 9, 9];
-
-pub static GAP_J2: &[u16] = &[23, 25, 25, 26, 27, 29, 29, 30, 32, 32, 34, 34, 34, 34, 34, 34, 35, 35, 34, 35, 35, 35, 34, 36, 36, 35, 35, 36, 35, 35, 37, 35, 36, 36, 36, 36, 37, 36, 37, 37, 37, 36, 37, 37, 37, 37, 38, 37, 38, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 41, 41, 42, 41, 40, 41, 41, 42, 42, 43, 41, 41, 42, 42, 42, 42, 42, 42, 43, 42, 44, 43, 42, 42, 44, 43, 43, 42, 42, 43, 42, 43, 42, 43, 43, 42, 44, 43, 44, 44, 44, 44, 44, 43, 43, 44, 43, 44, 45, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 44, 45, 45, 44, 44, 45, 44, 46, 45, 46, 45, 46, 45, 45, 46, 45, 46, 46, 45, 46, 46, 46, 46, 46, 47, 47, 46, 48, 47, 47, 47, 47, 47, 48, 47, 47, 48, 48, 48, 49, 48, 48, 49, 48, 48, 49, 49, 49, 49, 49, 49, 49, 50, 51, 50, 50, 50, 50, 50, 50, 51, 50, 50, 50, 52, 51, 51, 51, 50, 52, 51, 52, 52, 52, 52, 52, 52, 51, 50, 49, 48, 47, 46, 45, 44, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 20, 19, 19, 18, 17, 16, 16, 15, 15, 15, 13, 13, 11, 10, 10, 10, 10];
-
-pub const GCD_SUB_K: [usize; 1032] = [139,137,134,131,130,127,124,123,120,117,116,115,114,115,114,113,114,113,112,113,112,111,112,111,110,111,110,109,110,109,108,109,108,107,108,107,106,107,106,105,106,105,104,105,104,103,104,103,102,103,102,101,102,101,100,101,100,99,100,99,98,99,98,97,98,97,96,97,96,95,96,95,94,95,94,93,94,93,92,93,92,91,92,91,90,91,90,89,90,89,88,89,88,87,86,85,86,87,86,85,86,83,84,83,82,81,84,81,80,83,80,79,80,79,78,79,78,79,80,79,78,79,76,75,76,77,74,75,74,73,74,73,72,73,72,73,74,73,72,73,72,69,70,69,70,69,70,69,70,69,68,69,68,67,68,67,66,67,66,65,66,65,64,65,64,63,64,63,62,63,62,61,62,61,60,61,60,59,60,59,58,59,58,57,58,57,56,57,56,55,56,55,54,55,54,53,54,53,52,53,52,51,52,51,50,51,50,49,50,49,48,49,48,47,48,47,46,47,46,45,46,45,44,45,44,43,44,43,42,43,42,41,42,41,40,41,40,39,40,39,38,39,38,37,36,35,32,33,32,31,30,29,26,25,26,23,26,25,281,282,279,282,281,282,285,286,287,288,289,288,291,292,293,294,295,294,295,296,295,296,297,296,297,298,297,298,299,298,299,300,299,300,301,300,301,302,301,302,303,302,303,304,303,304,305,304,305,306,305,306,307,306,307,308,307,308,309,308,309,310,309,310,311,310,311,312,311,312,313,312,313,314,313,314,315,314,315,316,315,316,317,316,317,318,317,318,319,318,319,320,319,320,321,320,321,322,321,322,323,322,323,324,323,324,325,324,325,326,325,326,325,326,325,326,325,328,329,328,329,330,329,328,329,328,329,330,329,330,331,330,333,332,331,332,335,334,335,336,335,334,335,334,335,336,335,336,339,336,337,340,337,338,339,340,339,342,341,342,343,342,341,342,343,344,345,344,345,346,345,346,347,346,347,348,347,348,349,348,349,350,349,350,351,350,351,352,351,352,353,352,353,354,353,354,355,354,355,356,355,356,357,356,357,358,357,358,359,358,359,360,359,360,361,360,361,362,361,362,363,362,363,364,363,364,365,364,365,366,365,366,367,366,367,368,367,368,369,368,369,370,369,370,371,370,371,372,373,376,379,380,383,386,387,390,393,395,395,393,390,387,386,383,380,379,376,373,372,371,370,371,370,369,370,369,368,369,368,367,368,367,366,367,366,365,366,365,364,365,364,363,364,363,362,363,362,361,362,361,360,361,360,359,360,359,358,359,358,357,358,357,356,357,356,355,356,355,354,355,354,353,354,353,352,353,352,351,352,351,350,351,350,349,350,349,348,349,348,347,348,347,346,347,346,345,346,345,344,345,344,343,342,341,342,343,342,341,342,339,340,339,338,337,340,337,336,339,336,335,336,335,334,335,334,335,336,335,334,335,332,331,332,333,330,331,330,329,330,329,328,329,328,329,330,329,328,329,328,325,326,325,326,325,326,325,326,325,324,325,324,323,324,323,322,323,322,321,322,321,320,321,320,319,320,319,318,319,318,317,318,317,316,317,316,315,316,315,314,315,314,313,314,313,312,313,312,311,312,311,310,311,310,309,310,309,308,309,308,307,308,307,306,307,306,305,306,305,304,305,304,303,304,303,302,303,302,301,302,301,300,301,300,299,300,299,298,299,298,297,298,297,296,297,296,295,296,295,294,295,294,293,292,291,288,289,288,287,286,285,282,281,282,279,282,281,25,26,23,26,25,26,29,30,31,32,33,32,35,36,37,38,39,38,39,40,39,40,41,40,41,42,41,42,43,42,43,44,43,44,45,44,45,46,45,46,47,46,47,48,47,48,49,48,49,50,49,50,51,50,51,52,51,52,53,52,53,54,53,54,55,54,55,56,55,56,57,56,57,58,57,58,59,58,59,60,59,60,61,60,61,62,61,62,63,62,63,64,63,64,65,64,65,66,65,66,67,66,67,68,67,68,69,68,69,70,69,70,69,70,69,70,69,72,73,72,73,74,73,72,73,72,73,74,73,74,75,74,77,76,75,76,79,78,79,80,79,78,79,78,79,80,79,80,83,80,81,84,81,82,83,84,83,86,85,86,87,86,85,86,87,88,89,88,89,90,89,90,91,90,91,92,91,92,93,92,93,94,93,94,95,94,95,96,95,96,97,96,97,98,97,98,99,98,99,100,99,100,101,100,101,102,101,102,103,102,103,104,103,104,105,104,105,106,105,106,107,106,107,108,107,108,109,108,109,110,109,110,111,110,111,112,111,112,113,112,113,114,113,114,115,114,115,116,117,120,123,124,127,130,131,134,137,139];
-
-pub const APPLY_COUT_K: [usize; 516] = [138, 136, 133, 130, 129, 126, 123, 122, 119, 116, 115, 114, 113, 114, 113, 112, 113, 112, 111, 112, 111, 110, 111, 110, 109, 110, 109, 108, 109, 108, 107, 108, 107, 106, 107, 106, 105, 106, 105, 104, 105, 104, 103, 104, 103, 102, 103, 102, 101, 102, 101, 100, 101, 100, 99, 100, 99, 98, 99, 98, 97, 98, 97, 96, 97, 96, 95, 96, 95, 94, 95, 94, 93, 94, 93, 92, 93, 92, 91, 92, 91, 90, 91, 90, 89, 90, 89, 88, 89, 88, 87, 88, 87, 86, 85, 84, 85, 86, 85, 84, 85, 82, 83, 82, 81, 80, 83, 80, 79, 82, 79, 78, 79, 78, 77, 78, 77, 78, 79, 78, 77, 78, 75, 74, 75, 76, 73, 74, 73, 72, 73, 72, 71, 72, 71, 72, 73, 72, 71, 72, 71, 68, 69, 68, 69, 68, 69, 68, 69, 68, 67, 68, 67, 66, 67, 66, 65, 66, 65, 64, 65, 64, 63, 64, 63, 62, 63, 62, 61, 62, 61, 60, 61, 60, 59, 60, 59, 58, 59, 58, 57, 58, 57, 56, 57, 56, 55, 56, 55, 54, 55, 54, 53, 54, 53, 52, 53, 52, 51, 52, 51, 50, 51, 50, 49, 50, 49, 48, 49, 48, 47, 48, 47, 46, 47, 46, 45, 46, 45, 44, 45, 44, 43, 44, 43, 42, 43, 42, 41, 42, 41, 40, 41, 40, 39, 40, 39, 38, 39, 38, 37, 38, 37, 36, 35, 34, 31, 32, 31, 30, 29, 28, 25, 24, 25, 22, 25, 24, 24, 25, 22, 25, 24, 25, 28, 29, 30, 31, 32, 31, 34, 35, 36, 37, 38, 37, 38, 39, 38, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 43, 42, 43, 44, 43, 44, 45, 44, 45, 46, 45, 46, 47, 46, 47, 48, 47, 48, 49, 48, 49, 50, 49, 50, 51, 50, 51, 52, 51, 52, 53, 52, 53, 54, 53, 54, 55, 54, 55, 56, 55, 56, 57, 56, 57, 58, 57, 58, 59, 58, 59, 60, 59, 60, 61, 60, 61, 62, 61, 62, 63, 62, 63, 64, 63, 64, 65, 64, 65, 66, 65, 66, 67, 66, 67, 68, 67, 68, 69, 68, 69, 68, 69, 68, 69, 68, 71, 72, 71, 72, 73, 72, 71, 72, 71, 72, 73, 72, 73, 74, 73, 76, 75, 74, 75, 78, 77, 78, 79, 78, 77, 78, 77, 78, 79, 78, 79, 82, 79, 80, 83, 80, 81, 82, 83, 82, 85, 84, 85, 86, 85, 84, 85, 86, 87, 88, 87, 88, 89, 88, 89, 90, 89, 90, 91, 90, 91, 92, 91, 92, 93, 92, 93, 94, 93, 94, 95, 94, 95, 96, 95, 96, 97, 96, 97, 98, 97, 98, 99, 98, 99, 100, 99, 100, 101, 100, 101, 102, 101, 102, 103, 102, 103, 104, 103, 104, 105, 104, 105, 106, 105, 106, 107, 106, 107, 108, 107, 108, 109, 108, 109, 110, 109, 110, 111, 110, 111, 112, 111, 112, 113, 112, 113, 114, 113, 114, 115, 116, 119, 122, 123, 126, 129, 130, 133, 136, 138];
-
-pub const FOLD_SCHED: [i32; 514] = [53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,52,53,52,-5,52,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,20,19,20,17,20,19,19,20,17,20,19,20,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,52,-5,52,53,52,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53];
-
-pub const GCD_BRANCH: [u8; 1032] = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];
-
-pub const CMP_K: &[usize] = &[26, 26, 27, 28, 30, 30, 31, 33, 33, 35, 35, 35, 35, 35, 35, 36, 36, 35, 36, 36, 36, 35, 37, 37, 36, 36, 37, 36, 36, 38, 36, 37, 37, 37, 37, 38, 37, 38, 38, 38, 37, 38, 38, 38, 38, 39, 38, 39, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, 43, 42, 41, 42, 42, 43, 43, 44, 42, 42, 43, 43, 43, 43, 43, 43, 44, 43, 45, 44, 43, 43, 45, 44, 44, 45, 45, 46, 45, 46, 45, 46, 46, 45, 47, 46, 48, 47, 47, 47, 47, 46, 46, 47, 46, 47, 49, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 48, 49, 49, 48, 48, 49, 48, 50, 49, 50, 49, 50, 49, 49, 50, 49, 50, 50, 49, 50, 50, 50, 50, 50, 51, 51, 50, 52, 51, 51, 51, 51, 51, 52, 51, 51, 52, 52, 52, 52, 51, 52, 51, 50, 51, 50, 49, 50, 49, 48, 49, 48, 47, 48, 47, 46, 47, 46, 45, 46, 45, 44, 45, 44, 43, 44, 43, 42, 43, 42, 41, 42, 41, 40, 41, 40, 39, 40, 39, 38, 39, 38, 37, 38, 37, 36, 37, 36, 35, 36, 35, 34, 35, 34, 33, 34, 33, 32, 33, 32, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 22, 21, 20, 19, 19, 18, 17, 16, 16, 14, 14, 13, 13, 14, 16, 16, 18, 18, 18, 19, 19, 20, 21, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 55, 56, 54, 55, 55, 55, 56, 54, 54, 54, 55, 54, 54, 54, 54, 54, 54, 55, 54, 53, 53, 53, 53, 53, 53, 53, 52, 52, 53, 52, 52, 53, 52, 52, 52, 51, 51, 52, 51, 51, 51, 51, 51, 52, 50, 51, 51, 50, 50, 50, 50, 50, 49, 50, 50, 49, 50, 49, 49, 50, 49, 50, 49, 50, 48, 49, 48, 48, 49, 49, 48, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 49, 47, 46, 47, 46, 46, 47, 47, 47, 47, 48, 46, 47, 45, 46, 46, 45, 46, 45, 46, 45, 45, 44, 44, 45, 43, 43, 44, 45, 43, 44, 43, 43, 43, 43, 43, 43, 42, 42, 44, 43, 43, 42, 42, 41, 42, 43, 42, 42, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 38, 39, 38, 39, 38, 38, 38, 38, 37, 38, 38, 38, 37, 38, 37, 37, 37, 37, 36, 38, 36, 36, 37, 36, 36, 37, 37, 35, 36, 36, 36, 35, 36, 36, 35, 35, 35, 35, 35, 35, 33, 33, 31, 30, 30, 28, 27, 26, 26, 26, 26, 27, 28, 30, 30, 31, 33, 33, 35, 35, 35, 35, 35, 35, 36, 36, 35, 36, 36, 36, 35, 37, 37, 36, 36, 37, 36, 36, 38, 36, 37, 37, 37, 37, 38, 37, 38, 38, 38, 37, 38, 38, 38, 38, 39, 38, 39, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, 43, 42, 41, 42, 42, 43, 43, 44, 42, 42, 43, 43, 43, 43, 43, 43, 44, 43, 45, 44, 43, 43, 45, 44, 44, 45, 45, 46, 45, 46, 45, 46, 46, 45, 47, 46, 48, 47, 47, 47, 47, 46, 46, 47, 46, 47, 49, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 48, 49, 49, 48, 48, 49, 48, 50, 49, 50, 49, 50, 49, 49, 50, 49, 50, 50, 49, 50, 50, 50, 50, 50, 51, 51, 50, 52, 51, 51, 51, 51, 51, 52, 51, 51, 52, 52, 52, 53, 52, 52, 53, 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, 55, 54, 54, 54, 54, 54, 54, 55, 54, 54, 54, 56, 55, 55, 55, 54, 56, 55, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 22, 21, 20, 19, 19, 18, 18, 18, 16, 16, 14, 13, 13, 14, 14, 16, 16, 17, 18, 19, 19, 20, 21, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 32, 33, 32, 33, 34, 33, 34, 35, 34, 35, 36, 35, 36, 37, 36, 37, 38, 37, 38, 39, 38, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 43, 42, 43, 44, 43, 44, 45, 44, 45, 46, 45, 46, 47, 46, 47, 48, 47, 48, 49, 48, 49, 50, 49, 50, 51, 50, 51, 52, 51, 52, 52, 52, 52, 51, 51, 52, 51, 51, 51, 51, 51, 52, 50, 51, 51, 50, 50, 50, 50, 50, 49, 50, 50, 49, 50, 49, 49, 50, 49, 50, 49, 50, 48, 49, 48, 48, 49, 49, 48, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 49, 47, 46, 47, 46, 46, 47, 47, 47, 47, 48, 46, 47, 45, 46, 46, 45, 46, 45, 46, 45, 45, 44, 44, 45, 43, 43, 44, 45, 43, 44, 43, 43, 43, 43, 43, 43, 42, 42, 44, 43, 43, 42, 42, 41, 42, 43, 42, 42, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 38, 39, 38, 39, 38, 38, 38, 38, 37, 38, 38, 38, 37, 38, 37, 37, 37, 37, 36, 38, 36, 36, 37, 36, 36, 37, 37, 35, 36, 36, 36, 35, 36, 36, 35, 35, 35, 35, 35, 35, 33, 33, 31, 30, 30, 28, 27, 26, 26];
-
-pub const FFG_G: &[usize] = &[
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 45, 53, 45, 44, 45, 44, 42, 44, 42, 41, 42, 41, 40,
-    41, 40, 39, 40, 39, 37, 39, 37, 36, 37, 36, 35, 36, 35, 34, 35,
-    34, 33, 34, 33, 31, 33, 31, 30, 31, 30, 29, 30, 29, 28, 29, 28,
-    27, 28, 27, 26, 24, 23, 20, 21, 20, 19, 18, 16, 13, 12, 13, 10,
-    13, 12, 11, 12, 9, 12, 11, 12, 15, 16, 18, 19, 20, 19, 22, 23,
-    24, 26, 27, 26, 27, 28, 27, 28, 29, 28, 29, 30, 29, 30, 31, 30,
-    31, 33, 31, 33, 34, 33, 34, 35, 34, 35, 36, 35, 36, 37, 36, 37,
-    39, 37, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 44, 42, 44, 45,
-    44, 45, 53, 45, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-    53, 53, 53, 53,
-];
-
-pub const HYB_V: [usize; 1558] = [135,121,133,123,130,126,127,126,3,126,125,5,123,122,11,120,119,17,119,118,19,116,115,25,113,112,31,112,111,33,111,110,34,110,109,35,111,110,32,110,109,33,109,108,34,110,109,31,109,108,32,108,107,33,109,108,30,108,107,31,107,106,32,108,107,29,107,106,30,106,105,31,107,106,28,106,105,29,105,104,30,106,105,27,105,104,28,104,103,29,105,104,26,104,103,27,103,102,28,104,103,25,103,102,26,102,101,27,103,102,24,102,101,25,101,100,26,102,101,23,101,100,24,100,99,25,101,100,22,100,99,23,99,98,24,100,99,21,99,98,22,98,97,23,99,98,20,98,97,21,97,96,22,98,97,19,97,96,20,96,95,21,97,96,18,96,95,19,95,94,20,96,95,17,95,94,18,94,93,19,95,94,16,94,93,17,93,92,18,94,93,15,93,92,16,92,91,17,93,92,14,92,91,15,91,90,16,92,91,13,91,90,14,90,89,15,91,90,12,90,89,13,89,88,14,90,89,11,89,88,12,88,87,13,89,88,10,88,87,11,87,86,12,88,87,9,87,86,10,86,85,11,87,86,8,86,85,9,85,84,10,86,85,7,85,84,8,84,83,9,85,84,6,84,83,7,83,82,8,82,81,10,81,80,11,82,81,7,83,82,4,82,81,5,81,80,6,82,81,3,79,78,9,80,79,5,79,78,7,78,77,8,77,76,9,80,79,77,76,7,76,75,8,79,78,76,75,6,75,74,7,76,75,4,75,74,5,74,73,6,75,74,3,74,73,4,75,74,76,72,75,72,74,72,75,70,72,71,2,71,70,3,72,71,73,68,70,69,2,71,69,70,69,69,68,70,67,69,67,68,67,69,65,68,65,69,62,70,60,69,60,68,60,69,58,68,58,65,61,66,59,65,59,66,56,65,57,66,54,65,54,66,52,65,52,64,52,65,50,64,50,63,50,64,48,63,48,62,48,63,46,62,46,61,46,62,44,61,44,60,44,61,42,60,42,59,42,60,40,59,40,58,40,59,38,58,38,57,38,54,53,52,53,52,51,52,51,50,51,50,49,50,49,48,49,48,47,48,47,46,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,21,20,20,19,18,17,17,16,16,16,14,14,12,11,11,12,14,14,16,16,16,17,17,18,19,20,20,21,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,120,122,123,124,124,125,126,127,128,129,131,132,133,134,135,136,137,138,139,139,141,142,143,143,144,145,146,147,149,150,151,152,153,154,155,155,157,158,158,160,161,162,162,164,164,165,166,167,168,170,171,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,171,170,168,167,166,165,164,164,162,162,161,160,158,158,157,155,155,154,153,152,151,150,149,147,146,145,144,143,143,142,141,139,139,138,137,136,135,134,133,132,131,129,128,127,126,125,124,124,123,122,120,120,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,21,20,20,19,18,17,17,16,16,16,14,14,12,11,11,12,14,14,16,16,16,17,17,18,19,20,20,21,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,46,47,48,47,48,49,48,49,50,49,50,51,50,51,52,51,52,53,52,53,54,57,38,58,38,59,38,58,40,59,40,60,40,59,42,60,42,61,42,60,44,61,44,62,44,61,46,62,46,63,46,62,48,63,48,64,48,63,50,64,50,65,50,64,52,65,52,66,52,65,54,66,54,65,57,66,56,65,59,66,59,65,61,68,58,69,58,68,60,69,60,70,60,69,62,68,65,69,65,68,67,69,67,70,67,69,68,70,69,71,69,70,69,2,73,68,72,71,71,70,3,72,71,2,75,70,74,72,75,72,76,72,75,74,74,73,4,75,74,3,74,73,6,75,74,5,76,75,4,75,74,7,76,75,6,79,78,76,75,8,77,76,7,80,79,77,76,9,78,77,8,79,78,7,80,79,5,79,78,9,82,81,3,81,80,6,82,81,5,83,82,4,82,81,7,81,80,11,82,81,10,83,82,8,84,83,7,85,84,6,84,83,9,85,84,8,86,85,7,85,84,10,86,85,9,87,86,8,86,85,11,87,86,10,88,87,9,87,86,12,88,87,11,89,88,10,88,87,13,89,88,12,90,89,11,89,88,14,90,89,13,91,90,12,90,89,15,91,90,14,92,91,13,91,90,16,92,91,15,93,92,14,92,91,17,93,92,16,94,93,15,93,92,18,94,93,17,95,94,16,94,93,19,95,94,18,96,95,17,95,94,20,96,95,19,97,96,18,96,95,21,97,96,20,98,97,19,97,96,22,98,97,21,99,98,20,98,97,23,99,98,22,100,99,21,99,98,24,100,99,23,101,100,22,100,99,25,101,100,24,102,101,23,101,100,26,102,101,25,103,102,24,102,101,27,103,102,26,104,103,25,103,102,28,104,103,27,105,104,26,104,103,29,105,104,28,106,105,27,105,104,30,106,105,29,107,106,28,106,105,31,107,106,30,108,107,29,107,106,32,108,107,31,109,108,30,108,107,33,109,108,32,110,109,31,109,108,34,110,109,33,111,110,32,110,109,35,111,110,34,112,111,33,113,112,31,116,115,25,119,118,19,120,119,17,123,122,11,126,125,5,127,126,3,130,126,133,123,135,121];
-
-pub const SQ_ROW_K: [usize; 512] = [130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 132, 132, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130];
+
+pub const JUMP: usize = 2;
+
+pub const ITERS: usize = 258;
+
+pub const PAD: usize = 20;
+
+pub static SCHED_J2: &[u16] = &[
+    256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 254, 253, 252, 251, 250, 249, 248,
+    247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229,
+    228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210,
+    209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191,
+    190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 173,
+    172, 170, 169, 168, 167, 166, 166, 164, 164, 163, 162, 160, 160, 159, 157, 157, 156, 155, 154,
+    153, 152, 151, 149, 148, 147, 146, 145, 145, 144, 143, 141, 141, 140, 139, 138, 137, 136, 135,
+    134, 133, 131, 130, 129, 128, 127, 126, 126, 125, 124, 122, 122, 120, 119, 118, 117, 116, 115,
+    114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95,
+    94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71,
+    70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47,
+    46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 26, 25, 24, 23, 22, 21,
+    21, 20, 20, 19, 18, 17, 17, 16, 16, 16, 14, 14, 12, 11,
+];
+
+pub static GAP_J2: &[u16] = &[
+    23, 25, 25, 26, 27, 29, 29, 30, 32, 32, 34, 34, 34, 34, 34, 34, 35, 35, 34, 35, 35, 35, 34, 36,
+    36, 35, 35, 36, 35, 35, 37, 35, 36, 36, 36, 36, 37, 36, 37, 37, 37, 36, 37, 37, 37, 37, 38, 37,
+    38, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40,
+    40, 40, 41, 41, 42, 41, 40, 41, 41, 42, 42, 43, 41, 41, 42, 42, 42, 42, 42, 42, 43, 42, 44, 43,
+    42, 42, 44, 43, 43, 44, 44, 45, 44, 45, 44, 45, 45, 44, 46, 45, 46, 46, 46, 46, 46, 45, 45, 46,
+    45, 46, 47, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 46, 47, 47, 46, 46, 47, 46, 48, 47, 48,
+    47, 48, 47, 47, 48, 47, 48, 48, 47, 48, 48, 48, 48, 48, 49, 49, 48, 50, 49, 49, 49, 49, 49, 50,
+    49, 49, 50, 50, 50, 51, 50, 50, 51, 50, 50, 51, 51, 51, 51, 51, 51, 51, 52, 53, 52, 52, 52, 52,
+    52, 52, 53, 52, 52, 52, 54, 53, 53, 53, 52, 54, 53, 54, 54, 54, 54, 54, 54, 53, 52, 51, 50, 49,
+    48, 47, 46, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26,
+    25, 24, 23, 22, 22, 21, 21, 20, 19, 18, 18, 17, 17, 17, 15, 15, 13, 12,
+];
+
+pub const GCD_SUB_K: [usize; 1032] = [139,137,134,131,130,127,124,123,120,117,116,115,114,115,114,113,114,113,112,113,112,111,112,111,110,111,110,109,110,109,108,109,108,107,108,107,106,107,106,105,106,105,104,105,104,103,104,103,102,103,102,101,102,101,100,101,100,99,100,99,98,99,98,97,98,97,96,97,96,95,96,95,94,95,94,93,94,93,92,93,92,91,92,91,90,91,90,89,90,89,88,89,88,87,86,85,86,87,86,85,86,83,84,83,82,81,84,81,80,83,80,79,80,79,78,79,78,79,80,79,78,79,76,75,76,77,74,75,74,73,74,73,72,73,72,73,74,73,72,73,72,69,70,69,70,69,70,69,70,69,68,69,68,67,68,67,66,67,66,65,66,65,64,65,64,63,64,63,62,63,62,61,62,61,60,61,60,59,60,59,58,59,58,57,58,57,56,57,56,55,56,55,54,55,54,53,54,53,52,53,52,51,52,51,50,51,50,49,50,49,48,49,48,47,48,47,46,47,46,45,46,45,44,45,44,43,44,43,42,43,42,41,42,41,40,41,40,39,40,39,38,39,38,37,36,35,32,33,32,31,30,29,26,25,26,23,26,25,281,282,279,282,281,282,285,286,287,288,289,288,291,292,293,294,295,294,295,296,295,296,297,296,297,298,297,298,299,298,299,300,299,300,301,300,301,302,301,302,303,302,303,304,303,304,305,304,305,306,305,306,307,306,307,308,307,308,309,308,309,310,309,310,311,310,311,312,311,312,313,312,313,314,313,314,315,314,315,316,315,316,317,316,317,318,317,318,319,318,319,320,319,320,321,320,321,322,321,322,323,322,323,324,323,324,325,324,325,326,325,326,325,326,325,326,325,328,329,328,329,330,329,328,329,328,329,330,329,330,331,330,333,332,331,332,335,334,335,336,335,334,335,334,335,336,335,336,339,336,337,340,337,338,339,340,339,342,341,342,343,342,341,342,343,344,345,344,345,346,345,346,347,346,347,348,347,348,349,348,349,350,349,350,351,350,351,352,351,352,353,352,353,354,353,354,355,354,355,356,355,356,357,356,357,358,357,358,359,358,359,360,359,360,361,360,361,362,361,362,363,362,363,364,363,364,365,364,365,366,365,366,367,366,367,368,367,368,369,368,369,370,369,370,371,370,371,372,373,376,379,380,383,386,387,390,393,395,395,393,390,387,386,383,380,379,376,373,372,371,370,371,370,369,370,369,368,369,368,367,368,367,366,367,366,365,366,365,364,365,364,363,364,363,362,363,362,361,362,361,360,361,360,359,360,359,358,359,358,357,358,357,356,357,356,355,356,355,354,355,354,353,354,353,352,353,352,351,352,351,350,351,350,349,350,349,348,349,348,347,348,347,346,347,346,345,346,345,344,345,344,343,342,341,342,343,342,341,342,339,340,339,338,337,340,337,336,339,336,335,336,335,334,335,334,335,336,335,334,335,332,331,332,333,330,331,330,329,330,329,328,329,328,329,330,329,328,329,328,325,326,325,326,325,326,325,326,325,324,325,324,323,324,323,322,323,322,321,322,321,320,321,320,319,320,319,318,319,318,317,318,317,316,317,316,315,316,315,314,315,314,313,314,313,312,313,312,311,312,311,310,311,310,309,310,309,308,309,308,307,308,307,306,307,306,305,306,305,304,305,304,303,304,303,302,303,302,301,302,301,300,301,300,299,300,299,298,299,298,297,298,297,296,297,296,295,296,295,294,295,294,293,292,291,288,289,288,287,286,285,282,281,282,279,282,281,25,26,23,26,25,26,29,30,31,32,33,32,35,36,37,38,39,38,39,40,39,40,41,40,41,42,41,42,43,42,43,44,43,44,45,44,45,46,45,46,47,46,47,48,47,48,49,48,49,50,49,50,51,50,51,52,51,52,53,52,53,54,53,54,55,54,55,56,55,56,57,56,57,58,57,58,59,58,59,60,59,60,61,60,61,62,61,62,63,62,63,64,63,64,65,64,65,66,65,66,67,66,67,68,67,68,69,68,69,70,69,70,69,70,69,70,69,72,73,72,73,74,73,72,73,72,73,74,73,74,75,74,77,76,75,76,79,78,79,80,79,78,79,78,79,80,79,80,83,80,81,84,81,82,83,84,83,86,85,86,87,86,85,86,87,88,89,88,89,90,89,90,91,90,91,92,91,92,93,92,93,94,93,94,95,94,95,96,95,96,97,96,97,98,97,98,99,98,99,100,99,100,101,100,101,102,101,102,103,102,103,104,103,104,105,104,105,106,105,106,107,106,107,108,107,108,109,108,109,110,109,110,111,110,111,112,111,112,113,112,113,114,113,114,115,114,115,116,117,120,123,124,127,130,131,134,137,139];
+
+pub const APPLY_COUT_K: [usize; 516] = [138, 136, 133, 130, 129, 126, 123, 122, 119, 116, 115, 114, 113, 114, 113, 112, 113, 112, 111, 112, 111, 110, 111, 110, 109, 110, 109, 108, 109, 108, 107, 108, 107, 106, 107, 106, 105, 106, 105, 104, 105, 104, 103, 104, 103, 102, 103, 102, 101, 102, 101, 100, 101, 100, 99, 100, 99, 98, 99, 98, 97, 98, 97, 96, 97, 96, 95, 96, 95, 94, 95, 94, 93, 94, 93, 92, 93, 92, 91, 92, 91, 90, 91, 90, 89, 90, 89, 88, 89, 88, 87, 88, 87, 86, 85, 84, 85, 86, 85, 84, 85, 82, 83, 82, 81, 80, 83, 80, 79, 82, 79, 78, 79, 78, 77, 78, 77, 78, 79, 78, 77, 78, 75, 74, 75, 76, 73, 74, 73, 72, 73, 72, 71, 72, 71, 72, 73, 72, 71, 72, 71, 68, 69, 68, 69, 68, 69, 68, 69, 68, 67, 68, 67, 66, 67, 66, 65, 66, 65, 64, 65, 64, 63, 64, 63, 62, 63, 62, 61, 62, 61, 60, 61, 60, 59, 60, 59, 58, 59, 58, 57, 58, 57, 56, 57, 56, 55, 56, 55, 54, 55, 54, 53, 54, 53, 52, 53, 52, 51, 52, 51, 50, 51, 50, 49, 50, 49, 48, 49, 48, 47, 48, 47, 46, 47, 46, 45, 46, 45, 44, 45, 44, 43, 44, 43, 42, 43, 42, 41, 42, 41, 40, 41, 40, 39, 40, 39, 38, 39, 38, 37, 38, 37, 36, 35, 34, 31, 32, 31, 30, 29, 28, 25, 24, 25, 22, 25, 24, 24, 25, 22, 25, 24, 25, 28, 29, 30, 31, 32, 31, 34, 35, 36, 37, 38, 37, 38, 39, 38, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 43, 42, 43, 44, 43, 44, 45, 44, 45, 46, 45, 46, 47, 46, 47, 48, 47, 48, 49, 48, 49, 50, 49, 50, 51, 50, 51, 52, 51, 52, 53, 52, 53, 54, 53, 54, 55, 54, 55, 56, 55, 56, 57, 56, 57, 58, 57, 58, 59, 58, 59, 60, 59, 60, 61, 60, 61, 62, 61, 62, 63, 62, 63, 64, 63, 64, 65, 64, 65, 66, 65, 66, 67, 66, 67, 68, 67, 68, 69, 68, 69, 68, 69, 68, 69, 68, 71, 72, 71, 72, 73, 72, 71, 72, 71, 72, 73, 72, 73, 74, 73, 76, 75, 74, 75, 78, 77, 78, 79, 78, 77, 78, 77, 78, 79, 78, 79, 82, 79, 80, 83, 80, 81, 82, 83, 82, 85, 84, 85, 86, 85, 84, 85, 86, 87, 88, 87, 88, 89, 88, 89, 90, 89, 90, 91, 90, 91, 92, 91, 92, 93, 92, 93, 94, 93, 94, 95, 94, 95, 96, 95, 96, 97, 96, 97, 98, 97, 98, 99, 98, 99, 100, 99, 100, 101, 100, 101, 102, 101, 102, 103, 102, 103, 104, 103, 104, 105, 104, 105, 106, 105, 106, 107, 106, 107, 108, 107, 108, 109, 108, 109, 110, 109, 110, 111, 110, 111, 112, 111, 112, 113, 112, 113, 114, 113, 114, 115, 116, 119, 122, 123, 126, 129, 130, 133, 136, 138];
+
+pub const FOLD_SCHED: [i32; 514] = [53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,52,53,52,-5,52,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,20,19,20,17,20,19,19,20,17,20,19,20,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,52,-5,52,53,52,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53];
+
+pub const GCD_BRANCH: [u8; 1032] = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];
+
+pub const CMP_K: &[usize] = &[26, 26, 27, 28, 30, 30, 31, 33, 33, 35, 35, 35, 35, 35, 35, 36, 36, 35, 36, 36, 36, 35, 37, 37, 36, 36, 37, 36, 36, 38, 36, 37, 37, 37, 37, 38, 37, 38, 38, 38, 37, 38, 38, 38, 38, 39, 38, 39, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, 43, 42, 41, 42, 42, 43, 43, 44, 42, 42, 43, 43, 43, 43, 43, 43, 44, 43, 45, 44, 43, 43, 45, 44, 44, 45, 45, 46, 45, 46, 45, 46, 46, 45, 47, 46, 48, 47, 47, 47, 47, 46, 46, 47, 46, 47, 49, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 48, 49, 49, 48, 48, 49, 48, 50, 49, 50, 49, 50, 49, 49, 50, 49, 50, 50, 49, 50, 50, 50, 50, 50, 51, 51, 50, 52, 51, 51, 51, 51, 51, 52, 51, 51, 52, 52, 52, 52, 51, 52, 51, 50, 51, 50, 49, 50, 49, 48, 49, 48, 47, 48, 47, 46, 47, 46, 45, 46, 45, 44, 45, 44, 43, 44, 43, 42, 43, 42, 41, 42, 41, 40, 41, 40, 39, 40, 39, 38, 39, 38, 37, 38, 37, 36, 37, 36, 35, 36, 35, 34, 35, 34, 33, 34, 33, 32, 33, 32, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 22, 21, 20, 19, 19, 18, 17, 16, 16, 14, 14, 13, 13, 14, 16, 16, 18, 18, 18, 19, 19, 20, 21, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 55, 56, 54, 55, 55, 55, 56, 54, 54, 54, 55, 54, 54, 54, 54, 54, 54, 55, 54, 53, 53, 53, 53, 53, 53, 53, 52, 52, 53, 52, 52, 53, 52, 52, 52, 51, 51, 52, 51, 51, 51, 51, 51, 52, 50, 51, 51, 50, 50, 50, 50, 50, 49, 50, 50, 49, 50, 49, 49, 50, 49, 50, 49, 50, 48, 49, 48, 48, 49, 49, 48, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 49, 47, 46, 47, 46, 46, 47, 47, 47, 47, 48, 46, 47, 45, 46, 46, 45, 46, 45, 46, 45, 45, 44, 44, 45, 43, 43, 44, 45, 43, 44, 43, 43, 43, 43, 43, 43, 42, 42, 44, 43, 43, 42, 42, 41, 42, 43, 42, 42, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 38, 39, 38, 39, 38, 38, 38, 38, 37, 38, 38, 38, 37, 38, 37, 37, 37, 37, 36, 38, 36, 36, 37, 36, 36, 37, 37, 35, 36, 36, 36, 35, 36, 36, 35, 35, 35, 35, 35, 35, 33, 33, 31, 30, 30, 28, 27, 26, 26, 26, 26, 27, 28, 30, 30, 31, 33, 33, 35, 35, 35, 35, 35, 35, 36, 36, 35, 36, 36, 36, 35, 37, 37, 36, 36, 37, 36, 36, 38, 36, 37, 37, 37, 37, 38, 37, 38, 38, 38, 37, 38, 38, 38, 38, 39, 38, 39, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, 43, 42, 41, 42, 42, 43, 43, 44, 42, 42, 43, 43, 43, 43, 43, 43, 44, 43, 45, 44, 43, 43, 45, 44, 44, 45, 45, 46, 45, 46, 45, 46, 46, 45, 47, 46, 48, 47, 47, 47, 47, 46, 46, 47, 46, 47, 49, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 48, 49, 49, 48, 48, 49, 48, 50, 49, 50, 49, 50, 49, 49, 50, 49, 50, 50, 49, 50, 50, 50, 50, 50, 51, 51, 50, 52, 51, 51, 51, 51, 51, 52, 51, 51, 52, 52, 52, 53, 52, 52, 53, 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, 55, 54, 54, 54, 54, 54, 54, 55, 54, 54, 54, 56, 55, 55, 55, 54, 56, 55, 56, 56, 56, 56, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 22, 22, 21, 20, 19, 19, 18, 18, 18, 16, 16, 14, 13, 13, 14, 14, 16, 16, 17, 18, 19, 19, 20, 21, 22, 22, 23, 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, 32, 33, 32, 33, 34, 33, 34, 35, 34, 35, 36, 35, 36, 37, 36, 37, 38, 37, 38, 39, 38, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 43, 42, 43, 44, 43, 44, 45, 44, 45, 46, 45, 46, 47, 46, 47, 48, 47, 48, 49, 48, 49, 50, 49, 50, 51, 50, 51, 52, 51, 52, 52, 52, 52, 51, 51, 52, 51, 51, 51, 51, 51, 52, 50, 51, 51, 50, 50, 50, 50, 50, 49, 50, 50, 49, 50, 49, 49, 50, 49, 50, 49, 50, 48, 49, 48, 48, 49, 49, 48, 49, 49, 49, 49, 48, 48, 48, 48, 48, 48, 48, 49, 47, 46, 47, 46, 46, 47, 47, 47, 47, 48, 46, 47, 45, 46, 46, 45, 46, 45, 46, 45, 45, 44, 44, 45, 43, 43, 44, 45, 43, 44, 43, 43, 43, 43, 43, 43, 42, 42, 44, 43, 43, 42, 42, 41, 42, 43, 42, 42, 41, 41, 41, 41, 41, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39, 39, 39, 39, 39, 39, 38, 39, 38, 39, 38, 38, 38, 38, 37, 38, 38, 38, 37, 38, 37, 37, 37, 37, 36, 38, 36, 36, 37, 36, 36, 37, 37, 35, 36, 36, 36, 35, 36, 36, 35, 35, 35, 35, 35, 35, 33, 33, 31, 30, 30, 28, 27, 26, 26];
+
+pub const FFG_G: &[usize] = &[
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 45, 53, 45, 44, 45, 44, 42, 44, 42, 41, 42, 41, 40,
+    41, 40, 39, 40, 39, 37, 39, 37, 36, 37, 36, 35, 36, 35, 34, 35,
+    34, 33, 34, 33, 31, 33, 31, 30, 31, 30, 29, 30, 29, 28, 29, 28,
+    27, 28, 27, 26, 24, 23, 20, 21, 20, 19, 18, 16, 13, 12, 13, 10,
+    13, 12, 11, 12, 9, 12, 11, 12, 15, 16, 18, 19, 20, 19, 22, 23,
+    24, 26, 27, 26, 27, 28, 27, 28, 29, 28, 29, 30, 29, 30, 31, 30,
+    31, 33, 31, 33, 34, 33, 34, 35, 34, 35, 36, 35, 36, 37, 36, 37,
+    39, 37, 39, 40, 39, 40, 41, 40, 41, 42, 41, 42, 44, 42, 44, 45,
+    44, 45, 53, 45, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+    53, 53, 53, 53,
+];
+
+pub const HYB_V: [usize; 1558] = [135,121,133,123,130,126,127,126,3,126,125,5,123,122,11,120,119,17,119,118,19,116,115,25,113,112,31,112,111,33,111,110,34,110,109,35,111,110,32,110,109,33,109,108,34,110,109,31,109,108,32,108,107,33,109,108,30,108,107,31,107,106,32,108,107,29,107,106,30,106,105,31,107,106,28,106,105,29,105,104,30,106,105,27,105,104,28,104,103,29,105,104,26,104,103,27,103,102,28,104,103,25,103,102,26,102,101,27,103,102,24,102,101,25,101,100,26,102,101,23,101,100,24,100,99,25,101,100,22,100,99,23,99,98,24,100,99,21,99,98,22,98,97,23,99,98,20,98,97,21,97,96,22,98,97,19,97,96,20,96,95,21,97,96,18,96,95,19,95,94,20,96,95,17,95,94,18,94,93,19,95,94,16,94,93,17,93,92,18,94,93,15,93,92,16,92,91,17,93,92,14,92,91,15,91,90,16,92,91,13,91,90,14,90,89,15,91,90,12,90,89,13,89,88,14,90,89,11,89,88,12,88,87,13,89,88,10,88,87,11,87,86,12,88,87,9,87,86,10,86,85,11,87,86,8,86,85,9,85,84,10,86,85,7,85,84,8,84,83,9,85,84,6,84,83,7,83,82,8,82,81,10,81,80,11,82,81,7,83,82,4,82,81,5,81,80,6,82,81,3,79,78,9,80,79,5,79,78,7,78,77,8,77,76,9,80,79,77,76,7,76,75,8,79,78,76,75,6,75,74,7,76,75,4,75,74,5,74,73,6,75,74,3,74,73,4,75,74,76,72,75,72,74,72,75,70,72,71,2,71,70,3,72,71,73,68,70,69,2,71,69,70,69,69,68,70,67,69,67,68,67,69,65,68,65,69,62,70,60,69,60,68,60,69,58,68,58,65,61,66,59,65,59,66,56,65,57,66,54,65,54,66,52,65,52,64,52,65,50,64,50,63,50,64,48,63,48,62,48,63,46,62,46,61,46,62,44,61,44,60,44,61,42,60,42,59,42,60,40,59,40,58,40,59,38,58,38,57,38,54,53,52,53,52,51,52,51,50,51,50,49,50,49,48,49,48,47,48,47,46,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,21,20,20,19,18,17,17,16,16,16,14,14,12,11,11,12,14,14,16,16,16,17,17,18,19,20,20,21,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,120,120,122,123,124,124,125,126,127,128,129,131,132,133,134,135,136,137,138,139,139,141,142,143,143,144,145,146,147,149,150,151,152,153,154,155,155,157,158,158,160,161,162,162,164,164,165,166,167,168,170,171,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,253,252,251,250,249,248,247,246,245,244,243,242,241,240,239,238,237,236,235,234,233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,218,217,216,215,214,213,212,211,210,209,208,207,206,205,204,203,202,201,200,199,198,197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,173,172,171,171,170,168,167,166,165,164,164,162,162,161,160,158,158,157,155,155,154,153,152,151,150,149,147,146,145,144,143,143,142,141,139,139,138,137,136,135,134,133,132,131,129,128,127,126,125,124,124,123,122,120,120,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,21,20,20,19,18,17,17,16,16,16,14,14,12,11,11,12,14,14,16,16,16,17,17,18,19,20,20,21,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,46,47,48,47,48,49,48,49,50,49,50,51,50,51,52,51,52,53,52,53,54,57,38,58,38,59,38,58,40,59,40,60,40,59,42,60,42,61,42,60,44,61,44,62,44,61,46,62,46,63,46,62,48,63,48,64,48,63,50,64,50,65,50,64,52,65,52,66,52,65,54,66,54,65,57,66,56,65,59,66,59,65,61,68,58,69,58,68,60,69,60,70,60,69,62,68,65,69,65,68,67,69,67,70,67,69,68,70,69,71,69,70,69,2,73,68,72,71,71,70,3,72,71,2,75,70,74,72,75,72,76,72,75,74,74,73,4,75,74,3,74,73,6,75,74,5,76,75,4,75,74,7,76,75,6,79,78,76,75,8,77,76,7,80,79,77,76,9,78,77,8,79,78,7,80,79,5,79,78,9,82,81,3,81,80,6,82,81,5,83,82,4,82,81,7,81,80,11,82,81,10,83,82,8,84,83,7,85,84,6,84,83,9,85,84,8,86,85,7,85,84,10,86,85,9,87,86,8,86,85,11,87,86,10,88,87,9,87,86,12,88,87,11,89,88,10,88,87,13,89,88,12,90,89,11,89,88,14,90,89,13,91,90,12,90,89,15,91,90,14,92,91,13,91,90,16,92,91,15,93,92,14,92,91,17,93,92,16,94,93,15,93,92,18,94,93,17,95,94,16,94,93,19,95,94,18,96,95,17,95,94,20,96,95,19,97,96,18,96,95,21,97,96,20,98,97,19,97,96,22,98,97,21,99,98,20,98,97,23,99,98,22,100,99,21,99,98,24,100,99,23,101,100,22,100,99,25,101,100,24,102,101,23,101,100,26,102,101,25,103,102,24,102,101,27,103,102,26,104,103,25,103,102,28,104,103,27,105,104,26,104,103,29,105,104,28,106,105,27,105,104,30,106,105,29,107,106,28,106,105,31,107,106,30,108,107,29,107,106,32,108,107,31,109,108,30,108,107,33,109,108,32,110,109,31,109,108,34,110,109,33,111,110,32,110,109,35,111,110,34,112,111,33,113,112,31,116,115,25,119,118,19,120,119,17,123,122,11,126,125,5,127,126,3,130,126,133,123,135,121];
+
+pub const SQ_ROW_K: [usize; 512] = [130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 132, 132, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130];
diff --git a/src/point_add/trailmix_ludicrous/square.rs b/src/point_add/trailmix_ludicrous/square.rs
index 8e22da1f..e9a12d6c 100644
--- a/src/point_add/trailmix_ludicrous/square.rs
+++ b/src/point_add/trailmix_ludicrous/square.rs
@@ -417,31 +417,15 @@ fn apply_f_times_value(circ: &mut B, value: &[QubitId], output_reg: &[QubitId],
 fn apply_shifted_128_tagged(circ: &mut B, value: &[QubitId], output_reg: &[QubitId], op: ShiftOp, tag: &str) {
     assert!(value.len() <= N + 2, "128-shifted half product must be at most 258 bits");
     let low_len = value.len().min(128);
-    if env_tag_enabled("TLM_SQUARE_SHIFTED128_LOW_TAGS", tag) {
-        // Preserve the full-width allocator/free-pool schedule for the downstream
-        // identity-keyed strip. Removing these unused pads makes 4,486 keys stale.
-        let low_pads = alloc_zeroes(circ, 128);
-        let high_pads = alloc_zeroes(circ, 128 - low_len);
-        let mut operand = Vec::with_capacity(128);
-        operand.extend_from_slice(&value[..low_len]);
-        operand.extend_from_slice(&high_pads);
-        match op {
-            ShiftOp::Add => mod_add_shifted_low(circ, &operand, output_reg, 128),
-            ShiftOp::Sub => mod_sub_shifted_low(circ, &operand, output_reg, 128),
-        }
-        free_zeroes(circ, high_pads);
-        free_zeroes(circ, low_pads);
-    } else {
-        let low_pads = alloc_zeroes(circ, 128);
-        let high_pads = alloc_zeroes(circ, 128 - low_len);
-        let mut operand = Vec::with_capacity(N);
-        operand.extend_from_slice(&low_pads);
-        operand.extend_from_slice(&value[..low_len]);
-        operand.extend_from_slice(&high_pads);
-        apply_full_width(circ, &operand, output_reg, op);
-        free_zeroes(circ, high_pads);
-        free_zeroes(circ, low_pads);
-    }
+    let low_pads = alloc_zeroes(circ, 128);
+    let high_pads = alloc_zeroes(circ, 128 - low_len);
+    let mut operand = Vec::with_capacity(N);
+    operand.extend_from_slice(&low_pads);
+    operand.extend_from_slice(&value[..low_len]);
+    operand.extend_from_slice(&high_pads);
+    apply_full_width(circ, &operand, output_reg, op);
+    free_zeroes(circ, high_pads);
+    free_zeroes(circ, low_pads);
 
     if value.len() > 128 {
         if matches!(tag, "a" | "b" | "c") {
@@ -525,214 +509,3 @@ pub fn mod_square_sub_pm_secp256k1_symmetric(circ: &mut B, lambda: &[QubitId], o
     circ.set_phase("square_sum_hi_lo_unbuild");
     unbuild_sum_hi_lo(circ, lambda, sum);
 }
-
-pub fn shifted128_low_miter() -> Result {
-    use crate::point_add::SECP256K1_P;
-    use crate::sim::Simulator;
-    use alloy_primitives::U256;
-    use sha3::{
-        digest::{ExtendableOutput, Update, XofReader},
-        Shake256,
-    };
-
-    struct HelperCircuit {
-        ops: Vec,
-        source: Vec,
-        accumulator: Vec,
-        qubits: usize,
-        bits: usize,
-    }
-
-    fn build_helper(shifted: bool, op: ShiftOp) -> HelperCircuit {
-        let mut circ = B::new();
-        let source = circ.alloc_qubits(128);
-        let accumulator = circ.alloc_qubits(N);
-        if shifted {
-            match op {
-                ShiftOp::Add => mod_add_shifted_low(&mut circ, &source, &accumulator, 128),
-                ShiftOp::Sub => mod_sub_shifted_low(&mut circ, &source, &accumulator, 128),
-            }
-        } else {
-            let low_pads = alloc_zeroes(&mut circ, 128);
-            let mut operand = Vec::with_capacity(N);
-            operand.extend_from_slice(&low_pads);
-            operand.extend_from_slice(&source);
-            apply_full_width(&mut circ, &operand, &accumulator, op);
-            free_zeroes(&mut circ, low_pads);
-        }
-        HelperCircuit {
-            ops: circ.ops,
-            source,
-            accumulator,
-            qubits: circ.next_qubit as usize,
-            bits: circ.next_bit as usize,
-        }
-    }
-
-    fn subtract_mod(lhs: U256, rhs: U256) -> U256 {
-        if lhs >= rhs {
-            lhs - rhs
-        } else {
-            SECP256K1_P - (rhs - lhs)
-        }
-    }
-
-    fn run_helper(
-        circuit: &HelperCircuit,
-        source_values: &[U256; 64],
-        accumulator_values: &[U256; 64],
-        seed_label: &[u8],
-    ) -> Result<[U256; 64], String> {
-        let mut seed = Shake256::default();
-        seed.update(b"shifted128-low-helper-miter");
-        seed.update(seed_label);
-        let mut xof = seed.finalize_xof();
-        let mut sim = Simulator::new(circuit.qubits, circuit.bits, &mut xof);
-        sim.clear_for_shot();
-        for shot in 0..64 {
-            for bit in 0..128 {
-                if source_values[shot].bit(bit) {
-                    *sim.qubit_mut(circuit.source[bit]) |= 1u64 << shot;
-                }
-            }
-            for bit in 0..N {
-                if accumulator_values[shot].bit(bit) {
-                    *sim.qubit_mut(circuit.accumulator[bit]) |= 1u64 << shot;
-                }
-            }
-        }
-        sim.apply_iter(circuit.ops.iter());
-        if sim.phase != 0 {
-            return Err(format!("phase garbage 0x{:016x}", sim.phase));
-        }
-
-        let mut outputs = [U256::ZERO; 64];
-        for shot in 0..64 {
-            let mut source_after = U256::ZERO;
-            let mut output = U256::ZERO;
-            for bit in 0..128 {
-                if (sim.qubit(circuit.source[bit]) >> shot) & 1 == 1 {
-                    source_after |= U256::from(1u64) << bit;
-                }
-            }
-            for bit in 0..N {
-                if (sim.qubit(circuit.accumulator[bit]) >> shot) & 1 == 1 {
-                    output |= U256::from(1u64) << bit;
-                }
-            }
-            if source_after != source_values[shot] {
-                return Err(format!(
-                    "shot {shot}: source changed from {:#x} to {source_after:#x}",
-                    source_values[shot]
-                ));
-            }
-            outputs[shot] = output;
-        }
-
-        for q in 0..circuit.qubits as u64 {
-            if circuit.source.iter().any(|source| source.0 == q)
-                || circuit.accumulator.iter().any(|accumulator| accumulator.0 == q)
-            {
-                continue;
-            }
-            let value = sim.qubit(QubitId(q));
-            if value != 0 {
-                return Err(format!("ancilla qubit {q} not clean: 0x{value:016x}"));
-            }
-        }
-        Ok(outputs)
-    }
-
-    struct RestoreSquareMiterEnv {
-        no_vent_reduce: Option,
-        vent_shifted: Option,
-    }
-
-    impl Drop for RestoreSquareMiterEnv {
-        fn drop(&mut self) {
-            unsafe {
-                match self.no_vent_reduce.take() {
-                    Some(value) => std::env::set_var("TLM_SQUARE_NO_VENT_REDUCE", value),
-                    None => std::env::remove_var("TLM_SQUARE_NO_VENT_REDUCE"),
-                }
-                match self.vent_shifted.take() {
-                    Some(value) => std::env::set_var("TLM_SQUARE_VENT_SHIFTED", value),
-                    None => std::env::remove_var("TLM_SQUARE_VENT_SHIFTED"),
-                }
-            }
-        }
-    }
-
-    let _restore_env = RestoreSquareMiterEnv {
-        no_vent_reduce: std::env::var_os("TLM_SQUARE_NO_VENT_REDUCE"),
-        vent_shifted: std::env::var_os("TLM_SQUARE_VENT_SHIFTED"),
-    };
-    unsafe {
-        std::env::set_var("TLM_SQUARE_NO_VENT_REDUCE", "1");
-        std::env::remove_var("TLM_SQUARE_VENT_SHIFTED");
-    }
-    let mut checked = 0usize;
-    for (op_index, op) in [ShiftOp::Add, ShiftOp::Sub].into_iter().enumerate() {
-        let full = build_helper(false, op);
-        let shifted = build_helper(true, op);
-        for batch in 0u64..32 {
-            let mut input_seed = Shake256::default();
-            input_seed.update(b"shifted128-low-inputs");
-            input_seed.update(&(op_index as u64).to_le_bytes());
-            input_seed.update(&batch.to_le_bytes());
-            let mut inputs = input_seed.finalize_xof();
-            let mut source_values = [U256::ZERO; 64];
-            let mut accumulator_values = [U256::ZERO; 64];
-            let mut bytes = [0u8; 32];
-            for shot in 0..64 {
-                inputs.read(&mut bytes);
-                bytes[16..].fill(0);
-                source_values[shot] = U256::from_le_bytes(bytes);
-                inputs.read(&mut bytes);
-                accumulator_values[shot] = U256::from_le_bytes(bytes) % SECP256K1_P;
-            }
-
-            let mut label = [0u8; 24];
-            label[..8].copy_from_slice(&(op_index as u64).to_le_bytes());
-            label[8..16].copy_from_slice(&batch.to_le_bytes());
-            let full_outputs = run_helper(&full, &source_values, &accumulator_values, &label)
-                .map_err(|error| {
-                    format!("full helper op={op_index} batch={batch}: {error}")
-                })?;
-            let shifted_outputs =
-                run_helper(&shifted, &source_values, &accumulator_values, &label).map_err(
-                    |error| format!("shifted helper op={op_index} batch={batch}: {error}"),
-                )?;
-
-            for shot in 0..64 {
-                let operand = source_values[shot] << 128;
-                let expected = match op {
-                    ShiftOp::Add => {
-                        accumulator_values[shot].add_mod(operand, SECP256K1_P)
-                    }
-                    ShiftOp::Sub => subtract_mod(accumulator_values[shot], operand),
-                };
-                if full_outputs[shot] != expected {
-                    return Err(format!(
-                        "full helper op={op_index} batch={batch} shot={shot}: got {:#x}, expected {expected:#x}",
-                        full_outputs[shot]
-                    ));
-                }
-                if shifted_outputs[shot] != expected {
-                    return Err(format!(
-                        "shifted helper op={op_index} batch={batch} shot={shot}: got {:#x}, expected {expected:#x}",
-                        shifted_outputs[shot]
-                    ));
-                }
-                if shifted_outputs[shot] != full_outputs[shot] {
-                    return Err(format!(
-                        "miter op={op_index} batch={batch} shot={shot}: full={:#x}, shifted={:#x}",
-                        full_outputs[shot], shifted_outputs[shot]
-                    ));
-                }
-                checked += 1;
-            }
-        }
-    }
-    Ok(checked)
-}
diff --git a/src/point_add/venting.rs b/src/point_add/venting.rs
index 3225ebe1..6c2f52f6 100644
--- a/src/point_add/venting.rs
+++ b/src/point_add/venting.rs
@@ -1,2067 +1,2067 @@
-
-use super::{BitId, QubitId, B};
-use crate::circuit::{Op, OperationType};
-
-#[allow(dead_code)]
-pub(crate) fn xor_right_shifted_carries_into_classical(
-    b: &mut B,
-    q_src: &[QubitId],
-    offset_bits: u64,
-    q_dst: &[QubitId],
-    carry_in: bool,
-) {
-    let n = q_dst.len();
-    assert!(n <= q_src.len() && q_src.len() <= n + 1, "len mismatch");
-    if n == 0 {
-        return;
-    }
-
-    let bit = |k: usize| -> bool {
-        if k >= 64 {
-            false
-        } else {
-            (offset_bits >> k) & 1 != 0
-        }
-    };
-
-    let ccx_inv =
-        |b: &mut B, ctrl_a: QubitId, inv_a: bool, ctrl_b: QubitId, inv_b: bool, target: QubitId| {
-            if inv_a {
-                b.x(ctrl_a);
-            }
-            if inv_b {
-                b.x(ctrl_b);
-            }
-            b.ccx(ctrl_a, ctrl_b, target);
-            if inv_b {
-                b.x(ctrl_b);
-            }
-            if inv_a {
-                b.x(ctrl_a);
-            }
-        };
-
-    for k in (1..n).rev() {
-        ccx_inv(b, q_src[k], bit(k), q_dst[k - 1], false, q_dst[k]);
-    }
-
-    for k in 0..n {
-        if bit(k) {
-            b.x(q_dst[k]);
-        }
-    }
-
-    let carry_in_xor_offset0 = carry_in ^ bit(0);
-    if carry_in_xor_offset0 {
-
-        if bit(0) {
-            b.x(q_src[0]);
-        }
-        b.cx(q_src[0], q_dst[0]);
-        if bit(0) {
-            b.x(q_src[0]);
-        }
-    }
-
-    for k in 1..n {
-        ccx_inv(b, q_src[k], bit(k), q_dst[k - 1], bit(k), q_dst[k]);
-    }
-}
-
-pub(crate) fn add_vented_2clean_classical(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    offset_bits: u64,
-    carry_in: bool,
-    vent_keys: &[BitId],
-) {
-    add_vented_2clean_classical_cxt(
-        b,
-        q_target,
-        q_clean2,
-        offset_bits,
-        carry_in,
-        vent_keys,
-        None,
-    );
-}
-
-pub(crate) fn add_vented_2clean_classical_cxt(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    offset_bits: u64,
-    carry_in: bool,
-    vent_keys: &[BitId],
-    carry_xor_target: Option<&[Option]>,
-) {
-    let n = q_target.len();
-    if n == 0 {
-        return;
-    }
-    let bit = |k: usize| -> bool {
-        if k >= 64 {
-            false
-        } else {
-            (offset_bits >> k) & 1 != 0
-        }
-    };
-
-    if n == 1 {
-        if carry_in {
-            b.x(q_target[0]);
-        }
-        if bit(0) {
-            b.x(q_target[0]);
-        }
-        return;
-    }
-
-    for k in 0..n {
-        if bit(k) {
-            b.x(q_target[k]);
-        }
-    }
-
-    let get_carry_qubit = |k: usize| -> Option {
-        if k == 0 {
-            None
-        } else if k == n - 1 {
-            Some(q_target[n - 1])
-        } else {
-            Some(q_clean2[k % 2])
-        }
-    };
-
-    for k in 0..n - 1 {
-
-        if k < n - 2 {
-            if let Some(q) = get_carry_qubit(k + 1) {
-
-                let mut op = Op::empty();
-                op.kind = OperationType::R;
-                op.q_target = q;
-                b.ops.push(op);
-            }
-        }
-
-        if k == 0 {
-            let eff_carry = carry_in ^ bit(0);
-            if eff_carry {
-
-                if let Some(q) = get_carry_qubit(1) {
-                    b.cx(q_target[0], q);
-                }
-            }
-        } else {
-            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
-            let carry_next = get_carry_qubit(k + 1).expect("non-boundary next carry");
-            if bit(k) {
-                b.x(carry_q);
-                b.ccx(q_target[k], carry_q, carry_next);
-                b.x(carry_q);
-            } else {
-                b.ccx(q_target[k], carry_q, carry_next);
-            }
-        }
-
-        if k == 0 {
-            if carry_in {
-                b.x(q_target[0]);
-            }
-        } else {
-            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
-            b.cx(carry_q, q_target[k]);
-        }
-
-        if let Some(cxt) = carry_xor_target {
-            if k < cxt.len() {
-                if let Some(dst) = cxt[k] {
-                    if k == 0 {
-                        if carry_in {
-                            b.x(dst);
-                        }
-                    } else {
-                        let carry_q = get_carry_qubit(k).expect("non-boundary carry");
-                        b.cx(carry_q, dst);
-                    }
-                }
-            }
-        }
-
-        if k > 0 {
-            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
-            b.hmr(carry_q, vent_keys[k]);
-        }
-
-        if bit(k) {
-            if let Some(q) = get_carry_qubit(k + 1) {
-                b.x(q);
-            }
-        }
-    }
-}
-
-pub(crate) fn iadd_linear_clean_classical(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_clean: &[QubitId],
-    offset_bits: u64,
-    carry_in: bool,
-) {
-    let n = q_target.len();
-    if n == 0 {
-        return;
-    }
-    assert!(q_clean.len() >= n.saturating_sub(2), "need n-2 clean");
-    let q_clean = &q_clean[..n.saturating_sub(2)];
-
-    let bit = |k: usize| -> bool {
-        if k >= 64 {
-            false
-        } else {
-            (offset_bits >> k) & 1 != 0
-        }
-    };
-
-    if n == 1 {
-        if bit(0) {
-            b.x(q_target[0]);
-        }
-        if carry_in {
-            b.x(q_target[0]);
-        }
-        return;
-    }
-
-    if n == 2 {
-
-        if bit(0) {
-            b.x(q_target[1]);
-        }
-
-        for k in 0..2 {
-            if bit(k) {
-                b.x(q_target[k]);
-            }
-        }
-
-        let eff0 = carry_in ^ bit(0);
-        if eff0 {
-            b.cx(q_target[0], q_target[1]);
-        }
-
-        if carry_in {
-            b.x(q_target[0]);
-        }
-        return;
-    }
-
-    for &q in q_clean.iter() {
-        let mut op = Op::empty();
-        op.kind = OperationType::R;
-        op.q_target = q;
-        b.ops.push(op);
-    }
-
-    let get_carry = |k: usize| -> Option {
-        if k == 0 {
-            None
-        } else if k == n - 1 {
-            Some(q_target[n - 1])
-        } else {
-            Some(q_clean[k - 1])
-        }
-    };
-
-    for k in 0..n - 1 {
-        if bit(k) {
-            if let Some(q) = get_carry(k + 1) {
-                b.x(q);
-            }
-        }
-    }
-
-    for k in 0..n {
-        if bit(k) {
-            b.x(q_target[k]);
-        }
-    }
-
-    for k in 0..n - 1 {
-
-        let next = get_carry(k + 1).expect("k+1 in bounds");
-        if k == 0 {
-
-            let eff = carry_in ^ bit(0);
-            if eff {
-                b.cx(q_target[0], next);
-            }
-        } else {
-            let cur = get_carry(k).expect("k in bounds");
-            if bit(k) {
-                b.x(cur);
-                b.ccx(q_target[k], cur, next);
-                b.x(cur);
-            } else {
-                b.ccx(q_target[k], cur, next);
-            }
-        }
-    }
-
-    for k in (0..n - 2).rev() {
-
-        let next = get_carry(k + 1).expect("k+1 in bounds");
-        b.cx(next, q_target[k + 1]);
-
-        let m = b.alloc_bit();
-        b.hmr(next, m);
-
-        if bit(k) {
-            let mut op = Op::empty();
-            op.kind = OperationType::Neg;
-            op.c_condition = m;
-            b.ops.push(op);
-        }
-
-        if k == 0 {
-
-            let eff = carry_in ^ bit(0);
-            if eff {
-
-                let mut op = Op::empty();
-                op.kind = OperationType::Z;
-                op.q_target = q_target[k];
-                op.c_condition = m;
-                b.ops.push(op);
-            }
-        } else {
-            let cur = get_carry(k).expect("k in bounds");
-
-            if bit(k) {
-                b.x(cur);
-                b.cz_if(q_target[k], cur, m);
-                b.x(cur);
-            } else {
-                b.cz_if(q_target[k], cur, m);
-            }
-        }
-    }
-
-    if carry_in {
-        b.x(q_target[0]);
-    }
-}
-
-#[allow(dead_code)]
-pub(crate) fn iadd_dirty_2clean_classical(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_dirty: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    offset_bits: u64,
-    carry_in: bool,
-) {
-    let n = q_target.len();
-    if n == 0 {
-        return;
-    }
-
-    if n <= 4 {
-        iadd_linear_clean_classical(b, q_target, q_clean2, offset_bits, carry_in);
-        return;
-    }
-    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
-    let q_dirty = &q_dirty[..n - 2];
-
-    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
-
-    let cxt: Vec> = (0..n)
-        .map(|k| {
-            if k == 0 {
-                None
-            } else {
-                q_dirty.get(k - 1).copied()
-            }
-        })
-        .collect();
-
-    add_vented_2clean_classical_cxt(
-        b,
-        q_target,
-        q_clean2,
-        offset_bits,
-        carry_in,
-        &vent_keys,
-        Some(&cxt),
-    );
-
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-
-    for k in 0..n - 2 {
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-
-    xor_right_shifted_carries_into_classical(b, &q_target[..n - 1], offset_bits, q_dirty, carry_in);
-    for k in 0..n - 2 {
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-}
-
-pub(crate) fn ciadd_dirty_2clean_classical(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_dirty: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    offset_bits: u64,
-    ctrl: QubitId,
-    carry_in: bool,
-) {
-
-    assert!(
-        !carry_in,
-        "ciadd_dirty_2clean_classical requires carry_in=false; pre-process if needed"
-    );
-    let n = q_target.len();
-    if n == 0 {
-        return;
-    }
-    if n <= 4 {
-
-        let a: Vec = (0..n).map(|_| b.alloc_qubit()).collect();
-        for i in 0..n {
-            if (offset_bits >> i) & 1 != 0 {
-                b.cx(ctrl, a[i]);
-            }
-        }
-
-        for i in 0..n {
-            if (offset_bits >> i) & 1 != 0 {
-                b.cx(ctrl, a[i]);
-            }
-        }
-        for q in a {
-            b.free(q);
-        }
-        panic!("ciadd_dirty_2clean: n<=4 fallback not implemented; use uncontrolled path");
-    }
-    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
-    let q_dirty = &q_dirty[..n - 2];
-
-    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
-
-    let cxt: Vec> = (0..n)
-        .map(|k| {
-            if k == 0 {
-                None
-            } else {
-                q_dirty.get(k - 1).copied()
-            }
-        })
-        .collect();
-
-    c_add_vented_2clean_inline(
-        b,
-        q_target,
-        q_clean2,
-        offset_bits,
-        ctrl,
-        carry_in,
-        &vent_keys,
-        &cxt,
-    );
-
-    for k in 0..n {
-
-        b.cx(ctrl, q_target[k]);
-    }
-    for k in 0..n - 2 {
-
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-
-    c_xor_right_shifted_carries_into_classical(
-        b,
-        &q_target[..n - 1],
-        offset_bits,
-        ctrl,
-        q_dirty,
-        carry_in,
-    );
-    for k in 0..n - 2 {
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-    for k in 0..n {
-        b.cx(ctrl, q_target[k]);
-    }
-}
-
-fn c_add_vented_2clean_inline(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    offset_bits: u64,
-    ctrl: QubitId,
-    carry_in: bool,
-    vent_keys: &[BitId],
-    carry_xor_target: &[Option],
-) {
-    let n = q_target.len();
-    if n < 2 {
-
-        if n == 1 {
-            if carry_in {
-                b.cx(ctrl, q_target[0]);
-            }
-            if (offset_bits & 1) != 0 {
-                b.cx(ctrl, q_target[0]);
-            }
-        }
-        return;
-    }
-
-    let bit = |k: usize| -> bool {
-        if k >= 64 {
-            false
-        } else {
-            (offset_bits >> k) & 1 != 0
-        }
-    };
-
-    for k in 0..n {
-        if bit(k) {
-            b.cx(ctrl, q_target[k]);
-        }
-    }
-
-    let get_carry_qubit = |k: usize| -> Option {
-        if k == 0 {
-            None
-        } else if k == n - 1 {
-            Some(q_target[n - 1])
-        } else {
-            Some(q_clean2[k % 2])
-        }
-    };
-
-    for k in 0..n - 1 {
-
-        if k < n - 2 {
-            if let Some(q) = get_carry_qubit(k + 1) {
-                let mut op = Op::empty();
-                op.kind = OperationType::R;
-                op.q_target = q;
-                b.ops.push(op);
-            }
-        }
-
-        if k == 0 {
-            let next = get_carry_qubit(1);
-            if let Some(next_q) = next {
-                if bit(0) {
-
-                    if carry_in {
-
-                        b.x(ctrl);
-                        b.ccx(q_target[0], ctrl, next_q);
-                        b.x(ctrl);
-                    } else {
-                        b.ccx(q_target[0], ctrl, next_q);
-                    }
-                } else if carry_in {
-
-                    b.cx(q_target[0], next_q);
-                }
-
-            }
-        } else {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            let next = get_carry_qubit(k + 1).expect("non-boundary next carry");
-            if bit(k) {
-
-                b.cx(ctrl, cur);
-                b.ccx(q_target[k], cur, next);
-                b.cx(ctrl, cur);
-            } else {
-                b.ccx(q_target[k], cur, next);
-            }
-        }
-
-        if k == 0 {
-            if carry_in {
-                b.x(q_target[0]);
-            }
-        } else {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            b.cx(cur, q_target[k]);
-        }
-
-        if k < carry_xor_target.len() {
-            if let Some(dst) = carry_xor_target[k] {
-                if k == 0 {
-                    if carry_in {
-                        b.x(dst);
-                    }
-                } else {
-                    let cur = get_carry_qubit(k).expect("non-boundary carry");
-                    b.cx(cur, dst);
-                }
-            }
-        }
-
-        if k > 0 {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            b.hmr(cur, vent_keys[k]);
-        }
-
-        if bit(k) {
-            if let Some(q) = get_carry_qubit(k + 1) {
-                b.cx(ctrl, q);
-            }
-        }
-    }
-}
-
-pub(crate) fn add_vented_2clean_qoffset(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    q_offset: &[QubitId],
-    carry_in: bool,
-    vent_keys: &[BitId],
-    carry_xor_target: Option<&[Option]>,
-) {
-    let n = q_target.len();
-    assert_eq!(q_offset.len(), n, "q_offset length must match q_target");
-    if n == 0 {
-        return;
-    }
-    if n == 1 {
-        if carry_in {
-            b.x(q_target[0]);
-        }
-        b.cx(q_offset[0], q_target[0]);
-        return;
-    }
-
-    for k in 0..n {
-        b.cx(q_offset[k], q_target[k]);
-    }
-
-    let get_carry_qubit = |k: usize| -> Option {
-        if k == 0 {
-            None
-        } else if k == n - 1 {
-            Some(q_target[n - 1])
-        } else {
-            Some(q_clean2[k % 2])
-        }
-    };
-
-    for k in 0..n - 1 {
-        if k < n - 2 {
-            if let Some(q) = get_carry_qubit(k + 1) {
-                let mut op = Op::empty();
-                op.kind = OperationType::R;
-                op.q_target = q;
-                b.ops.push(op);
-            }
-        }
-
-        if k == 0 {
-            let next = get_carry_qubit(1);
-            if let Some(next_q) = next {
-                if carry_in {
-                    b.x(q_offset[0]);
-                    b.ccx(q_target[0], q_offset[0], next_q);
-                    b.x(q_offset[0]);
-                } else {
-                    b.ccx(q_target[0], q_offset[0], next_q);
-                }
-            }
-        } else {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            let next = get_carry_qubit(k + 1).expect("non-boundary next carry");
-
-            b.cx(q_offset[k], cur);
-            b.ccx(q_target[k], cur, next);
-            b.cx(q_offset[k], cur);
-        }
-
-        if k == 0 {
-            if carry_in {
-                b.x(q_target[0]);
-            }
-        } else {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            b.cx(cur, q_target[k]);
-        }
-
-        if let Some(cxt) = carry_xor_target {
-            if k < cxt.len() {
-                if let Some(dst) = cxt[k] {
-                    if k == 0 {
-                        if carry_in {
-                            b.x(dst);
-                        }
-                    } else {
-                        let cur = get_carry_qubit(k).expect("non-boundary carry");
-                        b.cx(cur, dst);
-                    }
-                }
-            }
-        }
-
-        if k > 0 {
-            let cur = get_carry_qubit(k).expect("non-boundary carry");
-            b.hmr(cur, vent_keys[k]);
-        }
-
-        if let Some(q) = get_carry_qubit(k + 1) {
-            b.cx(q_offset[k], q);
-        }
-    }
-}
-
-pub(crate) fn xor_right_shifted_carries_into_qoffset(
-    b: &mut B,
-    q_src: &[QubitId],
-    q_offset: &[QubitId],
-    q_dst: &[QubitId],
-    carry_in: bool,
-) {
-    let n = q_dst.len();
-    assert!(n <= q_src.len() && q_src.len() <= n + 1, "len mismatch");
-    if n == 0 {
-        return;
-    }
-
-    let ccx_with_qxor = |b: &mut B,
-                         ctrl_a: QubitId,
-                         xor_a: Option,
-                         ctrl_b: QubitId,
-                         xor_b: Option,
-                         target: QubitId| {
-        if let Some(x) = xor_a {
-            b.cx(x, ctrl_a);
-        }
-        if let Some(x) = xor_b {
-            b.cx(x, ctrl_b);
-        }
-        b.ccx(ctrl_a, ctrl_b, target);
-        if let Some(x) = xor_b {
-            b.cx(x, ctrl_b);
-        }
-        if let Some(x) = xor_a {
-            b.cx(x, ctrl_a);
-        }
-    };
-
-    for k in (1..n).rev() {
-        ccx_with_qxor(b, q_src[k], Some(q_offset[k]), q_dst[k - 1], None, q_dst[k]);
-    }
-
-    for k in 0..n {
-        b.cx(q_offset[k], q_dst[k]);
-    }
-
-    b.cx(q_offset[0], q_src[0]);
-    if carry_in {
-        b.x(q_offset[0]);
-    }
-    b.ccx(q_src[0], q_offset[0], q_dst[0]);
-    if carry_in {
-        b.x(q_offset[0]);
-    }
-    b.cx(q_offset[0], q_src[0]);
-
-    for k in 1..n {
-        ccx_with_qxor(
-            b,
-            q_src[k],
-            Some(q_offset[k]),
-            q_dst[k - 1],
-            Some(q_offset[k]),
-            q_dst[k],
-        );
-    }
-}
-
-pub(crate) fn iadd_dirty_2clean_qoffset(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_dirty: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    q_offset: &[QubitId],
-    carry_in: bool,
-) {
-    let n = q_target.len();
-    assert_eq!(q_offset.len(), n);
-    if n == 0 {
-        return;
-    }
-    if n <= 4 {
-        panic!("iadd_dirty_2clean_qoffset: n<=4 not supported yet, use cuccaro_add");
-    }
-    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
-    let q_dirty = &q_dirty[..n - 2];
-
-    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
-    let cxt: Vec> = (0..n)
-        .map(|k| {
-            if k == 0 {
-                None
-            } else {
-                q_dirty.get(k - 1).copied()
-            }
-        })
-        .collect();
-
-    add_vented_2clean_qoffset(
-        b,
-        q_target,
-        q_clean2,
-        q_offset,
-        carry_in,
-        &vent_keys,
-        Some(&cxt),
-    );
-
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-    for k in 0..n - 2 {
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-    xor_right_shifted_carries_into_qoffset(b, &q_target[..n - 1], q_offset, q_dirty, carry_in);
-    for k in 0..n - 2 {
-        let mut op = Op::empty();
-        op.kind = OperationType::Z;
-        op.q_target = q_dirty[k];
-        op.c_condition = vent_keys[k + 1];
-        b.ops.push(op);
-    }
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-}
-
-pub(crate) fn isub_dirty_2clean_qoffset(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_dirty: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    q_offset: &[QubitId],
-) {
-    let n = q_target.len();
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-    iadd_dirty_2clean_qoffset(b, q_target, q_dirty, q_clean2, q_offset, false);
-    for k in 0..n {
-        b.x(q_target[k]);
-    }
-}
-
-fn c_xor_right_shifted_carries_into_classical(
-    b: &mut B,
-    q_src: &[QubitId],
-    offset_bits: u64,
-    ctrl: QubitId,
-    q_dst: &[QubitId],
-    carry_in: bool,
-) {
-    let n = q_dst.len();
-    assert!(n <= q_src.len() && q_src.len() <= n + 1);
-    if n == 0 {
-        return;
-    }
-    let bit = |k: usize| -> bool {
-        if k >= 64 {
-            false
-        } else {
-            (offset_bits >> k) & 1 != 0
-        }
-    };
-
-    let ccx_ctrl_mix = |b: &mut B,
-                        ctrl_a: QubitId,
-                        a_xor_ctrl: bool,
-                        ctrl_b: QubitId,
-                        b_xor_ctrl: bool,
-                        target: QubitId| {
-        if a_xor_ctrl {
-            b.cx(ctrl, ctrl_a);
-        }
-        if b_xor_ctrl {
-            b.cx(ctrl, ctrl_b);
-        }
-        b.ccx(ctrl_a, ctrl_b, target);
-        if b_xor_ctrl {
-            b.cx(ctrl, ctrl_b);
-        }
-        if a_xor_ctrl {
-            b.cx(ctrl, ctrl_a);
-        }
-    };
-
-    for k in (1..n).rev() {
-        ccx_ctrl_mix(b, q_src[k], bit(k), q_dst[k - 1], false, q_dst[k]);
-    }
-
-    for k in 0..n {
-        if bit(k) {
-            b.cx(ctrl, q_dst[k]);
-        }
-    }
-
-    let cin_eff_uses_ctrl = bit(0);
-    let cin_classical_part = carry_in ^ false;
-    if cin_eff_uses_ctrl {
-
-        if carry_in {
-
-            b.cx(ctrl, q_src[0]);
-            b.x(ctrl);
-            b.ccx(q_src[0], ctrl, q_dst[0]);
-            b.x(ctrl);
-            b.cx(ctrl, q_src[0]);
-        } else {
-
-            b.cx(ctrl, q_src[0]);
-            b.ccx(q_src[0], ctrl, q_dst[0]);
-            b.cx(ctrl, q_src[0]);
-        }
-    } else {
-
-        if cin_classical_part {
-
-            b.cx(q_src[0], q_dst[0]);
-        }
-
-    }
-    for k in 1..n {
-        ccx_ctrl_mix(b, q_src[k], bit(k), q_dst[k - 1], bit(k), q_dst[k]);
-    }
-}
-
-pub(crate) fn cisub_dirty_2clean_classical(
-    b: &mut B,
-    q_target: &[QubitId],
-    q_dirty: &[QubitId],
-    q_clean2: &[QubitId; 2],
-    c_bits: u64,
-    ctrl: QubitId,
-) {
-    let n = q_target.len();
-
-    for k in 0..n {
-        b.cx(ctrl, q_target[k]);
-    }
-    ciadd_dirty_2clean_classical(
-        b, q_target, q_dirty, q_clean2, c_bits, ctrl,
-        false,
-    );
-    for k in 0..n {
-        b.cx(ctrl, q_target[k]);
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::sim::Simulator;
-    use sha3::{
-        digest::{ExtendableOutput, Update},
-        Shake256,
-    };
-
-    fn anf_degree_density_from_truth_table(mut table: Vec, vars: usize) -> (usize, usize) {
-        let states = 1usize << vars;
-
-        for bit in 0..vars {
-            let step = 1usize << bit;
-            for mask in 0..states {
-                if (mask & step) != 0 {
-                    table[mask] ^= table[mask ^ step];
-                }
-            }
-        }
-
-        let mut degree = 0usize;
-        let mut density = 0usize;
-        for (mask, &coeff) in table.iter().enumerate() {
-            if coeff != 0 {
-                density += 1;
-                degree = degree.max(mask.count_ones() as usize);
-            }
-        }
-        (degree, density)
-    }
-
-    fn product_phase_anf_degree_density(n: usize, phase_mask: u64) -> (usize, usize) {
-        assert!(n > 0 && n <= 10, "test keeps exhaustive table small");
-        let vars = 2 * n;
-        let states = 1usize << vars;
-        let x_mask = (1u64 << n) - 1;
-        let mut table = vec![0u8; states];
-        for state in 0..states {
-            let x = (state as u64) & x_mask;
-            let y = ((state as u64) >> n) & x_mask;
-            let prod = x * y;
-            table[state] = ((prod & phase_mask).count_ones() & 1) as u8;
-        }
-        anf_degree_density_from_truth_table(table, vars)
-    }
-
-    fn carry_save_product_bits_for_phase_test(n: usize, x: u64, y: u64) -> Vec {
-
-        let mut cols = vec![Vec::::new(); 2 * n + 8];
-        for i in 0..n {
-            for j in 0..n {
-                let bit = (((x >> i) & 1) & ((y >> j) & 1)) as u8;
-                cols[i + j].push(bit);
-            }
-        }
-        for k in 0..cols.len() - 1 {
-            while cols[k].len() > 2 {
-                let a = cols[k].pop().unwrap();
-                let b = cols[k].pop().unwrap();
-                let c = cols[k].pop().unwrap();
-                let sum = a ^ b ^ c;
-                let carry = (a & b) ^ (a & c) ^ (b & c);
-                cols[k].push(sum);
-                cols[k + 1].push(carry);
-            }
-        }
-        let mut out = Vec::with_capacity(4 * n + 4);
-        for col in cols.iter().take(2 * n + 2) {
-            out.push(*col.get(0).unwrap_or(&0));
-            out.push(*col.get(1).unwrap_or(&0));
-        }
-        out
-    }
-
-    fn carry_save_product_phase_anf_degree_density(
-        n: usize,
-        top_column_only: bool,
-    ) -> (usize, usize) {
-        assert!(
-            n > 0 && n <= 8,
-            "test keeps exhaustive carry-save table small"
-        );
-        let vars = 2 * n;
-        let states = 1usize << vars;
-        let x_mask = (1u64 << n) - 1;
-        let mut table = vec![0u8; states];
-        for state in 0..states {
-            let x = (state as u64) & x_mask;
-            let y = ((state as u64) >> n) & x_mask;
-            let bits = carry_save_product_bits_for_phase_test(n, x, y);
-            table[state] = if top_column_only {
-                let k = 2 * (2 * n - 2);
-                bits[k] ^ bits[k + 1]
-            } else {
-                bits.iter().fold(0u8, |acc, &b| acc ^ b)
-            };
-        }
-        anf_degree_density_from_truth_table(table, vars)
-    }
-
-    #[test]
-    fn raw_product_measurement_phase_is_dense_not_free_kickmix() {
-
-        for &n in &[4usize, 6, 8, 10] {
-            let full_mask = if 2 * n == 64 {
-                u64::MAX
-            } else {
-                (1u64 << (2 * n)) - 1
-            };
-            let high_mask = 1u64 << (2 * n - 2);
-            let (deg_full, dens_full) = product_phase_anf_degree_density(n, full_mask);
-            let (deg_high, dens_high) = product_phase_anf_degree_density(n, high_mask);
-            eprintln!(
-                "raw_product_phase n={n} full_deg={deg_full} full_density={dens_full} high_deg={deg_high} high_density={dens_high}"
-            );
-            if n == 10 {
-                println!("METRIC raw_product_mbu_fullmask_degree_n10={deg_full}");
-                println!("METRIC raw_product_mbu_fullmask_density_n10={dens_full}");
-                println!("METRIC raw_product_mbu_highbit_degree_n10={deg_high}");
-                println!("METRIC raw_product_mbu_highbit_density_n10={dens_high}");
-            }
-        }
-
-        let (deg_full, dens_full) = product_phase_anf_degree_density(10, (1u64 << 20) - 1);
-        let (deg_high, dens_high) = product_phase_anf_degree_density(10, 1u64 << 18);
-        assert_eq!(deg_full, 19);
-        assert_eq!(dens_full, 427_812);
-        assert_eq!(deg_high, 19);
-        assert_eq!(dens_high, 120_581);
-    }
-
-    #[test]
-    fn carry_save_product_scratch_mbu_still_has_dense_phases() {
-
-        for &n in &[4usize, 6, 8] {
-            let (deg_all, dens_all) = carry_save_product_phase_anf_degree_density(n, false);
-            let (deg_top, dens_top) = carry_save_product_phase_anf_degree_density(n, true);
-            eprintln!(
-                "carry_save_product_phase n={n} all_deg={deg_all} all_density={dens_all} top_deg={deg_top} top_density={dens_top}"
-            );
-            if n == 8 {
-                println!("METRIC carry_save_product_mbu_all_degree_n8={deg_all}");
-                println!("METRIC carry_save_product_mbu_all_density_n8={dens_all}");
-                println!("METRIC carry_save_product_mbu_top_degree_n8={deg_top}");
-                println!("METRIC carry_save_product_mbu_top_density_n8={dens_top}");
-            }
-        }
-        let (deg_all, dens_all) = carry_save_product_phase_anf_degree_density(8, false);
-        let (deg_top, dens_top) = carry_save_product_phase_anf_degree_density(8, true);
-        assert_eq!(deg_all, 16);
-        assert_eq!(dens_all, 20_440);
-        assert_eq!(deg_top, 15);
-        assert_eq!(dens_top, 3_602);
-    }
-
-    fn classical_carry(x: u64, d: u64, cin: bool, n: usize) -> u64 {
-
-        let mut c: u64 = 0;
-        let mut prev = cin;
-        for k in 0..n {
-            let xk = (x >> k) & 1 != 0;
-            let dk = (d >> k) & 1 != 0;
-
-            let new_carry = (prev && xk) || (prev && dk) || (xk && dk);
-            if new_carry {
-                c |= 1 << (k + 1);
-            }
-            prev = new_carry;
-        }
-
-        if cin {
-            c |= 1;
-        }
-        c
-    }
-
-    fn run_xor_rsh_carries(n: usize, trials: usize) -> bool {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 42]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        for _trial in 0..trials {
-            let mut buf = [0u8; 32];
-            xof.read(&mut buf);
-            let src_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let dst_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
-            let cin_raw = buf[24];
-            let src = if n < 64 {
-                src_raw & ((1u64 << n) - 1)
-            } else {
-                src_raw
-            };
-            let dst = if n < 64 {
-                dst_raw & ((1u64 << n) - 1)
-            } else {
-                dst_raw
-            };
-            let offset = if n < 64 {
-                offset_raw & ((1u64 << n) - 1)
-            } else {
-                offset_raw
-            };
-            let cin = (cin_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_src: Vec = bb.alloc_qubits(n);
-            let q_dst: Vec = bb.alloc_qubits(n);
-
-            xor_right_shifted_carries_into_classical(&mut bb, &q_src, offset, &q_dst, cin);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = 0usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[77u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-
-            for k in 0..n {
-                if (src >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_src[k]) = 1;
-                }
-                if (dst >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_dst[k]) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected_carries = classical_carry(src, offset, cin, n + 1);
-            let expected_rsh = expected_carries >> 1;
-            let expected_dst = (dst ^ expected_rsh) & ((1u64 << n) - 1);
-
-            let mut got_dst: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_dst[k]) & 1 != 0 {
-                    got_dst |= 1 << k;
-                }
-            }
-            if got_dst != expected_dst {
-                eprintln!(
-                    "n={} src={:#x} dst={:#x} offset={:#x} cin={} got={:#x} exp={:#x}",
-                    n, src, dst, offset, cin, got_dst, expected_dst
-                );
-                return false;
-            }
-        }
-        true
-    }
-
-    #[test]
-    fn test_xor_rsh_carries_small() {
-        for n in 1..=8 {
-            assert!(run_xor_rsh_carries(n, 20), "failed at n={n}");
-        }
-    }
-
-    fn run_vented_add_2clean(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 51]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 24];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let cin_raw = buf[16];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let offset = offset_raw & mask;
-            let cin = (cin_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-            let vent_keys: Vec = (0..n).map(|_| bb.alloc_bit()).collect();
-
-            add_vented_2clean_classical(&mut bb, &q_target, &q_clean2, offset, cin, &vent_keys);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[101u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            if got == expected_sum {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "vented add FAIL n={} t={:#x} o={:#x} cin={} got={:#x} exp={:#x}",
-                        n, target, offset, cin, got, expected_sum
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_vented_add_2clean_small() {
-        for n in 2..=8 {
-            let (ok, bad) = run_vented_add_2clean(n, 20);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    fn run_linear_clean_add(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 73]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 24];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let cin_raw = buf[16];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let offset = offset_raw & mask;
-            let cin = (cin_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let n_clean = n.saturating_sub(2).max(2);
-            let q_clean: Vec = bb.alloc_qubits(n_clean);
-
-            iadd_linear_clean_classical(&mut bb, &q_target, &q_clean, offset, cin);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[151u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            if got == expected_sum {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "HRS FAIL n={} t={:#x} o={:#x} cin={} got={:#x} exp={:#x}",
-                        n, target, offset, cin, got, expected_sum
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_iadd_linear_clean_small() {
-        for n in 1..=8 {
-            let (ok, bad) = run_linear_clean_add(n, 20);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    fn run_iadd_dirty_2clean(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 97]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 32];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
-            let cin_raw = buf[24];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let offset = offset_raw & mask;
-            let dirty_init = dirty_raw & mask;
-            let cin = (cin_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-
-            iadd_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, offset, cin);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[201u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dirty_ok = if n > 4 {
-                got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask))
-            } else {
-                true
-            };
-
-            let phase = sim.global_phase() & 1;
-
-            if got == expected_sum && dirty_ok && phase == 0 {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "iadd_dirty_2clean FAIL n={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} dirty_ok={} phase={}",
-                        n, target, offset, dirty_init, cin, got, expected_sum, dirty_ok, phase
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_iadd_dirty_2clean_small() {
-        for n in 2..=8 {
-            let (ok, bad) = run_iadd_dirty_2clean(n, 10);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    fn run_ciadd_dirty_2clean(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 113]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 40];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
-            let cin_raw = buf[24];
-            let ctrl_raw = buf[25];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let offset = offset_raw & mask;
-            let dirty_init = dirty_raw & mask;
-            let cin = false;
-            let _ = cin_raw;
-            let ctrl_val = (ctrl_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-            let q_ctrl = bb.alloc_qubit();
-
-            ciadd_dirty_2clean_classical(
-                &mut bb, &q_target, &q_dirty, &q_clean2, offset, q_ctrl, cin,
-            );
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[211u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            if ctrl_val {
-                *sim.qubit_mut(q_ctrl) = 1;
-            }
-            sim.apply(&ops);
-
-            let expected_sum = if ctrl_val {
-                (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask
-            } else {
-                target
-            };
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
-            let phase = sim.global_phase() & 1;
-            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
-
-            if got == expected_sum && dirty_ok && phase == 0 && ctrl_preserved {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "ciadd_dirty FAIL n={} t={:#x} o={:#x} d={:#x} cin={} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_preserved={}",
-                        n, target, offset, dirty_init, cin, ctrl_val, got, expected_sum, dirty_ok, phase, ctrl_preserved
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_ciadd_dirty_2clean_small() {
-        for n in 5..=10 {
-            let (ok, bad) = run_ciadd_dirty_2clean(n, 10);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    fn run_cisub_dirty(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 179]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 40];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let c_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
-            let ctrl_raw = buf[25];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let c = c_raw & mask;
-            let dirty_init = dirty_raw & mask;
-            let ctrl_val = (ctrl_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-            let q_ctrl = bb.alloc_qubit();
-
-            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c, q_ctrl);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[221u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            if ctrl_val {
-                *sim.qubit_mut(q_ctrl) = 1;
-            }
-            sim.apply(&ops);
-
-            let expected = if ctrl_val {
-                target.wrapping_sub(c) & mask
-            } else {
-                target
-            };
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
-            let phase = sim.global_phase() & 1;
-
-            if got == expected && dirty_ok && phase == 0 {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "cisub FAIL n={} t={:#x} c={:#x} ctrl={} got={:#x} exp={:#x} d_ok={} phase={}",
-                        n, target, c, ctrl_val, got, expected, dirty_ok, phase
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_cisub_dirty_small() {
-        for n in 5..=10 {
-            let (ok, bad) = run_cisub_dirty(n, 10);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    #[test]
-    fn test_cisub_dirty_large() {
-        let n = 256;
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, 50u8, 17]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let trials = 50;
-        let c_low = 0x1_0000_03D1u64;
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 40];
-            xof.read(&mut buf);
-            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let dirty_init = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let ctrl_val = (buf[16] & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n - 2);
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-            let q_ctrl = bb.alloc_qubit();
-
-            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c_low, q_ctrl);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[19u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..64 {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            for (k, &q) in q_dirty.iter().enumerate().take(64) {
-                if (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            if ctrl_val {
-                *sim.qubit_mut(q_ctrl) = 1;
-            }
-            sim.apply(&ops);
-
-            let expected = if ctrl_val {
-                target.wrapping_sub(c_low)
-            } else {
-                target
-            };
-            let mut got: u64 = 0;
-            for k in 0..64 {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate().take(64) {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dirty_ok = got_dirty == dirty_init;
-            let phase = sim.global_phase() & 1;
-            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
-            if got == expected && dirty_ok && phase == 0 && ctrl_preserved {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "cisub n=256 FAIL t={:#x} d={:#x} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_ok={}",
-                        target, dirty_init, ctrl_val, got, expected, dirty_ok, phase, ctrl_preserved
-                    );
-                }
-            }
-        }
-        assert_eq!(bad, 0, "n=256 cisub: {ok}/{trials} passed");
-    }
-
-    #[test]
-    fn test_cisub_dirty_kaliski_pattern() {
-
-        let n = 256;
-        let c_low = 0x1_0000_03D1u64;
-        let trials = 50;
-        let mut hasher = Shake256::default();
-        hasher.update(&[99u8]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 16];
-            xof.read(&mut buf);
-            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let dirty_u_lsb = (buf[8] & 1) != 0;
-            let ctrl_val = (buf[9] & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n - 2);
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-            let q_ctrl = bb.alloc_qubit();
-
-            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c_low, q_ctrl);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[77u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..64 {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-
-            if dirty_u_lsb {
-                *sim.qubit_mut(q_dirty[0]) = 1;
-            }
-            if ctrl_val {
-                *sim.qubit_mut(q_ctrl) = 1;
-            }
-            sim.apply(&ops);
-
-            let expected = if ctrl_val {
-                target.wrapping_sub(c_low)
-            } else {
-                target
-            };
-            let mut got: u64 = 0;
-            for k in 0..64 {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-            let got_dirty0 = sim.qubit(q_dirty[0]) & 1 != 0;
-            let dirty_ok = got_dirty0 == dirty_u_lsb;
-            let phase = sim.global_phase() & 1;
-            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
-            if got == expected && dirty_ok && phase == 0 && ctrl_preserved {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "cisub kaliski FAIL t={:#x} d0={} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_ok={}",
-                        target, dirty_u_lsb, ctrl_val, got, expected, dirty_ok, phase, ctrl_preserved
-                    );
-                }
-            }
-        }
-        assert_eq!(bad, 0, "kaliski pattern cisub: {ok}/{trials} passed");
-    }
-
-    fn run_iadd_qoffset_dirty(n: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, trials as u8, 199]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        for _trial in 0..trials {
-            let mut buf = [0u8; 40];
-            xof.read(&mut buf);
-            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
-            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
-            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
-            let cin_raw = buf[24];
-            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-            let target = target_raw & mask;
-            let offset = offset_raw & mask;
-            let dirty_init = dirty_raw & mask;
-            let cin = (cin_raw & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_offset: Vec = bb.alloc_qubits(n);
-            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-
-            iadd_dirty_2clean_qoffset(&mut bb, &q_target, &q_dirty, &q_clean2, &q_offset, cin);
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[231u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-                if (offset >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_offset[k]) = 1;
-                }
-            }
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
-            let mut got: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1 << k;
-                }
-            }
-
-            let mut got_offset: u64 = 0;
-            for k in 0..n {
-                if sim.qubit(q_offset[k]) & 1 != 0 {
-                    got_offset |= 1 << k;
-                }
-            }
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
-            let offset_ok = got_offset == offset;
-            let phase = sim.global_phase() & 1;
-
-            if got == expected && dirty_ok && offset_ok && phase == 0 {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "iadd_qoffset FAIL n={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} d_ok={} o_ok={} phase={}",
-                        n, target, offset, dirty_init, cin, got, expected, dirty_ok, offset_ok, phase
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_iadd_qoffset_dirty_small() {
-        for n in 5..=10 {
-            let (ok, bad) = run_iadd_qoffset_dirty(n, 10);
-            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
-        }
-    }
-
-    fn run_iadd_qoffset_narrow(n: usize, m: usize, trials: usize) -> (usize, usize) {
-        let mut hasher = Shake256::default();
-        hasher.update(&[n as u8, m as u8, trials as u8, 211]);
-        use sha3::digest::XofReader;
-        let mut xof = ::finalize_xof(hasher);
-        let mut ok = 0;
-        let mut bad = 0;
-        let nmask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
-        let mmask = if m < 64 { (1u64 << m) - 1 } else { u64::MAX };
-        for _trial in 0..trials {
-            let mut buf = [0u8; 40];
-            xof.read(&mut buf);
-            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap()) & nmask;
-            let offset = u64::from_le_bytes(buf[8..16].try_into().unwrap()) & mmask;
-            let dirty_init = u64::from_le_bytes(buf[16..24].try_into().unwrap()) & nmask;
-            let cin = (buf[24] & 1) != 0;
-
-            let mut bb = B::new();
-            let q_target: Vec = bb.alloc_qubits(n);
-            let q_offset: Vec = bb.alloc_qubits(m);
-            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
-            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
-
-            iadd_dirty_2clean_qoffset_narrow(
-                &mut bb, &q_target, &q_dirty, &q_clean2, &q_offset, cin,
-            );
-
-            let ops = bb.ops.clone();
-            let num_qubits = bb.next_qubit as usize;
-            let num_bits = bb.next_bit as usize;
-            let mut inner_hasher = Shake256::default();
-            inner_hasher.update(&[233u8]);
-            let mut inner_xof =
-                ::finalize_xof(inner_hasher);
-            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
-            sim.clear_for_shot();
-            for k in 0..n {
-                if k < 64 && (target >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_target[k]) = 1;
-                }
-            }
-            for k in 0..m {
-                if k < 64 && (offset >> k) & 1 != 0 {
-                    *sim.qubit_mut(q_offset[k]) = 1;
-                }
-            }
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if k < 64 && (dirty_init >> k) & 1 != 0 {
-                    *sim.qubit_mut(q) = 1;
-                }
-            }
-            sim.apply(&ops);
-
-            let expected: u128 = (target as u128) + (offset as u128) + (cin as u128);
-            let readbits = n.min(127);
-            let expected = expected & ((1u128 << readbits) - 1);
-            let mut got: u128 = 0;
-            for k in 0..readbits {
-                if sim.qubit(q_target[k]) & 1 != 0 {
-                    got |= 1u128 << k;
-                }
-            }
-            let mut got_offset: u64 = 0;
-            for k in 0..m {
-                if sim.qubit(q_offset[k]) & 1 != 0 {
-                    got_offset |= 1 << k;
-                }
-            }
-            let mut got_dirty: u64 = 0;
-            for (k, &q) in q_dirty.iter().enumerate() {
-                if sim.qubit(q) & 1 != 0 {
-                    got_dirty |= 1 << k;
-                }
-            }
-            let dmask = if q_dirty.len() < 64 {
-                (1u64 << q_dirty.len()) - 1
-            } else {
-                u64::MAX
-            };
-            let dirty_ok = got_dirty == (dirty_init & dmask & nmask);
-            let offset_ok = got_offset == offset;
-            let phase = sim.global_phase() & 1;
-
-            if got == expected && dirty_ok && offset_ok && phase == 0 {
-                ok += 1;
-            } else {
-                bad += 1;
-                if bad < 3 {
-                    eprintln!(
-                        "narrow FAIL n={} m={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} d_ok={} o_ok={} phase={}",
-                        n, m, target, offset, dirty_init, cin, got, expected, dirty_ok, offset_ok, phase
-                    );
-                }
-            }
-        }
-        (ok, bad)
-    }
-
-    #[test]
-    fn test_iadd_qoffset_narrow_small() {
-
-        for n in 5..=12 {
-            for m in 1..n {
-                let (ok, bad) = run_iadd_qoffset_narrow(n, m, 12);
-                assert_eq!(bad, 0, "n={n} m={m}: {ok}/{} passed", ok + bad);
-            }
-        }
-    }
-
-    #[test]
-    fn test_iadd_qoffset_narrow_wide() {
-
-        let (ok, bad) = run_iadd_qoffset_narrow(256, 22, 40);
-        assert_eq!(bad, 0, "n=256 m=22: {ok}/{} passed", ok + bad);
-    }
-}
+
+use super::{BitId, QubitId, B};
+use crate::circuit::{Op, OperationType};
+
+#[allow(dead_code)]
+pub(crate) fn xor_right_shifted_carries_into_classical(
+    b: &mut B,
+    q_src: &[QubitId],
+    offset_bits: u64,
+    q_dst: &[QubitId],
+    carry_in: bool,
+) {
+    let n = q_dst.len();
+    assert!(n <= q_src.len() && q_src.len() <= n + 1, "len mismatch");
+    if n == 0 {
+        return;
+    }
+
+    let bit = |k: usize| -> bool {
+        if k >= 64 {
+            false
+        } else {
+            (offset_bits >> k) & 1 != 0
+        }
+    };
+
+    let ccx_inv =
+        |b: &mut B, ctrl_a: QubitId, inv_a: bool, ctrl_b: QubitId, inv_b: bool, target: QubitId| {
+            if inv_a {
+                b.x(ctrl_a);
+            }
+            if inv_b {
+                b.x(ctrl_b);
+            }
+            b.ccx(ctrl_a, ctrl_b, target);
+            if inv_b {
+                b.x(ctrl_b);
+            }
+            if inv_a {
+                b.x(ctrl_a);
+            }
+        };
+
+    for k in (1..n).rev() {
+        ccx_inv(b, q_src[k], bit(k), q_dst[k - 1], false, q_dst[k]);
+    }
+
+    for k in 0..n {
+        if bit(k) {
+            b.x(q_dst[k]);
+        }
+    }
+
+    let carry_in_xor_offset0 = carry_in ^ bit(0);
+    if carry_in_xor_offset0 {
+
+        if bit(0) {
+            b.x(q_src[0]);
+        }
+        b.cx(q_src[0], q_dst[0]);
+        if bit(0) {
+            b.x(q_src[0]);
+        }
+    }
+
+    for k in 1..n {
+        ccx_inv(b, q_src[k], bit(k), q_dst[k - 1], bit(k), q_dst[k]);
+    }
+}
+
+pub(crate) fn add_vented_2clean_classical(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    offset_bits: u64,
+    carry_in: bool,
+    vent_keys: &[BitId],
+) {
+    add_vented_2clean_classical_cxt(
+        b,
+        q_target,
+        q_clean2,
+        offset_bits,
+        carry_in,
+        vent_keys,
+        None,
+    );
+}
+
+pub(crate) fn add_vented_2clean_classical_cxt(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    offset_bits: u64,
+    carry_in: bool,
+    vent_keys: &[BitId],
+    carry_xor_target: Option<&[Option]>,
+) {
+    let n = q_target.len();
+    if n == 0 {
+        return;
+    }
+    let bit = |k: usize| -> bool {
+        if k >= 64 {
+            false
+        } else {
+            (offset_bits >> k) & 1 != 0
+        }
+    };
+
+    if n == 1 {
+        if carry_in {
+            b.x(q_target[0]);
+        }
+        if bit(0) {
+            b.x(q_target[0]);
+        }
+        return;
+    }
+
+    for k in 0..n {
+        if bit(k) {
+            b.x(q_target[k]);
+        }
+    }
+
+    let get_carry_qubit = |k: usize| -> Option {
+        if k == 0 {
+            None
+        } else if k == n - 1 {
+            Some(q_target[n - 1])
+        } else {
+            Some(q_clean2[k % 2])
+        }
+    };
+
+    for k in 0..n - 1 {
+
+        if k < n - 2 {
+            if let Some(q) = get_carry_qubit(k + 1) {
+
+                let mut op = Op::empty();
+                op.kind = OperationType::R;
+                op.q_target = q;
+                b.ops.push(op);
+            }
+        }
+
+        if k == 0 {
+            let eff_carry = carry_in ^ bit(0);
+            if eff_carry {
+
+                if let Some(q) = get_carry_qubit(1) {
+                    b.cx(q_target[0], q);
+                }
+            }
+        } else {
+            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
+            let carry_next = get_carry_qubit(k + 1).expect("non-boundary next carry");
+            if bit(k) {
+                b.x(carry_q);
+                b.ccx(q_target[k], carry_q, carry_next);
+                b.x(carry_q);
+            } else {
+                b.ccx(q_target[k], carry_q, carry_next);
+            }
+        }
+
+        if k == 0 {
+            if carry_in {
+                b.x(q_target[0]);
+            }
+        } else {
+            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
+            b.cx(carry_q, q_target[k]);
+        }
+
+        if let Some(cxt) = carry_xor_target {
+            if k < cxt.len() {
+                if let Some(dst) = cxt[k] {
+                    if k == 0 {
+                        if carry_in {
+                            b.x(dst);
+                        }
+                    } else {
+                        let carry_q = get_carry_qubit(k).expect("non-boundary carry");
+                        b.cx(carry_q, dst);
+                    }
+                }
+            }
+        }
+
+        if k > 0 {
+            let carry_q = get_carry_qubit(k).expect("non-boundary carry");
+            b.hmr(carry_q, vent_keys[k]);
+        }
+
+        if bit(k) {
+            if let Some(q) = get_carry_qubit(k + 1) {
+                b.x(q);
+            }
+        }
+    }
+}
+
+pub(crate) fn iadd_linear_clean_classical(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_clean: &[QubitId],
+    offset_bits: u64,
+    carry_in: bool,
+) {
+    let n = q_target.len();
+    if n == 0 {
+        return;
+    }
+    assert!(q_clean.len() >= n.saturating_sub(2), "need n-2 clean");
+    let q_clean = &q_clean[..n.saturating_sub(2)];
+
+    let bit = |k: usize| -> bool {
+        if k >= 64 {
+            false
+        } else {
+            (offset_bits >> k) & 1 != 0
+        }
+    };
+
+    if n == 1 {
+        if bit(0) {
+            b.x(q_target[0]);
+        }
+        if carry_in {
+            b.x(q_target[0]);
+        }
+        return;
+    }
+
+    if n == 2 {
+
+        if bit(0) {
+            b.x(q_target[1]);
+        }
+
+        for k in 0..2 {
+            if bit(k) {
+                b.x(q_target[k]);
+            }
+        }
+
+        let eff0 = carry_in ^ bit(0);
+        if eff0 {
+            b.cx(q_target[0], q_target[1]);
+        }
+
+        if carry_in {
+            b.x(q_target[0]);
+        }
+        return;
+    }
+
+    for &q in q_clean.iter() {
+        let mut op = Op::empty();
+        op.kind = OperationType::R;
+        op.q_target = q;
+        b.ops.push(op);
+    }
+
+    let get_carry = |k: usize| -> Option {
+        if k == 0 {
+            None
+        } else if k == n - 1 {
+            Some(q_target[n - 1])
+        } else {
+            Some(q_clean[k - 1])
+        }
+    };
+
+    for k in 0..n - 1 {
+        if bit(k) {
+            if let Some(q) = get_carry(k + 1) {
+                b.x(q);
+            }
+        }
+    }
+
+    for k in 0..n {
+        if bit(k) {
+            b.x(q_target[k]);
+        }
+    }
+
+    for k in 0..n - 1 {
+
+        let next = get_carry(k + 1).expect("k+1 in bounds");
+        if k == 0 {
+
+            let eff = carry_in ^ bit(0);
+            if eff {
+                b.cx(q_target[0], next);
+            }
+        } else {
+            let cur = get_carry(k).expect("k in bounds");
+            if bit(k) {
+                b.x(cur);
+                b.ccx(q_target[k], cur, next);
+                b.x(cur);
+            } else {
+                b.ccx(q_target[k], cur, next);
+            }
+        }
+    }
+
+    for k in (0..n - 2).rev() {
+
+        let next = get_carry(k + 1).expect("k+1 in bounds");
+        b.cx(next, q_target[k + 1]);
+
+        let m = b.alloc_bit();
+        b.hmr(next, m);
+
+        if bit(k) {
+            let mut op = Op::empty();
+            op.kind = OperationType::Neg;
+            op.c_condition = m;
+            b.ops.push(op);
+        }
+
+        if k == 0 {
+
+            let eff = carry_in ^ bit(0);
+            if eff {
+
+                let mut op = Op::empty();
+                op.kind = OperationType::Z;
+                op.q_target = q_target[k];
+                op.c_condition = m;
+                b.ops.push(op);
+            }
+        } else {
+            let cur = get_carry(k).expect("k in bounds");
+
+            if bit(k) {
+                b.x(cur);
+                b.cz_if(q_target[k], cur, m);
+                b.x(cur);
+            } else {
+                b.cz_if(q_target[k], cur, m);
+            }
+        }
+    }
+
+    if carry_in {
+        b.x(q_target[0]);
+    }
+}
+
+#[allow(dead_code)]
+pub(crate) fn iadd_dirty_2clean_classical(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_dirty: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    offset_bits: u64,
+    carry_in: bool,
+) {
+    let n = q_target.len();
+    if n == 0 {
+        return;
+    }
+
+    if n <= 4 {
+        iadd_linear_clean_classical(b, q_target, q_clean2, offset_bits, carry_in);
+        return;
+    }
+    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
+    let q_dirty = &q_dirty[..n - 2];
+
+    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
+
+    let cxt: Vec> = (0..n)
+        .map(|k| {
+            if k == 0 {
+                None
+            } else {
+                q_dirty.get(k - 1).copied()
+            }
+        })
+        .collect();
+
+    add_vented_2clean_classical_cxt(
+        b,
+        q_target,
+        q_clean2,
+        offset_bits,
+        carry_in,
+        &vent_keys,
+        Some(&cxt),
+    );
+
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+
+    for k in 0..n - 2 {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+
+    xor_right_shifted_carries_into_classical(b, &q_target[..n - 1], offset_bits, q_dirty, carry_in);
+    for k in 0..n - 2 {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+}
+
+pub(crate) fn ciadd_dirty_2clean_classical(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_dirty: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    offset_bits: u64,
+    ctrl: QubitId,
+    carry_in: bool,
+) {
+
+    assert!(
+        !carry_in,
+        "ciadd_dirty_2clean_classical requires carry_in=false; pre-process if needed"
+    );
+    let n = q_target.len();
+    if n == 0 {
+        return;
+    }
+    if n <= 4 {
+
+        let a: Vec = (0..n).map(|_| b.alloc_qubit()).collect();
+        for i in 0..n {
+            if (offset_bits >> i) & 1 != 0 {
+                b.cx(ctrl, a[i]);
+            }
+        }
+
+        for i in 0..n {
+            if (offset_bits >> i) & 1 != 0 {
+                b.cx(ctrl, a[i]);
+            }
+        }
+        for q in a {
+            b.free(q);
+        }
+        panic!("ciadd_dirty_2clean: n<=4 fallback not implemented; use uncontrolled path");
+    }
+    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
+    let q_dirty = &q_dirty[..n - 2];
+
+    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
+
+    let cxt: Vec> = (0..n)
+        .map(|k| {
+            if k == 0 {
+                None
+            } else {
+                q_dirty.get(k - 1).copied()
+            }
+        })
+        .collect();
+
+    c_add_vented_2clean_inline(
+        b,
+        q_target,
+        q_clean2,
+        offset_bits,
+        ctrl,
+        carry_in,
+        &vent_keys,
+        &cxt,
+    );
+
+    for k in 0..n {
+
+        b.cx(ctrl, q_target[k]);
+    }
+    for k in 0..n - 2 {
+
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+
+    c_xor_right_shifted_carries_into_classical(
+        b,
+        &q_target[..n - 1],
+        offset_bits,
+        ctrl,
+        q_dirty,
+        carry_in,
+    );
+    for k in 0..n - 2 {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+    for k in 0..n {
+        b.cx(ctrl, q_target[k]);
+    }
+}
+
+fn c_add_vented_2clean_inline(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    offset_bits: u64,
+    ctrl: QubitId,
+    carry_in: bool,
+    vent_keys: &[BitId],
+    carry_xor_target: &[Option],
+) {
+    let n = q_target.len();
+    if n < 2 {
+
+        if n == 1 {
+            if carry_in {
+                b.cx(ctrl, q_target[0]);
+            }
+            if (offset_bits & 1) != 0 {
+                b.cx(ctrl, q_target[0]);
+            }
+        }
+        return;
+    }
+
+    let bit = |k: usize| -> bool {
+        if k >= 64 {
+            false
+        } else {
+            (offset_bits >> k) & 1 != 0
+        }
+    };
+
+    for k in 0..n {
+        if bit(k) {
+            b.cx(ctrl, q_target[k]);
+        }
+    }
+
+    let get_carry_qubit = |k: usize| -> Option {
+        if k == 0 {
+            None
+        } else if k == n - 1 {
+            Some(q_target[n - 1])
+        } else {
+            Some(q_clean2[k % 2])
+        }
+    };
+
+    for k in 0..n - 1 {
+
+        if k < n - 2 {
+            if let Some(q) = get_carry_qubit(k + 1) {
+                let mut op = Op::empty();
+                op.kind = OperationType::R;
+                op.q_target = q;
+                b.ops.push(op);
+            }
+        }
+
+        if k == 0 {
+            let next = get_carry_qubit(1);
+            if let Some(next_q) = next {
+                if bit(0) {
+
+                    if carry_in {
+
+                        b.x(ctrl);
+                        b.ccx(q_target[0], ctrl, next_q);
+                        b.x(ctrl);
+                    } else {
+                        b.ccx(q_target[0], ctrl, next_q);
+                    }
+                } else if carry_in {
+
+                    b.cx(q_target[0], next_q);
+                }
+
+            }
+        } else {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            let next = get_carry_qubit(k + 1).expect("non-boundary next carry");
+            if bit(k) {
+
+                b.cx(ctrl, cur);
+                b.ccx(q_target[k], cur, next);
+                b.cx(ctrl, cur);
+            } else {
+                b.ccx(q_target[k], cur, next);
+            }
+        }
+
+        if k == 0 {
+            if carry_in {
+                b.x(q_target[0]);
+            }
+        } else {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            b.cx(cur, q_target[k]);
+        }
+
+        if k < carry_xor_target.len() {
+            if let Some(dst) = carry_xor_target[k] {
+                if k == 0 {
+                    if carry_in {
+                        b.x(dst);
+                    }
+                } else {
+                    let cur = get_carry_qubit(k).expect("non-boundary carry");
+                    b.cx(cur, dst);
+                }
+            }
+        }
+
+        if k > 0 {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            b.hmr(cur, vent_keys[k]);
+        }
+
+        if bit(k) {
+            if let Some(q) = get_carry_qubit(k + 1) {
+                b.cx(ctrl, q);
+            }
+        }
+    }
+}
+
+pub(crate) fn add_vented_2clean_qoffset(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    q_offset: &[QubitId],
+    carry_in: bool,
+    vent_keys: &[BitId],
+    carry_xor_target: Option<&[Option]>,
+) {
+    let n = q_target.len();
+    assert_eq!(q_offset.len(), n, "q_offset length must match q_target");
+    if n == 0 {
+        return;
+    }
+    if n == 1 {
+        if carry_in {
+            b.x(q_target[0]);
+        }
+        b.cx(q_offset[0], q_target[0]);
+        return;
+    }
+
+    for k in 0..n {
+        b.cx(q_offset[k], q_target[k]);
+    }
+
+    let get_carry_qubit = |k: usize| -> Option {
+        if k == 0 {
+            None
+        } else if k == n - 1 {
+            Some(q_target[n - 1])
+        } else {
+            Some(q_clean2[k % 2])
+        }
+    };
+
+    for k in 0..n - 1 {
+        if k < n - 2 {
+            if let Some(q) = get_carry_qubit(k + 1) {
+                let mut op = Op::empty();
+                op.kind = OperationType::R;
+                op.q_target = q;
+                b.ops.push(op);
+            }
+        }
+
+        if k == 0 {
+            let next = get_carry_qubit(1);
+            if let Some(next_q) = next {
+                if carry_in {
+                    b.x(q_offset[0]);
+                    b.ccx(q_target[0], q_offset[0], next_q);
+                    b.x(q_offset[0]);
+                } else {
+                    b.ccx(q_target[0], q_offset[0], next_q);
+                }
+            }
+        } else {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            let next = get_carry_qubit(k + 1).expect("non-boundary next carry");
+
+            b.cx(q_offset[k], cur);
+            b.ccx(q_target[k], cur, next);
+            b.cx(q_offset[k], cur);
+        }
+
+        if k == 0 {
+            if carry_in {
+                b.x(q_target[0]);
+            }
+        } else {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            b.cx(cur, q_target[k]);
+        }
+
+        if let Some(cxt) = carry_xor_target {
+            if k < cxt.len() {
+                if let Some(dst) = cxt[k] {
+                    if k == 0 {
+                        if carry_in {
+                            b.x(dst);
+                        }
+                    } else {
+                        let cur = get_carry_qubit(k).expect("non-boundary carry");
+                        b.cx(cur, dst);
+                    }
+                }
+            }
+        }
+
+        if k > 0 {
+            let cur = get_carry_qubit(k).expect("non-boundary carry");
+            b.hmr(cur, vent_keys[k]);
+        }
+
+        if let Some(q) = get_carry_qubit(k + 1) {
+            b.cx(q_offset[k], q);
+        }
+    }
+}
+
+pub(crate) fn xor_right_shifted_carries_into_qoffset(
+    b: &mut B,
+    q_src: &[QubitId],
+    q_offset: &[QubitId],
+    q_dst: &[QubitId],
+    carry_in: bool,
+) {
+    let n = q_dst.len();
+    assert!(n <= q_src.len() && q_src.len() <= n + 1, "len mismatch");
+    if n == 0 {
+        return;
+    }
+
+    let ccx_with_qxor = |b: &mut B,
+                         ctrl_a: QubitId,
+                         xor_a: Option,
+                         ctrl_b: QubitId,
+                         xor_b: Option,
+                         target: QubitId| {
+        if let Some(x) = xor_a {
+            b.cx(x, ctrl_a);
+        }
+        if let Some(x) = xor_b {
+            b.cx(x, ctrl_b);
+        }
+        b.ccx(ctrl_a, ctrl_b, target);
+        if let Some(x) = xor_b {
+            b.cx(x, ctrl_b);
+        }
+        if let Some(x) = xor_a {
+            b.cx(x, ctrl_a);
+        }
+    };
+
+    for k in (1..n).rev() {
+        ccx_with_qxor(b, q_src[k], Some(q_offset[k]), q_dst[k - 1], None, q_dst[k]);
+    }
+
+    for k in 0..n {
+        b.cx(q_offset[k], q_dst[k]);
+    }
+
+    b.cx(q_offset[0], q_src[0]);
+    if carry_in {
+        b.x(q_offset[0]);
+    }
+    b.ccx(q_src[0], q_offset[0], q_dst[0]);
+    if carry_in {
+        b.x(q_offset[0]);
+    }
+    b.cx(q_offset[0], q_src[0]);
+
+    for k in 1..n {
+        ccx_with_qxor(
+            b,
+            q_src[k],
+            Some(q_offset[k]),
+            q_dst[k - 1],
+            Some(q_offset[k]),
+            q_dst[k],
+        );
+    }
+}
+
+pub(crate) fn iadd_dirty_2clean_qoffset(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_dirty: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    q_offset: &[QubitId],
+    carry_in: bool,
+) {
+    let n = q_target.len();
+    assert_eq!(q_offset.len(), n);
+    if n == 0 {
+        return;
+    }
+    if n <= 4 {
+        panic!("iadd_dirty_2clean_qoffset: n<=4 not supported yet, use cuccaro_add");
+    }
+    assert!(q_dirty.len() >= n - 2, "need n-2 dirty qubits");
+    let q_dirty = &q_dirty[..n - 2];
+
+    let vent_keys: Vec = (0..n).map(|_| b.alloc_bit()).collect();
+    let cxt: Vec> = (0..n)
+        .map(|k| {
+            if k == 0 {
+                None
+            } else {
+                q_dirty.get(k - 1).copied()
+            }
+        })
+        .collect();
+
+    add_vented_2clean_qoffset(
+        b,
+        q_target,
+        q_clean2,
+        q_offset,
+        carry_in,
+        &vent_keys,
+        Some(&cxt),
+    );
+
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+    for k in 0..n - 2 {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+    xor_right_shifted_carries_into_qoffset(b, &q_target[..n - 1], q_offset, q_dirty, carry_in);
+    for k in 0..n - 2 {
+        let mut op = Op::empty();
+        op.kind = OperationType::Z;
+        op.q_target = q_dirty[k];
+        op.c_condition = vent_keys[k + 1];
+        b.ops.push(op);
+    }
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+}
+
+pub(crate) fn isub_dirty_2clean_qoffset(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_dirty: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    q_offset: &[QubitId],
+) {
+    let n = q_target.len();
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+    iadd_dirty_2clean_qoffset(b, q_target, q_dirty, q_clean2, q_offset, false);
+    for k in 0..n {
+        b.x(q_target[k]);
+    }
+}
+
+fn c_xor_right_shifted_carries_into_classical(
+    b: &mut B,
+    q_src: &[QubitId],
+    offset_bits: u64,
+    ctrl: QubitId,
+    q_dst: &[QubitId],
+    carry_in: bool,
+) {
+    let n = q_dst.len();
+    assert!(n <= q_src.len() && q_src.len() <= n + 1);
+    if n == 0 {
+        return;
+    }
+    let bit = |k: usize| -> bool {
+        if k >= 64 {
+            false
+        } else {
+            (offset_bits >> k) & 1 != 0
+        }
+    };
+
+    let ccx_ctrl_mix = |b: &mut B,
+                        ctrl_a: QubitId,
+                        a_xor_ctrl: bool,
+                        ctrl_b: QubitId,
+                        b_xor_ctrl: bool,
+                        target: QubitId| {
+        if a_xor_ctrl {
+            b.cx(ctrl, ctrl_a);
+        }
+        if b_xor_ctrl {
+            b.cx(ctrl, ctrl_b);
+        }
+        b.ccx(ctrl_a, ctrl_b, target);
+        if b_xor_ctrl {
+            b.cx(ctrl, ctrl_b);
+        }
+        if a_xor_ctrl {
+            b.cx(ctrl, ctrl_a);
+        }
+    };
+
+    for k in (1..n).rev() {
+        ccx_ctrl_mix(b, q_src[k], bit(k), q_dst[k - 1], false, q_dst[k]);
+    }
+
+    for k in 0..n {
+        if bit(k) {
+            b.cx(ctrl, q_dst[k]);
+        }
+    }
+
+    let cin_eff_uses_ctrl = bit(0);
+    let cin_classical_part = carry_in ^ false;
+    if cin_eff_uses_ctrl {
+
+        if carry_in {
+
+            b.cx(ctrl, q_src[0]);
+            b.x(ctrl);
+            b.ccx(q_src[0], ctrl, q_dst[0]);
+            b.x(ctrl);
+            b.cx(ctrl, q_src[0]);
+        } else {
+
+            b.cx(ctrl, q_src[0]);
+            b.ccx(q_src[0], ctrl, q_dst[0]);
+            b.cx(ctrl, q_src[0]);
+        }
+    } else {
+
+        if cin_classical_part {
+
+            b.cx(q_src[0], q_dst[0]);
+        }
+
+    }
+    for k in 1..n {
+        ccx_ctrl_mix(b, q_src[k], bit(k), q_dst[k - 1], bit(k), q_dst[k]);
+    }
+}
+
+pub(crate) fn cisub_dirty_2clean_classical(
+    b: &mut B,
+    q_target: &[QubitId],
+    q_dirty: &[QubitId],
+    q_clean2: &[QubitId; 2],
+    c_bits: u64,
+    ctrl: QubitId,
+) {
+    let n = q_target.len();
+
+    for k in 0..n {
+        b.cx(ctrl, q_target[k]);
+    }
+    ciadd_dirty_2clean_classical(
+        b, q_target, q_dirty, q_clean2, c_bits, ctrl,
+        false,
+    );
+    for k in 0..n {
+        b.cx(ctrl, q_target[k]);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::sim::Simulator;
+    use sha3::{
+        digest::{ExtendableOutput, Update},
+        Shake256,
+    };
+
+    fn anf_degree_density_from_truth_table(mut table: Vec, vars: usize) -> (usize, usize) {
+        let states = 1usize << vars;
+
+        for bit in 0..vars {
+            let step = 1usize << bit;
+            for mask in 0..states {
+                if (mask & step) != 0 {
+                    table[mask] ^= table[mask ^ step];
+                }
+            }
+        }
+
+        let mut degree = 0usize;
+        let mut density = 0usize;
+        for (mask, &coeff) in table.iter().enumerate() {
+            if coeff != 0 {
+                density += 1;
+                degree = degree.max(mask.count_ones() as usize);
+            }
+        }
+        (degree, density)
+    }
+
+    fn product_phase_anf_degree_density(n: usize, phase_mask: u64) -> (usize, usize) {
+        assert!(n > 0 && n <= 10, "test keeps exhaustive table small");
+        let vars = 2 * n;
+        let states = 1usize << vars;
+        let x_mask = (1u64 << n) - 1;
+        let mut table = vec![0u8; states];
+        for state in 0..states {
+            let x = (state as u64) & x_mask;
+            let y = ((state as u64) >> n) & x_mask;
+            let prod = x * y;
+            table[state] = ((prod & phase_mask).count_ones() & 1) as u8;
+        }
+        anf_degree_density_from_truth_table(table, vars)
+    }
+
+    fn carry_save_product_bits_for_phase_test(n: usize, x: u64, y: u64) -> Vec {
+
+        let mut cols = vec![Vec::::new(); 2 * n + 8];
+        for i in 0..n {
+            for j in 0..n {
+                let bit = (((x >> i) & 1) & ((y >> j) & 1)) as u8;
+                cols[i + j].push(bit);
+            }
+        }
+        for k in 0..cols.len() - 1 {
+            while cols[k].len() > 2 {
+                let a = cols[k].pop().unwrap();
+                let b = cols[k].pop().unwrap();
+                let c = cols[k].pop().unwrap();
+                let sum = a ^ b ^ c;
+                let carry = (a & b) ^ (a & c) ^ (b & c);
+                cols[k].push(sum);
+                cols[k + 1].push(carry);
+            }
+        }
+        let mut out = Vec::with_capacity(4 * n + 4);
+        for col in cols.iter().take(2 * n + 2) {
+            out.push(*col.get(0).unwrap_or(&0));
+            out.push(*col.get(1).unwrap_or(&0));
+        }
+        out
+    }
+
+    fn carry_save_product_phase_anf_degree_density(
+        n: usize,
+        top_column_only: bool,
+    ) -> (usize, usize) {
+        assert!(
+            n > 0 && n <= 8,
+            "test keeps exhaustive carry-save table small"
+        );
+        let vars = 2 * n;
+        let states = 1usize << vars;
+        let x_mask = (1u64 << n) - 1;
+        let mut table = vec![0u8; states];
+        for state in 0..states {
+            let x = (state as u64) & x_mask;
+            let y = ((state as u64) >> n) & x_mask;
+            let bits = carry_save_product_bits_for_phase_test(n, x, y);
+            table[state] = if top_column_only {
+                let k = 2 * (2 * n - 2);
+                bits[k] ^ bits[k + 1]
+            } else {
+                bits.iter().fold(0u8, |acc, &b| acc ^ b)
+            };
+        }
+        anf_degree_density_from_truth_table(table, vars)
+    }
+
+    #[test]
+    fn raw_product_measurement_phase_is_dense_not_free_kickmix() {
+
+        for &n in &[4usize, 6, 8, 10] {
+            let full_mask = if 2 * n == 64 {
+                u64::MAX
+            } else {
+                (1u64 << (2 * n)) - 1
+            };
+            let high_mask = 1u64 << (2 * n - 2);
+            let (deg_full, dens_full) = product_phase_anf_degree_density(n, full_mask);
+            let (deg_high, dens_high) = product_phase_anf_degree_density(n, high_mask);
+            eprintln!(
+                "raw_product_phase n={n} full_deg={deg_full} full_density={dens_full} high_deg={deg_high} high_density={dens_high}"
+            );
+            if n == 10 {
+                println!("METRIC raw_product_mbu_fullmask_degree_n10={deg_full}");
+                println!("METRIC raw_product_mbu_fullmask_density_n10={dens_full}");
+                println!("METRIC raw_product_mbu_highbit_degree_n10={deg_high}");
+                println!("METRIC raw_product_mbu_highbit_density_n10={dens_high}");
+            }
+        }
+
+        let (deg_full, dens_full) = product_phase_anf_degree_density(10, (1u64 << 20) - 1);
+        let (deg_high, dens_high) = product_phase_anf_degree_density(10, 1u64 << 18);
+        assert_eq!(deg_full, 19);
+        assert_eq!(dens_full, 427_812);
+        assert_eq!(deg_high, 19);
+        assert_eq!(dens_high, 120_581);
+    }
+
+    #[test]
+    fn carry_save_product_scratch_mbu_still_has_dense_phases() {
+
+        for &n in &[4usize, 6, 8] {
+            let (deg_all, dens_all) = carry_save_product_phase_anf_degree_density(n, false);
+            let (deg_top, dens_top) = carry_save_product_phase_anf_degree_density(n, true);
+            eprintln!(
+                "carry_save_product_phase n={n} all_deg={deg_all} all_density={dens_all} top_deg={deg_top} top_density={dens_top}"
+            );
+            if n == 8 {
+                println!("METRIC carry_save_product_mbu_all_degree_n8={deg_all}");
+                println!("METRIC carry_save_product_mbu_all_density_n8={dens_all}");
+                println!("METRIC carry_save_product_mbu_top_degree_n8={deg_top}");
+                println!("METRIC carry_save_product_mbu_top_density_n8={dens_top}");
+            }
+        }
+        let (deg_all, dens_all) = carry_save_product_phase_anf_degree_density(8, false);
+        let (deg_top, dens_top) = carry_save_product_phase_anf_degree_density(8, true);
+        assert_eq!(deg_all, 16);
+        assert_eq!(dens_all, 20_440);
+        assert_eq!(deg_top, 15);
+        assert_eq!(dens_top, 3_602);
+    }
+
+    fn classical_carry(x: u64, d: u64, cin: bool, n: usize) -> u64 {
+
+        let mut c: u64 = 0;
+        let mut prev = cin;
+        for k in 0..n {
+            let xk = (x >> k) & 1 != 0;
+            let dk = (d >> k) & 1 != 0;
+
+            let new_carry = (prev && xk) || (prev && dk) || (xk && dk);
+            if new_carry {
+                c |= 1 << (k + 1);
+            }
+            prev = new_carry;
+        }
+
+        if cin {
+            c |= 1;
+        }
+        c
+    }
+
+    fn run_xor_rsh_carries(n: usize, trials: usize) -> bool {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 42]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        for _trial in 0..trials {
+            let mut buf = [0u8; 32];
+            xof.read(&mut buf);
+            let src_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let dst_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
+            let cin_raw = buf[24];
+            let src = if n < 64 {
+                src_raw & ((1u64 << n) - 1)
+            } else {
+                src_raw
+            };
+            let dst = if n < 64 {
+                dst_raw & ((1u64 << n) - 1)
+            } else {
+                dst_raw
+            };
+            let offset = if n < 64 {
+                offset_raw & ((1u64 << n) - 1)
+            } else {
+                offset_raw
+            };
+            let cin = (cin_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_src: Vec = bb.alloc_qubits(n);
+            let q_dst: Vec = bb.alloc_qubits(n);
+
+            xor_right_shifted_carries_into_classical(&mut bb, &q_src, offset, &q_dst, cin);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = 0usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[77u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+
+            for k in 0..n {
+                if (src >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_src[k]) = 1;
+                }
+                if (dst >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_dst[k]) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected_carries = classical_carry(src, offset, cin, n + 1);
+            let expected_rsh = expected_carries >> 1;
+            let expected_dst = (dst ^ expected_rsh) & ((1u64 << n) - 1);
+
+            let mut got_dst: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_dst[k]) & 1 != 0 {
+                    got_dst |= 1 << k;
+                }
+            }
+            if got_dst != expected_dst {
+                eprintln!(
+                    "n={} src={:#x} dst={:#x} offset={:#x} cin={} got={:#x} exp={:#x}",
+                    n, src, dst, offset, cin, got_dst, expected_dst
+                );
+                return false;
+            }
+        }
+        true
+    }
+
+    #[test]
+    fn test_xor_rsh_carries_small() {
+        for n in 1..=8 {
+            assert!(run_xor_rsh_carries(n, 20), "failed at n={n}");
+        }
+    }
+
+    fn run_vented_add_2clean(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 51]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 24];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let cin_raw = buf[16];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let offset = offset_raw & mask;
+            let cin = (cin_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+            let vent_keys: Vec = (0..n).map(|_| bb.alloc_bit()).collect();
+
+            add_vented_2clean_classical(&mut bb, &q_target, &q_clean2, offset, cin, &vent_keys);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[101u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            if got == expected_sum {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "vented add FAIL n={} t={:#x} o={:#x} cin={} got={:#x} exp={:#x}",
+                        n, target, offset, cin, got, expected_sum
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_vented_add_2clean_small() {
+        for n in 2..=8 {
+            let (ok, bad) = run_vented_add_2clean(n, 20);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    fn run_linear_clean_add(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 73]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 24];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let cin_raw = buf[16];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let offset = offset_raw & mask;
+            let cin = (cin_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let n_clean = n.saturating_sub(2).max(2);
+            let q_clean: Vec = bb.alloc_qubits(n_clean);
+
+            iadd_linear_clean_classical(&mut bb, &q_target, &q_clean, offset, cin);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[151u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            if got == expected_sum {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "HRS FAIL n={} t={:#x} o={:#x} cin={} got={:#x} exp={:#x}",
+                        n, target, offset, cin, got, expected_sum
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_iadd_linear_clean_small() {
+        for n in 1..=8 {
+            let (ok, bad) = run_linear_clean_add(n, 20);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    fn run_iadd_dirty_2clean(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 97]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 32];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
+            let cin_raw = buf[24];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let offset = offset_raw & mask;
+            let dirty_init = dirty_raw & mask;
+            let cin = (cin_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+
+            iadd_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, offset, cin);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[201u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected_sum = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dirty_ok = if n > 4 {
+                got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask))
+            } else {
+                true
+            };
+
+            let phase = sim.global_phase() & 1;
+
+            if got == expected_sum && dirty_ok && phase == 0 {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "iadd_dirty_2clean FAIL n={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} dirty_ok={} phase={}",
+                        n, target, offset, dirty_init, cin, got, expected_sum, dirty_ok, phase
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_iadd_dirty_2clean_small() {
+        for n in 2..=8 {
+            let (ok, bad) = run_iadd_dirty_2clean(n, 10);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    fn run_ciadd_dirty_2clean(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 113]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 40];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
+            let cin_raw = buf[24];
+            let ctrl_raw = buf[25];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let offset = offset_raw & mask;
+            let dirty_init = dirty_raw & mask;
+            let cin = false;
+            let _ = cin_raw;
+            let ctrl_val = (ctrl_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+            let q_ctrl = bb.alloc_qubit();
+
+            ciadd_dirty_2clean_classical(
+                &mut bb, &q_target, &q_dirty, &q_clean2, offset, q_ctrl, cin,
+            );
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[211u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            if ctrl_val {
+                *sim.qubit_mut(q_ctrl) = 1;
+            }
+            sim.apply(&ops);
+
+            let expected_sum = if ctrl_val {
+                (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask
+            } else {
+                target
+            };
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
+            let phase = sim.global_phase() & 1;
+            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
+
+            if got == expected_sum && dirty_ok && phase == 0 && ctrl_preserved {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "ciadd_dirty FAIL n={} t={:#x} o={:#x} d={:#x} cin={} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_preserved={}",
+                        n, target, offset, dirty_init, cin, ctrl_val, got, expected_sum, dirty_ok, phase, ctrl_preserved
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_ciadd_dirty_2clean_small() {
+        for n in 5..=10 {
+            let (ok, bad) = run_ciadd_dirty_2clean(n, 10);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    fn run_cisub_dirty(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 179]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 40];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let c_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
+            let ctrl_raw = buf[25];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let c = c_raw & mask;
+            let dirty_init = dirty_raw & mask;
+            let ctrl_val = (ctrl_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+            let q_ctrl = bb.alloc_qubit();
+
+            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c, q_ctrl);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[221u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            if ctrl_val {
+                *sim.qubit_mut(q_ctrl) = 1;
+            }
+            sim.apply(&ops);
+
+            let expected = if ctrl_val {
+                target.wrapping_sub(c) & mask
+            } else {
+                target
+            };
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
+            let phase = sim.global_phase() & 1;
+
+            if got == expected && dirty_ok && phase == 0 {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "cisub FAIL n={} t={:#x} c={:#x} ctrl={} got={:#x} exp={:#x} d_ok={} phase={}",
+                        n, target, c, ctrl_val, got, expected, dirty_ok, phase
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_cisub_dirty_small() {
+        for n in 5..=10 {
+            let (ok, bad) = run_cisub_dirty(n, 10);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    #[test]
+    fn test_cisub_dirty_large() {
+        let n = 256;
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, 50u8, 17]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let trials = 50;
+        let c_low = 0x1_0000_03D1u64;
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 40];
+            xof.read(&mut buf);
+            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let dirty_init = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let ctrl_val = (buf[16] & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n - 2);
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+            let q_ctrl = bb.alloc_qubit();
+
+            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c_low, q_ctrl);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[19u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..64 {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            for (k, &q) in q_dirty.iter().enumerate().take(64) {
+                if (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            if ctrl_val {
+                *sim.qubit_mut(q_ctrl) = 1;
+            }
+            sim.apply(&ops);
+
+            let expected = if ctrl_val {
+                target.wrapping_sub(c_low)
+            } else {
+                target
+            };
+            let mut got: u64 = 0;
+            for k in 0..64 {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate().take(64) {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dirty_ok = got_dirty == dirty_init;
+            let phase = sim.global_phase() & 1;
+            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
+            if got == expected && dirty_ok && phase == 0 && ctrl_preserved {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "cisub n=256 FAIL t={:#x} d={:#x} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_ok={}",
+                        target, dirty_init, ctrl_val, got, expected, dirty_ok, phase, ctrl_preserved
+                    );
+                }
+            }
+        }
+        assert_eq!(bad, 0, "n=256 cisub: {ok}/{trials} passed");
+    }
+
+    #[test]
+    fn test_cisub_dirty_kaliski_pattern() {
+
+        let n = 256;
+        let c_low = 0x1_0000_03D1u64;
+        let trials = 50;
+        let mut hasher = Shake256::default();
+        hasher.update(&[99u8]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 16];
+            xof.read(&mut buf);
+            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let dirty_u_lsb = (buf[8] & 1) != 0;
+            let ctrl_val = (buf[9] & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n - 2);
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+            let q_ctrl = bb.alloc_qubit();
+
+            cisub_dirty_2clean_classical(&mut bb, &q_target, &q_dirty, &q_clean2, c_low, q_ctrl);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[77u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..64 {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+
+            if dirty_u_lsb {
+                *sim.qubit_mut(q_dirty[0]) = 1;
+            }
+            if ctrl_val {
+                *sim.qubit_mut(q_ctrl) = 1;
+            }
+            sim.apply(&ops);
+
+            let expected = if ctrl_val {
+                target.wrapping_sub(c_low)
+            } else {
+                target
+            };
+            let mut got: u64 = 0;
+            for k in 0..64 {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+            let got_dirty0 = sim.qubit(q_dirty[0]) & 1 != 0;
+            let dirty_ok = got_dirty0 == dirty_u_lsb;
+            let phase = sim.global_phase() & 1;
+            let ctrl_preserved = sim.qubit(q_ctrl) & 1 == (ctrl_val as u64);
+            if got == expected && dirty_ok && phase == 0 && ctrl_preserved {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "cisub kaliski FAIL t={:#x} d0={} ctrl={} got={:#x} exp={:#x} d_ok={} phase={} ctrl_ok={}",
+                        target, dirty_u_lsb, ctrl_val, got, expected, dirty_ok, phase, ctrl_preserved
+                    );
+                }
+            }
+        }
+        assert_eq!(bad, 0, "kaliski pattern cisub: {ok}/{trials} passed");
+    }
+
+    fn run_iadd_qoffset_dirty(n: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, trials as u8, 199]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        for _trial in 0..trials {
+            let mut buf = [0u8; 40];
+            xof.read(&mut buf);
+            let target_raw = u64::from_le_bytes(buf[0..8].try_into().unwrap());
+            let offset_raw = u64::from_le_bytes(buf[8..16].try_into().unwrap());
+            let dirty_raw = u64::from_le_bytes(buf[16..24].try_into().unwrap());
+            let cin_raw = buf[24];
+            let mask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+            let target = target_raw & mask;
+            let offset = offset_raw & mask;
+            let dirty_init = dirty_raw & mask;
+            let cin = (cin_raw & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_offset: Vec = bb.alloc_qubits(n);
+            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+
+            iadd_dirty_2clean_qoffset(&mut bb, &q_target, &q_dirty, &q_clean2, &q_offset, cin);
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[231u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+                if (offset >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_offset[k]) = 1;
+                }
+            }
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected = (target.wrapping_add(offset).wrapping_add(cin as u64)) & mask;
+            let mut got: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1 << k;
+                }
+            }
+
+            let mut got_offset: u64 = 0;
+            for k in 0..n {
+                if sim.qubit(q_offset[k]) & 1 != 0 {
+                    got_offset |= 1 << k;
+                }
+            }
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dirty_ok = got_dirty == (dirty_init & ((1u64 << q_dirty.len()) - 1).min(mask));
+            let offset_ok = got_offset == offset;
+            let phase = sim.global_phase() & 1;
+
+            if got == expected && dirty_ok && offset_ok && phase == 0 {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "iadd_qoffset FAIL n={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} d_ok={} o_ok={} phase={}",
+                        n, target, offset, dirty_init, cin, got, expected, dirty_ok, offset_ok, phase
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_iadd_qoffset_dirty_small() {
+        for n in 5..=10 {
+            let (ok, bad) = run_iadd_qoffset_dirty(n, 10);
+            assert_eq!(bad, 0, "n={n}: {ok}/{} passed", ok + bad);
+        }
+    }
+
+    fn run_iadd_qoffset_narrow(n: usize, m: usize, trials: usize) -> (usize, usize) {
+        let mut hasher = Shake256::default();
+        hasher.update(&[n as u8, m as u8, trials as u8, 211]);
+        use sha3::digest::XofReader;
+        let mut xof = ::finalize_xof(hasher);
+        let mut ok = 0;
+        let mut bad = 0;
+        let nmask = if n < 64 { (1u64 << n) - 1 } else { u64::MAX };
+        let mmask = if m < 64 { (1u64 << m) - 1 } else { u64::MAX };
+        for _trial in 0..trials {
+            let mut buf = [0u8; 40];
+            xof.read(&mut buf);
+            let target = u64::from_le_bytes(buf[0..8].try_into().unwrap()) & nmask;
+            let offset = u64::from_le_bytes(buf[8..16].try_into().unwrap()) & mmask;
+            let dirty_init = u64::from_le_bytes(buf[16..24].try_into().unwrap()) & nmask;
+            let cin = (buf[24] & 1) != 0;
+
+            let mut bb = B::new();
+            let q_target: Vec = bb.alloc_qubits(n);
+            let q_offset: Vec = bb.alloc_qubits(m);
+            let q_dirty: Vec = bb.alloc_qubits(n.saturating_sub(2).max(1));
+            let q_clean2: [QubitId; 2] = [bb.alloc_qubit(), bb.alloc_qubit()];
+
+            iadd_dirty_2clean_qoffset_narrow(
+                &mut bb, &q_target, &q_dirty, &q_clean2, &q_offset, cin,
+            );
+
+            let ops = bb.ops.clone();
+            let num_qubits = bb.next_qubit as usize;
+            let num_bits = bb.next_bit as usize;
+            let mut inner_hasher = Shake256::default();
+            inner_hasher.update(&[233u8]);
+            let mut inner_xof =
+                ::finalize_xof(inner_hasher);
+            let mut sim = Simulator::new(num_qubits, num_bits, &mut inner_xof);
+            sim.clear_for_shot();
+            for k in 0..n {
+                if k < 64 && (target >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_target[k]) = 1;
+                }
+            }
+            for k in 0..m {
+                if k < 64 && (offset >> k) & 1 != 0 {
+                    *sim.qubit_mut(q_offset[k]) = 1;
+                }
+            }
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if k < 64 && (dirty_init >> k) & 1 != 0 {
+                    *sim.qubit_mut(q) = 1;
+                }
+            }
+            sim.apply(&ops);
+
+            let expected: u128 = (target as u128) + (offset as u128) + (cin as u128);
+            let readbits = n.min(127);
+            let expected = expected & ((1u128 << readbits) - 1);
+            let mut got: u128 = 0;
+            for k in 0..readbits {
+                if sim.qubit(q_target[k]) & 1 != 0 {
+                    got |= 1u128 << k;
+                }
+            }
+            let mut got_offset: u64 = 0;
+            for k in 0..m {
+                if sim.qubit(q_offset[k]) & 1 != 0 {
+                    got_offset |= 1 << k;
+                }
+            }
+            let mut got_dirty: u64 = 0;
+            for (k, &q) in q_dirty.iter().enumerate() {
+                if sim.qubit(q) & 1 != 0 {
+                    got_dirty |= 1 << k;
+                }
+            }
+            let dmask = if q_dirty.len() < 64 {
+                (1u64 << q_dirty.len()) - 1
+            } else {
+                u64::MAX
+            };
+            let dirty_ok = got_dirty == (dirty_init & dmask & nmask);
+            let offset_ok = got_offset == offset;
+            let phase = sim.global_phase() & 1;
+
+            if got == expected && dirty_ok && offset_ok && phase == 0 {
+                ok += 1;
+            } else {
+                bad += 1;
+                if bad < 3 {
+                    eprintln!(
+                        "narrow FAIL n={} m={} t={:#x} o={:#x} d={:#x} cin={} got={:#x} exp={:#x} d_ok={} o_ok={} phase={}",
+                        n, m, target, offset, dirty_init, cin, got, expected, dirty_ok, offset_ok, phase
+                    );
+                }
+            }
+        }
+        (ok, bad)
+    }
+
+    #[test]
+    fn test_iadd_qoffset_narrow_small() {
+
+        for n in 5..=12 {
+            for m in 1..n {
+                let (ok, bad) = run_iadd_qoffset_narrow(n, m, 12);
+                assert_eq!(bad, 0, "n={n} m={m}: {ok}/{} passed", ok + bad);
+            }
+        }
+    }
+
+    #[test]
+    fn test_iadd_qoffset_narrow_wide() {
+
+        let (ok, bad) = run_iadd_qoffset_narrow(256, 22, 40);
+        assert_eq!(bad, 0, "n=256 m=22: {ok}/{} passed", ok + bad);
+    }
+}