diff --git a/pipeline/tests/powdr_std.rs b/pipeline/tests/powdr_std.rs index 046c057c4f..d70fa2201d 100644 --- a/pipeline/tests/powdr_std.rs +++ b/pipeline/tests/powdr_std.rs @@ -137,6 +137,25 @@ fn arith_large_test() { test_halo2(make_simple_prepared_pipeline(f)); } +#[test] +#[ignore = "Too slow"] +fn arith256_memory_large_test() { + let f = "std/arith256_memory_large_test.asm"; + let pipeline = make_simple_prepared_pipeline(f); + test_pilcom(pipeline.clone()); + + // Running gen_estark_proof(f, Default::default()) + // is too slow for the PR tests. This will only create a single + // eStark proof instead of 3. + #[cfg(feature = "estark-starky")] + pipeline + .with_backend(powdr_backend::BackendType::EStarkStarky, None) + .compute_proof() + .unwrap(); + + test_halo2(make_simple_prepared_pipeline(f)); +} + #[test] #[ignore = "Too slow"] fn memory_large_test() { diff --git a/std/machines/large_field/arith256_memory.asm b/std/machines/large_field/arith256_memory.asm new file mode 100644 index 0000000000..660479903f --- /dev/null +++ b/std/machines/large_field/arith256_memory.asm @@ -0,0 +1,486 @@ +use std::array; +use std::utils::unchanged_until; +use std::utils::force_bool; +use std::utils::sum; +use std::math::ff; +use std::field::modulus; +use std::check::panic; +use std::check::require_field_bits; +use std::convert::int; +use std::convert::fe; +use std::convert::expr; +use std::prover::eval; +use std::prelude::Query; +use std::machines::range::Byte2; +use std::machines::large_field::memory::Memory; + +// Implements 256-Bit addition and multiplication. +// Ported mainly from Polygon: https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/arith.pil +// Requires the field to contain at least 48 bits. +machine Arith256Memory(mem: Memory) with + latch: CLK32_31, + operation_id: operation_id, + // Allow this machine to be connected via a permutation + call_selectors: sel, +{ + require_field_bits(48, || "Arith256Memory requires a field that fits any 48-Bit value."); + + Byte2 byte2; + + // One-hot encode the operation + col witness is_affine, is_mod, is_ec_add, is_ec_double; + let operation_selectors = [is_affine, is_mod, is_ec_add, is_ec_double]; + array::map(operation_selectors, |s| force_bool(s)); + array::map(operation_selectors, fixed_inside_32_block); + let operation_id = sum(4, |i| 2 ** i * operation_selectors[i]); + + // affine_256(a, b, c) = a * b + c, where a, b, and c are 256-bit words. The result is a 512-bit word. + operation affine_256<1> time_step, addr1, addr2, addr3, addr4 ->; + + // mod_256(x, p) = x % p, where x is a 512-bit word and p is a 256-bit word. The result is a 256-bit word. + // While hint computes the modulus, there's no guarantee from user generated witness input that the remainder is smaller than the modulus. + // In fact, the remainder can contain any multiples of modulus. + operation mod_256<2> time_step, addr1, addr2, addr3 ->; + + // ec_add((x1, y1), (x2, y2)) performs elliptic curve addition of points (x1, y2) and (x2, y2). All pointers point to a 2-tuple of 256-bit words. + operation ec_add<4> time_step, addr1, addr2, addr3 ->; + + // ec_double((x1, y1)) performs elliptic curve doubling of the point (x1, y1). Both pointers point to a 2-tuple of 256-bit words. + operation ec_double<8> time_step, addr1, addr2 ->; + + // ------------- Begin memory read / write --------------- + + // Get an intermediate column that indicates that we're in an + // actual block, not a default block. Its value is constant + // within the block. + // TODO: Witgen fails if this is an intermediate column. + col witness used; + used = array::sum(sel); + array::map(sel, |s| unchanged_until(s, CLK32[31])); + std::utils::force_bool(used); + + // Repeat the time step and addresses in the whole block + let time_step; + col witness addr1, addr2, addr3, addr4; + let addr = [addr1, addr2, addr3, addr4]; + array::map(addr, |a| unchanged_until(a, CLK32[31])); + unchanged_until(time_step, CLK32[31]); + + // Group the 32 rows into 4 blocks of 8 rows each + let block = array::new(4, |i| sum(8, |j| CLK32[8 * i + j])); + + // Index in each block + let offset = sum(8, |i| expr(i * 4) * (CLK32[i] + CLK32[8 + i] + CLK32[16 + i] + CLK32[24 + i])); + + // Memory reads: + // - affine_256: + // - addr1 -> x1 (block 0) + // - addr2 -> y1 (block 1) + // - addr3 -> x2 (block 2) + // - mod_256: + // - addr1 -> (y2, y3) (blocks 0 & 1) + // - addr2 -> x1 (block 2) + // - ec_add: + // - addr1 -> (x1, y1) (blocks 0 & 1) + // - addr2 -> (x2, y2) (blocks 2 & 3) + // - ec_double: + // - addr1 -> (x1, y1) (blocks 0 & 1) + + // Compute the "base" input address (we'll read words at base_input_address + offset) + col witness base_input_address; + is_affine * (base_input_address - (block[0] * addr1 + block[1] * addr2 + block[2] * addr3)) = 0; + is_mod * (base_input_address - (block[0] * addr1 + block[1] * (addr1 + 32) + block[2] * addr2)) = 0; + is_ec_add * (base_input_address - (block[0] * addr1 + block[1] * (addr1 + 32) + block[2] * addr2 + block[3] * (addr2 + 32))) = 0; + is_ec_double * (base_input_address - (block[0] * addr1 + block[1] * (addr1 + 32))) = 0; + + let input_address; + input_address = base_input_address + offset; + + // Compute whether to read from memory at all. + let do_mload; + (is_affine + is_mod) * (do_mload - (block[0] + block[1] + block[2])) = 0; + is_ec_add * (do_mload - 1) = 0; + is_ec_double * (do_mload - (block[0] + block[1])) = 0; + + // Select the target cell + let target_cell = ( + is_affine * ( + sum(8, |i| CLK32[i] * x1c[i]) + + sum(8, |i| CLK32[8 + i] * y1c[i]) + + sum(8, |i| CLK32[16 + i] * x2c[i]) + ) + + is_mod * ( + sum(8, |i| CLK32[i] * y2c[i]) + + sum(8, |i| CLK32[8 + i] * y3c[i]) + + sum(8, |i| CLK32[16 + i] * x1c[i]) + ) + + is_ec_add * ( + sum(8, |i| CLK32[i] * x1c[i]) + + sum(8, |i| CLK32[8 + i] * y1c[i]) + + sum(8, |i| CLK32[16 + i] * x2c[i]) + + sum(8, |i| CLK32[24 + i] * y2c[i]) + ) + + is_ec_double * ( + sum(8, |i| CLK32[i] * x1c[i]) + + sum(8, |i| CLK32[8 + i] * y1c[i]) + ) + ); + + // Read the word + let read_word; + read_word = target_cell; + link if (used * do_mload) ~> read_word = mem.mload(input_address, time_step); + + // Memory writes: + // - affine_256: (y2, y3) -> addr4 (blocks 0 & 1) + // - mod_256: x2 -> addr3 (block 0) + // - ec_add: (x3, y3) -> addr3 (blocks 0 & 1) + // - ec_double: (x3, y3) -> addr2 (blocks 0 & 1) + + // Compute the "base" output address (we'll write words at base_output_address + offset) + col witness base_output_address; + is_affine * (base_output_address - (block[0] * addr4 + block[1] * (addr4 + 32))) = 0; + is_mod * (base_output_address - (block[0] * addr3)) = 0; + is_ec_add * (base_output_address - (block[0] * addr3 + block[1] * (addr3 + 32))) = 0; + is_ec_double * (base_output_address - (block[0] * addr2 + block[1] * (addr2 + 32))) = 0; + + let output_address; + output_address = base_output_address + offset; + + // Compute whether to write to memory at all. + let do_mstore; + (is_affine + is_ec_add + is_ec_double) * (do_mstore - (block[0] + block[1])) = 0; + is_mod * (do_mstore - block[0]) = 0; + + // Select the source cell + let source_cell = ( + is_affine * ( + sum(8, |i| CLK32[i] * y2c[i]) + + sum(8, |i| CLK32[8 + i] * y3c[i]) + ) + + is_mod * ( + sum(8, |i| CLK32[i] * x2c[i]) + ) + + is_ec_add * ( + sum(8, |i| CLK32[i] * x3c[i]) + + sum(8, |i| CLK32[8 + i] * y3c[i]) + ) + + is_ec_double * ( + sum(8, |i| CLK32[i] * x3c[i]) + + sum(8, |i| CLK32[8 + i] * y3c[i]) + ) + ); + + // Write the word + let write_word; + write_word = source_cell; + link if (used * do_mstore) ~> mem.mstore(output_address, time_step + 1, write_word); + + + // ------------- End memory read / write ----------------- + + + let secp_modulus = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f; + + let inverse: int -> int = |x| ff::inverse(x, secp_modulus); + let add = |x, y| ff::add(x, y, secp_modulus); + let sub = |x, y| ff::sub(x, y, secp_modulus); + let mul = |x, y| ff::mul(x, y, secp_modulus); + let div = |x, y| ff::div(x, y, secp_modulus); + + col witness x1[16], x2[16], x3[16]; + col witness y1[16], y2[16], y3[16]; + col witness s[16], q0[16], q1[16], q2[16]; + + // Selects the ith limb of x (little endian) + // Note that the most significant limb can be up to 32 bits; all others are 16 bits. + let select_limb = |x, i| if i >= 0 { + (x >> (i * 16)) & if i < 15 { 0xffff } else { 0xffffffff } + } else { + 0 + }; + + let limbs_to_int: expr[] -> int = query |limbs| array::sum(array::map_enumerated(limbs, |i, limb| int(eval(limb)) << (i * 16))); + + let x1_int = query || limbs_to_int(x1); + let y1_int = query || limbs_to_int(y1); + let x2_int = query || limbs_to_int(x2); + let y2_int = query || limbs_to_int(y2); + let x3_int = query || limbs_to_int(x3); + let y3_int = query || limbs_to_int(y3); + let s_int = query || limbs_to_int(s); + + let get_operation = query || match eval(operation_id) { + 1 => "affine_256", + 2 => "mod_256", + 4 => "ec_add", + 8 => "ec_double", + _ => panic("Unknown operation") + }; + + + let provide_values = query |column_arr, row, value| { + let _ = array::map_enumerated(column_arr, |j, column| std::prover::provide_value(column, row, fe(select_limb(value, j)))); + }; + query |i| { + let op = get_operation(); + if op == "affine_256" || op == "mod_256" { + match std::prover::try_eval(y1[0]) { + Option::Some(_) => { + // y1 is an input, in this case we do not need a hint. + }, + Option::None => { + // y1 is not an input, which means we are probably computing + // division or modulo. + let y2 = y2_int(); + let y3 = y3_int(); + let x1 = x1_int(); + let dividend = (y2 << 256) + y3; + provide_values(y1, i, dividend / x1); + provide_values(x2, i, dividend % x1); + } + } + } else { + let y1 = y1_int(); + // y2 is unused for ec_double + let y2 = if op == "ec_add" { y2_int() } else { 0 }; + let x1 = x1_int(); + let x2 = x2_int(); + let s_val = if op == "ec_add" { + div(sub(y2, y1), sub(x2, x1)) + } else { + div(mul(3, mul(x1, x1)), mul(2, y1)) + }; + provide_values(s, i, s_val); + // Compute quotients. + // Note that we add 2**258 to it, to move it from the (-2**258, 2**258) to the (0, 2**259) range, so it can + // be represented as an unsigned 272-bit integer. + // See the comment for `product_with_p` below. + let q0_val = if op == "ec_add" { + -(s_val * x2 - s_val * x1 - y2 + y1) / secp_modulus + (1 << 258) + } else { + -(2 * s_val * y1 - 3 * x1 * x1) / secp_modulus + (1 << 258) + }; + provide_values(q0, i, q0_val); + + // Adding secp_modulus to make sure that that all numbers are positive when % is applied to it. + let x3_val = (s_val * s_val - x1 - x2 + 2 * secp_modulus) % secp_modulus; + provide_values(x3, i, x3_val); + let y3_val = (s_val * ((x1 - x3_val) + secp_modulus) - y1 + secp_modulus) % secp_modulus; + provide_values(y3, i, y3_val); + + provide_values(q1, i, -(s_val * s_val - x1 - x2 - x3_val) / secp_modulus + (1 << 258)); + provide_values(q2, i, -(s_val * x1 - s_val * x3_val - y1 - y3_val) / secp_modulus + (1 << 258)); + } + }; + + let combine: expr[] -> expr[] = |x| array::new(array::len(x) / 2, |i| x[2 * i + 1] * 2**16 + x[2 * i]); + // Intermediate polynomials, arrays of 8 columns, 32 bit per column. + col x1c[8] = combine(x1); + col y1c[8] = combine(y1); + col x2c[8] = combine(x2); + col y2c[8] = combine(y2); + col x3c[8] = combine(x3); + col y3c[8] = combine(y3); + + let CLK32: col[32] = array::new(32, |i| |row| if row % 32 == i { 1 } else { 0 }); + let CLK32_31: expr = CLK32[31]; + + // TODO: Add the equivalent of these constraints for soundness: https://github.com/0xPolygonHermez/zkevm-proverjs/blob/main/pil/arith.pil#L43-L243 + + /**** + * + * LATCH POLS: x1,y1,x2,y2,x3,y3,s,q0,q1,q2 + * + *****/ + + let fixed_inside_32_block = |e| unchanged_until(e, CLK32[31]); + + array::map(x1, fixed_inside_32_block); + array::map(y1, fixed_inside_32_block); + array::map(x2, fixed_inside_32_block); + array::map(y2, fixed_inside_32_block); + array::map(x3, fixed_inside_32_block); + array::map(y3, fixed_inside_32_block); + array::map(s, fixed_inside_32_block); + array::map(q0, fixed_inside_32_block); + array::map(q1, fixed_inside_32_block); + array::map(q2, fixed_inside_32_block); + + /**** + * + * RANGE CHECK x1,y1,x2,y2,x3,y3,s,q0,q1,q2 + * + *****/ + + link => byte2.check(sum(16, |i| x1[i] * CLK32[i]) + sum(16, |i| y1[i] * CLK32[16 + i])); + link => byte2.check(sum(16, |i| x2[i] * CLK32[i]) + sum(16, |i| y2[i] * CLK32[16 + i])); + link => byte2.check(sum(16, |i| x3[i] * CLK32[i]) + sum(16, |i| y3[i] * CLK32[16 + i])); + // Note that for q0-q2, we only range-constrain the first 15 limbs here + link => byte2.check(sum(16, |i| s[i] * CLK32[i]) + sum(15, |i| q0[i] * CLK32[16 + i])); + link => byte2.check(sum(15, |i| q1[i] * CLK32[i]) + sum(15, |i| q2[i] * CLK32[16 + i])); + + // The most significant limbs of q0-q2 are constrained to be 32 bits + // In Polygon's version they are 19 bits, but that requires increasing the minimum degree + // to fit the lookup. + // Instead, we decompose the most significant limb into two 16-Bit limbs. + // Having a larger range-constraint is fine, because we're only multiplying it with 16-bit + // limbs of the prime, so the result is within 48 bits, still far from overflowing the + // Goldilocks field. + pol witness q0_15_high, q0_15_low, q1_15_high, q1_15_low, q2_15_high, q2_15_low; + link => byte2.check(q0_15_high * CLK32[0] + q0_15_low * CLK32[1] + q1_15_high * CLK32[2] + q1_15_low * CLK32[3] + q2_15_high * CLK32[4] + q2_15_low * CLK32[5]); + + fixed_inside_32_block(q0_15_high); + fixed_inside_32_block(q0_15_low); + fixed_inside_32_block(q1_15_high); + fixed_inside_32_block(q1_15_low); + fixed_inside_32_block(q2_15_high); + fixed_inside_32_block(q2_15_low); + + q0[15] = 2**16 * q0_15_high + q0_15_low; + q1[15] = 2**16 * q1_15_high + q1_15_low; + q2[15] = 2**16 * q2_15_high + q2_15_low; + + /******* + * + * EQ0: A(x1) * B(y1) + C(x2) = D (y2) * 2 ** 256 + op (y3) + * x1 * y1 + x2 - y2 * 2**256 - y3 = 0 + * + *******/ + + /// returns a(0) * b(0) + ... + a(n - 1) * b(n - 1) + let dot_prod = |n, a, b| sum(n, |i| a(i) * b(i)); + /// returns |n| a(0) * b(n) + ... + a(n) * b(0) + let product = |a, b| |n| dot_prod(n + 1, a, |i| b(n - i)); + /// Converts array to function, extended by zeros. + let array_as_fun: expr[] -> (int -> expr) = |arr| |i| if 0 <= i && i < array::len(arr) { + arr[i] + } else { + 0 + }; + let shift_right = |fn, amount| |i| fn(i - amount); + + let x1f = array_as_fun(x1); + let y1f = array_as_fun(y1); + let x2f = array_as_fun(x2); + let y2f = array_as_fun(y2); + let x3f = array_as_fun(x3); + let y3f = array_as_fun(y3); + let sf = array_as_fun(s); + let q0f = array_as_fun(q0); + let q1f = array_as_fun(q1); + let q2f = array_as_fun(q2); + + // Defined for arguments from 0 to 31 (inclusive) + let eq0 = |nr| + product(x1f, y1f)(nr) + + x2f(nr) + - shift_right(y2f, 16)(nr) + - y3f(nr); + + /******* + * + * EQ1: s * x2 - s * x1 - y2 + y1 + (q0 * p) + * + *******/ + + let p = |i| expr(select_limb(secp_modulus, i)); + + // The "- 4 * shift_right(p, 16)" effectively subtracts 4 * (p << 16 * 16) = 2 ** 258 * p + // As a result, the term computes `(x - 2 ** 258) * p`. + let product_with_p = |x| |nr| product(p, x)(nr) - 4 * shift_right(p, 16)(nr); + + let eq1 = |nr| product(sf, x2f)(nr) - product(sf, x1f)(nr) - y2f(nr) + y1f(nr) + product_with_p(q0f)(nr); + + /******* + * + * EQ2: 2 * s * y1 - 3 * x1 * x1 + (q0 * p) + * + *******/ + + let eq2 = |nr| 2 * product(sf, y1f)(nr) - 3 * product(x1f, x1f)(nr) + product_with_p(q0f)(nr); + + /******* + * + * EQ3: s * s - x1 - x2 - x3 + (q1 * p) + * + *******/ + + // If we're doing the ec_double operation, x2 is so far unconstrained and should be set to x1 + array::new(16, |i| is_ec_double * (x1[i] - x2[i]) = 0); + + let eq3 = |nr| product(sf, sf)(nr) - x1f(nr) - x2f(nr) - x3f(nr) + product_with_p(q1f)(nr); + + + /******* + * + * EQ4: s * x1 - s * x3 - y1 - y3 + (q2 * p) + * + *******/ + + let eq4 = |nr| product(sf, x1f)(nr) - product(sf, x3f)(nr) - y1f(nr) - y3f(nr) + product_with_p(q2f)(nr); + + + /******* + * + * Equation Selectors + * + *******/ + + let selEq = [ + // Equation 0: x1 * y1 + x2 - y2 * 2**256 - y3 = 0 + is_affine + is_mod, + // Equation 1: s * x2 - s * x1 - y2 + y1 + (q0 * p) = 0 + // (Computes slope for EC addition) + is_ec_add, + // Equation 2: 2 * s * y1 - 3 * x1 * x1 + (q0 * p) = 0 + // (Computes slope for EC doubling) + is_ec_double, + // Equation 3: s * s - x1 - x2 - x3 + (q1 * p) = 0 + // (Computes x3) + is_ec_add + is_ec_double, + // Equation 4: s * x1 - s * x3 - y1 - y3 + (q2 * p) = 0 + // (Computes y3) + is_ec_add + is_ec_double + ]; + + /******* + * + * Carry + * + *******/ + + // Note that Polygon uses a single 22-Bit column. However, this approach allows for a lower degree (2**16) + // while still preventing overflows: The 32-bit carry gets added to 32 48-Bit values, which can't overflow + // the Goldilocks field. + pol witness carry_low[3], carry_high[3]; + link => byte2.check(carry_low[0]); + link => byte2.check(carry_low[1]); + link => byte2.check(carry_low[2]); + link => byte2.check(carry_high[0]); + link => byte2.check(carry_high[1]); + link => byte2.check(carry_high[2]); + + // Carries can be any integer in the range [-2**31, 2**31 - 1) + let carry = array::new(3, |i| carry_high[i] * 2**16 + carry_low[i] - 2 ** 31); + + array::map(carry, |c| c * CLK32[0] = 0); + + /******* + * + * Putting everything together + * + *******/ + + col eq0_sum = sum(32, |i| eq0(i) * CLK32[i]); + col eq1_sum = sum(32, |i| eq1(i) * CLK32[i]); + col eq2_sum = sum(32, |i| eq2(i) * CLK32[i]); + col eq3_sum = sum(32, |i| eq3(i) * CLK32[i]); + col eq4_sum = sum(32, |i| eq4(i) * CLK32[i]); + + selEq[0] * (eq0_sum + carry[0]) = selEq[0] * carry[0]' * 2**16; + selEq[1] * (eq1_sum + carry[0]) = selEq[1] * carry[0]' * 2**16; + selEq[2] * (eq2_sum + carry[0]) = selEq[2] * carry[0]' * 2**16; + selEq[3] * (eq3_sum + carry[1]) = selEq[3] * carry[1]' * 2**16; + selEq[4] * (eq4_sum + carry[2]) = selEq[4] * carry[2]' * 2**16; +} diff --git a/std/machines/large_field/mod.asm b/std/machines/large_field/mod.asm index 569dfe941d..a5b687cabe 100644 --- a/std/machines/large_field/mod.asm +++ b/std/machines/large_field/mod.asm @@ -2,6 +2,7 @@ // Goldilocks, Bn254 mod arith; +mod arith256_memory; mod binary; mod memory; mod memory_with_bootloader_write; diff --git a/test_data/std/arith256_memory_large_test.asm b/test_data/std/arith256_memory_large_test.asm new file mode 100644 index 0000000000..bd2eab2aa1 --- /dev/null +++ b/test_data/std/arith256_memory_large_test.asm @@ -0,0 +1,979 @@ +use std::machines::large_field::arith256_memory::Arith256Memory; +use std::machines::range::Byte2; +use std::machines::large_field::memory::Memory; + +machine Main with degree: 65536 { + reg pc[@pc]; + reg W[<=]; + reg X[<=]; + reg Y[<=]; + reg Z[<=]; + reg A0[<=]; + reg A1[<=]; + reg A2[<=]; + reg A3[<=]; + reg A4[<=]; + reg A5[<=]; + reg A6[<=]; + reg A7[<=]; + + col fixed STEP(i) { i * 4 }; + Byte2 byte2; + Memory memory(byte2); + Arith256Memory arith(memory); + + instr mstore X, A0, A1, A2, A3, A4, A5, A6, A7 -> + link ~> memory.mstore(X, STEP, A0) + link ~> memory.mstore(X + 4, STEP, A1) + link ~> memory.mstore(X + 8, STEP, A2) + link ~> memory.mstore(X + 12, STEP, A3) + link ~> memory.mstore(X + 16, STEP, A4) + link ~> memory.mstore(X + 20, STEP, A5) + link ~> memory.mstore(X + 24, STEP, A6) + link ~> memory.mstore(X + 28, STEP, A7); + + instr affine_256 W, X, Y, Z -> link ~> arith.affine_256(STEP, W, X, Y, Z); + instr mod_256 W, X, Y -> link ~> arith.mod_256(STEP, W, X, Y); + instr ec_add W, X, Y -> link ~> arith.ec_add(STEP, W, X, Y); + instr ec_double W, X -> link ~> arith.ec_double(STEP, W, X); + + instr assert_eq X, A0, A1, A2, A3, A4, A5, A6, A7 + link ~> A0 = memory.mload(X, STEP) + link ~> A1 = memory.mload(X + 4, STEP) + link ~> A2 = memory.mload(X + 8, STEP) + link ~> A3 = memory.mload(X + 12, STEP) + link ~> A4 = memory.mload(X + 16, STEP) + link ~> A5 = memory.mload(X + 20, STEP) + link ~> A6 = memory.mload(X + 24, STEP) + link ~> A7 = memory.mload(X + 28, STEP); + + + function main { + + // 0x0000000011111111222222223333333344444444555555556666666677777777 + // * 0x8888888899999999aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffff + // + 0xaaaaaaaabbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbaaaaaaaa + // == 0x91a2b3c579be024740da740e6f8091a38e38e38f258bf259be024691fdb97530da740da60b60b60907f6e5d369d0369ca8641fda1907f6e33333333 + // == 0x00000000_091a2b3c_579be024_740da740_e6f8091a_38e38e38_f258bf25_9be02469 * 2**256 + 0x1fdb9753_0da740da_60b60b60_907f6e5d_369d0369_ca8641fd_a1907f6e_33333333 + + mstore 0, 0x77777777, 0x66666666, 0x55555555, 0x44444444, 0x33333333, 0x22222222, 0x11111111, 0x00000000; + mstore 32, 0xffffffff, 0xeeeeeeee, 0xdddddddd, 0xcccccccc, 0xbbbbbbbb, 0xaaaaaaaa, 0x99999999, 0x88888888; + mstore 64, 0xaaaaaaaa, 0xbbbbbbbb, 0xbbbbbbbb, 0xaaaaaaaa, 0xaaaaaaaa, 0xbbbbbbbb, 0xbbbbbbbb, 0xaaaaaaaa; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0x9be02469, 0xf258bf25, 0x38e38e38, 0xe6f8091a, 0x740da740, 0x579be024, 0x091a2b3c, 0x00000000; + assert_eq 32, 0x33333333, 0xa1907f6e, 0xca8641fd, 0x369d0369, 0x907f6e5d, 0x60b60b60, 0x0da740da, 0x1fdb9753; + + // Test vectors from: https://github.com/0xPolygonHermez/zkevm-proverjs/blob/a4006af3d7fe4a57a85500c01dc791fb5013cef0/test/sm/sm_arith.js + + // 2 * 3 + 5 = 11 + mstore 0, 2, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 3, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 11, 0, 0, 0, 0, 0, 0, 0; + + // 256 * 256 + 1 = 65537 + mstore 0, 256, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 256, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 1, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 65537, 0, 0, 0, 0, 0, 0, 0; + + // 3000 * 2000 + 5000 = 6005000 + mstore 0, 3000, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 2000, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5000, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 6005000, 0, 0, 0, 0, 0, 0, 0; + + // 3000000 * 2000000 + 5000000 = 6000005000000 + mstore 0, 3000000, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 2000000, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5000000, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 0xfc2aab40, 0x574, 0, 0, 0, 0, 0, 0; + + // 3000 * 0 + 5000 = 5000 + mstore 0, 3000, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 0, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5000, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 5000, 0, 0, 0, 0, 0, 0, 0; + + // 2**255 * 2 + 0 = 2 ** 256 + mstore 0, 0, 0, 0, 0, 0, 0, 0, 0x80000000; + mstore 32, 2, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0, 0, 0, 0, 0, 0, 0, 0; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 1, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 0, 0, 0, 0, 0, 0, 0, 0; + + // (2**256 - 1) * (2**256 - 1) + (2**256 - 1) + mstore 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + mstore 32, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + mstore 64, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + assert_eq 32, 0, 0, 0, 0, 0, 0, 0, 0; + + // (2**256 - 1) * 1 + (2**256 - 1) + mstore 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + mstore 32, 1, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 1, 0, 0, 0, 0, 0, 0, 0; + assert_eq 32, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + + // Mod 256: + // 6 % 5 = 1 + mstore 0, 0, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 6, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5, 0, 0, 0, 0, 0, 0, 0; + + mod_256 0, 64, 0; + + assert_eq 0, 1, 0, 0, 0, 0, 0, 0, 0; + + // 3000 % 5000 = 3000 + mstore 0, 0, 0, 0, 0, 0, 0, 0, 0; + mstore 32, 3000, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 5000, 0, 0, 0, 0, 0, 0, 0; + + mod_256 0, 64, 0; + + assert_eq 0, 3000, 0, 0, 0, 0, 0, 0, 0; + + // (2 ** 508) % (2 ** 255) = 0 + mstore 0, 0, 0, 0, 0, 0, 0, 0, 0x10000000; + mstore 32, 0, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0, 0, 0, 0, 0, 0, 0, 0x80000000; + + mod_256 0, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + + // (2 ** 508 + 1) % (2 ** 255) = 1 + mstore 0, 0, 0, 0, 0, 0, 0, 0, 0x10000000; + mstore 32, 1, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0, 0, 0, 0, 0, 0, 0, 0x80000000; + + mod_256 0, 64, 0; + + assert_eq 0, 1, 0, 0, 0, 0, 0, 0, 0; + + // 0xaaaaaaaabbbbbbbbcccccccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111 + // % 0xddddddddeeeeeeeeffffffff0000000000000000000000000000000022222222 + // = 0x05973e6b48bd15d35f92aff26cad25d5b54f806e5ce298cda76b91baf89af7cf + mstore 0, 0, 0, 0, 0, 0, 0xcccccccc, 0xbbbbbbbb, 0xaaaaaaaa; + mstore 32, 0x11111111, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0x22222222, 0, 0, 0, 0, 0xffffffff, 0xeeeeeeee, 0xdddddddd; + + mod_256 0, 64, 0; + + assert_eq 0, 0xF89AF7CF, 0xA76B91BA, 0x5CE298CD, 0xB54F806E, 0x6CAD25D5, 0x5F92AFF2, 0x48BD15D3, 0x05973E6B; + + // 0x11111111222222223333333344444444555555556666666677777777888888889999999900000000aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffff + // % 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f (secp_modulus) + // = 0xddddde1e 777777b9 55555596 999999da ddddde1f 22222263 7777783a 333428f9 + mstore 0, 0x88888888, 0x77777777, 0x66666666, 0x55555555, 0x44444444, 0x33333333, 0x22222222, 0x11111111; + mstore 32, 0xffffffff, 0xeeeeeeee, 0xdddddddd, 0xcccccccc, 0xbbbbbbbb, 0xaaaaaaaa, 0x00000000, 0x99999999; + mstore 64, 0xfffffc2f, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + + mod_256 0, 64, 0; + + assert_eq 0, 0x333428f9, 0x7777783a, 0x22222263, 0xddddde1f, 0x999999da, 0x55555596, 0x777777b9, 0xddddde1e; + + // ((2**256 - 1) * (2**256 - 1) + (2**256 - 1)) % (2**256 - 1) + mstore 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + mstore 32, 0, 0, 0, 0, 0, 0, 0, 0; + mstore 64, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff; + + affine_256 0, 32, 64, 0; + + assert_eq 0, 0, 0, 0, 0, 0, 0, 0, 0; + + + // EC Addition: + // x1: 55066263022277343669578718895168534326250603453777594175500187360389116729240 + // = 0x79be667e f9dcbbac 55a06295 ce870b07 029bfcdb 2dce28d9 59f2815b 16f81798 + // y1: 32670510020758816978083085130507043184471273380659243275938904335757337482424 + // = 0x483ada77 26a3c465 5da4fbfc 0e1108a8 fd17b448 a6855419 9c47d08f fb10d4b8 + // x2: 89565891926547004231252920425935692360644145829622209833684329913297188986597 + // = 0xc6047f94 41ed7d6d 3045406e 95c07cd8 5c778e4b 8cef3ca7 abac09b9 5c709ee5 + // y2: 12158399299693830322967808612713398636155367887041628176798871954788371653930 + // = 0x1ae168fe a63dc339 a3c58419 466ceaee f7f63265 3266d0e1 236431a9 50cfe52a + // x3: 112711660439710606056748659173929673102114977341539408544630613555209775888121 + // = 0xf9308a01 9258c310 49344f85 f89d5229 b531c845 836f99b0 8601f113 bce036f9 + // y3: 25583027980570883691656905877401976406448868254816295069919888960541586679410 + // = 0x388f7b0f 632de814 0fe337e6 2a37f356 6500a999 34c2231b 6cb9fd75 84b8e672 + + mstore 0, 0x16f81798, 0x59f2815b, 0x2dce28d9, 0x029bfcdb, 0xce870b07, 0x55a06295, 0xf9dcbbac, 0x79be667e; + mstore 32, 0xfb10d4b8, 0x9c47d08f, 0xa6855419, 0xfd17b448, 0x0e1108a8, 0x5da4fbfc, 0x26a3c465, 0x483ada77; + mstore 64, 0x5c709ee5, 0xabac09b9, 0x8cef3ca7, 0x5c778e4b, 0x95c07cd8, 0x3045406e, 0x41ed7d6d, 0xc6047f94; + mstore 96, 0x50cfe52a, 0x236431a9, 0x3266d0e1, 0xf7f63265, 0x466ceaee, 0xa3c58419, 0xa63dc339, 0x1ae168fe; + + ec_add 0, 64, 0; + + assert_eq 0, 0xbce036f9, 0x8601f113, 0x836f99b0, 0xb531c845, 0xf89d5229, 0x49344f85, 0x9258c310, 0xf9308a01; + assert_eq 32, 0x84b8e672, 0x6cb9fd75, 0x34c2231b, 0x6500a999, 0x2a37f356, 0x0fe337e6, 0x632de814, 0x388f7b0f; + + + // EC Double: + // x1: 115780575977492633039504758427830329241728645270042306223540962614150928364886 + // = 0xfff97bd5 755eeea4 20453a14 355235d3 82f6472f 8568a18b 2f057a14 60297556 + // y1: 78735063515800386211891312544505775871260717697865196436804966483607426560663 + // = 0xae12777a acfbb620 f3be9601 7f45c560 de80f0f6 518fe4a0 3c870c36 b075f297 + // x3: 94111259592240215275188773285036844871058226277992966241101117022315524122714 + // = 0xd01115d5 48e7561b 15c38f00 4d734633 687cf441 9620095b c5b0f470 70afe85a + // y3: 76870767327212528811304566602812752860184934880685532702451763239157141742375 + // = 0xa9f34ffd c815e0d7 a8b64537 e17bd815 79238c5d d9a86d52 6b051b13 f4062327 + + mstore 0, 0x60297556, 0x2f057a14, 0x8568a18b, 0x82f6472f, 0x355235d3, 0x20453a14, 0x755eeea4, 0xfff97bd5; + mstore 32, 0xb075f297, 0x3c870c36, 0x518fe4a0, 0xde80f0f6, 0x7f45c560, 0xf3be9601, 0xacfbb620, 0xae12777a; + + ec_double 0, 0; + + assert_eq 0, 0x70afe85a, 0xc5b0f470, 0x9620095b, 0x687cf441, 0x4d734633, 0x15c38f00, 0x48e7561b, 0xd01115d5; + assert_eq 32, 0xf4062327, 0x6b051b13, 0xd9a86d52, 0x79238c5d, 0xe17bd815, 0xa8b64537, 0xc815e0d7, 0xa9f34ffd; + + // Auto-generated rest of the test cases, + // see: https://gist.github.com/georgwiese/a66425ae95c839b548edffffe6a692f9 + mstore 0, 0x70afe85a, 0xc5b0f470, 0x9620095b, 0x687cf441, 0x4d734633, 0x15c38f00, 0x48e7561b, 0xd01115d5; + mstore 32, 0xf4062327, 0x6b051b13, 0xd9a86d52, 0x79238c5d, 0xe17bd815, 0xa8b64537, 0xc815e0d7, 0xa9f34ffd; + + ec_double 0, 0; + + assert_eq 0, 0xb202e6ce, 0x502bda8, 0x9d62b794, 0x68321543, 0x61ba8b09, 0x8ac09c91, 0x413d33d4, 0xfe72c435; + assert_eq 32, 0xcf58c5bf, 0x978ed2fb, 0x6b4a9d22, 0x1dc88e3, 0x9d729981, 0xd3ab47e0, 0x7ff24a68, 0x6851de06; + + mstore 0, 0xb202e6ce, 0x502bda8, 0x9d62b794, 0x68321543, 0x61ba8b09, 0x8ac09c91, 0x413d33d4, 0xfe72c435; + mstore 32, 0xcf58c5bf, 0x978ed2fb, 0x6b4a9d22, 0x1dc88e3, 0x9d729981, 0xd3ab47e0, 0x7ff24a68, 0x6851de06; + + ec_double 0, 0; + + assert_eq 0, 0x1118e5c3, 0x9bd870aa, 0x452bebc1, 0xfc579b27, 0xf4e65b4b, 0xb441656e, 0x9645307d, 0x6eca335d; + assert_eq 32, 0x5a08668, 0x498a2f78, 0x3bf8ec34, 0x3a496a3a, 0x74b875a0, 0x592f5790, 0x7a7a0710, 0xd50123b5; + + mstore 0, 0x1118e5c3, 0x9bd870aa, 0x452bebc1, 0xfc579b27, 0xf4e65b4b, 0xb441656e, 0x9645307d, 0x6eca335d; + mstore 32, 0x5a08668, 0x498a2f78, 0x3bf8ec34, 0x3a496a3a, 0x74b875a0, 0x592f5790, 0x7a7a0710, 0xd50123b5; + + ec_double 0, 0; + + assert_eq 0, 0x7f8cb0e3, 0x43933aca, 0xe1efe3a4, 0xa22eb53f, 0x4b2eb72e, 0x8fa64e04, 0x74456d8f, 0x3f0e80e5; + assert_eq 32, 0xea5f404f, 0xcb0289e2, 0xa65b53a4, 0x9501253a, 0x485d01b3, 0xe90b9c08, 0x296cbc91, 0xcb66d7d7; + + mstore 0, 0x7f8cb0e3, 0x43933aca, 0xe1efe3a4, 0xa22eb53f, 0x4b2eb72e, 0x8fa64e04, 0x74456d8f, 0x3f0e80e5; + mstore 32, 0xea5f404f, 0xcb0289e2, 0xa65b53a4, 0x9501253a, 0x485d01b3, 0xe90b9c08, 0x296cbc91, 0xcb66d7d7; + + ec_double 0, 0; + + assert_eq 0, 0x33ce1752, 0xc7b750f7, 0xd7cd204e, 0xe783c797, 0xd99c9aea, 0x812ddf64, 0xd01dc635, 0xd7a0da58; + assert_eq 32, 0x762cef4, 0xbbc02738, 0xc062b742, 0xbe040a8, 0x40e28465, 0xf6f29283, 0x68008032, 0x912770e0; + + mstore 0, 0x33ce1752, 0xc7b750f7, 0xd7cd204e, 0xe783c797, 0xd99c9aea, 0x812ddf64, 0xd01dc635, 0xd7a0da58; + mstore 32, 0x762cef4, 0xbbc02738, 0xc062b742, 0xbe040a8, 0x40e28465, 0xf6f29283, 0x68008032, 0x912770e0; + + ec_double 0, 0; + + assert_eq 0, 0xb5476085, 0xa908b701, 0x96eb9f84, 0xb5714e77, 0xa78ed1af, 0x10d3aad6, 0x7a08cd3e, 0x3443a706; + assert_eq 32, 0x8b8f52d8, 0x6d3484bd, 0xd0c2b67f, 0x18a4b27, 0x8c7e1da9, 0x4f6e8c4b, 0x829b6f85, 0x661a7a5f; + + mstore 0, 0xb5476085, 0xa908b701, 0x96eb9f84, 0xb5714e77, 0xa78ed1af, 0x10d3aad6, 0x7a08cd3e, 0x3443a706; + mstore 32, 0x8b8f52d8, 0x6d3484bd, 0xd0c2b67f, 0x18a4b27, 0x8c7e1da9, 0x4f6e8c4b, 0x829b6f85, 0x661a7a5f; + + ec_double 0, 0; + + assert_eq 0, 0xe57e8dfa, 0xfcfc0cb9, 0xa3c7e184, 0x9809191, 0xaca98ca0, 0xd9a30f8, 0xf0799c4c, 0x8262cf2f; + assert_eq 32, 0xfbac376a, 0x35cff8d8, 0x2b14c478, 0x57b6ed33, 0xc5b34f34, 0x66fee22e, 0x9109e4e, 0x83fd95e2; + + mstore 0, 0xe57e8dfa, 0xfcfc0cb9, 0xa3c7e184, 0x9809191, 0xaca98ca0, 0xd9a30f8, 0xf0799c4c, 0x8262cf2f; + mstore 32, 0xfbac376a, 0x35cff8d8, 0x2b14c478, 0x57b6ed33, 0xc5b34f34, 0x66fee22e, 0x9109e4e, 0x83fd95e2; + + ec_double 0, 0; + + assert_eq 0, 0x7c70620c, 0xd17cc1f2, 0xabc288d9, 0x4998c4be, 0x2b671780, 0xc60dd31a, 0x8d2c236d, 0x1653a8a4; + assert_eq 32, 0x315b32cd, 0x6ca2e81d, 0xdfd3dc52, 0x12af748, 0x4efa701c, 0xeafa9947, 0x35af7f7a, 0x3382909; + + mstore 0, 0x7c70620c, 0xd17cc1f2, 0xabc288d9, 0x4998c4be, 0x2b671780, 0xc60dd31a, 0x8d2c236d, 0x1653a8a4; + mstore 32, 0x315b32cd, 0x6ca2e81d, 0xdfd3dc52, 0x12af748, 0x4efa701c, 0xeafa9947, 0x35af7f7a, 0x3382909; + + ec_double 0, 0; + + assert_eq 0, 0xe71dabcd, 0x47d42ba6, 0x89e5cb4f, 0x54d3fe49, 0x60b5373f, 0x6098ae32, 0x6b63f43c, 0xd49ee4fb; + assert_eq 32, 0x16603c2, 0xe66a90cf, 0x12ff7031, 0x129c5093, 0xa61bf356, 0xd7c87ea7, 0x9a5490d, 0x531e392; + + mstore 0, 0xe71dabcd, 0x47d42ba6, 0x89e5cb4f, 0x54d3fe49, 0x60b5373f, 0x6098ae32, 0x6b63f43c, 0xd49ee4fb; + mstore 32, 0x16603c2, 0xe66a90cf, 0x12ff7031, 0x129c5093, 0xa61bf356, 0xd7c87ea7, 0x9a5490d, 0x531e392; + + ec_double 0, 0; + + assert_eq 0, 0xc8c828a, 0x53f30ab9, 0xc96ae41f, 0x132eb242, 0x17e81c75, 0xe44a0d8, 0xa4149e75, 0x5f94851c; + assert_eq 32, 0x37344d80, 0xbfeb0a3f, 0x4fc68b04, 0x8c66df75, 0x8882f35e, 0xe5f0797d, 0xafa1fee8, 0x26b8c3b8; + + mstore 0, 0xc8c828a, 0x53f30ab9, 0xc96ae41f, 0x132eb242, 0x17e81c75, 0xe44a0d8, 0xa4149e75, 0x5f94851c; + mstore 32, 0x37344d80, 0xbfeb0a3f, 0x4fc68b04, 0x8c66df75, 0x8882f35e, 0xe5f0797d, 0xafa1fee8, 0x26b8c3b8; + + ec_double 0, 0; + + assert_eq 0, 0xc5041216, 0x65b7f8f1, 0x842b836a, 0x3f7335f6, 0xdc2fed52, 0x128b59ef, 0x21f7acf4, 0xda75317b; + assert_eq 32, 0x6e708572, 0xdaed3298, 0xe77aceda, 0xe9aac07a, 0x342d7fc6, 0xdf19e21b, 0xbf72d5f0, 0x73f8a046; + + mstore 0, 0xc5041216, 0x65b7f8f1, 0x842b836a, 0x3f7335f6, 0xdc2fed52, 0x128b59ef, 0x21f7acf4, 0xda75317b; + mstore 32, 0x6e708572, 0xdaed3298, 0xe77aceda, 0xe9aac07a, 0x342d7fc6, 0xdf19e21b, 0xbf72d5f0, 0x73f8a046; + + ec_double 0, 0; + + assert_eq 0, 0x3c62bac0, 0x9505324f, 0x51f0ab06, 0x19150ddf, 0xc3e8b70e, 0x1364b7d2, 0x23f469c, 0x9530f0f9; + assert_eq 32, 0x7618e309, 0x478abda9, 0x2f1fdc68, 0xe25b3285, 0x59b333e0, 0x34dd2f7f, 0x8f9f21e2, 0x8f3c305a; + + mstore 0, 0x3c62bac0, 0x9505324f, 0x51f0ab06, 0x19150ddf, 0xc3e8b70e, 0x1364b7d2, 0x23f469c, 0x9530f0f9; + mstore 32, 0x7618e309, 0x478abda9, 0x2f1fdc68, 0xe25b3285, 0x59b333e0, 0x34dd2f7f, 0x8f9f21e2, 0x8f3c305a; + + ec_double 0, 0; + + assert_eq 0, 0xdc3c9c8f, 0x6704385, 0x3e4367b2, 0xf2816fee, 0xaaa332b0, 0x6f09ff43, 0xbe4298fd, 0x67be02dc; + assert_eq 32, 0x593652d9, 0x55384998, 0xb88c2be, 0xcd993bf6, 0x8291693, 0xa2c945b6, 0x3e4def84, 0x7a9b55a7; + + mstore 0, 0xdc3c9c8f, 0x6704385, 0x3e4367b2, 0xf2816fee, 0xaaa332b0, 0x6f09ff43, 0xbe4298fd, 0x67be02dc; + mstore 32, 0x593652d9, 0x55384998, 0xb88c2be, 0xcd993bf6, 0x8291693, 0xa2c945b6, 0x3e4def84, 0x7a9b55a7; + + ec_double 0, 0; + + assert_eq 0, 0x10aaa33a, 0x11f9bcbe, 0xc17b9ca5, 0x8c92dd29, 0xbc571836, 0xdf569013, 0xf4ef876a, 0x893b2492; + assert_eq 32, 0xd1af3445, 0x67b80b8a, 0x13ceeb42, 0xa439e8a2, 0x66507f32, 0xf413a007, 0x72d1c89e, 0xcdb152b6; + + mstore 0, 0x10aaa33a, 0x11f9bcbe, 0xc17b9ca5, 0x8c92dd29, 0xbc571836, 0xdf569013, 0xf4ef876a, 0x893b2492; + mstore 32, 0xd1af3445, 0x67b80b8a, 0x13ceeb42, 0xa439e8a2, 0x66507f32, 0xf413a007, 0x72d1c89e, 0xcdb152b6; + + ec_double 0, 0; + + assert_eq 0, 0xf6e55dc8, 0x4b891216, 0xeaca0439, 0x6ff95ab6, 0xc0509442, 0xba84a440, 0x90c5ffb2, 0x44314047; + assert_eq 32, 0xdbe323b3, 0x31d944ae, 0x9eaa2e50, 0xa66a29b7, 0x5642fed7, 0xfe99837f, 0xe65366f8, 0x96b0c142; + + mstore 0, 0xf6e55dc8, 0x4b891216, 0xeaca0439, 0x6ff95ab6, 0xc0509442, 0xba84a440, 0x90c5ffb2, 0x44314047; + mstore 32, 0xdbe323b3, 0x31d944ae, 0x9eaa2e50, 0xa66a29b7, 0x5642fed7, 0xfe99837f, 0xe65366f8, 0x96b0c142; + + ec_double 0, 0; + + assert_eq 0, 0x33f0e9aa, 0x3eb5e196, 0xb11bd34b, 0x68112776, 0xd58138d2, 0xb7924ae0, 0x575f26ad, 0xe5380fe8; + assert_eq 32, 0x4082720f, 0xc4ba4136, 0xf468318e, 0x6fb94e5d, 0x924c8e01, 0x5b691363, 0x9087b41d, 0xb97fd873; + + mstore 0, 0x33f0e9aa, 0x3eb5e196, 0xb11bd34b, 0x68112776, 0xd58138d2, 0xb7924ae0, 0x575f26ad, 0xe5380fe8; + mstore 32, 0x4082720f, 0xc4ba4136, 0xf468318e, 0x6fb94e5d, 0x924c8e01, 0x5b691363, 0x9087b41d, 0xb97fd873; + + ec_double 0, 0; + + assert_eq 0, 0xeebc61d6, 0x1aed361b, 0xd9ff42de, 0x8a8fd3a7, 0x5d6b1f51, 0xc395f0d1, 0xa3ed9af0, 0x939ff3e4; + assert_eq 32, 0xa3f5cb70, 0xe75ea466, 0xb78c7f82, 0x980bf26e, 0xef016c04, 0x9d46fc4e, 0x8b7a90e, 0xdeab3bcf; + + mstore 0, 0xeebc61d6, 0x1aed361b, 0xd9ff42de, 0x8a8fd3a7, 0x5d6b1f51, 0xc395f0d1, 0xa3ed9af0, 0x939ff3e4; + mstore 32, 0xa3f5cb70, 0xe75ea466, 0xb78c7f82, 0x980bf26e, 0xef016c04, 0x9d46fc4e, 0x8b7a90e, 0xdeab3bcf; + + ec_double 0, 0; + + assert_eq 0, 0xc497e0df, 0x16e134d, 0xecf76f53, 0x4c3bb436, 0xfe6029a0, 0x7858785, 0xae383293, 0xfdc63e52; + assert_eq 32, 0xdb9eb19f, 0xf0604449, 0xbf35d9d5, 0x7bbeb22f, 0x8ae2e8b8, 0xe3df7142, 0xacebbb52, 0x292dad67; + + mstore 0, 0xc497e0df, 0x16e134d, 0xecf76f53, 0x4c3bb436, 0xfe6029a0, 0x7858785, 0xae383293, 0xfdc63e52; + mstore 32, 0xdb9eb19f, 0xf0604449, 0xbf35d9d5, 0x7bbeb22f, 0x8ae2e8b8, 0xe3df7142, 0xacebbb52, 0x292dad67; + + ec_double 0, 0; + + assert_eq 0, 0xf55812dd, 0xa0a2a582, 0x552d30e2, 0x3d446723, 0xc058f78e, 0xb6abed6, 0x92ff352f, 0x7029bd7a; + assert_eq 32, 0x1a2d2927, 0x721cc66b, 0x43b2c73c, 0x47dae842, 0xe30683ac, 0x7dd6544a, 0xfde8b3d2, 0xb0eefada; + + mstore 0, 0xf55812dd, 0xa0a2a582, 0x552d30e2, 0x3d446723, 0xc058f78e, 0xb6abed6, 0x92ff352f, 0x7029bd7a; + mstore 32, 0x1a2d2927, 0x721cc66b, 0x43b2c73c, 0x47dae842, 0xe30683ac, 0x7dd6544a, 0xfde8b3d2, 0xb0eefada; + + ec_double 0, 0; + + assert_eq 0, 0xb181fdc2, 0xdcdabff9, 0x5cc62364, 0xdd2f62bb, 0x18a34e7e, 0x4aa264b8, 0xf47e6e47, 0xf42c102a; + assert_eq 32, 0xa485d7fd, 0x81f00093, 0x9a2acf26, 0x4c15502d, 0xb86fe22a, 0x78fad05c, 0x6cfe806c, 0x57503ab4; + + mstore 0, 0xb181fdc2, 0xdcdabff9, 0x5cc62364, 0xdd2f62bb, 0x18a34e7e, 0x4aa264b8, 0xf47e6e47, 0xf42c102a; + mstore 32, 0xa485d7fd, 0x81f00093, 0x9a2acf26, 0x4c15502d, 0xb86fe22a, 0x78fad05c, 0x6cfe806c, 0x57503ab4; + + ec_double 0, 0; + + assert_eq 0, 0xeedd7dd6, 0x3866d47d, 0x65e1968c, 0x49376fe2, 0xee7cfdec, 0xca5a7840, 0x24c7524b, 0x32cfcf6a; + assert_eq 32, 0xfe08e330, 0x25fd44ae, 0x349a08b, 0x7a0d8cd2, 0x409f561e, 0x6208096a, 0x976a7748, 0x21846a34; + + mstore 0, 0xeedd7dd6, 0x3866d47d, 0x65e1968c, 0x49376fe2, 0xee7cfdec, 0xca5a7840, 0x24c7524b, 0x32cfcf6a; + mstore 32, 0xfe08e330, 0x25fd44ae, 0x349a08b, 0x7a0d8cd2, 0x409f561e, 0x6208096a, 0x976a7748, 0x21846a34; + + ec_double 0, 0; + + assert_eq 0, 0x21231d11, 0xce674831, 0x3c2aaad7, 0x22ab36c6, 0xc777c398, 0x33d1155c, 0x8b9388e4, 0x3514d41e; + assert_eq 32, 0xe3855df5, 0x53d6fb40, 0xaf79ebe, 0x9384f31d, 0x56839eff, 0xef44d11e, 0x16017eb8, 0x89a83250; + + mstore 0, 0x21231d11, 0xce674831, 0x3c2aaad7, 0x22ab36c6, 0xc777c398, 0x33d1155c, 0x8b9388e4, 0x3514d41e; + mstore 32, 0xe3855df5, 0x53d6fb40, 0xaf79ebe, 0x9384f31d, 0x56839eff, 0xef44d11e, 0x16017eb8, 0x89a83250; + + ec_double 0, 0; + + assert_eq 0, 0x80633cb1, 0x2567e09e, 0x69d02113, 0x575a224b, 0x12181fcb, 0xc62732, 0x17aacad4, 0x6dde9cf3; + assert_eq 32, 0x67ce6b34, 0x57dd49aa, 0xcf859ef3, 0x80b27fda, 0xa1ba66a8, 0x5c99ef86, 0xa707e41d, 0x9188fbe7; + + mstore 0, 0x80633cb1, 0x2567e09e, 0x69d02113, 0x575a224b, 0x12181fcb, 0xc62732, 0x17aacad4, 0x6dde9cf3; + mstore 32, 0x67ce6b34, 0x57dd49aa, 0xcf859ef3, 0x80b27fda, 0xa1ba66a8, 0x5c99ef86, 0xa707e41d, 0x9188fbe7; + + ec_double 0, 0; + + assert_eq 0, 0x44e5467d, 0x4d0bd76a, 0x19bbface, 0x40908ab8, 0xec970e9, 0x2c21f62e, 0xfc69a122, 0x97d064f0; + assert_eq 32, 0x1e9cb3fa, 0x797300fd, 0x54f17ccd, 0xda5fb3b8, 0xa850861f, 0x3f7c66f, 0xd33402cc, 0x89974f2e; + + mstore 0, 0x44e5467d, 0x4d0bd76a, 0x19bbface, 0x40908ab8, 0xec970e9, 0x2c21f62e, 0xfc69a122, 0x97d064f0; + mstore 32, 0x1e9cb3fa, 0x797300fd, 0x54f17ccd, 0xda5fb3b8, 0xa850861f, 0x3f7c66f, 0xd33402cc, 0x89974f2e; + + ec_double 0, 0; + + assert_eq 0, 0x13613bec, 0xcca81cb9, 0x101cfe67, 0x8bb5fc9d, 0xc74f972a, 0xedf1b33d, 0xc93937bd, 0x2dcfcab8; + assert_eq 32, 0x9a039215, 0x3e730924, 0xd33f5f38, 0x3732cfba, 0xd6f6c6f4, 0x65f088b7, 0x9474a412, 0x46dbc4dd; + + mstore 0, 0x13613bec, 0xcca81cb9, 0x101cfe67, 0x8bb5fc9d, 0xc74f972a, 0xedf1b33d, 0xc93937bd, 0x2dcfcab8; + mstore 32, 0x9a039215, 0x3e730924, 0xd33f5f38, 0x3732cfba, 0xd6f6c6f4, 0x65f088b7, 0x9474a412, 0x46dbc4dd; + + ec_double 0, 0; + + assert_eq 0, 0x47fb9e1a, 0x17cd1708, 0xde2a3296, 0x7fe74b74, 0xbbab0e76, 0xf1a02bc9, 0xa48ec5a8, 0x1bec414a; + assert_eq 32, 0x749c0443, 0x57f6e117, 0xe8c9796e, 0x681385da, 0x30c54b0f, 0x8a79bc57, 0x70126667, 0xe3586704; + + mstore 0, 0x47fb9e1a, 0x17cd1708, 0xde2a3296, 0x7fe74b74, 0xbbab0e76, 0xf1a02bc9, 0xa48ec5a8, 0x1bec414a; + mstore 32, 0x749c0443, 0x57f6e117, 0xe8c9796e, 0x681385da, 0x30c54b0f, 0x8a79bc57, 0x70126667, 0xe3586704; + + ec_double 0, 0; + + assert_eq 0, 0xbb7ceceb, 0xf3f678ff, 0x8897faf0, 0x73a59f93, 0x6f6e6814, 0x36ffb812, 0x4276d450, 0x437a8620; + assert_eq 32, 0x56c181e1, 0x7363bcc3, 0xdc8f9782, 0x87220fcf, 0x99d297ff, 0x69b8feb6, 0x3eeac32f, 0xb916ba1; + + mstore 0, 0xbb7ceceb, 0xf3f678ff, 0x8897faf0, 0x73a59f93, 0x6f6e6814, 0x36ffb812, 0x4276d450, 0x437a8620; + mstore 32, 0x56c181e1, 0x7363bcc3, 0xdc8f9782, 0x87220fcf, 0x99d297ff, 0x69b8feb6, 0x3eeac32f, 0xb916ba1; + + ec_double 0, 0; + + assert_eq 0, 0xdcbf00eb, 0x4c9d9d87, 0xc18d0227, 0x41b4e98b, 0xa1a30bc2, 0x49be16f6, 0x96ead4dc, 0xb89070ae; + assert_eq 32, 0x1b0e664e, 0x1b7f1bcd, 0xb6b96a67, 0xcb0d8b06, 0xc1c4a766, 0x472294e4, 0xc8a2d88f, 0x6f24c8c2; + + mstore 0, 0xdcbf00eb, 0x4c9d9d87, 0xc18d0227, 0x41b4e98b, 0xa1a30bc2, 0x49be16f6, 0x96ead4dc, 0xb89070ae; + mstore 32, 0x1b0e664e, 0x1b7f1bcd, 0xb6b96a67, 0xcb0d8b06, 0xc1c4a766, 0x472294e4, 0xc8a2d88f, 0x6f24c8c2; + + ec_double 0, 0; + + assert_eq 0, 0xb6fbe7b2, 0xb9d6ff9a, 0x458d65a3, 0x5eadedc1, 0xb2a88460, 0xf336bbb1, 0x9cb441f8, 0x26488766; + assert_eq 32, 0x21bc2a34, 0x932a78bc, 0x6a0eb603, 0x5638d981, 0xd02ddf18, 0x8f2f2dca, 0xb2014498, 0x9e15dab4; + + mstore 0, 0xb6fbe7b2, 0xb9d6ff9a, 0x458d65a3, 0x5eadedc1, 0xb2a88460, 0xf336bbb1, 0x9cb441f8, 0x26488766; + mstore 32, 0x21bc2a34, 0x932a78bc, 0x6a0eb603, 0x5638d981, 0xd02ddf18, 0x8f2f2dca, 0xb2014498, 0x9e15dab4; + + ec_double 0, 0; + + assert_eq 0, 0x2b038315, 0x9690d306, 0x69310e6f, 0x9cacc433, 0x9794b862, 0x1e4680e3, 0x56771222, 0xaba55687; + assert_eq 32, 0xae25fc0a, 0xf9a003f9, 0xd8b63338, 0x3fbfb532, 0x25130d6f, 0x63d570f6, 0xaa365edb, 0xa0e75d87; + + mstore 0, 0x2b038315, 0x9690d306, 0x69310e6f, 0x9cacc433, 0x9794b862, 0x1e4680e3, 0x56771222, 0xaba55687; + mstore 32, 0xae25fc0a, 0xf9a003f9, 0xd8b63338, 0x3fbfb532, 0x25130d6f, 0x63d570f6, 0xaa365edb, 0xa0e75d87; + + ec_double 0, 0; + + assert_eq 0, 0x95bc15b4, 0x9cb9a134, 0x465a2ee6, 0x9275028e, 0xced7ca8d, 0xed858ee9, 0x51eeadc9, 0x10e90e2e; + assert_eq 32, 0x58aa258d, 0x34ebe609, 0x2bb6a88, 0x4ca58963, 0x16ad1f75, 0x4d57a8c6, 0x80d5e042, 0xc68a3703; + + mstore 0, 0x95bc15b4, 0x9cb9a134, 0x465a2ee6, 0x9275028e, 0xced7ca8d, 0xed858ee9, 0x51eeadc9, 0x10e90e2e; + mstore 32, 0x58aa258d, 0x34ebe609, 0x2bb6a88, 0x4ca58963, 0x16ad1f75, 0x4d57a8c6, 0x80d5e042, 0xc68a3703; + + ec_double 0, 0; + + assert_eq 0, 0x7a1c0a80, 0xf62abc8, 0xc65a9c74, 0x4d625158, 0x2ff9c3, 0xb17c9be7, 0xa614cca5, 0xb6b15a68; + assert_eq 32, 0x41ce0a03, 0xb6cd0110, 0x82e16ee, 0x9c9a12b3, 0xef6536d4, 0xa54e223e, 0xd6cdb61e, 0xfae62e14; + + mstore 0, 0x7a1c0a80, 0xf62abc8, 0xc65a9c74, 0x4d625158, 0x2ff9c3, 0xb17c9be7, 0xa614cca5, 0xb6b15a68; + mstore 32, 0x41ce0a03, 0xb6cd0110, 0x82e16ee, 0x9c9a12b3, 0xef6536d4, 0xa54e223e, 0xd6cdb61e, 0xfae62e14; + + ec_double 0, 0; + + assert_eq 0, 0x92b062d4, 0xa7caa50a, 0x9bb6a141, 0x7a5ce7e5, 0x83ea227a, 0x6fb1712, 0x3256eaca, 0x35963ea4; + assert_eq 32, 0xbbb25302, 0xa10aa4d1, 0x64de59b1, 0xd04082b9, 0xf9c08a96, 0xbfcce196, 0x4951e5c9, 0xf65be145; + + mstore 0, 0x92b062d4, 0xa7caa50a, 0x9bb6a141, 0x7a5ce7e5, 0x83ea227a, 0x6fb1712, 0x3256eaca, 0x35963ea4; + mstore 32, 0xbbb25302, 0xa10aa4d1, 0x64de59b1, 0xd04082b9, 0xf9c08a96, 0xbfcce196, 0x4951e5c9, 0xf65be145; + + ec_double 0, 0; + + assert_eq 0, 0x1d33fd27, 0xfa0bf5c5, 0xb646cc62, 0x445f573d, 0xda82361b, 0xd022388e, 0x2263e84c, 0x9ed73f09; + assert_eq 32, 0x2716c458, 0x5972b2de, 0xb2e44934, 0x94a823e5, 0x42467254, 0xee75b4f3, 0xebb1eeea, 0xb6318967; + + mstore 0, 0x1d33fd27, 0xfa0bf5c5, 0xb646cc62, 0x445f573d, 0xda82361b, 0xd022388e, 0x2263e84c, 0x9ed73f09; + mstore 32, 0x2716c458, 0x5972b2de, 0xb2e44934, 0x94a823e5, 0x42467254, 0xee75b4f3, 0xebb1eeea, 0xb6318967; + + ec_double 0, 0; + + assert_eq 0, 0xef028d83, 0x579623ae, 0xba743961, 0x6195926d, 0x15de69db, 0x6a5abe5a, 0xe3c785ec, 0xa7ebf7c4; + assert_eq 32, 0x99d0bed1, 0x9640392b, 0x4b053919, 0x47a38927, 0x7044804b, 0xcfd9c737, 0xbfe362d5, 0x6205152f; + + mstore 0, 0xef028d83, 0x579623ae, 0xba743961, 0x6195926d, 0x15de69db, 0x6a5abe5a, 0xe3c785ec, 0xa7ebf7c4; + mstore 32, 0x99d0bed1, 0x9640392b, 0x4b053919, 0x47a38927, 0x7044804b, 0xcfd9c737, 0xbfe362d5, 0x6205152f; + + ec_double 0, 0; + + assert_eq 0, 0x7bb61ee5, 0xf2884413, 0xfb1f0c13, 0xda4f04e2, 0x8974ae6e, 0x662638cd, 0xcc8721b8, 0xd4933230; + assert_eq 32, 0xe5d694a8, 0x662da4d0, 0x5a438ddc, 0x1ad12c8c, 0x1ecafb5e, 0xedcc5e9d, 0xf51a9d23, 0x21c09ab; + + mstore 0, 0x7bb61ee5, 0xf2884413, 0xfb1f0c13, 0xda4f04e2, 0x8974ae6e, 0x662638cd, 0xcc8721b8, 0xd4933230; + mstore 32, 0xe5d694a8, 0x662da4d0, 0x5a438ddc, 0x1ad12c8c, 0x1ecafb5e, 0xedcc5e9d, 0xf51a9d23, 0x21c09ab; + + ec_double 0, 0; + + assert_eq 0, 0xec04554a, 0x530ddcbc, 0x4688cffe, 0xaadcffbb, 0x7a10a2ec, 0x474652c2, 0x9873d1a0, 0x896f37c8; + assert_eq 32, 0x929138df, 0xd68f9fe1, 0xacc417dc, 0xe6085b61, 0x4e811bf1, 0xda622bb0, 0x224ac4ac, 0x380423e7; + + mstore 0, 0xec04554a, 0x530ddcbc, 0x4688cffe, 0xaadcffbb, 0x7a10a2ec, 0x474652c2, 0x9873d1a0, 0x896f37c8; + mstore 32, 0x929138df, 0xd68f9fe1, 0xacc417dc, 0xe6085b61, 0x4e811bf1, 0xda622bb0, 0x224ac4ac, 0x380423e7; + + ec_double 0, 0; + + assert_eq 0, 0xb43fca26, 0x84077d1a, 0xa3bc2367, 0x7dfb841d, 0xbf3578a2, 0xca6c209d, 0x774b6d6c, 0x11b3b97f; + assert_eq 32, 0x5b679d58, 0xd3b27eaf, 0x4b9f9d42, 0x3bae231c, 0x2f36d3bb, 0x8cd5650c, 0xae600c50, 0x65331f9f; + + mstore 0, 0xb43fca26, 0x84077d1a, 0xa3bc2367, 0x7dfb841d, 0xbf3578a2, 0xca6c209d, 0x774b6d6c, 0x11b3b97f; + mstore 32, 0x5b679d58, 0xd3b27eaf, 0x4b9f9d42, 0x3bae231c, 0x2f36d3bb, 0x8cd5650c, 0xae600c50, 0x65331f9f; + + ec_double 0, 0; + + assert_eq 0, 0x48dfd587, 0x79361bb, 0xc9b02656, 0x5ec4ba38, 0x2cf5a12d, 0x34867aaa, 0xacf4508b, 0x5084b41b; + assert_eq 32, 0x91470e89, 0x6e79e97f, 0x6891f560, 0x5db6f560, 0x55292747, 0x619aa6c8, 0x1d980d31, 0x34a9631a; + + mstore 0, 0x48dfd587, 0x79361bb, 0xc9b02656, 0x5ec4ba38, 0x2cf5a12d, 0x34867aaa, 0xacf4508b, 0x5084b41b; + mstore 32, 0x91470e89, 0x6e79e97f, 0x6891f560, 0x5db6f560, 0x55292747, 0x619aa6c8, 0x1d980d31, 0x34a9631a; + + ec_double 0, 0; + + assert_eq 0, 0x6c953fa9, 0x4d05956d, 0xf0b8c3db, 0x28ab2629, 0x4bd18c06, 0x3a5f485d, 0xaaab9323, 0xa49ed10e; + assert_eq 32, 0x46fb4c72, 0x67b2bd22, 0x968e181b, 0x5ae87534, 0xa0dfddfb, 0xe03476c0, 0x660f5398, 0xcc72b894; + + mstore 0, 0x60297556, 0x2f057a14, 0x8568a18b, 0x82f6472f, 0x355235d3, 0x20453a14, 0x755eeea4, 0xfff97bd5; + mstore 32, 0xb075f297, 0x3c870c36, 0x518fe4a0, 0xde80f0f6, 0x7f45c560, 0xf3be9601, 0xacfbb620, 0xae12777a; + mstore 64, 0x6c953fa9, 0x4d05956d, 0xf0b8c3db, 0x28ab2629, 0x4bd18c06, 0x3a5f485d, 0xaaab9323, 0xa49ed10e; + mstore 96, 0x46fb4c72, 0x67b2bd22, 0x968e181b, 0x5ae87534, 0xa0dfddfb, 0xe03476c0, 0x660f5398, 0xcc72b894; + + ec_add 0, 64, 0; + + assert_eq 0, 0x23510ef9, 0xbb3af611, 0xf22c19c7, 0x87d4c3cb, 0x53cecf40, 0xd11823c1, 0xdc6f9ec5, 0xe12026ef; + assert_eq 32, 0xb058f360, 0x96451fbb, 0x20e5efc6, 0xdcda7f72, 0xe03ad137, 0xf367ef20, 0x5a51eadc, 0x30a930ea; + + mstore 0, 0x70afe85a, 0xc5b0f470, 0x9620095b, 0x687cf441, 0x4d734633, 0x15c38f00, 0x48e7561b, 0xd01115d5; + mstore 32, 0xf4062327, 0x6b051b13, 0xd9a86d52, 0x79238c5d, 0xe17bd815, 0xa8b64537, 0xc815e0d7, 0xa9f34ffd; + mstore 64, 0x23510ef9, 0xbb3af611, 0xf22c19c7, 0x87d4c3cb, 0x53cecf40, 0xd11823c1, 0xdc6f9ec5, 0xe12026ef; + mstore 96, 0xb058f360, 0x96451fbb, 0x20e5efc6, 0xdcda7f72, 0xe03ad137, 0xf367ef20, 0x5a51eadc, 0x30a930ea; + + ec_add 0, 64, 0; + + assert_eq 0, 0xaee8b7f4, 0xbfd2ecb4, 0xe21c31ef, 0x22c7841e, 0x2da82592, 0x7d356af0, 0x64eab6f5, 0xd5ae772d; + assert_eq 32, 0x454d87bc, 0x18cf6cf2, 0xe498d098, 0x8d035085, 0x121f031d, 0x43b132ac, 0x313a838a, 0x10231a1d; + + mstore 0, 0xb202e6ce, 0x502bda8, 0x9d62b794, 0x68321543, 0x61ba8b09, 0x8ac09c91, 0x413d33d4, 0xfe72c435; + mstore 32, 0xcf58c5bf, 0x978ed2fb, 0x6b4a9d22, 0x1dc88e3, 0x9d729981, 0xd3ab47e0, 0x7ff24a68, 0x6851de06; + mstore 64, 0xaee8b7f4, 0xbfd2ecb4, 0xe21c31ef, 0x22c7841e, 0x2da82592, 0x7d356af0, 0x64eab6f5, 0xd5ae772d; + mstore 96, 0x454d87bc, 0x18cf6cf2, 0xe498d098, 0x8d035085, 0x121f031d, 0x43b132ac, 0x313a838a, 0x10231a1d; + + ec_add 0, 64, 0; + + assert_eq 0, 0x29f01588, 0x47a519de, 0x80b7983e, 0xe3a17625, 0xc7a542b9, 0x2c03e1b0, 0xd5ba06de, 0xf952de32; + assert_eq 32, 0x96452adf, 0xcc4f6b5a, 0xa0593002, 0x1ebbb2bb, 0x49fb7433, 0xee209edb, 0x9e3a6edb, 0x23c02d3; + + mstore 0, 0x1118e5c3, 0x9bd870aa, 0x452bebc1, 0xfc579b27, 0xf4e65b4b, 0xb441656e, 0x9645307d, 0x6eca335d; + mstore 32, 0x5a08668, 0x498a2f78, 0x3bf8ec34, 0x3a496a3a, 0x74b875a0, 0x592f5790, 0x7a7a0710, 0xd50123b5; + mstore 64, 0x29f01588, 0x47a519de, 0x80b7983e, 0xe3a17625, 0xc7a542b9, 0x2c03e1b0, 0xd5ba06de, 0xf952de32; + mstore 96, 0x96452adf, 0xcc4f6b5a, 0xa0593002, 0x1ebbb2bb, 0x49fb7433, 0xee209edb, 0x9e3a6edb, 0x23c02d3; + + ec_add 0, 64, 0; + + assert_eq 0, 0x170508d7, 0x5137b67a, 0xfec94132, 0xacb18631, 0xca0ddf6b, 0xa9f0b9c1, 0x59982afe, 0x19d6a989; + assert_eq 32, 0x311ed142, 0xacf14bf8, 0x9cdeddfc, 0xa372ada, 0x47016a3d, 0xe73aacf, 0xa468f4db, 0x221a2b52; + + mstore 0, 0x7f8cb0e3, 0x43933aca, 0xe1efe3a4, 0xa22eb53f, 0x4b2eb72e, 0x8fa64e04, 0x74456d8f, 0x3f0e80e5; + mstore 32, 0xea5f404f, 0xcb0289e2, 0xa65b53a4, 0x9501253a, 0x485d01b3, 0xe90b9c08, 0x296cbc91, 0xcb66d7d7; + mstore 64, 0x170508d7, 0x5137b67a, 0xfec94132, 0xacb18631, 0xca0ddf6b, 0xa9f0b9c1, 0x59982afe, 0x19d6a989; + mstore 96, 0x311ed142, 0xacf14bf8, 0x9cdeddfc, 0xa372ada, 0x47016a3d, 0xe73aacf, 0xa468f4db, 0x221a2b52; + + ec_add 0, 64, 0; + + assert_eq 0, 0xb4774055, 0x3beba8b, 0x1e5354e0, 0x390e80f2, 0x84fe6b81, 0x7da29ade, 0x873a0892, 0x9e60108; + assert_eq 32, 0xe91c37b4, 0x1f4b0a9e, 0xa0f5c9df, 0xf8b46cf3, 0xa2e33e67, 0xdd6c49ac, 0x8cc23a00, 0xb16a1638; + + mstore 0, 0x33ce1752, 0xc7b750f7, 0xd7cd204e, 0xe783c797, 0xd99c9aea, 0x812ddf64, 0xd01dc635, 0xd7a0da58; + mstore 32, 0x762cef4, 0xbbc02738, 0xc062b742, 0xbe040a8, 0x40e28465, 0xf6f29283, 0x68008032, 0x912770e0; + mstore 64, 0xb4774055, 0x3beba8b, 0x1e5354e0, 0x390e80f2, 0x84fe6b81, 0x7da29ade, 0x873a0892, 0x9e60108; + mstore 96, 0xe91c37b4, 0x1f4b0a9e, 0xa0f5c9df, 0xf8b46cf3, 0xa2e33e67, 0xdd6c49ac, 0x8cc23a00, 0xb16a1638; + + ec_add 0, 64, 0; + + assert_eq 0, 0xb2993603, 0x84fd71bd, 0x35e25ff7, 0x1077370c, 0x5867e485, 0x9edfb935, 0xd0b48228, 0x2de4cdc; + assert_eq 32, 0xf3c18392, 0xd7b138d4, 0xa44f7f11, 0x1bd09b1d, 0x87477348, 0x53396a92, 0xc1c97199, 0x18b5caf6; + + mstore 0, 0xb5476085, 0xa908b701, 0x96eb9f84, 0xb5714e77, 0xa78ed1af, 0x10d3aad6, 0x7a08cd3e, 0x3443a706; + mstore 32, 0x8b8f52d8, 0x6d3484bd, 0xd0c2b67f, 0x18a4b27, 0x8c7e1da9, 0x4f6e8c4b, 0x829b6f85, 0x661a7a5f; + mstore 64, 0xb2993603, 0x84fd71bd, 0x35e25ff7, 0x1077370c, 0x5867e485, 0x9edfb935, 0xd0b48228, 0x2de4cdc; + mstore 96, 0xf3c18392, 0xd7b138d4, 0xa44f7f11, 0x1bd09b1d, 0x87477348, 0x53396a92, 0xc1c97199, 0x18b5caf6; + + ec_add 0, 64, 0; + + assert_eq 0, 0x694478f1, 0xb4fb31d0, 0x639a1309, 0xe3af2921, 0x8069c19c, 0xcea090c4, 0xdb4efc49, 0x2ce2bd56; + assert_eq 32, 0xc94a43b7, 0xdb966e56, 0xa8a289c1, 0x166b72, 0xe9560522, 0x78291fe1, 0x3d95a2e2, 0xb56a711; + + mstore 0, 0xe57e8dfa, 0xfcfc0cb9, 0xa3c7e184, 0x9809191, 0xaca98ca0, 0xd9a30f8, 0xf0799c4c, 0x8262cf2f; + mstore 32, 0xfbac376a, 0x35cff8d8, 0x2b14c478, 0x57b6ed33, 0xc5b34f34, 0x66fee22e, 0x9109e4e, 0x83fd95e2; + mstore 64, 0x694478f1, 0xb4fb31d0, 0x639a1309, 0xe3af2921, 0x8069c19c, 0xcea090c4, 0xdb4efc49, 0x2ce2bd56; + mstore 96, 0xc94a43b7, 0xdb966e56, 0xa8a289c1, 0x166b72, 0xe9560522, 0x78291fe1, 0x3d95a2e2, 0xb56a711; + + ec_add 0, 64, 0; + + assert_eq 0, 0x44ad3367, 0x9aeb9669, 0x637f77d7, 0xc3a1a0e7, 0x6964096c, 0xdf790607, 0x3e8509c2, 0xab7527e3; + assert_eq 32, 0xba33e3e9, 0xc844b48d, 0xda415aa3, 0xc572928e, 0xa95cf18e, 0x4778ec33, 0xfa8b39, 0xfac5ff0c; + + mstore 0, 0x7c70620c, 0xd17cc1f2, 0xabc288d9, 0x4998c4be, 0x2b671780, 0xc60dd31a, 0x8d2c236d, 0x1653a8a4; + mstore 32, 0x315b32cd, 0x6ca2e81d, 0xdfd3dc52, 0x12af748, 0x4efa701c, 0xeafa9947, 0x35af7f7a, 0x3382909; + mstore 64, 0x44ad3367, 0x9aeb9669, 0x637f77d7, 0xc3a1a0e7, 0x6964096c, 0xdf790607, 0x3e8509c2, 0xab7527e3; + mstore 96, 0xba33e3e9, 0xc844b48d, 0xda415aa3, 0xc572928e, 0xa95cf18e, 0x4778ec33, 0xfa8b39, 0xfac5ff0c; + + ec_add 0, 64, 0; + + assert_eq 0, 0x344d1571, 0xfbc3a3ed, 0x6d037843, 0xd86e1c94, 0xb24f4644, 0x3c6685fd, 0xb14dbaa6, 0xd4632e2b; + assert_eq 32, 0xb26ac915, 0x57c30d45, 0xa60c041f, 0xaff15cc2, 0x76a49ec0, 0x2e672992, 0xed49e170, 0x5b7067; + + mstore 0, 0xe71dabcd, 0x47d42ba6, 0x89e5cb4f, 0x54d3fe49, 0x60b5373f, 0x6098ae32, 0x6b63f43c, 0xd49ee4fb; + mstore 32, 0x16603c2, 0xe66a90cf, 0x12ff7031, 0x129c5093, 0xa61bf356, 0xd7c87ea7, 0x9a5490d, 0x531e392; + mstore 64, 0x344d1571, 0xfbc3a3ed, 0x6d037843, 0xd86e1c94, 0xb24f4644, 0x3c6685fd, 0xb14dbaa6, 0xd4632e2b; + mstore 96, 0xb26ac915, 0x57c30d45, 0xa60c041f, 0xaff15cc2, 0x76a49ec0, 0x2e672992, 0xed49e170, 0x5b7067; + + ec_add 0, 64, 0; + + assert_eq 0, 0xdbe47240, 0xf2ee698, 0xb9575b37, 0xe2d2cfe2, 0x4a09b9d5, 0xbfe560fa, 0xaf3c4f5c, 0xb311519d; + assert_eq 32, 0x66c734da, 0x1147627c, 0xa4e7d38c, 0x41bf546d, 0xa86dd053, 0xbd7ee596, 0x65390183, 0xe8608078; + + mstore 0, 0xc8c828a, 0x53f30ab9, 0xc96ae41f, 0x132eb242, 0x17e81c75, 0xe44a0d8, 0xa4149e75, 0x5f94851c; + mstore 32, 0x37344d80, 0xbfeb0a3f, 0x4fc68b04, 0x8c66df75, 0x8882f35e, 0xe5f0797d, 0xafa1fee8, 0x26b8c3b8; + mstore 64, 0xdbe47240, 0xf2ee698, 0xb9575b37, 0xe2d2cfe2, 0x4a09b9d5, 0xbfe560fa, 0xaf3c4f5c, 0xb311519d; + mstore 96, 0x66c734da, 0x1147627c, 0xa4e7d38c, 0x41bf546d, 0xa86dd053, 0xbd7ee596, 0x65390183, 0xe8608078; + + ec_add 0, 64, 0; + + assert_eq 0, 0x7950604f, 0x3904da0a, 0x8d3a8c08, 0x7f74a2e8, 0x5270445, 0x70f70734, 0x3ca5ebf9, 0xa4da524a; + assert_eq 32, 0xe01e4087, 0x6f2bfded, 0x85e258c9, 0xb7498e0b, 0x51ab50dd, 0x1cb690a9, 0xae9bf4bc, 0x3bc500fb; + + mstore 0, 0xc5041216, 0x65b7f8f1, 0x842b836a, 0x3f7335f6, 0xdc2fed52, 0x128b59ef, 0x21f7acf4, 0xda75317b; + mstore 32, 0x6e708572, 0xdaed3298, 0xe77aceda, 0xe9aac07a, 0x342d7fc6, 0xdf19e21b, 0xbf72d5f0, 0x73f8a046; + mstore 64, 0x7950604f, 0x3904da0a, 0x8d3a8c08, 0x7f74a2e8, 0x5270445, 0x70f70734, 0x3ca5ebf9, 0xa4da524a; + mstore 96, 0xe01e4087, 0x6f2bfded, 0x85e258c9, 0xb7498e0b, 0x51ab50dd, 0x1cb690a9, 0xae9bf4bc, 0x3bc500fb; + + ec_add 0, 64, 0; + + assert_eq 0, 0x84b81f7f, 0xf0507d87, 0xa12969d7, 0xee9f7214, 0x1d049f95, 0xddb232b2, 0x640741b1, 0x448316e7; + assert_eq 32, 0x5e2540f7, 0x3630d948, 0xb351e0f, 0x43ce853a, 0x803089f2, 0x692ec20e, 0x29d5008f, 0xf4bf3660; + + mstore 0, 0x3c62bac0, 0x9505324f, 0x51f0ab06, 0x19150ddf, 0xc3e8b70e, 0x1364b7d2, 0x23f469c, 0x9530f0f9; + mstore 32, 0x7618e309, 0x478abda9, 0x2f1fdc68, 0xe25b3285, 0x59b333e0, 0x34dd2f7f, 0x8f9f21e2, 0x8f3c305a; + mstore 64, 0x84b81f7f, 0xf0507d87, 0xa12969d7, 0xee9f7214, 0x1d049f95, 0xddb232b2, 0x640741b1, 0x448316e7; + mstore 96, 0x5e2540f7, 0x3630d948, 0xb351e0f, 0x43ce853a, 0x803089f2, 0x692ec20e, 0x29d5008f, 0xf4bf3660; + + ec_add 0, 64, 0; + + assert_eq 0, 0xc37466d3, 0x1258ebbc, 0x79fac61e, 0x5911c69b, 0x594aefa8, 0x6a450d16, 0xb5da30ac, 0xebee8e11; + assert_eq 32, 0xaf04f45f, 0x99500512, 0xde6da3c0, 0xd8a47486, 0x8facdfd6, 0xab96ea50, 0xcc61f51d, 0x5c523787; + + mstore 0, 0xdc3c9c8f, 0x6704385, 0x3e4367b2, 0xf2816fee, 0xaaa332b0, 0x6f09ff43, 0xbe4298fd, 0x67be02dc; + mstore 32, 0x593652d9, 0x55384998, 0xb88c2be, 0xcd993bf6, 0x8291693, 0xa2c945b6, 0x3e4def84, 0x7a9b55a7; + mstore 64, 0xc37466d3, 0x1258ebbc, 0x79fac61e, 0x5911c69b, 0x594aefa8, 0x6a450d16, 0xb5da30ac, 0xebee8e11; + mstore 96, 0xaf04f45f, 0x99500512, 0xde6da3c0, 0xd8a47486, 0x8facdfd6, 0xab96ea50, 0xcc61f51d, 0x5c523787; + + ec_add 0, 64, 0; + + assert_eq 0, 0xa0aae439, 0x4f4c07cf, 0x89c4c360, 0x6f99cc22, 0x11576d96, 0x536674ab, 0xaa9cf13d, 0x9d9c34cc; + assert_eq 32, 0xb57534d9, 0xab01d669, 0xa1e9a5a7, 0xcd33ec53, 0x421d0474, 0x399ae585, 0x40a53d7d, 0xd9c7c978; + + mstore 0, 0x10aaa33a, 0x11f9bcbe, 0xc17b9ca5, 0x8c92dd29, 0xbc571836, 0xdf569013, 0xf4ef876a, 0x893b2492; + mstore 32, 0xd1af3445, 0x67b80b8a, 0x13ceeb42, 0xa439e8a2, 0x66507f32, 0xf413a007, 0x72d1c89e, 0xcdb152b6; + mstore 64, 0xa0aae439, 0x4f4c07cf, 0x89c4c360, 0x6f99cc22, 0x11576d96, 0x536674ab, 0xaa9cf13d, 0x9d9c34cc; + mstore 96, 0xb57534d9, 0xab01d669, 0xa1e9a5a7, 0xcd33ec53, 0x421d0474, 0x399ae585, 0x40a53d7d, 0xd9c7c978; + + ec_add 0, 64, 0; + + assert_eq 0, 0x61dec56, 0xc3d986b6, 0x3fa64819, 0xa346dbb9, 0x5106c8a, 0xcf195055, 0x89c4b6c0, 0x4d83a5c; + assert_eq 32, 0xde60d2c4, 0x28c617d, 0xbc06b39, 0x3ed8a31f, 0x85df1f33, 0xb8f6d515, 0x5a0b2233, 0xcf911e0f; + + mstore 0, 0xf6e55dc8, 0x4b891216, 0xeaca0439, 0x6ff95ab6, 0xc0509442, 0xba84a440, 0x90c5ffb2, 0x44314047; + mstore 32, 0xdbe323b3, 0x31d944ae, 0x9eaa2e50, 0xa66a29b7, 0x5642fed7, 0xfe99837f, 0xe65366f8, 0x96b0c142; + mstore 64, 0x61dec56, 0xc3d986b6, 0x3fa64819, 0xa346dbb9, 0x5106c8a, 0xcf195055, 0x89c4b6c0, 0x4d83a5c; + mstore 96, 0xde60d2c4, 0x28c617d, 0xbc06b39, 0x3ed8a31f, 0x85df1f33, 0xb8f6d515, 0x5a0b2233, 0xcf911e0f; + + ec_add 0, 64, 0; + + assert_eq 0, 0x11b05bca, 0x2a7f5d14, 0x3949a197, 0xb9db55f0, 0xb966688, 0x13962410, 0xbbc05a67, 0x6ed24224; + assert_eq 32, 0x8e241ae8, 0x38555bc9, 0xdc0cc527, 0x55bb4406, 0xd4c00fb5, 0x447a0f71, 0xf36480ac, 0x5160ba0; + + mstore 0, 0x33f0e9aa, 0x3eb5e196, 0xb11bd34b, 0x68112776, 0xd58138d2, 0xb7924ae0, 0x575f26ad, 0xe5380fe8; + mstore 32, 0x4082720f, 0xc4ba4136, 0xf468318e, 0x6fb94e5d, 0x924c8e01, 0x5b691363, 0x9087b41d, 0xb97fd873; + mstore 64, 0x11b05bca, 0x2a7f5d14, 0x3949a197, 0xb9db55f0, 0xb966688, 0x13962410, 0xbbc05a67, 0x6ed24224; + mstore 96, 0x8e241ae8, 0x38555bc9, 0xdc0cc527, 0x55bb4406, 0xd4c00fb5, 0x447a0f71, 0xf36480ac, 0x5160ba0; + + ec_add 0, 64, 0; + + assert_eq 0, 0x6522cef6, 0xf3e9afc9, 0x3f587dda, 0xac84eab3, 0xa8c2e75d, 0x14466cd4, 0x17b57b58, 0x6d663b77; + assert_eq 32, 0x4564c5a4, 0x827c89b6, 0xe66d0671, 0xff99027c, 0xa69fd33b, 0x4325889a, 0xa57f3c05, 0xd69cf941; + + mstore 0, 0xeebc61d6, 0x1aed361b, 0xd9ff42de, 0x8a8fd3a7, 0x5d6b1f51, 0xc395f0d1, 0xa3ed9af0, 0x939ff3e4; + mstore 32, 0xa3f5cb70, 0xe75ea466, 0xb78c7f82, 0x980bf26e, 0xef016c04, 0x9d46fc4e, 0x8b7a90e, 0xdeab3bcf; + mstore 64, 0x6522cef6, 0xf3e9afc9, 0x3f587dda, 0xac84eab3, 0xa8c2e75d, 0x14466cd4, 0x17b57b58, 0x6d663b77; + mstore 96, 0x4564c5a4, 0x827c89b6, 0xe66d0671, 0xff99027c, 0xa69fd33b, 0x4325889a, 0xa57f3c05, 0xd69cf941; + + ec_add 0, 64, 0; + + assert_eq 0, 0xc75826ca, 0x64c7ca6, 0xc829e086, 0xdc2329c, 0xff69f2ec, 0xa840f259, 0x40689eac, 0xf80118d; + assert_eq 32, 0x49b394f1, 0x49420a27, 0xaecd9f53, 0xc5f848b0, 0x8658a660, 0x1e5fa185, 0x9fd2f732, 0xb518b863; + + mstore 0, 0xc497e0df, 0x16e134d, 0xecf76f53, 0x4c3bb436, 0xfe6029a0, 0x7858785, 0xae383293, 0xfdc63e52; + mstore 32, 0xdb9eb19f, 0xf0604449, 0xbf35d9d5, 0x7bbeb22f, 0x8ae2e8b8, 0xe3df7142, 0xacebbb52, 0x292dad67; + mstore 64, 0xc75826ca, 0x64c7ca6, 0xc829e086, 0xdc2329c, 0xff69f2ec, 0xa840f259, 0x40689eac, 0xf80118d; + mstore 96, 0x49b394f1, 0x49420a27, 0xaecd9f53, 0xc5f848b0, 0x8658a660, 0x1e5fa185, 0x9fd2f732, 0xb518b863; + + ec_add 0, 64, 0; + + assert_eq 0, 0x5d52bd3b, 0xd260a04e, 0xe527dc75, 0x41a7866d, 0xba1eb327, 0x1cc02fa9, 0xf290ba01, 0x1d931895; + assert_eq 32, 0x54a028f0, 0x8a9692c7, 0xdd90d86a, 0xd007d5eb, 0x8ef4581a, 0xcb5c9f55, 0xfd528566, 0x17e3d9dd; + + mstore 0, 0xf55812dd, 0xa0a2a582, 0x552d30e2, 0x3d446723, 0xc058f78e, 0xb6abed6, 0x92ff352f, 0x7029bd7a; + mstore 32, 0x1a2d2927, 0x721cc66b, 0x43b2c73c, 0x47dae842, 0xe30683ac, 0x7dd6544a, 0xfde8b3d2, 0xb0eefada; + mstore 64, 0x5d52bd3b, 0xd260a04e, 0xe527dc75, 0x41a7866d, 0xba1eb327, 0x1cc02fa9, 0xf290ba01, 0x1d931895; + mstore 96, 0x54a028f0, 0x8a9692c7, 0xdd90d86a, 0xd007d5eb, 0x8ef4581a, 0xcb5c9f55, 0xfd528566, 0x17e3d9dd; + + ec_add 0, 64, 0; + + assert_eq 0, 0xb054c95a, 0xbcd8f87c, 0xb25e5d80, 0x459c9fcc, 0x1674b8f, 0x516609ce, 0x7cc748c, 0x2f6c48fd; + assert_eq 32, 0x9bef73d9, 0x89dc0133, 0x19da7c6, 0xd2d4e81d, 0xada47bd1, 0xc91bfe10, 0x4a947582, 0x6633d51b; + + mstore 0, 0xb181fdc2, 0xdcdabff9, 0x5cc62364, 0xdd2f62bb, 0x18a34e7e, 0x4aa264b8, 0xf47e6e47, 0xf42c102a; + mstore 32, 0xa485d7fd, 0x81f00093, 0x9a2acf26, 0x4c15502d, 0xb86fe22a, 0x78fad05c, 0x6cfe806c, 0x57503ab4; + mstore 64, 0xb054c95a, 0xbcd8f87c, 0xb25e5d80, 0x459c9fcc, 0x1674b8f, 0x516609ce, 0x7cc748c, 0x2f6c48fd; + mstore 96, 0x9bef73d9, 0x89dc0133, 0x19da7c6, 0xd2d4e81d, 0xada47bd1, 0xc91bfe10, 0x4a947582, 0x6633d51b; + + ec_add 0, 64, 0; + + assert_eq 0, 0x7cf01352, 0x3fca8944, 0xc3b91a98, 0x47e08381, 0xc5409be0, 0x48662b2e, 0x51b3b0dd, 0x331795e5; + assert_eq 32, 0x87069ca1, 0xb6fba74, 0xa10b410a, 0x866f98f, 0x5f2a5ed2, 0xa0afcbbe, 0x3f7674bd, 0x515daa7f; + + mstore 0, 0xeedd7dd6, 0x3866d47d, 0x65e1968c, 0x49376fe2, 0xee7cfdec, 0xca5a7840, 0x24c7524b, 0x32cfcf6a; + mstore 32, 0xfe08e330, 0x25fd44ae, 0x349a08b, 0x7a0d8cd2, 0x409f561e, 0x6208096a, 0x976a7748, 0x21846a34; + mstore 64, 0x7cf01352, 0x3fca8944, 0xc3b91a98, 0x47e08381, 0xc5409be0, 0x48662b2e, 0x51b3b0dd, 0x331795e5; + mstore 96, 0x87069ca1, 0xb6fba74, 0xa10b410a, 0x866f98f, 0x5f2a5ed2, 0xa0afcbbe, 0x3f7674bd, 0x515daa7f; + + ec_add 0, 64, 0; + + assert_eq 0, 0x472a1fd3, 0x3020c90, 0x8e1aca3, 0xc31a79e1, 0x633ce07, 0x73ea1256, 0xef361199, 0x63f74113; + assert_eq 32, 0x48050037, 0x1b081bdc, 0x8371f934, 0xd3405d6b, 0x3b8c2882, 0xdf0fd90a, 0x730bdfce, 0x83b14db6; + + mstore 0, 0x21231d11, 0xce674831, 0x3c2aaad7, 0x22ab36c6, 0xc777c398, 0x33d1155c, 0x8b9388e4, 0x3514d41e; + mstore 32, 0xe3855df5, 0x53d6fb40, 0xaf79ebe, 0x9384f31d, 0x56839eff, 0xef44d11e, 0x16017eb8, 0x89a83250; + mstore 64, 0x472a1fd3, 0x3020c90, 0x8e1aca3, 0xc31a79e1, 0x633ce07, 0x73ea1256, 0xef361199, 0x63f74113; + mstore 96, 0x48050037, 0x1b081bdc, 0x8371f934, 0xd3405d6b, 0x3b8c2882, 0xdf0fd90a, 0x730bdfce, 0x83b14db6; + + ec_add 0, 64, 0; + + assert_eq 0, 0xa38fb89e, 0x72d6446a, 0xe51dd73e, 0x15410f1, 0xb5a38c2f, 0x99eade1f, 0x3f79e108, 0xfb202e0f; + assert_eq 32, 0xcde0a70a, 0x5999a198, 0xb48c34b6, 0x343ea4ea, 0xcdb51927, 0x89aafe43, 0x4580257c, 0x5f924734; + + mstore 0, 0x80633cb1, 0x2567e09e, 0x69d02113, 0x575a224b, 0x12181fcb, 0xc62732, 0x17aacad4, 0x6dde9cf3; + mstore 32, 0x67ce6b34, 0x57dd49aa, 0xcf859ef3, 0x80b27fda, 0xa1ba66a8, 0x5c99ef86, 0xa707e41d, 0x9188fbe7; + mstore 64, 0xa38fb89e, 0x72d6446a, 0xe51dd73e, 0x15410f1, 0xb5a38c2f, 0x99eade1f, 0x3f79e108, 0xfb202e0f; + mstore 96, 0xcde0a70a, 0x5999a198, 0xb48c34b6, 0x343ea4ea, 0xcdb51927, 0x89aafe43, 0x4580257c, 0x5f924734; + + ec_add 0, 64, 0; + + assert_eq 0, 0x4e1fdadb, 0x30998607, 0x50dd64ce, 0xfdf652c1, 0xbc4a599, 0x122bc1a, 0xf1769ea5, 0x51a4c0ac; + assert_eq 32, 0x521044ef, 0xadff4507, 0xfb522d06, 0x6f255923, 0x8cba892a, 0xe3517e53, 0x8c01d153, 0x77c8d346; + + mstore 0, 0x44e5467d, 0x4d0bd76a, 0x19bbface, 0x40908ab8, 0xec970e9, 0x2c21f62e, 0xfc69a122, 0x97d064f0; + mstore 32, 0x1e9cb3fa, 0x797300fd, 0x54f17ccd, 0xda5fb3b8, 0xa850861f, 0x3f7c66f, 0xd33402cc, 0x89974f2e; + mstore 64, 0x4e1fdadb, 0x30998607, 0x50dd64ce, 0xfdf652c1, 0xbc4a599, 0x122bc1a, 0xf1769ea5, 0x51a4c0ac; + mstore 96, 0x521044ef, 0xadff4507, 0xfb522d06, 0x6f255923, 0x8cba892a, 0xe3517e53, 0x8c01d153, 0x77c8d346; + + ec_add 0, 64, 0; + + assert_eq 0, 0x926341d9, 0xffcca36d, 0x20156334, 0x47b40a76, 0xe290d534, 0x19612e4a, 0xbb0b867, 0xbca7069b; + assert_eq 32, 0xbb0b77b, 0xc0d93775, 0x6a1fc9b3, 0x6204875d, 0x70b64966, 0x982754ac, 0x1566660, 0x5a7df87d; + + mstore 0, 0x13613bec, 0xcca81cb9, 0x101cfe67, 0x8bb5fc9d, 0xc74f972a, 0xedf1b33d, 0xc93937bd, 0x2dcfcab8; + mstore 32, 0x9a039215, 0x3e730924, 0xd33f5f38, 0x3732cfba, 0xd6f6c6f4, 0x65f088b7, 0x9474a412, 0x46dbc4dd; + mstore 64, 0x926341d9, 0xffcca36d, 0x20156334, 0x47b40a76, 0xe290d534, 0x19612e4a, 0xbb0b867, 0xbca7069b; + mstore 96, 0xbb0b77b, 0xc0d93775, 0x6a1fc9b3, 0x6204875d, 0x70b64966, 0x982754ac, 0x1566660, 0x5a7df87d; + + ec_add 0, 64, 0; + + assert_eq 0, 0x2bbfca49, 0x712b0408, 0xd867f353, 0x62f95f3d, 0x41a92b20, 0xd1ea0c49, 0x7ac6f3aa, 0xdeb21645; + assert_eq 32, 0xe16061a8, 0xcc4c43b3, 0xf6aa30a4, 0xb75e791b, 0x870bf702, 0x2ff3ef86, 0x5c58abfc, 0xe07e6c7e; + + mstore 0, 0x47fb9e1a, 0x17cd1708, 0xde2a3296, 0x7fe74b74, 0xbbab0e76, 0xf1a02bc9, 0xa48ec5a8, 0x1bec414a; + mstore 32, 0x749c0443, 0x57f6e117, 0xe8c9796e, 0x681385da, 0x30c54b0f, 0x8a79bc57, 0x70126667, 0xe3586704; + mstore 64, 0x2bbfca49, 0x712b0408, 0xd867f353, 0x62f95f3d, 0x41a92b20, 0xd1ea0c49, 0x7ac6f3aa, 0xdeb21645; + mstore 96, 0xe16061a8, 0xcc4c43b3, 0xf6aa30a4, 0xb75e791b, 0x870bf702, 0x2ff3ef86, 0x5c58abfc, 0xe07e6c7e; + + ec_add 0, 64, 0; + + assert_eq 0, 0x58a42d36, 0x8d906bf7, 0xb8d381b8, 0xd367e918, 0x4606faae, 0x17469bda, 0xdc7a255b, 0xeb6e3277; + assert_eq 32, 0x993cc451, 0x56a4320a, 0x892949a2, 0x7abe2059, 0xa0c8d1ff, 0xe30a6394, 0x80e9e03d, 0x615fa4f7; + + mstore 0, 0xbb7ceceb, 0xf3f678ff, 0x8897faf0, 0x73a59f93, 0x6f6e6814, 0x36ffb812, 0x4276d450, 0x437a8620; + mstore 32, 0x56c181e1, 0x7363bcc3, 0xdc8f9782, 0x87220fcf, 0x99d297ff, 0x69b8feb6, 0x3eeac32f, 0xb916ba1; + mstore 64, 0x58a42d36, 0x8d906bf7, 0xb8d381b8, 0xd367e918, 0x4606faae, 0x17469bda, 0xdc7a255b, 0xeb6e3277; + mstore 96, 0x993cc451, 0x56a4320a, 0x892949a2, 0x7abe2059, 0xa0c8d1ff, 0xe30a6394, 0x80e9e03d, 0x615fa4f7; + + ec_add 0, 64, 0; + + assert_eq 0, 0xc1a7674e, 0xc0497aa4, 0x27b9af61, 0x813645a4, 0xc1c691a3, 0x3be4aee1, 0xa5a4164c, 0x955e83c9; + assert_eq 32, 0xd6ae5ea4, 0x71ae0ae5, 0xcc9834ac, 0xbe2ecf82, 0x5ef04324, 0x753b98ff, 0x93b1d494, 0xc87400d2; + + mstore 0, 0xdcbf00eb, 0x4c9d9d87, 0xc18d0227, 0x41b4e98b, 0xa1a30bc2, 0x49be16f6, 0x96ead4dc, 0xb89070ae; + mstore 32, 0x1b0e664e, 0x1b7f1bcd, 0xb6b96a67, 0xcb0d8b06, 0xc1c4a766, 0x472294e4, 0xc8a2d88f, 0x6f24c8c2; + mstore 64, 0xc1a7674e, 0xc0497aa4, 0x27b9af61, 0x813645a4, 0xc1c691a3, 0x3be4aee1, 0xa5a4164c, 0x955e83c9; + mstore 96, 0xd6ae5ea4, 0x71ae0ae5, 0xcc9834ac, 0xbe2ecf82, 0x5ef04324, 0x753b98ff, 0x93b1d494, 0xc87400d2; + + ec_add 0, 64, 0; + + assert_eq 0, 0x47f62b82, 0x47e3fb06, 0xc2414cdc, 0x4d64416a, 0x9b263f25, 0x122b078f, 0xc89072f7, 0xcd9aa0b; + assert_eq 32, 0x14ca295f, 0x30910574, 0x19149bd4, 0x25b0ad0, 0xd8b34884, 0x9a61a4e0, 0xb15c4d94, 0xc510e04c; + + mstore 0, 0xb6fbe7b2, 0xb9d6ff9a, 0x458d65a3, 0x5eadedc1, 0xb2a88460, 0xf336bbb1, 0x9cb441f8, 0x26488766; + mstore 32, 0x21bc2a34, 0x932a78bc, 0x6a0eb603, 0x5638d981, 0xd02ddf18, 0x8f2f2dca, 0xb2014498, 0x9e15dab4; + mstore 64, 0x47f62b82, 0x47e3fb06, 0xc2414cdc, 0x4d64416a, 0x9b263f25, 0x122b078f, 0xc89072f7, 0xcd9aa0b; + mstore 96, 0x14ca295f, 0x30910574, 0x19149bd4, 0x25b0ad0, 0xd8b34884, 0x9a61a4e0, 0xb15c4d94, 0xc510e04c; + + ec_add 0, 64, 0; + + assert_eq 0, 0xb0263efb, 0xcc80645c, 0x7316d99, 0x4d5abacd, 0xb542ffec, 0xc03d886c, 0x5bc3b48b, 0xb9ad22c1; + assert_eq 32, 0xc37062b9, 0x474ad42a, 0x3e498d1a, 0x109e16c7, 0x9444c97b, 0x49968c1c, 0xbb4f8cca, 0xeb85392; + + mstore 0, 0x2b038315, 0x9690d306, 0x69310e6f, 0x9cacc433, 0x9794b862, 0x1e4680e3, 0x56771222, 0xaba55687; + mstore 32, 0xae25fc0a, 0xf9a003f9, 0xd8b63338, 0x3fbfb532, 0x25130d6f, 0x63d570f6, 0xaa365edb, 0xa0e75d87; + mstore 64, 0xb0263efb, 0xcc80645c, 0x7316d99, 0x4d5abacd, 0xb542ffec, 0xc03d886c, 0x5bc3b48b, 0xb9ad22c1; + mstore 96, 0xc37062b9, 0x474ad42a, 0x3e498d1a, 0x109e16c7, 0x9444c97b, 0x49968c1c, 0xbb4f8cca, 0xeb85392; + + ec_add 0, 64, 0; + + assert_eq 0, 0x16e97240, 0xb56720fb, 0x25349558, 0x15ab0093, 0xf2363793, 0x1f147d1a, 0x76551f7, 0x81e874bb; + assert_eq 32, 0x1ceb8018, 0x3937014e, 0x6c600999, 0xaf1ce7cf, 0xfaeb8246, 0x2032d276, 0x4664bb0, 0xc2791f04; + + mstore 0, 0x95bc15b4, 0x9cb9a134, 0x465a2ee6, 0x9275028e, 0xced7ca8d, 0xed858ee9, 0x51eeadc9, 0x10e90e2e; + mstore 32, 0x58aa258d, 0x34ebe609, 0x2bb6a88, 0x4ca58963, 0x16ad1f75, 0x4d57a8c6, 0x80d5e042, 0xc68a3703; + mstore 64, 0x16e97240, 0xb56720fb, 0x25349558, 0x15ab0093, 0xf2363793, 0x1f147d1a, 0x76551f7, 0x81e874bb; + mstore 96, 0x1ceb8018, 0x3937014e, 0x6c600999, 0xaf1ce7cf, 0xfaeb8246, 0x2032d276, 0x4664bb0, 0xc2791f04; + + ec_add 0, 64, 0; + + assert_eq 0, 0xf94b2dfb, 0x8add44b4, 0x33978c7a, 0x5d5d4dd3, 0xd75d0b54, 0x61ca58e9, 0x97c539fd, 0xe0a6cdb7; + assert_eq 32, 0xed63d567, 0x7446491b, 0xe5c5e6d3, 0x8055cb06, 0xd0165eb0, 0xae321a97, 0x2dc8eb3f, 0x8d1484c4; + + mstore 0, 0x7a1c0a80, 0xf62abc8, 0xc65a9c74, 0x4d625158, 0x2ff9c3, 0xb17c9be7, 0xa614cca5, 0xb6b15a68; + mstore 32, 0x41ce0a03, 0xb6cd0110, 0x82e16ee, 0x9c9a12b3, 0xef6536d4, 0xa54e223e, 0xd6cdb61e, 0xfae62e14; + mstore 64, 0xf94b2dfb, 0x8add44b4, 0x33978c7a, 0x5d5d4dd3, 0xd75d0b54, 0x61ca58e9, 0x97c539fd, 0xe0a6cdb7; + mstore 96, 0xed63d567, 0x7446491b, 0xe5c5e6d3, 0x8055cb06, 0xd0165eb0, 0xae321a97, 0x2dc8eb3f, 0x8d1484c4; + + ec_add 0, 64, 0; + + assert_eq 0, 0xe6409a8e, 0xa14dcacb, 0x2639e842, 0xece0189b, 0x1414cac6, 0x3979374e, 0xed7d382d, 0x1e3faaf7; + assert_eq 32, 0xae6d0176, 0x8c62c805, 0x97c1e2e6, 0xa6e353ea, 0x70d1f1d5, 0xbd387a7, 0x7aa6fb10, 0x2eff9414; + + mstore 0, 0x92b062d4, 0xa7caa50a, 0x9bb6a141, 0x7a5ce7e5, 0x83ea227a, 0x6fb1712, 0x3256eaca, 0x35963ea4; + mstore 32, 0xbbb25302, 0xa10aa4d1, 0x64de59b1, 0xd04082b9, 0xf9c08a96, 0xbfcce196, 0x4951e5c9, 0xf65be145; + mstore 64, 0xe6409a8e, 0xa14dcacb, 0x2639e842, 0xece0189b, 0x1414cac6, 0x3979374e, 0xed7d382d, 0x1e3faaf7; + mstore 96, 0xae6d0176, 0x8c62c805, 0x97c1e2e6, 0xa6e353ea, 0x70d1f1d5, 0xbd387a7, 0x7aa6fb10, 0x2eff9414; + + ec_add 0, 64, 0; + + assert_eq 0, 0x2548781a, 0xe605a68, 0x1ceff047, 0xf0d2b94d, 0x45e90176, 0x3b3b64d5, 0x15169a11, 0x37e15dc4; + assert_eq 32, 0x18c6306a, 0xea220b3a, 0x17dc3bc2, 0x1efec53b, 0xa03a580, 0xc329cc5b, 0x1d3d12f0, 0x4e6dfbf5; + + mstore 0, 0x1d33fd27, 0xfa0bf5c5, 0xb646cc62, 0x445f573d, 0xda82361b, 0xd022388e, 0x2263e84c, 0x9ed73f09; + mstore 32, 0x2716c458, 0x5972b2de, 0xb2e44934, 0x94a823e5, 0x42467254, 0xee75b4f3, 0xebb1eeea, 0xb6318967; + mstore 64, 0x2548781a, 0xe605a68, 0x1ceff047, 0xf0d2b94d, 0x45e90176, 0x3b3b64d5, 0x15169a11, 0x37e15dc4; + mstore 96, 0x18c6306a, 0xea220b3a, 0x17dc3bc2, 0x1efec53b, 0xa03a580, 0xc329cc5b, 0x1d3d12f0, 0x4e6dfbf5; + + ec_add 0, 64, 0; + + assert_eq 0, 0xdae7b802, 0xecfda59, 0x8e518ce7, 0xe5ab4c5, 0x7cd74c07, 0x2c98b4ea, 0x216c600f, 0x328a2f7a; + assert_eq 32, 0xd9b7d882, 0x86610a8e, 0x29924aee, 0x9754734c, 0x6e285105, 0x607959f5, 0x34212010, 0xb9d97615; + + mstore 0, 0xef028d83, 0x579623ae, 0xba743961, 0x6195926d, 0x15de69db, 0x6a5abe5a, 0xe3c785ec, 0xa7ebf7c4; + mstore 32, 0x99d0bed1, 0x9640392b, 0x4b053919, 0x47a38927, 0x7044804b, 0xcfd9c737, 0xbfe362d5, 0x6205152f; + mstore 64, 0xdae7b802, 0xecfda59, 0x8e518ce7, 0xe5ab4c5, 0x7cd74c07, 0x2c98b4ea, 0x216c600f, 0x328a2f7a; + mstore 96, 0xd9b7d882, 0x86610a8e, 0x29924aee, 0x9754734c, 0x6e285105, 0x607959f5, 0x34212010, 0xb9d97615; + + ec_add 0, 64, 0; + + assert_eq 0, 0x7498cf74, 0xbb2d0fe6, 0x2d4edb8, 0x35fa8af, 0xfe19c40f, 0x1eef3c75, 0xac797f07, 0xad59a910; + assert_eq 32, 0xffaadfdd, 0x84d70ced, 0xa3defb74, 0xdeee57b6, 0x5624675d, 0xa5225083, 0x9035d182, 0xd758026d; + + mstore 0, 0x7bb61ee5, 0xf2884413, 0xfb1f0c13, 0xda4f04e2, 0x8974ae6e, 0x662638cd, 0xcc8721b8, 0xd4933230; + mstore 32, 0xe5d694a8, 0x662da4d0, 0x5a438ddc, 0x1ad12c8c, 0x1ecafb5e, 0xedcc5e9d, 0xf51a9d23, 0x21c09ab; + mstore 64, 0x7498cf74, 0xbb2d0fe6, 0x2d4edb8, 0x35fa8af, 0xfe19c40f, 0x1eef3c75, 0xac797f07, 0xad59a910; + mstore 96, 0xffaadfdd, 0x84d70ced, 0xa3defb74, 0xdeee57b6, 0x5624675d, 0xa5225083, 0x9035d182, 0xd758026d; + + ec_add 0, 64, 0; + + assert_eq 0, 0x39cf7518, 0x5eee87ed, 0x7312f938, 0x519c909, 0x17773d04, 0x3f3fe6bc, 0x94420f9a, 0x99966667; + assert_eq 32, 0xbeb56284, 0x7cb2d8ef, 0xfc349071, 0xa97b338a, 0xdbaa9dc0, 0x23089a10, 0x76ecf29, 0x6986934a; + + mstore 0, 0xec04554a, 0x530ddcbc, 0x4688cffe, 0xaadcffbb, 0x7a10a2ec, 0x474652c2, 0x9873d1a0, 0x896f37c8; + mstore 32, 0x929138df, 0xd68f9fe1, 0xacc417dc, 0xe6085b61, 0x4e811bf1, 0xda622bb0, 0x224ac4ac, 0x380423e7; + mstore 64, 0x39cf7518, 0x5eee87ed, 0x7312f938, 0x519c909, 0x17773d04, 0x3f3fe6bc, 0x94420f9a, 0x99966667; + mstore 96, 0xbeb56284, 0x7cb2d8ef, 0xfc349071, 0xa97b338a, 0xdbaa9dc0, 0x23089a10, 0x76ecf29, 0x6986934a; + + ec_add 0, 64, 0; + + assert_eq 0, 0xca77ca75, 0x6ffe52cb, 0x8f7ef3dd, 0x8b554eb8, 0x3b86af90, 0x387c6679, 0xc837de69, 0xc7ce6fa9; + assert_eq 32, 0xd8ce2d85, 0x216c037b, 0x8f97bcee, 0xfb1f33db, 0xb4898bdf, 0x7eb02451, 0xc41130a7, 0x1d6668e2; + + mstore 0, 0xb43fca26, 0x84077d1a, 0xa3bc2367, 0x7dfb841d, 0xbf3578a2, 0xca6c209d, 0x774b6d6c, 0x11b3b97f; + mstore 32, 0x5b679d58, 0xd3b27eaf, 0x4b9f9d42, 0x3bae231c, 0x2f36d3bb, 0x8cd5650c, 0xae600c50, 0x65331f9f; + mstore 64, 0xca77ca75, 0x6ffe52cb, 0x8f7ef3dd, 0x8b554eb8, 0x3b86af90, 0x387c6679, 0xc837de69, 0xc7ce6fa9; + mstore 96, 0xd8ce2d85, 0x216c037b, 0x8f97bcee, 0xfb1f33db, 0xb4898bdf, 0x7eb02451, 0xc41130a7, 0x1d6668e2; + + ec_add 0, 64, 0; + + assert_eq 0, 0xbf92c52f, 0x49bbb218, 0x58dc039d, 0x4fc6d734, 0x8ad8179f, 0xdd9068ac, 0xdc747673, 0x213995c9; + assert_eq 32, 0x84240dd, 0xed98f6fa, 0x3ecbf6a4, 0x907e4ae8, 0x7d55c35a, 0x2d8acdec, 0xddf22625, 0x458f0e6b; + + mstore 0, 0x48dfd587, 0x79361bb, 0xc9b02656, 0x5ec4ba38, 0x2cf5a12d, 0x34867aaa, 0xacf4508b, 0x5084b41b; + mstore 32, 0x91470e89, 0x6e79e97f, 0x6891f560, 0x5db6f560, 0x55292747, 0x619aa6c8, 0x1d980d31, 0x34a9631a; + mstore 64, 0xbf92c52f, 0x49bbb218, 0x58dc039d, 0x4fc6d734, 0x8ad8179f, 0xdd9068ac, 0xdc747673, 0x213995c9; + mstore 96, 0x84240dd, 0xed98f6fa, 0x3ecbf6a4, 0x907e4ae8, 0x7d55c35a, 0x2d8acdec, 0xddf22625, 0x458f0e6b; + + ec_add 0, 64, 0; + + assert_eq 0, 0xed91aaf, 0x96eb71b9, 0xe5e3ee7d, 0x7d30103b, 0xa207dafc, 0x501b2c67, 0x237542f4, 0x1159abd4; + assert_eq 32, 0x6a255906, 0xb1976404, 0x3c3747d4, 0xebd4f608, 0x6bd3bbf, 0x40d90c4b, 0x23adb6fd, 0xb5196132; + + // Left out these test cases, because the format is different... + // https://github.com/0xPolygonHermez/zkevm-proverjs/blob/a4006af3d7fe4a57a85500c01dc791fb5013cef0/test/sm/sm_arith.js#L1196-L1211 + } +} diff --git a/test_data/std/arith_large_test.asm b/test_data/std/arith_large_test.asm index 492f42aa89..4c26168e7e 100644 --- a/test_data/std/arith_large_test.asm +++ b/test_data/std/arith_large_test.asm @@ -267,7 +267,8 @@ machine Main with degree: 65536 { assert_eq t_0_0, t_0_1, t_0_2, t_0_3, t_0_4, t_0_5, t_0_6, t_0_7, 0x70afe85a, 0xc5b0f470, 0x9620095b, 0x687cf441, 0x4d734633, 0x15c38f00, 0x48e7561b, 0xd01115d5; assert_eq t_1_0, t_1_1, t_1_2, t_1_3, t_1_4, t_1_5, t_1_6, t_1_7, 0xf4062327, 0x6b051b13, 0xd9a86d52, 0x79238c5d, 0xe17bd815, 0xa8b64537, 0xc815e0d7, 0xa9f34ffd; - // Auto-generated rest of the test cases: + // Auto-generated rest of the test cases, + // see: https://gist.github.com/georgwiese/a66425ae95c839b548edffffe6a692f9 t_0_0, t_0_1, t_0_2, t_0_3, t_0_4, t_0_5, t_0_6, t_0_7, t_1_0, t_1_1, t_1_2, t_1_3, t_1_4, t_1_5, t_1_6, t_1_7 <== ec_double( 0x70afe85a, 0xc5b0f470, 0x9620095b, 0x687cf441, 0x4d734633, 0x15c38f00, 0x48e7561b, 0xd01115d5, 0xf4062327, 0x6b051b13, 0xd9a86d52, 0x79238c5d, 0xe17bd815, 0xa8b64537, 0xc815e0d7, 0xa9f34ffd);