From 761d4d1266eda7b5d569bf88c12f8256b74ba454 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 22:15:23 +0000 Subject: [PATCH] Migrate the proofs to Rocq 9.2; keep the published Coq 8.20.1 version verbatim in coq-legacy/ - coq-legacy/: the Coq 8.20.1 development exactly as published (tree identical to main:coq), checked by check-legacy.sh / Dockerfile.legacy in the same digest-pinned coqorg/coq:8.20.1 image. - coq/: the Rocq 9.2 version. Changes are imports only (From Coq -> From Stdlib, Coq.* -> Stdlib.* paths); no definition, statement or proof changed. - check.sh / Dockerfile: rocq makefile, rocqchk, rocq c; rocq/rocq-prover:9.2 pinned by digest. - CI: two jobs, the Rocq check and the legacy Coq check. - README: section on the migration and the legacy version. Both checks pass locally: rocqchk and coqchk each report no axioms, no type-in-type, no unsafe fixpoints, no assumed positivity. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019VctApPTf4Vkbc7JRkGiXb --- .github/workflows/check.yml | 8 +- Dockerfile | 12 +- Dockerfile.legacy | 12 + README.md | 26 +- check-legacy.sh | 35 + check.sh | 24 +- coq-legacy/constraints/_CoqProject | 20 + coq-legacy/constraints/bits_kit.v | 105 + coq-legacy/constraints/bm_adequacy.v | 715 +++++++ coq-legacy/constraints/bm_model_facts.v | 116 + coq-legacy/constraints/bm_semantic.v | 342 +++ coq-legacy/constraints/bm_soundness.v | 400 ++++ coq-legacy/constraints/field_order_lift.v | 98 + coq-legacy/constraints/gen/bm_model_gen.v | 1894 +++++++++++++++++ coq-legacy/constraints/gen/bm_necessity_gen.v | 860 ++++++++ coq-legacy/constraints/gen/bm_scaffold_gen.v | 136 ++ coq-legacy/constraints/gen/bm_wires_gen.v | 23 + coq-legacy/constraints/pfcs.v | 140 ++ coq-legacy/constraints/range_field.v | 158 ++ coq-legacy/constraints/range_field_pasta.v | 908 ++++++++ coq-legacy/spec/bm_rule.v | 182 ++ coq/constraints/bits_kit.v | 2 +- coq/constraints/bm_adequacy.v | 2 +- coq/constraints/bm_model_facts.v | 2 +- coq/constraints/bm_semantic.v | 2 +- coq/constraints/bm_soundness.v | 2 +- coq/constraints/field_order_lift.v | 2 +- coq/constraints/gen/bm_model_gen.v | 2 +- coq/constraints/gen/bm_necessity_gen.v | 2 +- coq/constraints/gen/bm_scaffold_gen.v | 2 +- coq/constraints/gen/bm_wires_gen.v | 2 +- coq/constraints/pfcs.v | 6 +- coq/constraints/range_field.v | 2 +- coq/constraints/range_field_pasta.v | 8 +- coq/spec/bm_rule.v | 4 +- 35 files changed, 6212 insertions(+), 42 deletions(-) create mode 100644 Dockerfile.legacy create mode 100755 check-legacy.sh create mode 100644 coq-legacy/constraints/_CoqProject create mode 100644 coq-legacy/constraints/bits_kit.v create mode 100644 coq-legacy/constraints/bm_adequacy.v create mode 100644 coq-legacy/constraints/bm_model_facts.v create mode 100644 coq-legacy/constraints/bm_semantic.v create mode 100644 coq-legacy/constraints/bm_soundness.v create mode 100644 coq-legacy/constraints/field_order_lift.v create mode 100644 coq-legacy/constraints/gen/bm_model_gen.v create mode 100644 coq-legacy/constraints/gen/bm_necessity_gen.v create mode 100644 coq-legacy/constraints/gen/bm_scaffold_gen.v create mode 100644 coq-legacy/constraints/gen/bm_wires_gen.v create mode 100644 coq-legacy/constraints/pfcs.v create mode 100644 coq-legacy/constraints/range_field.v create mode 100644 coq-legacy/constraints/range_field_pasta.v create mode 100644 coq-legacy/spec/bm_rule.v diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 8f17603..954df02 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -5,9 +5,15 @@ on: [push, pull_request, workflow_dispatch] permissions: contents: read jobs: - coqchk: + rocqchk: runs-on: ubuntu-latest timeout-minutes: 240 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - run: docker build --no-cache --progress=plain --build-arg JOBS=2 . + coqchk-legacy: + runs-on: ubuntu-latest + timeout-minutes: 240 + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - run: docker build --no-cache --progress=plain --build-arg JOBS=2 -f Dockerfile.legacy . diff --git a/Dockerfile b/Dockerfile index e861115..42cd26a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,11 @@ # SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd # # One command: docker build . (with BuildKit, add --progress=plain to see every line of the check) -# The build runs check.sh; the build fails if any check fails. The base is the public Coq 8.20.1 image, -# pinned by digest so every rebuild uses the same checker. -FROM coqorg/coq:8.20.1@sha256:e50d77c4c5a9aa0d76ae1b343d79c5f922da3a75054b79c5dc635895438e4674 -WORKDIR /home/coq/bigmult -COPY --chown=coq:coq coq/ coq/ -COPY --chown=coq:coq check.sh ./ +# The build runs check.sh; the build fails if any check fails. The base is the public Rocq 9.2 image, +# pinned by digest so every rebuild uses the same checker. The Coq 8.20.1 version is checked by Dockerfile.legacy. +FROM rocq/rocq-prover:9.2@sha256:33926fb3757b2b560c3844157bd64173a26b6d338a256be1ae5eec8df2019025 +WORKDIR /home/rocq/bigmult +COPY --chown=rocq:rocq coq/ coq/ +COPY --chown=rocq:rocq check.sh ./ ARG JOBS=2 RUN JOBS=${JOBS} ./check.sh diff --git a/Dockerfile.legacy b/Dockerfile.legacy new file mode 100644 index 0000000..36cc05b --- /dev/null +++ b/Dockerfile.legacy @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd +# +# One command: docker build . (with BuildKit, add --progress=plain to see every line of the check) +# The build runs check-legacy.sh; the build fails if any check fails. The base is the public Coq 8.20.1 image, +# pinned by digest so every rebuild uses the same checker. +FROM coqorg/coq:8.20.1@sha256:e50d77c4c5a9aa0d76ae1b343d79c5f922da3a75054b79c5dc635895438e4674 +WORKDIR /home/coq/bigmult +COPY --chown=coq:coq coq-legacy/ coq-legacy/ +COPY --chown=coq:coq check-legacy.sh ./ +ARG JOBS=2 +RUN JOBS=${JOBS} ./check-legacy.sh diff --git a/README.md b/README.md index c053ca5..f41bcd2 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,32 @@ cd bigmult docker build . ``` -The build compiles every proof from source in the public Coq 8.20.1 image, pinned by digest in the Dockerfile, -then re-checks the whole development, together with the parts of Coq's standard library it uses, with coqchk, -Coq's independent kernel checker. It fails unless coqchk accepts everything and reports no axioms, and its last +The build compiles every proof from source in the public Rocq 9.2 image, pinned by digest in the Dockerfile, +then re-checks the whole development, together with the parts of Rocq's standard library it uses, with rocqchk, +Rocq's independent kernel checker. It fails unless rocqchk accepts everything and reports no axioms, and its last step prints the theorem exactly as the kernel states it, with the two definitions it is stated with (reproduced below). With BuildKit, add `--progress=plain` to see every line. The same build runs on every push, from `.github/workflows/check.yml`. If you run it, you are welcome to add a line to [REPRODUCTIONS.md](REPRODUCTIONS.md). +## Rocq 9.2 and the Coq legacy version + +The proofs now build with Rocq 9.2 (`coq/`, checked by `docker build .`). The published Coq 8.20.1 version is kept +verbatim in `coq-legacy/`, with its own one-command check, which uses the same pinned Coq 8.20.1 image as before: + +``` +docker build -f Dockerfile.legacy . +``` + +The changes from `coq-legacy/` to `coq/` are imports only: `From Coq Require ...` became `From Stdlib Require ...`, +and the two fully qualified paths `Coq.Arith.Arith` and `Coq.ZArith.Zpow_facts` (in `range_field_pasta.v`) became +`Stdlib.Arith.Arith` and `Stdlib.ZArith.Zpow_facts`. No definition, lemma or theorem statement, and no proof, was +changed. + +The statement block below was captured from the Coq 8.20.1 check. Rocq 9.2 prints the same statement, except that +argument-scope annotations are written with an underscore (`%_function_scope`, `%_list_scope` instead of +`%function_scope`, `%list_scope`): a change in the printer, not in the theorem. The check scripts differ only in the tool names (`rocq makefile`, `rocqchk`, `rocq c` in place of +`coq_makefile`, `coqchk`, `coqc`). + ## The theorem, as the kernel states it @@ -187,6 +206,7 @@ zero-knowledge proof for each execution. None of those is in this repository, an | file | what it holds | |---|---| +| `coq-legacy/` | the Coq 8.20.1 version as published, same layout as `coq/`; checked by `check-legacy.sh` | | `coq/spec/bm_rule.v` | the rule: `PRE_bm`, `REL_bm`, `adequate`, and facts about it | | `coq/constraints/gen/bm_model_gen.v` | the circuit's constraint model: the field prime, the 930 polynomial constraints, the 8 copy constraints | | `coq/constraints/gen/bm_scaffold_gen.v` | cells, assignments, evaluation, and the acceptance predicate `sat` | diff --git a/check-legacy.sh b/check-legacy.sh new file mode 100755 index 0000000..b7ac591 --- /dev/null +++ b/check-legacy.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd +# +# Rebuilds every proof from source, then re-checks the whole development with coqchk, Coq's independent +# kernel checker, including the parts of Coq's standard library it uses. Exits non-zero unless every file +# compiles, coqchk accepts everything, and coqchk reports no axioms and no disabled kernel check. +set -euo pipefail +cd "$(dirname "$0")/coq-legacy/constraints" +JOBS="${JOBS:-2}" +Q=(-Q . Constraints -Q gen Generated -Q ../spec "") + +echo "== 1/3 compile" +coq_makefile -f _CoqProject -o CoqMakefile +make -f CoqMakefile -j"$JOBS" + +echo "== 2/3 independent kernel re-check (coqchk)" +if ! coqchk -o "${Q[@]}" Constraints.bm_adequacy > coqchk.log 2>&1; then + cat coqchk.log; echo "FAIL: coqchk rejected the development"; exit 1 +fi +summary="$(sed -n '/CONTEXT SUMMARY/,$p' coqchk.log)" +[ -n "$summary" ] || { cat coqchk.log; echo "FAIL: coqchk printed no context summary"; exit 1; } +printf '%s\n' "$summary" +for field in "Axioms" "Constants/Inductives relying on type-in-type" \ + "Constants/Inductives relying on unsafe (co)fixpoints" "Inductives whose positivity is assumed"; do + grep -qF "* $field: " <<<"$summary" || { echo "FAIL: coqchk does not report '$field: '"; exit 1; } +done + +echo "== 3/3 the theorem, as the kernel states it, and the two definitions it is stated with" +tmp="$(mktemp -d)" +printf '%s\n' 'Require Import Constraints.bm_adequacy.' 'Check policy_adequacy_bm.' \ + 'Print bm_rule.adequate.' 'Print accepts_bm.' \ + 'Print Assumptions policy_adequacy_bm.' > "$tmp/Statement.v" +coqc "${Q[@]}" "$tmp/Statement.v" +echo "OK: all checks passed" diff --git a/check.sh b/check.sh index c02d26c..a7e0de5 100755 --- a/check.sh +++ b/check.sh @@ -2,28 +2,28 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd # -# Rebuilds every proof from source, then re-checks the whole development with coqchk, Coq's independent -# kernel checker, including the parts of Coq's standard library it uses. Exits non-zero unless every file -# compiles, coqchk accepts everything, and coqchk reports no axioms and no disabled kernel check. +# Rebuilds every proof from source, then re-checks the whole development with rocqchk, Rocq's independent +# kernel checker, including the parts of Rocq's standard library it uses. Exits non-zero unless every file +# compiles, rocqchk accepts everything, and rocqchk reports no axioms and no disabled kernel check. set -euo pipefail cd "$(dirname "$0")/coq/constraints" JOBS="${JOBS:-2}" Q=(-Q . Constraints -Q gen Generated -Q ../spec "") echo "== 1/3 compile" -coq_makefile -f _CoqProject -o CoqMakefile -make -f CoqMakefile -j"$JOBS" +rocq makefile -f _CoqProject -o RocqMakefile +make -f RocqMakefile -j"$JOBS" -echo "== 2/3 independent kernel re-check (coqchk)" -if ! coqchk -o "${Q[@]}" Constraints.bm_adequacy > coqchk.log 2>&1; then - cat coqchk.log; echo "FAIL: coqchk rejected the development"; exit 1 +echo "== 2/3 independent kernel re-check (rocqchk)" +if ! rocqchk -o "${Q[@]}" Constraints.bm_adequacy > rocqchk.log 2>&1; then + cat rocqchk.log; echo "FAIL: rocqchk rejected the development"; exit 1 fi -summary="$(sed -n '/CONTEXT SUMMARY/,$p' coqchk.log)" -[ -n "$summary" ] || { cat coqchk.log; echo "FAIL: coqchk printed no context summary"; exit 1; } +summary="$(sed -n '/CONTEXT SUMMARY/,$p' rocqchk.log)" +[ -n "$summary" ] || { cat rocqchk.log; echo "FAIL: rocqchk printed no context summary"; exit 1; } printf '%s\n' "$summary" for field in "Axioms" "Constants/Inductives relying on type-in-type" \ "Constants/Inductives relying on unsafe (co)fixpoints" "Inductives whose positivity is assumed"; do - grep -qF "* $field: " <<<"$summary" || { echo "FAIL: coqchk does not report '$field: '"; exit 1; } + grep -qF "* $field: " <<<"$summary" || { echo "FAIL: rocqchk does not report '$field: '"; exit 1; } done echo "== 3/3 the theorem, as the kernel states it, and the two definitions it is stated with" @@ -31,5 +31,5 @@ tmp="$(mktemp -d)" printf '%s\n' 'Require Import Constraints.bm_adequacy.' 'Check policy_adequacy_bm.' \ 'Print bm_rule.adequate.' 'Print accepts_bm.' \ 'Print Assumptions policy_adequacy_bm.' > "$tmp/Statement.v" -coqc "${Q[@]}" "$tmp/Statement.v" +rocq c "${Q[@]}" "$tmp/Statement.v" echo "OK: all checks passed" diff --git a/coq-legacy/constraints/_CoqProject b/coq-legacy/constraints/_CoqProject new file mode 100644 index 0000000..c43f563 --- /dev/null +++ b/coq-legacy/constraints/_CoqProject @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +# SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd +-Q . Constraints +-Q gen Generated +-Q ../spec "" + +gen/bm_model_gen.v +gen/bm_wires_gen.v +gen/bm_scaffold_gen.v +pfcs.v +range_field.v +range_field_pasta.v +field_order_lift.v +bits_kit.v +../spec/bm_rule.v +gen/bm_necessity_gen.v +bm_semantic.v +bm_model_facts.v +bm_soundness.v +bm_adequacy.v diff --git a/coq-legacy/constraints/bits_kit.v b/coq-legacy/constraints/bits_kit.v new file mode 100644 index 0000000..7ecc176 --- /dev/null +++ b/coq-legacy/constraints/bits_kit.v @@ -0,0 +1,105 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Bit decompositions (bits_of) and their weighted sums, facts about small residues modulo a positive + number, a computed modular inverse (finv), and small list utilities. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List Znumtheory Zpow_facts. +Import ListNotations. Open Scope Z_scope. +Require Import Constraints.field_order_lift. + +Definition bits_of (d:Z) (j:nat) : Z := Z.b2z (Z.testbit d (Z.of_nat j)). + +Lemma bits_of_bool : forall d i, bits_of d i = 0 \/ bits_of d i = 1. +Proof. intros d i. unfold bits_of, Z.b2z. destruct (Z.testbit d (Z.of_nat i)); auto. Qed. + +Lemma wpow_pow2 : forall n, wpow n = 2 ^ (Z.of_nat n). +Proof. + induction n as [|n IH]. + - reflexivity. + - cbn [wpow]. rewrite IH. rewrite Nat2Z.inj_succ. + rewrite Z.pow_succ_r by apply Nat2Z.is_nonneg. + reflexivity. +Qed. + +Lemma bitsum_bits_of : forall n d, 0 <= d -> bitsum (bits_of d) n = d mod (wpow n). +Proof. + induction n as [|n IH]; intros d Hd. + - cbn [bitsum wpow]. rewrite Z.mod_1_r. reflexivity. + - pose proof (wpow_pos n) as Hw. + cbn [bitsum]. rewrite (IH d Hd). + replace (wpow (S n)) with (wpow n * 2) by (cbn [wpow]; ring). + rewrite (Z.rem_mul_r d (wpow n) 2) by lia. + unfold bits_of. + rewrite (Z.testbit_spec' d (Z.of_nat n)) by apply Nat2Z.is_nonneg. + rewrite <- wpow_pow2. + ring. +Qed. + +Lemma bitsum64_bits_of : forall d, 0 <= d < 2^64 -> bitsum (bits_of d) 64 = d. +Proof. + intros d [Hlo Hhi]. + assert (H64 : wpow 64 = 2 ^ 64) by (rewrite wpow_pow2; reflexivity). + rewrite (bitsum_bits_of 64 d Hlo), H64. + apply Z.mod_small. lia. +Qed. + +Lemma mul_le_neg : forall P m, 0 < P -> m <= -1 -> m * P <= -P. +Proof. + intros P m HP Hm. + replace (-P) with ((-1)*P) by ring. apply Z.mul_le_mono_nonneg_r; lia. +Qed. + +Lemma mul_ge_pos : forall P m, 0 < P -> 1 <= m -> P <= m * P. +Proof. + intros P m HP Hm. + replace P with (1*P) at 1 by ring. apply Z.mul_le_mono_nonneg_r; lia. +Qed. + +Lemma no_wrap_zero : forall P z, 0 < P -> -P < z -> z < P -> z mod P = 0 -> z = 0. +Proof. + intros P z HP Hlo Hhi Hm. + destruct (Zmod_divide z P (ltac:(lia)) Hm) as [k Hk]. + destruct (Z.le_gt_cases k (-1)) as [Hk1|Hk1]. + - pose proof (mul_le_neg P k HP Hk1). lia. + - destruct (Z.eq_dec k 0) as [Hk0|Hk0]. + + subst k. rewrite Z.mul_0_l in Hk. exact Hk. + + pose proof (mul_ge_pos P k HP (ltac:(lia))). lia. +Qed. + +Lemma small_nonzero_residue : forall P z, 0 < P -> -P < z -> z < P -> z <> 0 -> z mod P <> 0. +Proof. + intros P z HP Hlo Hhi Hnz Hm. apply Hnz. exact (no_wrap_zero P z HP Hlo Hhi Hm). +Qed. + +Definition finv (P m : Z) : Z := Zpow_mod (m mod P) (P - 2) P. + +Definition drop_nth {A:Type} (n:nat) (l:list A) : list A := + firstn n l ++ skipn (S n) l. + +Lemma drop_nth_length : forall (A:Type) (n:nat) (l:list A), + (n < length l)%nat -> length (drop_nth n l) = (length l - 1)%nat. +Proof. + intros A n l Hn. unfold drop_nth. + rewrite app_length. rewrite firstn_length_le by lia. rewrite skipn_length. lia. +Qed. + +Lemma drop_nth_incl : forall (A:Type) (n:nat) (l:list A) (x:A), + In x (drop_nth n l) -> In x l. +Proof. + intros A n l x Hin. unfold drop_nth in Hin. + apply in_app_or in Hin. destruct Hin as [H|H]. + - rewrite <- (firstn_skipn n l). apply in_or_app. left. exact H. + - rewrite <- (firstn_skipn (S n) l). apply in_or_app. right. exact H. +Qed. + +Print Assumptions bits_of_bool. +Print Assumptions wpow_pow2. +Print Assumptions bitsum_bits_of. +Print Assumptions bitsum64_bits_of. +Print Assumptions no_wrap_zero. +Print Assumptions small_nonzero_residue. +Print Assumptions drop_nth_length. +Print Assumptions drop_nth_incl. diff --git a/coq-legacy/constraints/bm_adequacy.v b/coq-legacy/constraints/bm_adequacy.v new file mode 100644 index 0000000..611e28d --- /dev/null +++ b/coq-legacy/constraints/bm_adequacy.v @@ -0,0 +1,715 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Completeness (bridge_complete), and soundness and completeness as one theorem: under the input + assumption, the circuit accepts a triple exactly when the relation does (policy_adequacy_bm; the + two directions stated separately in policy_adequacy_bm_conj). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +Open Scope Z_scope. + +Require Import Generated.bm_model_gen. +Require Import Generated.bm_wires_gen. +Require Import Generated.bm_scaffold_gen. +Require Import Constraints.field_order_lift. +Require Import Constraints.range_field_pasta. +Require Import Constraints.bits_kit. +Require Import Constraints.bm_semantic. +Require Import Constraints.bm_model_facts. +Require Import Constraints.bm_soundness. +Require bm_rule. + +Definition CARRYC (s o : list Z) (i : nat) : Z := + (bm_rule.VAL (firstn (S i) s) - bm_rule.VAL (firstn (S i) o)) / bm_rule.B ^ Z.of_nat (S i). + +Lemma CARRYC_exact : forall s o i, + bm_rule.VAL o = bm_rule.VAL s -> + bm_rule.VAL (firstn (S i) s) - bm_rule.VAL (firstn (S i) o) + = bm_rule.B ^ Z.of_nat (S i) * (bm_rule.VAL (skipn (S i) o) - bm_rule.VAL (skipn (S i) s)). +Proof. + intros s o i Heq. + pose proof (bm_rule.VAL_firstn_skipn (S i) s) as Hi. + pose proof (bm_rule.VAL_firstn_skipn (S i) o) as Ho. + rewrite Heq in Ho. rewrite Z.mul_sub_distr_l. lia. +Qed. + +Theorem CARRYC_is_suffix_difference : forall s o i, + bm_rule.VAL o = bm_rule.VAL s -> + CARRYC s o i = bm_rule.VAL (skipn (S i) o) - bm_rule.VAL (skipn (S i) s). +Proof. + intros s o i Heq. unfold CARRYC. + rewrite (CARRYC_exact s o i Heq), Z.mul_comm. + apply Z.div_mul. apply bm_rule.B_pow_nonzero. +Qed. + +Lemma VAL_skipn_S : forall i v, + bm_rule.VAL (skipn i v) = nth i v 0 + bm_rule.B * bm_rule.VAL (skipn (S i) v). +Proof. + induction i as [|i IH]; intro v; destruct v as [|x t]. + - cbn [skipn nth]. rewrite bm_rule.VAL_nil. ring. + - cbn [skipn nth]. rewrite bm_rule.VAL_cons. ring. + - cbn [skipn nth]. rewrite bm_rule.VAL_nil. ring. + - change (skipn (S i) (x :: t)) with (skipn i t). + change (skipn (S (S i)) (x :: t)) with (skipn (S i) t). + change (nth (S i) (x :: t) 0) with (nth i t 0). apply IH. +Qed. + +Theorem REL_running : forall s o, + bm_rule.VAL o = bm_rule.VAL s -> + forall i, nth i s 0 - nth i o 0 = CARRYC s o i * bm_rule.B - prevc (CARRYC s o) i. +Proof. + intros s o Heq i. + rewrite (CARRYC_is_suffix_difference s o i Heq). + pose proof (VAL_skipn_S i s) as Hi. pose proof (VAL_skipn_S i o) as Ho. + + destruct i as [|j]; cbn [prevc]. + - change (skipn 0 s) with s in Hi. change (skipn 0 o) with o in Ho. + rewrite bm_rule.B_value in *. lia. + - rewrite (CARRYC_is_suffix_difference s o j Heq). + rewrite bm_rule.B_value in *. lia. +Qed. + +Theorem the_last_carry_is_the_top_limb : forall s o, + length s = 7%nat -> length o = 8%nat -> bm_rule.VAL o = bm_rule.VAL s -> + CARRYC s o 6 = nth 7 o 0. +Proof. + intros s o Hls Hlo Heq. + rewrite (CARRYC_is_suffix_difference s o 6 Heq). + rewrite (skipn_all2 s) by (rewrite Hls; lia). + rewrite (VAL_skipn_S 7 o), (skipn_all2 o) by (rewrite Hlo; lia). + rewrite !bm_rule.VAL_nil. ring. +Qed. + +Lemma VAL_firstn_bound : forall M v n, 0 <= M -> + (forall m, 0 <= nth m v 0 <= M * (bm_rule.B - 1)) -> + 0 <= bm_rule.VAL (firstn n v) <= M * (bm_rule.B ^ Z.of_nat n - 1). +Proof. + intros M v n HM Hv. induction n as [|n IH]. + - cbn [firstn Z.of_nat]. rewrite bm_rule.VAL_nil, Z.pow_0_r. lia. + - rewrite VAL_firstn_S, Nat2Z.inj_succ, Z.pow_succ_r by lia. + assert (HX : 0 < bm_rule.B ^ Z.of_nat n) + by (apply Z.pow_pos_nonneg; [ exact bm_rule.B_pos | lia ]). + set (X := bm_rule.B ^ Z.of_nat n) in *. + pose proof (Hv n) as Hn. pose proof bm_rule.B_pos. + assert (H1 : X * nth n v 0 <= X * (M * (bm_rule.B - 1))) + by (apply Z.mul_le_mono_nonneg_l; lia). + assert (H2 : 0 <= X * nth n v 0) by (apply Z.mul_nonneg_nonneg; lia). + replace (M * (bm_rule.B * X - 1)) with (M * (X - 1) + X * (M * (bm_rule.B - 1))) by ring. + lia. +Qed. + +Lemma nth_limb1 : forall v m, Forall bm_rule.limb_ok v -> 0 <= nth m v 0 <= 1 * (bm_rule.B - 1). +Proof. intros v m Hf. pose proof (nth_limb v m Hf). lia. Qed. + +Lemma VAL_out_is_VAL_CONV : forall a b out, bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + bm_rule.VAL out = bm_rule.VAL (CONV a b). +Proof. + intros a b out [Ha [Hb _]] [_ [_ Hv]]. rewrite Hv. symmetry. apply VAL_CONV; assumption. +Qed. + +Theorem carry_bound : forall a b out, bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + forall k, 0 <= CARRYC (CONV a b) out k < 2 ^ 66. +Proof. + intros a b out Hpre HR k. + pose proof (VAL_out_is_VAL_CONV a b out Hpre HR) as Hvs. + destruct HR as [_ [Hf _]]. + pose proof (CARRYC_exact (CONV a b) out k Hvs) as HE. + rewrite (CARRYC_is_suffix_difference (CONV a b) out k Hvs). + set (c := bm_rule.VAL (skipn (S k) out) - bm_rule.VAL (skipn (S k) (CONV a b))) in *. + assert (HX : 0 < bm_rule.B ^ Z.of_nat (S k)) + by (apply Z.pow_pos_nonneg; [ exact bm_rule.B_pos | lia ]). + pose proof (VAL_firstn_bound (4 * (bm_rule.B - 1)) (CONV a b) (S k) + ltac:(rewrite bm_rule.B_value; lia) (CONV_elem_bound a b Hpre)) as Hs. + pose proof (VAL_firstn_bound 1 out (S k) ltac:(lia) (fun m => nth_limb1 out m Hf)) as Ho. + set (X := bm_rule.B ^ Z.of_nat (S k)) in *. + set (Ps := bm_rule.VAL (firstn (S k) (CONV a b))) in *. + set (Po := bm_rule.VAL (firstn (S k) out)) in *. + pose proof bm_rule.B_pos as HB0. + assert (Hc0 : 0 <= c). + { destruct (Z.le_gt_cases 0 c) as [H|H]; [ exact H | exfalso ]. + pose proof (mul_le_neg X c HX ltac:(lia)). nia. } + assert (Hc1 : c < 4 * (bm_rule.B - 1)). + { destruct (Z.lt_ge_cases c (4 * (bm_rule.B - 1))) as [H|H]; [ exact H | exfalso ]. + assert (X * (4 * (bm_rule.B - 1)) <= X * c) by (apply Z.mul_le_mono_nonneg_l; lia). + rewrite bm_rule.B_value in *. nia. } + rewrite bm_rule.B_value in Hc1. split; [ exact Hc0 | ]. lia. +Qed. + +Lemma bitsum_ext : forall n (f g : nat -> Z), + (forall j, (j < n)%nat -> f j = g j) -> bitsum f n = bitsum g n. +Proof. + induction n as [|n IH]; intros f g H; [ reflexivity | ]. + cbn [bitsum]. rewrite (IH f g) by (intros j Hj; apply H; lia). + rewrite (H n) by lia. reflexivity. +Qed. + +Lemma bitsum66_bits_of : forall d, 0 <= d < 73786976294838206464 -> + bitsum (bits_of d) 66 = d. +Proof. + intros d [Hlo Hhi]. rewrite (bitsum_bits_of 66 d Hlo). + rewrite wpow66_val. apply Z.mod_small. lia. +Qed. + +Lemma in_firstn_or_skipn : forall (A : Type) (n : nat) (l : list A) (x : A), + In x l -> In x (firstn n l) \/ In x (skipn n l). +Proof. intros A n l x H. rewrite <- (firstn_skipn n l) in H. apply in_app_or. exact H. Qed. + +Lemma nat_split : forall k q r, (0 < k)%nat -> (r < k)%nat -> + ((q * k + r) / k = q)%nat /\ ((q * k + r) mod k = r)%nat. +Proof. + intros k q r Hk Hr. + assert (Hd : ((q * k + r) / k = q)%nat). + { rewrite Nat.div_add_l by lia. rewrite (Nat.div_small r k Hr). lia. } + split; [ exact Hd | ]. + pose proof (Nat.div_mod_eq (q * k + r) k) as H. rewrite Hd in H. lia. +Qed. + +Lemma list_four : forall (v : list Z), length v = 4%nat -> + v = [nth 0 v 0; nth 1 v 0; nth 2 v 0; nth 3 v 0]. +Proof. + intros v Hl. destruct v as [|a [|b [|c [|d [|e v]]]]]; cbn [length] in Hl; try lia. + reflexivity. +Qed. + +Lemma list_eight : forall (v : list Z), length v = 8%nat -> + v = [nth 0 v 0; nth 1 v 0; nth 2 v 0; nth 3 v 0; nth 4 v 0; nth 5 v 0; nth 6 v 0; nth 7 v 0]. +Proof. + intros v Hl. destruct v as [|a [|b [|c [|d [|e [|f [|g [|h [|i v]]]]]]]]]; cbn [length] in Hl; try lia. + reflexivity. +Qed. + +Lemma B64_lt_p : 18446744073709551616 < p. +Proof. apply Z.ltb_lt. vm_compute. reflexivity. Qed. + +Definition cellv (xs ys outs cs : list Z) (c : nat) : Z := + if (c if Nat.eqb (fst cl) 2000 then nth (snd cl) outs 0 + else if Nat.eqb (snd cl) 0 then cellv xs ys outs cs (fst cl) else 0. + +Section Builder. +Variables xs ys outs cs : list Z. + +Lemma mkW_cell : forall c, (c < 931)%nat -> mkW xs ys outs cs (c, 0%nat) = cellv xs ys outs cs c. +Proof. + intros c Hc. unfold mkW. cbn [fst snd]. + rewrite (proj2 (Nat.eqb_neq c 2000) ltac:(lia)). reflexivity. +Qed. + +Lemma mkW_a : forall c, (c < 4)%nat -> mkW xs ys outs cs (c, 0%nat) = nth c xs 0. +Proof. + intros c Hc. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_lt c 4) Hc). reflexivity. +Qed. + +Lemma mkW_b : forall c, (4 <= c < 8)%nat -> mkW xs ys outs cs (c, 0%nat) = nth (c - 4) ys 0. +Proof. + intros c Hc. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge c 4) ltac:(lia)), (proj2 (Nat.ltb_lt c 8) ltac:(lia)). reflexivity. +Qed. + +Lemma mkW_out : forall c, (8 <= c < 16)%nat -> mkW xs ys outs cs (c, 0%nat) = nth (c - 8) outs 0. +Proof. + intros c Hc. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge c 4) ltac:(lia)), (proj2 (Nat.ltb_ge c 8) ltac:(lia)), + (proj2 (Nat.ltb_lt c 16) ltac:(lia)). reflexivity. +Qed. + +Lemma mkW_cc : forall c, (16 <= c < 23)%nat -> mkW xs ys outs cs (c, 0%nat) = nth (c - 16) cs 0. +Proof. + intros c Hc. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge c 4) ltac:(lia)), (proj2 (Nat.ltb_ge c 8) ltac:(lia)), + (proj2 (Nat.ltb_ge c 16) ltac:(lia)), (proj2 (Nat.ltb_lt c 23) ltac:(lia)). reflexivity. +Qed. + +Lemma mkW_pub : forall j, mkW xs ys outs cs (2000%nat, j) = nth j outs 0. +Proof. intro j. reflexivity. Qed. + +Lemma mkW_bool : forall c, (23 <= c < 931)%nat -> + mkW xs ys outs cs (c, 0%nat) = 0 \/ mkW xs ys outs cs (c, 0%nat) = 1. +Proof. + intros c Hc. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge c 4) ltac:(lia)), (proj2 (Nat.ltb_ge c 8) ltac:(lia)), + (proj2 (Nat.ltb_ge c 16) ltac:(lia)), (proj2 (Nat.ltb_ge c 23) ltac:(lia)). + destruct (c (j < 64)%nat -> + bits_at (mkW xs ys outs cs) (23 + 64 * i)%nat j = bits_of (nth i outs 0) j. +Proof. + intros i j Hi Hj. unfold bits_at. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge (23 + 64 * i + j) 4) ltac:(lia)), + (proj2 (Nat.ltb_ge (23 + 64 * i + j) 8) ltac:(lia)), + (proj2 (Nat.ltb_ge (23 + 64 * i + j) 16) ltac:(lia)), + (proj2 (Nat.ltb_ge (23 + 64 * i + j) 23) ltac:(lia)), + (proj2 (Nat.ltb_lt (23 + 64 * i + j) 535) ltac:(lia)). + replace (23 + 64 * i + j - 23)%nat with (i * 64 + j)%nat by lia. + destruct (nat_split 64 i j ltac:(lia) Hj) as [Hd Hm]. rewrite Hd, Hm. reflexivity. +Qed. + +Lemma bat_c : forall i j, (i < 6)%nat -> (j < 66)%nat -> + bits_at (mkW xs ys outs cs) (535 + 66 * i)%nat j = bits_of (nth i cs 0) j. +Proof. + intros i j Hi Hj. unfold bits_at. rewrite mkW_cell by lia. unfold cellv. + rewrite (proj2 (Nat.ltb_ge (535 + 66 * i + j) 4) ltac:(lia)), + (proj2 (Nat.ltb_ge (535 + 66 * i + j) 8) ltac:(lia)), + (proj2 (Nat.ltb_ge (535 + 66 * i + j) 16) ltac:(lia)), + (proj2 (Nat.ltb_ge (535 + 66 * i + j) 23) ltac:(lia)), + (proj2 (Nat.ltb_ge (535 + 66 * i + j) 535) ltac:(lia)), + (proj2 (Nat.ltb_lt (535 + 66 * i + j) 931) ltac:(lia)). + replace (535 + 66 * i + j - 535)%nat with (i * 66 + j)%nat by lia. + destruct (nat_split 66 i j ltac:(lia) Hj) as [Hd Hm]. rewrite Hd, Hm. reflexivity. +Qed. + +Lemma g_bool : forall j, (j < 908)%nat -> gate_holds (mkW xs ys outs cs) (bool_gate (23 + j)%nat). +Proof. + intros j Hj. unfold gate_holds, bool_gate. cbn [eval]. + destruct (mkW_bool (23 + j)%nat ltac:(lia)) as [E|E]; rewrite E; + [ replace (0 * (0 - 1)) with 0 by ring | replace (1 * (1 - 1)) with 0 by ring ]; + apply Zmod_0_l. +Qed. + +Theorem mkW_copies_hold : copy_holds (mkW xs ys outs cs) deployed_copy. +Proof. + intros e Hin. cbn [deployed_copy In] in Hin. + repeat (destruct Hin as [<-|Hin]; [ cbn [fst snd]; rewrite mkW_out by lia; reflexivity | ]). + destruct Hin. +Qed. + +End Builder. + +Definition carries_of (a b out : list Z) : list Z := + map (CARRYC (CONV a b) out) (seq 0 7). + +Definition ASG (a b out : list Z) : Assignment := mkW a b out (carries_of a b out). + +Lemma nth_carries : forall a b out k, (k < 7)%nat -> + nth k (carries_of a b out) 0 = CARRYC (CONV a b) out k. +Proof. intros a b out k Hk. do 7 (destruct k as [|k]; [ reflexivity | ]). lia. Qed. + +Section Witness. +Variables a b out : list Z. + +Lemma g_rec_out : bm_rule.REL_bm a b out -> + forall k, (k < 8)%nat -> gate_holds (ASG a b out) (nth k tg_rec_out (EConst 0)). +Proof. + intros [Hlo [Hf _]] k Hk. unfold gate_holds, ASG. + destruct k as [|k]. + { rewrite ev_rec_out_0. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 23) (bits_of (nth 0 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 0 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 0 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 8) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_1. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 87) (bits_of (nth 1 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 1 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 1 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 9) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_2. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 151) (bits_of (nth 2 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 2 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 2 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 10) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_3. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 215) (bits_of (nth 3 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 3 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 3 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 11) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_4. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 279) (bits_of (nth 4 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 4 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 4 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 12) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_5. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 343) (bits_of (nth 5 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 5 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 5 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 13) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_6. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 407) (bits_of (nth 6 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 6 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 6 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 14) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_out_7. + rewrite (bitsum_ext 64 (bits_at (mkW a b out (carries_of a b out)) 471) (bits_of (nth 7 out 0)) + (fun j Hj => bat_out a b out (carries_of a b out) 7 j ltac:(lia) Hj)). + rewrite bitsum64_bits_of by (pose proof (nth_limb out 7 Hf) as Hn; rewrite bm_rule.B_value in Hn; lia). + rewrite (mkW_out a b out (carries_of a b out) 15) by lia. cbn [Nat.sub]. + rewrite Z.sub_diag. apply Zmod_0_l. } + lia. +Qed. + +Lemma g_rec_c : bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + forall k, (k < 6)%nat -> gate_holds (ASG a b out) (nth k tg_rec_c (EConst 0)). +Proof. + intros Hpre HR k Hk. unfold gate_holds, ASG. + destruct k as [|k]. + { rewrite ev_rec_c_0. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 535) (bits_of (nth 0 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 0 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 0) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 0%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 16) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 0) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_c_1. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 601) (bits_of (nth 1 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 1 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 1) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 1%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 17) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 1) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_c_2. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 667) (bits_of (nth 2 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 2 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 2) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 2%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 18) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 2) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_c_3. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 733) (bits_of (nth 3 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 3 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 3) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 3%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 19) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 3) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_c_4. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 799) (bits_of (nth 4 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 4 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 4) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 4%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 20) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 4) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_rec_c_5. + rewrite (bitsum_ext 66 (bits_at (mkW a b out (carries_of a b out)) 865) (bits_of (nth 5 (carries_of a b out) 0)) + (fun j Hj => bat_c a b out (carries_of a b out) 5 j ltac:(lia) Hj)). + rewrite (nth_carries a b out 5) by lia. + rewrite bitsum66_bits_of by (pose proof (carry_bound a b out Hpre HR 5%nat) as Hcb; lia). + rewrite (mkW_cc a b out (carries_of a b out) 21) by lia. cbn [Nat.sub]. + rewrite (nth_carries a b out 5) by lia. + rewrite Z.sub_diag. apply Zmod_0_l. } + lia. +Qed. + +Lemma g_chain : bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + forall k, (k < 7)%nat -> gate_holds (ASG a b out) (nth k tg_chain (EConst 0)). +Proof. + intros Hpre HR k Hk. unfold gate_holds, ASG. + pose proof (REL_running (CONV a b) out (VAL_out_is_VAL_CONV a b out Hpre HR)) as HRR. + destruct k as [|k]. + { rewrite ev_chain_0. unfold RW0. + rewrite (mkW_a a b out (carries_of a b out) 0) by lia. + rewrite (mkW_b a b out (carries_of a b out) 4) by lia. + rewrite (mkW_out a b out (carries_of a b out) 8) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 16) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 0%nat) as H. cbn [prevc] in H. + change (nth 0 (CONV a b) 0) with (nth 0 a 0 * nth 0 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_1. unfold RW1. + rewrite (mkW_a a b out (carries_of a b out) 0) by lia. + rewrite (mkW_a a b out (carries_of a b out) 1) by lia. + rewrite (mkW_b a b out (carries_of a b out) 5) by lia. + rewrite (mkW_b a b out (carries_of a b out) 4) by lia. + rewrite (mkW_out a b out (carries_of a b out) 9) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 16) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 17) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 1%nat) as H. cbn [prevc] in H. + change (nth 1 (CONV a b) 0) with (nth 0 a 0 * nth 1 b 0 + nth 1 a 0 * nth 0 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_2. unfold RW2. + rewrite (mkW_a a b out (carries_of a b out) 0) by lia. + rewrite (mkW_a a b out (carries_of a b out) 1) by lia. + rewrite (mkW_a a b out (carries_of a b out) 2) by lia. + rewrite (mkW_b a b out (carries_of a b out) 6) by lia. + rewrite (mkW_b a b out (carries_of a b out) 5) by lia. + rewrite (mkW_b a b out (carries_of a b out) 4) by lia. + rewrite (mkW_out a b out (carries_of a b out) 10) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 17) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 18) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 2%nat) as H. cbn [prevc] in H. + change (nth 2 (CONV a b) 0) with (nth 0 a 0 * nth 2 b 0 + nth 1 a 0 * nth 1 b 0 + nth 2 a 0 * nth 0 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_3. unfold RW3. + rewrite (mkW_a a b out (carries_of a b out) 0) by lia. + rewrite (mkW_a a b out (carries_of a b out) 1) by lia. + rewrite (mkW_a a b out (carries_of a b out) 2) by lia. + rewrite (mkW_a a b out (carries_of a b out) 3) by lia. + rewrite (mkW_b a b out (carries_of a b out) 7) by lia. + rewrite (mkW_b a b out (carries_of a b out) 6) by lia. + rewrite (mkW_b a b out (carries_of a b out) 5) by lia. + rewrite (mkW_b a b out (carries_of a b out) 4) by lia. + rewrite (mkW_out a b out (carries_of a b out) 11) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 18) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 19) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 3%nat) as H. cbn [prevc] in H. + change (nth 3 (CONV a b) 0) with (nth 0 a 0 * nth 3 b 0 + nth 1 a 0 * nth 2 b 0 + nth 2 a 0 * nth 1 b 0 + nth 3 a 0 * nth 0 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_4. unfold RW4. + rewrite (mkW_a a b out (carries_of a b out) 1) by lia. + rewrite (mkW_a a b out (carries_of a b out) 2) by lia. + rewrite (mkW_a a b out (carries_of a b out) 3) by lia. + rewrite (mkW_b a b out (carries_of a b out) 7) by lia. + rewrite (mkW_b a b out (carries_of a b out) 6) by lia. + rewrite (mkW_b a b out (carries_of a b out) 5) by lia. + rewrite (mkW_out a b out (carries_of a b out) 12) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 19) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 20) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 4%nat) as H. cbn [prevc] in H. + change (nth 4 (CONV a b) 0) with (nth 1 a 0 * nth 3 b 0 + nth 2 a 0 * nth 2 b 0 + nth 3 a 0 * nth 1 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_5. unfold RW5. + rewrite (mkW_a a b out (carries_of a b out) 2) by lia. + rewrite (mkW_a a b out (carries_of a b out) 3) by lia. + rewrite (mkW_b a b out (carries_of a b out) 7) by lia. + rewrite (mkW_b a b out (carries_of a b out) 6) by lia. + rewrite (mkW_out a b out (carries_of a b out) 13) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 20) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 21) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 5%nat) as H. cbn [prevc] in H. + change (nth 5 (CONV a b) 0) with (nth 2 a 0 * nth 3 b 0 + nth 3 a 0 * nth 2 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + destruct k as [|k]. + { rewrite ev_chain_6. unfold RW6. + rewrite (mkW_a a b out (carries_of a b out) 3) by lia. + rewrite (mkW_b a b out (carries_of a b out) 7) by lia. + rewrite (mkW_out a b out (carries_of a b out) 14) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 21) by lia. + rewrite (mkW_cc a b out (carries_of a b out) 22) by lia. + cbn [Nat.sub]. rewrite !nth_carries by lia. + pose proof (HRR 6%nat) as H. cbn [prevc] in H. + change (nth 6 (CONV a b) 0) with (nth 3 a 0 * nth 3 b 0) in H. + rewrite bm_rule.B_value in H. + replace (_ - _) with 0 by lia. apply Zmod_0_l. } + lia. +Qed. + +Lemma g_end : bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + gate_holds (ASG a b out) (nth 0 tg_end (EConst 0)). +Proof. + intros Hpre HR. pose proof (VAL_out_is_VAL_CONV a b out Hpre HR) as Hvs. + destruct HR as [Hlo _]. unfold gate_holds, ASG. + rewrite ev_end. unfold RWEND. + rewrite (mkW_cc a b out (carries_of a b out) 22) by lia. + rewrite (mkW_out a b out (carries_of a b out) 15) by lia. + cbn [Nat.sub]. rewrite nth_carries by lia. + rewrite (the_last_carry_is_the_top_limb (CONV a b) out (CONV_length a b) Hlo Hvs). + rewrite Z.sub_diag. apply Zmod_0_l. +Qed. + +Theorem all_gates_hold : bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + gates_hold (ASG a b out) deployed_gates. +Proof. + intros Hpre HR g Hin. + destruct (in_firstn_or_skipn _ 908 deployed_gates g Hin) as [Hh|Ht]. + - rewrite head_is_the_booleanity_bank in Hh. + apply in_map_iff in Hh. destruct Hh as [j [Hj Hseq]]. + apply in_seq in Hseq. subst g. apply g_bool. lia. + - change (skipn 908 deployed_gates) with tail_gates in Ht. + rewrite <- tail_split_is_a_partition in Ht. + repeat (apply in_app_or in Ht; destruct Ht as [Ht|Ht]). + + apply (In_nth _ _ (EConst 0)) in Ht. destruct Ht as [k [Hk Hg]]. + rewrite tg_rec_out_len in Hk. subst g. apply g_rec_out; assumption. + + apply (In_nth _ _ (EConst 0)) in Ht. destruct Ht as [k [Hk Hg]]. + rewrite tg_rec_c_len in Hk. subst g. apply g_rec_c; assumption. + + apply (In_nth _ _ (EConst 0)) in Ht. destruct Ht as [k [Hk Hg]]. + rewrite tg_chain_len in Hk. subst g. apply g_chain; assumption. + + apply (In_nth _ _ (EConst 0)) in Ht. destruct Ht as [k [Hk Hg]]. + rewrite tg_end_len in Hk. assert (k = 0%nat) by lia. subst k g. + apply g_end; assumption. +Qed. + +Theorem ASG_sat : bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + sat deployed_model (ASG a b out). +Proof. + intros Hpre HR. split; [ exact (all_gates_hold Hpre HR) | apply mkW_copies_hold ]. +Qed. + +Lemma canon_small : forall x, 0 <= x <= bm_rule.B - 1 -> x mod p = x. +Proof. + intros x Hx. apply Z.mod_small. pose proof B64_lt_p. rewrite bm_rule.B_value in Hx. lia. +Qed. + +Lemma decode_a : bm_rule.PRE_bm a b -> a_l (ASG a b out) = a. +Proof. + intros [Ha [_ [Fa _]]]. + unfold a_l, dc, ASG. + rewrite !(mkW_a a b out (carries_of a b out)) by lia. + rewrite !canon_small by (apply nth_limb; exact Fa). + symmetry. apply list_four. exact Ha. +Qed. + +Lemma decode_b : bm_rule.PRE_bm a b -> b_l (ASG a b out) = b. +Proof. + intros [_ [Hb [_ Fb]]]. + unfold b_l, dc, ASG. + rewrite !(mkW_b a b out (carries_of a b out)) by lia. cbn [Nat.sub]. + rewrite !canon_small by (apply nth_limb; exact Fb). + symmetry. apply list_four. exact Hb. +Qed. + +Lemma decode_out : bm_rule.REL_bm a b out -> out_l (ASG a b out) = out. +Proof. + intros [Hlo [Hf _]]. + unfold out_l, dc, ASG. + rewrite !(mkW_out a b out (carries_of a b out)) by lia. cbn [Nat.sub]. + rewrite !canon_small by (apply nth_limb; exact Hf). + symmetry. apply list_eight. exact Hlo. +Qed. + +End Witness. + +(* Completeness: for every triple satisfying the input assumption and the relation, there is a + filling the circuit accepts that reads back as exactly that triple. *) +Theorem bridge_complete : forall a b out, + bm_rule.PRE_bm a b -> + bm_rule.REL_bm a b out -> + exists al, sat deployed_model al /\ CANON_bm al + /\ a_l al = a /\ b_l al = b /\ out_l al = out. +Proof. + intros a b out Hpre HR. exists (ASG a b out). + split; [ exact (ASG_sat a b out Hpre HR) | ]. + split; [ apply CANON_is_free | ]. + split; [ exact (decode_a a b out Hpre) | ]. + split; [ exact (decode_b a b out Hpre) | exact (decode_out a b out HR) ]. +Qed. + +Definition accepts_bm (a b out : list Z) : Prop := + exists al, sat deployed_model al /\ CANON_bm al + /\ a_l al = a /\ b_l al = b /\ out_l al = out. + +(* Soundness and completeness as one theorem, for inputs satisfying the input assumption. *) +Theorem policy_adequacy_bm : bm_rule.adequate accepts_bm. +Proof. + intros a b out Hpre. split. + - intros [al [Hs [Hc [Ha [Hb Ho]]]]]. subst a b out. + exact (bridge_sound al Hs Hc Hpre). + - intros HR. exact (bridge_complete a b out Hpre HR). +Qed. + +Theorem policy_adequacy_bm_conj : + (forall al, sat deployed_model al -> CANON_bm al -> bm_rule.PRE_bm (a_l al) (b_l al) -> + bm_rule.REL_bm (a_l al) (b_l al) (out_l al)) + /\ + (forall a b out, bm_rule.PRE_bm a b -> bm_rule.REL_bm a b out -> + exists al, sat deployed_model al /\ CANON_bm al + /\ a_l al = a /\ b_l al = b /\ out_l al = out). +Proof. split; [ exact bridge_sound | exact bridge_complete ]. Qed. + +Theorem completeness_hypothesis_is_INHABITED : + bm_rule.PRE_bm bm_rule.CORNER bm_rule.CORNER + /\ bm_rule.REL_bm bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT. +Proof. split; [ exact bm_rule.corner_pre | exact bm_rule.corner_rel ]. Qed. + +Theorem the_corner_is_ACCEPTED : accepts_bm bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT. +Proof. apply policy_adequacy_bm; [ exact bm_rule.corner_pre | exact bm_rule.corner_rel ]. Qed. + +Theorem the_diag_row_is_ACCEPTED : accepts_bm bm_rule.DIAG_A bm_rule.DIAG_A bm_rule.DIAG_OUT. +Proof. apply policy_adequacy_bm; [ exact bm_rule.diag_row_pre | exact bm_rule.diag_row_rel ]. Qed. + +Theorem the_corner_carries_fill_the_66_bit_bank : + carries_of bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT = [18446744073709551614; 36893488147419103229; 55340232221128654844; 73786976294838206459; 55340232221128654845; 36893488147419103230; 18446744073709551615] + /\ 2 ^ 65 <= nth 2 (carries_of bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT) 0 < 2 ^ 66. +Proof. + + split; [ vm_compute; reflexivity | ]. + split; [ apply Z.leb_le | apply Z.ltb_lt ]; vm_compute; reflexivity. +Qed. + +Theorem accepts_bm_is_canonical : forall a b out, accepts_bm a b out -> + Forall (fun x => 0 <= x < p) a /\ Forall (fun x => 0 <= x < p) b + /\ Forall (fun x => 0 <= x < p) out. +Proof. + intros a b out [al [_ [_ [Ha [Hb Ho]]]]]. subst a b out. + unfold a_l, b_l, out_l. + split; [ | split ]; repeat (apply Forall_cons; [ apply dc_range | ]); apply Forall_nil. +Qed. + +Theorem accepts_is_not_mod_q_invariant : + accepts_bm bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT + /\ ~ accepts_bm [2 ^ 64 - 1 + p; 2 ^ 64 - 1; 2 ^ 64 - 1; 2 ^ 64 - 1] bm_rule.CORNER bm_rule.CORNER_OUT. +Proof. + split; [ exact the_corner_is_ACCEPTED | ]. + intros Hacc. destruct (accepts_bm_is_canonical _ _ _ Hacc) as [Ha _]. + + apply Forall_inv in Ha. cbn beta in Ha. + pose proof (Z.pow_pos_nonneg 2 64 ltac:(lia) ltac:(lia)). lia. +Qed. + +Theorem accepts_bm_fixes_the_arity : forall a b out, accepts_bm a b out -> + length a = bm_rule.K /\ length b = bm_rule.K. +Proof. intros a b out [al [_ [_ [Ha [Hb _]]]]]. subst a b. split; reflexivity. Qed. + +Print Assumptions CARRYC_exact. +Print Assumptions CARRYC_is_suffix_difference. +Print Assumptions VAL_skipn_S. +Print Assumptions REL_running. +Print Assumptions the_last_carry_is_the_top_limb. +Print Assumptions VAL_firstn_bound. +Print Assumptions carry_bound. +Print Assumptions bitsum66_bits_of. +Print Assumptions mkW_copies_hold. +Print Assumptions all_gates_hold. +Print Assumptions ASG_sat. +Print Assumptions decode_a. +Print Assumptions decode_b. +Print Assumptions decode_out. +Print Assumptions bridge_complete. +Print Assumptions policy_adequacy_bm. +Print Assumptions policy_adequacy_bm_conj. +Print Assumptions completeness_hypothesis_is_INHABITED. +Print Assumptions the_corner_is_ACCEPTED. +Print Assumptions the_diag_row_is_ACCEPTED. +Print Assumptions the_corner_carries_fill_the_66_bit_bank. +Print Assumptions accepts_bm_is_canonical. +Print Assumptions accepts_is_not_mod_q_invariant. +Print Assumptions accepts_bm_fixes_the_arity. diff --git a/coq-legacy/constraints/bm_model_facts.v b/coq-legacy/constraints/bm_model_facts.v new file mode 100644 index 0000000..4983d34 --- /dev/null +++ b/coq-legacy/constraints/bm_model_facts.v @@ -0,0 +1,116 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Facts about the model used by the proofs. In every accepted filling the output limbs lie in [0, 2^64) + (out_limbs_in_range) and the first six carry cells in [0, 2^66) (carry_cells_in_range); the + output limbs agree with the public cells. Also: the decoded values are canonical, a 64-bit limb is at + most half the field prime, each input cell is read only by the constraints that compute the product, and the + relation is an equality of integers, not a congruence modulo p (REL_is_a_value_equality_not_mod_q). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +Open Scope Z_scope. + +Require Import Generated.bm_model_gen. +Require Import Generated.bm_scaffold_gen. +Require Import Constraints.bm_semantic. +Require bm_rule. + +Theorem one_member : bm_rule.N_BITS = 64 /\ bm_rule.K = 4%nat. +Proof. split; reflexivity. Qed. + +Theorem the_decode_is_canonical : forall a c, + dc a c = (a (c, 0%nat)) mod p /\ 0 <= dc a c < p. +Proof. intros a c. split; [ reflexivity | apply dc_range ]. Qed. + +Theorem n_bit_limb_is_at_most_half_field : forall P x, + 2 ^ 65 <= P -> 0 <= x < 2 ^ 64 -> x <= (P - 1) / 2. +Proof. + intros P x HP Hx. apply Z.div_le_lower_bound; [ lia | ]. + assert (H : 2 ^ 65 = 2 * 2 ^ 64) by reflexivity. lia. +Qed. + +Theorem on_pasta_every_limb_is_below_half : 2 ^ 64 - 1 <= HALF. +Proof. pose proof HALF_big. assert (2 ^ 64 <= 2 ^ 140) by (apply Z.pow_le_mono_r; lia). lia. Qed. + +Theorem each_input_cell_is_read_only_by_chain_gates : + map (fun c => length (filter (reads_b (c, 0%nat)) deployed_gates)) (seq 0 8) + = [4; 4; 4; 4; 4; 4; 4; 4]%nat + /\ map (fun c => length (filter (reads_b (c, 0%nat)) tg_chain)) (seq 0 8) + = [4; 4; 4; 4; 4; 4; 4; 4]%nat. +Proof. split; vm_compute; reflexivity. Qed. + +Theorem ab_cell_indices_lie_below_OUTBIT_BASE : + OUTBIT_BASE = 23%nat /\ (forall c, (c < 8)%nat -> (c < OUTBIT_BASE)%nat). +Proof. split; [ reflexivity | intros c Hc; unfold OUTBIT_BASE; lia ]. Qed. + +Theorem out_limbs_in_range : forall a, + sat deployed_model a -> Forall bm_rule.limb_ok (out_l a). +Proof. + intros a Hs. unfold out_l. + pose proof (rng_out a Hs) as H. unfold bm_rule.limb_ok. rewrite bm_rule.B_value. + + apply Forall_cons; [ exact (H 0%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 1%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 2%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 3%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 4%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 5%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 6%nat ltac:(lia)) | ]. + apply Forall_cons; [ exact (H 7%nat ltac:(lia)) | ]. + apply Forall_nil. +Qed. + +Theorem carry_cells_in_range : forall a, + sat deployed_model a -> + forall i, (i < 6)%nat -> 0 <= cc a i < 2 ^ 66. +Proof. + intros a Hs i Hi. change (2 ^ 66) with 73786976294838206464. exact (rng_c a Hs i Hi). +Qed. + +Definition CORNER_ALIAS : list Z := [11037532056220336130; 2469829653914515739; 0; 4611686018427387904; 18446744073709551614; 18446744073709551615; 18446744073709551615; 18446744073709551615]. + +Theorem REL_is_a_value_equality_not_mod_q : + bm_rule.REL_bm bm_rule.CORNER bm_rule.CORNER bm_rule.CORNER_OUT + /\ bm_rule.VAL CORNER_ALIAS = bm_rule.VAL bm_rule.CORNER_OUT + p + /\ (bm_rule.VAL CORNER_ALIAS) mod p = (bm_rule.VAL bm_rule.CORNER_OUT) mod p + /\ length CORNER_ALIAS = 8%nat /\ Forall bm_rule.limb_ok CORNER_ALIAS + /\ ~ bm_rule.REL_bm bm_rule.CORNER bm_rule.CORNER CORNER_ALIAS. +Proof. + split; [ exact bm_rule.corner_rel | ]. + split; [ vm_compute; reflexivity | ]. + split; [ vm_compute; reflexivity | ]. + split; [ reflexivity | ]. + split. + - unfold CORNER_ALIAS, bm_rule.limb_ok. rewrite bm_rule.B_value. + repeat (apply Forall_cons; [ lia | ]). apply Forall_nil. + - intros [_ [_ H]]. vm_compute in H. discriminate. +Qed. + +Theorem the_product_fits_2K_limbs : forall a b out, + bm_rule.REL_bm a b out -> 0 <= bm_rule.VAL out < bm_rule.B ^ 8. +Proof. + intros a b out [Hl [Hf _]]. pose proof (bm_rule.VAL_bound out Hf) as H. + rewrite Hl in H. exact H. +Qed. + +Theorem out_limbs_are_pinned_to_public_cells : forall a, + sat deployed_model a -> PINS_bm a. +Proof. exact answer_pins_are_DERIVED. Qed. + +Theorem X2_margin_on_pasta : 2 ^ 131 < HALF. +Proof. pose proof HALF_big. assert (2 ^ 131 < 2 ^ 140) by (apply Z.pow_lt_mono_r; lia). lia. Qed. + +Print Assumptions one_member. +Print Assumptions the_decode_is_canonical. +Print Assumptions n_bit_limb_is_at_most_half_field. +Print Assumptions on_pasta_every_limb_is_below_half. +Print Assumptions each_input_cell_is_read_only_by_chain_gates. +Print Assumptions ab_cell_indices_lie_below_OUTBIT_BASE. +Print Assumptions out_limbs_in_range. +Print Assumptions carry_cells_in_range. +Print Assumptions REL_is_a_value_equality_not_mod_q. +Print Assumptions the_product_fits_2K_limbs. +Print Assumptions out_limbs_are_pinned_to_public_cells. +Print Assumptions X2_margin_on_pasta. diff --git a/coq-legacy/constraints/bm_semantic.v b/coq-legacy/constraints/bm_semantic.v new file mode 100644 index 0000000..d5056ca --- /dev/null +++ b/coq-legacy/constraints/bm_semantic.v @@ -0,0 +1,342 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Reading the operand triple off a filling: each operand cell as its canonical remainder modulo p (dc), + the vectors a_l, b_l and out_l, and the canonicity predicate CANON_bm, which every filling satisfies + (CANON_is_free). Also the public cells' agreement with the output cells, derived from the copy + constraints (answer_pins_are_DERIVED), the checked count of polynomial constraints (dg_len), and the + range bounds every accepted filling puts on its output cells and its first six carry cells + (rng_out, rng_c). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +Open Scope Z_scope. + +Require Import Generated.bm_model_gen. +Require Import Generated.bm_wires_gen. +Require Import Generated.bm_scaffold_gen. +Require Import Constraints.field_order_lift. +Require Import Constraints.range_field_pasta. +Require bm_rule. + +Lemma p_eq_pasta : p = pasta_p. +Proof. reflexivity. Qed. + +Lemma p_prime : prime p. +Proof. rewrite p_eq_pasta. exact pasta_prime. Qed. + +Lemma p_ge2 : 2 <= p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Definition HALF : Z := (p - 1) / 2. + +Lemma p_odd : p = 2 * HALF + 1. +Proof. vm_compute. reflexivity. Qed. + +Lemma HALF_big : 2 ^ 140 <= HALF. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Definition dc (a : Assignment) (c : nat) : Z := (a (c, 0%nat)) mod p. + +Definition A_BASE : nat := 0. +Definition B_BASE : nat := 4. +Definition OUT_BASE : nat := 8. +Definition C_BASE : nat := 16. +Definition OUTBIT_BASE : nat := 23. +Definition CBIT_BASE : nat := 535. +Definition N_ADVICE : nat := 931. +Definition TAG_BASE : nat := 2000. + +Definition a_l (a : Assignment) : list Z := [dc a 0; dc a 1; dc a 2; dc a 3]. +Definition b_l (a : Assignment) : list Z := [dc a 4; dc a 5; dc a 6; dc a 7]. +Definition out_l (a : Assignment) : list Z := + [dc a 8; dc a 9; dc a 10; dc a 11; dc a 12; dc a 13; dc a 14; dc a 15]. + +Definition cc (a : Assignment) (i : nat) : Z := dc a (16 + i). + +Lemma a_l_length : forall a, length (a_l a) = bm_rule.K. +Proof. reflexivity. Qed. +Lemma b_l_length : forall a, length (b_l a) = bm_rule.K. +Proof. reflexivity. Qed. +Lemma out_l_length : forall a, length (out_l a) = (2 * bm_rule.K)%nat. +Proof. reflexivity. Qed. + +Lemma dc_range : forall a c, 0 <= dc a c < p. +Proof. intros a c. unfold dc. apply Z.mod_pos_bound. pose proof p_ge2. lia. Qed. + +Definition bool_gate (c : nat) : Expr := + EMul (ECell (c, 0%nat)) (ESub (ECell (c, 0%nat)) (EConst 1)). + +Lemma in_firstn_in : forall (A : Type) n (l : list A) x, + In x (firstn n l) -> In x l. +Proof. + intros A n. induction n as [|n IH]; intros l x H; [ destruct H | ]. + destruct l as [|y l]; [ destruct H | ]. + cbn [firstn] in H. destruct H as [->|H]; [ left; reflexivity | ]. + right. exact (IH l x H). +Qed. + +Lemma in_skipn_in : forall (A : Type) n (l : list A) x, + In x (skipn n l) -> In x l. +Proof. + intros A n. induction n as [|n IH]; intros l x H; [ exact H | ]. + destruct l as [|y l]; [ destruct H | ]. + cbn [skipn] in H. right. exact (IH l x H). +Qed. + +Theorem head_is_the_booleanity_bank : + firstn 908 deployed_gates = map (fun j => bool_gate (23 + j)) (seq 0 908). +Proof. vm_compute. reflexivity. Qed. + +Lemma bool_gate_in_model : forall j, (j < 908)%nat -> + In (bool_gate (23 + j)) deployed_gates. +Proof. + intros j Hj. apply (in_firstn_in _ 908). + rewrite head_is_the_booleanity_bank. + apply (in_map (fun k => bool_gate (23 + k)%nat)). apply in_seq. lia. +Qed. + +Definition tail_gates : list Expr := Eval vm_compute in (skipn 908 deployed_gates). + +Lemma tail_gates_length : length tail_gates = 22%nat. +Proof. reflexivity. Qed. + +(* The model has 930 polynomial constraints (the 8 copy constraints are separate). *) +Lemma dg_len : length deployed_gates = 930%nat. +Proof. vm_compute. reflexivity. Qed. + +Lemma head_and_tail_exhaust_the_model : + (908 + length tail_gates)%nat = length deployed_gates. +Proof. rewrite tail_gates_length, dg_len. reflexivity. Qed. + +Definition tg_rec_out : list Expr := Eval vm_compute in (firstn 8 tail_gates). +Definition tg_rec_c : list Expr := Eval vm_compute in (firstn 6 (skipn 8 tail_gates)). +Definition tg_chain : list Expr := Eval vm_compute in (firstn 7 (skipn 14 tail_gates)). +Definition tg_end : list Expr := Eval vm_compute in (skipn 21 tail_gates). + +Lemma tg_rec_out_eq : tg_rec_out = firstn 8 tail_gates. Proof. vm_compute. reflexivity. Qed. +Lemma tg_rec_c_eq : tg_rec_c = firstn 6 (skipn 8 tail_gates). Proof. vm_compute. reflexivity. Qed. +Lemma tg_chain_eq : tg_chain = firstn 7 (skipn 14 tail_gates). Proof. vm_compute. reflexivity. Qed. +Lemma tg_end_eq : tg_end = skipn 21 tail_gates. Proof. vm_compute. reflexivity. Qed. + +Theorem tail_split_is_a_partition : + tg_rec_out ++ tg_rec_c ++ tg_chain ++ tg_end = tail_gates. +Proof. vm_compute. reflexivity. Qed. + +Lemma tg_rec_out_len : length tg_rec_out = 8%nat. Proof. reflexivity. Qed. +Lemma tg_rec_c_len : length tg_rec_c = 6%nat. Proof. reflexivity. Qed. +Lemma tg_chain_len : length tg_chain = 7%nat. Proof. reflexivity. Qed. +Lemma tg_end_len : length tg_end = 1%nat. Proof. reflexivity. Qed. + +Lemma in_tail_in_model : forall x, In x tail_gates -> In x deployed_gates. +Proof. + intros x H. apply (in_skipn_in _ 908). + change (skipn 908 deployed_gates) with tail_gates. exact H. +Qed. + +Lemma tg_rec_out_in : forall k, (k < 8)%nat -> In (nth k tg_rec_out (EConst 0)) deployed_gates. +Proof. + intros k Hk. apply in_tail_in_model. apply (in_firstn_in _ 8). + rewrite <- tg_rec_out_eq. apply nth_In. rewrite tg_rec_out_len. exact Hk. +Qed. +Lemma tg_rec_c_in : forall k, (k < 6)%nat -> In (nth k tg_rec_c (EConst 0)) deployed_gates. +Proof. + intros k Hk. apply in_tail_in_model. apply (in_skipn_in _ 8). apply (in_firstn_in _ 6). + rewrite <- tg_rec_c_eq. apply nth_In. rewrite tg_rec_c_len. exact Hk. +Qed. +Lemma tg_chain_in : forall k, (k < 7)%nat -> In (nth k tg_chain (EConst 0)) deployed_gates. +Proof. + intros k Hk. apply in_tail_in_model. apply (in_skipn_in _ 14). apply (in_firstn_in _ 7). + rewrite <- tg_chain_eq. apply nth_In. rewrite tg_chain_len. exact Hk. +Qed. +Lemma tg_end_in : In (nth 0 tg_end (EConst 0)) deployed_gates. +Proof. + apply in_tail_in_model. apply (in_skipn_in _ 21). + rewrite <- tg_end_eq. apply nth_In. rewrite tg_end_len. lia. +Qed. + +Definition CANON_bm (a : Assignment) : Prop := + (forall i, (i < 4)%nat -> 0 <= dc a (0 + i) < p) + /\ (forall i, (i < 4)%nat -> 0 <= dc a (4 + i) < p) + /\ (forall i, (i < 8)%nat -> 0 <= dc a (8 + i) < p). + +Theorem CANON_is_free : forall a, CANON_bm a. +Proof. intro a. split; [ | split ]; intros i _; apply dc_range. Qed. + +Definition PINS_bm (a : Assignment) : Prop := + forall j, (j < 8)%nat -> dc a (8 + j) = (a (2000%nat, j)) mod p. + +Theorem answer_pins_are_DERIVED : forall a, sat deployed_model a -> PINS_bm a. +Proof. + intros a [_ Hc] j Hj. unfold dc. + do 8 (destruct j as [|j]; + [ first [ exact (copy_get a _ _ Hc in_copy_1) | exact (copy_get a _ _ Hc in_copy_2) + | exact (copy_get a _ _ Hc in_copy_3) | exact (copy_get a _ _ Hc in_copy_4) + | exact (copy_get a _ _ Hc in_copy_5) | exact (copy_get a _ _ Hc in_copy_6) + | exact (copy_get a _ _ Hc in_copy_7) | exact (copy_get a _ _ Hc in_copy_8) ] | ]). + lia. +Qed. + +Theorem every_bit_cell_is_boolean : forall a, + sat deployed_model a -> + forall j, (j < 908)%nat -> + (a ((23 + j)%nat, 0%nat)) mod p = 0 \/ (a ((23 + j)%nat, 0%nat)) mod p = 1. +Proof. + intros a [Hg _] j Hj. + pose proof (Hg _ (bool_gate_in_model j Hj)) as H. + unfold gate_holds in H. cbn [eval] in H. + apply (range_field.bool_mod_forces_01 p p_prime). + replace (a ((23 + j)%nat, 0%nat) * a ((23 + j)%nat, 0%nat) - a ((23 + j)%nat, 0%nat)) + with (a ((23 + j)%nat, 0%nat) * (a ((23 + j)%nat, 0%nat) - 1)) by ring. + exact H. +Qed. + +Definition bits_at (a : Assignment) (b : nat) : nat -> Z := + fun j => a ((b + j)%nat, 0%nat). + +Lemma bank_bits_boolean : forall a, + sat deployed_model a -> + forall b n, (23 <= b)%nat -> (b + n <= 931)%nat -> + forall j, (j < n)%nat -> + (bits_at a b j) mod p = 0 \/ (bits_at a b j) mod p = 1. +Proof. + intros a Hs b n Hb Hbn j Hj. unfold bits_at. + replace (b + j)%nat with (23 + (b - 23 + j))%nat by lia. + apply (every_bit_cell_is_boolean a Hs). lia. +Qed. + +Lemma wpow64_le_p : wpow 64 <= p. +Proof. rewrite p_eq_pasta. exact wpow64_le_pasta. Qed. +Lemma wpow66_le_p : wpow 66 <= p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. +Lemma wpow64_val : wpow 64 = 18446744073709551616. +Proof. vm_compute. reflexivity. Qed. +Lemma wpow66_val : wpow 66 = 73786976294838206464. +Proof. vm_compute. reflexivity. Qed. + +Lemma range_from_gate : forall a b n v, + sat deployed_model a -> + (23 <= b)%nat -> (b + n <= 931)%nat -> + wpow n <= p -> + (bitsum (bits_at a b) n - v) mod p = 0 -> + 0 <= v mod p < wpow n. +Proof. + intros a b n v Hs Hb Hbn Hw Hres. + destruct (order_lift p p_ge2 (bits_at a b) n v Hw + (bank_bits_boolean a Hs b n Hb Hbn) Hres) as [_ Hr]. + exact Hr. +Qed. +Lemma ev_rec_out_0 : forall a, eval a (nth 0 tg_rec_out (EConst 0)) + = bitsum (bits_at a 23) 64 - a (8%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_1 : forall a, eval a (nth 1 tg_rec_out (EConst 0)) + = bitsum (bits_at a 87) 64 - a (9%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_2 : forall a, eval a (nth 2 tg_rec_out (EConst 0)) + = bitsum (bits_at a 151) 64 - a (10%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_3 : forall a, eval a (nth 3 tg_rec_out (EConst 0)) + = bitsum (bits_at a 215) 64 - a (11%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_4 : forall a, eval a (nth 4 tg_rec_out (EConst 0)) + = bitsum (bits_at a 279) 64 - a (12%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_5 : forall a, eval a (nth 5 tg_rec_out (EConst 0)) + = bitsum (bits_at a 343) 64 - a (13%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_6 : forall a, eval a (nth 6 tg_rec_out (EConst 0)) + = bitsum (bits_at a 407) 64 - a (14%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_out_7 : forall a, eval a (nth 7 tg_rec_out (EConst 0)) + = bitsum (bits_at a 471) 64 - a (15%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_out eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_0 : forall a, eval a (nth 0 tg_rec_c (EConst 0)) + = bitsum (bits_at a 535) 66 - a (16%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_1 : forall a, eval a (nth 1 tg_rec_c (EConst 0)) + = bitsum (bits_at a 601) 66 - a (17%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_2 : forall a, eval a (nth 2 tg_rec_c (EConst 0)) + = bitsum (bits_at a 667) 66 - a (18%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_3 : forall a, eval a (nth 3 tg_rec_c (EConst 0)) + = bitsum (bits_at a 733) 66 - a (19%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_4 : forall a, eval a (nth 4 tg_rec_c (EConst 0)) + = bitsum (bits_at a 799) 66 - a (20%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. +Lemma ev_rec_c_5 : forall a, eval a (nth 5 tg_rec_c (EConst 0)) + = bitsum (bits_at a 865) 66 - a (21%nat, 0%nat). +Proof. intro a. unfold bits_at. cbn [nth tg_rec_c eval bitsum wpow Nat.add]. ring. Qed. + +Theorem rng_out : forall a, sat deployed_model a -> + forall i, (i < 8)%nat -> 0 <= dc a (8 + i) < 18446744073709551616. +Proof. + intros a Hs i Hi. unfold dc. rewrite <- wpow64_val. + destruct Hs as [Hg Hc]. + destruct i as [|i]. + { apply (range_from_gate a 23 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_0. exact (Hg _ (tg_rec_out_in 0 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 87 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_1. exact (Hg _ (tg_rec_out_in 1 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 151 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_2. exact (Hg _ (tg_rec_out_in 2 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 215 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_3. exact (Hg _ (tg_rec_out_in 3 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 279 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_4. exact (Hg _ (tg_rec_out_in 4 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 343 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_5. exact (Hg _ (tg_rec_out_in 5 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 407 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_6. exact (Hg _ (tg_rec_out_in 6 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 471 64 _ (conj Hg Hc)); [ lia | lia | exact wpow64_le_p | ]. + rewrite <- ev_rec_out_7. exact (Hg _ (tg_rec_out_in 7 ltac:(lia))). } + lia. +Qed. + +Theorem rng_c : forall a, sat deployed_model a -> + forall i, (i < 6)%nat -> 0 <= cc a i < 73786976294838206464. +Proof. + intros a Hs i Hi. unfold cc, dc. rewrite <- wpow66_val. + destruct Hs as [Hg Hc]. + destruct i as [|i]. + { apply (range_from_gate a 535 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_0. exact (Hg _ (tg_rec_c_in 0 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 601 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_1. exact (Hg _ (tg_rec_c_in 1 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 667 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_2. exact (Hg _ (tg_rec_c_in 2 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 733 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_3. exact (Hg _ (tg_rec_c_in 3 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 799 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_4. exact (Hg _ (tg_rec_c_in 4 ltac:(lia))). } + destruct i as [|i]. + { apply (range_from_gate a 865 66 _ (conj Hg Hc)); [ lia | lia | exact wpow66_le_p | ]. + rewrite <- ev_rec_c_5. exact (Hg _ (tg_rec_c_in 5 ltac:(lia))). } + lia. +Qed. + +Print Assumptions p_prime. +Print Assumptions p_odd. +Print Assumptions HALF_big. +Print Assumptions dc_range. +Print Assumptions head_is_the_booleanity_bank. +Print Assumptions head_and_tail_exhaust_the_model. +Print Assumptions tail_split_is_a_partition. +Print Assumptions CANON_is_free. +Print Assumptions answer_pins_are_DERIVED. +Print Assumptions every_bit_cell_is_boolean. +Print Assumptions rng_out. +Print Assumptions rng_c. diff --git a/coq-legacy/constraints/bm_soundness.v b/coq-legacy/constraints/bm_soundness.v new file mode 100644 index 0000000..d910b4b --- /dev/null +++ b/coq-legacy/constraints/bm_soundness.v @@ -0,0 +1,400 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Soundness: every accepted filling whose inputs satisfy the input assumption yields a triple the + relation accepts (bridge_sound). Also, at the input whose limbs are all 2^64 - 1: an accepted filling + decodes to it and its product, and no accepted filling decodes to an output that equals the product + only modulo p, or to a named wrong output. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +Open Scope Z_scope. + +Require Import Generated.bm_model_gen. +Require Import Generated.bm_wires_gen. +Require Import Generated.bm_scaffold_gen. +Require Import Generated.bm_necessity_gen. +Require Import Constraints.field_order_lift. +Require Import Constraints.range_field_pasta. +Require Import Constraints.bits_kit. +Require Import Constraints.bm_semantic. +Require Import Constraints.bm_model_facts. +Require bm_rule. + +Definition CONV (a b : list Z) : list Z := + [nth 0 a 0 * nth 0 b 0; + nth 0 a 0 * nth 1 b 0 + nth 1 a 0 * nth 0 b 0; + nth 0 a 0 * nth 2 b 0 + nth 1 a 0 * nth 1 b 0 + nth 2 a 0 * nth 0 b 0; + nth 0 a 0 * nth 3 b 0 + nth 1 a 0 * nth 2 b 0 + nth 2 a 0 * nth 1 b 0 + nth 3 a 0 * nth 0 b 0; + nth 1 a 0 * nth 3 b 0 + nth 2 a 0 * nth 2 b 0 + nth 3 a 0 * nth 1 b 0; + nth 2 a 0 * nth 3 b 0 + nth 3 a 0 * nth 2 b 0; + nth 3 a 0 * nth 3 b 0]. + +Lemma CONV_length : forall a b, length (CONV a b) = 7%nat. +Proof. reflexivity. Qed. + +Theorem VAL_CONV : forall a b, length a = 4%nat -> length b = 4%nat -> + bm_rule.VAL (CONV a b) = bm_rule.VAL a * bm_rule.VAL b. +Proof. + intros a b Ha Hb. + destruct a as [|a0 [|a1 [|a2 [|a3 [|? ?]]]]]; cbn [length] in Ha; try lia. + destruct b as [|b0 [|b1 [|b2 [|b3 [|? ?]]]]]; cbn [length] in Hb; try lia. + unfold CONV. cbn [nth]. symmetry. apply bm_rule.VAL_product_is_the_convolution. +Qed. + +Lemma nth_limb : forall v i, Forall bm_rule.limb_ok v -> 0 <= nth i v 0 <= bm_rule.B - 1. +Proof. + intros v i Hf. destruct (Nat.lt_ge_cases i (length v)) as [Hi|Hi]. + - rewrite Forall_forall in Hf. pose proof (Hf _ (nth_In v 0 Hi)) as H. + unfold bm_rule.limb_ok in H. lia. + - rewrite nth_overflow by exact Hi. rewrite bm_rule.B_value. lia. +Qed. + +Lemma prod_bound : forall x y, 0 <= x <= bm_rule.B - 1 -> 0 <= y <= bm_rule.B - 1 -> + 0 <= x * y <= (bm_rule.B - 1) * (bm_rule.B - 1). +Proof. intros x y Hx Hy. split; [ nia | apply Z.mul_le_mono_nonneg; lia ]. Qed. + +Theorem CONV_elem_bound : forall a b, bm_rule.PRE_bm a b -> + forall m, 0 <= nth m (CONV a b) 0 <= 4 * (bm_rule.B - 1) * (bm_rule.B - 1). +Proof. + intros a b [_ [_ [Fa Fb]]] m. + pose proof (fun i => nth_limb a i Fa) as HA. pose proof (fun j => nth_limb b j Fb) as HB. + pose proof (prod_bound _ _ (HA 0%nat) (HB 0%nat)) as P00. + pose proof (prod_bound _ _ (HA 0%nat) (HB 1%nat)) as P01. + pose proof (prod_bound _ _ (HA 0%nat) (HB 2%nat)) as P02. + pose proof (prod_bound _ _ (HA 0%nat) (HB 3%nat)) as P03. + pose proof (prod_bound _ _ (HA 1%nat) (HB 0%nat)) as P10. + pose proof (prod_bound _ _ (HA 1%nat) (HB 1%nat)) as P11. + pose proof (prod_bound _ _ (HA 1%nat) (HB 2%nat)) as P12. + pose proof (prod_bound _ _ (HA 1%nat) (HB 3%nat)) as P13. + pose proof (prod_bound _ _ (HA 2%nat) (HB 0%nat)) as P20. + pose proof (prod_bound _ _ (HA 2%nat) (HB 1%nat)) as P21. + pose proof (prod_bound _ _ (HA 2%nat) (HB 2%nat)) as P22. + pose proof (prod_bound _ _ (HA 2%nat) (HB 3%nat)) as P23. + pose proof (prod_bound _ _ (HA 3%nat) (HB 0%nat)) as P30. + pose proof (prod_bound _ _ (HA 3%nat) (HB 1%nat)) as P31. + pose proof (prod_bound _ _ (HA 3%nat) (HB 2%nat)) as P32. + pose proof (prod_bound _ _ (HA 3%nat) (HB 3%nat)) as P33. + destruct (Nat.lt_ge_cases m 7) as [Hm|Hm]. + - rewrite bm_rule.B_value in *. + do 7 (destruct m as [|m]; [ cbn [CONV nth]; lia | ]). lia. + - rewrite nth_overflow by (rewrite CONV_length; exact Hm). rewrite bm_rule.B_value. lia. +Qed. + +Lemma VAL_firstn_S : forall i v, + bm_rule.VAL (firstn (S i) v) + = bm_rule.VAL (firstn i v) + bm_rule.B ^ Z.of_nat i * nth i v 0. +Proof. + induction i as [|i IH]; intro v; destruct v as [|x t]. + - cbn [firstn nth Z.of_nat]. rewrite bm_rule.VAL_nil. ring. + - cbn [firstn nth Z.of_nat]. rewrite bm_rule.VAL_cons, !bm_rule.VAL_nil. ring. + - cbn [firstn nth]. rewrite bm_rule.VAL_nil. ring. + - change (firstn (S (S i)) (x :: t)) with (x :: firstn (S i) t). + change (firstn (S i) (x :: t)) with (x :: firstn i t). + change (nth (S i) (x :: t) 0) with (nth i t 0). + rewrite !bm_rule.VAL_cons, (IH t). + rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. ring. +Qed. + +Definition prevc (c : nat -> Z) (i : nat) : Z := + match i with O => 0 | S j => c j end. + +Theorem prefix_telescopes : forall (s o : list Z) (c : nat -> Z) n, + (forall i, (i <= n)%nat -> nth i s 0 - nth i o 0 = c i * bm_rule.B - prevc c i) -> + bm_rule.VAL (firstn (S n) s) - bm_rule.VAL (firstn (S n) o) + = c n * bm_rule.B ^ Z.of_nat (S n). +Proof. + intros s o c n. induction n as [|n IH]; intro H. + - rewrite !(VAL_firstn_S 0). cbn [firstn Z.of_nat]. rewrite bm_rule.VAL_nil. + pose proof (H 0%nat ltac:(lia)) as H0. cbn [prevc] in H0. + rewrite Z.pow_0_r. rewrite Z.pow_1_r. lia. + - rewrite !(VAL_firstn_S (S n)). + pose proof (IH (fun i Hi => H i ltac:(lia))) as IHn. + pose proof (H (S n) ltac:(lia)) as Hs. cbn [prevc] in Hs. + replace (bm_rule.VAL (firstn (S n) s) + bm_rule.B ^ Z.of_nat (S n) * nth (S n) s 0 - + (bm_rule.VAL (firstn (S n) o) + bm_rule.B ^ Z.of_nat (S n) * nth (S n) o 0)) + with ((bm_rule.VAL (firstn (S n) s) - bm_rule.VAL (firstn (S n) o)) + + bm_rule.B ^ Z.of_nat (S n) * (nth (S n) s 0 - nth (S n) o 0)) by ring. + rewrite IHn, Hs. + rewrite (Nat2Z.inj_succ (S n)), (Z.pow_succ_r _ (Z.of_nat (S n))) by lia. ring. +Qed. + +Lemma cong_add : forall x y x' y', x mod p = x' mod p -> y mod p = y' mod p -> + (x + y) mod p = (x' + y') mod p. +Proof. intros. rewrite Zplus_mod, H, H0, <- Zplus_mod. reflexivity. Qed. +Lemma cong_sub : forall x y x' y', x mod p = x' mod p -> y mod p = y' mod p -> + (x - y) mod p = (x' - y') mod p. +Proof. intros. rewrite Zminus_mod, H, H0, <- Zminus_mod. reflexivity. Qed. +Lemma cong_mul : forall x y x' y', x mod p = x' mod p -> y mod p = y' mod p -> + (x * y) mod p = (x' * y') mod p. +Proof. intros. rewrite Zmult_mod, H, H0, <- Zmult_mod. reflexivity. Qed. +Lemma cong_dc : forall a c, (dc a c) mod p = (a (c, 0%nat)) mod p. +Proof. intros. unfold dc. apply Zmod_mod. Qed. +Lemma cong_cc : forall a i, (cc a i) mod p = (a ((16 + i)%nat, 0%nat)) mod p. +Proof. intros. unfold cc. apply cong_dc. Qed. + +Ltac cong := repeat first + [ apply cong_dc | apply cong_cc | apply cong_mul | apply cong_sub | apply cong_add | reflexivity ]. + +Lemma p_pos : 0 < p. Proof. pose proof p_ge2. lia. Qed. + +Definition EEND (a : Assignment) : Z := cc a 6 - dc a 15. +Definition RWEND (a : Assignment) : Z := a (22%nat, 0%nat) - a (15%nat, 0%nat). +Lemma ev_end : forall a, eval a (nth 0 tg_end (EConst 0)) = RWEND a. +Proof. intro a. unfold RWEND. cbn [nth tg_end eval]. ring. Qed. +Lemma cong_EEND : forall a, (EEND a) mod p = (RWEND a) mod p. +Proof. intro a. unfold EEND, RWEND. cong. Qed. + +Theorem the_last_carry_cell_is_out7 : forall a, sat deployed_model a -> cc a 6 = dc a 15. +Proof. + intros a Hs. + assert (HE : EEND a = 0). + { apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_EEND, <- ev_end. destruct Hs as [Hg _]. exact (Hg _ tg_end_in). } + + all: pose proof (dc_range a 22); pose proof (dc_range a 15); + unfold EEND; change (cc a 6) with (dc a 22); lia. } + unfold EEND in HE. lia. +Qed. + +Definition E0 (a : Assignment) : Z := nth 0 (CONV (a_l a) (b_l a)) 0 - dc a 8 - cc a 0 * 18446744073709551616. +Definition RW0 (a : Assignment) : Z := a (0%nat, 0%nat) * a (4%nat, 0%nat) - a (8%nat, 0%nat) - a (16%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_0 : forall a, eval a (nth 0 tg_chain (EConst 0)) = RW0 a. +Proof. intro a. unfold RW0. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E0 : forall a, (E0 a) mod p = (RW0 a) mod p. +Proof. intro a. unfold E0, RW0, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E1 (a : Assignment) : Z := nth 1 (CONV (a_l a) (b_l a)) 0 - dc a 9 + cc a 0 - cc a 1 * 18446744073709551616. +Definition RW1 (a : Assignment) : Z := a (0%nat, 0%nat) * a (5%nat, 0%nat) + a (1%nat, 0%nat) * a (4%nat, 0%nat) - a (9%nat, 0%nat) + a (16%nat, 0%nat) - a (17%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_1 : forall a, eval a (nth 1 tg_chain (EConst 0)) = RW1 a. +Proof. intro a. unfold RW1. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E1 : forall a, (E1 a) mod p = (RW1 a) mod p. +Proof. intro a. unfold E1, RW1, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E2 (a : Assignment) : Z := nth 2 (CONV (a_l a) (b_l a)) 0 - dc a 10 + cc a 1 - cc a 2 * 18446744073709551616. +Definition RW2 (a : Assignment) : Z := a (0%nat, 0%nat) * a (6%nat, 0%nat) + a (1%nat, 0%nat) * a (5%nat, 0%nat) + a (2%nat, 0%nat) * a (4%nat, 0%nat) - a (10%nat, 0%nat) + a (17%nat, 0%nat) - a (18%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_2 : forall a, eval a (nth 2 tg_chain (EConst 0)) = RW2 a. +Proof. intro a. unfold RW2. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E2 : forall a, (E2 a) mod p = (RW2 a) mod p. +Proof. intro a. unfold E2, RW2, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E3 (a : Assignment) : Z := nth 3 (CONV (a_l a) (b_l a)) 0 - dc a 11 + cc a 2 - cc a 3 * 18446744073709551616. +Definition RW3 (a : Assignment) : Z := a (0%nat, 0%nat) * a (7%nat, 0%nat) + a (1%nat, 0%nat) * a (6%nat, 0%nat) + a (2%nat, 0%nat) * a (5%nat, 0%nat) + a (3%nat, 0%nat) * a (4%nat, 0%nat) - a (11%nat, 0%nat) + a (18%nat, 0%nat) - a (19%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_3 : forall a, eval a (nth 3 tg_chain (EConst 0)) = RW3 a. +Proof. intro a. unfold RW3. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E3 : forall a, (E3 a) mod p = (RW3 a) mod p. +Proof. intro a. unfold E3, RW3, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E4 (a : Assignment) : Z := nth 4 (CONV (a_l a) (b_l a)) 0 - dc a 12 + cc a 3 - cc a 4 * 18446744073709551616. +Definition RW4 (a : Assignment) : Z := a (1%nat, 0%nat) * a (7%nat, 0%nat) + a (2%nat, 0%nat) * a (6%nat, 0%nat) + a (3%nat, 0%nat) * a (5%nat, 0%nat) - a (12%nat, 0%nat) + a (19%nat, 0%nat) - a (20%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_4 : forall a, eval a (nth 4 tg_chain (EConst 0)) = RW4 a. +Proof. intro a. unfold RW4. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E4 : forall a, (E4 a) mod p = (RW4 a) mod p. +Proof. intro a. unfold E4, RW4, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E5 (a : Assignment) : Z := nth 5 (CONV (a_l a) (b_l a)) 0 - dc a 13 + cc a 4 - cc a 5 * 18446744073709551616. +Definition RW5 (a : Assignment) : Z := a (2%nat, 0%nat) * a (7%nat, 0%nat) + a (3%nat, 0%nat) * a (6%nat, 0%nat) - a (13%nat, 0%nat) + a (20%nat, 0%nat) - a (21%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_5 : forall a, eval a (nth 5 tg_chain (EConst 0)) = RW5 a. +Proof. intro a. unfold RW5. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E5 : forall a, (E5 a) mod p = (RW5 a) mod p. +Proof. intro a. unfold E5, RW5, CONV, a_l, b_l. cbn [nth]. cong. Qed. +Definition E6 (a : Assignment) : Z := nth 6 (CONV (a_l a) (b_l a)) 0 - dc a 14 + cc a 5 - cc a 6 * 18446744073709551616. +Definition RW6 (a : Assignment) : Z := a (3%nat, 0%nat) * a (7%nat, 0%nat) - a (14%nat, 0%nat) + a (21%nat, 0%nat) - a (22%nat, 0%nat) * 18446744073709551616. +Lemma ev_chain_6 : forall a, eval a (nth 6 tg_chain (EConst 0)) = RW6 a. +Proof. intro a. unfold RW6. cbn [nth tg_chain eval]. ring. Qed. +Lemma cong_E6 : forall a, (E6 a) mod p = (RW6 a) mod p. +Proof. intro a. unfold E6, RW6, CONV, a_l, b_l. cbn [nth]. cong. Qed. + +Lemma E0_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E0 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E0, <- ev_chain_0. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 0%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 0%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 0%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 0%nat ltac:(lia)) as Hc; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E0; lia. +Qed. +Lemma E1_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E1 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E1, <- ev_chain_1. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 1%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 1%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 1%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 1%nat ltac:(lia)) as Hc; + pose proof (rng_c a Hs 0%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E1; lia. +Qed. +Lemma E2_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E2 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E2, <- ev_chain_2. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 2%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 2%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 2%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 2%nat ltac:(lia)) as Hc; + pose proof (rng_c a Hs 1%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E2; lia. +Qed. +Lemma E3_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E3 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E3, <- ev_chain_3. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 3%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 3%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 3%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 3%nat ltac:(lia)) as Hc; + pose proof (rng_c a Hs 2%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E3; lia. +Qed. +Lemma E4_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E4 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E4, <- ev_chain_4. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 4%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 4%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 4%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 4%nat ltac:(lia)) as Hc; + pose proof (rng_c a Hs 3%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E4; lia. +Qed. +Lemma E5_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E5 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E5, <- ev_chain_5. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 5%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 5%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 5%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (rng_c a Hs 5%nat ltac:(lia)) as Hc; + pose proof (rng_c a Hs 4%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E5; lia. +Qed. +Lemma E6_zero : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> E6 a = 0. +Proof. + intros a Hs Hpre. apply (no_wrap_zero p); [ exact p_pos | | | ]. + 3: { rewrite cong_E6, <- ev_chain_6. destruct Hs as [Hg _]. + exact (Hg _ (tg_chain_in 6%nat ltac:(lia))). } + all: pose proof (CONV_elem_bound (a_l a) (b_l a) Hpre 6%nat) as Hv; rewrite bm_rule.B_value in Hv; + pose proof (rng_out a Hs 6%nat ltac:(lia)) as Ho; cbn [Nat.add] in Ho; + pose proof (the_last_carry_cell_is_out7 a Hs) as H6; pose proof (rng_out a Hs 7%nat ltac:(lia)) as Hc; cbn [Nat.add] in Hc; + pose proof (rng_c a Hs 5%nat ltac:(lia)) as Hp; + pose proof p_odd; pose proof HALF_big; + change (2 ^ 140) with 1393796574908163946345982392040522594123776 in *; + unfold E6; lia. +Qed. + +Theorem circuit_running : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> + forall i, (i <= 6)%nat -> + nth i (CONV (a_l a) (b_l a)) 0 - nth i (out_l a) 0 = cc a i * bm_rule.B - prevc (cc a) i. +Proof. + intros a Hs Hpre i Hi. rewrite bm_rule.B_value. + destruct i as [|i]; [ pose proof (E0_zero a Hs Hpre) as HE; unfold E0 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E1_zero a Hs Hpre) as HE; unfold E1 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E2_zero a Hs Hpre) as HE; unfold E2 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E3_zero a Hs Hpre) as HE; unfold E3 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E4_zero a Hs Hpre) as HE; unfold E4 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E5_zero a Hs Hpre) as HE; unfold E5 in HE; cbn [prevc nth out_l]; lia | ]. + destruct i as [|i]; [ pose proof (E6_zero a Hs Hpre) as HE; unfold E6 in HE; cbn [prevc nth out_l]; lia | ]. + lia. +Qed. + +Lemma CONV_firstn : forall a b, firstn 7 (CONV a b) = CONV a b. +Proof. reflexivity. Qed. +Lemma out_l_skipn : forall a, skipn 7 (out_l a) = [dc a 15]. +Proof. reflexivity. Qed. + +Theorem values_agree : forall a, sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> + bm_rule.VAL (out_l a) = bm_rule.VAL (a_l a) * bm_rule.VAL (b_l a). +Proof. + intros a Hs Hpre. + pose proof (prefix_telescopes (CONV (a_l a) (b_l a)) (out_l a) (cc a) 6 + (fun i Hi => circuit_running a Hs Hpre i Hi)) as T. + rewrite CONV_firstn in T. + rewrite (VAL_CONV (a_l a) (b_l a) (a_l_length a) (b_l_length a)) in T. + pose proof (bm_rule.VAL_firstn_skipn 7 (out_l a)) as S7. + rewrite out_l_skipn in S7. + assert (Hv : bm_rule.VAL [dc a 15] = dc a 15) + by (rewrite bm_rule.VAL_cons, bm_rule.VAL_nil; ring). + rewrite Hv in S7. + rewrite (the_last_carry_cell_is_out7 a Hs) in T. + assert (HC : dc a 15 * bm_rule.B ^ Z.of_nat 7 = bm_rule.B ^ Z.of_nat 7 * dc a 15) by ring. + lia. +Qed. + +(* Soundness, for accepted fillings whose inputs satisfy the input assumption. *) +Theorem bridge_sound : forall a, + sat deployed_model a -> + CANON_bm a -> + bm_rule.PRE_bm (a_l a) (b_l a) -> + bm_rule.REL_bm (a_l a) (b_l a) (out_l a). +Proof. + intros a Hs _ Hpre. + split; [ reflexivity | ]. + split; [ exact (out_limbs_in_range a Hs) | exact (values_agree a Hs Hpre) ]. +Qed. + +Theorem bridge_sound_without_CANON : forall a, + sat deployed_model a -> bm_rule.PRE_bm (a_l a) (b_l a) -> + bm_rule.REL_bm (a_l a) (b_l a) (out_l a). +Proof. intros a Hs Hpre. exact (bridge_sound a Hs (CANON_is_free a) Hpre). Qed. + +Theorem nonvacuity_the_honest_row_decodes_to_the_corner : + sat deployed_model wit_honest_bm + /\ a_l wit_honest_bm = bm_rule.CORNER + /\ b_l wit_honest_bm = bm_rule.CORNER + /\ out_l wit_honest_bm = bm_rule.CORNER_OUT. +Proof. + split; [ exact honest_full_sat_bm | ]. + split; [ vm_compute; reflexivity | ]. split; vm_compute; reflexivity. +Qed. + +Theorem nonvacuity_the_corner_is_ACCEPTED : + bm_rule.REL_bm (a_l wit_honest_bm) (b_l wit_honest_bm) (out_l wit_honest_bm). +Proof. + destruct nonvacuity_the_honest_row_decodes_to_the_corner as [Hs [Ha [Hb _]]]. + apply (bridge_sound_without_CANON _ Hs). rewrite Ha, Hb. exact bm_rule.corner_pre. +Qed. + +Theorem no_satisfying_row_decodes_to_the_modular_alias : forall a, + sat deployed_model a -> + ~ (a_l a = bm_rule.CORNER /\ b_l a = bm_rule.CORNER /\ out_l a = CORNER_ALIAS). +Proof. + intros a Hs [Ha [Hb Ho]]. + destruct REL_is_a_value_equality_not_mod_q as [_ [_ [_ [_ [_ Hn]]]]]. apply Hn. + rewrite <- Ha at 1. rewrite <- Hb, <- Ho. + apply (bridge_sound_without_CANON a Hs). rewrite Ha, Hb. exact bm_rule.corner_pre. +Qed. + +Theorem no_satisfying_row_decodes_to_the_corner_fraud : forall a, + sat deployed_model a -> + ~ (a_l a = bm_rule.CORNER /\ b_l a = bm_rule.CORNER /\ out_l a = bm_rule.CORNER_FRAUD). +Proof. + intros a Hs [Ha [Hb Ho]]. apply bm_rule.corner_fraud_refused. + rewrite <- Ha at 1. rewrite <- Hb, <- Ho. + apply (bridge_sound_without_CANON a Hs). rewrite Ha, Hb. exact bm_rule.corner_pre. +Qed. + +Print Assumptions VAL_CONV. +Print Assumptions nth_limb. +Print Assumptions prod_bound. +Print Assumptions CONV_elem_bound. +Print Assumptions VAL_firstn_S. +Print Assumptions prefix_telescopes. +Print Assumptions the_last_carry_cell_is_out7. +Print Assumptions circuit_running. +Print Assumptions values_agree. +Print Assumptions bridge_sound. +Print Assumptions bridge_sound_without_CANON. +Print Assumptions nonvacuity_the_honest_row_decodes_to_the_corner. +Print Assumptions nonvacuity_the_corner_is_ACCEPTED. +Print Assumptions no_satisfying_row_decodes_to_the_modular_alias. +Print Assumptions no_satisfying_row_decodes_to_the_corner_fraud. diff --git a/coq-legacy/constraints/field_order_lift.v b/coq-legacy/constraints/field_order_lift.v new file mode 100644 index 0000000..1d62089 --- /dev/null +++ b/coq-legacy/constraints/field_order_lift.v @@ -0,0 +1,98 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Lifting from the field to the integers (order_lift): when 2^n is at most p, each bit is 0 or 1 modulo p, + and the weighted bit sum equals v modulo p, the residue of v modulo p lies in [0, 2^n) and equals the + weighted sum of the canonical bits. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia. Open Scope Z_scope. +Require Import Constraints.range_field_pasta. + +Section OrderLift. + Context (p : Z) (Hp2 : 2 <= p). + + Fixpoint wpow (k:nat) : Z := match k with O => 1 | S j => 2 * wpow j end. + + Lemma wpow_pos : forall k, 0 < wpow k. + Proof. induction k as [|k IH]; cbn [wpow]; lia. Qed. + + Fixpoint bitsum (bits:nat->Z) (n:nat) : Z := + match n with O => 0 | S k => bitsum bits k + bits k * wpow k end. + + Definition cbitsum (bits:nat->Z) (n:nat) : Z := + bitsum (fun i => bits i mod p) n. + + Lemma cbitsum_bound : forall bits n, + (forall i, (i bits i mod p = 0 \/ bits i mod p = 1) -> + 0 <= cbitsum bits n <= wpow n - 1. + Proof. + intros bits n; revert bits. induction n as [|k IH]; intros bits Hb. + - cbn [cbitsum bitsum wpow]. lia. + - assert (Hk : bits k mod p = 0 \/ bits k mod p = 1) by (apply Hb; lia). + assert (Hrec : forall i, (i bits i mod p = 0 \/ bits i mod p = 1) + by (intros i Hi; apply Hb; lia). + specialize (IH bits Hrec). + pose proof (wpow_pos k) as Hwk. + unfold cbitsum in *. cbn [bitsum wpow]. + destruct Hk as [E|E]; rewrite E; lia. + Qed. + + Lemma bitsum_mod : forall bits n, + bitsum bits n mod p = cbitsum bits n mod p. + Proof. + intros bits n; revert bits. induction n as [|k IH]; intros bits. + - reflexivity. + - unfold cbitsum in *. cbn [bitsum]. + rewrite (Zplus_mod (bitsum bits k)), IH. + rewrite (Zplus_mod (bitsum (fun i => bits i mod p) k)). + f_equal. f_equal. + symmetry. apply Zmult_mod_idemp_l. + Qed. + + Lemma order_lift : forall bits n v, + wpow n <= p -> + (forall i, (i bits i mod p = 0 \/ bits i mod p = 1) -> + (bitsum bits n - v) mod p = 0 -> + v mod p = cbitsum bits n /\ 0 <= v mod p < wpow n. + Proof. + intros bits n v Hnw Hb Hres. + pose proof (cbitsum_bound bits n Hb) as [Hlo Hhi]. + + assert (Hcbmod : cbitsum bits n mod p = cbitsum bits n) + by (apply Z.mod_small; lia). + + pose proof (Z.mod_pos_bound (bitsum bits n) p ltac:(lia)) as [Ha1 Ha2]. + pose proof (Z.mod_pos_bound v p ltac:(lia)) as [Hb1 Hb2]. + assert (Hd0 : ((bitsum bits n) mod p - v mod p) mod p = 0) + by (rewrite <- Zminus_mod; exact Hres). + apply Z.mod_divide in Hd0; [| lia]. + destruct Hd0 as [q Hq]. + assert (Hq0 : q = 0) by nia. subst q. + assert (Hvsum : v mod p = bitsum bits n mod p) by lia. + + assert (Hv : v mod p = cbitsum bits n) + by (rewrite Hvsum, bitsum_mod, Hcbmod; reflexivity). + split; [exact Hv | rewrite Hv; split; [exact Hlo | lia]]. + Qed. + +End OrderLift. + +Lemma pasta_ge2 : 2 <= pasta_p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Lemma wpow64_le_pasta : wpow 64 <= pasta_p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Lemma wpow14_le_pasta : wpow 14 <= pasta_p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Lemma wpow8_le_pasta : wpow 8 <= pasta_p. +Proof. apply Z.leb_le. vm_compute. reflexivity. Qed. + +Definition order_lift_pasta := order_lift pasta_p pasta_ge2. + +Print Assumptions order_lift. +Print Assumptions order_lift_pasta. +Print Assumptions wpow64_le_pasta. diff --git a/coq-legacy/constraints/gen/bm_model_gen.v b/coq-legacy/constraints/gen/bm_model_gen.v new file mode 100644 index 0000000..51bc22b --- /dev/null +++ b/coq-legacy/constraints/gen/bm_model_gen.v @@ -0,0 +1,1894 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + The circuit's constraint model, generated from our circuit implementation: the field prime p, the + polynomial constraints (deployed_gates) and the copy constraints (deployed_copy). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith List. Import ListNotations. Open Scope Z_scope. + +Definition Cell := (nat * nat)%type. +Inductive Expr := EConst (_:Z) | ECell (_:Cell) | EAdd (_ _:Expr) | ESub (_ _:Expr) | EMul (_ _:Expr) | ENeg (_:Expr) | EScaled (_:Expr) (_:Z). +Record CircuitModel := mk_model { cm_p:Z ; cm_gates:list Expr ; cm_copy:list (Cell*Cell) }. + +Definition p : Z := 28948022309329048855892746252171976963363056481941560715954676764349967630337. + +Definition deployed_gates : list Expr := + [ + + (EMul (ECell (23%nat, 0%nat)) (ESub (ECell (23%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (24%nat, 0%nat)) (ESub (ECell (24%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (25%nat, 0%nat)) (ESub (ECell (25%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (26%nat, 0%nat)) (ESub (ECell (26%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (27%nat, 0%nat)) (ESub (ECell (27%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (28%nat, 0%nat)) (ESub (ECell (28%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (29%nat, 0%nat)) (ESub (ECell (29%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (30%nat, 0%nat)) (ESub (ECell (30%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (31%nat, 0%nat)) (ESub (ECell (31%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (32%nat, 0%nat)) (ESub (ECell (32%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (33%nat, 0%nat)) (ESub (ECell (33%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (34%nat, 0%nat)) (ESub (ECell (34%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (35%nat, 0%nat)) (ESub (ECell (35%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (36%nat, 0%nat)) (ESub (ECell (36%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (37%nat, 0%nat)) (ESub (ECell (37%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (38%nat, 0%nat)) (ESub (ECell (38%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (39%nat, 0%nat)) (ESub (ECell (39%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (40%nat, 0%nat)) (ESub (ECell (40%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (41%nat, 0%nat)) (ESub (ECell (41%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (42%nat, 0%nat)) (ESub (ECell (42%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (43%nat, 0%nat)) (ESub (ECell (43%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (44%nat, 0%nat)) (ESub (ECell (44%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (45%nat, 0%nat)) (ESub (ECell (45%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (46%nat, 0%nat)) (ESub (ECell (46%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (47%nat, 0%nat)) (ESub (ECell (47%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (48%nat, 0%nat)) (ESub (ECell (48%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (49%nat, 0%nat)) (ESub (ECell (49%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (50%nat, 0%nat)) (ESub (ECell (50%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (51%nat, 0%nat)) (ESub (ECell (51%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (52%nat, 0%nat)) (ESub (ECell (52%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (53%nat, 0%nat)) (ESub (ECell (53%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (54%nat, 0%nat)) (ESub (ECell (54%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (55%nat, 0%nat)) (ESub (ECell (55%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (56%nat, 0%nat)) (ESub (ECell (56%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (57%nat, 0%nat)) (ESub (ECell (57%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (58%nat, 0%nat)) (ESub (ECell (58%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (59%nat, 0%nat)) (ESub (ECell (59%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (60%nat, 0%nat)) (ESub (ECell (60%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (61%nat, 0%nat)) (ESub (ECell (61%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (62%nat, 0%nat)) (ESub (ECell (62%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (63%nat, 0%nat)) (ESub (ECell (63%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (64%nat, 0%nat)) (ESub (ECell (64%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (65%nat, 0%nat)) (ESub (ECell (65%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (66%nat, 0%nat)) (ESub (ECell (66%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (67%nat, 0%nat)) (ESub (ECell (67%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (68%nat, 0%nat)) (ESub (ECell (68%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (69%nat, 0%nat)) (ESub (ECell (69%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (70%nat, 0%nat)) (ESub (ECell (70%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (71%nat, 0%nat)) (ESub (ECell (71%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (72%nat, 0%nat)) (ESub (ECell (72%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (73%nat, 0%nat)) (ESub (ECell (73%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (74%nat, 0%nat)) (ESub (ECell (74%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (75%nat, 0%nat)) (ESub (ECell (75%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (76%nat, 0%nat)) (ESub (ECell (76%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (77%nat, 0%nat)) (ESub (ECell (77%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (78%nat, 0%nat)) (ESub (ECell (78%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (79%nat, 0%nat)) (ESub (ECell (79%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (80%nat, 0%nat)) (ESub (ECell (80%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (81%nat, 0%nat)) (ESub (ECell (81%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (82%nat, 0%nat)) (ESub (ECell (82%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (83%nat, 0%nat)) (ESub (ECell (83%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (84%nat, 0%nat)) (ESub (ECell (84%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (85%nat, 0%nat)) (ESub (ECell (85%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (86%nat, 0%nat)) (ESub (ECell (86%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (87%nat, 0%nat)) (ESub (ECell (87%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (88%nat, 0%nat)) (ESub (ECell (88%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (89%nat, 0%nat)) (ESub (ECell (89%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (90%nat, 0%nat)) (ESub (ECell (90%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (91%nat, 0%nat)) (ESub (ECell (91%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (92%nat, 0%nat)) (ESub (ECell (92%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (93%nat, 0%nat)) (ESub (ECell (93%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (94%nat, 0%nat)) (ESub (ECell (94%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (95%nat, 0%nat)) (ESub (ECell (95%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (96%nat, 0%nat)) (ESub (ECell (96%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (97%nat, 0%nat)) (ESub (ECell (97%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (98%nat, 0%nat)) (ESub (ECell (98%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (99%nat, 0%nat)) (ESub (ECell (99%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (100%nat, 0%nat)) (ESub (ECell (100%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (101%nat, 0%nat)) (ESub (ECell (101%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (102%nat, 0%nat)) (ESub (ECell (102%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (103%nat, 0%nat)) (ESub (ECell (103%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (104%nat, 0%nat)) (ESub (ECell (104%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (105%nat, 0%nat)) (ESub (ECell (105%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (106%nat, 0%nat)) (ESub (ECell (106%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (107%nat, 0%nat)) (ESub (ECell (107%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (108%nat, 0%nat)) (ESub (ECell (108%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (109%nat, 0%nat)) (ESub (ECell (109%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (110%nat, 0%nat)) (ESub (ECell (110%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (111%nat, 0%nat)) (ESub (ECell (111%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (112%nat, 0%nat)) (ESub (ECell (112%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (113%nat, 0%nat)) (ESub (ECell (113%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (114%nat, 0%nat)) (ESub (ECell (114%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (115%nat, 0%nat)) (ESub (ECell (115%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (116%nat, 0%nat)) (ESub (ECell (116%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (117%nat, 0%nat)) (ESub (ECell (117%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (118%nat, 0%nat)) (ESub (ECell (118%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (119%nat, 0%nat)) (ESub (ECell (119%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (120%nat, 0%nat)) (ESub (ECell (120%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (121%nat, 0%nat)) (ESub (ECell (121%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (122%nat, 0%nat)) (ESub (ECell (122%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (123%nat, 0%nat)) (ESub (ECell (123%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (124%nat, 0%nat)) (ESub (ECell (124%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (125%nat, 0%nat)) (ESub (ECell (125%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (126%nat, 0%nat)) (ESub (ECell (126%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (127%nat, 0%nat)) (ESub (ECell (127%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (128%nat, 0%nat)) (ESub (ECell (128%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (129%nat, 0%nat)) (ESub (ECell (129%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (130%nat, 0%nat)) (ESub (ECell (130%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (131%nat, 0%nat)) (ESub (ECell (131%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (132%nat, 0%nat)) (ESub (ECell (132%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (133%nat, 0%nat)) (ESub (ECell (133%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (134%nat, 0%nat)) (ESub (ECell (134%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (135%nat, 0%nat)) (ESub (ECell (135%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (136%nat, 0%nat)) (ESub (ECell (136%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (137%nat, 0%nat)) (ESub (ECell (137%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (138%nat, 0%nat)) (ESub (ECell (138%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (139%nat, 0%nat)) (ESub (ECell (139%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (140%nat, 0%nat)) (ESub (ECell (140%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (141%nat, 0%nat)) (ESub (ECell (141%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (142%nat, 0%nat)) (ESub (ECell (142%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (143%nat, 0%nat)) (ESub (ECell (143%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (144%nat, 0%nat)) (ESub (ECell (144%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (145%nat, 0%nat)) (ESub (ECell (145%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (146%nat, 0%nat)) (ESub (ECell (146%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (147%nat, 0%nat)) (ESub (ECell (147%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (148%nat, 0%nat)) (ESub (ECell (148%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (149%nat, 0%nat)) (ESub (ECell (149%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (150%nat, 0%nat)) (ESub (ECell (150%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (151%nat, 0%nat)) (ESub (ECell (151%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (152%nat, 0%nat)) (ESub (ECell (152%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (153%nat, 0%nat)) (ESub (ECell (153%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (154%nat, 0%nat)) (ESub (ECell (154%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (155%nat, 0%nat)) (ESub (ECell (155%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (156%nat, 0%nat)) (ESub (ECell (156%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (157%nat, 0%nat)) (ESub (ECell (157%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (158%nat, 0%nat)) (ESub (ECell (158%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (159%nat, 0%nat)) (ESub (ECell (159%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (160%nat, 0%nat)) (ESub (ECell (160%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (161%nat, 0%nat)) (ESub (ECell (161%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (162%nat, 0%nat)) (ESub (ECell (162%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (163%nat, 0%nat)) (ESub (ECell (163%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (164%nat, 0%nat)) (ESub (ECell (164%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (165%nat, 0%nat)) (ESub (ECell (165%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (166%nat, 0%nat)) (ESub (ECell (166%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (167%nat, 0%nat)) (ESub (ECell (167%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (168%nat, 0%nat)) (ESub (ECell (168%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (169%nat, 0%nat)) (ESub (ECell (169%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (170%nat, 0%nat)) (ESub (ECell (170%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (171%nat, 0%nat)) (ESub (ECell (171%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (172%nat, 0%nat)) (ESub (ECell (172%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (173%nat, 0%nat)) (ESub (ECell (173%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (174%nat, 0%nat)) (ESub (ECell (174%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (175%nat, 0%nat)) (ESub (ECell (175%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (176%nat, 0%nat)) (ESub (ECell (176%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (177%nat, 0%nat)) (ESub (ECell (177%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (178%nat, 0%nat)) (ESub (ECell (178%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (179%nat, 0%nat)) (ESub (ECell (179%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (180%nat, 0%nat)) (ESub (ECell (180%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (181%nat, 0%nat)) (ESub (ECell (181%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (182%nat, 0%nat)) (ESub (ECell (182%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (183%nat, 0%nat)) (ESub (ECell (183%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (184%nat, 0%nat)) (ESub (ECell (184%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (185%nat, 0%nat)) (ESub (ECell (185%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (186%nat, 0%nat)) (ESub (ECell (186%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (187%nat, 0%nat)) (ESub (ECell (187%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (188%nat, 0%nat)) (ESub (ECell (188%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (189%nat, 0%nat)) (ESub (ECell (189%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (190%nat, 0%nat)) (ESub (ECell (190%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (191%nat, 0%nat)) (ESub (ECell (191%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (192%nat, 0%nat)) (ESub (ECell (192%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (193%nat, 0%nat)) (ESub (ECell (193%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (194%nat, 0%nat)) (ESub (ECell (194%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (195%nat, 0%nat)) (ESub (ECell (195%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (196%nat, 0%nat)) (ESub (ECell (196%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (197%nat, 0%nat)) (ESub (ECell (197%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (198%nat, 0%nat)) (ESub (ECell (198%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (199%nat, 0%nat)) (ESub (ECell (199%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (200%nat, 0%nat)) (ESub (ECell (200%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (201%nat, 0%nat)) (ESub (ECell (201%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (202%nat, 0%nat)) (ESub (ECell (202%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (203%nat, 0%nat)) (ESub (ECell (203%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (204%nat, 0%nat)) (ESub (ECell (204%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (205%nat, 0%nat)) (ESub (ECell (205%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (206%nat, 0%nat)) (ESub (ECell (206%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (207%nat, 0%nat)) (ESub (ECell (207%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (208%nat, 0%nat)) (ESub (ECell (208%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (209%nat, 0%nat)) (ESub (ECell (209%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (210%nat, 0%nat)) (ESub (ECell (210%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (211%nat, 0%nat)) (ESub (ECell (211%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (212%nat, 0%nat)) (ESub (ECell (212%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (213%nat, 0%nat)) (ESub (ECell (213%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (214%nat, 0%nat)) (ESub (ECell (214%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (215%nat, 0%nat)) (ESub (ECell (215%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (216%nat, 0%nat)) (ESub (ECell (216%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (217%nat, 0%nat)) (ESub (ECell (217%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (218%nat, 0%nat)) (ESub (ECell (218%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (219%nat, 0%nat)) (ESub (ECell (219%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (220%nat, 0%nat)) (ESub (ECell (220%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (221%nat, 0%nat)) (ESub (ECell (221%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (222%nat, 0%nat)) (ESub (ECell (222%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (223%nat, 0%nat)) (ESub (ECell (223%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (224%nat, 0%nat)) (ESub (ECell (224%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (225%nat, 0%nat)) (ESub (ECell (225%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (226%nat, 0%nat)) (ESub (ECell (226%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (227%nat, 0%nat)) (ESub (ECell (227%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (228%nat, 0%nat)) (ESub (ECell (228%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (229%nat, 0%nat)) (ESub (ECell (229%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (230%nat, 0%nat)) (ESub (ECell (230%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (231%nat, 0%nat)) (ESub (ECell (231%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (232%nat, 0%nat)) (ESub (ECell (232%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (233%nat, 0%nat)) (ESub (ECell (233%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (234%nat, 0%nat)) (ESub (ECell (234%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (235%nat, 0%nat)) (ESub (ECell (235%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (236%nat, 0%nat)) (ESub (ECell (236%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (237%nat, 0%nat)) (ESub (ECell (237%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (238%nat, 0%nat)) (ESub (ECell (238%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (239%nat, 0%nat)) (ESub (ECell (239%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (240%nat, 0%nat)) (ESub (ECell (240%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (241%nat, 0%nat)) (ESub (ECell (241%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (242%nat, 0%nat)) (ESub (ECell (242%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (243%nat, 0%nat)) (ESub (ECell (243%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (244%nat, 0%nat)) (ESub (ECell (244%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (245%nat, 0%nat)) (ESub (ECell (245%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (246%nat, 0%nat)) (ESub (ECell (246%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (247%nat, 0%nat)) (ESub (ECell (247%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (248%nat, 0%nat)) (ESub (ECell (248%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (249%nat, 0%nat)) (ESub (ECell (249%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (250%nat, 0%nat)) (ESub (ECell (250%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (251%nat, 0%nat)) (ESub (ECell (251%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (252%nat, 0%nat)) (ESub (ECell (252%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (253%nat, 0%nat)) (ESub (ECell (253%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (254%nat, 0%nat)) (ESub (ECell (254%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (255%nat, 0%nat)) (ESub (ECell (255%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (256%nat, 0%nat)) (ESub (ECell (256%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (257%nat, 0%nat)) (ESub (ECell (257%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (258%nat, 0%nat)) (ESub (ECell (258%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (259%nat, 0%nat)) (ESub (ECell (259%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (260%nat, 0%nat)) (ESub (ECell (260%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (261%nat, 0%nat)) (ESub (ECell (261%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (262%nat, 0%nat)) (ESub (ECell (262%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (263%nat, 0%nat)) (ESub (ECell (263%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (264%nat, 0%nat)) (ESub (ECell (264%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (265%nat, 0%nat)) (ESub (ECell (265%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (266%nat, 0%nat)) (ESub (ECell (266%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (267%nat, 0%nat)) (ESub (ECell (267%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (268%nat, 0%nat)) (ESub (ECell (268%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (269%nat, 0%nat)) (ESub (ECell (269%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (270%nat, 0%nat)) (ESub (ECell (270%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (271%nat, 0%nat)) (ESub (ECell (271%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (272%nat, 0%nat)) (ESub (ECell (272%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (273%nat, 0%nat)) (ESub (ECell (273%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (274%nat, 0%nat)) (ESub (ECell (274%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (275%nat, 0%nat)) (ESub (ECell (275%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (276%nat, 0%nat)) (ESub (ECell (276%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (277%nat, 0%nat)) (ESub (ECell (277%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (278%nat, 0%nat)) (ESub (ECell (278%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (279%nat, 0%nat)) (ESub (ECell (279%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (280%nat, 0%nat)) (ESub (ECell (280%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (281%nat, 0%nat)) (ESub (ECell (281%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (282%nat, 0%nat)) (ESub (ECell (282%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (283%nat, 0%nat)) (ESub (ECell (283%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (284%nat, 0%nat)) (ESub (ECell (284%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (285%nat, 0%nat)) (ESub (ECell (285%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (286%nat, 0%nat)) (ESub (ECell (286%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (287%nat, 0%nat)) (ESub (ECell (287%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (288%nat, 0%nat)) (ESub (ECell (288%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (289%nat, 0%nat)) (ESub (ECell (289%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (290%nat, 0%nat)) (ESub (ECell (290%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (291%nat, 0%nat)) (ESub (ECell (291%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (292%nat, 0%nat)) (ESub (ECell (292%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (293%nat, 0%nat)) (ESub (ECell (293%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (294%nat, 0%nat)) (ESub (ECell (294%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (295%nat, 0%nat)) (ESub (ECell (295%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (296%nat, 0%nat)) (ESub (ECell (296%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (297%nat, 0%nat)) (ESub (ECell (297%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (298%nat, 0%nat)) (ESub (ECell (298%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (299%nat, 0%nat)) (ESub (ECell (299%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (300%nat, 0%nat)) (ESub (ECell (300%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (301%nat, 0%nat)) (ESub (ECell (301%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (302%nat, 0%nat)) (ESub (ECell (302%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (303%nat, 0%nat)) (ESub (ECell (303%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (304%nat, 0%nat)) (ESub (ECell (304%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (305%nat, 0%nat)) (ESub (ECell (305%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (306%nat, 0%nat)) (ESub (ECell (306%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (307%nat, 0%nat)) (ESub (ECell (307%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (308%nat, 0%nat)) (ESub (ECell (308%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (309%nat, 0%nat)) (ESub (ECell (309%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (310%nat, 0%nat)) (ESub (ECell (310%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (311%nat, 0%nat)) (ESub (ECell (311%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (312%nat, 0%nat)) (ESub (ECell (312%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (313%nat, 0%nat)) (ESub (ECell (313%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (314%nat, 0%nat)) (ESub (ECell (314%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (315%nat, 0%nat)) (ESub (ECell (315%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (316%nat, 0%nat)) (ESub (ECell (316%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (317%nat, 0%nat)) (ESub (ECell (317%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (318%nat, 0%nat)) (ESub (ECell (318%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (319%nat, 0%nat)) (ESub (ECell (319%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (320%nat, 0%nat)) (ESub (ECell (320%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (321%nat, 0%nat)) (ESub (ECell (321%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (322%nat, 0%nat)) (ESub (ECell (322%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (323%nat, 0%nat)) (ESub (ECell (323%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (324%nat, 0%nat)) (ESub (ECell (324%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (325%nat, 0%nat)) (ESub (ECell (325%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (326%nat, 0%nat)) (ESub (ECell (326%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (327%nat, 0%nat)) (ESub (ECell (327%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (328%nat, 0%nat)) (ESub (ECell (328%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (329%nat, 0%nat)) (ESub (ECell (329%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (330%nat, 0%nat)) (ESub (ECell (330%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (331%nat, 0%nat)) (ESub (ECell (331%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (332%nat, 0%nat)) (ESub (ECell (332%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (333%nat, 0%nat)) (ESub (ECell (333%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (334%nat, 0%nat)) (ESub (ECell (334%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (335%nat, 0%nat)) (ESub (ECell (335%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (336%nat, 0%nat)) (ESub (ECell (336%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (337%nat, 0%nat)) (ESub (ECell (337%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (338%nat, 0%nat)) (ESub (ECell (338%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (339%nat, 0%nat)) (ESub (ECell (339%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (340%nat, 0%nat)) (ESub (ECell (340%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (341%nat, 0%nat)) (ESub (ECell (341%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (342%nat, 0%nat)) (ESub (ECell (342%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (343%nat, 0%nat)) (ESub (ECell (343%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (344%nat, 0%nat)) (ESub (ECell (344%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (345%nat, 0%nat)) (ESub (ECell (345%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (346%nat, 0%nat)) (ESub (ECell (346%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (347%nat, 0%nat)) (ESub (ECell (347%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (348%nat, 0%nat)) (ESub (ECell (348%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (349%nat, 0%nat)) (ESub (ECell (349%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (350%nat, 0%nat)) (ESub (ECell (350%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (351%nat, 0%nat)) (ESub (ECell (351%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (352%nat, 0%nat)) (ESub (ECell (352%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (353%nat, 0%nat)) (ESub (ECell (353%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (354%nat, 0%nat)) (ESub (ECell (354%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (355%nat, 0%nat)) (ESub (ECell (355%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (356%nat, 0%nat)) (ESub (ECell (356%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (357%nat, 0%nat)) (ESub (ECell (357%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (358%nat, 0%nat)) (ESub (ECell (358%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (359%nat, 0%nat)) (ESub (ECell (359%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (360%nat, 0%nat)) (ESub (ECell (360%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (361%nat, 0%nat)) (ESub (ECell (361%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (362%nat, 0%nat)) (ESub (ECell (362%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (363%nat, 0%nat)) (ESub (ECell (363%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (364%nat, 0%nat)) (ESub (ECell (364%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (365%nat, 0%nat)) (ESub (ECell (365%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (366%nat, 0%nat)) (ESub (ECell (366%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (367%nat, 0%nat)) (ESub (ECell (367%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (368%nat, 0%nat)) (ESub (ECell (368%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (369%nat, 0%nat)) (ESub (ECell (369%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (370%nat, 0%nat)) (ESub (ECell (370%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (371%nat, 0%nat)) (ESub (ECell (371%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (372%nat, 0%nat)) (ESub (ECell (372%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (373%nat, 0%nat)) (ESub (ECell (373%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (374%nat, 0%nat)) (ESub (ECell (374%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (375%nat, 0%nat)) (ESub (ECell (375%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (376%nat, 0%nat)) (ESub (ECell (376%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (377%nat, 0%nat)) (ESub (ECell (377%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (378%nat, 0%nat)) (ESub (ECell (378%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (379%nat, 0%nat)) (ESub (ECell (379%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (380%nat, 0%nat)) (ESub (ECell (380%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (381%nat, 0%nat)) (ESub (ECell (381%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (382%nat, 0%nat)) (ESub (ECell (382%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (383%nat, 0%nat)) (ESub (ECell (383%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (384%nat, 0%nat)) (ESub (ECell (384%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (385%nat, 0%nat)) (ESub (ECell (385%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (386%nat, 0%nat)) (ESub (ECell (386%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (387%nat, 0%nat)) (ESub (ECell (387%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (388%nat, 0%nat)) (ESub (ECell (388%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (389%nat, 0%nat)) (ESub (ECell (389%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (390%nat, 0%nat)) (ESub (ECell (390%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (391%nat, 0%nat)) (ESub (ECell (391%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (392%nat, 0%nat)) (ESub (ECell (392%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (393%nat, 0%nat)) (ESub (ECell (393%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (394%nat, 0%nat)) (ESub (ECell (394%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (395%nat, 0%nat)) (ESub (ECell (395%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (396%nat, 0%nat)) (ESub (ECell (396%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (397%nat, 0%nat)) (ESub (ECell (397%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (398%nat, 0%nat)) (ESub (ECell (398%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (399%nat, 0%nat)) (ESub (ECell (399%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (400%nat, 0%nat)) (ESub (ECell (400%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (401%nat, 0%nat)) (ESub (ECell (401%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (402%nat, 0%nat)) (ESub (ECell (402%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (403%nat, 0%nat)) (ESub (ECell (403%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (404%nat, 0%nat)) (ESub (ECell (404%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (405%nat, 0%nat)) (ESub (ECell (405%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (406%nat, 0%nat)) (ESub (ECell (406%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (407%nat, 0%nat)) (ESub (ECell (407%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (408%nat, 0%nat)) (ESub (ECell (408%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (409%nat, 0%nat)) (ESub (ECell (409%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (410%nat, 0%nat)) (ESub (ECell (410%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (411%nat, 0%nat)) (ESub (ECell (411%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (412%nat, 0%nat)) (ESub (ECell (412%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (413%nat, 0%nat)) (ESub (ECell (413%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (414%nat, 0%nat)) (ESub (ECell (414%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (415%nat, 0%nat)) (ESub (ECell (415%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (416%nat, 0%nat)) (ESub (ECell (416%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (417%nat, 0%nat)) (ESub (ECell (417%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (418%nat, 0%nat)) (ESub (ECell (418%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (419%nat, 0%nat)) (ESub (ECell (419%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (420%nat, 0%nat)) (ESub (ECell (420%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (421%nat, 0%nat)) (ESub (ECell (421%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (422%nat, 0%nat)) (ESub (ECell (422%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (423%nat, 0%nat)) (ESub (ECell (423%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (424%nat, 0%nat)) (ESub (ECell (424%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (425%nat, 0%nat)) (ESub (ECell (425%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (426%nat, 0%nat)) (ESub (ECell (426%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (427%nat, 0%nat)) (ESub (ECell (427%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (428%nat, 0%nat)) (ESub (ECell (428%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (429%nat, 0%nat)) (ESub (ECell (429%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (430%nat, 0%nat)) (ESub (ECell (430%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (431%nat, 0%nat)) (ESub (ECell (431%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (432%nat, 0%nat)) (ESub (ECell (432%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (433%nat, 0%nat)) (ESub (ECell (433%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (434%nat, 0%nat)) (ESub (ECell (434%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (435%nat, 0%nat)) (ESub (ECell (435%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (436%nat, 0%nat)) (ESub (ECell (436%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (437%nat, 0%nat)) (ESub (ECell (437%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (438%nat, 0%nat)) (ESub (ECell (438%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (439%nat, 0%nat)) (ESub (ECell (439%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (440%nat, 0%nat)) (ESub (ECell (440%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (441%nat, 0%nat)) (ESub (ECell (441%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (442%nat, 0%nat)) (ESub (ECell (442%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (443%nat, 0%nat)) (ESub (ECell (443%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (444%nat, 0%nat)) (ESub (ECell (444%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (445%nat, 0%nat)) (ESub (ECell (445%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (446%nat, 0%nat)) (ESub (ECell (446%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (447%nat, 0%nat)) (ESub (ECell (447%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (448%nat, 0%nat)) (ESub (ECell (448%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (449%nat, 0%nat)) (ESub (ECell (449%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (450%nat, 0%nat)) (ESub (ECell (450%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (451%nat, 0%nat)) (ESub (ECell (451%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (452%nat, 0%nat)) (ESub (ECell (452%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (453%nat, 0%nat)) (ESub (ECell (453%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (454%nat, 0%nat)) (ESub (ECell (454%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (455%nat, 0%nat)) (ESub (ECell (455%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (456%nat, 0%nat)) (ESub (ECell (456%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (457%nat, 0%nat)) (ESub (ECell (457%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (458%nat, 0%nat)) (ESub (ECell (458%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (459%nat, 0%nat)) (ESub (ECell (459%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (460%nat, 0%nat)) (ESub (ECell (460%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (461%nat, 0%nat)) (ESub (ECell (461%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (462%nat, 0%nat)) (ESub (ECell (462%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (463%nat, 0%nat)) (ESub (ECell (463%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (464%nat, 0%nat)) (ESub (ECell (464%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (465%nat, 0%nat)) (ESub (ECell (465%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (466%nat, 0%nat)) (ESub (ECell (466%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (467%nat, 0%nat)) (ESub (ECell (467%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (468%nat, 0%nat)) (ESub (ECell (468%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (469%nat, 0%nat)) (ESub (ECell (469%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (470%nat, 0%nat)) (ESub (ECell (470%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (471%nat, 0%nat)) (ESub (ECell (471%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (472%nat, 0%nat)) (ESub (ECell (472%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (473%nat, 0%nat)) (ESub (ECell (473%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (474%nat, 0%nat)) (ESub (ECell (474%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (475%nat, 0%nat)) (ESub (ECell (475%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (476%nat, 0%nat)) (ESub (ECell (476%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (477%nat, 0%nat)) (ESub (ECell (477%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (478%nat, 0%nat)) (ESub (ECell (478%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (479%nat, 0%nat)) (ESub (ECell (479%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (480%nat, 0%nat)) (ESub (ECell (480%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (481%nat, 0%nat)) (ESub (ECell (481%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (482%nat, 0%nat)) (ESub (ECell (482%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (483%nat, 0%nat)) (ESub (ECell (483%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (484%nat, 0%nat)) (ESub (ECell (484%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (485%nat, 0%nat)) (ESub (ECell (485%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (486%nat, 0%nat)) (ESub (ECell (486%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (487%nat, 0%nat)) (ESub (ECell (487%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (488%nat, 0%nat)) (ESub (ECell (488%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (489%nat, 0%nat)) (ESub (ECell (489%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (490%nat, 0%nat)) (ESub (ECell (490%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (491%nat, 0%nat)) (ESub (ECell (491%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (492%nat, 0%nat)) (ESub (ECell (492%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (493%nat, 0%nat)) (ESub (ECell (493%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (494%nat, 0%nat)) (ESub (ECell (494%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (495%nat, 0%nat)) (ESub (ECell (495%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (496%nat, 0%nat)) (ESub (ECell (496%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (497%nat, 0%nat)) (ESub (ECell (497%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (498%nat, 0%nat)) (ESub (ECell (498%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (499%nat, 0%nat)) (ESub (ECell (499%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (500%nat, 0%nat)) (ESub (ECell (500%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (501%nat, 0%nat)) (ESub (ECell (501%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (502%nat, 0%nat)) (ESub (ECell (502%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (503%nat, 0%nat)) (ESub (ECell (503%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (504%nat, 0%nat)) (ESub (ECell (504%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (505%nat, 0%nat)) (ESub (ECell (505%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (506%nat, 0%nat)) (ESub (ECell (506%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (507%nat, 0%nat)) (ESub (ECell (507%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (508%nat, 0%nat)) (ESub (ECell (508%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (509%nat, 0%nat)) (ESub (ECell (509%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (510%nat, 0%nat)) (ESub (ECell (510%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (511%nat, 0%nat)) (ESub (ECell (511%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (512%nat, 0%nat)) (ESub (ECell (512%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (513%nat, 0%nat)) (ESub (ECell (513%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (514%nat, 0%nat)) (ESub (ECell (514%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (515%nat, 0%nat)) (ESub (ECell (515%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (516%nat, 0%nat)) (ESub (ECell (516%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (517%nat, 0%nat)) (ESub (ECell (517%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (518%nat, 0%nat)) (ESub (ECell (518%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (519%nat, 0%nat)) (ESub (ECell (519%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (520%nat, 0%nat)) (ESub (ECell (520%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (521%nat, 0%nat)) (ESub (ECell (521%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (522%nat, 0%nat)) (ESub (ECell (522%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (523%nat, 0%nat)) (ESub (ECell (523%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (524%nat, 0%nat)) (ESub (ECell (524%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (525%nat, 0%nat)) (ESub (ECell (525%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (526%nat, 0%nat)) (ESub (ECell (526%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (527%nat, 0%nat)) (ESub (ECell (527%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (528%nat, 0%nat)) (ESub (ECell (528%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (529%nat, 0%nat)) (ESub (ECell (529%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (530%nat, 0%nat)) (ESub (ECell (530%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (531%nat, 0%nat)) (ESub (ECell (531%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (532%nat, 0%nat)) (ESub (ECell (532%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (533%nat, 0%nat)) (ESub (ECell (533%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (534%nat, 0%nat)) (ESub (ECell (534%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (535%nat, 0%nat)) (ESub (ECell (535%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (536%nat, 0%nat)) (ESub (ECell (536%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (537%nat, 0%nat)) (ESub (ECell (537%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (538%nat, 0%nat)) (ESub (ECell (538%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (539%nat, 0%nat)) (ESub (ECell (539%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (540%nat, 0%nat)) (ESub (ECell (540%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (541%nat, 0%nat)) (ESub (ECell (541%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (542%nat, 0%nat)) (ESub (ECell (542%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (543%nat, 0%nat)) (ESub (ECell (543%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (544%nat, 0%nat)) (ESub (ECell (544%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (545%nat, 0%nat)) (ESub (ECell (545%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (546%nat, 0%nat)) (ESub (ECell (546%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (547%nat, 0%nat)) (ESub (ECell (547%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (548%nat, 0%nat)) (ESub (ECell (548%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (549%nat, 0%nat)) (ESub (ECell (549%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (550%nat, 0%nat)) (ESub (ECell (550%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (551%nat, 0%nat)) (ESub (ECell (551%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (552%nat, 0%nat)) (ESub (ECell (552%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (553%nat, 0%nat)) (ESub (ECell (553%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (554%nat, 0%nat)) (ESub (ECell (554%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (555%nat, 0%nat)) (ESub (ECell (555%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (556%nat, 0%nat)) (ESub (ECell (556%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (557%nat, 0%nat)) (ESub (ECell (557%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (558%nat, 0%nat)) (ESub (ECell (558%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (559%nat, 0%nat)) (ESub (ECell (559%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (560%nat, 0%nat)) (ESub (ECell (560%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (561%nat, 0%nat)) (ESub (ECell (561%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (562%nat, 0%nat)) (ESub (ECell (562%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (563%nat, 0%nat)) (ESub (ECell (563%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (564%nat, 0%nat)) (ESub (ECell (564%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (565%nat, 0%nat)) (ESub (ECell (565%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (566%nat, 0%nat)) (ESub (ECell (566%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (567%nat, 0%nat)) (ESub (ECell (567%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (568%nat, 0%nat)) (ESub (ECell (568%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (569%nat, 0%nat)) (ESub (ECell (569%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (570%nat, 0%nat)) (ESub (ECell (570%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (571%nat, 0%nat)) (ESub (ECell (571%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (572%nat, 0%nat)) (ESub (ECell (572%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (573%nat, 0%nat)) (ESub (ECell (573%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (574%nat, 0%nat)) (ESub (ECell (574%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (575%nat, 0%nat)) (ESub (ECell (575%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (576%nat, 0%nat)) (ESub (ECell (576%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (577%nat, 0%nat)) (ESub (ECell (577%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (578%nat, 0%nat)) (ESub (ECell (578%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (579%nat, 0%nat)) (ESub (ECell (579%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (580%nat, 0%nat)) (ESub (ECell (580%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (581%nat, 0%nat)) (ESub (ECell (581%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (582%nat, 0%nat)) (ESub (ECell (582%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (583%nat, 0%nat)) (ESub (ECell (583%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (584%nat, 0%nat)) (ESub (ECell (584%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (585%nat, 0%nat)) (ESub (ECell (585%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (586%nat, 0%nat)) (ESub (ECell (586%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (587%nat, 0%nat)) (ESub (ECell (587%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (588%nat, 0%nat)) (ESub (ECell (588%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (589%nat, 0%nat)) (ESub (ECell (589%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (590%nat, 0%nat)) (ESub (ECell (590%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (591%nat, 0%nat)) (ESub (ECell (591%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (592%nat, 0%nat)) (ESub (ECell (592%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (593%nat, 0%nat)) (ESub (ECell (593%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (594%nat, 0%nat)) (ESub (ECell (594%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (595%nat, 0%nat)) (ESub (ECell (595%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (596%nat, 0%nat)) (ESub (ECell (596%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (597%nat, 0%nat)) (ESub (ECell (597%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (598%nat, 0%nat)) (ESub (ECell (598%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (599%nat, 0%nat)) (ESub (ECell (599%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (600%nat, 0%nat)) (ESub (ECell (600%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (601%nat, 0%nat)) (ESub (ECell (601%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (602%nat, 0%nat)) (ESub (ECell (602%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (603%nat, 0%nat)) (ESub (ECell (603%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (604%nat, 0%nat)) (ESub (ECell (604%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (605%nat, 0%nat)) (ESub (ECell (605%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (606%nat, 0%nat)) (ESub (ECell (606%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (607%nat, 0%nat)) (ESub (ECell (607%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (608%nat, 0%nat)) (ESub (ECell (608%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (609%nat, 0%nat)) (ESub (ECell (609%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (610%nat, 0%nat)) (ESub (ECell (610%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (611%nat, 0%nat)) (ESub (ECell (611%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (612%nat, 0%nat)) (ESub (ECell (612%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (613%nat, 0%nat)) (ESub (ECell (613%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (614%nat, 0%nat)) (ESub (ECell (614%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (615%nat, 0%nat)) (ESub (ECell (615%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (616%nat, 0%nat)) (ESub (ECell (616%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (617%nat, 0%nat)) (ESub (ECell (617%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (618%nat, 0%nat)) (ESub (ECell (618%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (619%nat, 0%nat)) (ESub (ECell (619%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (620%nat, 0%nat)) (ESub (ECell (620%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (621%nat, 0%nat)) (ESub (ECell (621%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (622%nat, 0%nat)) (ESub (ECell (622%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (623%nat, 0%nat)) (ESub (ECell (623%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (624%nat, 0%nat)) (ESub (ECell (624%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (625%nat, 0%nat)) (ESub (ECell (625%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (626%nat, 0%nat)) (ESub (ECell (626%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (627%nat, 0%nat)) (ESub (ECell (627%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (628%nat, 0%nat)) (ESub (ECell (628%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (629%nat, 0%nat)) (ESub (ECell (629%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (630%nat, 0%nat)) (ESub (ECell (630%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (631%nat, 0%nat)) (ESub (ECell (631%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (632%nat, 0%nat)) (ESub (ECell (632%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (633%nat, 0%nat)) (ESub (ECell (633%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (634%nat, 0%nat)) (ESub (ECell (634%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (635%nat, 0%nat)) (ESub (ECell (635%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (636%nat, 0%nat)) (ESub (ECell (636%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (637%nat, 0%nat)) (ESub (ECell (637%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (638%nat, 0%nat)) (ESub (ECell (638%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (639%nat, 0%nat)) (ESub (ECell (639%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (640%nat, 0%nat)) (ESub (ECell (640%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (641%nat, 0%nat)) (ESub (ECell (641%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (642%nat, 0%nat)) (ESub (ECell (642%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (643%nat, 0%nat)) (ESub (ECell (643%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (644%nat, 0%nat)) (ESub (ECell (644%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (645%nat, 0%nat)) (ESub (ECell (645%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (646%nat, 0%nat)) (ESub (ECell (646%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (647%nat, 0%nat)) (ESub (ECell (647%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (648%nat, 0%nat)) (ESub (ECell (648%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (649%nat, 0%nat)) (ESub (ECell (649%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (650%nat, 0%nat)) (ESub (ECell (650%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (651%nat, 0%nat)) (ESub (ECell (651%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (652%nat, 0%nat)) (ESub (ECell (652%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (653%nat, 0%nat)) (ESub (ECell (653%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (654%nat, 0%nat)) (ESub (ECell (654%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (655%nat, 0%nat)) (ESub (ECell (655%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (656%nat, 0%nat)) (ESub (ECell (656%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (657%nat, 0%nat)) (ESub (ECell (657%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (658%nat, 0%nat)) (ESub (ECell (658%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (659%nat, 0%nat)) (ESub (ECell (659%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (660%nat, 0%nat)) (ESub (ECell (660%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (661%nat, 0%nat)) (ESub (ECell (661%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (662%nat, 0%nat)) (ESub (ECell (662%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (663%nat, 0%nat)) (ESub (ECell (663%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (664%nat, 0%nat)) (ESub (ECell (664%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (665%nat, 0%nat)) (ESub (ECell (665%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (666%nat, 0%nat)) (ESub (ECell (666%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (667%nat, 0%nat)) (ESub (ECell (667%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (668%nat, 0%nat)) (ESub (ECell (668%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (669%nat, 0%nat)) (ESub (ECell (669%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (670%nat, 0%nat)) (ESub (ECell (670%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (671%nat, 0%nat)) (ESub (ECell (671%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (672%nat, 0%nat)) (ESub (ECell (672%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (673%nat, 0%nat)) (ESub (ECell (673%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (674%nat, 0%nat)) (ESub (ECell (674%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (675%nat, 0%nat)) (ESub (ECell (675%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (676%nat, 0%nat)) (ESub (ECell (676%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (677%nat, 0%nat)) (ESub (ECell (677%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (678%nat, 0%nat)) (ESub (ECell (678%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (679%nat, 0%nat)) (ESub (ECell (679%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (680%nat, 0%nat)) (ESub (ECell (680%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (681%nat, 0%nat)) (ESub (ECell (681%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (682%nat, 0%nat)) (ESub (ECell (682%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (683%nat, 0%nat)) (ESub (ECell (683%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (684%nat, 0%nat)) (ESub (ECell (684%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (685%nat, 0%nat)) (ESub (ECell (685%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (686%nat, 0%nat)) (ESub (ECell (686%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (687%nat, 0%nat)) (ESub (ECell (687%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (688%nat, 0%nat)) (ESub (ECell (688%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (689%nat, 0%nat)) (ESub (ECell (689%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (690%nat, 0%nat)) (ESub (ECell (690%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (691%nat, 0%nat)) (ESub (ECell (691%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (692%nat, 0%nat)) (ESub (ECell (692%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (693%nat, 0%nat)) (ESub (ECell (693%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (694%nat, 0%nat)) (ESub (ECell (694%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (695%nat, 0%nat)) (ESub (ECell (695%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (696%nat, 0%nat)) (ESub (ECell (696%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (697%nat, 0%nat)) (ESub (ECell (697%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (698%nat, 0%nat)) (ESub (ECell (698%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (699%nat, 0%nat)) (ESub (ECell (699%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (700%nat, 0%nat)) (ESub (ECell (700%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (701%nat, 0%nat)) (ESub (ECell (701%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (702%nat, 0%nat)) (ESub (ECell (702%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (703%nat, 0%nat)) (ESub (ECell (703%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (704%nat, 0%nat)) (ESub (ECell (704%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (705%nat, 0%nat)) (ESub (ECell (705%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (706%nat, 0%nat)) (ESub (ECell (706%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (707%nat, 0%nat)) (ESub (ECell (707%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (708%nat, 0%nat)) (ESub (ECell (708%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (709%nat, 0%nat)) (ESub (ECell (709%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (710%nat, 0%nat)) (ESub (ECell (710%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (711%nat, 0%nat)) (ESub (ECell (711%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (712%nat, 0%nat)) (ESub (ECell (712%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (713%nat, 0%nat)) (ESub (ECell (713%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (714%nat, 0%nat)) (ESub (ECell (714%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (715%nat, 0%nat)) (ESub (ECell (715%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (716%nat, 0%nat)) (ESub (ECell (716%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (717%nat, 0%nat)) (ESub (ECell (717%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (718%nat, 0%nat)) (ESub (ECell (718%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (719%nat, 0%nat)) (ESub (ECell (719%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (720%nat, 0%nat)) (ESub (ECell (720%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (721%nat, 0%nat)) (ESub (ECell (721%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (722%nat, 0%nat)) (ESub (ECell (722%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (723%nat, 0%nat)) (ESub (ECell (723%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (724%nat, 0%nat)) (ESub (ECell (724%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (725%nat, 0%nat)) (ESub (ECell (725%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (726%nat, 0%nat)) (ESub (ECell (726%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (727%nat, 0%nat)) (ESub (ECell (727%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (728%nat, 0%nat)) (ESub (ECell (728%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (729%nat, 0%nat)) (ESub (ECell (729%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (730%nat, 0%nat)) (ESub (ECell (730%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (731%nat, 0%nat)) (ESub (ECell (731%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (732%nat, 0%nat)) (ESub (ECell (732%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (733%nat, 0%nat)) (ESub (ECell (733%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (734%nat, 0%nat)) (ESub (ECell (734%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (735%nat, 0%nat)) (ESub (ECell (735%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (736%nat, 0%nat)) (ESub (ECell (736%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (737%nat, 0%nat)) (ESub (ECell (737%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (738%nat, 0%nat)) (ESub (ECell (738%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (739%nat, 0%nat)) (ESub (ECell (739%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (740%nat, 0%nat)) (ESub (ECell (740%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (741%nat, 0%nat)) (ESub (ECell (741%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (742%nat, 0%nat)) (ESub (ECell (742%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (743%nat, 0%nat)) (ESub (ECell (743%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (744%nat, 0%nat)) (ESub (ECell (744%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (745%nat, 0%nat)) (ESub (ECell (745%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (746%nat, 0%nat)) (ESub (ECell (746%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (747%nat, 0%nat)) (ESub (ECell (747%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (748%nat, 0%nat)) (ESub (ECell (748%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (749%nat, 0%nat)) (ESub (ECell (749%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (750%nat, 0%nat)) (ESub (ECell (750%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (751%nat, 0%nat)) (ESub (ECell (751%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (752%nat, 0%nat)) (ESub (ECell (752%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (753%nat, 0%nat)) (ESub (ECell (753%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (754%nat, 0%nat)) (ESub (ECell (754%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (755%nat, 0%nat)) (ESub (ECell (755%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (756%nat, 0%nat)) (ESub (ECell (756%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (757%nat, 0%nat)) (ESub (ECell (757%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (758%nat, 0%nat)) (ESub (ECell (758%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (759%nat, 0%nat)) (ESub (ECell (759%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (760%nat, 0%nat)) (ESub (ECell (760%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (761%nat, 0%nat)) (ESub (ECell (761%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (762%nat, 0%nat)) (ESub (ECell (762%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (763%nat, 0%nat)) (ESub (ECell (763%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (764%nat, 0%nat)) (ESub (ECell (764%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (765%nat, 0%nat)) (ESub (ECell (765%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (766%nat, 0%nat)) (ESub (ECell (766%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (767%nat, 0%nat)) (ESub (ECell (767%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (768%nat, 0%nat)) (ESub (ECell (768%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (769%nat, 0%nat)) (ESub (ECell (769%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (770%nat, 0%nat)) (ESub (ECell (770%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (771%nat, 0%nat)) (ESub (ECell (771%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (772%nat, 0%nat)) (ESub (ECell (772%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (773%nat, 0%nat)) (ESub (ECell (773%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (774%nat, 0%nat)) (ESub (ECell (774%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (775%nat, 0%nat)) (ESub (ECell (775%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (776%nat, 0%nat)) (ESub (ECell (776%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (777%nat, 0%nat)) (ESub (ECell (777%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (778%nat, 0%nat)) (ESub (ECell (778%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (779%nat, 0%nat)) (ESub (ECell (779%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (780%nat, 0%nat)) (ESub (ECell (780%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (781%nat, 0%nat)) (ESub (ECell (781%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (782%nat, 0%nat)) (ESub (ECell (782%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (783%nat, 0%nat)) (ESub (ECell (783%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (784%nat, 0%nat)) (ESub (ECell (784%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (785%nat, 0%nat)) (ESub (ECell (785%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (786%nat, 0%nat)) (ESub (ECell (786%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (787%nat, 0%nat)) (ESub (ECell (787%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (788%nat, 0%nat)) (ESub (ECell (788%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (789%nat, 0%nat)) (ESub (ECell (789%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (790%nat, 0%nat)) (ESub (ECell (790%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (791%nat, 0%nat)) (ESub (ECell (791%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (792%nat, 0%nat)) (ESub (ECell (792%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (793%nat, 0%nat)) (ESub (ECell (793%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (794%nat, 0%nat)) (ESub (ECell (794%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (795%nat, 0%nat)) (ESub (ECell (795%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (796%nat, 0%nat)) (ESub (ECell (796%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (797%nat, 0%nat)) (ESub (ECell (797%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (798%nat, 0%nat)) (ESub (ECell (798%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (799%nat, 0%nat)) (ESub (ECell (799%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (800%nat, 0%nat)) (ESub (ECell (800%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (801%nat, 0%nat)) (ESub (ECell (801%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (802%nat, 0%nat)) (ESub (ECell (802%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (803%nat, 0%nat)) (ESub (ECell (803%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (804%nat, 0%nat)) (ESub (ECell (804%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (805%nat, 0%nat)) (ESub (ECell (805%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (806%nat, 0%nat)) (ESub (ECell (806%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (807%nat, 0%nat)) (ESub (ECell (807%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (808%nat, 0%nat)) (ESub (ECell (808%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (809%nat, 0%nat)) (ESub (ECell (809%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (810%nat, 0%nat)) (ESub (ECell (810%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (811%nat, 0%nat)) (ESub (ECell (811%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (812%nat, 0%nat)) (ESub (ECell (812%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (813%nat, 0%nat)) (ESub (ECell (813%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (814%nat, 0%nat)) (ESub (ECell (814%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (815%nat, 0%nat)) (ESub (ECell (815%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (816%nat, 0%nat)) (ESub (ECell (816%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (817%nat, 0%nat)) (ESub (ECell (817%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (818%nat, 0%nat)) (ESub (ECell (818%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (819%nat, 0%nat)) (ESub (ECell (819%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (820%nat, 0%nat)) (ESub (ECell (820%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (821%nat, 0%nat)) (ESub (ECell (821%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (822%nat, 0%nat)) (ESub (ECell (822%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (823%nat, 0%nat)) (ESub (ECell (823%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (824%nat, 0%nat)) (ESub (ECell (824%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (825%nat, 0%nat)) (ESub (ECell (825%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (826%nat, 0%nat)) (ESub (ECell (826%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (827%nat, 0%nat)) (ESub (ECell (827%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (828%nat, 0%nat)) (ESub (ECell (828%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (829%nat, 0%nat)) (ESub (ECell (829%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (830%nat, 0%nat)) (ESub (ECell (830%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (831%nat, 0%nat)) (ESub (ECell (831%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (832%nat, 0%nat)) (ESub (ECell (832%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (833%nat, 0%nat)) (ESub (ECell (833%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (834%nat, 0%nat)) (ESub (ECell (834%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (835%nat, 0%nat)) (ESub (ECell (835%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (836%nat, 0%nat)) (ESub (ECell (836%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (837%nat, 0%nat)) (ESub (ECell (837%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (838%nat, 0%nat)) (ESub (ECell (838%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (839%nat, 0%nat)) (ESub (ECell (839%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (840%nat, 0%nat)) (ESub (ECell (840%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (841%nat, 0%nat)) (ESub (ECell (841%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (842%nat, 0%nat)) (ESub (ECell (842%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (843%nat, 0%nat)) (ESub (ECell (843%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (844%nat, 0%nat)) (ESub (ECell (844%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (845%nat, 0%nat)) (ESub (ECell (845%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (846%nat, 0%nat)) (ESub (ECell (846%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (847%nat, 0%nat)) (ESub (ECell (847%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (848%nat, 0%nat)) (ESub (ECell (848%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (849%nat, 0%nat)) (ESub (ECell (849%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (850%nat, 0%nat)) (ESub (ECell (850%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (851%nat, 0%nat)) (ESub (ECell (851%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (852%nat, 0%nat)) (ESub (ECell (852%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (853%nat, 0%nat)) (ESub (ECell (853%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (854%nat, 0%nat)) (ESub (ECell (854%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (855%nat, 0%nat)) (ESub (ECell (855%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (856%nat, 0%nat)) (ESub (ECell (856%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (857%nat, 0%nat)) (ESub (ECell (857%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (858%nat, 0%nat)) (ESub (ECell (858%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (859%nat, 0%nat)) (ESub (ECell (859%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (860%nat, 0%nat)) (ESub (ECell (860%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (861%nat, 0%nat)) (ESub (ECell (861%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (862%nat, 0%nat)) (ESub (ECell (862%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (863%nat, 0%nat)) (ESub (ECell (863%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (864%nat, 0%nat)) (ESub (ECell (864%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (865%nat, 0%nat)) (ESub (ECell (865%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (866%nat, 0%nat)) (ESub (ECell (866%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (867%nat, 0%nat)) (ESub (ECell (867%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (868%nat, 0%nat)) (ESub (ECell (868%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (869%nat, 0%nat)) (ESub (ECell (869%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (870%nat, 0%nat)) (ESub (ECell (870%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (871%nat, 0%nat)) (ESub (ECell (871%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (872%nat, 0%nat)) (ESub (ECell (872%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (873%nat, 0%nat)) (ESub (ECell (873%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (874%nat, 0%nat)) (ESub (ECell (874%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (875%nat, 0%nat)) (ESub (ECell (875%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (876%nat, 0%nat)) (ESub (ECell (876%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (877%nat, 0%nat)) (ESub (ECell (877%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (878%nat, 0%nat)) (ESub (ECell (878%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (879%nat, 0%nat)) (ESub (ECell (879%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (880%nat, 0%nat)) (ESub (ECell (880%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (881%nat, 0%nat)) (ESub (ECell (881%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (882%nat, 0%nat)) (ESub (ECell (882%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (883%nat, 0%nat)) (ESub (ECell (883%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (884%nat, 0%nat)) (ESub (ECell (884%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (885%nat, 0%nat)) (ESub (ECell (885%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (886%nat, 0%nat)) (ESub (ECell (886%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (887%nat, 0%nat)) (ESub (ECell (887%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (888%nat, 0%nat)) (ESub (ECell (888%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (889%nat, 0%nat)) (ESub (ECell (889%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (890%nat, 0%nat)) (ESub (ECell (890%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (891%nat, 0%nat)) (ESub (ECell (891%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (892%nat, 0%nat)) (ESub (ECell (892%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (893%nat, 0%nat)) (ESub (ECell (893%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (894%nat, 0%nat)) (ESub (ECell (894%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (895%nat, 0%nat)) (ESub (ECell (895%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (896%nat, 0%nat)) (ESub (ECell (896%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (897%nat, 0%nat)) (ESub (ECell (897%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (898%nat, 0%nat)) (ESub (ECell (898%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (899%nat, 0%nat)) (ESub (ECell (899%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (900%nat, 0%nat)) (ESub (ECell (900%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (901%nat, 0%nat)) (ESub (ECell (901%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (902%nat, 0%nat)) (ESub (ECell (902%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (903%nat, 0%nat)) (ESub (ECell (903%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (904%nat, 0%nat)) (ESub (ECell (904%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (905%nat, 0%nat)) (ESub (ECell (905%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (906%nat, 0%nat)) (ESub (ECell (906%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (907%nat, 0%nat)) (ESub (ECell (907%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (908%nat, 0%nat)) (ESub (ECell (908%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (909%nat, 0%nat)) (ESub (ECell (909%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (910%nat, 0%nat)) (ESub (ECell (910%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (911%nat, 0%nat)) (ESub (ECell (911%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (912%nat, 0%nat)) (ESub (ECell (912%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (913%nat, 0%nat)) (ESub (ECell (913%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (914%nat, 0%nat)) (ESub (ECell (914%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (915%nat, 0%nat)) (ESub (ECell (915%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (916%nat, 0%nat)) (ESub (ECell (916%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (917%nat, 0%nat)) (ESub (ECell (917%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (918%nat, 0%nat)) (ESub (ECell (918%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (919%nat, 0%nat)) (ESub (ECell (919%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (920%nat, 0%nat)) (ESub (ECell (920%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (921%nat, 0%nat)) (ESub (ECell (921%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (922%nat, 0%nat)) (ESub (ECell (922%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (923%nat, 0%nat)) (ESub (ECell (923%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (924%nat, 0%nat)) (ESub (ECell (924%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (925%nat, 0%nat)) (ESub (ECell (925%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (926%nat, 0%nat)) (ESub (ECell (926%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (927%nat, 0%nat)) (ESub (ECell (927%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (928%nat, 0%nat)) (ESub (ECell (928%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (929%nat, 0%nat)) (ESub (ECell (929%nat, 0%nat)) (EConst 1))); + + (EMul (ECell (930%nat, 0%nat)) (ESub (ECell (930%nat, 0%nat)) (EConst 1))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (23%nat, 0%nat)) 1)) (EScaled (ECell (24%nat, 0%nat)) 2)) (EScaled (ECell (25%nat, 0%nat)) 4)) (EScaled (ECell (26%nat, 0%nat)) 8)) (EScaled (ECell (27%nat, 0%nat)) 16)) (EScaled (ECell (28%nat, 0%nat)) 32)) (EScaled (ECell (29%nat, 0%nat)) 64)) (EScaled (ECell (30%nat, 0%nat)) 128)) (EScaled (ECell (31%nat, 0%nat)) 256)) (EScaled (ECell (32%nat, 0%nat)) 512)) (EScaled (ECell (33%nat, 0%nat)) 1024)) (EScaled (ECell (34%nat, 0%nat)) 2048)) (EScaled (ECell (35%nat, 0%nat)) 4096)) (EScaled (ECell (36%nat, 0%nat)) 8192)) (EScaled (ECell (37%nat, 0%nat)) 16384)) (EScaled (ECell (38%nat, 0%nat)) 32768)) (EScaled (ECell (39%nat, 0%nat)) 65536)) (EScaled (ECell (40%nat, 0%nat)) 131072)) (EScaled (ECell (41%nat, 0%nat)) 262144)) (EScaled (ECell (42%nat, 0%nat)) 524288)) (EScaled (ECell (43%nat, 0%nat)) 1048576)) (EScaled (ECell (44%nat, 0%nat)) 2097152)) (EScaled (ECell (45%nat, 0%nat)) 4194304)) (EScaled (ECell (46%nat, 0%nat)) 8388608)) (EScaled (ECell (47%nat, 0%nat)) 16777216)) (EScaled (ECell (48%nat, 0%nat)) 33554432)) (EScaled (ECell (49%nat, 0%nat)) 67108864)) (EScaled (ECell (50%nat, 0%nat)) 134217728)) (EScaled (ECell (51%nat, 0%nat)) 268435456)) (EScaled (ECell (52%nat, 0%nat)) 536870912)) (EScaled (ECell (53%nat, 0%nat)) 1073741824)) (EScaled (ECell (54%nat, 0%nat)) 2147483648)) (EScaled (ECell (55%nat, 0%nat)) 4294967296)) (EScaled (ECell (56%nat, 0%nat)) 8589934592)) (EScaled (ECell (57%nat, 0%nat)) 17179869184)) (EScaled (ECell (58%nat, 0%nat)) 34359738368)) (EScaled (ECell (59%nat, 0%nat)) 68719476736)) (EScaled (ECell (60%nat, 0%nat)) 137438953472)) (EScaled (ECell (61%nat, 0%nat)) 274877906944)) (EScaled (ECell (62%nat, 0%nat)) 549755813888)) (EScaled (ECell (63%nat, 0%nat)) 1099511627776)) (EScaled (ECell (64%nat, 0%nat)) 2199023255552)) (EScaled (ECell (65%nat, 0%nat)) 4398046511104)) (EScaled (ECell (66%nat, 0%nat)) 8796093022208)) (EScaled (ECell (67%nat, 0%nat)) 17592186044416)) (EScaled (ECell (68%nat, 0%nat)) 35184372088832)) (EScaled (ECell (69%nat, 0%nat)) 70368744177664)) (EScaled (ECell (70%nat, 0%nat)) 140737488355328)) (EScaled (ECell (71%nat, 0%nat)) 281474976710656)) (EScaled (ECell (72%nat, 0%nat)) 562949953421312)) (EScaled (ECell (73%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (74%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (75%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (76%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (77%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (78%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (79%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (80%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (81%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (82%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (83%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (84%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (85%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (86%nat, 0%nat)) 9223372036854775808)) (ECell (8%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (87%nat, 0%nat)) 1)) (EScaled (ECell (88%nat, 0%nat)) 2)) (EScaled (ECell (89%nat, 0%nat)) 4)) (EScaled (ECell (90%nat, 0%nat)) 8)) (EScaled (ECell (91%nat, 0%nat)) 16)) (EScaled (ECell (92%nat, 0%nat)) 32)) (EScaled (ECell (93%nat, 0%nat)) 64)) (EScaled (ECell (94%nat, 0%nat)) 128)) (EScaled (ECell (95%nat, 0%nat)) 256)) (EScaled (ECell (96%nat, 0%nat)) 512)) (EScaled (ECell (97%nat, 0%nat)) 1024)) (EScaled (ECell (98%nat, 0%nat)) 2048)) (EScaled (ECell (99%nat, 0%nat)) 4096)) (EScaled (ECell (100%nat, 0%nat)) 8192)) (EScaled (ECell (101%nat, 0%nat)) 16384)) (EScaled (ECell (102%nat, 0%nat)) 32768)) (EScaled (ECell (103%nat, 0%nat)) 65536)) (EScaled (ECell (104%nat, 0%nat)) 131072)) (EScaled (ECell (105%nat, 0%nat)) 262144)) (EScaled (ECell (106%nat, 0%nat)) 524288)) (EScaled (ECell (107%nat, 0%nat)) 1048576)) (EScaled (ECell (108%nat, 0%nat)) 2097152)) (EScaled (ECell (109%nat, 0%nat)) 4194304)) (EScaled (ECell (110%nat, 0%nat)) 8388608)) (EScaled (ECell (111%nat, 0%nat)) 16777216)) (EScaled (ECell (112%nat, 0%nat)) 33554432)) (EScaled (ECell (113%nat, 0%nat)) 67108864)) (EScaled (ECell (114%nat, 0%nat)) 134217728)) (EScaled (ECell (115%nat, 0%nat)) 268435456)) (EScaled (ECell (116%nat, 0%nat)) 536870912)) (EScaled (ECell (117%nat, 0%nat)) 1073741824)) (EScaled (ECell (118%nat, 0%nat)) 2147483648)) (EScaled (ECell (119%nat, 0%nat)) 4294967296)) (EScaled (ECell (120%nat, 0%nat)) 8589934592)) (EScaled (ECell (121%nat, 0%nat)) 17179869184)) (EScaled (ECell (122%nat, 0%nat)) 34359738368)) (EScaled (ECell (123%nat, 0%nat)) 68719476736)) (EScaled (ECell (124%nat, 0%nat)) 137438953472)) (EScaled (ECell (125%nat, 0%nat)) 274877906944)) (EScaled (ECell (126%nat, 0%nat)) 549755813888)) (EScaled (ECell (127%nat, 0%nat)) 1099511627776)) (EScaled (ECell (128%nat, 0%nat)) 2199023255552)) (EScaled (ECell (129%nat, 0%nat)) 4398046511104)) (EScaled (ECell (130%nat, 0%nat)) 8796093022208)) (EScaled (ECell (131%nat, 0%nat)) 17592186044416)) (EScaled (ECell (132%nat, 0%nat)) 35184372088832)) (EScaled (ECell (133%nat, 0%nat)) 70368744177664)) (EScaled (ECell (134%nat, 0%nat)) 140737488355328)) (EScaled (ECell (135%nat, 0%nat)) 281474976710656)) (EScaled (ECell (136%nat, 0%nat)) 562949953421312)) (EScaled (ECell (137%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (138%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (139%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (140%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (141%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (142%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (143%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (144%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (145%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (146%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (147%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (148%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (149%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (150%nat, 0%nat)) 9223372036854775808)) (ECell (9%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (151%nat, 0%nat)) 1)) (EScaled (ECell (152%nat, 0%nat)) 2)) (EScaled (ECell (153%nat, 0%nat)) 4)) (EScaled (ECell (154%nat, 0%nat)) 8)) (EScaled (ECell (155%nat, 0%nat)) 16)) (EScaled (ECell (156%nat, 0%nat)) 32)) (EScaled (ECell (157%nat, 0%nat)) 64)) (EScaled (ECell (158%nat, 0%nat)) 128)) (EScaled (ECell (159%nat, 0%nat)) 256)) (EScaled (ECell (160%nat, 0%nat)) 512)) (EScaled (ECell (161%nat, 0%nat)) 1024)) (EScaled (ECell (162%nat, 0%nat)) 2048)) (EScaled (ECell (163%nat, 0%nat)) 4096)) (EScaled (ECell (164%nat, 0%nat)) 8192)) (EScaled (ECell (165%nat, 0%nat)) 16384)) (EScaled (ECell (166%nat, 0%nat)) 32768)) (EScaled (ECell (167%nat, 0%nat)) 65536)) (EScaled (ECell (168%nat, 0%nat)) 131072)) (EScaled (ECell (169%nat, 0%nat)) 262144)) (EScaled (ECell (170%nat, 0%nat)) 524288)) (EScaled (ECell (171%nat, 0%nat)) 1048576)) (EScaled (ECell (172%nat, 0%nat)) 2097152)) (EScaled (ECell (173%nat, 0%nat)) 4194304)) (EScaled (ECell (174%nat, 0%nat)) 8388608)) (EScaled (ECell (175%nat, 0%nat)) 16777216)) (EScaled (ECell (176%nat, 0%nat)) 33554432)) (EScaled (ECell (177%nat, 0%nat)) 67108864)) (EScaled (ECell (178%nat, 0%nat)) 134217728)) (EScaled (ECell (179%nat, 0%nat)) 268435456)) (EScaled (ECell (180%nat, 0%nat)) 536870912)) (EScaled (ECell (181%nat, 0%nat)) 1073741824)) (EScaled (ECell (182%nat, 0%nat)) 2147483648)) (EScaled (ECell (183%nat, 0%nat)) 4294967296)) (EScaled (ECell (184%nat, 0%nat)) 8589934592)) (EScaled (ECell (185%nat, 0%nat)) 17179869184)) (EScaled (ECell (186%nat, 0%nat)) 34359738368)) (EScaled (ECell (187%nat, 0%nat)) 68719476736)) (EScaled (ECell (188%nat, 0%nat)) 137438953472)) (EScaled (ECell (189%nat, 0%nat)) 274877906944)) (EScaled (ECell (190%nat, 0%nat)) 549755813888)) (EScaled (ECell (191%nat, 0%nat)) 1099511627776)) (EScaled (ECell (192%nat, 0%nat)) 2199023255552)) (EScaled (ECell (193%nat, 0%nat)) 4398046511104)) (EScaled (ECell (194%nat, 0%nat)) 8796093022208)) (EScaled (ECell (195%nat, 0%nat)) 17592186044416)) (EScaled (ECell (196%nat, 0%nat)) 35184372088832)) (EScaled (ECell (197%nat, 0%nat)) 70368744177664)) (EScaled (ECell (198%nat, 0%nat)) 140737488355328)) (EScaled (ECell (199%nat, 0%nat)) 281474976710656)) (EScaled (ECell (200%nat, 0%nat)) 562949953421312)) (EScaled (ECell (201%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (202%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (203%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (204%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (205%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (206%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (207%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (208%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (209%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (210%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (211%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (212%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (213%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (214%nat, 0%nat)) 9223372036854775808)) (ECell (10%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (215%nat, 0%nat)) 1)) (EScaled (ECell (216%nat, 0%nat)) 2)) (EScaled (ECell (217%nat, 0%nat)) 4)) (EScaled (ECell (218%nat, 0%nat)) 8)) (EScaled (ECell (219%nat, 0%nat)) 16)) (EScaled (ECell (220%nat, 0%nat)) 32)) (EScaled (ECell (221%nat, 0%nat)) 64)) (EScaled (ECell (222%nat, 0%nat)) 128)) (EScaled (ECell (223%nat, 0%nat)) 256)) (EScaled (ECell (224%nat, 0%nat)) 512)) (EScaled (ECell (225%nat, 0%nat)) 1024)) (EScaled (ECell (226%nat, 0%nat)) 2048)) (EScaled (ECell (227%nat, 0%nat)) 4096)) (EScaled (ECell (228%nat, 0%nat)) 8192)) (EScaled (ECell (229%nat, 0%nat)) 16384)) (EScaled (ECell (230%nat, 0%nat)) 32768)) (EScaled (ECell (231%nat, 0%nat)) 65536)) (EScaled (ECell (232%nat, 0%nat)) 131072)) (EScaled (ECell (233%nat, 0%nat)) 262144)) (EScaled (ECell (234%nat, 0%nat)) 524288)) (EScaled (ECell (235%nat, 0%nat)) 1048576)) (EScaled (ECell (236%nat, 0%nat)) 2097152)) (EScaled (ECell (237%nat, 0%nat)) 4194304)) (EScaled (ECell (238%nat, 0%nat)) 8388608)) (EScaled (ECell (239%nat, 0%nat)) 16777216)) (EScaled (ECell (240%nat, 0%nat)) 33554432)) (EScaled (ECell (241%nat, 0%nat)) 67108864)) (EScaled (ECell (242%nat, 0%nat)) 134217728)) (EScaled (ECell (243%nat, 0%nat)) 268435456)) (EScaled (ECell (244%nat, 0%nat)) 536870912)) (EScaled (ECell (245%nat, 0%nat)) 1073741824)) (EScaled (ECell (246%nat, 0%nat)) 2147483648)) (EScaled (ECell (247%nat, 0%nat)) 4294967296)) (EScaled (ECell (248%nat, 0%nat)) 8589934592)) (EScaled (ECell (249%nat, 0%nat)) 17179869184)) (EScaled (ECell (250%nat, 0%nat)) 34359738368)) (EScaled (ECell (251%nat, 0%nat)) 68719476736)) (EScaled (ECell (252%nat, 0%nat)) 137438953472)) (EScaled (ECell (253%nat, 0%nat)) 274877906944)) (EScaled (ECell (254%nat, 0%nat)) 549755813888)) (EScaled (ECell (255%nat, 0%nat)) 1099511627776)) (EScaled (ECell (256%nat, 0%nat)) 2199023255552)) (EScaled (ECell (257%nat, 0%nat)) 4398046511104)) (EScaled (ECell (258%nat, 0%nat)) 8796093022208)) (EScaled (ECell (259%nat, 0%nat)) 17592186044416)) (EScaled (ECell (260%nat, 0%nat)) 35184372088832)) (EScaled (ECell (261%nat, 0%nat)) 70368744177664)) (EScaled (ECell (262%nat, 0%nat)) 140737488355328)) (EScaled (ECell (263%nat, 0%nat)) 281474976710656)) (EScaled (ECell (264%nat, 0%nat)) 562949953421312)) (EScaled (ECell (265%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (266%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (267%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (268%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (269%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (270%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (271%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (272%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (273%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (274%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (275%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (276%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (277%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (278%nat, 0%nat)) 9223372036854775808)) (ECell (11%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (279%nat, 0%nat)) 1)) (EScaled (ECell (280%nat, 0%nat)) 2)) (EScaled (ECell (281%nat, 0%nat)) 4)) (EScaled (ECell (282%nat, 0%nat)) 8)) (EScaled (ECell (283%nat, 0%nat)) 16)) (EScaled (ECell (284%nat, 0%nat)) 32)) (EScaled (ECell (285%nat, 0%nat)) 64)) (EScaled (ECell (286%nat, 0%nat)) 128)) (EScaled (ECell (287%nat, 0%nat)) 256)) (EScaled (ECell (288%nat, 0%nat)) 512)) (EScaled (ECell (289%nat, 0%nat)) 1024)) (EScaled (ECell (290%nat, 0%nat)) 2048)) (EScaled (ECell (291%nat, 0%nat)) 4096)) (EScaled (ECell (292%nat, 0%nat)) 8192)) (EScaled (ECell (293%nat, 0%nat)) 16384)) (EScaled (ECell (294%nat, 0%nat)) 32768)) (EScaled (ECell (295%nat, 0%nat)) 65536)) (EScaled (ECell (296%nat, 0%nat)) 131072)) (EScaled (ECell (297%nat, 0%nat)) 262144)) (EScaled (ECell (298%nat, 0%nat)) 524288)) (EScaled (ECell (299%nat, 0%nat)) 1048576)) (EScaled (ECell (300%nat, 0%nat)) 2097152)) (EScaled (ECell (301%nat, 0%nat)) 4194304)) (EScaled (ECell (302%nat, 0%nat)) 8388608)) (EScaled (ECell (303%nat, 0%nat)) 16777216)) (EScaled (ECell (304%nat, 0%nat)) 33554432)) (EScaled (ECell (305%nat, 0%nat)) 67108864)) (EScaled (ECell (306%nat, 0%nat)) 134217728)) (EScaled (ECell (307%nat, 0%nat)) 268435456)) (EScaled (ECell (308%nat, 0%nat)) 536870912)) (EScaled (ECell (309%nat, 0%nat)) 1073741824)) (EScaled (ECell (310%nat, 0%nat)) 2147483648)) (EScaled (ECell (311%nat, 0%nat)) 4294967296)) (EScaled (ECell (312%nat, 0%nat)) 8589934592)) (EScaled (ECell (313%nat, 0%nat)) 17179869184)) (EScaled (ECell (314%nat, 0%nat)) 34359738368)) (EScaled (ECell (315%nat, 0%nat)) 68719476736)) (EScaled (ECell (316%nat, 0%nat)) 137438953472)) (EScaled (ECell (317%nat, 0%nat)) 274877906944)) (EScaled (ECell (318%nat, 0%nat)) 549755813888)) (EScaled (ECell (319%nat, 0%nat)) 1099511627776)) (EScaled (ECell (320%nat, 0%nat)) 2199023255552)) (EScaled (ECell (321%nat, 0%nat)) 4398046511104)) (EScaled (ECell (322%nat, 0%nat)) 8796093022208)) (EScaled (ECell (323%nat, 0%nat)) 17592186044416)) (EScaled (ECell (324%nat, 0%nat)) 35184372088832)) (EScaled (ECell (325%nat, 0%nat)) 70368744177664)) (EScaled (ECell (326%nat, 0%nat)) 140737488355328)) (EScaled (ECell (327%nat, 0%nat)) 281474976710656)) (EScaled (ECell (328%nat, 0%nat)) 562949953421312)) (EScaled (ECell (329%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (330%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (331%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (332%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (333%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (334%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (335%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (336%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (337%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (338%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (339%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (340%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (341%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (342%nat, 0%nat)) 9223372036854775808)) (ECell (12%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (343%nat, 0%nat)) 1)) (EScaled (ECell (344%nat, 0%nat)) 2)) (EScaled (ECell (345%nat, 0%nat)) 4)) (EScaled (ECell (346%nat, 0%nat)) 8)) (EScaled (ECell (347%nat, 0%nat)) 16)) (EScaled (ECell (348%nat, 0%nat)) 32)) (EScaled (ECell (349%nat, 0%nat)) 64)) (EScaled (ECell (350%nat, 0%nat)) 128)) (EScaled (ECell (351%nat, 0%nat)) 256)) (EScaled (ECell (352%nat, 0%nat)) 512)) (EScaled (ECell (353%nat, 0%nat)) 1024)) (EScaled (ECell (354%nat, 0%nat)) 2048)) (EScaled (ECell (355%nat, 0%nat)) 4096)) (EScaled (ECell (356%nat, 0%nat)) 8192)) (EScaled (ECell (357%nat, 0%nat)) 16384)) (EScaled (ECell (358%nat, 0%nat)) 32768)) (EScaled (ECell (359%nat, 0%nat)) 65536)) (EScaled (ECell (360%nat, 0%nat)) 131072)) (EScaled (ECell (361%nat, 0%nat)) 262144)) (EScaled (ECell (362%nat, 0%nat)) 524288)) (EScaled (ECell (363%nat, 0%nat)) 1048576)) (EScaled (ECell (364%nat, 0%nat)) 2097152)) (EScaled (ECell (365%nat, 0%nat)) 4194304)) (EScaled (ECell (366%nat, 0%nat)) 8388608)) (EScaled (ECell (367%nat, 0%nat)) 16777216)) (EScaled (ECell (368%nat, 0%nat)) 33554432)) (EScaled (ECell (369%nat, 0%nat)) 67108864)) (EScaled (ECell (370%nat, 0%nat)) 134217728)) (EScaled (ECell (371%nat, 0%nat)) 268435456)) (EScaled (ECell (372%nat, 0%nat)) 536870912)) (EScaled (ECell (373%nat, 0%nat)) 1073741824)) (EScaled (ECell (374%nat, 0%nat)) 2147483648)) (EScaled (ECell (375%nat, 0%nat)) 4294967296)) (EScaled (ECell (376%nat, 0%nat)) 8589934592)) (EScaled (ECell (377%nat, 0%nat)) 17179869184)) (EScaled (ECell (378%nat, 0%nat)) 34359738368)) (EScaled (ECell (379%nat, 0%nat)) 68719476736)) (EScaled (ECell (380%nat, 0%nat)) 137438953472)) (EScaled (ECell (381%nat, 0%nat)) 274877906944)) (EScaled (ECell (382%nat, 0%nat)) 549755813888)) (EScaled (ECell (383%nat, 0%nat)) 1099511627776)) (EScaled (ECell (384%nat, 0%nat)) 2199023255552)) (EScaled (ECell (385%nat, 0%nat)) 4398046511104)) (EScaled (ECell (386%nat, 0%nat)) 8796093022208)) (EScaled (ECell (387%nat, 0%nat)) 17592186044416)) (EScaled (ECell (388%nat, 0%nat)) 35184372088832)) (EScaled (ECell (389%nat, 0%nat)) 70368744177664)) (EScaled (ECell (390%nat, 0%nat)) 140737488355328)) (EScaled (ECell (391%nat, 0%nat)) 281474976710656)) (EScaled (ECell (392%nat, 0%nat)) 562949953421312)) (EScaled (ECell (393%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (394%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (395%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (396%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (397%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (398%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (399%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (400%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (401%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (402%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (403%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (404%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (405%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (406%nat, 0%nat)) 9223372036854775808)) (ECell (13%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (407%nat, 0%nat)) 1)) (EScaled (ECell (408%nat, 0%nat)) 2)) (EScaled (ECell (409%nat, 0%nat)) 4)) (EScaled (ECell (410%nat, 0%nat)) 8)) (EScaled (ECell (411%nat, 0%nat)) 16)) (EScaled (ECell (412%nat, 0%nat)) 32)) (EScaled (ECell (413%nat, 0%nat)) 64)) (EScaled (ECell (414%nat, 0%nat)) 128)) (EScaled (ECell (415%nat, 0%nat)) 256)) (EScaled (ECell (416%nat, 0%nat)) 512)) (EScaled (ECell (417%nat, 0%nat)) 1024)) (EScaled (ECell (418%nat, 0%nat)) 2048)) (EScaled (ECell (419%nat, 0%nat)) 4096)) (EScaled (ECell (420%nat, 0%nat)) 8192)) (EScaled (ECell (421%nat, 0%nat)) 16384)) (EScaled (ECell (422%nat, 0%nat)) 32768)) (EScaled (ECell (423%nat, 0%nat)) 65536)) (EScaled (ECell (424%nat, 0%nat)) 131072)) (EScaled (ECell (425%nat, 0%nat)) 262144)) (EScaled (ECell (426%nat, 0%nat)) 524288)) (EScaled (ECell (427%nat, 0%nat)) 1048576)) (EScaled (ECell (428%nat, 0%nat)) 2097152)) (EScaled (ECell (429%nat, 0%nat)) 4194304)) (EScaled (ECell (430%nat, 0%nat)) 8388608)) (EScaled (ECell (431%nat, 0%nat)) 16777216)) (EScaled (ECell (432%nat, 0%nat)) 33554432)) (EScaled (ECell (433%nat, 0%nat)) 67108864)) (EScaled (ECell (434%nat, 0%nat)) 134217728)) (EScaled (ECell (435%nat, 0%nat)) 268435456)) (EScaled (ECell (436%nat, 0%nat)) 536870912)) (EScaled (ECell (437%nat, 0%nat)) 1073741824)) (EScaled (ECell (438%nat, 0%nat)) 2147483648)) (EScaled (ECell (439%nat, 0%nat)) 4294967296)) (EScaled (ECell (440%nat, 0%nat)) 8589934592)) (EScaled (ECell (441%nat, 0%nat)) 17179869184)) (EScaled (ECell (442%nat, 0%nat)) 34359738368)) (EScaled (ECell (443%nat, 0%nat)) 68719476736)) (EScaled (ECell (444%nat, 0%nat)) 137438953472)) (EScaled (ECell (445%nat, 0%nat)) 274877906944)) (EScaled (ECell (446%nat, 0%nat)) 549755813888)) (EScaled (ECell (447%nat, 0%nat)) 1099511627776)) (EScaled (ECell (448%nat, 0%nat)) 2199023255552)) (EScaled (ECell (449%nat, 0%nat)) 4398046511104)) (EScaled (ECell (450%nat, 0%nat)) 8796093022208)) (EScaled (ECell (451%nat, 0%nat)) 17592186044416)) (EScaled (ECell (452%nat, 0%nat)) 35184372088832)) (EScaled (ECell (453%nat, 0%nat)) 70368744177664)) (EScaled (ECell (454%nat, 0%nat)) 140737488355328)) (EScaled (ECell (455%nat, 0%nat)) 281474976710656)) (EScaled (ECell (456%nat, 0%nat)) 562949953421312)) (EScaled (ECell (457%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (458%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (459%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (460%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (461%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (462%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (463%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (464%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (465%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (466%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (467%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (468%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (469%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (470%nat, 0%nat)) 9223372036854775808)) (ECell (14%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (471%nat, 0%nat)) 1)) (EScaled (ECell (472%nat, 0%nat)) 2)) (EScaled (ECell (473%nat, 0%nat)) 4)) (EScaled (ECell (474%nat, 0%nat)) 8)) (EScaled (ECell (475%nat, 0%nat)) 16)) (EScaled (ECell (476%nat, 0%nat)) 32)) (EScaled (ECell (477%nat, 0%nat)) 64)) (EScaled (ECell (478%nat, 0%nat)) 128)) (EScaled (ECell (479%nat, 0%nat)) 256)) (EScaled (ECell (480%nat, 0%nat)) 512)) (EScaled (ECell (481%nat, 0%nat)) 1024)) (EScaled (ECell (482%nat, 0%nat)) 2048)) (EScaled (ECell (483%nat, 0%nat)) 4096)) (EScaled (ECell (484%nat, 0%nat)) 8192)) (EScaled (ECell (485%nat, 0%nat)) 16384)) (EScaled (ECell (486%nat, 0%nat)) 32768)) (EScaled (ECell (487%nat, 0%nat)) 65536)) (EScaled (ECell (488%nat, 0%nat)) 131072)) (EScaled (ECell (489%nat, 0%nat)) 262144)) (EScaled (ECell (490%nat, 0%nat)) 524288)) (EScaled (ECell (491%nat, 0%nat)) 1048576)) (EScaled (ECell (492%nat, 0%nat)) 2097152)) (EScaled (ECell (493%nat, 0%nat)) 4194304)) (EScaled (ECell (494%nat, 0%nat)) 8388608)) (EScaled (ECell (495%nat, 0%nat)) 16777216)) (EScaled (ECell (496%nat, 0%nat)) 33554432)) (EScaled (ECell (497%nat, 0%nat)) 67108864)) (EScaled (ECell (498%nat, 0%nat)) 134217728)) (EScaled (ECell (499%nat, 0%nat)) 268435456)) (EScaled (ECell (500%nat, 0%nat)) 536870912)) (EScaled (ECell (501%nat, 0%nat)) 1073741824)) (EScaled (ECell (502%nat, 0%nat)) 2147483648)) (EScaled (ECell (503%nat, 0%nat)) 4294967296)) (EScaled (ECell (504%nat, 0%nat)) 8589934592)) (EScaled (ECell (505%nat, 0%nat)) 17179869184)) (EScaled (ECell (506%nat, 0%nat)) 34359738368)) (EScaled (ECell (507%nat, 0%nat)) 68719476736)) (EScaled (ECell (508%nat, 0%nat)) 137438953472)) (EScaled (ECell (509%nat, 0%nat)) 274877906944)) (EScaled (ECell (510%nat, 0%nat)) 549755813888)) (EScaled (ECell (511%nat, 0%nat)) 1099511627776)) (EScaled (ECell (512%nat, 0%nat)) 2199023255552)) (EScaled (ECell (513%nat, 0%nat)) 4398046511104)) (EScaled (ECell (514%nat, 0%nat)) 8796093022208)) (EScaled (ECell (515%nat, 0%nat)) 17592186044416)) (EScaled (ECell (516%nat, 0%nat)) 35184372088832)) (EScaled (ECell (517%nat, 0%nat)) 70368744177664)) (EScaled (ECell (518%nat, 0%nat)) 140737488355328)) (EScaled (ECell (519%nat, 0%nat)) 281474976710656)) (EScaled (ECell (520%nat, 0%nat)) 562949953421312)) (EScaled (ECell (521%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (522%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (523%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (524%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (525%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (526%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (527%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (528%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (529%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (530%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (531%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (532%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (533%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (534%nat, 0%nat)) 9223372036854775808)) (ECell (15%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (535%nat, 0%nat)) 1)) (EScaled (ECell (536%nat, 0%nat)) 2)) (EScaled (ECell (537%nat, 0%nat)) 4)) (EScaled (ECell (538%nat, 0%nat)) 8)) (EScaled (ECell (539%nat, 0%nat)) 16)) (EScaled (ECell (540%nat, 0%nat)) 32)) (EScaled (ECell (541%nat, 0%nat)) 64)) (EScaled (ECell (542%nat, 0%nat)) 128)) (EScaled (ECell (543%nat, 0%nat)) 256)) (EScaled (ECell (544%nat, 0%nat)) 512)) (EScaled (ECell (545%nat, 0%nat)) 1024)) (EScaled (ECell (546%nat, 0%nat)) 2048)) (EScaled (ECell (547%nat, 0%nat)) 4096)) (EScaled (ECell (548%nat, 0%nat)) 8192)) (EScaled (ECell (549%nat, 0%nat)) 16384)) (EScaled (ECell (550%nat, 0%nat)) 32768)) (EScaled (ECell (551%nat, 0%nat)) 65536)) (EScaled (ECell (552%nat, 0%nat)) 131072)) (EScaled (ECell (553%nat, 0%nat)) 262144)) (EScaled (ECell (554%nat, 0%nat)) 524288)) (EScaled (ECell (555%nat, 0%nat)) 1048576)) (EScaled (ECell (556%nat, 0%nat)) 2097152)) (EScaled (ECell (557%nat, 0%nat)) 4194304)) (EScaled (ECell (558%nat, 0%nat)) 8388608)) (EScaled (ECell (559%nat, 0%nat)) 16777216)) (EScaled (ECell (560%nat, 0%nat)) 33554432)) (EScaled (ECell (561%nat, 0%nat)) 67108864)) (EScaled (ECell (562%nat, 0%nat)) 134217728)) (EScaled (ECell (563%nat, 0%nat)) 268435456)) (EScaled (ECell (564%nat, 0%nat)) 536870912)) (EScaled (ECell (565%nat, 0%nat)) 1073741824)) (EScaled (ECell (566%nat, 0%nat)) 2147483648)) (EScaled (ECell (567%nat, 0%nat)) 4294967296)) (EScaled (ECell (568%nat, 0%nat)) 8589934592)) (EScaled (ECell (569%nat, 0%nat)) 17179869184)) (EScaled (ECell (570%nat, 0%nat)) 34359738368)) (EScaled (ECell (571%nat, 0%nat)) 68719476736)) (EScaled (ECell (572%nat, 0%nat)) 137438953472)) (EScaled (ECell (573%nat, 0%nat)) 274877906944)) (EScaled (ECell (574%nat, 0%nat)) 549755813888)) (EScaled (ECell (575%nat, 0%nat)) 1099511627776)) (EScaled (ECell (576%nat, 0%nat)) 2199023255552)) (EScaled (ECell (577%nat, 0%nat)) 4398046511104)) (EScaled (ECell (578%nat, 0%nat)) 8796093022208)) (EScaled (ECell (579%nat, 0%nat)) 17592186044416)) (EScaled (ECell (580%nat, 0%nat)) 35184372088832)) (EScaled (ECell (581%nat, 0%nat)) 70368744177664)) (EScaled (ECell (582%nat, 0%nat)) 140737488355328)) (EScaled (ECell (583%nat, 0%nat)) 281474976710656)) (EScaled (ECell (584%nat, 0%nat)) 562949953421312)) (EScaled (ECell (585%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (586%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (587%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (588%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (589%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (590%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (591%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (592%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (593%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (594%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (595%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (596%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (597%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (598%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (599%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (600%nat, 0%nat)) 36893488147419103232)) (ECell (16%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (601%nat, 0%nat)) 1)) (EScaled (ECell (602%nat, 0%nat)) 2)) (EScaled (ECell (603%nat, 0%nat)) 4)) (EScaled (ECell (604%nat, 0%nat)) 8)) (EScaled (ECell (605%nat, 0%nat)) 16)) (EScaled (ECell (606%nat, 0%nat)) 32)) (EScaled (ECell (607%nat, 0%nat)) 64)) (EScaled (ECell (608%nat, 0%nat)) 128)) (EScaled (ECell (609%nat, 0%nat)) 256)) (EScaled (ECell (610%nat, 0%nat)) 512)) (EScaled (ECell (611%nat, 0%nat)) 1024)) (EScaled (ECell (612%nat, 0%nat)) 2048)) (EScaled (ECell (613%nat, 0%nat)) 4096)) (EScaled (ECell (614%nat, 0%nat)) 8192)) (EScaled (ECell (615%nat, 0%nat)) 16384)) (EScaled (ECell (616%nat, 0%nat)) 32768)) (EScaled (ECell (617%nat, 0%nat)) 65536)) (EScaled (ECell (618%nat, 0%nat)) 131072)) (EScaled (ECell (619%nat, 0%nat)) 262144)) (EScaled (ECell (620%nat, 0%nat)) 524288)) (EScaled (ECell (621%nat, 0%nat)) 1048576)) (EScaled (ECell (622%nat, 0%nat)) 2097152)) (EScaled (ECell (623%nat, 0%nat)) 4194304)) (EScaled (ECell (624%nat, 0%nat)) 8388608)) (EScaled (ECell (625%nat, 0%nat)) 16777216)) (EScaled (ECell (626%nat, 0%nat)) 33554432)) (EScaled (ECell (627%nat, 0%nat)) 67108864)) (EScaled (ECell (628%nat, 0%nat)) 134217728)) (EScaled (ECell (629%nat, 0%nat)) 268435456)) (EScaled (ECell (630%nat, 0%nat)) 536870912)) (EScaled (ECell (631%nat, 0%nat)) 1073741824)) (EScaled (ECell (632%nat, 0%nat)) 2147483648)) (EScaled (ECell (633%nat, 0%nat)) 4294967296)) (EScaled (ECell (634%nat, 0%nat)) 8589934592)) (EScaled (ECell (635%nat, 0%nat)) 17179869184)) (EScaled (ECell (636%nat, 0%nat)) 34359738368)) (EScaled (ECell (637%nat, 0%nat)) 68719476736)) (EScaled (ECell (638%nat, 0%nat)) 137438953472)) (EScaled (ECell (639%nat, 0%nat)) 274877906944)) (EScaled (ECell (640%nat, 0%nat)) 549755813888)) (EScaled (ECell (641%nat, 0%nat)) 1099511627776)) (EScaled (ECell (642%nat, 0%nat)) 2199023255552)) (EScaled (ECell (643%nat, 0%nat)) 4398046511104)) (EScaled (ECell (644%nat, 0%nat)) 8796093022208)) (EScaled (ECell (645%nat, 0%nat)) 17592186044416)) (EScaled (ECell (646%nat, 0%nat)) 35184372088832)) (EScaled (ECell (647%nat, 0%nat)) 70368744177664)) (EScaled (ECell (648%nat, 0%nat)) 140737488355328)) (EScaled (ECell (649%nat, 0%nat)) 281474976710656)) (EScaled (ECell (650%nat, 0%nat)) 562949953421312)) (EScaled (ECell (651%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (652%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (653%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (654%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (655%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (656%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (657%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (658%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (659%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (660%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (661%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (662%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (663%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (664%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (665%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (666%nat, 0%nat)) 36893488147419103232)) (ECell (17%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (667%nat, 0%nat)) 1)) (EScaled (ECell (668%nat, 0%nat)) 2)) (EScaled (ECell (669%nat, 0%nat)) 4)) (EScaled (ECell (670%nat, 0%nat)) 8)) (EScaled (ECell (671%nat, 0%nat)) 16)) (EScaled (ECell (672%nat, 0%nat)) 32)) (EScaled (ECell (673%nat, 0%nat)) 64)) (EScaled (ECell (674%nat, 0%nat)) 128)) (EScaled (ECell (675%nat, 0%nat)) 256)) (EScaled (ECell (676%nat, 0%nat)) 512)) (EScaled (ECell (677%nat, 0%nat)) 1024)) (EScaled (ECell (678%nat, 0%nat)) 2048)) (EScaled (ECell (679%nat, 0%nat)) 4096)) (EScaled (ECell (680%nat, 0%nat)) 8192)) (EScaled (ECell (681%nat, 0%nat)) 16384)) (EScaled (ECell (682%nat, 0%nat)) 32768)) (EScaled (ECell (683%nat, 0%nat)) 65536)) (EScaled (ECell (684%nat, 0%nat)) 131072)) (EScaled (ECell (685%nat, 0%nat)) 262144)) (EScaled (ECell (686%nat, 0%nat)) 524288)) (EScaled (ECell (687%nat, 0%nat)) 1048576)) (EScaled (ECell (688%nat, 0%nat)) 2097152)) (EScaled (ECell (689%nat, 0%nat)) 4194304)) (EScaled (ECell (690%nat, 0%nat)) 8388608)) (EScaled (ECell (691%nat, 0%nat)) 16777216)) (EScaled (ECell (692%nat, 0%nat)) 33554432)) (EScaled (ECell (693%nat, 0%nat)) 67108864)) (EScaled (ECell (694%nat, 0%nat)) 134217728)) (EScaled (ECell (695%nat, 0%nat)) 268435456)) (EScaled (ECell (696%nat, 0%nat)) 536870912)) (EScaled (ECell (697%nat, 0%nat)) 1073741824)) (EScaled (ECell (698%nat, 0%nat)) 2147483648)) (EScaled (ECell (699%nat, 0%nat)) 4294967296)) (EScaled (ECell (700%nat, 0%nat)) 8589934592)) (EScaled (ECell (701%nat, 0%nat)) 17179869184)) (EScaled (ECell (702%nat, 0%nat)) 34359738368)) (EScaled (ECell (703%nat, 0%nat)) 68719476736)) (EScaled (ECell (704%nat, 0%nat)) 137438953472)) (EScaled (ECell (705%nat, 0%nat)) 274877906944)) (EScaled (ECell (706%nat, 0%nat)) 549755813888)) (EScaled (ECell (707%nat, 0%nat)) 1099511627776)) (EScaled (ECell (708%nat, 0%nat)) 2199023255552)) (EScaled (ECell (709%nat, 0%nat)) 4398046511104)) (EScaled (ECell (710%nat, 0%nat)) 8796093022208)) (EScaled (ECell (711%nat, 0%nat)) 17592186044416)) (EScaled (ECell (712%nat, 0%nat)) 35184372088832)) (EScaled (ECell (713%nat, 0%nat)) 70368744177664)) (EScaled (ECell (714%nat, 0%nat)) 140737488355328)) (EScaled (ECell (715%nat, 0%nat)) 281474976710656)) (EScaled (ECell (716%nat, 0%nat)) 562949953421312)) (EScaled (ECell (717%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (718%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (719%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (720%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (721%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (722%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (723%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (724%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (725%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (726%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (727%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (728%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (729%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (730%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (731%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (732%nat, 0%nat)) 36893488147419103232)) (ECell (18%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (733%nat, 0%nat)) 1)) (EScaled (ECell (734%nat, 0%nat)) 2)) (EScaled (ECell (735%nat, 0%nat)) 4)) (EScaled (ECell (736%nat, 0%nat)) 8)) (EScaled (ECell (737%nat, 0%nat)) 16)) (EScaled (ECell (738%nat, 0%nat)) 32)) (EScaled (ECell (739%nat, 0%nat)) 64)) (EScaled (ECell (740%nat, 0%nat)) 128)) (EScaled (ECell (741%nat, 0%nat)) 256)) (EScaled (ECell (742%nat, 0%nat)) 512)) (EScaled (ECell (743%nat, 0%nat)) 1024)) (EScaled (ECell (744%nat, 0%nat)) 2048)) (EScaled (ECell (745%nat, 0%nat)) 4096)) (EScaled (ECell (746%nat, 0%nat)) 8192)) (EScaled (ECell (747%nat, 0%nat)) 16384)) (EScaled (ECell (748%nat, 0%nat)) 32768)) (EScaled (ECell (749%nat, 0%nat)) 65536)) (EScaled (ECell (750%nat, 0%nat)) 131072)) (EScaled (ECell (751%nat, 0%nat)) 262144)) (EScaled (ECell (752%nat, 0%nat)) 524288)) (EScaled (ECell (753%nat, 0%nat)) 1048576)) (EScaled (ECell (754%nat, 0%nat)) 2097152)) (EScaled (ECell (755%nat, 0%nat)) 4194304)) (EScaled (ECell (756%nat, 0%nat)) 8388608)) (EScaled (ECell (757%nat, 0%nat)) 16777216)) (EScaled (ECell (758%nat, 0%nat)) 33554432)) (EScaled (ECell (759%nat, 0%nat)) 67108864)) (EScaled (ECell (760%nat, 0%nat)) 134217728)) (EScaled (ECell (761%nat, 0%nat)) 268435456)) (EScaled (ECell (762%nat, 0%nat)) 536870912)) (EScaled (ECell (763%nat, 0%nat)) 1073741824)) (EScaled (ECell (764%nat, 0%nat)) 2147483648)) (EScaled (ECell (765%nat, 0%nat)) 4294967296)) (EScaled (ECell (766%nat, 0%nat)) 8589934592)) (EScaled (ECell (767%nat, 0%nat)) 17179869184)) (EScaled (ECell (768%nat, 0%nat)) 34359738368)) (EScaled (ECell (769%nat, 0%nat)) 68719476736)) (EScaled (ECell (770%nat, 0%nat)) 137438953472)) (EScaled (ECell (771%nat, 0%nat)) 274877906944)) (EScaled (ECell (772%nat, 0%nat)) 549755813888)) (EScaled (ECell (773%nat, 0%nat)) 1099511627776)) (EScaled (ECell (774%nat, 0%nat)) 2199023255552)) (EScaled (ECell (775%nat, 0%nat)) 4398046511104)) (EScaled (ECell (776%nat, 0%nat)) 8796093022208)) (EScaled (ECell (777%nat, 0%nat)) 17592186044416)) (EScaled (ECell (778%nat, 0%nat)) 35184372088832)) (EScaled (ECell (779%nat, 0%nat)) 70368744177664)) (EScaled (ECell (780%nat, 0%nat)) 140737488355328)) (EScaled (ECell (781%nat, 0%nat)) 281474976710656)) (EScaled (ECell (782%nat, 0%nat)) 562949953421312)) (EScaled (ECell (783%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (784%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (785%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (786%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (787%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (788%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (789%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (790%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (791%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (792%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (793%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (794%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (795%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (796%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (797%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (798%nat, 0%nat)) 36893488147419103232)) (ECell (19%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (799%nat, 0%nat)) 1)) (EScaled (ECell (800%nat, 0%nat)) 2)) (EScaled (ECell (801%nat, 0%nat)) 4)) (EScaled (ECell (802%nat, 0%nat)) 8)) (EScaled (ECell (803%nat, 0%nat)) 16)) (EScaled (ECell (804%nat, 0%nat)) 32)) (EScaled (ECell (805%nat, 0%nat)) 64)) (EScaled (ECell (806%nat, 0%nat)) 128)) (EScaled (ECell (807%nat, 0%nat)) 256)) (EScaled (ECell (808%nat, 0%nat)) 512)) (EScaled (ECell (809%nat, 0%nat)) 1024)) (EScaled (ECell (810%nat, 0%nat)) 2048)) (EScaled (ECell (811%nat, 0%nat)) 4096)) (EScaled (ECell (812%nat, 0%nat)) 8192)) (EScaled (ECell (813%nat, 0%nat)) 16384)) (EScaled (ECell (814%nat, 0%nat)) 32768)) (EScaled (ECell (815%nat, 0%nat)) 65536)) (EScaled (ECell (816%nat, 0%nat)) 131072)) (EScaled (ECell (817%nat, 0%nat)) 262144)) (EScaled (ECell (818%nat, 0%nat)) 524288)) (EScaled (ECell (819%nat, 0%nat)) 1048576)) (EScaled (ECell (820%nat, 0%nat)) 2097152)) (EScaled (ECell (821%nat, 0%nat)) 4194304)) (EScaled (ECell (822%nat, 0%nat)) 8388608)) (EScaled (ECell (823%nat, 0%nat)) 16777216)) (EScaled (ECell (824%nat, 0%nat)) 33554432)) (EScaled (ECell (825%nat, 0%nat)) 67108864)) (EScaled (ECell (826%nat, 0%nat)) 134217728)) (EScaled (ECell (827%nat, 0%nat)) 268435456)) (EScaled (ECell (828%nat, 0%nat)) 536870912)) (EScaled (ECell (829%nat, 0%nat)) 1073741824)) (EScaled (ECell (830%nat, 0%nat)) 2147483648)) (EScaled (ECell (831%nat, 0%nat)) 4294967296)) (EScaled (ECell (832%nat, 0%nat)) 8589934592)) (EScaled (ECell (833%nat, 0%nat)) 17179869184)) (EScaled (ECell (834%nat, 0%nat)) 34359738368)) (EScaled (ECell (835%nat, 0%nat)) 68719476736)) (EScaled (ECell (836%nat, 0%nat)) 137438953472)) (EScaled (ECell (837%nat, 0%nat)) 274877906944)) (EScaled (ECell (838%nat, 0%nat)) 549755813888)) (EScaled (ECell (839%nat, 0%nat)) 1099511627776)) (EScaled (ECell (840%nat, 0%nat)) 2199023255552)) (EScaled (ECell (841%nat, 0%nat)) 4398046511104)) (EScaled (ECell (842%nat, 0%nat)) 8796093022208)) (EScaled (ECell (843%nat, 0%nat)) 17592186044416)) (EScaled (ECell (844%nat, 0%nat)) 35184372088832)) (EScaled (ECell (845%nat, 0%nat)) 70368744177664)) (EScaled (ECell (846%nat, 0%nat)) 140737488355328)) (EScaled (ECell (847%nat, 0%nat)) 281474976710656)) (EScaled (ECell (848%nat, 0%nat)) 562949953421312)) (EScaled (ECell (849%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (850%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (851%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (852%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (853%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (854%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (855%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (856%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (857%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (858%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (859%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (860%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (861%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (862%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (863%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (864%nat, 0%nat)) 36893488147419103232)) (ECell (20%nat, 0%nat))); + + (ESub (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EAdd (EConst 0) (EScaled (ECell (865%nat, 0%nat)) 1)) (EScaled (ECell (866%nat, 0%nat)) 2)) (EScaled (ECell (867%nat, 0%nat)) 4)) (EScaled (ECell (868%nat, 0%nat)) 8)) (EScaled (ECell (869%nat, 0%nat)) 16)) (EScaled (ECell (870%nat, 0%nat)) 32)) (EScaled (ECell (871%nat, 0%nat)) 64)) (EScaled (ECell (872%nat, 0%nat)) 128)) (EScaled (ECell (873%nat, 0%nat)) 256)) (EScaled (ECell (874%nat, 0%nat)) 512)) (EScaled (ECell (875%nat, 0%nat)) 1024)) (EScaled (ECell (876%nat, 0%nat)) 2048)) (EScaled (ECell (877%nat, 0%nat)) 4096)) (EScaled (ECell (878%nat, 0%nat)) 8192)) (EScaled (ECell (879%nat, 0%nat)) 16384)) (EScaled (ECell (880%nat, 0%nat)) 32768)) (EScaled (ECell (881%nat, 0%nat)) 65536)) (EScaled (ECell (882%nat, 0%nat)) 131072)) (EScaled (ECell (883%nat, 0%nat)) 262144)) (EScaled (ECell (884%nat, 0%nat)) 524288)) (EScaled (ECell (885%nat, 0%nat)) 1048576)) (EScaled (ECell (886%nat, 0%nat)) 2097152)) (EScaled (ECell (887%nat, 0%nat)) 4194304)) (EScaled (ECell (888%nat, 0%nat)) 8388608)) (EScaled (ECell (889%nat, 0%nat)) 16777216)) (EScaled (ECell (890%nat, 0%nat)) 33554432)) (EScaled (ECell (891%nat, 0%nat)) 67108864)) (EScaled (ECell (892%nat, 0%nat)) 134217728)) (EScaled (ECell (893%nat, 0%nat)) 268435456)) (EScaled (ECell (894%nat, 0%nat)) 536870912)) (EScaled (ECell (895%nat, 0%nat)) 1073741824)) (EScaled (ECell (896%nat, 0%nat)) 2147483648)) (EScaled (ECell (897%nat, 0%nat)) 4294967296)) (EScaled (ECell (898%nat, 0%nat)) 8589934592)) (EScaled (ECell (899%nat, 0%nat)) 17179869184)) (EScaled (ECell (900%nat, 0%nat)) 34359738368)) (EScaled (ECell (901%nat, 0%nat)) 68719476736)) (EScaled (ECell (902%nat, 0%nat)) 137438953472)) (EScaled (ECell (903%nat, 0%nat)) 274877906944)) (EScaled (ECell (904%nat, 0%nat)) 549755813888)) (EScaled (ECell (905%nat, 0%nat)) 1099511627776)) (EScaled (ECell (906%nat, 0%nat)) 2199023255552)) (EScaled (ECell (907%nat, 0%nat)) 4398046511104)) (EScaled (ECell (908%nat, 0%nat)) 8796093022208)) (EScaled (ECell (909%nat, 0%nat)) 17592186044416)) (EScaled (ECell (910%nat, 0%nat)) 35184372088832)) (EScaled (ECell (911%nat, 0%nat)) 70368744177664)) (EScaled (ECell (912%nat, 0%nat)) 140737488355328)) (EScaled (ECell (913%nat, 0%nat)) 281474976710656)) (EScaled (ECell (914%nat, 0%nat)) 562949953421312)) (EScaled (ECell (915%nat, 0%nat)) 1125899906842624)) (EScaled (ECell (916%nat, 0%nat)) 2251799813685248)) (EScaled (ECell (917%nat, 0%nat)) 4503599627370496)) (EScaled (ECell (918%nat, 0%nat)) 9007199254740992)) (EScaled (ECell (919%nat, 0%nat)) 18014398509481984)) (EScaled (ECell (920%nat, 0%nat)) 36028797018963968)) (EScaled (ECell (921%nat, 0%nat)) 72057594037927936)) (EScaled (ECell (922%nat, 0%nat)) 144115188075855872)) (EScaled (ECell (923%nat, 0%nat)) 288230376151711744)) (EScaled (ECell (924%nat, 0%nat)) 576460752303423488)) (EScaled (ECell (925%nat, 0%nat)) 1152921504606846976)) (EScaled (ECell (926%nat, 0%nat)) 2305843009213693952)) (EScaled (ECell (927%nat, 0%nat)) 4611686018427387904)) (EScaled (ECell (928%nat, 0%nat)) 9223372036854775808)) (EScaled (ECell (929%nat, 0%nat)) 18446744073709551616)) (EScaled (ECell (930%nat, 0%nat)) 36893488147419103232)) (ECell (21%nat, 0%nat))); + + (ESub (ESub (EMul (ECell (0%nat, 0%nat)) (ECell (4%nat, 0%nat))) (ECell (8%nat, 0%nat))) (EScaled (ECell (16%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EAdd (EMul (ECell (0%nat, 0%nat)) (ECell (5%nat, 0%nat))) (EMul (ECell (1%nat, 0%nat)) (ECell (4%nat, 0%nat)))) (ECell (9%nat, 0%nat))) (ECell (16%nat, 0%nat))) (EScaled (ECell (17%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EAdd (EAdd (EMul (ECell (0%nat, 0%nat)) (ECell (6%nat, 0%nat))) (EMul (ECell (1%nat, 0%nat)) (ECell (5%nat, 0%nat)))) (EMul (ECell (2%nat, 0%nat)) (ECell (4%nat, 0%nat)))) (ECell (10%nat, 0%nat))) (ECell (17%nat, 0%nat))) (EScaled (ECell (18%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EAdd (EAdd (EAdd (EMul (ECell (0%nat, 0%nat)) (ECell (7%nat, 0%nat))) (EMul (ECell (1%nat, 0%nat)) (ECell (6%nat, 0%nat)))) (EMul (ECell (2%nat, 0%nat)) (ECell (5%nat, 0%nat)))) (EMul (ECell (3%nat, 0%nat)) (ECell (4%nat, 0%nat)))) (ECell (11%nat, 0%nat))) (ECell (18%nat, 0%nat))) (EScaled (ECell (19%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EAdd (EAdd (EMul (ECell (1%nat, 0%nat)) (ECell (7%nat, 0%nat))) (EMul (ECell (2%nat, 0%nat)) (ECell (6%nat, 0%nat)))) (EMul (ECell (3%nat, 0%nat)) (ECell (5%nat, 0%nat)))) (ECell (12%nat, 0%nat))) (ECell (19%nat, 0%nat))) (EScaled (ECell (20%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EAdd (EMul (ECell (2%nat, 0%nat)) (ECell (7%nat, 0%nat))) (EMul (ECell (3%nat, 0%nat)) (ECell (6%nat, 0%nat)))) (ECell (13%nat, 0%nat))) (ECell (20%nat, 0%nat))) (EScaled (ECell (21%nat, 0%nat)) 18446744073709551616)); + + (ESub (EAdd (ESub (EMul (ECell (3%nat, 0%nat)) (ECell (7%nat, 0%nat))) (ECell (14%nat, 0%nat))) (ECell (21%nat, 0%nat))) (EScaled (ECell (22%nat, 0%nat)) 18446744073709551616)); + + (ESub (ECell (22%nat, 0%nat)) (ECell (15%nat, 0%nat))) + ]. + +Definition deployed_copy : list (Cell*Cell) := + [ + ((8%nat, 0%nat), (2000%nat, 0%nat)); + ((9%nat, 0%nat), (2000%nat, 1%nat)); + ((10%nat, 0%nat), (2000%nat, 2%nat)); + ((11%nat, 0%nat), (2000%nat, 3%nat)); + ((12%nat, 0%nat), (2000%nat, 4%nat)); + ((13%nat, 0%nat), (2000%nat, 5%nat)); + ((14%nat, 0%nat), (2000%nat, 6%nat)); + ((15%nat, 0%nat), (2000%nat, 7%nat)) + ]. + +Definition deployed_model : CircuitModel := + mk_model p deployed_gates deployed_copy. diff --git a/coq-legacy/constraints/gen/bm_necessity_gen.v b/coq-legacy/constraints/gen/bm_necessity_gen.v new file mode 100644 index 0000000..ff9d896 --- /dev/null +++ b/coq-legacy/constraints/gen/bm_necessity_gen.v @@ -0,0 +1,860 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Each copy constraint is necessary: the model with any one of the eight copy constraints removed no + longer refines the intended public interface (mutant_wcopy_1_not_refines and its seven siblings), shown + by an explicit filling. bm_all_wires_closed_gen collects these facts with the full model's refinement. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. +Require Import Generated.bm_model_gen. +Require Import Generated.bm_wires_gen. +Require Import Generated.bm_scaffold_gen. + +Fixpoint expr_eqb (x y:Expr) : bool := + match x, y with + | EConst a, EConst b => Z.eqb a b + | ECell a, ECell b => cell_eqb a b + | EAdd a1 a2, EAdd b1 b2 => andb (expr_eqb a1 b1) (expr_eqb a2 b2) + | ESub a1 a2, ESub b1 b2 => andb (expr_eqb a1 b1) (expr_eqb a2 b2) + | EMul a1 a2, EMul b1 b2 => andb (expr_eqb a1 b1) (expr_eqb a2 b2) + | ENeg a, ENeg b => expr_eqb a b + | EScaled a z1, EScaled b z2 => andb (expr_eqb a b) (Z.eqb z1 z2) + | _, _ => false + end. + +Definition cut_edge_bm (e:Cell*Cell) : list (Cell*Cell) := + filter (fun f => negb (cellpair_eqb f e)) deployed_copy. +Definition cut_copy_model_bm (e:Cell*Cell) : CircuitModel := + mk_model p deployed_gates (cut_edge_bm e). + +Definition no_gate_reads_bm (t:Cell) : Prop := forall g, In g deployed_gates -> reads_b t g = false. +Ltac noreads_tac := + let g := fresh "g" in let Hin := fresh "Hin" in + intros g Hin; cbn in Hin; + repeat (destruct Hin as [<-|Hin]; [vm_compute; reflexivity| ]); + contradiction. + +Definition wit_honest_bm : Assignment := fun c => + if cell_eqb c (0%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (1%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (2%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (3%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (4%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (5%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (6%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (7%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (8%nat, 0%nat) then 1 else + if cell_eqb c (12%nat, 0%nat) then 18446744073709551614 else + if cell_eqb c (13%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (14%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (15%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (16%nat, 0%nat) then 18446744073709551614 else + if cell_eqb c (17%nat, 0%nat) then 36893488147419103229 else + if cell_eqb c (18%nat, 0%nat) then 55340232221128654844 else + if cell_eqb c (19%nat, 0%nat) then 73786976294838206459 else + if cell_eqb c (20%nat, 0%nat) then 55340232221128654845 else + if cell_eqb c (21%nat, 0%nat) then 36893488147419103230 else + if cell_eqb c (22%nat, 0%nat) then 18446744073709551615 else + if cell_eqb c (23%nat, 0%nat) then 1 else + if cell_eqb c (280%nat, 0%nat) then 1 else + if cell_eqb c (281%nat, 0%nat) then 1 else + if cell_eqb c (282%nat, 0%nat) then 1 else + if cell_eqb c (283%nat, 0%nat) then 1 else + if cell_eqb c (284%nat, 0%nat) then 1 else + if cell_eqb c (285%nat, 0%nat) then 1 else + if cell_eqb c (286%nat, 0%nat) then 1 else + if cell_eqb c (287%nat, 0%nat) then 1 else + if cell_eqb c (288%nat, 0%nat) then 1 else + if cell_eqb c (289%nat, 0%nat) then 1 else + if cell_eqb c (290%nat, 0%nat) then 1 else + if cell_eqb c (291%nat, 0%nat) then 1 else + if cell_eqb c (292%nat, 0%nat) then 1 else + if cell_eqb c (293%nat, 0%nat) then 1 else + if cell_eqb c (294%nat, 0%nat) then 1 else + if cell_eqb c (295%nat, 0%nat) then 1 else + if cell_eqb c (296%nat, 0%nat) then 1 else + if cell_eqb c (297%nat, 0%nat) then 1 else + if cell_eqb c (298%nat, 0%nat) then 1 else + if cell_eqb c (299%nat, 0%nat) then 1 else + if cell_eqb c (300%nat, 0%nat) then 1 else + if cell_eqb c (301%nat, 0%nat) then 1 else + if cell_eqb c (302%nat, 0%nat) then 1 else + if cell_eqb c (303%nat, 0%nat) then 1 else + if cell_eqb c (304%nat, 0%nat) then 1 else + if cell_eqb c (305%nat, 0%nat) then 1 else + if cell_eqb c (306%nat, 0%nat) then 1 else + if cell_eqb c (307%nat, 0%nat) then 1 else + if cell_eqb c (308%nat, 0%nat) then 1 else + if cell_eqb c (309%nat, 0%nat) then 1 else + if cell_eqb c (310%nat, 0%nat) then 1 else + if cell_eqb c (311%nat, 0%nat) then 1 else + if cell_eqb c (312%nat, 0%nat) then 1 else + if cell_eqb c (313%nat, 0%nat) then 1 else + if cell_eqb c (314%nat, 0%nat) then 1 else + if cell_eqb c (315%nat, 0%nat) then 1 else + if cell_eqb c (316%nat, 0%nat) then 1 else + if cell_eqb c (317%nat, 0%nat) then 1 else + if cell_eqb c (318%nat, 0%nat) then 1 else + if cell_eqb c (319%nat, 0%nat) then 1 else + if cell_eqb c (320%nat, 0%nat) then 1 else + if cell_eqb c (321%nat, 0%nat) then 1 else + if cell_eqb c (322%nat, 0%nat) then 1 else + if cell_eqb c (323%nat, 0%nat) then 1 else + if cell_eqb c (324%nat, 0%nat) then 1 else + if cell_eqb c (325%nat, 0%nat) then 1 else + if cell_eqb c (326%nat, 0%nat) then 1 else + if cell_eqb c (327%nat, 0%nat) then 1 else + if cell_eqb c (328%nat, 0%nat) then 1 else + if cell_eqb c (329%nat, 0%nat) then 1 else + if cell_eqb c (330%nat, 0%nat) then 1 else + if cell_eqb c (331%nat, 0%nat) then 1 else + if cell_eqb c (332%nat, 0%nat) then 1 else + if cell_eqb c (333%nat, 0%nat) then 1 else + if cell_eqb c (334%nat, 0%nat) then 1 else + if cell_eqb c (335%nat, 0%nat) then 1 else + if cell_eqb c (336%nat, 0%nat) then 1 else + if cell_eqb c (337%nat, 0%nat) then 1 else + if cell_eqb c (338%nat, 0%nat) then 1 else + if cell_eqb c (339%nat, 0%nat) then 1 else + if cell_eqb c (340%nat, 0%nat) then 1 else + if cell_eqb c (341%nat, 0%nat) then 1 else + if cell_eqb c (342%nat, 0%nat) then 1 else + if cell_eqb c (343%nat, 0%nat) then 1 else + if cell_eqb c (344%nat, 0%nat) then 1 else + if cell_eqb c (345%nat, 0%nat) then 1 else + if cell_eqb c (346%nat, 0%nat) then 1 else + if cell_eqb c (347%nat, 0%nat) then 1 else + if cell_eqb c (348%nat, 0%nat) then 1 else + if cell_eqb c (349%nat, 0%nat) then 1 else + if cell_eqb c (350%nat, 0%nat) then 1 else + if cell_eqb c (351%nat, 0%nat) then 1 else + if cell_eqb c (352%nat, 0%nat) then 1 else + if cell_eqb c (353%nat, 0%nat) then 1 else + if cell_eqb c (354%nat, 0%nat) then 1 else + if cell_eqb c (355%nat, 0%nat) then 1 else + if cell_eqb c (356%nat, 0%nat) then 1 else + if cell_eqb c (357%nat, 0%nat) then 1 else + if cell_eqb c (358%nat, 0%nat) then 1 else + if cell_eqb c (359%nat, 0%nat) then 1 else + if cell_eqb c (360%nat, 0%nat) then 1 else + if cell_eqb c (361%nat, 0%nat) then 1 else + if cell_eqb c (362%nat, 0%nat) then 1 else + if cell_eqb c (363%nat, 0%nat) then 1 else + if cell_eqb c (364%nat, 0%nat) then 1 else + if cell_eqb c (365%nat, 0%nat) then 1 else + if cell_eqb c (366%nat, 0%nat) then 1 else + if cell_eqb c (367%nat, 0%nat) then 1 else + if cell_eqb c (368%nat, 0%nat) then 1 else + if cell_eqb c (369%nat, 0%nat) then 1 else + if cell_eqb c (370%nat, 0%nat) then 1 else + if cell_eqb c (371%nat, 0%nat) then 1 else + if cell_eqb c (372%nat, 0%nat) then 1 else + if cell_eqb c (373%nat, 0%nat) then 1 else + if cell_eqb c (374%nat, 0%nat) then 1 else + if cell_eqb c (375%nat, 0%nat) then 1 else + if cell_eqb c (376%nat, 0%nat) then 1 else + if cell_eqb c (377%nat, 0%nat) then 1 else + if cell_eqb c (378%nat, 0%nat) then 1 else + if cell_eqb c (379%nat, 0%nat) then 1 else + if cell_eqb c (380%nat, 0%nat) then 1 else + if cell_eqb c (381%nat, 0%nat) then 1 else + if cell_eqb c (382%nat, 0%nat) then 1 else + if cell_eqb c (383%nat, 0%nat) then 1 else + if cell_eqb c (384%nat, 0%nat) then 1 else + if cell_eqb c (385%nat, 0%nat) then 1 else + if cell_eqb c (386%nat, 0%nat) then 1 else + if cell_eqb c (387%nat, 0%nat) then 1 else + if cell_eqb c (388%nat, 0%nat) then 1 else + if cell_eqb c (389%nat, 0%nat) then 1 else + if cell_eqb c (390%nat, 0%nat) then 1 else + if cell_eqb c (391%nat, 0%nat) then 1 else + if cell_eqb c (392%nat, 0%nat) then 1 else + if cell_eqb c (393%nat, 0%nat) then 1 else + if cell_eqb c (394%nat, 0%nat) then 1 else + if cell_eqb c (395%nat, 0%nat) then 1 else + if cell_eqb c (396%nat, 0%nat) then 1 else + if cell_eqb c (397%nat, 0%nat) then 1 else + if cell_eqb c (398%nat, 0%nat) then 1 else + if cell_eqb c (399%nat, 0%nat) then 1 else + if cell_eqb c (400%nat, 0%nat) then 1 else + if cell_eqb c (401%nat, 0%nat) then 1 else + if cell_eqb c (402%nat, 0%nat) then 1 else + if cell_eqb c (403%nat, 0%nat) then 1 else + if cell_eqb c (404%nat, 0%nat) then 1 else + if cell_eqb c (405%nat, 0%nat) then 1 else + if cell_eqb c (406%nat, 0%nat) then 1 else + if cell_eqb c (407%nat, 0%nat) then 1 else + if cell_eqb c (408%nat, 0%nat) then 1 else + if cell_eqb c (409%nat, 0%nat) then 1 else + if cell_eqb c (410%nat, 0%nat) then 1 else + if cell_eqb c (411%nat, 0%nat) then 1 else + if cell_eqb c (412%nat, 0%nat) then 1 else + if cell_eqb c (413%nat, 0%nat) then 1 else + if cell_eqb c (414%nat, 0%nat) then 1 else + if cell_eqb c (415%nat, 0%nat) then 1 else + if cell_eqb c (416%nat, 0%nat) then 1 else + if cell_eqb c (417%nat, 0%nat) then 1 else + if cell_eqb c (418%nat, 0%nat) then 1 else + if cell_eqb c (419%nat, 0%nat) then 1 else + if cell_eqb c (420%nat, 0%nat) then 1 else + if cell_eqb c (421%nat, 0%nat) then 1 else + if cell_eqb c (422%nat, 0%nat) then 1 else + if cell_eqb c (423%nat, 0%nat) then 1 else + if cell_eqb c (424%nat, 0%nat) then 1 else + if cell_eqb c (425%nat, 0%nat) then 1 else + if cell_eqb c (426%nat, 0%nat) then 1 else + if cell_eqb c (427%nat, 0%nat) then 1 else + if cell_eqb c (428%nat, 0%nat) then 1 else + if cell_eqb c (429%nat, 0%nat) then 1 else + if cell_eqb c (430%nat, 0%nat) then 1 else + if cell_eqb c (431%nat, 0%nat) then 1 else + if cell_eqb c (432%nat, 0%nat) then 1 else + if cell_eqb c (433%nat, 0%nat) then 1 else + if cell_eqb c (434%nat, 0%nat) then 1 else + if cell_eqb c (435%nat, 0%nat) then 1 else + if cell_eqb c (436%nat, 0%nat) then 1 else + if cell_eqb c (437%nat, 0%nat) then 1 else + if cell_eqb c (438%nat, 0%nat) then 1 else + if cell_eqb c (439%nat, 0%nat) then 1 else + if cell_eqb c (440%nat, 0%nat) then 1 else + if cell_eqb c (441%nat, 0%nat) then 1 else + if cell_eqb c (442%nat, 0%nat) then 1 else + if cell_eqb c (443%nat, 0%nat) then 1 else + if cell_eqb c (444%nat, 0%nat) then 1 else + if cell_eqb c (445%nat, 0%nat) then 1 else + if cell_eqb c (446%nat, 0%nat) then 1 else + if cell_eqb c (447%nat, 0%nat) then 1 else + if cell_eqb c (448%nat, 0%nat) then 1 else + if cell_eqb c (449%nat, 0%nat) then 1 else + if cell_eqb c (450%nat, 0%nat) then 1 else + if cell_eqb c (451%nat, 0%nat) then 1 else + if cell_eqb c (452%nat, 0%nat) then 1 else + if cell_eqb c (453%nat, 0%nat) then 1 else + if cell_eqb c (454%nat, 0%nat) then 1 else + if cell_eqb c (455%nat, 0%nat) then 1 else + if cell_eqb c (456%nat, 0%nat) then 1 else + if cell_eqb c (457%nat, 0%nat) then 1 else + if cell_eqb c (458%nat, 0%nat) then 1 else + if cell_eqb c (459%nat, 0%nat) then 1 else + if cell_eqb c (460%nat, 0%nat) then 1 else + if cell_eqb c (461%nat, 0%nat) then 1 else + if cell_eqb c (462%nat, 0%nat) then 1 else + if cell_eqb c (463%nat, 0%nat) then 1 else + if cell_eqb c (464%nat, 0%nat) then 1 else + if cell_eqb c (465%nat, 0%nat) then 1 else + if cell_eqb c (466%nat, 0%nat) then 1 else + if cell_eqb c (467%nat, 0%nat) then 1 else + if cell_eqb c (468%nat, 0%nat) then 1 else + if cell_eqb c (469%nat, 0%nat) then 1 else + if cell_eqb c (470%nat, 0%nat) then 1 else + if cell_eqb c (471%nat, 0%nat) then 1 else + if cell_eqb c (472%nat, 0%nat) then 1 else + if cell_eqb c (473%nat, 0%nat) then 1 else + if cell_eqb c (474%nat, 0%nat) then 1 else + if cell_eqb c (475%nat, 0%nat) then 1 else + if cell_eqb c (476%nat, 0%nat) then 1 else + if cell_eqb c (477%nat, 0%nat) then 1 else + if cell_eqb c (478%nat, 0%nat) then 1 else + if cell_eqb c (479%nat, 0%nat) then 1 else + if cell_eqb c (480%nat, 0%nat) then 1 else + if cell_eqb c (481%nat, 0%nat) then 1 else + if cell_eqb c (482%nat, 0%nat) then 1 else + if cell_eqb c (483%nat, 0%nat) then 1 else + if cell_eqb c (484%nat, 0%nat) then 1 else + if cell_eqb c (485%nat, 0%nat) then 1 else + if cell_eqb c (486%nat, 0%nat) then 1 else + if cell_eqb c (487%nat, 0%nat) then 1 else + if cell_eqb c (488%nat, 0%nat) then 1 else + if cell_eqb c (489%nat, 0%nat) then 1 else + if cell_eqb c (490%nat, 0%nat) then 1 else + if cell_eqb c (491%nat, 0%nat) then 1 else + if cell_eqb c (492%nat, 0%nat) then 1 else + if cell_eqb c (493%nat, 0%nat) then 1 else + if cell_eqb c (494%nat, 0%nat) then 1 else + if cell_eqb c (495%nat, 0%nat) then 1 else + if cell_eqb c (496%nat, 0%nat) then 1 else + if cell_eqb c (497%nat, 0%nat) then 1 else + if cell_eqb c (498%nat, 0%nat) then 1 else + if cell_eqb c (499%nat, 0%nat) then 1 else + if cell_eqb c (500%nat, 0%nat) then 1 else + if cell_eqb c (501%nat, 0%nat) then 1 else + if cell_eqb c (502%nat, 0%nat) then 1 else + if cell_eqb c (503%nat, 0%nat) then 1 else + if cell_eqb c (504%nat, 0%nat) then 1 else + if cell_eqb c (505%nat, 0%nat) then 1 else + if cell_eqb c (506%nat, 0%nat) then 1 else + if cell_eqb c (507%nat, 0%nat) then 1 else + if cell_eqb c (508%nat, 0%nat) then 1 else + if cell_eqb c (509%nat, 0%nat) then 1 else + if cell_eqb c (510%nat, 0%nat) then 1 else + if cell_eqb c (511%nat, 0%nat) then 1 else + if cell_eqb c (512%nat, 0%nat) then 1 else + if cell_eqb c (513%nat, 0%nat) then 1 else + if cell_eqb c (514%nat, 0%nat) then 1 else + if cell_eqb c (515%nat, 0%nat) then 1 else + if cell_eqb c (516%nat, 0%nat) then 1 else + if cell_eqb c (517%nat, 0%nat) then 1 else + if cell_eqb c (518%nat, 0%nat) then 1 else + if cell_eqb c (519%nat, 0%nat) then 1 else + if cell_eqb c (520%nat, 0%nat) then 1 else + if cell_eqb c (521%nat, 0%nat) then 1 else + if cell_eqb c (522%nat, 0%nat) then 1 else + if cell_eqb c (523%nat, 0%nat) then 1 else + if cell_eqb c (524%nat, 0%nat) then 1 else + if cell_eqb c (525%nat, 0%nat) then 1 else + if cell_eqb c (526%nat, 0%nat) then 1 else + if cell_eqb c (527%nat, 0%nat) then 1 else + if cell_eqb c (528%nat, 0%nat) then 1 else + if cell_eqb c (529%nat, 0%nat) then 1 else + if cell_eqb c (530%nat, 0%nat) then 1 else + if cell_eqb c (531%nat, 0%nat) then 1 else + if cell_eqb c (532%nat, 0%nat) then 1 else + if cell_eqb c (533%nat, 0%nat) then 1 else + if cell_eqb c (534%nat, 0%nat) then 1 else + if cell_eqb c (536%nat, 0%nat) then 1 else + if cell_eqb c (537%nat, 0%nat) then 1 else + if cell_eqb c (538%nat, 0%nat) then 1 else + if cell_eqb c (539%nat, 0%nat) then 1 else + if cell_eqb c (540%nat, 0%nat) then 1 else + if cell_eqb c (541%nat, 0%nat) then 1 else + if cell_eqb c (542%nat, 0%nat) then 1 else + if cell_eqb c (543%nat, 0%nat) then 1 else + if cell_eqb c (544%nat, 0%nat) then 1 else + if cell_eqb c (545%nat, 0%nat) then 1 else + if cell_eqb c (546%nat, 0%nat) then 1 else + if cell_eqb c (547%nat, 0%nat) then 1 else + if cell_eqb c (548%nat, 0%nat) then 1 else + if cell_eqb c (549%nat, 0%nat) then 1 else + if cell_eqb c (550%nat, 0%nat) then 1 else + if cell_eqb c (551%nat, 0%nat) then 1 else + if cell_eqb c (552%nat, 0%nat) then 1 else + if cell_eqb c (553%nat, 0%nat) then 1 else + if cell_eqb c (554%nat, 0%nat) then 1 else + if cell_eqb c (555%nat, 0%nat) then 1 else + if cell_eqb c (556%nat, 0%nat) then 1 else + if cell_eqb c (557%nat, 0%nat) then 1 else + if cell_eqb c (558%nat, 0%nat) then 1 else + if cell_eqb c (559%nat, 0%nat) then 1 else + if cell_eqb c (560%nat, 0%nat) then 1 else + if cell_eqb c (561%nat, 0%nat) then 1 else + if cell_eqb c (562%nat, 0%nat) then 1 else + if cell_eqb c (563%nat, 0%nat) then 1 else + if cell_eqb c (564%nat, 0%nat) then 1 else + if cell_eqb c (565%nat, 0%nat) then 1 else + if cell_eqb c (566%nat, 0%nat) then 1 else + if cell_eqb c (567%nat, 0%nat) then 1 else + if cell_eqb c (568%nat, 0%nat) then 1 else + if cell_eqb c (569%nat, 0%nat) then 1 else + if cell_eqb c (570%nat, 0%nat) then 1 else + if cell_eqb c (571%nat, 0%nat) then 1 else + if cell_eqb c (572%nat, 0%nat) then 1 else + if cell_eqb c (573%nat, 0%nat) then 1 else + if cell_eqb c (574%nat, 0%nat) then 1 else + if cell_eqb c (575%nat, 0%nat) then 1 else + if cell_eqb c (576%nat, 0%nat) then 1 else + if cell_eqb c (577%nat, 0%nat) then 1 else + if cell_eqb c (578%nat, 0%nat) then 1 else + if cell_eqb c (579%nat, 0%nat) then 1 else + if cell_eqb c (580%nat, 0%nat) then 1 else + if cell_eqb c (581%nat, 0%nat) then 1 else + if cell_eqb c (582%nat, 0%nat) then 1 else + if cell_eqb c (583%nat, 0%nat) then 1 else + if cell_eqb c (584%nat, 0%nat) then 1 else + if cell_eqb c (585%nat, 0%nat) then 1 else + if cell_eqb c (586%nat, 0%nat) then 1 else + if cell_eqb c (587%nat, 0%nat) then 1 else + if cell_eqb c (588%nat, 0%nat) then 1 else + if cell_eqb c (589%nat, 0%nat) then 1 else + if cell_eqb c (590%nat, 0%nat) then 1 else + if cell_eqb c (591%nat, 0%nat) then 1 else + if cell_eqb c (592%nat, 0%nat) then 1 else + if cell_eqb c (593%nat, 0%nat) then 1 else + if cell_eqb c (594%nat, 0%nat) then 1 else + if cell_eqb c (595%nat, 0%nat) then 1 else + if cell_eqb c (596%nat, 0%nat) then 1 else + if cell_eqb c (597%nat, 0%nat) then 1 else + if cell_eqb c (598%nat, 0%nat) then 1 else + if cell_eqb c (601%nat, 0%nat) then 1 else + if cell_eqb c (603%nat, 0%nat) then 1 else + if cell_eqb c (604%nat, 0%nat) then 1 else + if cell_eqb c (605%nat, 0%nat) then 1 else + if cell_eqb c (606%nat, 0%nat) then 1 else + if cell_eqb c (607%nat, 0%nat) then 1 else + if cell_eqb c (608%nat, 0%nat) then 1 else + if cell_eqb c (609%nat, 0%nat) then 1 else + if cell_eqb c (610%nat, 0%nat) then 1 else + if cell_eqb c (611%nat, 0%nat) then 1 else + if cell_eqb c (612%nat, 0%nat) then 1 else + if cell_eqb c (613%nat, 0%nat) then 1 else + if cell_eqb c (614%nat, 0%nat) then 1 else + if cell_eqb c (615%nat, 0%nat) then 1 else + if cell_eqb c (616%nat, 0%nat) then 1 else + if cell_eqb c (617%nat, 0%nat) then 1 else + if cell_eqb c (618%nat, 0%nat) then 1 else + if cell_eqb c (619%nat, 0%nat) then 1 else + if cell_eqb c (620%nat, 0%nat) then 1 else + if cell_eqb c (621%nat, 0%nat) then 1 else + if cell_eqb c (622%nat, 0%nat) then 1 else + if cell_eqb c (623%nat, 0%nat) then 1 else + if cell_eqb c (624%nat, 0%nat) then 1 else + if cell_eqb c (625%nat, 0%nat) then 1 else + if cell_eqb c (626%nat, 0%nat) then 1 else + if cell_eqb c (627%nat, 0%nat) then 1 else + if cell_eqb c (628%nat, 0%nat) then 1 else + if cell_eqb c (629%nat, 0%nat) then 1 else + if cell_eqb c (630%nat, 0%nat) then 1 else + if cell_eqb c (631%nat, 0%nat) then 1 else + if cell_eqb c (632%nat, 0%nat) then 1 else + if cell_eqb c (633%nat, 0%nat) then 1 else + if cell_eqb c (634%nat, 0%nat) then 1 else + if cell_eqb c (635%nat, 0%nat) then 1 else + if cell_eqb c (636%nat, 0%nat) then 1 else + if cell_eqb c (637%nat, 0%nat) then 1 else + if cell_eqb c (638%nat, 0%nat) then 1 else + if cell_eqb c (639%nat, 0%nat) then 1 else + if cell_eqb c (640%nat, 0%nat) then 1 else + if cell_eqb c (641%nat, 0%nat) then 1 else + if cell_eqb c (642%nat, 0%nat) then 1 else + if cell_eqb c (643%nat, 0%nat) then 1 else + if cell_eqb c (644%nat, 0%nat) then 1 else + if cell_eqb c (645%nat, 0%nat) then 1 else + if cell_eqb c (646%nat, 0%nat) then 1 else + if cell_eqb c (647%nat, 0%nat) then 1 else + if cell_eqb c (648%nat, 0%nat) then 1 else + if cell_eqb c (649%nat, 0%nat) then 1 else + if cell_eqb c (650%nat, 0%nat) then 1 else + if cell_eqb c (651%nat, 0%nat) then 1 else + if cell_eqb c (652%nat, 0%nat) then 1 else + if cell_eqb c (653%nat, 0%nat) then 1 else + if cell_eqb c (654%nat, 0%nat) then 1 else + if cell_eqb c (655%nat, 0%nat) then 1 else + if cell_eqb c (656%nat, 0%nat) then 1 else + if cell_eqb c (657%nat, 0%nat) then 1 else + if cell_eqb c (658%nat, 0%nat) then 1 else + if cell_eqb c (659%nat, 0%nat) then 1 else + if cell_eqb c (660%nat, 0%nat) then 1 else + if cell_eqb c (661%nat, 0%nat) then 1 else + if cell_eqb c (662%nat, 0%nat) then 1 else + if cell_eqb c (663%nat, 0%nat) then 1 else + if cell_eqb c (664%nat, 0%nat) then 1 else + if cell_eqb c (665%nat, 0%nat) then 1 else + if cell_eqb c (669%nat, 0%nat) then 1 else + if cell_eqb c (670%nat, 0%nat) then 1 else + if cell_eqb c (671%nat, 0%nat) then 1 else + if cell_eqb c (672%nat, 0%nat) then 1 else + if cell_eqb c (673%nat, 0%nat) then 1 else + if cell_eqb c (674%nat, 0%nat) then 1 else + if cell_eqb c (675%nat, 0%nat) then 1 else + if cell_eqb c (676%nat, 0%nat) then 1 else + if cell_eqb c (677%nat, 0%nat) then 1 else + if cell_eqb c (678%nat, 0%nat) then 1 else + if cell_eqb c (679%nat, 0%nat) then 1 else + if cell_eqb c (680%nat, 0%nat) then 1 else + if cell_eqb c (681%nat, 0%nat) then 1 else + if cell_eqb c (682%nat, 0%nat) then 1 else + if cell_eqb c (683%nat, 0%nat) then 1 else + if cell_eqb c (684%nat, 0%nat) then 1 else + if cell_eqb c (685%nat, 0%nat) then 1 else + if cell_eqb c (686%nat, 0%nat) then 1 else + if cell_eqb c (687%nat, 0%nat) then 1 else + if cell_eqb c (688%nat, 0%nat) then 1 else + if cell_eqb c (689%nat, 0%nat) then 1 else + if cell_eqb c (690%nat, 0%nat) then 1 else + if cell_eqb c (691%nat, 0%nat) then 1 else + if cell_eqb c (692%nat, 0%nat) then 1 else + if cell_eqb c (693%nat, 0%nat) then 1 else + if cell_eqb c (694%nat, 0%nat) then 1 else + if cell_eqb c (695%nat, 0%nat) then 1 else + if cell_eqb c (696%nat, 0%nat) then 1 else + if cell_eqb c (697%nat, 0%nat) then 1 else + if cell_eqb c (698%nat, 0%nat) then 1 else + if cell_eqb c (699%nat, 0%nat) then 1 else + if cell_eqb c (700%nat, 0%nat) then 1 else + if cell_eqb c (701%nat, 0%nat) then 1 else + if cell_eqb c (702%nat, 0%nat) then 1 else + if cell_eqb c (703%nat, 0%nat) then 1 else + if cell_eqb c (704%nat, 0%nat) then 1 else + if cell_eqb c (705%nat, 0%nat) then 1 else + if cell_eqb c (706%nat, 0%nat) then 1 else + if cell_eqb c (707%nat, 0%nat) then 1 else + if cell_eqb c (708%nat, 0%nat) then 1 else + if cell_eqb c (709%nat, 0%nat) then 1 else + if cell_eqb c (710%nat, 0%nat) then 1 else + if cell_eqb c (711%nat, 0%nat) then 1 else + if cell_eqb c (712%nat, 0%nat) then 1 else + if cell_eqb c (713%nat, 0%nat) then 1 else + if cell_eqb c (714%nat, 0%nat) then 1 else + if cell_eqb c (715%nat, 0%nat) then 1 else + if cell_eqb c (716%nat, 0%nat) then 1 else + if cell_eqb c (717%nat, 0%nat) then 1 else + if cell_eqb c (718%nat, 0%nat) then 1 else + if cell_eqb c (719%nat, 0%nat) then 1 else + if cell_eqb c (720%nat, 0%nat) then 1 else + if cell_eqb c (721%nat, 0%nat) then 1 else + if cell_eqb c (722%nat, 0%nat) then 1 else + if cell_eqb c (723%nat, 0%nat) then 1 else + if cell_eqb c (724%nat, 0%nat) then 1 else + if cell_eqb c (725%nat, 0%nat) then 1 else + if cell_eqb c (726%nat, 0%nat) then 1 else + if cell_eqb c (727%nat, 0%nat) then 1 else + if cell_eqb c (728%nat, 0%nat) then 1 else + if cell_eqb c (729%nat, 0%nat) then 1 else + if cell_eqb c (730%nat, 0%nat) then 1 else + if cell_eqb c (732%nat, 0%nat) then 1 else + if cell_eqb c (733%nat, 0%nat) then 1 else + if cell_eqb c (734%nat, 0%nat) then 1 else + if cell_eqb c (736%nat, 0%nat) then 1 else + if cell_eqb c (737%nat, 0%nat) then 1 else + if cell_eqb c (738%nat, 0%nat) then 1 else + if cell_eqb c (739%nat, 0%nat) then 1 else + if cell_eqb c (740%nat, 0%nat) then 1 else + if cell_eqb c (741%nat, 0%nat) then 1 else + if cell_eqb c (742%nat, 0%nat) then 1 else + if cell_eqb c (743%nat, 0%nat) then 1 else + if cell_eqb c (744%nat, 0%nat) then 1 else + if cell_eqb c (745%nat, 0%nat) then 1 else + if cell_eqb c (746%nat, 0%nat) then 1 else + if cell_eqb c (747%nat, 0%nat) then 1 else + if cell_eqb c (748%nat, 0%nat) then 1 else + if cell_eqb c (749%nat, 0%nat) then 1 else + if cell_eqb c (750%nat, 0%nat) then 1 else + if cell_eqb c (751%nat, 0%nat) then 1 else + if cell_eqb c (752%nat, 0%nat) then 1 else + if cell_eqb c (753%nat, 0%nat) then 1 else + if cell_eqb c (754%nat, 0%nat) then 1 else + if cell_eqb c (755%nat, 0%nat) then 1 else + if cell_eqb c (756%nat, 0%nat) then 1 else + if cell_eqb c (757%nat, 0%nat) then 1 else + if cell_eqb c (758%nat, 0%nat) then 1 else + if cell_eqb c (759%nat, 0%nat) then 1 else + if cell_eqb c (760%nat, 0%nat) then 1 else + if cell_eqb c (761%nat, 0%nat) then 1 else + if cell_eqb c (762%nat, 0%nat) then 1 else + if cell_eqb c (763%nat, 0%nat) then 1 else + if cell_eqb c (764%nat, 0%nat) then 1 else + if cell_eqb c (765%nat, 0%nat) then 1 else + if cell_eqb c (766%nat, 0%nat) then 1 else + if cell_eqb c (767%nat, 0%nat) then 1 else + if cell_eqb c (768%nat, 0%nat) then 1 else + if cell_eqb c (769%nat, 0%nat) then 1 else + if cell_eqb c (770%nat, 0%nat) then 1 else + if cell_eqb c (771%nat, 0%nat) then 1 else + if cell_eqb c (772%nat, 0%nat) then 1 else + if cell_eqb c (773%nat, 0%nat) then 1 else + if cell_eqb c (774%nat, 0%nat) then 1 else + if cell_eqb c (775%nat, 0%nat) then 1 else + if cell_eqb c (776%nat, 0%nat) then 1 else + if cell_eqb c (777%nat, 0%nat) then 1 else + if cell_eqb c (778%nat, 0%nat) then 1 else + if cell_eqb c (779%nat, 0%nat) then 1 else + if cell_eqb c (780%nat, 0%nat) then 1 else + if cell_eqb c (781%nat, 0%nat) then 1 else + if cell_eqb c (782%nat, 0%nat) then 1 else + if cell_eqb c (783%nat, 0%nat) then 1 else + if cell_eqb c (784%nat, 0%nat) then 1 else + if cell_eqb c (785%nat, 0%nat) then 1 else + if cell_eqb c (786%nat, 0%nat) then 1 else + if cell_eqb c (787%nat, 0%nat) then 1 else + if cell_eqb c (788%nat, 0%nat) then 1 else + if cell_eqb c (789%nat, 0%nat) then 1 else + if cell_eqb c (790%nat, 0%nat) then 1 else + if cell_eqb c (791%nat, 0%nat) then 1 else + if cell_eqb c (792%nat, 0%nat) then 1 else + if cell_eqb c (793%nat, 0%nat) then 1 else + if cell_eqb c (794%nat, 0%nat) then 1 else + if cell_eqb c (795%nat, 0%nat) then 1 else + if cell_eqb c (796%nat, 0%nat) then 1 else + if cell_eqb c (797%nat, 0%nat) then 1 else + if cell_eqb c (798%nat, 0%nat) then 1 else + if cell_eqb c (799%nat, 0%nat) then 1 else + if cell_eqb c (801%nat, 0%nat) then 1 else + if cell_eqb c (802%nat, 0%nat) then 1 else + if cell_eqb c (803%nat, 0%nat) then 1 else + if cell_eqb c (804%nat, 0%nat) then 1 else + if cell_eqb c (805%nat, 0%nat) then 1 else + if cell_eqb c (806%nat, 0%nat) then 1 else + if cell_eqb c (807%nat, 0%nat) then 1 else + if cell_eqb c (808%nat, 0%nat) then 1 else + if cell_eqb c (809%nat, 0%nat) then 1 else + if cell_eqb c (810%nat, 0%nat) then 1 else + if cell_eqb c (811%nat, 0%nat) then 1 else + if cell_eqb c (812%nat, 0%nat) then 1 else + if cell_eqb c (813%nat, 0%nat) then 1 else + if cell_eqb c (814%nat, 0%nat) then 1 else + if cell_eqb c (815%nat, 0%nat) then 1 else + if cell_eqb c (816%nat, 0%nat) then 1 else + if cell_eqb c (817%nat, 0%nat) then 1 else + if cell_eqb c (818%nat, 0%nat) then 1 else + if cell_eqb c (819%nat, 0%nat) then 1 else + if cell_eqb c (820%nat, 0%nat) then 1 else + if cell_eqb c (821%nat, 0%nat) then 1 else + if cell_eqb c (822%nat, 0%nat) then 1 else + if cell_eqb c (823%nat, 0%nat) then 1 else + if cell_eqb c (824%nat, 0%nat) then 1 else + if cell_eqb c (825%nat, 0%nat) then 1 else + if cell_eqb c (826%nat, 0%nat) then 1 else + if cell_eqb c (827%nat, 0%nat) then 1 else + if cell_eqb c (828%nat, 0%nat) then 1 else + if cell_eqb c (829%nat, 0%nat) then 1 else + if cell_eqb c (830%nat, 0%nat) then 1 else + if cell_eqb c (831%nat, 0%nat) then 1 else + if cell_eqb c (832%nat, 0%nat) then 1 else + if cell_eqb c (833%nat, 0%nat) then 1 else + if cell_eqb c (834%nat, 0%nat) then 1 else + if cell_eqb c (835%nat, 0%nat) then 1 else + if cell_eqb c (836%nat, 0%nat) then 1 else + if cell_eqb c (837%nat, 0%nat) then 1 else + if cell_eqb c (838%nat, 0%nat) then 1 else + if cell_eqb c (839%nat, 0%nat) then 1 else + if cell_eqb c (840%nat, 0%nat) then 1 else + if cell_eqb c (841%nat, 0%nat) then 1 else + if cell_eqb c (842%nat, 0%nat) then 1 else + if cell_eqb c (843%nat, 0%nat) then 1 else + if cell_eqb c (844%nat, 0%nat) then 1 else + if cell_eqb c (845%nat, 0%nat) then 1 else + if cell_eqb c (846%nat, 0%nat) then 1 else + if cell_eqb c (847%nat, 0%nat) then 1 else + if cell_eqb c (848%nat, 0%nat) then 1 else + if cell_eqb c (849%nat, 0%nat) then 1 else + if cell_eqb c (850%nat, 0%nat) then 1 else + if cell_eqb c (851%nat, 0%nat) then 1 else + if cell_eqb c (852%nat, 0%nat) then 1 else + if cell_eqb c (853%nat, 0%nat) then 1 else + if cell_eqb c (854%nat, 0%nat) then 1 else + if cell_eqb c (855%nat, 0%nat) then 1 else + if cell_eqb c (856%nat, 0%nat) then 1 else + if cell_eqb c (857%nat, 0%nat) then 1 else + if cell_eqb c (858%nat, 0%nat) then 1 else + if cell_eqb c (859%nat, 0%nat) then 1 else + if cell_eqb c (860%nat, 0%nat) then 1 else + if cell_eqb c (861%nat, 0%nat) then 1 else + if cell_eqb c (862%nat, 0%nat) then 1 else + if cell_eqb c (864%nat, 0%nat) then 1 else + if cell_eqb c (866%nat, 0%nat) then 1 else + if cell_eqb c (867%nat, 0%nat) then 1 else + if cell_eqb c (868%nat, 0%nat) then 1 else + if cell_eqb c (869%nat, 0%nat) then 1 else + if cell_eqb c (870%nat, 0%nat) then 1 else + if cell_eqb c (871%nat, 0%nat) then 1 else + if cell_eqb c (872%nat, 0%nat) then 1 else + if cell_eqb c (873%nat, 0%nat) then 1 else + if cell_eqb c (874%nat, 0%nat) then 1 else + if cell_eqb c (875%nat, 0%nat) then 1 else + if cell_eqb c (876%nat, 0%nat) then 1 else + if cell_eqb c (877%nat, 0%nat) then 1 else + if cell_eqb c (878%nat, 0%nat) then 1 else + if cell_eqb c (879%nat, 0%nat) then 1 else + if cell_eqb c (880%nat, 0%nat) then 1 else + if cell_eqb c (881%nat, 0%nat) then 1 else + if cell_eqb c (882%nat, 0%nat) then 1 else + if cell_eqb c (883%nat, 0%nat) then 1 else + if cell_eqb c (884%nat, 0%nat) then 1 else + if cell_eqb c (885%nat, 0%nat) then 1 else + if cell_eqb c (886%nat, 0%nat) then 1 else + if cell_eqb c (887%nat, 0%nat) then 1 else + if cell_eqb c (888%nat, 0%nat) then 1 else + if cell_eqb c (889%nat, 0%nat) then 1 else + if cell_eqb c (890%nat, 0%nat) then 1 else + if cell_eqb c (891%nat, 0%nat) then 1 else + if cell_eqb c (892%nat, 0%nat) then 1 else + if cell_eqb c (893%nat, 0%nat) then 1 else + if cell_eqb c (894%nat, 0%nat) then 1 else + if cell_eqb c (895%nat, 0%nat) then 1 else + if cell_eqb c (896%nat, 0%nat) then 1 else + if cell_eqb c (897%nat, 0%nat) then 1 else + if cell_eqb c (898%nat, 0%nat) then 1 else + if cell_eqb c (899%nat, 0%nat) then 1 else + if cell_eqb c (900%nat, 0%nat) then 1 else + if cell_eqb c (901%nat, 0%nat) then 1 else + if cell_eqb c (902%nat, 0%nat) then 1 else + if cell_eqb c (903%nat, 0%nat) then 1 else + if cell_eqb c (904%nat, 0%nat) then 1 else + if cell_eqb c (905%nat, 0%nat) then 1 else + if cell_eqb c (906%nat, 0%nat) then 1 else + if cell_eqb c (907%nat, 0%nat) then 1 else + if cell_eqb c (908%nat, 0%nat) then 1 else + if cell_eqb c (909%nat, 0%nat) then 1 else + if cell_eqb c (910%nat, 0%nat) then 1 else + if cell_eqb c (911%nat, 0%nat) then 1 else + if cell_eqb c (912%nat, 0%nat) then 1 else + if cell_eqb c (913%nat, 0%nat) then 1 else + if cell_eqb c (914%nat, 0%nat) then 1 else + if cell_eqb c (915%nat, 0%nat) then 1 else + if cell_eqb c (916%nat, 0%nat) then 1 else + if cell_eqb c (917%nat, 0%nat) then 1 else + if cell_eqb c (918%nat, 0%nat) then 1 else + if cell_eqb c (919%nat, 0%nat) then 1 else + if cell_eqb c (920%nat, 0%nat) then 1 else + if cell_eqb c (921%nat, 0%nat) then 1 else + if cell_eqb c (922%nat, 0%nat) then 1 else + if cell_eqb c (923%nat, 0%nat) then 1 else + if cell_eqb c (924%nat, 0%nat) then 1 else + if cell_eqb c (925%nat, 0%nat) then 1 else + if cell_eqb c (926%nat, 0%nat) then 1 else + if cell_eqb c (927%nat, 0%nat) then 1 else + if cell_eqb c (928%nat, 0%nat) then 1 else + if cell_eqb c (929%nat, 0%nat) then 1 else + if cell_eqb c (2000%nat, 0%nat) then 1 else + if cell_eqb c (2000%nat, 4%nat) then 18446744073709551614 else + if cell_eqb c (2000%nat, 5%nat) then 18446744073709551615 else + if cell_eqb c (2000%nat, 6%nat) then 18446744073709551615 else + if cell_eqb c (2000%nat, 7%nat) then 18446744073709551615 else + 0. + +Lemma honest_full_sat_bm : sat deployed_model wit_honest_bm. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. + +Definition mutant_wcopy_1_model : CircuitModel := cut_copy_model_bm ((8%nat, 0%nat), (2000%nat, 0%nat)). +Definition wit_wcopy_1 : Assignment := fun c => + if cell_eqb c (2000%nat, 0%nat) then 2 else + wit_honest_bm c. +Lemma wcopy_1_split_sat : sat mutant_wcopy_1_model wit_wcopy_1. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_1_not_refines : ~ refinesD_bm_gen mutant_wcopy_1_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_1 wcopy_1_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 H) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_2_model : CircuitModel := cut_copy_model_bm ((9%nat, 0%nat), (2000%nat, 1%nat)). +Definition wit_wcopy_2 : Assignment := fun c => + if cell_eqb c (2000%nat, 1%nat) then 1 else + wit_honest_bm c. +Lemma wcopy_2_split_sat : sat mutant_wcopy_2_model wit_wcopy_2. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_2_not_refines : ~ refinesD_bm_gen mutant_wcopy_2_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_2 wcopy_2_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 H)) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_3_model : CircuitModel := cut_copy_model_bm ((10%nat, 0%nat), (2000%nat, 2%nat)). +Definition wit_wcopy_3 : Assignment := fun c => + if cell_eqb c (2000%nat, 2%nat) then 1 else + wit_honest_bm c. +Lemma wcopy_3_split_sat : sat mutant_wcopy_3_model wit_wcopy_3. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_3_not_refines : ~ refinesD_bm_gen mutant_wcopy_3_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_3 wcopy_3_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 (proj2 H))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_4_model : CircuitModel := cut_copy_model_bm ((11%nat, 0%nat), (2000%nat, 3%nat)). +Definition wit_wcopy_4 : Assignment := fun c => + if cell_eqb c (2000%nat, 3%nat) then 1 else + wit_honest_bm c. +Lemma wcopy_4_split_sat : sat mutant_wcopy_4_model wit_wcopy_4. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_4_not_refines : ~ refinesD_bm_gen mutant_wcopy_4_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_4 wcopy_4_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 (proj2 (proj2 H)))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_5_model : CircuitModel := cut_copy_model_bm ((12%nat, 0%nat), (2000%nat, 4%nat)). +Definition wit_wcopy_5 : Assignment := fun c => + if cell_eqb c (2000%nat, 4%nat) then 18446744073709551615 else + wit_honest_bm c. +Lemma wcopy_5_split_sat : sat mutant_wcopy_5_model wit_wcopy_5. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_5_not_refines : ~ refinesD_bm_gen mutant_wcopy_5_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_5 wcopy_5_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 (proj2 (proj2 (proj2 H))))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_6_model : CircuitModel := cut_copy_model_bm ((13%nat, 0%nat), (2000%nat, 5%nat)). +Definition wit_wcopy_6 : Assignment := fun c => + if cell_eqb c (2000%nat, 5%nat) then 18446744073709551616 else + wit_honest_bm c. +Lemma wcopy_6_split_sat : sat mutant_wcopy_6_model wit_wcopy_6. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_6_not_refines : ~ refinesD_bm_gen mutant_wcopy_6_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_6 wcopy_6_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 (proj2 (proj2 (proj2 (proj2 H)))))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_7_model : CircuitModel := cut_copy_model_bm ((14%nat, 0%nat), (2000%nat, 6%nat)). +Definition wit_wcopy_7 : Assignment := fun c => + if cell_eqb c (2000%nat, 6%nat) then 18446744073709551616 else + wit_honest_bm c. +Lemma wcopy_7_split_sat : sat mutant_wcopy_7_model wit_wcopy_7. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_7_not_refines : ~ refinesD_bm_gen mutant_wcopy_7_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_7 wcopy_7_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj1 (proj2 (proj2 (proj2 (proj2 (proj2 (proj2 H))))))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Definition mutant_wcopy_8_model : CircuitModel := cut_copy_model_bm ((15%nat, 0%nat), (2000%nat, 7%nat)). +Definition wit_wcopy_8 : Assignment := fun c => + if cell_eqb c (2000%nat, 7%nat) then 18446744073709551616 else + wit_honest_bm c. +Lemma wcopy_8_split_sat : sat mutant_wcopy_8_model wit_wcopy_8. +Proof. split; [ apply gates_holdb_sound; vm_compute; reflexivity | apply copy_holdsb_sound; vm_compute; reflexivity ]. Qed. +Theorem mutant_wcopy_8_not_refines : ~ refinesD_bm_gen mutant_wcopy_8_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intro H. specialize (H wit_wcopy_8 wcopy_8_split_sat). + unfold RD_bm_gen in H. cbn [ intact_ports_bm_gen] in H. + pose proof (proj2 (proj2 (proj2 (proj2 (proj2 (proj2 (proj2 H))))))) as Hc. + vm_compute in Hc. discriminate Hc. +Qed. + +Theorem bm_all_wires_closed_gen : + (In ((8%nat, 0%nat), (2000%nat, 0%nat)) deployed_copy /\ + In ((9%nat, 0%nat), (2000%nat, 1%nat)) deployed_copy /\ + In ((10%nat, 0%nat), (2000%nat, 2%nat)) deployed_copy /\ + In ((11%nat, 0%nat), (2000%nat, 3%nat)) deployed_copy /\ + In ((12%nat, 0%nat), (2000%nat, 4%nat)) deployed_copy /\ + In ((13%nat, 0%nat), (2000%nat, 5%nat)) deployed_copy /\ + In ((14%nat, 0%nat), (2000%nat, 6%nat)) deployed_copy /\ + In ((15%nat, 0%nat), (2000%nat, 7%nat)) deployed_copy) /\ + (refinesD_bm_gen deployed_model intact_ports_bm_gen /\ + sat deployed_model wit_honest_bm) /\ + (~ refinesD_bm_gen mutant_wcopy_1_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_2_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_3_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_4_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_5_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_6_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_7_model intact_ports_bm_gen /\ + ~ refinesD_bm_gen mutant_wcopy_8_model intact_ports_bm_gen). +Proof. + split; [| split]. + - repeat split; + first [ exact in_copy_1 + | exact in_copy_2 + | exact in_copy_3 + | exact in_copy_4 + | exact in_copy_5 + | exact in_copy_6 + | exact in_copy_7 + | exact in_copy_8 ]. + - split; [ exact deployed_refines_RD_bm_gen | exact honest_full_sat_bm ]. + - exact (conj mutant_wcopy_1_not_refines + (conj mutant_wcopy_2_not_refines + (conj mutant_wcopy_3_not_refines + (conj mutant_wcopy_4_not_refines + (conj mutant_wcopy_5_not_refines + (conj mutant_wcopy_6_not_refines + (conj mutant_wcopy_7_not_refines + (mutant_wcopy_8_not_refines)))))))). +Qed. diff --git a/coq-legacy/constraints/gen/bm_scaffold_gen.v b/coq-legacy/constraints/gen/bm_scaffold_gen.v new file mode 100644 index 0000000..2812f44 --- /dev/null +++ b/coq-legacy/constraints/gen/bm_scaffold_gen.v @@ -0,0 +1,136 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Assignments, the evaluator for constraint expressions, and the acceptance predicate sat: every + polynomial constraint evaluates to zero modulo p, and every copy constraint holds. Also the intended + public interface (RD_bm_gen: each output cell agrees modulo p with its public cell), which the model + refines (deployed_refines_RD_bm_gen). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. +Require Import Generated.bm_model_gen. +Require Import Generated.bm_wires_gen. + +Definition Assignment := Cell -> Z. + +Fixpoint eval (a:Assignment) (e:Expr) : Z := + match e with + | EConst z => z + | ECell c => a c + | EAdd x y => eval a x + eval a y + | ESub x y => eval a x - eval a y + | EMul x y => eval a x * eval a y + | ENeg x => - eval a x + | EScaled x z => eval a x * z + end. + +Definition gate_holds a g : Prop := (eval a g) mod p = 0. +Definition gates_hold a gs : Prop := forall g, In g gs -> gate_holds a g. +Definition copy_holds a (cp:list (Cell*Cell)) : Prop := + forall e, In e cp -> (a (fst e)) mod p = (a (snd e)) mod p. +Definition sat (m:CircuitModel) a : Prop := + gates_hold a (cm_gates m) /\ copy_holds a (cm_copy m). + +Definition cell_eqb (c d:Cell) : bool := + match c, d with + | (c1,c2),(d1,d2) => andb (Nat.eqb c1 d1) (Nat.eqb c2 d2) + end. +Definition cellpair_eqb (e f:Cell*Cell) : bool := + andb (cell_eqb (fst e) (fst f)) (cell_eqb (snd e) (snd f)). + +Fixpoint reads_b (t:Cell) (e:Expr) : bool := + match e with + | EConst _ => false + | ECell c => cell_eqb c t + | EAdd x y => orb (reads_b t x) (reads_b t y) + | ESub x y => orb (reads_b t x) (reads_b t y) + | EMul x y => orb (reads_b t x) (reads_b t y) + | ENeg x => reads_b t x + | EScaled x _ => reads_b t x + end. +Definition reads (t:Cell) (e:Expr) : Prop := reads_b t e = true. + +Lemma copy_get : forall (a:Assignment) (c1 c2:Cell), + copy_holds a deployed_copy -> + In (c1,c2) deployed_copy -> + (a c1) mod p = (a c2) mod p. +Proof. intros a c1 c2 H Hin. specialize (H _ Hin). cbn [fst snd] in H. exact H. Qed. + +Ltac gates_tac := + let g := fresh "g" in let Hin := fresh "Hin" in + intros g Hin; cbn in Hin; + repeat (destruct Hin as [<-|Hin]; [vm_compute; reflexivity| ]); + contradiction. +Ltac copy_tac := + let e := fresh "e" in let Hin := fresh "Hin" in + intros e Hin; cbn in Hin; + repeat (destruct Hin as [<-|Hin]; [vm_compute; reflexivity| ]); + contradiction. + +Definition gates_holdb (a:Assignment) (gs:list Expr) : bool := + forallb (fun g => Z.eqb ((eval a g) mod p) 0) gs. +Definition copy_holdsb (a:Assignment) (cp:list (Cell*Cell)) : bool := + forallb (fun e => Z.eqb ((a (fst e)) mod p) ((a (snd e)) mod p)) cp. + +Lemma gates_holdb_sound : forall a gs, gates_holdb a gs = true -> gates_hold a gs. +Proof. + intros a gs H g Hin. + unfold gates_holdb in H. rewrite forallb_forall in H. + specialize (H g Hin). apply Z.eqb_eq in H. exact H. +Qed. +Lemma copy_holdsb_sound : forall a cp, copy_holdsb a cp = true -> copy_holds a cp. +Proof. + intros a cp H e Hin. + unfold copy_holdsb in H. rewrite forallb_forall in H. + specialize (H e Hin). apply Z.eqb_eq in H. exact H. +Qed. + +Lemma in_copy_1 : In ((8%nat, 0%nat), (2000%nat, 0%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 0); vm_compute; reflexivity. Qed. +Lemma in_copy_2 : In ((9%nat, 0%nat), (2000%nat, 1%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 1); vm_compute; reflexivity. Qed. +Lemma in_copy_3 : In ((10%nat, 0%nat), (2000%nat, 2%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 2); vm_compute; reflexivity. Qed. +Lemma in_copy_4 : In ((11%nat, 0%nat), (2000%nat, 3%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 3); vm_compute; reflexivity. Qed. +Lemma in_copy_5 : In ((12%nat, 0%nat), (2000%nat, 4%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 4); vm_compute; reflexivity. Qed. +Lemma in_copy_6 : In ((13%nat, 0%nat), (2000%nat, 5%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 5); vm_compute; reflexivity. Qed. +Lemma in_copy_7 : In ((14%nat, 0%nat), (2000%nat, 6%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 6); vm_compute; reflexivity. Qed. +Lemma in_copy_8 : In ((15%nat, 0%nat), (2000%nat, 7%nat)) deployed_copy. +Proof. apply (nth_error_In deployed_copy 7); vm_compute; reflexivity. Qed. + +Record Ports_bm_gen := mk_ports_bm_gen { }. +Definition intact_ports_bm_gen : Ports_bm_gen := mk_ports_bm_gen. + +Definition RD_bm_gen (pts:Ports_bm_gen) (a:Assignment) : Prop := + (a (8%nat, 0%nat)) mod p = (a (2000%nat, 0%nat)) mod p /\ + (a (9%nat, 0%nat)) mod p = (a (2000%nat, 1%nat)) mod p /\ + (a (10%nat, 0%nat)) mod p = (a (2000%nat, 2%nat)) mod p /\ + (a (11%nat, 0%nat)) mod p = (a (2000%nat, 3%nat)) mod p /\ + (a (12%nat, 0%nat)) mod p = (a (2000%nat, 4%nat)) mod p /\ + (a (13%nat, 0%nat)) mod p = (a (2000%nat, 5%nat)) mod p /\ + (a (14%nat, 0%nat)) mod p = (a (2000%nat, 6%nat)) mod p /\ + (a (15%nat, 0%nat)) mod p = (a (2000%nat, 7%nat)) mod p. + +Definition refinesD_bm_gen (m:CircuitModel) (pts:Ports_bm_gen) : Prop := + forall a, sat m a -> RD_bm_gen pts a. + +Theorem deployed_refines_RD_bm_gen : refinesD_bm_gen deployed_model intact_ports_bm_gen. +Proof. + unfold refinesD_bm_gen. intros a [Hg Hc]. + unfold RD_bm_gen. cbn [intact_ports_bm_gen]. + repeat split; + try reflexivity; + first [ exact (copy_get a _ _ Hc in_copy_1) + | exact (copy_get a _ _ Hc in_copy_2) + | exact (copy_get a _ _ Hc in_copy_3) + | exact (copy_get a _ _ Hc in_copy_4) + | exact (copy_get a _ _ Hc in_copy_5) + | exact (copy_get a _ _ Hc in_copy_6) + | exact (copy_get a _ _ Hc in_copy_7) + | exact (copy_get a _ _ Hc in_copy_8) ]. +Qed. diff --git a/coq-legacy/constraints/gen/bm_wires_gen.v b/coq-legacy/constraints/gen/bm_wires_gen.v new file mode 100644 index 0000000..182fe1c --- /dev/null +++ b/coq-legacy/constraints/gen/bm_wires_gen.v @@ -0,0 +1,23 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + The eight copy wires, from the output cells (8..15, 0) to the public cells (2000, 0..7). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith List. Import ListNotations. Open Scope Z_scope. +Require Import Generated.bm_model_gen. + +Definition wcopy_1 : Cell * Cell := ((8%nat, 0%nat), (2000%nat, 0%nat)). +Definition wcopy_2 : Cell * Cell := ((9%nat, 0%nat), (2000%nat, 1%nat)). +Definition wcopy_3 : Cell * Cell := ((10%nat, 0%nat), (2000%nat, 2%nat)). +Definition wcopy_4 : Cell * Cell := ((11%nat, 0%nat), (2000%nat, 3%nat)). +Definition wcopy_5 : Cell * Cell := ((12%nat, 0%nat), (2000%nat, 4%nat)). +Definition wcopy_6 : Cell * Cell := ((13%nat, 0%nat), (2000%nat, 5%nat)). +Definition wcopy_7 : Cell * Cell := ((14%nat, 0%nat), (2000%nat, 6%nat)). +Definition wcopy_8 : Cell * Cell := ((15%nat, 0%nat), (2000%nat, 7%nat)). +Definition copy_wires : list (Cell * Cell) := + [ wcopy_1; wcopy_2; wcopy_3; wcopy_4; wcopy_5; wcopy_6; wcopy_7; wcopy_8 ]. + +Definition share_wires : list Cell := + [ ]. diff --git a/coq-legacy/constraints/pfcs.v b/coq-legacy/constraints/pfcs.v new file mode 100644 index 0000000..32b562b --- /dev/null +++ b/coq-legacy/constraints/pfcs.v @@ -0,0 +1,140 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + A Coq embedding of prime-field constraint systems (polynomials, constraints, and the satisfaction + relation), following the PFCS formalism of A. Coglio, E. McCarthy and E. W. Smith, "Formal + Verification of Zero-Knowledge Circuits", arXiv:2311.08858. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import Init.Datatypes. +From Coq Require Import Lists.List. +From Coq Require Import Arith.PeanoNat. + +Import ListNotations. + +Record FieldOps (F : Type) : Type := { + fzero : F; + fone : F; + fadd : F -> F -> F; + fmul : F -> F -> F; + fneg : F -> F; + feqb : F -> F -> bool +}. + +Arguments fzero {F} _. +Arguments fone {F} _. +Arguments fadd {F} _ _ _. +Arguments fmul {F} _ _ _. +Arguments fneg {F} _ _. +Arguments feqb {F} _ _ _. + +Definition Var : Set := nat. +Definition ProcName : Set := nat. + +Inductive Poly (F : Type) : Type := +| PConst : F -> Poly F +| PVar : Var -> Poly F +| PAdd : Poly F -> Poly F -> Poly F +| PMul : Poly F -> Poly F -> Poly F +| PNeg : Poly F -> Poly F. + +Arguments PConst {F} _. +Arguments PVar {F} _. +Arguments PAdd {F} _ _. +Arguments PMul {F} _ _. +Arguments PNeg {F} _. + +Inductive Constraint (F : Type) : Type := +| Eq : Poly F -> Poly F -> Constraint F +| And : Constraint F -> Constraint F -> Constraint F +| Exists : Var -> Constraint F -> Constraint F +| Call : ProcName -> list (Poly F) -> Constraint F. + +Arguments Eq {F} _ _. +Arguments And {F} _ _. +Arguments Exists {F} _ _. +Arguments Call {F} _ _. + +Record ProcDef (F : Type) : Type := { + pd_name : ProcName; + pd_args : list Var; + pd_locals : list Var; + pd_body : Constraint F; + pd_spec : Constraint F +}. + +Arguments pd_name {F} _. +Arguments pd_args {F} _. +Arguments pd_locals {F} _. +Arguments pd_body {F} _. +Arguments pd_spec {F} _. + +Definition Program (F : Type) : Type := list (ProcName * ProcDef F). + +Definition lookup_proc {F : Type} (prog : Program F) (n : ProcName) + : option (ProcDef F) := + match find (fun kv => Nat.eqb (fst kv) n) prog with + | Some (_, pd) => Some pd + | None => None + end. + +Definition Env (F : Type) : Type := Var -> option F. + +Definition empty_env {F : Type} : Env F := fun _ => None. + +Definition env_extend {F : Type} (e : Env F) (v : Var) (x : F) : Env F := + fun w => if Nat.eqb v w then Some x else e w. + +Definition extend_pairs {F : Type} (e : Env F) + (pairs : list (Var * F)) : Env F := + fold_left (fun acc xv => env_extend acc (fst xv) (snd xv)) pairs e. + +Definition arg_env {F : Type} (args : list Var) (vs : list F) : Env F := + extend_pairs empty_env (combine args vs). + +Fixpoint eval_poly {F : Type} (ops : FieldOps F) (e : Env F) (p : Poly F) + : option F := + match p with + | PConst k => Some k + | PVar v => e v + | PAdd p1 p2 => + match eval_poly ops e p1, eval_poly ops e p2 with + | Some v1, Some v2 => Some (fadd ops v1 v2) + | _, _ => None + end + | PMul p1 p2 => + match eval_poly ops e p1, eval_poly ops e p2 with + | Some v1, Some v2 => Some (fmul ops v1 v2) + | _, _ => None + end + | PNeg p1 => + match eval_poly ops e p1 with + | Some v => Some (fneg ops v) + | None => None + end + end. + +Inductive satisfies {F : Type} (ops : FieldOps F) (prog : Program F) + : Env F -> Constraint F -> Prop := + +| Sat_Eq : forall (e : Env F) (p q : Poly F) (v : F), + eval_poly ops e p = Some v -> + eval_poly ops e q = Some v -> + satisfies ops prog e (Eq p q) + +| Sat_And : forall (e : Env F) (c1 c2 : Constraint F), + satisfies ops prog e c1 -> + satisfies ops prog e c2 -> + satisfies ops prog e (And c1 c2) + +| Sat_Exists : forall (e : Env F) (x : Var) (c : Constraint F) (w : F), + satisfies ops prog (env_extend e x w) c -> + satisfies ops prog e (Exists x c) + +| Sat_Call : forall (e : Env F) (name : ProcName) (args : list (Poly F)) + (pd : ProcDef F) (vs : list F), + lookup_proc prog name = Some pd -> + map (eval_poly ops e) args = map (@Some F) vs -> + satisfies ops prog (arg_env (pd_args pd) vs) (pd_spec pd) -> + satisfies ops prog e (Call name args). diff --git a/coq-legacy/constraints/range_field.v b/coq-legacy/constraints/range_field.v new file mode 100644 index 0000000..cbdbb51 --- /dev/null +++ b/coq-legacy/constraints/range_field.v @@ -0,0 +1,158 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Soundness of bit-decomposition range checks over a prime field given as a parameter: when 2^n is at + most p, a value whose n-bit decomposition constraints are satisfied lies in [0, 2^n) modulo p + (range_tail_sound_field). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List String Znumtheory. +Import ListNotations. +From Constraints Require Import pfcs. +Open Scope Z_scope. + +Section PrimeField. +Variable p : Z. +Hypothesis Hp : prime p. + +Definition zp : FieldOps Z := + {| fzero := 0; + fone := 1; + fadd := fun a b => (a + b) mod p; + fmul := fun a b => (a * b) mod p; + fneg := fun a => (- a) mod p; + feqb := fun a b => Z.eqb (a mod p) (b mod p) |}. + +Definition Cbool (b : Var) : Constraint Z := + Eq (PAdd (PMul (PVar b) (PVar b)) (PNeg (PVar b))) (PConst 0). +Definition Cbitsum_step (t b tl : Var) : Constraint Z := + Eq (PVar t) (PAdd (PVar b) (PAdd (PVar tl) (PVar tl))). + +Fixpoint range_tail (t : Var) (base : Var) (n : nat) : Constraint Z := + match n with + | O => Eq (PVar t) (PConst 0) + | S m => + Exists base + (Exists (S base) + (And (Cbitsum_step t base (S base)) + (And (Cbool base) + (range_tail (S base) (S (S base)) m)))) + end. + +Lemma env_extend_eq : forall (e : Env Z) (k : Var) (x : Z), + env_extend e k x k = Some x. +Proof. intros. unfold env_extend. rewrite Nat.eqb_refl. reflexivity. Qed. +Lemma env_extend_neq : forall (e : Env Z) (k j : Var) (x : Z), + k <> j -> env_extend e k x j = e j. +Proof. + intros e k j x H. unfold env_extend. + destruct (Nat.eqb k j) eqn:Hkj. + - apply Nat.eqb_eq in Hkj. contradiction. + - reflexivity. +Qed. + +Lemma bool_mod_forces_01 : forall b, + (b * b - b) mod p = 0 -> + b mod p = 0 \/ b mod p = 1. +Proof. + intros b Hb. pose proof (prime_ge_2 _ Hp) as Hp2. + replace (b * b - b) with (b * (b - 1)) in Hb by ring. + apply Z.mod_divide in Hb; [| lia]. + apply prime_mult in Hb; [| exact Hp]. + destruct Hb as [H|H]. + - left. apply Z.mod_divide in H; [exact H | lia]. + - right. + assert (Hm1 : (b - 1) mod p = 0) by (apply Z.mod_divide; [lia | exact H]). + replace b with ((b - 1) + 1) by ring. + rewrite Zplus_mod, Hm1, Z.add_0_l, Zmod_mod. + rewrite Z.mod_small by lia. reflexivity. +Qed. + +Lemma range_tail_sound_field : + forall (n : nat) (t base : Var) (e : Env Z) (d : Z), + 2 ^ (Z.of_nat n) <= p -> + (t < base)%nat -> + e t = Some d -> + satisfies zp [] e (range_tail t base n) -> + 0 <= d mod p < 2 ^ (Z.of_nat n). +Proof. + pose proof (prime_ge_2 _ Hp) as Hp2. + induction n as [| m IH]; intros t base e d Hnowrap Hlt Het Hsat; simpl in Hsat. + - + inversion Hsat as [e0 pp qq vv Hpp Hqq | | | ]; subst. + cbn [eval_poly] in Hpp, Hqq. rewrite Het in Hpp. + inversion Hpp; subst vv. inversion Hqq as [Hd0]. + change (Z.of_nat 0) with 0%Z. rewrite Z.pow_0_r. + assert (d = 0) by lia. subst d. rewrite Zmod_0_l. lia. + - + assert (Hpow : 2 ^ (Z.of_nat (S m)) = 2 * 2 ^ (Z.of_nat m)). + { rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. ring. } + assert (Hpowm_pos : 0 < 2 ^ (Z.of_nat m)) by (apply Z.pow_pos_nonneg; lia). + assert (Hnowrap_m : 2 ^ (Z.of_nat m) <= p) by lia. + inversion Hsat as [| | e0 x c wb Hsb Hx Hc | ]; subst; clear Hsat. + inversion Hsb as [| | e1 x1 c1 wtl Hstl Hx1 Hc1 | ]; subst; clear Hsb. + set (eb := env_extend (env_extend e base wb) (S base) wtl) in *. + inversion Hstl as [ | e2 ca cb Hand1 Hand2 | | ]; subst; clear Hstl. + inversion Hand2 as [ | e3 ca3 cb3 Hbool Hrest | | ]; subst; clear Hand2. + inversion Hand1 as [ eb' pp qq vv Hpp Hqq Heqeb | | | ]; subst; clear Hand1. + assert (Hb_eb : eb base = Some wb). + { unfold eb. rewrite env_extend_neq by lia. apply env_extend_eq. } + assert (Htl_eb : eb (S base) = Some wtl). + { unfold eb. apply env_extend_eq. } + assert (Ht_eb : eb t = Some d). + { unfold eb. rewrite env_extend_neq by lia. + rewrite env_extend_neq by lia. exact Het. } + cbn [eval_poly] in Hpp, Hqq. + rewrite Ht_eb in Hpp. + rewrite Hb_eb, Htl_eb in Hqq. + + injection Hpp as Hppe. + injection Hqq as Hqqe. + assert (Hd_mod : d = (wb + (wtl + wtl) mod p) mod p) by lia. + inversion Hbool as [ ec pp2 qq2 vv2 Hpp2 Hqq2 | | | ]; clear Hbool. + cbn [eval_poly] in Hpp2, Hqq2. + rewrite Hb_eb in Hpp2. + injection Hpp2 as Hbool_val. + injection Hqq2 as Hzero. + assert (Hwb_mod0 : (wb * wb - wb) mod p = 0). + { replace (wb * wb - wb) with (wb * wb + (- wb)) by ring. + rewrite Zplus_mod, Hbool_val, <- Hzero. reflexivity. } + apply bool_mod_forces_01 in Hwb_mod0. + assert (Htl_bound : 0 <= wtl mod p < 2 ^ (Z.of_nat m)). + { eapply IH with (t := S base) (base := S (S base)) (e := eb). + - exact Hnowrap_m. + - lia. + - exact Htl_eb. + - exact Hrest. } + + set (vb := wb mod p) in *. + set (vt := wtl mod p) in *. + set (v := vb + 2 * vt). + assert (Hv_lo : 0 <= v). + { unfold v. destruct Hwb_mod0 as [Hbb|Hbb]; rewrite Hbb; lia. } + assert (Hv_hi : v < 2 ^ (Z.of_nat (S m))). + { unfold v. rewrite Hpow. destruct Hwb_mod0 as [Hbb|Hbb]; rewrite Hbb; lia. } + + assert (Hv_lt_p : v < p) by lia. + assert (Hv_modp : v mod p = v) by (apply Z.mod_small; lia). + + assert (Hcollapse : d mod p = (wb + 2 * wtl) mod p). + { rewrite Hd_mod, Zmod_mod. + rewrite (Zplus_mod wb ((wtl + wtl) mod p)), Zmod_mod, + <- (Zplus_mod wb (wtl + wtl)). + f_equal. ring. } + + assert (Hcong : (wb + 2 * wtl) mod p = v). + { assert (Hsplit : wb + 2 * wtl = v + (wb / p + 2 * (wtl / p)) * p). + { unfold v, vb, vt. + rewrite (Z.div_mod wb p) at 1 by lia. + rewrite (Z.div_mod wtl p) at 1 by lia. ring. } + rewrite Hsplit, Z.mod_add by lia. rewrite Hv_modp. reflexivity. } + assert (Hd_eq_v : d mod p = v) by (rewrite Hcollapse, Hcong; reflexivity). + rewrite Hd_eq_v. lia. +Qed. + +End PrimeField. + +Print Assumptions range_tail_sound_field. diff --git a/coq-legacy/constraints/range_field_pasta.v b/coq-legacy/constraints/range_field_pasta.v new file mode 100644 index 0000000..852d24b --- /dev/null +++ b/coq-legacy/constraints/range_field_pasta.v @@ -0,0 +1,908 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + Field facts for the Pasta prime, including its primality, proved by a Pocklington certificate + (pasta_prime), and the range-check soundness of range_field.v instantiated at that prime. + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith Lia List String Znumtheory. +Import ListNotations. +Open Scope Z_scope. +From Constraints Require Import pfcs range_field. + +Require Import Coq.Arith.Arith Coq.ZArith.Zpow_facts. + +From Coq Require Import ZArith Lia List Arith. +Import ListNotations. +Open Scope nat_scope. + +Fixpoint binom (n k : nat) : nat := + match n, k with + | _, O => 1 + | O, S _ => 0 + | S n', S k' => binom n' k' + binom n' (S k') + end. +Lemma binom_n_0 n : binom n 0 = 1. Proof. destruct n; reflexivity. Qed. +Lemma binom_pascal n k : binom (S n) (S k) = binom n k + binom n (S k). +Proof. reflexivity. Qed. +Lemma binom_gt n k : (n < k) -> binom n k = 0. +Proof. + revert k. induction n as [|n IH]; intros k Hk. + - destruct k. lia. reflexivity. + - destruct k. lia. rewrite binom_pascal, !IH by lia. reflexivity. +Qed. + +Open Scope Z_scope. +Definition bterm (x:Z) (n k:nat) : Z := Z.of_nat (binom n k) * x ^ Z.of_nat k. +Definition bsum (x:Z) (n:nat) : Z := fold_right Z.add 0 (map (bterm x n) (seq 0 (S n))). + +Lemma fold_add_app l1 l2 : + fold_right Z.add 0 (l1 ++ l2) = fold_right Z.add 0 l1 + fold_right Z.add 0 l2. +Proof. induction l1 as [|a l IH]; simpl; [ring | rewrite IH; ring]. Qed. + +Lemma fold_add_map_ext (f g : nat -> Z) l : + (forall k, In k l -> f k = g k) -> + fold_right Z.add 0 (map f l) = fold_right Z.add 0 (map g l). +Proof. + induction l as [|a l IH]; intro H; simpl. reflexivity. + rewrite H by (simpl; auto). rewrite IH. reflexivity. + intros k Hk. apply H. simpl; auto. +Qed. + +Lemma seq_split_head m (f : nat -> Z) : + fold_right Z.add 0 (map f (seq 0 (S m))) = + f 0%nat + fold_right Z.add 0 (map (fun k => f (S k)) (seq 0 m)). +Proof. + simpl. f_equal. + rewrite <- seq_shift, map_map. reflexivity. +Qed. + +Lemma binom_thm : forall n (x:Z), (1 + x) ^ Z.of_nat n = bsum x n. +Proof. + induction n as [|n IH]; intro x. + - cbv [bsum]. simpl. cbv [bterm]. simpl. ring. + - rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. rewrite IH. + + unfold bsum at 2. + + rewrite (seq_split_head (S n) (bterm x (S n))). + + assert (Hb0a : bterm x (S n) 0%nat = 1) by (cbv [bterm]; rewrite binom_n_0; simpl; ring); rewrite Hb0a. + + erewrite fold_add_map_ext with + (g := fun k => bterm x n (S k) + x * bterm x n k). + 2:{ intros k Hk. cbv [bterm]. + rewrite binom_pascal, Nat2Z.inj_add. + rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. ring. } + + assert (Hsplit : forall (u v : nat -> Z) l, + fold_right Z.add 0 (map (fun k => u k + v k) l) + = fold_right Z.add 0 (map u l) + fold_right Z.add 0 (map v l)). + { intros u v l. induction l as [|a l IHl]; simpl. ring. rewrite IHl. ring. } + rewrite Hsplit. + + assert (Hscale : forall (u:nat->Z) c l, + fold_right Z.add 0 (map (fun k => c * u k) l) = c * fold_right Z.add 0 (map u l)). + { intros u c l. induction l as [|a l IHl]; simpl. ring. rewrite IHl; ring. } + rewrite Hscale. + + rewrite seq_S, map_app, fold_add_app. + assert (Hbz : bterm x n (S (0 + n)) = 0). + { unfold bterm. rewrite (binom_gt n (S (0+n))) by lia. simpl (Z.of_nat 0). ring. } + assert (Hz : fold_right Z.add 0 (map (fun k => bterm x n (S k)) [0 + n]%nat) = 0). + { cbn [map fold_right]. rewrite Hbz. ring. } + rewrite Hz, Z.add_0_r. + + assert (Hbs : bsum x n = bterm x n 0%nat + fold_right Z.add 0 (map (fun k => bterm x n (S k)) (seq 0 n))). + { unfold bsum. apply seq_split_head. } + assert (Hb0b : bterm x n 0%nat = 1) by (cbv [bterm]; rewrite binom_n_0; simpl; ring); rewrite Hb0b in Hbs. + set (A := fold_right Z.add 0 (map (fun k => bterm x n (S k)) (seq 0 n))) in *. + rewrite <- seq_S. fold (bsum x n). rewrite Hbs. ring. +Qed. + +From Coq Require Import Znumtheory Zpow_facts. + +Lemma binom_n_n n : binom n n = 1%nat. +Proof. + induction n as [|n IH]. reflexivity. + rewrite binom_pascal, IH, (binom_gt n (S n)) by lia. lia. +Qed. + +Section FRESHMAN. +Variable r : Z. +Hypothesis Hr : prime r. + +Hypothesis Hmid : forall k, (0 < k < Z.to_nat r)%nat -> (r | Z.of_nat (binom (Z.to_nat r) k)). + +Lemma bterm_mid_mod x k : (0 < k < Z.to_nat r)%nat -> (bterm x (Z.to_nat r) k) mod r = 0. +Proof. + intros Hk. unfold bterm. + apply Z.mod_divide. pose proof (prime_ge_2 _ Hr); lia. + apply Z.divide_mul_l. apply Hmid; exact Hk. +Qed. + +Lemma freshman x : ((x + 1) ^ r) mod r = (x ^ r + 1) mod r. +Proof. + pose proof (prime_ge_2 _ Hr) as Hr2. + set (rn := Z.to_nat r) in *. + assert (Hrn : Z.of_nat rn = r) by (unfold rn; rewrite Z2Nat.id; lia). + + assert (Hxr : (x + 1) ^ r = bsum x rn). + { rewrite <- Hrn at 1. rewrite <- binom_thm. f_equal. ring. } + rewrite Hxr. + + unfold bsum. + + rewrite seq_split_head. + assert (Hb0 : bterm x rn 0%nat = 1) by (unfold bterm; rewrite binom_n_0; simpl; ring). + rewrite Hb0. + + destruct rn as [|m] eqn:Erm. lia. + + rewrite seq_S, map_app, fold_add_app. + + assert (Hlast : fold_right Z.add 0 (map (fun k => bterm x (S m) (S k)) [0 + m]%nat) + = x ^ r). + { cbn [map fold_right]. unfold bterm. + replace (S (0 + m)) with (S m) by lia. rewrite binom_n_n. + rewrite Hrn. simpl (Z.of_nat 1). ring. } + rewrite Hlast. + + set (Mid := fold_right Z.add 0 (map (fun k => bterm x (S m) (S k)) (seq 0 m))). + assert (HMid0 : Mid mod r = 0). + { unfold Mid. + + assert (Hall : forall k, In k (seq 0 m) -> (bterm x (S m) (S k)) mod r = 0). + { intros k Hk. rewrite in_seq in Hk. + unfold bterm. apply Z.mod_divide; [lia|]. + apply Z.divide_mul_l. + apply (Hmid (S k)). lia. } + + revert Hall. generalize (seq 0 m) as l. induction l as [|a l IHl]; intro Hall. + - reflexivity. + - cbn [map fold_right]. rewrite Zplus_mod. + rewrite (Hall a) by (simpl; auto). + rewrite IHl by (intros; apply Hall; simpl; auto). + reflexivity. } + + assert (Hdiff : (1 + (Mid + x ^ r)) = (x ^ r + 1) + Mid) by ring. + rewrite Hdiff. + apply Z.mod_divide in HMid0; [|lia]. + destruct HMid0 as [c Hc]. + rewrite Hc, Z_mod_plus_full. reflexivity. +Qed. + +End FRESHMAN. + +Fixpoint fact (n:nat) : nat := match n with O => 1 | S m => n * fact m end%nat. + +Lemma binom_fact_id : forall n k, (k <= n)%nat -> + (binom n k * (fact k * fact (n - k)) = fact n)%nat. +Proof. + induction n as [|n IH]; intros k Hk. + - assert (k = 0)%nat by lia. subst. reflexivity. + - destruct k as [|k]. + + rewrite binom_n_0. replace (S n - 0)%nat with (S n) by lia. + simpl (fact 0). lia. + + replace (S n - S k)%nat with (n - k)%nat by lia. + destruct (Nat.eq_dec (S k) (S n)) as [He|Hne]. + * assert (Hkn : k = n) by lia. subst k. + rewrite binom_pascal. + assert (Hbgt : binom n (S n) = 0%nat) by (apply binom_gt; lia). + assert (Hsub : (n - n = 0)%nat) by lia. + rewrite Hbgt, binom_n_n, Hsub. simpl (fact 0). lia. + * assert (HSkn : (S k <= n)%nat) by lia. + rewrite binom_pascal. + pose proof (IH k ltac:(lia)) as Ha. + pose proof (IH (S k) ltac:(lia)) as Hb. + assert (Hnk1 : (n - k = S (n - S k))%nat) by lia. + replace (fact (S k)) with (S k * fact k)%nat by reflexivity. + rewrite Hnk1. + replace (fact (S (n - S k))) with (S (n - S k) * fact (n - S k))%nat by reflexivity. + set (Ck := binom n k) in *. set (Csk := binom n (S k)) in *. + set (fk := fact k) in *. set (fnk := fact (n - S k)) in *. + rewrite Hnk1 in Ha. + replace (fact (S (n - S k))) with (S (n - S k) * fnk)%nat in Ha by reflexivity. + replace (fact (S k)) with (S k * fk)%nat in Hb by reflexivity. + simpl (fact (S n)). + assert (Hn : (n = k + S (n - S k))%nat) by lia. + nia. +Qed. + +Lemma prime_not_div_fact : forall (r:Z), prime r -> + forall m, (Z.of_nat m < r) -> ~ (r | Z.of_nat (fact m)). +Proof. + intros r Hr m. induction m as [|m IH]; intros Hm. + - simpl (fact 0). intro Hd. pose proof (prime_ge_2 _ Hr) as Hr2. + apply Z.divide_1_r in Hd. lia. + - rewrite Nat2Z.inj_succ in Hm. + replace (fact (S m)) with (S m * fact m)%nat by reflexivity. + rewrite Nat2Z.inj_mul, Nat2Z.inj_succ. intro Hd. + apply prime_mult in Hd; [| exact Hr]. + destruct Hd as [H1|H2]. + + pose proof (prime_ge_2 _ Hr) as Hr2. + apply Z.divide_pos_le in H1; lia. + + apply IH; [lia | exact H2]. +Qed. + +Lemma prime_div_fact_self : forall (r:Z), prime r -> + (r | Z.of_nat (fact (Z.to_nat r))). +Proof. + intros r Hr. pose proof (prime_ge_2 _ Hr) as Hr2. + set (rn := Z.to_nat r). + assert (Hrn : Z.of_nat rn = r) by (unfold rn; rewrite Z2Nat.id; lia). + assert (Hpos : (0 < rn)%nat) by (unfold rn; lia). + destruct rn as [|m] eqn:E. lia. + replace (fact (S m)) with (S m * fact m)%nat by reflexivity. + rewrite Nat2Z.inj_mul. apply Z.divide_mul_l. + rewrite Hrn. apply Z.divide_refl. +Qed. + +Lemma prime_div_binom : forall (r:Z), prime r -> + forall k, (0 < k < Z.to_nat r)%nat -> + (r | Z.of_nat (binom (Z.to_nat r) k)). +Proof. + intros r Hr k Hk. pose proof (prime_ge_2 _ Hr) as Hr2. + set (rn := Z.to_nat r) in *. + assert (Hrn : Z.of_nat rn = r) by (unfold rn; rewrite Z2Nat.id; lia). + pose proof (binom_fact_id rn k ltac:(lia)) as Hid. + pose proof (prime_div_fact_self r Hr) as Hdivfact. fold rn in Hdivfact. + rewrite <- Hid in Hdivfact. + rewrite !Nat2Z.inj_mul in Hdivfact. + apply prime_mult in Hdivfact; [| exact Hr]. + destruct Hdivfact as [Hb | Hrest]. + - exact Hb. + - exfalso. apply prime_mult in Hrest; [| exact Hr]. + destruct Hrest as [Hfk | Hfrk]. + + apply (prime_not_div_fact r Hr k); [rewrite <- Hrn; apply Nat2Z.inj_lt; lia | exact Hfk]. + + apply (prime_not_div_fact r Hr (rn - k)); [rewrite <- Hrn; apply Nat2Z.inj_lt; lia | exact Hfrk]. +Qed. + +Lemma freshman' : forall (r:Z), prime r -> forall x, + (x + 1) ^ r mod r = (x ^ r + 1) mod r. +Proof. + intros r Hr x. apply freshman; auto. + intros k Hk. apply prime_div_binom; auto. +Qed. + +Lemma fermat_nonneg : forall (r:Z), prime r -> forall a, 0 <= a -> + a ^ r mod r = a mod r. +Proof. + intros r Hr. pose proof (prime_ge_2 _ Hr) as Hr2. + + intros a Ha. pattern a. apply natlike_ind; [ | | exact Ha]. + - + rewrite Z.pow_0_l by lia. reflexivity. + - + intros n Hn IH. + replace (Z.succ n) with (n + 1) by lia. + rewrite (freshman' r Hr n). + + rewrite Zplus_mod, IH, <- Zplus_mod. reflexivity. +Qed. + +Lemma fermat_all : forall (r:Z), prime r -> forall a, a ^ r mod r = a mod r. +Proof. + intros r Hr a. pose proof (prime_ge_2 _ Hr) as Hr2. + + assert (Hb : 0 <= a mod r < r) by (apply Z.mod_pos_bound; lia). + transitivity ((a mod r) ^ r mod r). + - rewrite (Zpower_mod a r r) by lia. reflexivity. + - rewrite (fermat_nonneg r Hr (a mod r)) by lia. rewrite Zmod_mod. reflexivity. +Qed. + +Lemma fermat_little : forall (r:Z), prime r -> forall a, + rel_prime a r -> a ^ (r - 1) mod r = 1 mod r. +Proof. + intros r Hr a Hcop. pose proof (prime_ge_2 _ Hr) as Hr2. + + assert (Hsplit : a ^ r = a * a ^ (r - 1)). + { rewrite <- Z.pow_succ_r by lia. f_equal. lia. } + pose proof (fermat_all r Hr a) as Hf. rewrite Hsplit in Hf. + + assert (Hdvd : (r | a * (a ^ (r - 1) - 1))). + { apply Z.mod_divide; [lia|]. + replace (a * (a ^ (r - 1) - 1)) with (a * a ^ (r - 1) - a) by ring. + rewrite Zminus_mod, Hf, <- Zminus_mod. rewrite Z.sub_diag. reflexivity. } + + apply Gauss in Hdvd; [| apply rel_prime_sym; exact Hcop]. + + destruct Hdvd as [c Hc]. + + assert (Hval : a ^ (r-1) = 1 + c * r) by lia. + rewrite Hval. rewrite Z_mod_plus_full. reflexivity. +Qed. + +Lemma exists_inv : forall r a, 1 < r -> rel_prime a r -> + exists u, (a * u) mod r = 1 mod r. +Proof. + intros r a Hr Hcop. + apply rel_prime_bezout in Hcop. destruct Hcop as [u v Huv]. + exists u. + assert (a * u = 1 - v * r) by lia. + rewrite H. rewrite Zminus_mod, Z_mod_mult, Z.sub_0_r, Zmod_mod. reflexivity. +Qed. + +Lemma pow_cong_one_sub : forall r a m k, 1 < r -> rel_prime a r -> + (0 <= k <= m) -> + a ^ m mod r = 1 mod r -> a ^ k mod r = 1 mod r -> + a ^ (m - k) mod r = 1 mod r. +Proof. + intros r a m k Hr Hcop Hkm Hm Hk. + + assert (Hsplit : a ^ m = a ^ k * a ^ (m - k)). + { rewrite <- Z.pow_add_r by lia. f_equal. lia. } + + assert (Hak : rel_prime (a ^ k) r). + { apply rel_prime_sym. apply rel_prime_Zpower_r; [lia | apply rel_prime_sym; exact Hcop]. } + destruct (exists_inv r (a ^ k) Hr Hak) as [u Hu]. + + assert (E : a ^ (m - k) mod r = ((a ^ k * u) * a ^ (m - k)) mod r). + { rewrite (Zmult_mod (a^k * u)). rewrite Hu. + rewrite (Z.mod_small 1 r) by lia. rewrite Z.mul_1_l, Zmod_mod. reflexivity. } + rewrite E. + + replace (a ^ k * u * a ^ (m - k)) with (u * (a ^ k * a ^ (m - k))) by ring. + rewrite <- Hsplit. + + rewrite Zmult_mod, Hm, (Z.mod_small 1 r) by lia. + rewrite Z.mul_1_r, Zmod_mod. + + rewrite Zmult_mod, Hk, (Z.mod_small 1 r) in Hu by lia. + rewrite Z.mul_1_l, Zmod_mod in Hu. exact Hu. +Qed. + +Lemma pow_cong_one_mul : forall r a k t, 1 < r -> 0 <= k -> 0 <= t -> + a ^ k mod r = 1 mod r -> a ^ (k * t) mod r = 1 mod r. +Proof. + intros r a k t Hr Hk Ht Hak. + rewrite Z.pow_mul_r by lia. + + rewrite Zpower_mod by lia. rewrite Hak. + rewrite <- Zpower_mod by lia. rewrite Z.pow_1_l by lia. + reflexivity. +Qed. + +Lemma pow_cong_one_gcd : forall r a, 1 < r -> rel_prime a r -> + forall N, (0 <= N) -> forall m k, 0 <= m -> 0 <= k -> (m + k <= N) -> + a ^ m mod r = 1 mod r -> a ^ k mod r = 1 mod r -> + a ^ (Z.gcd m k) mod r = 1 mod r. +Proof. + intros r a Hr Hcop N HN. pattern N. apply Z_lt_induction; [| exact HN]. + clear N HN. intros N IH m k Hm Hk Hmk Hpm Hpk. + destruct (Z.eq_dec k 0) as [Hk0|Hk0]. + - subst k. rewrite Z.gcd_0_r. rewrite Z.abs_eq by lia. exact Hpm. + - destruct (Z.eq_dec m 0) as [Hm0|Hm0]. + + subst m. rewrite Z.gcd_0_l. rewrite Z.abs_eq by lia. exact Hpk. + + destruct (Z.le_gt_cases k m) as [Hle|Hgt]. + * + assert (Hsub : a ^ (m - k) mod r = 1 mod r). + { apply pow_cong_one_sub; auto; lia. } + + assert (Hg : Z.gcd m k = Z.gcd (m - k) k). + { rewrite (Z.gcd_comm m k), (Z.gcd_comm (m-k) k). + symmetry. apply Z.gcd_sub_diag_r. } + rewrite Hg. apply (IH (m - k + k)); try lia; auto. + * + assert (Hsub : a ^ (k - m) mod r = 1 mod r). + { apply pow_cong_one_sub; auto; lia. } + assert (Hg : Z.gcd m k = Z.gcd m (k - m)). + { symmetry. apply Z.gcd_sub_diag_r. } + rewrite Hg. apply (IH (m + (k - m))); try lia; auto. +Qed. + +Lemma has_prime_divisor : forall n, 1 < n -> exists q, prime q /\ (q | n). +Proof. + intros n Hn0. assert (Hnn : 0 <= n) by lia. revert Hn0. + pattern n. apply Z_lt_induction; [| exact Hnn]. + clear n Hnn. intros n IH Hn. + destruct (prime_dec n) as [Hp|Hnp]. + - exists n; split; [exact Hp | apply Z.divide_refl]. + - destruct (not_prime_divide n Hn Hnp) as [d [Hd Hdvd]]. + destruct (IH d ltac:(lia) ltac:(lia)) as [q [Hq Hqd]]. + exists q; split; [exact Hq | apply Z.divide_trans with d; auto]. +Qed. + +Lemma pocklington_div : forall N r a, + prime r -> 1 < N -> rel_prime a r -> + a ^ (N - 1) mod r = 1 mod r -> + (forall q, prime q -> (q | (N - 1)) -> + a ^ ((N - 1) / q) mod r <> 1 mod r) -> + ((N - 1) | (r - 1)). +Proof. + intros N r a Hr HN Hcop Hferm Hno. + pose proof (prime_ge_2 _ Hr) as Hr2. + set (M := N - 1) in *. + assert (HM : 0 < M) by lia. + + pose proof (fermat_little r Hr a Hcop) as Hfr. + + set (g := Z.gcd M (r - 1)). + assert (Hg_dvd_M : (g | M)) by apply Z.gcd_divide_l. + assert (Hg_dvd_r1 : (g | (r - 1))) by apply Z.gcd_divide_r. + assert (Hgpos : 0 < g). + { assert (0 <= g) by apply Z.gcd_nonneg. + assert (g <> 0). { intro Hg0. apply Z.gcd_eq_0_l in Hg0. lia. } + lia. } + assert (Hr1 : 1 < r) by lia. + assert (Hag : a ^ g mod r = 1 mod r). + { apply (pow_cong_one_gcd r a Hr1 Hcop (M + (r-1))); try lia; auto. } + + assert (HgM : g = M). + { destruct (Z.eq_dec g M) as [He|Hne]; [exact He|]. + exfalso. + + assert (Hgle : g <= M) by (apply Z.divide_pos_le; auto; lia). + assert (Hquot : M = g * (M / g)) by (apply Zdivide_Zdiv_eq; auto). + assert (HMg1 : 1 < M / g). + { assert (M / g >= 1). + { apply Z.le_ge. apply Z.div_le_lower_bound; lia. } + destruct (Z.eq_dec (M / g) 1) as [E1|E1]. + - rewrite E1 in Hquot. lia. + - lia. } + destruct (has_prime_divisor (M / g) HMg1) as [q [Hq Hqdvd]]. + + assert (HqM : (q | M)). + { rewrite Hquot. apply Z.divide_mul_r; auto. } + + destruct Hqdvd as [c Hc]. + assert (HMq : M / q = g * c). + { + assert (HMval : M = (g * c) * q) by (rewrite Hquot, Hc; ring). + rewrite HMval. rewrite Z.div_mul by (pose proof (prime_ge_2 _ Hq); lia). reflexivity. } + assert (Hg_dvd_Mq : (g | (M / q))) by (rewrite HMq; apply Z.divide_factor_l). + + destruct Hg_dvd_Mq as [t Ht]. + pose proof (prime_ge_2 _ Hq) as Hq2. + assert (HMqpos : 0 <= M / q) by (apply Z.div_pos; lia). + assert (Htpos : 0 <= t) by nia. + assert (Hcontra : a ^ (M / q) mod r = 1 mod r). + { rewrite Ht. rewrite Z.mul_comm. apply pow_cong_one_mul; auto; lia. } + apply (Hno q Hq HqM). exact Hcontra. } + + rewrite <- HgM. exact Hg_dvd_r1. +Qed. + +Lemma pow_one_rel_prime : forall r a m, 1 < r -> 0 < m -> + a ^ m mod r = 1 mod r -> rel_prime a r. +Proof. + intros r a m Hr Hm Hpow. + + assert (Hsplit : a ^ m = a * a ^ (m - 1)). + { rewrite <- Z.pow_succ_r by lia. f_equal. lia. } + rewrite Hsplit in Hpow. + + assert (Hdvd : (r | a * a ^ (m-1) - 1)). + { apply Z.mod_divide; [lia|]. + rewrite Zminus_mod, Hpow, (Z.mod_small 1 r) by lia. + rewrite Z.sub_diag. reflexivity. } + destruct Hdvd as [c Hc]. + + apply bezout_rel_prime. + apply (Bezout_intro a r 1 (a ^ (m-1)) (- c)). lia. +Qed. + +Theorem pocklington_prime : forall N a, + 1 < N -> + a ^ (N - 1) mod N = 1 mod N -> + (forall q, prime q -> (q | (N - 1)) -> Z.gcd (a ^ ((N - 1) / q) - 1) N = 1) -> + prime N. +Proof. + intros N a HN Hferm Hgcd. + apply prime_alt. split; [exact HN|]. + intros n [Hn1 HnN] HndivN. + + destruct (has_prime_divisor n Hn1) as [r [Hr Hrn]]. + pose proof (prime_ge_2 _ Hr) as Hr2. + assert (HrN : (r | N)) by (apply Z.divide_trans with n; auto). + assert (HrleN : r <= n) by (apply Z.divide_pos_le; auto; lia). + + assert (HfermR : a ^ (N - 1) mod r = 1 mod r). + { + destruct HrN as [s Hs]. + assert (Hd : (r | a ^ (N-1) - 1)). + { apply Z.divide_trans with N; [exists s; lia|]. + apply Z.mod_divide; [lia|]. + rewrite Zminus_mod, Hferm, (Z.mod_small 1 N) by lia. + rewrite Z.sub_diag. reflexivity. } + destruct Hd as [c Hc]. + assert (Hav : a ^ (N-1) = 1 + c * r) by lia. + rewrite Hav, Z_mod_plus_full. reflexivity. } + assert (HcopR : rel_prime a r) by (apply (pow_one_rel_prime r a (N-1)); auto; lia). + assert (HnoR : forall q, prime q -> (q | (N - 1)) -> + a ^ ((N - 1) / q) mod r <> 1 mod r). + { intros q Hq Hqdvd Heq. + + assert (Hrdvd : (r | a ^ ((N-1)/q) - 1)). + { apply Z.mod_divide; [lia|]. + rewrite Zminus_mod, Heq, (Z.mod_small 1 r) by lia. + rewrite Z.sub_diag. reflexivity. } + pose proof (Hgcd q Hq Hqdvd) as Hg1. + assert (Hrgcd : (r | Z.gcd (a ^ ((N-1)/q) - 1) N)). + { apply Z.gcd_greatest; auto. } + rewrite Hg1 in Hrgcd. apply Z.divide_1_r in Hrgcd. lia. } + + pose proof (pocklington_div N r a Hr HN HcopR HfermR HnoR) as Hdvd. + assert (Hr1pos : 0 < r - 1) by lia. + assert (HleN1 : N - 1 <= r - 1) by (apply Z.divide_pos_le; auto; lia). + + lia. +Qed. + +Record PFactor := { pf_prime : Z; pf_pow : Z }. + +Fixpoint prod_pows (l : list PFactor) : Z := + match l with + | [] => 1 + | f :: tl => pf_pow f * prod_pows tl + end. + +Lemma prime_div_prod : forall (l : list PFactor) q, prime q -> + (q | prod_pows l) -> + exists f, In f l /\ (q | pf_pow f). +Proof. + induction l as [|f tl IH]; intros q Hq Hdvd; simpl in Hdvd. + - apply Z.divide_1_r in Hdvd. pose proof (prime_ge_2 _ Hq). lia. + - apply prime_mult in Hdvd; [| exact Hq]. + destruct Hdvd as [H1|H2]. + + exists f; split; [left; reflexivity | exact H1]. + + destruct (IH q Hq H2) as [f' [Hin Hdv]]. + exists f'; split; [right; exact Hin | exact Hdv]. +Qed. + +Lemma prime_div_primepow : forall p q e, prime p -> prime q -> + 0 <= e -> (q | p ^ e) -> q = p. +Proof. + intros p q e Hp Hq He Hdvd. + apply (prime_power_prime q p e); auto. +Qed. + +Definition wf_factor (f : PFactor) (e : Z) : Prop := + prime (pf_prime f) /\ 0 <= e /\ pf_pow f = (pf_prime f) ^ e. + +Theorem pocklington_prime_list : forall N a (L : list PFactor) (es : list Z), + 1 < N -> + N - 1 = prod_pows L -> + length es = length L -> + (forall i, (i < length L)%nat -> + wf_factor (nth i L {| pf_prime := 2; pf_pow := 2 |}) (nth i es 0)) -> + a ^ (N - 1) mod N = 1 mod N -> + (forall f, In f L -> Z.gcd (a ^ ((N - 1) / (pf_prime f)) - 1) N = 1) -> + prime N. +Proof. + intros N a L es HN Hprod Hlen Hwf Hferm Hgcd. + apply (pocklington_prime N a HN Hferm). + intros q Hq HqdvdM. + + rewrite Hprod in HqdvdM. + destruct (prime_div_prod L q Hq HqdvdM) as [f [Hin Hdvf]]. + + apply In_nth with (d := {| pf_prime := 2; pf_pow := 2 |}) in Hin. + destruct Hin as [i [Hi Hnth]]. + pose proof (Hwf i Hi) as Hwfi. unfold wf_factor in Hwfi. + rewrite Hnth in Hwfi. destruct Hwfi as [Hpp [He Hpow]]. + + rewrite Hpow in Hdvf. + assert (Hqeq : q = pf_prime f) by (apply (prime_div_primepow (pf_prime f) q (nth i es 0)); auto). + rewrite Hqeq. + apply Hgcd. rewrite <- Hnth. apply nth_In. exact Hi. +Qed. + +Lemma zpow_mod_eq : forall a e N, N <> 0 -> 0 <= e -> + Zpow_mod a e N = a ^ e mod N. +Proof. intros. apply Zpow_mod_correct; auto. Qed. + +Lemma gcd_sub1_mod : forall x N, N <> 0 -> + Z.gcd (x - 1) N = Z.gcd (x mod N - 1) N. +Proof. + intros x N HN. + assert (Hx : x - 1 = (x mod N - 1) + (x / N) * N). + { rewrite (Z.div_mod x N HN) at 1. ring. } + rewrite Hx. + rewrite Z.gcd_comm. rewrite Z.gcd_add_mult_diag_r. rewrite Z.gcd_comm. + reflexivity. +Qed. + +Lemma gcd_pow_bridge : forall a e N, N <> 0 -> 0 <= e -> + Z.gcd ((Zpow_mod a e N) - 1) N = 1 -> + Z.gcd (a ^ e - 1) N = 1. +Proof. + intros a e N HN He H. + rewrite zpow_mod_eq in H by auto. + rewrite (gcd_sub1_mod (a ^ e) N HN). exact H. +Qed. + +Lemma fermat_from_zpow : forall a N, 1 < N -> + Zpow_mod a (N - 1) N = 1 -> + a ^ (N - 1) mod N = 1 mod N. +Proof. + intros a N HN H. rewrite zpow_mod_eq in H by lia. + rewrite H, (Z.mod_small 1 N) by lia. reflexivity. +Qed. + +Theorem pocklington_prime_compute : + forall N a (L : list PFactor) (es : list Z), + 1 < N -> + N - 1 = prod_pows L -> + length es = length L -> + (forall i, (i < length L)%nat -> + wf_factor (nth i L {| pf_prime := 2; pf_pow := 2 |}) (nth i es 0)) -> + Zpow_mod a (N - 1) N = 1 -> + (forall f, In f L -> Z.gcd ((Zpow_mod a ((N - 1) / (pf_prime f)) N) - 1) N = 1) -> + prime N. +Proof. + intros N a L es HN Hprod Hlen Hwf Hferm Hgcd. + apply (pocklington_prime_list N a L es HN Hprod Hlen Hwf). + - apply fermat_from_zpow; auto. + - intros f Hin. + pose proof (Hgcd f Hin) as Hg. + apply gcd_pow_bridge; [lia | | exact Hg]. + + apply In_nth with (d := {| pf_prime := 2; pf_pow := 2 |}) in Hin. + destruct Hin as [i [Hi Hnth]]. + pose proof (Hwf i Hi) as Hwfi. unfold wf_factor in Hwfi. + rewrite Hnth in Hwfi. destruct Hwfi as [Hpp _]. + pose proof (prime_ge_2 _ Hpp) as Hp2. + apply Z.div_pos; lia. +Qed. + +Open Scope Z_scope. + +Fixpoint nodiv (p : Z) (d : Z) (fuel : nat) : bool := + match fuel with + | O => true + | S f => + if Z.ltb p (d * d) then true + else if Z.eqb (Z.modulo p d) 0 then false + else nodiv p (d + 1) f + end. + +Definition prime_test (p : Z) : bool := + if Z.leb p 1 then false else nodiv p 2 (S (Z.to_nat (Z.sqrt p))). + +Lemma nodiv_sound : forall fuel p d, + 2 <= d -> + nodiv p d fuel = true -> + forall k, d <= k -> k * k <= p -> (k - d < Z.of_nat fuel) -> ~ (k | p). +Proof. + induction fuel as [|f IH]; intros p d Hd Hnodiv k Hdk Hkk Hfuel. + - simpl in Hfuel. lia. + - simpl in Hnodiv. + destruct (Z.ltb p (d * d)) eqn:Hlt. + + + apply Z.ltb_lt in Hlt. nia. + + apply Z.ltb_ge in Hlt. + destruct (Z.eqb (p mod d) 0) eqn:Hmod. + * discriminate. + * apply Z.eqb_neq in Hmod. + + destruct (Z.eq_dec k d) as [He|Hne]. + -- subst k. intro Hdvd. apply Hmod. apply Z.mod_divide; [lia | exact Hdvd]. + -- + apply (IH p (d + 1)); try lia. + exact Hnodiv. +Qed. + +Lemma no_small_div_prime : forall p, 2 <= p -> + (forall k, 2 <= k -> k * k <= p -> ~ (k | p)) -> prime p. +Proof. + intros p Hp Hnd. apply prime_alt. split; [lia|]. + intros n [Hn1 HnP] HndvdN. + + assert (Hpn : p = n * (p / n)). + { apply Zdivide_Zdiv_eq; [lia | exact HndvdN]. } + set (m := p / n) in *. + assert (Hm2 : 2 <= m). + { assert (0 < m). { unfold m. apply Z.div_str_pos; lia. } + destruct (Z.eq_dec m 1) as [E|E]; [ rewrite E in Hpn; lia | lia ]. } + destruct (Z.le_gt_cases (n * n) p) as [Hle|Hgt]. + - apply (Hnd n); [lia | exact Hle | exact HndvdN]. + - + assert (Hmlt : m < n) by nia. + assert (Hmm : m * m <= p) by nia. + apply (Hnd m); [lia | exact Hmm |]. + rewrite Hpn. apply Z.divide_factor_r. +Qed. + +Lemma prime_test_sound : forall p, prime_test p = true -> prime p. +Proof. + intros p Hpt. unfold prime_test in Hpt. + destruct (Z.leb p 1) eqn:Hle1; [discriminate|]. + apply Z.leb_gt in Hle1. + apply no_small_div_prime; [lia|]. + intros k Hk2 Hkk. + apply (nodiv_sound (S (Z.to_nat (Z.sqrt p))) p 2); auto. + - lia. + - + rewrite Nat2Z.inj_succ, Z2Nat.id by (apply Z.sqrt_nonneg). + + assert (Hksqrt : k <= Z.sqrt p). + { apply (Z.sqrt_le_square p k); [lia | lia | exact Hkk]. } + pose proof (Z.sqrt_nonneg p). lia. +Qed. + +Ltac prove_prime_small := apply prime_test_sound; vm_compute; reflexivity. + +Open Scope Z_scope. + +Ltac wf_slot lem := split; [ apply lem | split; [ cbn; lia | vm_compute; reflexivity ] ]. + +Lemma prime_463 : prime 463. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_89 : prime 89. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_14923 : prime 14923. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_417677162933 : prime 417677162933. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_539204044132271846773 : prime 539204044132271846773. +Proof. + apply (pocklington_prime_compute 539204044132271846773 5 + [ {| pf_prime := 2; pf_pow := 4 |} ; {| pf_prime := 3; pf_pow := 243 |} ; {| pf_prime := 89; pf_pow := 89 |} ; {| pf_prime := 14923; pf_pow := 14923 |} ; {| pf_prime := 417677162933; pf_pow := 417677162933 |} ] + [2;5;1;1;1]). + - lia. + - vm_compute; reflexivity. + - reflexivity. + - intros i Hi; simpl in Hi; + (destruct i as [|i]; [ wf_slot prime_2 |]); + (destruct i as [|i]; [ wf_slot prime_3 |]); + (destruct i as [|i]; [ wf_slot prime_89 |]); + (destruct i as [|i]; [ wf_slot prime_14923 |]); + (destruct i as [|i]; [ wf_slot prime_417677162933 |]); + lia. + - vm_compute; reflexivity. + - intros f Hf; simpl in Hf; + repeat (destruct Hf as [<-|Hf]; [ vm_compute; reflexivity |]); + destruct Hf. +Qed. + +Lemma prime_11 : prime 11. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_2531 : prime 2531. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_115603 : prime 115603. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_1197907 : prime 1197907. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_22160661629 : prime 22160661629. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_509 : prime 509. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_413527 : prime 413527. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_772231 : prime 772231. +Proof. apply prime_test_sound; vm_compute; reflexivity. Qed. + +Lemma prime_325086459374267 : prime 325086459374267. +Proof. + apply (pocklington_prime_compute 325086459374267 2 + [ {| pf_prime := 2; pf_pow := 2 |} ; {| pf_prime := 509; pf_pow := 509 |} ; {| pf_prime := 413527; pf_pow := 413527 |} ; {| pf_prime := 772231; pf_pow := 772231 |} ] + [1;1;1;1]). + - lia. + - vm_compute; reflexivity. + - reflexivity. + - intros i Hi; simpl in Hi; + (destruct i as [|i]; [ wf_slot prime_2 |]); + (destruct i as [|i]; [ wf_slot prime_509 |]); + (destruct i as [|i]; [ wf_slot prime_413527 |]); + (destruct i as [|i]; [ wf_slot prime_772231 |]); + lia. + - vm_compute; reflexivity. + - intros f Hf; simpl in Hf; + repeat (destruct Hf as [<-|Hf]; [ vm_compute; reflexivity |]); + destruct Hf. +Qed. + +Lemma prime_8999194758858563409123804352480028797519453 : prime 8999194758858563409123804352480028797519453. +Proof. + apply (pocklington_prime_compute 8999194758858563409123804352480028797519453 2 + [ {| pf_prime := 2; pf_pow := 4 |} ; {| pf_prime := 3; pf_pow := 81 |} ; {| pf_prime := 11; pf_pow := 11 |} ; {| pf_prime := 2531; pf_pow := 2531 |} ; {| pf_prime := 115603; pf_pow := 115603 |} ; {| pf_prime := 1197907; pf_pow := 1197907 |} ; {| pf_prime := 22160661629; pf_pow := 22160661629 |} ; {| pf_prime := 325086459374267; pf_pow := 325086459374267 |} ] + [2;4;1;1;1;1;1;1]). + - lia. + - vm_compute; reflexivity. + - reflexivity. + - intros i Hi; simpl in Hi; + (destruct i as [|i]; [ wf_slot prime_2 |]); + (destruct i as [|i]; [ wf_slot prime_3 |]); + (destruct i as [|i]; [ wf_slot prime_11 |]); + (destruct i as [|i]; [ wf_slot prime_2531 |]); + (destruct i as [|i]; [ wf_slot prime_115603 |]); + (destruct i as [|i]; [ wf_slot prime_1197907 |]); + (destruct i as [|i]; [ wf_slot prime_22160661629 |]); + (destruct i as [|i]; [ wf_slot prime_325086459374267 |]); + lia. + - vm_compute; reflexivity. + - intros f Hf; simpl in Hf; + repeat (destruct Hf as [<-|Hf]; [ vm_compute; reflexivity |]); + destruct Hf. +Qed. + +Lemma prime_28948022309329048855892746252171976963363056481941560715954676764349967630337 : prime 28948022309329048855892746252171976963363056481941560715954676764349967630337. +Proof. + apply (pocklington_prime_compute 28948022309329048855892746252171976963363056481941560715954676764349967630337 5 + [ {| pf_prime := 2; pf_pow := 4294967296 |} ; {| pf_prime := 3; pf_pow := 3 |} ; {| pf_prime := 463; pf_pow := 463 |} ; {| pf_prime := 539204044132271846773; pf_pow := 539204044132271846773 |} ; {| pf_prime := 8999194758858563409123804352480028797519453; pf_pow := 8999194758858563409123804352480028797519453 |} ] + [32;1;1;1;1]). + - lia. + - vm_compute; reflexivity. + - reflexivity. + - intros i Hi; simpl in Hi; + (destruct i as [|i]; [ wf_slot prime_2 |]); + (destruct i as [|i]; [ wf_slot prime_3 |]); + (destruct i as [|i]; [ wf_slot prime_463 |]); + (destruct i as [|i]; [ wf_slot prime_539204044132271846773 |]); + (destruct i as [|i]; [ wf_slot prime_8999194758858563409123804352480028797519453 |]); + lia. + - vm_compute; reflexivity. + - intros f Hf; simpl in Hf; + repeat (destruct Hf as [<-|Hf]; [ vm_compute; reflexivity |]); + destruct Hf. +Qed. + +Definition pasta_p : Z := 28948022309329048855892746252171976963363056481941560715954676764349967630337. +Lemma pasta_prime : prime pasta_p. Proof. unfold pasta_p. exact prime_28948022309329048855892746252171976963363056481941560715954676764349967630337. Qed. + +Lemma pasta_nowrap : 2 ^ 64 <= pasta_p. +Proof. unfold pasta_p. lia. Qed. + +Definition range_tail_sound_field_pasta := range_tail_sound_field pasta_p pasta_prime. + +Definition e_zero : Env Z := fun _ => Some 0. +Lemma e_zero_get : forall w, e_zero w = Some 0. Proof. reflexivity. Qed. + +Lemma nv_zero_sat_gen : forall n t base (e : Env Z), + (forall w, e w = Some 0) -> + (t < base)%nat -> + satisfies (zp pasta_p) [] e (range_tail t base n). +Proof. + induction n as [|m IH]; intros t base e He Hlt; simpl. + - eapply Sat_Eq; cbn [eval_poly]; rewrite ?He; reflexivity. + - apply Sat_Exists with (w := 0). + apply Sat_Exists with (w := 0). + set (e2 := env_extend (env_extend e base 0) (S base) 0). + assert (He2 : forall w, e2 w = Some 0). + { intro w. unfold e2, env_extend. + destruct (Nat.eqb (S base) w); [reflexivity|]. + destruct (Nat.eqb base w); [reflexivity| apply He]. } + apply Sat_And. + + eapply Sat_Eq; cbn [eval_poly]; rewrite ?He2; reflexivity. + + apply Sat_And. + * eapply Sat_Eq; cbn [eval_poly]; rewrite ?He2; reflexivity. + * apply IH; [exact He2 | lia]. +Qed. + +Lemma nv_zero_sat : forall n t base, + (t < base)%nat -> + satisfies (zp pasta_p) [] e_zero (range_tail t base n). +Proof. intros. apply nv_zero_sat_gen; [apply e_zero_get | exact H]. Qed. + +Lemma nv_pasta_64 : 0 <= (0 mod pasta_p) < 2 ^ (Z.of_nat 64). +Proof. + apply (range_tail_sound_field_pasta 64%nat 0%nat 1%nat e_zero 0). + - change (Z.of_nat 64) with 64. apply pasta_nowrap. + - lia. + - apply e_zero_get. + - apply nv_zero_sat. lia. +Qed. + +Lemma nv_pasta_64_boundary : 0 <= ((2 ^ 64 - 1) mod pasta_p) < 2 ^ (Z.of_nat 64). +Proof. + pose proof pasta_nowrap as Hp. + assert (Hmod : (2 ^ 64 - 1) mod pasta_p = 2 ^ 64 - 1) by (apply Z.mod_small; lia). + rewrite Hmod. change (Z.of_nat 64) with 64. lia. +Qed. + +Print Assumptions range_tail_sound_field_pasta. +Print Assumptions nv_pasta_64. +Print Assumptions nv_pasta_64_boundary. diff --git a/coq-legacy/spec/bm_rule.v b/coq-legacy/spec/bm_rule.v new file mode 100644 index 0000000..55b08f4 --- /dev/null +++ b/coq-legacy/spec/bm_rule.v @@ -0,0 +1,182 @@ +(* SPDX-License-Identifier: Apache-2.0 + SPDX-FileCopyrightText: 2026 Next Ridge Solutions Ltd + + The rule for BigMult at four limbs of 64 bits: the input assumption PRE_bm (a and b each have exactly + 4 limbs, each in [0, 2^64)), the relation REL_bm (out has exactly 8 limbs, each in [0, 2^64), and the + value of out is the value of a times the value of b), and `adequate`: under the input assumption, a + circuit accepts exactly the triples the relation accepts. Checked examples follow: triples the relation + accepts, triples it rejects (a wrong product, an output limb out of range), and an input the assumption + rejects (a 65-bit limb). + + Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) + +From Coq Require Import ZArith List. +Import ListNotations. +Open Scope Z_scope. + +Definition N_BITS : Z := 64. +Definition K : nat := 4. +Definition B : Z := 2 ^ N_BITS. + +Definition VAL (v : list Z) : Z := fold_right (fun x acc => x + B * acc) 0 v. + +Definition limb_ok (x : Z) : Prop := 0 <= x < B. + +(* The input assumption: a and b have exactly 4 limbs, each in [0, 2^64). A hypothesis of the + theorems; the circuit does not check it. *) +Definition PRE_bm (a b : list Z) : Prop := + length a = K /\ length b = K /\ Forall limb_ok a /\ Forall limb_ok b. + +(* The relation: out has exactly 8 limbs, each in [0, 2^64), and its value is the product of the + input values, as an equality of integers (not modulo anything). *) +Definition REL_bm (a b out : list Z) : Prop := + length out = (2 * K)%nat /\ Forall limb_ok out /\ VAL out = VAL a * VAL b. + +(* Adequacy: for inputs satisfying the input assumption, acceptance and the relation coincide. *) +Definition adequate (accepts : list Z -> list Z -> list Z -> Prop) : Prop := + forall a b out, PRE_bm a b -> (accepts a b out <-> REL_bm a b out). + +From Coq Require Import Lia. + +Lemma N_BITS_val : N_BITS = 64. Proof. reflexivity. Qed. +Lemma K_val : K = 4%nat. Proof. reflexivity. Qed. + +Lemma B_value : B = 18446744073709551616. +Proof. unfold B, N_BITS. vm_compute. reflexivity. Qed. + +Lemma B_pos : 0 < B. +Proof. rewrite B_value. lia. Qed. + +Lemma VAL_nil : VAL [] = 0. Proof. reflexivity. Qed. +Lemma VAL_cons : forall x t, VAL (x :: t) = x + B * VAL t. Proof. reflexivity. Qed. + +Lemma VAL_firstn_skipn : forall n v, + VAL v = VAL (firstn n v) + B ^ Z.of_nat n * VAL (skipn n v). +Proof. + induction n as [|n IH]; intro v. + - cbn [firstn skipn Z.of_nat]. rewrite Z.pow_0_r, VAL_nil. ring. + - destruct v as [|x t]. + + cbn [firstn skipn]. rewrite VAL_nil. ring. + + cbn [firstn skipn]. rewrite !VAL_cons, (IH t). + rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. ring. +Qed. + +Lemma B_pow_nonzero : forall n, B ^ Z.of_nat n <> 0. +Proof. intro n. apply Z.pow_nonzero; [ rewrite B_value; lia | lia ]. Qed. + +Theorem VAL_product_is_the_convolution : forall a0 a1 a2 a3 b0 b1 b2 b3, + VAL [a0; a1; a2; a3] * VAL [b0; b1; b2; b3] + = VAL [a0 * b0; a0 * b1 + a1 * b0; a0 * b2 + a1 * b1 + a2 * b0; + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; a1 * b3 + a2 * b2 + a3 * b1; + a2 * b3 + a3 * b2; a3 * b3]. +Proof. intros. unfold VAL. cbn [fold_right]. ring. Qed. + +Lemma VAL_bound : forall v, Forall limb_ok v -> + 0 <= VAL v < B ^ Z.of_nat (length v). +Proof. + induction v as [|x t IH]; intro Hf. + - cbn. lia. + - inversion Hf as [|? ? Hx Ht]; subst. unfold limb_ok in Hx. + specialize (IH Ht). rewrite VAL_cons. cbn [length]. + rewrite Nat2Z.inj_succ, Z.pow_succ_r by lia. + pose proof B_pos. nia. +Qed. + +Theorem PRE_product_fits_2K_limbs : forall a b, + PRE_bm a b -> 0 <= VAL a * VAL b < B ^ 8. +Proof. + intros a b [Hla [Hlb [Ha Hb]]]. + pose proof (VAL_bound a Ha) as HA. pose proof (VAL_bound b Hb) as HB. + rewrite Hla in HA. rewrite Hlb in HB. unfold K in *. + + change (Z.of_nat 4) with 4 in HA, HB. + change (B ^ 8) with (B ^ 4 * B ^ 4). + split; [ nia | ]. + apply Z.mul_lt_mono_nonneg; lia. +Qed. + +Example rel_anchor : REL_bm [2^64-1;0;0;0] [2^64-1;0;0;0] [1;2^64-2;0;0;0;0;0;0]. +Proof. unfold REL_bm, limb_ok, B, N_BITS, K. split; [reflexivity|split]. + - repeat constructor; vm_compute; congruence. + - vm_compute. reflexivity. Qed. +Example rel_fraud : ~ REL_bm [2^64-1;0;0;0] [2^64-1;0;0;0] [1;2^64-1;0;0;0;0;0;0]. +Proof. unfold REL_bm. intros [_ [_ H]]. vm_compute in H. discriminate. Qed. + +Example top : VAL [2^64-1;2^64-1;2^64-1;2^64-1] * VAL [2^64-1;2^64-1;2^64-1;2^64-1] < B ^ 8. +Proof. apply Z.ltb_lt. vm_compute. reflexivity. Qed. + +Lemma carry_step_bound : forall c r, + 0 <= c <= 4 * (B - 1) ^ 2 -> 0 <= r <= 4 * (B - 1) -> 0 <= (c + r) / B <= 4 * (B - 1). +Proof. + intros c r Hc Hr. assert (HB : 0 < B) by (unfold B, N_BITS; lia). + split. - apply Z.div_pos; lia. + - apply Z.div_le_upper_bound; [lia|]. nia. +Qed. +Example carry_fits_67 : 4 * (B - 1) < 2 ^ 66 /\ 2 ^ 66 < 2 ^ 67. +Proof. unfold B, N_BITS. split; apply Z.ltb_lt; vm_compute; reflexivity. Qed. +Example coef_bound : 4 * (B - 1) ^ 2 < 2 ^ 130. +Proof. unfold B, N_BITS. apply Z.ltb_lt; vm_compute; reflexivity. Qed. + +Ltac limbs := repeat (apply Forall_cons; [ unfold limb_ok; rewrite B_value; lia | ]); apply Forall_nil. +Ltac pre_row := split; [reflexivity|]; split; [reflexivity|]; split; limbs. +Ltac rel_row := split; [reflexivity|]; split; [limbs|]; vm_compute; reflexivity. + +Definition DIAG_A : list Z := [2^64-1; 0; 0; 0]. +Definition DIAG_OUT : list Z := [1; 2^64-2; 0; 0; 0; 0; 0; 0]. +Example diag_row_pre : PRE_bm DIAG_A DIAG_A. Proof. unfold DIAG_A. pre_row. Qed. +Example diag_row_rel : REL_bm DIAG_A DIAG_A DIAG_OUT. +Proof. unfold DIAG_A, DIAG_OUT. rel_row. Qed. + +Definition CORNER : list Z := [2^64-1; 2^64-1; 2^64-1; 2^64-1]. +Definition CORNER_OUT : list Z := [1; 0; 0; 0; 2^64-2; 2^64-1; 2^64-1; 2^64-1]. +Example corner_pre : PRE_bm CORNER CORNER. Proof. unfold CORNER. pre_row. Qed. +Example corner_rel : REL_bm CORNER CORNER CORNER_OUT. +Proof. unfold CORNER, CORNER_OUT. rel_row. Qed. + +Definition CORNER_FRAUD : list Z := [1; 0; 0; 0; 2^64-2; 2^64-1; 2^64-2; 2^64-1]. +Example corner_fraud_refused : ~ REL_bm CORNER CORNER CORNER_FRAUD. +Proof. intros [_ [_ H]]. vm_compute in H. discriminate. Qed. +Example wrong_product_refused : ~ REL_bm DIAG_A DIAG_A CORNER_OUT. +Proof. intros [_ [_ H]]. vm_compute in H. discriminate. Qed. + +Definition DIAG_OUT_WIDE : list Z := [2^64+1; 2^64-3; 0; 0; 0; 0; 0; 0]. +Example wide_out_val_equal : VAL DIAG_OUT_WIDE = VAL DIAG_A * VAL DIAG_A. +Proof. vm_compute. reflexivity. Qed. +Example wide_out_refused : ~ REL_bm DIAG_A DIAG_A DIAG_OUT_WIDE. +Proof. + intros [_ [H _]]. inversion H as [|? ? Hx _]; subst. unfold limb_ok in Hx. + rewrite B_value in Hx. lia. +Qed. + +Example pre_refuses_a_65_bit_limb : ~ PRE_bm [2^64; 0; 0; 0] [1; 0; 0; 0]. +Proof. + intros [_ [_ [Ha _]]]. inversion Ha as [|? ? Hx _]; subst. unfold limb_ok in Hx. + rewrite B_value in Hx. lia. +Qed. + +Print Assumptions N_BITS_val. +Print Assumptions K_val. +Print Assumptions B_value. +Print Assumptions B_pos. +Print Assumptions VAL_nil. +Print Assumptions VAL_cons. +Print Assumptions VAL_firstn_skipn. +Print Assumptions B_pow_nonzero. +Print Assumptions VAL_product_is_the_convolution. +Print Assumptions VAL_bound. +Print Assumptions PRE_product_fits_2K_limbs. +Print Assumptions rel_anchor. +Print Assumptions rel_fraud. +Print Assumptions top. +Print Assumptions carry_step_bound. +Print Assumptions carry_fits_67. +Print Assumptions coef_bound. +Print Assumptions diag_row_pre. +Print Assumptions diag_row_rel. +Print Assumptions corner_pre. +Print Assumptions corner_rel. +Print Assumptions corner_fraud_refused. +Print Assumptions wrong_product_refused. +Print Assumptions wide_out_val_equal. +Print Assumptions wide_out_refused. +Print Assumptions pre_refuses_a_65_bit_limb. diff --git a/coq/constraints/bits_kit.v b/coq/constraints/bits_kit.v index 7ecc176..eaef4f2 100644 --- a/coq/constraints/bits_kit.v +++ b/coq/constraints/bits_kit.v @@ -6,7 +6,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List Znumtheory Zpow_facts. +From Stdlib Require Import ZArith Lia List Znumtheory Zpow_facts. Import ListNotations. Open Scope Z_scope. Require Import Constraints.field_order_lift. diff --git a/coq/constraints/bm_adequacy.v b/coq/constraints/bm_adequacy.v index 611e28d..34214fb 100644 --- a/coq/constraints/bm_adequacy.v +++ b/coq/constraints/bm_adequacy.v @@ -7,7 +7,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +From Stdlib Require Import ZArith Lia List Znumtheory. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. diff --git a/coq/constraints/bm_model_facts.v b/coq/constraints/bm_model_facts.v index 4983d34..d8586ae 100644 --- a/coq/constraints/bm_model_facts.v +++ b/coq/constraints/bm_model_facts.v @@ -9,7 +9,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +From Stdlib Require Import ZArith Lia List Znumtheory. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. diff --git a/coq/constraints/bm_semantic.v b/coq/constraints/bm_semantic.v index d5056ca..181e6d2 100644 --- a/coq/constraints/bm_semantic.v +++ b/coq/constraints/bm_semantic.v @@ -10,7 +10,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +From Stdlib Require Import ZArith Lia List Znumtheory. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. diff --git a/coq/constraints/bm_soundness.v b/coq/constraints/bm_soundness.v index d910b4b..e04fa7c 100644 --- a/coq/constraints/bm_soundness.v +++ b/coq/constraints/bm_soundness.v @@ -8,7 +8,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List Znumtheory. Import ListNotations. +From Stdlib Require Import ZArith Lia List Znumtheory. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. diff --git a/coq/constraints/field_order_lift.v b/coq/constraints/field_order_lift.v index 1d62089..7081a54 100644 --- a/coq/constraints/field_order_lift.v +++ b/coq/constraints/field_order_lift.v @@ -7,7 +7,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia. Open Scope Z_scope. +From Stdlib Require Import ZArith Lia. Open Scope Z_scope. Require Import Constraints.range_field_pasta. Section OrderLift. diff --git a/coq/constraints/gen/bm_model_gen.v b/coq/constraints/gen/bm_model_gen.v index 51bc22b..5897c4b 100644 --- a/coq/constraints/gen/bm_model_gen.v +++ b/coq/constraints/gen/bm_model_gen.v @@ -6,7 +6,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith List. Import ListNotations. Open Scope Z_scope. +From Stdlib Require Import ZArith List. Import ListNotations. Open Scope Z_scope. Definition Cell := (nat * nat)%type. Inductive Expr := EConst (_:Z) | ECell (_:Cell) | EAdd (_ _:Expr) | ESub (_ _:Expr) | EMul (_ _:Expr) | ENeg (_:Expr) | EScaled (_:Expr) (_:Z). diff --git a/coq/constraints/gen/bm_necessity_gen.v b/coq/constraints/gen/bm_necessity_gen.v index ff9d896..884a3c0 100644 --- a/coq/constraints/gen/bm_necessity_gen.v +++ b/coq/constraints/gen/bm_necessity_gen.v @@ -7,7 +7,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. +From Stdlib Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. Require Import Generated.bm_wires_gen. Require Import Generated.bm_scaffold_gen. diff --git a/coq/constraints/gen/bm_scaffold_gen.v b/coq/constraints/gen/bm_scaffold_gen.v index 2812f44..d8e5690 100644 --- a/coq/constraints/gen/bm_scaffold_gen.v +++ b/coq/constraints/gen/bm_scaffold_gen.v @@ -8,7 +8,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. +From Stdlib Require Import ZArith List Lia. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. Require Import Generated.bm_wires_gen. diff --git a/coq/constraints/gen/bm_wires_gen.v b/coq/constraints/gen/bm_wires_gen.v index 182fe1c..ca74d58 100644 --- a/coq/constraints/gen/bm_wires_gen.v +++ b/coq/constraints/gen/bm_wires_gen.v @@ -5,7 +5,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith List. Import ListNotations. Open Scope Z_scope. +From Stdlib Require Import ZArith List. Import ListNotations. Open Scope Z_scope. Require Import Generated.bm_model_gen. Definition wcopy_1 : Cell * Cell := ((8%nat, 0%nat), (2000%nat, 0%nat)). diff --git a/coq/constraints/pfcs.v b/coq/constraints/pfcs.v index 32b562b..46c4283 100644 --- a/coq/constraints/pfcs.v +++ b/coq/constraints/pfcs.v @@ -7,9 +7,9 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import Init.Datatypes. -From Coq Require Import Lists.List. -From Coq Require Import Arith.PeanoNat. +From Stdlib Require Import Init.Datatypes. +From Stdlib Require Import Lists.List. +From Stdlib Require Import Arith.PeanoNat. Import ListNotations. diff --git a/coq/constraints/range_field.v b/coq/constraints/range_field.v index cbdbb51..ed60690 100644 --- a/coq/constraints/range_field.v +++ b/coq/constraints/range_field.v @@ -7,7 +7,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List String Znumtheory. +From Stdlib Require Import ZArith Lia List String Znumtheory. Import ListNotations. From Constraints Require Import pfcs. Open Scope Z_scope. diff --git a/coq/constraints/range_field_pasta.v b/coq/constraints/range_field_pasta.v index 852d24b..7640128 100644 --- a/coq/constraints/range_field_pasta.v +++ b/coq/constraints/range_field_pasta.v @@ -6,14 +6,14 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith Lia List String Znumtheory. +From Stdlib Require Import ZArith Lia List String Znumtheory. Import ListNotations. Open Scope Z_scope. From Constraints Require Import pfcs range_field. -Require Import Coq.Arith.Arith Coq.ZArith.Zpow_facts. +Require Import Stdlib.Arith.Arith Stdlib.ZArith.Zpow_facts. -From Coq Require Import ZArith Lia List Arith. +From Stdlib Require Import ZArith Lia List Arith. Import ListNotations. Open Scope nat_scope. @@ -101,7 +101,7 @@ Proof. rewrite <- seq_S. fold (bsum x n). rewrite Hbs. ring. Qed. -From Coq Require Import Znumtheory Zpow_facts. +From Stdlib Require Import Znumtheory Zpow_facts. Lemma binom_n_n n : binom n n = 1%nat. Proof. diff --git a/coq/spec/bm_rule.v b/coq/spec/bm_rule.v index 55b08f4..243ad79 100644 --- a/coq/spec/bm_rule.v +++ b/coq/spec/bm_rule.v @@ -10,7 +10,7 @@ Scope: these results bind the formal (Coq) layer only; the generated constraint model's fidelity to the circuit implementation, and the implementation itself, are outside them. *) -From Coq Require Import ZArith List. +From Stdlib Require Import ZArith List. Import ListNotations. Open Scope Z_scope. @@ -36,7 +36,7 @@ Definition REL_bm (a b out : list Z) : Prop := Definition adequate (accepts : list Z -> list Z -> list Z -> Prop) : Prop := forall a b out, PRE_bm a b -> (accepts a b out <-> REL_bm a b out). -From Coq Require Import Lia. +From Stdlib Require Import Lia. Lemma N_BITS_val : N_BITS = 64. Proof. reflexivity. Qed. Lemma K_val : K = 4%nat. Proof. reflexivity. Qed.