From c131ec39e9d1a99cb3550a0015078835a57b4a78 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Tue, 8 Sep 2026 16:05:15 +0100 Subject: [PATCH 1/9] asm: transcribe pasta_curves' AArch64 Pasta Montgomery routines zcash/pasta_curves#100 vendors Semolina v0.1.4's AArch64 Montgomery multiplication, squaring, and conversion for the Pasta fields. This adds the groundwork for proving those routines correct here. - `CompElliptic/Asm/AArch64/Semantics.lean`: the dozen instructions the file uses (`mul`, `umulh`, the `adds`/`adcs`/`adc` and `subs`/`sbcs` carry chains, `lsl`/`lsr`, `csel` on `lo`) as functions on natural numbers reduced modulo 2^64, so that the vectors are kernel-checkable with `decide` and the carry arithmetic stays in `omega`'s fragment. - `scripts/gen_aarch64_pasta_mul.py` generates `PastaMul.lean` from the vendored `.S`, one `let` per instruction with the instruction as a comment. Loads and stores become limb reads and result bindings; the stack frame and the return address are outside the model, and the script checks that no instruction reads a register it does not model. Loads the routines never read (`p[2]`, and `p[3]` in the helper) are left as comments: the code hard-codes `p[2] = 0` and `p[3] = 2^62`. - `PastaMulVectors.lean`: 1052 outputs of the real routines (pasta_curves 8ad85e9fab7929f6236960e472f432a4bd9ccd74 on an Apple M-series machine) on boundary, random canonical, and unreduced operands, each checked against the transcription by the kernel. They pass in about five seconds. - `scripts/check_aarch64_pasta_mul.sh`, run by CI: the vendored assembly and vectors match their recorded hashes, and regeneration reproduces the committed Lean files. - `design/aarch64-pasta-mul-verification.md`: the trust story, the operand contracts, and the theorems to be stated. Only the vectors are proved here. Co-authored-by: Claude Fable 5.1 --- .github/workflows/ci.yml | 4 + CompElliptic/Asm/AArch64/PastaMul.lean | 590 ++ CompElliptic/Asm/AArch64/PastaMulVectors.lean | 8392 +++++++++++++++++ CompElliptic/Asm/AArch64/Semantics.lean | 84 + CompElliptic/Asm/AArch64/vendor/SHA256SUMS | 2 + .../vendor/pasta_mul-armv8-vectors.txt | 1052 +++ .../Asm/AArch64/vendor/pasta_mul-armv8.S | 474 + README.md | 6 +- design/aarch64-pasta-mul-verification.md | 108 + scripts/check_aarch64_pasta_mul.sh | 15 + scripts/gen_aarch64_pasta_mul.py | 429 + 11 files changed, 11155 insertions(+), 1 deletion(-) create mode 100644 CompElliptic/Asm/AArch64/PastaMul.lean create mode 100644 CompElliptic/Asm/AArch64/PastaMulVectors.lean create mode 100644 CompElliptic/Asm/AArch64/Semantics.lean create mode 100644 CompElliptic/Asm/AArch64/vendor/SHA256SUMS create mode 100644 CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt create mode 100644 CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S create mode 100644 design/aarch64-pasta-mul-verification.md create mode 100755 scripts/check_aarch64_pasta_mul.sh create mode 100755 scripts/gen_aarch64_pasta_mul.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2f5756..fb55e25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,6 +72,10 @@ jobs: python3 scripts/gen_jubjub.py > CompElliptic/Fields/Jubjub.lean - name: Fail if the regenerated files differ from the committed ones run: git diff --exit-code CompElliptic/Fields/Pasta.lean CompElliptic/Fields/Jubjub.lean + # The AArch64 transcription is generated the same way, from the vendored assembly and + # reference vectors; the script also checks their recorded hashes. + - name: Check the AArch64 Pasta transcription is current + run: scripts/check_aarch64_pasta_mul.sh sage-checks: name: sage checks - Vélu certificates and Weil-derivation identities diff --git a/CompElliptic/Asm/AArch64/PastaMul.lean b/CompElliptic/Asm/AArch64/PastaMul.lean new file mode 100644 index 0000000..37ef609 --- /dev/null +++ b/CompElliptic/Asm/AArch64/PastaMul.lean @@ -0,0 +1,590 @@ +/- +Copyright (c) 2026 CompElliptic Contributors. +Released under the Apache License, Version 2.0, or the MIT license, at your option, +as described in the files LICENSE-APACHE and LICENSE-MIT. +Authors: Daira-Emma Hopwood +-/ +import CompElliptic.Asm.AArch64.Semantics + +/-! +# The Pasta Montgomery routines of `pasta_mul-armv8.S`, transcribed + +GENERATED by `scripts/gen_aarch64_pasta_mul.py` from +`CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S`; do not edit by hand. Each definition +follows its routine instruction by instruction (the instruction is the trailing comment), +over the semantics of `CompElliptic.Asm.AArch64.Semantics`: registers are rebound by the +instructions that write them, `c` is the carry flag, `s` is the (result, carry) pair of the +instruction that last set both, argument limbs are read where the assembly loads them, and +the output limbs are bound where the assembly stores them. Bindings that nothing reads are +left as comments; the stack frame and the return address are not part of the model. See the +generator's docstring for what it checks. +-/ + +namespace CompElliptic.Asm.AArch64 + +/-- The shared reduction helper (`L$pasta_curves_mul_by_1_mont_pasta`): four Montgomery cancellation +steps on `t`, returning `(t + Q * p) / 2^256` for the `Q` they choose, without a final conditional +subtraction. `x10`-`x13` hold `t` and `x4` holds `inv` on entry; the modulus limbs are loaded +through `x2`. -/ +def mulBy1 (t modulus : Limbs) (inv : Nat) : Limbs := + let x10 := t.l0 -- argument + let x11 := t.l1 -- argument + let x12 := t.l2 -- argument + let x13 := t.l3 -- argument + let x4 := inv -- argument + let x3 := mulLo x4 x10 -- mul x3,x4,x10 + let x5 := modulus.l0 -- ldp x5,x6,[x2] + let x6 := modulus.l1 -- ldp x5,x6,[x2] + -- ldp x7,x8,[x2,#16]: x7 = modulus.l2 is never read + -- ldp x7,x8,[x2,#16]: x8 = modulus.l3 is never read + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let c := (subc x10 1 1).2 -- subs xzr,x10,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x11 x15 c -- adcs x11,x11,x15 + let x11 := s.1 -- adcs x11,x11,x15 + let c := s.2 -- adcs x11,x11,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x12 0 c -- adcs x12,x12,xzr + let x12 := s.1 -- adcs x12,x12,xzr + let c := s.2 -- adcs x12,x12,xzr + let s := addc x13 x17 c -- adcs x13,x13,x17 + let x13 := s.1 -- adcs x13,x13,x17 + let c := s.2 -- adcs x13,x13,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x9 := (addc 0 0 c).1 -- adc x9,xzr,xzr + let s := addc x11 x14 0 -- adds x10,x11,x14 + let x10 := s.1 -- adds x10,x11,x14 + let c := s.2 -- adds x10,x11,x14 + let s := addc x12 x15 c -- adcs x11,x12,x15 + let x11 := s.1 -- adcs x11,x12,x15 + let c := s.2 -- adcs x11,x12,x15 + let s := addc x13 0 c -- adcs x12,x13,xzr + let x12 := s.1 -- adcs x12,x13,xzr + let c := s.2 -- adcs x12,x13,xzr + let x3 := mulLo x4 x10 -- mul x3,x4,x10 + let x13 := (addc x9 x17 c).1 -- adc x13,x9,x17 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let c := (subc x10 1 1).2 -- subs xzr,x10,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x11 x15 c -- adcs x11,x11,x15 + let x11 := s.1 -- adcs x11,x11,x15 + let c := s.2 -- adcs x11,x11,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x12 0 c -- adcs x12,x12,xzr + let x12 := s.1 -- adcs x12,x12,xzr + let c := s.2 -- adcs x12,x12,xzr + let s := addc x13 x17 c -- adcs x13,x13,x17 + let x13 := s.1 -- adcs x13,x13,x17 + let c := s.2 -- adcs x13,x13,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x9 := (addc 0 0 c).1 -- adc x9,xzr,xzr + let s := addc x11 x14 0 -- adds x10,x11,x14 + let x10 := s.1 -- adds x10,x11,x14 + let c := s.2 -- adds x10,x11,x14 + let s := addc x12 x15 c -- adcs x11,x12,x15 + let x11 := s.1 -- adcs x11,x12,x15 + let c := s.2 -- adcs x11,x12,x15 + let s := addc x13 0 c -- adcs x12,x13,xzr + let x12 := s.1 -- adcs x12,x13,xzr + let c := s.2 -- adcs x12,x13,xzr + let x3 := mulLo x4 x10 -- mul x3,x4,x10 + let x13 := (addc x9 x17 c).1 -- adc x13,x9,x17 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let c := (subc x10 1 1).2 -- subs xzr,x10,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x11 x15 c -- adcs x11,x11,x15 + let x11 := s.1 -- adcs x11,x11,x15 + let c := s.2 -- adcs x11,x11,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x12 0 c -- adcs x12,x12,xzr + let x12 := s.1 -- adcs x12,x12,xzr + let c := s.2 -- adcs x12,x12,xzr + let s := addc x13 x17 c -- adcs x13,x13,x17 + let x13 := s.1 -- adcs x13,x13,x17 + let c := s.2 -- adcs x13,x13,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x9 := (addc 0 0 c).1 -- adc x9,xzr,xzr + let s := addc x11 x14 0 -- adds x10,x11,x14 + let x10 := s.1 -- adds x10,x11,x14 + let c := s.2 -- adds x10,x11,x14 + let s := addc x12 x15 c -- adcs x11,x12,x15 + let x11 := s.1 -- adcs x11,x12,x15 + let c := s.2 -- adcs x11,x12,x15 + let s := addc x13 0 c -- adcs x12,x13,xzr + let x12 := s.1 -- adcs x12,x13,xzr + let c := s.2 -- adcs x12,x13,xzr + let x3 := mulLo x4 x10 -- mul x3,x4,x10 + let x13 := (addc x9 x17 c).1 -- adc x13,x9,x17 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let c := (subc x10 1 1).2 -- subs xzr,x10,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x11 x15 c -- adcs x11,x11,x15 + let x11 := s.1 -- adcs x11,x11,x15 + let c := s.2 -- adcs x11,x11,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x12 0 c -- adcs x12,x12,xzr + let x12 := s.1 -- adcs x12,x12,xzr + let c := s.2 -- adcs x12,x12,xzr + let s := addc x13 x17 c -- adcs x13,x13,x17 + let x13 := s.1 -- adcs x13,x13,x17 + let c := s.2 -- adcs x13,x13,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x9 := (addc 0 0 c).1 -- adc x9,xzr,xzr + let s := addc x11 x14 0 -- adds x10,x11,x14 + let x10 := s.1 -- adds x10,x11,x14 + let c := s.2 -- adds x10,x11,x14 + let s := addc x12 x15 c -- adcs x11,x12,x15 + let x11 := s.1 -- adcs x11,x12,x15 + let c := s.2 -- adcs x11,x12,x15 + let s := addc x13 0 c -- adcs x12,x13,xzr + let x12 := s.1 -- adcs x12,x13,xzr + let c := s.2 -- adcs x12,x13,xzr + let x13 := (addc x9 x17 c).1 -- adc x13,x9,x17 + ⟨x10, x11, x12, x13⟩ + +/-- `_pasta_curves_mul_mont_pasta`: Montgomery multiplication, `lhs * rhs * 2^-256 mod p`, with the +result stored through `x0`. -/ +def mulMont (lhs rhs modulus : Limbs) (inv : Nat) : Limbs := + let x4 := inv -- argument + let x10 := lhs.l0 -- ldp x10,x11,[x1] + let x11 := lhs.l1 -- ldp x10,x11,[x1] + let x9 := rhs.l0 -- ldr x9,[x2] + let x12 := lhs.l2 -- ldp x12,x13,[x1,#16] + let x13 := lhs.l3 -- ldp x12,x13,[x1,#16] + let x19 := mulLo x10 x9 -- mul x19,x10,x9 + let x5 := modulus.l0 -- ldp x5,x6,[x3] + let x6 := modulus.l1 -- ldp x5,x6,[x3] + let x20 := mulLo x11 x9 -- mul x20,x11,x9 + -- ldp x7,x8,[x3,#16]: x7 = modulus.l2 is never read + let x8 := modulus.l3 -- ldp x7,x8,[x3,#16] + let x21 := mulLo x12 x9 -- mul x21,x12,x9 + let x22 := mulLo x13 x9 -- mul x22,x13,x9 + let x14 := umulh x10 x9 -- umulh x14,x10,x9 + let x15 := umulh x11 x9 -- umulh x15,x11,x9 + let x3 := mulLo x4 x19 -- mul x3,x4,x19 + let x16 := umulh x12 x9 -- umulh x16,x12,x9 + let x17 := umulh x13 x9 -- umulh x17,x13,x9 + let s := addc x20 x14 0 -- adds x20,x20,x14 + let x20 := s.1 -- adds x20,x20,x14 + let c := s.2 -- adds x20,x20,x14 + let s := addc x21 x15 c -- adcs x21,x21,x15 + let x21 := s.1 -- adcs x21,x21,x15 + let c := s.2 -- adcs x21,x21,x15 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let s := addc x22 x16 c -- adcs x22,x22,x16 + let x22 := s.1 -- adcs x22,x22,x16 + let c := s.2 -- adcs x22,x22,x16 + let x23 := (addc 0 x17 c).1 -- adc x23,xzr,x17 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let x9 := rhs.l1 -- ldr x9,[x2,8*1] + let c := (subc x19 1 1).2 -- subs xzr,x19,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x21 0 c -- adcs x21,x21,xzr + let x21 := s.1 -- adcs x21,x21,xzr + let c := s.2 -- adcs x21,x21,xzr + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x19,x20,x14 + let x19 := s.1 -- adds x19,x20,x14 + let c := s.2 -- adds x19,x20,x14 + let x14 := mulLo x10 x9 -- mul x14,x10,x9 + let s := addc x21 x15 c -- adcs x20,x21,x15 + let x20 := s.1 -- adcs x20,x21,x15 + let c := s.2 -- adcs x20,x21,x15 + let x15 := mulLo x11 x9 -- mul x15,x11,x9 + let s := addc x22 0 c -- adcs x21,x22,xzr + let x21 := s.1 -- adcs x21,x22,xzr + let c := s.2 -- adcs x21,x22,xzr + let x16 := mulLo x12 x9 -- mul x16,x12,x9 + let s := addc x23 x17 c -- adcs x22,x23,x17 + let x22 := s.1 -- adcs x22,x23,x17 + let c := s.2 -- adcs x22,x23,x17 + let x17 := mulLo x13 x9 -- mul x17,x13,x9 + let x23 := (addc 0 0 c).1 -- adc x23,xzr,xzr + let s := addc x19 x14 0 -- adds x19,x19,x14 + let x19 := s.1 -- adds x19,x19,x14 + let c := s.2 -- adds x19,x19,x14 + let x14 := umulh x10 x9 -- umulh x14,x10,x9 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x11 x9 -- umulh x15,x11,x9 + let s := addc x21 x16 c -- adcs x21,x21,x16 + let x21 := s.1 -- adcs x21,x21,x16 + let c := s.2 -- adcs x21,x21,x16 + let x3 := mulLo x4 x19 -- mul x3,x4,x19 + let x16 := umulh x12 x9 -- umulh x16,x12,x9 + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := umulh x13 x9 -- umulh x17,x13,x9 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x20,x20,x14 + let x20 := s.1 -- adds x20,x20,x14 + let c := s.2 -- adds x20,x20,x14 + let s := addc x21 x15 c -- adcs x21,x21,x15 + let x21 := s.1 -- adcs x21,x21,x15 + let c := s.2 -- adcs x21,x21,x15 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let s := addc x22 x16 c -- adcs x22,x22,x16 + let x22 := s.1 -- adcs x22,x22,x16 + let c := s.2 -- adcs x22,x22,x16 + let x23 := (addc x23 x17 c).1 -- adc x23,x23,x17 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let x9 := rhs.l2 -- ldr x9,[x2,8*2] + let c := (subc x19 1 1).2 -- subs xzr,x19,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x21 0 c -- adcs x21,x21,xzr + let x21 := s.1 -- adcs x21,x21,xzr + let c := s.2 -- adcs x21,x21,xzr + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x19,x20,x14 + let x19 := s.1 -- adds x19,x20,x14 + let c := s.2 -- adds x19,x20,x14 + let x14 := mulLo x10 x9 -- mul x14,x10,x9 + let s := addc x21 x15 c -- adcs x20,x21,x15 + let x20 := s.1 -- adcs x20,x21,x15 + let c := s.2 -- adcs x20,x21,x15 + let x15 := mulLo x11 x9 -- mul x15,x11,x9 + let s := addc x22 0 c -- adcs x21,x22,xzr + let x21 := s.1 -- adcs x21,x22,xzr + let c := s.2 -- adcs x21,x22,xzr + let x16 := mulLo x12 x9 -- mul x16,x12,x9 + let s := addc x23 x17 c -- adcs x22,x23,x17 + let x22 := s.1 -- adcs x22,x23,x17 + let c := s.2 -- adcs x22,x23,x17 + let x17 := mulLo x13 x9 -- mul x17,x13,x9 + let x23 := (addc 0 0 c).1 -- adc x23,xzr,xzr + let s := addc x19 x14 0 -- adds x19,x19,x14 + let x19 := s.1 -- adds x19,x19,x14 + let c := s.2 -- adds x19,x19,x14 + let x14 := umulh x10 x9 -- umulh x14,x10,x9 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x11 x9 -- umulh x15,x11,x9 + let s := addc x21 x16 c -- adcs x21,x21,x16 + let x21 := s.1 -- adcs x21,x21,x16 + let c := s.2 -- adcs x21,x21,x16 + let x3 := mulLo x4 x19 -- mul x3,x4,x19 + let x16 := umulh x12 x9 -- umulh x16,x12,x9 + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := umulh x13 x9 -- umulh x17,x13,x9 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x20,x20,x14 + let x20 := s.1 -- adds x20,x20,x14 + let c := s.2 -- adds x20,x20,x14 + let s := addc x21 x15 c -- adcs x21,x21,x15 + let x21 := s.1 -- adcs x21,x21,x15 + let c := s.2 -- adcs x21,x21,x15 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let s := addc x22 x16 c -- adcs x22,x22,x16 + let x22 := s.1 -- adcs x22,x22,x16 + let c := s.2 -- adcs x22,x22,x16 + let x23 := (addc x23 x17 c).1 -- adc x23,x23,x17 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let x9 := rhs.l3 -- ldr x9,[x2,8*3] + let c := (subc x19 1 1).2 -- subs xzr,x19,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x21 0 c -- adcs x21,x21,xzr + let x21 := s.1 -- adcs x21,x21,xzr + let c := s.2 -- adcs x21,x21,xzr + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x19,x20,x14 + let x19 := s.1 -- adds x19,x20,x14 + let c := s.2 -- adds x19,x20,x14 + let x14 := mulLo x10 x9 -- mul x14,x10,x9 + let s := addc x21 x15 c -- adcs x20,x21,x15 + let x20 := s.1 -- adcs x20,x21,x15 + let c := s.2 -- adcs x20,x21,x15 + let x15 := mulLo x11 x9 -- mul x15,x11,x9 + let s := addc x22 0 c -- adcs x21,x22,xzr + let x21 := s.1 -- adcs x21,x22,xzr + let c := s.2 -- adcs x21,x22,xzr + let x16 := mulLo x12 x9 -- mul x16,x12,x9 + let s := addc x23 x17 c -- adcs x22,x23,x17 + let x22 := s.1 -- adcs x22,x23,x17 + let c := s.2 -- adcs x22,x23,x17 + let x17 := mulLo x13 x9 -- mul x17,x13,x9 + let x23 := (addc 0 0 c).1 -- adc x23,xzr,xzr + let s := addc x19 x14 0 -- adds x19,x19,x14 + let x19 := s.1 -- adds x19,x19,x14 + let c := s.2 -- adds x19,x19,x14 + let x14 := umulh x10 x9 -- umulh x14,x10,x9 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x11 x9 -- umulh x15,x11,x9 + let s := addc x21 x16 c -- adcs x21,x21,x16 + let x21 := s.1 -- adcs x21,x21,x16 + let c := s.2 -- adcs x21,x21,x16 + let x3 := mulLo x4 x19 -- mul x3,x4,x19 + let x16 := umulh x12 x9 -- umulh x16,x12,x9 + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := umulh x13 x9 -- umulh x17,x13,x9 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x20,x20,x14 + let x20 := s.1 -- adds x20,x20,x14 + let c := s.2 -- adds x20,x20,x14 + let s := addc x21 x15 c -- adcs x21,x21,x15 + let x21 := s.1 -- adcs x21,x21,x15 + let c := s.2 -- adcs x21,x21,x15 + let x15 := mulLo x6 x3 -- mul x15,x6,x3 + let s := addc x22 x16 c -- adcs x22,x22,x16 + let x22 := s.1 -- adcs x22,x22,x16 + let c := s.2 -- adcs x22,x22,x16 + let x23 := (addc x23 x17 c).1 -- adc x23,x23,x17 + let x17 := lsl x3 62 -- lsl x17,x3,#62 + let c := (subc x19 1 1).2 -- subs xzr,x19,#1 + let x14 := umulh x5 x3 -- umulh x14,x5,x3 + let s := addc x20 x15 c -- adcs x20,x20,x15 + let x20 := s.1 -- adcs x20,x20,x15 + let c := s.2 -- adcs x20,x20,x15 + let x15 := umulh x6 x3 -- umulh x15,x6,x3 + let s := addc x21 0 c -- adcs x21,x21,xzr + let x21 := s.1 -- adcs x21,x21,xzr + let c := s.2 -- adcs x21,x21,xzr + let s := addc x22 x17 c -- adcs x22,x22,x17 + let x22 := s.1 -- adcs x22,x22,x17 + let c := s.2 -- adcs x22,x22,x17 + let x17 := lsr x3 2 -- lsr x17,x3,#2 + let x23 := (addc x23 0 c).1 -- adc x23,x23,xzr + let s := addc x20 x14 0 -- adds x19,x20,x14 + let x19 := s.1 -- adds x19,x20,x14 + let c := s.2 -- adds x19,x20,x14 + let s := addc x21 x15 c -- adcs x20,x21,x15 + let x20 := s.1 -- adcs x20,x21,x15 + let c := s.2 -- adcs x20,x21,x15 + let s := addc x22 0 c -- adcs x21,x22,xzr + let x21 := s.1 -- adcs x21,x22,xzr + let c := s.2 -- adcs x21,x22,xzr + let s := addc x23 x17 c -- adcs x22,x23,x17 + let x22 := s.1 -- adcs x22,x23,x17 + let c := s.2 -- adcs x22,x23,x17 + let x23 := (addc 0 0 c).1 -- adc x23,xzr,xzr + let s := subc x19 x5 1 -- subs x14,x19,x5 + let x14 := s.1 -- subs x14,x19,x5 + let c := s.2 -- subs x14,x19,x5 + let s := subc x20 x6 c -- sbcs x15,x20,x6 + let x15 := s.1 -- sbcs x15,x20,x6 + let c := s.2 -- sbcs x15,x20,x6 + let s := subc x21 0 c -- sbcs x16,x21,xzr + let x16 := s.1 -- sbcs x16,x21,xzr + let c := s.2 -- sbcs x16,x21,xzr + let s := subc x22 x8 c -- sbcs x17,x22,x8 + let x17 := s.1 -- sbcs x17,x22,x8 + let c := s.2 -- sbcs x17,x22,x8 + let c := (subc x23 0 c).2 -- sbcs xzr,x23,xzr + let x19 := cselLo c x19 x14 -- csel x19,x19,x14,lo + let x20 := cselLo c x20 x15 -- csel x20,x20,x15,lo + let x21 := cselLo c x21 x16 -- csel x21,x21,x16,lo + let x22 := cselLo c x22 x17 -- csel x22,x22,x17,lo + let out0 := x19 -- stp x19,x20,[x0] + let out1 := x20 -- stp x19,x20,[x0] + let out2 := x21 -- stp x21,x22,[x0,#16] + let out3 := x22 -- stp x21,x22,[x0,#16] + ⟨out0, out1, out2, out3⟩ + +/-- `_pasta_curves_sqr_mont_pasta`: Montgomery squaring, `value^2 * 2^-256 mod p`. -/ +def sqrMont (value modulus : Limbs) (inv : Nat) : Limbs := + let x3 := inv -- argument + let x5 := value.l0 -- ldp x5,x6,[x1] + let x6 := value.l1 -- ldp x5,x6,[x1] + let x7 := value.l2 -- ldp x7,x8,[x1,#16] + let x8 := value.l3 -- ldp x7,x8,[x1,#16] + let x4 := x3 -- mov x4,x3 + let x11 := mulLo x6 x5 -- mul x11,x6,x5 + let x15 := umulh x6 x5 -- umulh x15,x6,x5 + let x12 := mulLo x7 x5 -- mul x12,x7,x5 + let x16 := umulh x7 x5 -- umulh x16,x7,x5 + let x13 := mulLo x8 x5 -- mul x13,x8,x5 + let x19 := umulh x8 x5 -- umulh x19,x8,x5 + let s := addc x12 x15 0 -- adds x12,x12,x15 + let x12 := s.1 -- adds x12,x12,x15 + let c := s.2 -- adds x12,x12,x15 + let x14 := mulLo x7 x6 -- mul x14,x7,x6 + let x15 := umulh x7 x6 -- umulh x15,x7,x6 + let s := addc x13 x16 c -- adcs x13,x13,x16 + let x13 := s.1 -- adcs x13,x13,x16 + let c := s.2 -- adcs x13,x13,x16 + let x16 := mulLo x8 x6 -- mul x16,x8,x6 + let x17 := umulh x8 x6 -- umulh x17,x8,x6 + let x19 := (addc x19 0 c).1 -- adc x19,x19,xzr + let x20 := mulLo x8 x7 -- mul x20,x8,x7 + let x21 := umulh x8 x7 -- umulh x21,x8,x7 + let s := addc x15 x16 0 -- adds x15,x15,x16 + let x15 := s.1 -- adds x15,x15,x16 + let c := s.2 -- adds x15,x15,x16 + let x10 := mulLo x5 x5 -- mul x10,x5,x5 + let x16 := (addc x17 0 c).1 -- adc x16,x17,xzr + let s := addc x13 x14 0 -- adds x13,x13,x14 + let x13 := s.1 -- adds x13,x13,x14 + let c := s.2 -- adds x13,x13,x14 + let x5 := umulh x5 x5 -- umulh x5,x5,x5 + let s := addc x19 x15 c -- adcs x19,x19,x15 + let x19 := s.1 -- adcs x19,x19,x15 + let c := s.2 -- adcs x19,x19,x15 + let x15 := mulLo x6 x6 -- mul x15,x6,x6 + let s := addc x20 x16 c -- adcs x20,x20,x16 + let x20 := s.1 -- adcs x20,x20,x16 + let c := s.2 -- adcs x20,x20,x16 + let x6 := umulh x6 x6 -- umulh x6,x6,x6 + let x21 := (addc x21 0 c).1 -- adc x21,x21,xzr + let s := addc x11 x11 0 -- adds x11,x11,x11 + let x11 := s.1 -- adds x11,x11,x11 + let c := s.2 -- adds x11,x11,x11 + let x16 := mulLo x7 x7 -- mul x16,x7,x7 + let s := addc x12 x12 c -- adcs x12,x12,x12 + let x12 := s.1 -- adcs x12,x12,x12 + let c := s.2 -- adcs x12,x12,x12 + let x7 := umulh x7 x7 -- umulh x7,x7,x7 + let s := addc x13 x13 c -- adcs x13,x13,x13 + let x13 := s.1 -- adcs x13,x13,x13 + let c := s.2 -- adcs x13,x13,x13 + let x17 := mulLo x8 x8 -- mul x17,x8,x8 + let s := addc x19 x19 c -- adcs x19,x19,x19 + let x19 := s.1 -- adcs x19,x19,x19 + let c := s.2 -- adcs x19,x19,x19 + let x8 := umulh x8 x8 -- umulh x8,x8,x8 + let s := addc x20 x20 c -- adcs x20,x20,x20 + let x20 := s.1 -- adcs x20,x20,x20 + let c := s.2 -- adcs x20,x20,x20 + let s := addc x21 x21 c -- adcs x21,x21,x21 + let x21 := s.1 -- adcs x21,x21,x21 + let c := s.2 -- adcs x21,x21,x21 + let x22 := (addc 0 0 c).1 -- adc x22,xzr,xzr + let s := addc x11 x5 0 -- adds x11,x11,x5 + let x11 := s.1 -- adds x11,x11,x5 + let c := s.2 -- adds x11,x11,x5 + let s := addc x12 x15 c -- adcs x12,x12,x15 + let x12 := s.1 -- adcs x12,x12,x15 + let c := s.2 -- adcs x12,x12,x15 + let s := addc x13 x6 c -- adcs x13,x13,x6 + let x13 := s.1 -- adcs x13,x13,x6 + let c := s.2 -- adcs x13,x13,x6 + let s := addc x19 x16 c -- adcs x19,x19,x16 + let x19 := s.1 -- adcs x19,x19,x16 + let c := s.2 -- adcs x19,x19,x16 + let s := addc x20 x7 c -- adcs x20,x20,x7 + let x20 := s.1 -- adcs x20,x20,x7 + let c := s.2 -- adcs x20,x20,x7 + let s := addc x21 x17 c -- adcs x21,x21,x17 + let x21 := s.1 -- adcs x21,x21,x17 + let c := s.2 -- adcs x21,x21,x17 + let x22 := (addc x22 x8 c).1 -- adc x22,x22,x8 + let r := mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 -- bl L$pasta_curves_mul_by_1_mont_pasta + let x10 := r.l0 -- helper output + let x11 := r.l1 -- helper output + let x12 := r.l2 -- helper output + let x13 := r.l3 -- helper output + let x5 := modulus.l0 -- loaded by the helper + let x6 := modulus.l1 -- loaded by the helper + let x7 := modulus.l2 -- loaded by the helper + let x8 := modulus.l3 -- loaded by the helper + let s := addc x10 x19 0 -- adds x10,x10,x19 + let x10 := s.1 -- adds x10,x10,x19 + let c := s.2 -- adds x10,x10,x19 + let s := addc x11 x20 c -- adcs x11,x11,x20 + let x11 := s.1 -- adcs x11,x11,x20 + let c := s.2 -- adcs x11,x11,x20 + let s := addc x12 x21 c -- adcs x12,x12,x21 + let x12 := s.1 -- adcs x12,x12,x21 + let c := s.2 -- adcs x12,x12,x21 + let s := addc x13 x22 c -- adcs x13,x13,x22 + let x13 := s.1 -- adcs x13,x13,x22 + let c := s.2 -- adcs x13,x13,x22 + let x19 := (addc 0 0 c).1 -- adc x19,xzr,xzr + let s := subc x10 x5 1 -- subs x14,x10,x5 + let x14 := s.1 -- subs x14,x10,x5 + let c := s.2 -- subs x14,x10,x5 + let s := subc x11 x6 c -- sbcs x15,x11,x6 + let x15 := s.1 -- sbcs x15,x11,x6 + let c := s.2 -- sbcs x15,x11,x6 + let s := subc x12 x7 c -- sbcs x16,x12,x7 + let x16 := s.1 -- sbcs x16,x12,x7 + let c := s.2 -- sbcs x16,x12,x7 + let s := subc x13 x8 c -- sbcs x17,x13,x8 + let x17 := s.1 -- sbcs x17,x13,x8 + let c := s.2 -- sbcs x17,x13,x8 + let c := (subc x19 0 c).2 -- sbcs xzr,x19,xzr + let x10 := cselLo c x10 x14 -- csel x10,x10,x14,lo + let x11 := cselLo c x11 x15 -- csel x11,x11,x15,lo + let x12 := cselLo c x12 x16 -- csel x12,x12,x16,lo + let x13 := cselLo c x13 x17 -- csel x13,x13,x17,lo + let out0 := x10 -- stp x10,x11,[x0] + let out1 := x11 -- stp x10,x11,[x0] + let out2 := x12 -- stp x12,x13,[x0,#16] + let out3 := x13 -- stp x12,x13,[x0,#16] + ⟨out0, out1, out2, out3⟩ + +/-- `_pasta_curves_from_mont_pasta`: conversion out of Montgomery form, `value * 2^-256 mod p`. -/ +def fromMont (value modulus : Limbs) (inv : Nat) : Limbs := + let x3 := inv -- argument + let x4 := x3 -- mov x4,x3 + let x10 := value.l0 -- ldp x10,x11,[x1] + let x11 := value.l1 -- ldp x10,x11,[x1] + let x12 := value.l2 -- ldp x12,x13,[x1,#16] + let x13 := value.l3 -- ldp x12,x13,[x1,#16] + let r := mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 -- bl L$pasta_curves_mul_by_1_mont_pasta + let x10 := r.l0 -- helper output + let x11 := r.l1 -- helper output + let x12 := r.l2 -- helper output + let x13 := r.l3 -- helper output + let x5 := modulus.l0 -- loaded by the helper + let x6 := modulus.l1 -- loaded by the helper + let x7 := modulus.l2 -- loaded by the helper + let x8 := modulus.l3 -- loaded by the helper + let s := subc x10 x5 1 -- subs x14,x10,x5 + let x14 := s.1 -- subs x14,x10,x5 + let c := s.2 -- subs x14,x10,x5 + let s := subc x11 x6 c -- sbcs x15,x11,x6 + let x15 := s.1 -- sbcs x15,x11,x6 + let c := s.2 -- sbcs x15,x11,x6 + let s := subc x12 x7 c -- sbcs x16,x12,x7 + let x16 := s.1 -- sbcs x16,x12,x7 + let c := s.2 -- sbcs x16,x12,x7 + let s := subc x13 x8 c -- sbcs x17,x13,x8 + let x17 := s.1 -- sbcs x17,x13,x8 + let c := s.2 -- sbcs x17,x13,x8 + let x10 := cselLo c x10 x14 -- csel x10,x10,x14,lo + let x11 := cselLo c x11 x15 -- csel x11,x11,x15,lo + let x12 := cselLo c x12 x16 -- csel x12,x12,x16,lo + let x13 := cselLo c x13 x17 -- csel x13,x13,x17,lo + let out0 := x10 -- stp x10,x11,[x0] + let out1 := x11 -- stp x10,x11,[x0] + let out2 := x12 -- stp x12,x13,[x0,#16] + let out3 := x13 -- stp x12,x13,[x0,#16] + ⟨out0, out1, out2, out3⟩ + +end CompElliptic.Asm.AArch64 diff --git a/CompElliptic/Asm/AArch64/PastaMulVectors.lean b/CompElliptic/Asm/AArch64/PastaMulVectors.lean new file mode 100644 index 0000000..b792a11 --- /dev/null +++ b/CompElliptic/Asm/AArch64/PastaMulVectors.lean @@ -0,0 +1,8392 @@ +/- +Copyright (c) 2026 CompElliptic Contributors. +Released under the Apache License, Version 2.0, or the MIT license, at your option, +as described in the files LICENSE-APACHE and LICENSE-MIT. +Authors: Daira-Emma Hopwood +-/ +import CompElliptic.Asm.AArch64.PastaMul + +/-! +# Reference vectors for the transcribed routines + +GENERATED by `scripts/gen_aarch64_pasta_mul.py` from +`CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt`; do not edit by hand. Each +vector is the output of the real assembly (pasta_curves `8ad85e9fab7929f6236960e472f432a4bd9ccd74`, +run on an Apple M-series machine) on the given operands, and each example asks the kernel +to evaluate the transcription on the same operands. The vectors cover boundary operands +(zero, one, `R`, `R2`, `R3`, `p - 1`, single all-ones limbs), random canonical operands, +and unreduced operands in both positions, so they also record the routines' behaviour +outside their operand contracts. + +The modulus limbs and `inv` are the crate's constants for its `Fp` (the Pallas base field) +and `Fq` (the Vesta base field). +-/ + +namespace CompElliptic.Asm.AArch64 + +/-- The Pallas base field modulus, as the crate's `MODULUS` limbs. -/ +def pallasBaseModulus : Limbs := ⟨0x992d30ed00000001, 0x224698fc094cf91b, 0, 0x4000000000000000⟩ + +/-- `-p^-1 mod 2^64` for the Pallas base field, the crate's `INV`. -/ +def pallasBaseInv : Nat := 0x992d30ecffffffff + +/-- The Vesta base field modulus, as the crate's `MODULUS` limbs. -/ +def vestaBaseModulus : Limbs := ⟨0x8c46eb2100000001, 0x224698fc0994a8dd, 0, 0x4000000000000000⟩ + +/-- `-p^-1 mod 2^64` for the Vesta base field, the crate's `INV`. -/ +def vestaBaseInv : Nat := 0x8c46eb20ffffffff + +example : + fromMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21cce888a6cab566710d6cd04c692c9784379b4cc10e927b1dfc65f6ad0492ae) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000891a63f02533e46e64b4c3b400000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffff76e59c0fdacc1b9246ac39382e80dd85fde1f4a100000005) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x125b506bdee72dc51de5ea66f0f257463e8669ae6516b680c969876800000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x36e59c0fdacc1b919b4b3c4bfffffffcefee2ee4411acfc1303c567b00000007) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x125b506bdee72dc51de5ea66f0f25746c7a0cd9e8a4a9aef2e1e4b1c00000008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2da4af942118d23ae21a15990f0da8b9e3c02f4da436429acfc3a984fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3031b67010dc5f33e1768c975480689a91ad57216c5706a8810c3c6089daf8b6) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b22a80cd2c81a0c889a01873458140ef909266c546d35f5014930b21f53b554) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x10548582022977317020e583ebc9e08237f899a30131ff72b3387ebd971aec55) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x348bf875968510c9c9602914af00483e46f3b5921d2c02b91578ba31cf7bad4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0791f325de14e664b4aa62282e98a644f50840433dbfc7626da70eaaf58145f5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x08102d3c3c95a063e1e6c2328bbd8e7ed2a208c993640dc0c477d288cfba797a) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0662a11d61e1a30f915945eff265faff24953adafa8636a3c01ff3639e2aed4c) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21cce888a6cab566710d6cd04c692c9784379b4cc10e927b1dfc65f6ad0492ae) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0662a11d61e1a30f915945eff265faff24953adafa8636a3c01ff3639e2aed4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3692be50846348eb886856643c36a2e74a738b3e7e3f18340cb44439fffffff2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2a67ec482ca6045b2ef3341a17f2ecf6a3c75cc8bdaf33e0efe592118d23a0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ab8c2488b4b664437e344050d4ff50b575e968be1ab27492f434e180ea7843f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x09595b20624498f13919469f2d8f1ea91d1e34d0388bbd88e9421d36f0da8b8e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x314b80990faeaf2fc04b9a69498697f27f8b88ce569d4661a2ca61650ea78430) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x05473db774b499bbc81cbbfaf2b00af4cae8027027a1d1d269e9e2d4f1587bc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x11059dda0a0984a24c432eaa84cb8a47e785e51edefe7cefa723d05be7cd96b1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2a8c68e806154a62330fa85f54dedea8453b7a0d756f7860ca191c12c6265afb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x28b001b79faac705f426b23ca533d40220e19e6209f724ada5c28c17b9f0d326) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3c2c602b7bf8fbf1790afd71b3e16fad0c5531d44cf930398f831a05338f2444) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d679a6b16f9788e6430d173a58607f8d5e7ec854b246cf10a63c8d6170c9008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096a1374bdff44bcdb81d15301f0d099d8fc397f7e24afe149933c9ef8a6efe3) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000891a63f02533e46e64b4c3b400000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3692be50846348eb886856643c36a2e74a738b3e7e3f18340cb44439fffffff2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31269b682e59de6fd65951678f204af90e79463ab37aa332256c3921cc314cff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31f1c4ff1e2278d570cb2996efc89a65b53160a942cb3a9eb58adac293a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x075fd91f3b718e08c51be01df5028ccc419bfe790f5b558fc4eb03ea21c2bedc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a80d4fab5ba20a8a16195cd72a675e5f66caca2755bd372e73d60d346332931) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1c2e48522b3388de50ade90d1f25cd139a10bd0f15f3fc4da795b0484e2be97c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0c942c15724e2a539b07cff51781ad5803eb22a0d9a2d7be0b3215dfda494d90) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x24ec7781e5ebd60e91be9e56ea3634df88c55c71ebc034e1a63b4075c102abe4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3be85d8069b8128c838e08fd1ed8306682f054442bd65e6f1bbc40a1c35cc5b2) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1acd4a009f399376e232c5736e77fb8c1c35dfa341e703db83392c958598c6be) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffff76e59c0fdacc1b9246ac39382e80dd85fde1f4a100000005) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2a67ec482ca6045b2ef3341a17f2ecf6a3c75cc8bdaf33e0efe592118d23a0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31269b682e59de6fd65951678f204af90e79463ab37aa332256c3921cc314cff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1acd4a009f399376e232c5736e77fb8c1c35dfa341e703db83392c958598c6be) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e47264b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d000f740db18f02f00e052c4f204af954d1de0b0cab76c3b5b5e0d408b278e3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x01269b682e59de6fd65951678f204af8f4c4537dac80e85db28a54700c314cfe) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad472e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0243f901466f013c8772ef73a588001a8cfd085e39574506f699f0ce0f88f6ff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x191f3f2d4313aac2ca49e3117da6cccc88309e28da5f78ff277a04b81d1babd3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0b805f450c0dbbcac5b4d865b01cc2cfdf8b1a0da5a185b347115895fafa0cf5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x318c5c205acc7cfb9dd944e14c01dc9dc04c7e3f598fcdcf20995458a381f6df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x132dd92afbb5a12f1cbf9c47baf77e853f10c4c3988db021b3feac2f58b2041e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x385a54834adfe22620b33bbf39551c1ebe43143dccc4fe9a83b5c6ed6a3d0fe4) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x125b506bdee72dc51de5ea66f0f257463e8669ae6516b680c969876800000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ab8c2488b4b664437e344050d4ff50b575e968be1ab27492f434e180ea7843f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e47264b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000004891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x200000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30000000000000000000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1f0f0f09f84f08783843fdf0cf348dc097a0b54e3aa246c5b55a5622784f0e97) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b5460f6403423b40d9318fd6638bebd8e6eef198af3853ff6d6f357647edda2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x352c1aa827cc3842bae5326c6b8c0507b63abda4f5381c1fba0caf01e03ae083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2d0e14a05cd1d9fc243491206fc89a663293063e00578f9e26d1cbe7d1ec3cd7) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x36e59c0fdacc1b919b4b3c4bfffffffcefee2ee4411acfc1303c567b00000007) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x09595b20624498f13919469f2d8f1ea91d1e34d0388bbd88e9421d36f0da8b8e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d000f740db18f02f00e052c4f204af954d1de0b0cab76c3b5b5e0d408b278e3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000004891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2d0e14a05cd1d9fc243491206fc89a663293063e00578f9e26d1cbe7d1ec3cd7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x177feccfbd7a2968ca7fdd5bafc89a662707ba151e1487b414bd60fc52c9d33f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2fffffffffffffffffffffffffffffffd9b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x09b6e874ebf7015713395bc67cb37e35bf190f9737a661f2590218bef5ccf20d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2369223ec0ba778f450631700e279844d7602068e54753affa279ed410cd00c8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x113537aabc2a7e9a9f170ff0466ace9eb6bd66c2ac39a2cb6bcd60b2cac31dca) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f65a101a6ce5999439c8a3a3746ccd5da1def3365e774fd07693f94385002f0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2fed7572b6ad1fb4518addae8bb2afaca112b6073915376d60bf257769db7f62) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x190d90428434fe44c0c829966224346c7b42f390ed1288f2ffb94f3b3ebd874b) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x11f1c4ff1e2278d570cb2996efc89a659b7c6dec3bd17fca02a8f610d3a769a8) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x125b506bdee72dc51de5ea66f0f25746c7a0cd9e8a4a9aef2e1e4b1c00000008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x314b80990faeaf2fc04b9a69498697f27f8b88ce569d4661a2ca61650ea78430) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31f1c4ff1e2278d570cb2996efc89a65b53160a942cb3a9eb58adac293a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x01269b682e59de6fd65951678f204af8f4c4537dac80e85db28a54700c314cfe) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x200000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x177feccfbd7a2968ca7fdd5bafc89a662707ba151e1487b414bd60fc52c9d33f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x11f1c4ff1e2278d570cb2996efc89a659b7c6dec3bd17fca02a8f610d3a769a8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x266ee82933c09680fd5fde0ec4371a8cd93cb3c749fd9c557a455a0c9a11cd73) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x35d535f0f5ee445caef4aecad8df34a3629502bff7025f9744e7233daab206d2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x24d18d9e8ac25f467d7768da1b243aff4ec9316f02e7ed32b5910bb626e6e7f1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x01c046bd9a1a629655ed0261830db25f97df4749c58dfac22c1193f4ba842e12) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2986a354618709211610cad3a6c0c64806e77df3f7aeb7eef421e1551f863117) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ea7b13e2bf23d01001eece10c10cec411682c86b78d02cf0553467a8010c1ac) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2da4af942118d23ae21a15990f0da8b9e3c02f4da436429acfc3a984fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x05473db774b499bbc81cbbfaf2b00af4cae8027027a1d1d269e9e2d4f1587bc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad472e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30000000000000000000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2fffffffffffffffffffffffffffffffd9b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x20f0f0f607b0f787c7bc020f30cb723f8aa5e3adceaab255e3d2daca87b0f16a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e5973dba2563d959b81225f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x375cbab3a0712997d3368033040192146d8e249c1c5908368b31d57f2745018c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ad3e557d833c7bd451acd939473faf86c0bdb571414dcfbdf2081eb1fc51f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b65d42d8464cced7badd38343756e97a4247779fd5e760e4b46900da17c7ace) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d40ac423dc5d58b836f1c1c12c761a293cec0b97d9654bbaf962b14434c0407) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3e3eab736edbf3946567e005720448fa968090b33ceae01c4381bc2109eeaf68) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3031b67010dc5f33e1768c975480689a91ad57216c5706a8810c3c6089daf8b6) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x11059dda0a0984a24c432eaa84cb8a47e785e51edefe7cefa723d05be7cd96b1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x075fd91f3b718e08c51be01df5028ccc419bfe790f5b558fc4eb03ea21c2bedc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0243f901466f013c8772ef73a588001a8cfd085e39574506f699f0ce0f88f6ff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1f0f0f09f84f08783843fdf0cf348dc097a0b54e3aa246c5b55a5622784f0e97) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x09b6e874ebf7015713395bc67cb37e35bf190f9737a661f2590218bef5ccf20d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x266ee82933c09680fd5fde0ec4371a8cd93cb3c749fd9c557a455a0c9a11cd73) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x20f0f0f607b0f787c7bc020f30cb723f8aa5e3adceaab255e3d2daca87b0f16a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3e3eab736edbf3946567e005720448fa968090b33ceae01c4381bc2109eeaf68) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a9fa1eab51f114925de48e933973c839a851f8d16897802cce98a6267201387) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2433c132353f7a7f730575508359403919905b802503b90d7f4089fc0acd1e2a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x18a27a96677cebda48524b4f66ca32081b52f70b717294b8645d87743ef435db) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1b1d201950d04201d5a13d2f40f232fcf3da86444bfbdd96a840d51974c1a9d7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fe1bce271b680a3432473b59a47a1c89bb3fa7f9abd3fc2582838316659e21a) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x23e2d584e303750afbe701cc135a158c167f8e478e3e5fc5d9a12bd944145437) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b22a80cd2c81a0c889a01873458140ef909266c546d35f5014930b21f53b554) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2a8c68e806154a62330fa85f54dedea8453b7a0d756f7860ca191c12c6265afb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a80d4fab5ba20a8a16195cd72a675e5f66caca2755bd372e73d60d346332931) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x191f3f2d4313aac2ca49e3117da6cccc88309e28da5f78ff277a04b81d1babd3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b5460f6403423b40d9318fd6638bebd8e6eef198af3853ff6d6f357647edda2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2369223ec0ba778f450631700e279844d7602068e54753affa279ed410cd00c8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x35d535f0f5ee445caef4aecad8df34a3629502bff7025f9744e7233daab206d2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e5973dba2563d959b81225f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a9fa1eab51f114925de48e933973c839a851f8d16897802cce98a6267201387) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x23e2d584e303750afbe701cc135a158c167f8e478e3e5fc5d9a12bd944145437) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ce872d15beb15e7588f5de133d0911cd1c2e096c89f9f45c5e09880d85839c5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3259897b8dc9480ee45a3263849a285c4956e607a01e8d672e92443b91d4af79) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x13b5bc4323ef673b7d2ebb04dc796bcc0595773c37288657aa1b5b21897e52d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x241142522c7e16f6adc74f23033257a67598c7dbd63840792ffe83c6b9c1e770) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x101375a000c3fbfa17d36b7a1e49055624cd7677331a60db2cc29f483741ff50) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x10548582022977317020e583ebc9e08237f899a30131ff72b3387ebd971aec55) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x28b001b79faac705f426b23ca533d40220e19e6209f724ada5c28c17b9f0d326) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1c2e48522b3388de50ade90d1f25cd139a10bd0f15f3fc4da795b0484e2be97c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0b805f450c0dbbcac5b4d865b01cc2cfdf8b1a0da5a185b347115895fafa0cf5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x113537aabc2a7e9a9f170ff0466ace9eb6bd66c2ac39a2cb6bcd60b2cac31dca) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x24d18d9e8ac25f467d7768da1b243aff4ec9316f02e7ed32b5910bb626e6e7f1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x375cbab3a0712997d3368033040192146d8e249c1c5908368b31d57f2745018c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2433c132353f7a7f730575508359403919905b802503b90d7f4089fc0acd1e2a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ce872d15beb15e7588f5de133d0911cd1c2e096c89f9f45c5e09880d85839c5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x101375a000c3fbfa17d36b7a1e49055624cd7677331a60db2cc29f483741ff50) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x216088e1212a7e3fc1f7dec7525eecdf393fe793f52a875cf043848ad8095cc3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x35c5000bc6c052e6674d650b37e06a3a0a4fba0c34fd24ce261a45452089bc46) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2565d74b6f42ec480e49fae1cd43df66bbb7502f0cef496c28f6c4879667d453) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1677ce27814b54d771a091ab04eef7ad2cdf503fcfe6b9e8dad6ba85e7d8fbc9) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x348bf875968510c9c9602914af00483e46f3b5921d2c02b91578ba31cf7bad4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3c2c602b7bf8fbf1790afd71b3e16fad0c5531d44cf930398f831a05338f2444) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0c942c15724e2a539b07cff51781ad5803eb22a0d9a2d7be0b3215dfda494d90) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x318c5c205acc7cfb9dd944e14c01dc9dc04c7e3f598fcdcf20995458a381f6df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x352c1aa827cc3842bae5326c6b8c0507b63abda4f5381c1fba0caf01e03ae083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f65a101a6ce5999439c8a3a3746ccd5da1def3365e774fd07693f94385002f0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x01c046bd9a1a629655ed0261830db25f97df4749c58dfac22c1193f4ba842e12) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ad3e557d833c7bd451acd939473faf86c0bdb571414dcfbdf2081eb1fc51f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x18a27a96677cebda48524b4f66ca32081b52f70b717294b8645d87743ef435db) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3259897b8dc9480ee45a3263849a285c4956e607a01e8d672e92443b91d4af79) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x216088e1212a7e3fc1f7dec7525eecdf393fe793f52a875cf043848ad8095cc3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1677ce27814b54d771a091ab04eef7ad2cdf503fcfe6b9e8dad6ba85e7d8fbc9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x360e55958d8e8464a1fd7990b64f92ffbfae77cba35ea31dc8f26d8c0274ce1f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x12d5679fd842c0fae489e6f8fd950712a6801d77da2000d2e180e73af156d5b3) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ce69b158811c2f8acefdc7b0e5a9df4c9bd80d3b24d8f94654a3efada3cf581) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0791f325de14e664b4aa62282e98a644f50840433dbfc7626da70eaaf58145f5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d679a6b16f9788e6430d173a58607f8d5e7ec854b246cf10a63c8d6170c9008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x24ec7781e5ebd60e91be9e56ea3634df88c55c71ebc034e1a63b4075c102abe4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x132dd92afbb5a12f1cbf9c47baf77e853f10c4c3988db021b3feac2f58b2041e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2fed7572b6ad1fb4518addae8bb2afaca112b6073915376d60bf257769db7f62) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2986a354618709211610cad3a6c0c64806e77df3f7aeb7eef421e1551f863117) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3b65d42d8464cced7badd38343756e97a4247779fd5e760e4b46900da17c7ace) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1b1d201950d04201d5a13d2f40f232fcf3da86444bfbdd96a840d51974c1a9d7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x13b5bc4323ef673b7d2ebb04dc796bcc0595773c37288657aa1b5b21897e52d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x35c5000bc6c052e6674d650b37e06a3a0a4fba0c34fd24ce261a45452089bc46) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x360e55958d8e8464a1fd7990b64f92ffbfae77cba35ea31dc8f26d8c0274ce1f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ce69b158811c2f8acefdc7b0e5a9df4c9bd80d3b24d8f94654a3efada3cf581) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ce2105c41fe09975371bc977a9cacd087001027e8f2f0eebb02070709dbc6cd) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0b67e1cebd614788846394194b77a658559fe5bf4d14fa7d808af326b918255d) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x08102d3c3c95a063e1e6c2328bbd8e7ed2a208c993640dc0c477d288cfba797a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096a1374bdff44bcdb81d15301f0d099d8fc397f7e24afe149933c9ef8a6efe3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3be85d8069b8128c838e08fd1ed8306682f054442bd65e6f1bbc40a1c35cc5b2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x385a54834adfe22620b33bbf39551c1ebe43143dccc4fe9a83b5c6ed6a3d0fe4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x190d90428434fe44c0c829966224346c7b42f390ed1288f2ffb94f3b3ebd874b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ea7b13e2bf23d01001eece10c10cec411682c86b78d02cf0553467a8010c1ac) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3d40ac423dc5d58b836f1c1c12c761a293cec0b97d9654bbaf962b14434c0407) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fe1bce271b680a3432473b59a47a1c89bb3fa7f9abd3fc2582838316659e21a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x241142522c7e16f6adc74f23033257a67598c7dbd63840792ffe83c6b9c1e770) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2565d74b6f42ec480e49fae1cd43df66bbb7502f0cef496c28f6c4879667d453) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x12d5679fd842c0fae489e6f8fd950712a6801d77da2000d2e180e73af156d5b3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ce2105c41fe09975371bc977a9cacd087001027e8f2f0eebb02070709dbc6cd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0b67e1cebd614788846394194b77a658559fe5bf4d14fa7d808af326b918255d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d1960ed71adb041c555f12db06700000013) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d1960ed71adb041c555f12db06700000013) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2175c772b190e1fc67f56678717677141ed3817ddfb7d0ea650cb8e63a9e10ea) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2175c772b190e1fc67f56678717677141ed3817ddfb7d0ea650cb8e63a9e10ea) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31269b682e59de6fd65951678f204af90e79463ab37aa333256c3921cc314cfe) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31269b682e59de6fd65951678f204af90e79463ab37aa333256c3921cc314cfe) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fffffffffffffffffffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fffffffffffffffffffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x077feccfbd7a2968ca7fdd5bafc89a66de7613d61bc1496d2e7214c112c9d33e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31f1c4ff1e2278d570cb2996efc89a6492eac7ad397e41831c5da9d593a769a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x31f1c4ff1e2278d570cb2996efc89a6592eac7ad397e41831c5da9d593a769a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x300000000000000000000000000000003bfb8bb91046b3f04c0f159ec0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x300000000000000000000000000000003bfb8bb91046b3f04c0f159ec0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a64ac9fba6a4077fc57cf3f8e8753a769a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a64ac9fba6a4077fc57cf3f8e8753a769a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761ca9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6bc06d0d2b964a52404300865287761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xc83d113a5e2278d430cb2996efc89a647c94c6d6abc5909ccdfc4e25d1062bf3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xc83d113a5e2278d430cb2996efc89a657c94c6d6abc5909ccdfc4e25d1062bf3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ac34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ac34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb71500b20d8be8fd41873c87d1718b0de0eb8c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb71500b20d8be8fd41873c87d1718b0de0eb8c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x334b5f8669643bf80cc67344575e84274a76531d20471ad21d4a04412910ed4b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x334b5f8669643bf80cc67344575e84274a76531d20471ad21d4a04412910ed4b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6cc06d0d2b964a52414300865287761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6cc06d0d2b964a52414300865287761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x165951678f204af8f4268bf420a84f6cf243669771939f57a2330c8c46988640) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x165951678f204af8f4268bf420a84f6cf243669771939f57a2330c8c46988640) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0a7fdd5bafc89a65da71d82f60a84f6cabeacec71862cbc511e964da0a175a5c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0a7fdd5bafc89a65da71d82f60a84f6dabeacec71862cbc511e964da0a175a5c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6b9e26742f8cfd592569d3556587761ca9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6c9e26742f8cfd592569d3556587761ca9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91bd92d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91bd92d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30cb2996efc89a659a71d82f60a84f6bc06d0d2b964a52404300865287761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761ca9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xda71d82f60a84f6ba64b4c3b3fffffffabe30d981b69b9cd07a048d940dd9669) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xda71d82f60a84f6ba64b4c3b3fffffffabe30d981b69b9cd07a048d940dd9669) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6b9e26742f8cfd5924a9d3556587761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2205637b9cb7182e2a67ec482ca604fcfe4d7d773c0e0beec288616b306e5a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2205637b9cb7182e2a67ec482ca604fcfe4d7d773c0e0beec288616b306e5a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30c4d737c038663a7d125d564448de03477954dba8c4a49f5592d170b2235101) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x30c4d737c038663a7d125d564448de03477954dba8c4a49f5592d170b2235101) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x083d113a5e2278d530cb2996efc89a659edb5fd2b51289b867297f12d1062bf5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x083d113a5e2278d530cb2996efc89a659edb5fd2b51289b867297f12d1062bf5) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1771e7a36e59de6f965951678f204af900b4eba328153093bd5629ad49900f4a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1771e7a36e59de6f965951678f204af900b4eba328153093bd5629ad49900f4a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fffffffffffffffbfffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0fffffffffffffffbfffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2dcb390afd7a29688a7fdd5bafc89a66f2f8523a99a8cfe85f8936399028958c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2dcb390afd7a29688a7fdd5bafc89a66f2f8523a99a8cfe85f8936399028958c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x183d113a5e2278d4f0cb2996efc89a6585266d15ae18cee3b4479a6111062bf4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x183d113a5e2278d4f0cb2996efc89a6585266d15ae18cee3b4479a6111062bf4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x300000000000000040000000000000003bfb8bb91046b3f04c0f159ec0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x300000000000000040000000000000003bfb8bb91046b3f04c0f159ec0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xc83d113a5e2278d430cb2996efc89a657c94c6d6abc5909ccdfc4e25d1062bf3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xc83d113a5e2278d430cb2996efc89a647c94c6d6abc5909ccdfc4e25d1062bf3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xf0cb2996efc89a649a71d82f60a84f6b9e26742f8cfd5924a9d3556587761caa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xee885d759e2278d2f0cb2996efc89a669117053b29ad1718ff136f9e4e64ee41) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xee885d759e2278d2f0cb2996efc89a669117053b29ad1718ff136f9e4e64ee41) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2205637b9cb7182e2a67ec482ca60473e3e98d5208299d8a0dc4ad6b306e56) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x2e2205637b9cb7182e2a67ec482ca60473e3e98d5208299d8a0dc4ad6b306e56) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a3218e73bd51d4ef4aa06f208123b1c1f4c629933d28586e20bbe23b2235110) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3a3218e73bd51d4ef4aa06f208123b1c1f4c629933d28586e20bbe23b2235110) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000014823e647de7867c311721787d5ec24d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000014823e647de7867c311721787d5ec24d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000014823e647de7867d311721787d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000014823e647de7867d311721787d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffc00000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffc00000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000114823e647de7867b311721787d5ec24d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffffc00000000000000114823e647de7867b311721787d5ec24d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffff7ffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x264b4c3b3fffffff7ffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000004000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x00000000000000004000000000000000224698fc094cf91b992d30ed00000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xe64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffe0000000000000000ddb96703f6b306e466d2cf12ffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0xbffffffffffffffe0000000000000000ddb96703f6b306e466d2cf12ffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02533e46e64b4c3b40000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000002) + pallasBaseModulus pallasBaseInv = + (Limbs.ofNat 0x21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2c37a71489ba60888d0f36071632bdabf7abe57547cfa14c569bba29179df5c1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000891a63f02652a376311bac8400000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffff76e59c0fd9ad5c8a7a4550682fe74c4fbd6297a500000005) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x125b506bdf33f6aa5feb88c401333d642280770e64abaff06237590800000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x36e59c0fd9ad5c89cee4537bfffffffcefee2ee443109e0ed5f06de700000007) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x125b506bdf33f6aa5feb88c401333d64ab9adafe8afe53669353058c00000008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2da4af9420cc0955a014773bfeccc29bffc621eda4e8f8ed2a0f9218fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20479a657a172f2bd053df0b7b5acf61f516940d35cc6f334c3e480121ca423e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16fba5370a930060cff5e6c18f3efbc1986f687608a3b3fcf657e3356e1c9356) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16a094a2dd10d63d2c60481914864a53c49d67e2fff2361ddc8141f24bcb8913) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2ac11d8d47008bf94cf18afe7fd17c31bea8fcfadd1b069daf58145a6c87f0c3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07945afd7e00a6ecaae30dbeb11ac138e9070a556c84c5f4aef2f319fb865fa2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fea57e1d7583502228891684693b1965d038faf2fd53ebf2dc9e5ec41ca2ca0) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x038c4c2cb8c23f053299d52676a921b7dd1364fa0ac2fcf0fc84cc799aab7c2c) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2c37a71489ba60888d0f36071632bdabf7abe57547cfa14c569bba29179df5c1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x038c4c2cb8c23f053299d52676a921b7dd1364fa0ac2fcf0fc84cc799aab7c2c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3692be50833025568051dceffb330a6fba8b55be807a91f98fb07221fffffff2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3640e16087fd1ae6e300af3fd67183a566437c7da4492248e68449fe0cc0954c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x01f765e81b99e4b2223fb3b2e38572d8f84ef69436e904c98022d08709276b93) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x194190a05e6e9e8c2c35db5bf20b9edcb2b5763b2229611dd38eb15feccc29b0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x388a24389eca0a08a29190a2deb87d48b2da4c52b76396c30fd342a909276b85) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e089a17e4661b4dddc04c4d1c7a8d2729f7a267d2aba4140c241a99f6d8946e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10e39b4454685a50cda5f68d7421d880290d079f1b2efeff5236de2f12b9584d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b69e9ea6b3ef352ce65cb0486bf9ee41c235797a8223a9b07f2158afdc4df11) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x30ad74e124fe0fd490a54db31012ffb9eae004a5908bc2fa359cb7410d8e104d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x091036f343941ce36cbd9dae1bb6b5b9d052a05d8cf4c1e9768fce3835f5853b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x11a0830b593802f951f6f8fe756548c8d841da513ea0771876a98bb914291f34) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x015fc1fe4f6bc49f7f332185abed51d9d68235db8e6e529e7701dbe27fe1cd65) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000891a63f02652a376311bac8400000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3692be50833025568051dceffb330a6fba8b55be807a91f98fb07221fffffff2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015515ab5e093eebac54cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debce) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2f7a89dd176479535790be58c050df13cf1f8766a02b2c22c42b5ea5ce1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x08e3f1ac2cec85a9ebd61c12e24187ee5f46bb56d67d7bf1d99ef159d81f27ea) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x02683a9e88d96a42d2525444f0f72fc4cb896e005cffa087873f20021fc330ac) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1b8c3844ef7c813344df83590724b05d747e3cbeb4846815616d8d7b0972c6ae) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0a4238b7de27388f3c7fefa41b9be8e9c51d89d74ce4065966e9ca9af0679aa4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1a15faed9b09c8b25320734f25c10a1e2a563b1764b2ccaab523a7b787301dc9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x027a9d83cb2d151a417ef47f8f8094d51fadc9677dc2151816869bbdd83802ca) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x260b1bcff7a77ed30f3e5bd83e8757c543ee76f0fb69fb41d53cd52f47fabdcb) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffff76e59c0fd9ad5c8a7a4550682fe74c4fbd6297a500000005) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3640e16087fd1ae6e300af3fd67183a566437c7da4492248e68449fe0cc0954c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015515ab5e093eebac54cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x260b1bcff7a77ed30f3e5bd83e8757c543ee76f0fb69fb41d53cd52f47fabdcb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a37a311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x354977a8362ed6983eccf4ec1f6c1b6cef2a2328b319ab393e3c3d23695cc27f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x17e9cb8457139a3fa1deafb45f6c1b6c9f6ee8da77667f4d4e6fc4072bac54cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea5e9353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1d0dd5994aaafdbb915247b038c80ae3ddd1f438869d7be1b3dfdbb28bd13e92) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3015e65997e23a7e0812ed29f00c525c12f01d43879cddb33c70d9084328d9b8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16acb4ebe857d0d5df2227b5ff215a2a8b94f780dddabc16e2473bfbc764cb7b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0dc24913c28b4fa57ce0e4e232d4db48921ea6321220eb845887d65769047ce1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x06f5879e7548be9436c2abeb5db509810c5d405277106fec6a6b9256f3574092) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00fba9043bac804523250acf5718e5fa5f27a4762881d669ede2565604ec5733) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x125b506bdf33f6aa5feb88c401333d642280770e64abaff06237590800000004) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x01f765e81b99e4b2223fb3b2e38572d8f84ef69436e904c98022d08709276b93) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a37a311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000004891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x200000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x30000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f0f0f09f84f08783843fdf0cf348dc097a0b54e3ab432b63220c4af784f0e97) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b5460f6403423b40d9318fd6638bebd8e6eef198b2949116d2a3efe647edda2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x352c1aa827cc3842bae5326c6b8c0507b63abda4f56ddff1305ffaa8e03ae083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x34166c94559af205116d48c84050df1451976d5c5294ada2ba72ad0190a1681e) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x36e59c0fd9ad5c89cee4537bfffffffcefee2ee443109e0ed5f06de700000007) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x194190a05e6e9e8c2c35db5bf20b9edcb2b5763b2229611dd38eb15feccc29b0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debce) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x354977a8362ed6983eccf4ec1f6c1b6cef2a2328b319ab393e3c3d23695cc27f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000004891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x34166c94559af205116d48c84050df1451976d5c5294ada2ba72ad0190a1681e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x39c87b38b67fb5ac347f03908050df1454a44d80fa9281fe70d7e337cf5debce) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2fffffffffffffffffffffffffffffffd9b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2e601d498373089f5f94d5da69f27957ef96481487e5a7b736bd369f612547a4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3828d38387ee8cda01425d288c785223d5a48e3759503d09e2dc6ea9e39fefc0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x35cedca1e7792b005e925c002e69b1e8a51bb0eb0cdf91d049b1dd1526058824) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0aa32df5f5602aee07a126de3b6108679a01e1b4e89c2dc62431eeb25ed73e4b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3db83389d2fdc8153f65cf02c73d84eb4fd4670fd63dec9e876bbf8d1e344642) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2420b3d392c5663f81c5e7e0d2cc98db3cb0725047f4d0c9828c32b1163a561f) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0f7a89dd176479535790be58c050df13b56a94a998fbad7c9af62e4d0e1a6f7e) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x125b506bdf33f6aa5feb88c401333d64ab9adafe8afe53669353058c00000008) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x388a24389eca0a08a29190a2deb87d48b2da4c52b76396c30fd342a909276b85) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2f7a89dd176479535790be58c050df13cf1f8766a02b2c22c42b5ea5ce1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x17e9cb8457139a3fa1deafb45f6c1b6c9f6ee8da77667f4d4e6fc4072bac54cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x200000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x39c87b38b67fb5ac347f03908050df1454a44d80fa9281fe70d7e337cf5debce) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0f7a89dd176479535790be58c050df13b56a94a998fbad7c9af62e4d0e1a6f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x27f300b6253b8e22241a1a03b17615aef6e770a51131aea80bbfb609506e3681) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3dbc9b94c90d8df6dfe56d42572fee8259f85d19e828e998f4695f0084420e4e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x242f7d914f0b579b71a9032603231e492936b11ea17858fa6f68e8e8e22dc523) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3f6e536005f370d1f76522108727edf17b58477c4251e64a9749c543d0a27b27) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1eb026c016a4fbc4d7729fcbe24b9b86a8785c9970a14fb8030a4896e5b3a2fc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0539f1418d673f8ebe0fd8637cb93332ae25a1aa0978b978001da19694ebfec4) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2da4af9420cc0955a014773bfeccc29bffc621eda4e8f8ed2a0f9218fffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e089a17e4661b4dddc04c4d1c7a8d2729f7a267d2aba4140c241a99f6d8946e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea5e9353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x30000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2fffffffffffffffffffffffffffffffd9b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20f0f0f607b0f787c7bc020f30cb723f8aa5e3adcee076275a26267187b0f16a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e6b5fcc1f1cac229b81225f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x375cbab3a0712997d3368033040192146d8e249c1ca0b7f87e4b8fb32745018c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0ad3e557d833c7bd451acd939473faf86c0bdb571426c8ec5be6f0781fc51f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b65d42d8464cced7badd38343756e97a4247779fda625d03e604a41a17c7ace) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d40ac423dc5d58b836f1c1c12c761a293cec0b97dde047da2afe548434c0407) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3c826e4b14082aff58fa381b66ebb31ffc424a9827324372300385a712a3af71) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20479a657a172f2bd053df0b7b5acf61f516940d35cc6f334c3e480121ca423e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10e39b4454685a50cda5f68d7421d880290d079f1b2efeff5236de2f12b9584d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x08e3f1ac2cec85a9ebd61c12e24187ee5f46bb56d67d7bf1d99ef159d81f27ea) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1d0dd5994aaafdbb915247b038c80ae3ddd1f438869d7be1b3dfdbb28bd13e92) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f0f0f09f84f08783843fdf0cf348dc097a0b54e3ab432b63220c4af784f0e97) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2e601d498373089f5f94d5da69f27957ef96481487e5a7b736bd369f612547a4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x27f300b6253b8e22241a1a03b17615aef6e770a51131aea80bbfb609506e3681) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20f0f0f607b0f787c7bc020f30cb723f8aa5e3adcee076275a26267187b0f16a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3c826e4b14082aff58fa381b66ebb31ffc424a9827324372300385a712a3af71) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cc98a7c4a2f2d1577731209ca0bb4345acf26d96e40b1a3621c4b697c1f89a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3af6ee59b3b4c38b0c54be9896161e88bd2a6b3048071d6589bd19dad1f26ffb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1abad769c6cbad4123a911553b6e7852138fc045cf42b1fb85534fd5c8b7cddd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0ee9cb3f0c351f50055b7dd7ae3544e2a01c48185ebf81b388f231fab7cab006) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d32c8fb7d3d545107b4a69a4c5b2e75eab93d6f80b3cd86eee20d43663e5339) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x071895d90ab40b08c4b42617ac1cdd5513304a1aff12e439c017aaa5c9466628) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16fba5370a930060cff5e6c18f3efbc1986f687608a3b3fcf657e3356e1c9356) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b69e9ea6b3ef352ce65cb0486bf9ee41c235797a8223a9b07f2158afdc4df11) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x02683a9e88d96a42d2525444f0f72fc4cb896e005cffa087873f20021fc330ac) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3015e65997e23a7e0812ed29f00c525c12f01d43879cddb33c70d9084328d9b8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b5460f6403423b40d9318fd6638bebd8e6eef198b2949116d2a3efe647edda2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3828d38387ee8cda01425d288c785223d5a48e3759503d09e2dc6ea9e39fefc0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3dbc9b94c90d8df6dfe56d42572fee8259f85d19e828e998f4695f0084420e4e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e6b5fcc1f1cac229b81225f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cc98a7c4a2f2d1577731209ca0bb4345acf26d96e40b1a3621c4b697c1f89a7) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x071895d90ab40b08c4b42617ac1cdd5513304a1aff12e439c017aaa5c9466628) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x246419a4981faaddc27e8d0019c448456fd856014fa4b0db941ae20af878ac3a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b6909a05dbf22befee2b044abcd8be253ec04353872409056b582ed8ab676e9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x193b8747b4746b70f877067f44e731bdfa6932f2e629d4909748eb6234c0a751) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0209da84c6f912d00000b696ba1b54f5ca8ef4ab4e7d28f5b128d1b75aa555cb) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x28435f86f478c99d44fc0ad902afe026c9368241bbf2fd91c20583bd78c314ef) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16a094a2dd10d63d2c60481914864a53c49d67e2fff2361ddc8141f24bcb8913) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x30ad74e124fe0fd490a54db31012ffb9eae004a5908bc2fa359cb7410d8e104d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1b8c3844ef7c813344df83590724b05d747e3cbeb4846815616d8d7b0972c6ae) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x16acb4ebe857d0d5df2227b5ff215a2a8b94f780dddabc16e2473bfbc764cb7b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x35cedca1e7792b005e925c002e69b1e8a51bb0eb0cdf91d049b1dd1526058824) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x242f7d914f0b579b71a9032603231e492936b11ea17858fa6f68e8e8e22dc523) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x375cbab3a0712997d3368033040192146d8e249c1ca0b7f87e4b8fb32745018c) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3af6ee59b3b4c38b0c54be9896161e88bd2a6b3048071d6589bd19dad1f26ffb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x246419a4981faaddc27e8d0019c448456fd856014fa4b0db941ae20af878ac3a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x28435f86f478c99d44fc0ad902afe026c9368241bbf2fd91c20583bd78c314ef) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3f744b5a1aea28e70d8ad46f3327904a134f8a4051fd9dfa111fd1f5d5c938c9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x03efd48ce6c15c4f257ad17a20e64d1c1a6215ad1e97f54e0f7e2ce750c5441a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3eb73a2da6c346e9eefbb70091ae4f358ab2d0eef6bed877e8232e30747a4648) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d5449b2fe7e68a890240a11344fe522edcaea8796292af2d0d8fb99b79db040) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2ac11d8d47008bf94cf18afe7fd17c31bea8fcfadd1b069daf58145a6c87f0c3) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x091036f343941ce36cbd9dae1bb6b5b9d052a05d8cf4c1e9768fce3835f5853b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0a4238b7de27388f3c7fefa41b9be8e9c51d89d74ce4065966e9ca9af0679aa4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0dc24913c28b4fa57ce0e4e232d4db48921ea6321220eb845887d65769047ce1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x352c1aa827cc3842bae5326c6b8c0507b63abda4f56ddff1305ffaa8e03ae083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0aa32df5f5602aee07a126de3b6108679a01e1b4e89c2dc62431eeb25ed73e4b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3f6e536005f370d1f76522108727edf17b58477c4251e64a9749c543d0a27b27) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0ad3e557d833c7bd451acd939473faf86c0bdb571426c8ec5be6f0781fc51f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1abad769c6cbad4123a911553b6e7852138fc045cf42b1fb85534fd5c8b7cddd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b6909a05dbf22befee2b044abcd8be253ec04353872409056b582ed8ab676e9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3f744b5a1aea28e70d8ad46f3327904a134f8a4051fd9dfa111fd1f5d5c938c9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d5449b2fe7e68a890240a11344fe522edcaea8796292af2d0d8fb99b79db040) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b3fabae42dffc45164e657541c6b93696e8f3fcdfb4760f33ce254e2256c55b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2d7db430e8803ea69f052e2842768f1b94f4de6d72a0fd3c4daac60d51d4d068) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x04a79fe0cdfaa798f1a3dd8da208e41b79987431a7264d941832206dceae62b2) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07945afd7e00a6ecaae30dbeb11ac138e9070a556c84c5f4aef2f319fb865fa2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x11a0830b593802f951f6f8fe756548c8d841da513ea0771876a98bb914291f34) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1a15faed9b09c8b25320734f25c10a1e2a563b1764b2ccaab523a7b787301dc9) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x06f5879e7548be9436c2abeb5db509810c5d405277106fec6a6b9256f3574092) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3db83389d2fdc8153f65cf02c73d84eb4fd4670fd63dec9e876bbf8d1e344642) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1eb026c016a4fbc4d7729fcbe24b9b86a8785c9970a14fb8030a4896e5b3a2fc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b65d42d8464cced7badd38343756e97a4247779fda625d03e604a41a17c7ace) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0ee9cb3f0c351f50055b7dd7ae3544e2a01c48185ebf81b388f231fab7cab006) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x193b8747b4746b70f877067f44e731bdfa6932f2e629d4909748eb6234c0a751) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x03efd48ce6c15c4f257ad17a20e64d1c1a6215ad1e97f54e0f7e2ce750c5441a) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3b3fabae42dffc45164e657541c6b93696e8f3fcdfb4760f33ce254e2256c55b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x04a79fe0cdfaa798f1a3dd8da208e41b79987431a7264d941832206dceae62b2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fbc4473858d96888a4cf4f26122be6d5452e97f2372b0740ea8da1591130845) := by + decide +kernel + +example : + sqrMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e0a34d529799ca3bb2cd3d706454717da0139fab7c3ec1918efdc79a0f7527f) := by + decide +kernel + +example : + fromMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fea57e1d7583502228891684693b1965d038faf2fd53ebf2dc9e5ec41ca2ca0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x015fc1fe4f6bc49f7f332185abed51d9d68235db8e6e529e7701dbe27fe1cd65) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x027a9d83cb2d151a417ef47f8f8094d51fadc9677dc2151816869bbdd83802ca) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00fba9043bac804523250acf5718e5fa5f27a4762881d669ede2565604ec5733) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2420b3d392c5663f81c5e7e0d2cc98db3cb0725047f4d0c9828c32b1163a561f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0539f1418d673f8ebe0fd8637cb93332ae25a1aa0978b978001da19694ebfec4) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d40ac423dc5d58b836f1c1c12c761a293cec0b97dde047da2afe548434c0407) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d32c8fb7d3d545107b4a69a4c5b2e75eab93d6f80b3cd86eee20d43663e5339) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0209da84c6f912d00000b696ba1b54f5ca8ef4ab4e7d28f5b128d1b75aa555cb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3eb73a2da6c346e9eefbb70091ae4f358ab2d0eef6bed877e8232e30747a4648) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2d7db430e8803ea69f052e2842768f1b94f4de6d72a0fd3c4daac60d51d4d068) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fbc4473858d96888a4cf4f26122be6d5452e97f2372b0740ea8da1591130845) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + (Limbs.ofNat 0x0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e0a34d529799ca3bb2cd3d706454717da0139fab7c3ec1918efdc79a0f7527f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf590f0d5a72daf6cba5a2db2258300000013) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf590f0d5a72daf6cba5a2db2258300000013) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e7055f0f197b81f0950abbb8948d5d39bc7300f5c1ea51f903bb43e249dae3e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3e7055f0f197b81f0950abbb8948d5d39bc7300f5c1ea51f903bb43e249dae3e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015516ab5e093eebac54cb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015516ab5e093eebac54cb) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fffffffffffffffffffffffffffffffe64b0d42f8d08159d6cacfa73fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fffffffffffffffffffffffffffffffe64b0d42f8d08159d6cacfa73fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debcd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x29c87b38b67fb5ac347f03908050df150c12a741f82d57c70dc6286f8f5debcd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2f7a89dd176479535790be58c050df12acd8ee6a9696834537e47384ce1a6f7d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2f7a89dd176479535790be58c050df13acd8ee6a9696834537e47384ce1a6f7d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x300000000000000000000000000000003bfb8bb910c42783b57c1b79c0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x300000000000000000000000000000003bfb8bb910c42783b57c1b79c0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df12c68de1279dc601eb6119a3dd8e1a6f7d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df12c68de1279dc601eb6119a3dd8e1a6f7d) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a62fb09e8c28c4acd4b5bb9a9ea26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xc28c44a5576479521790be58c050df1294c8c9a26e4db0782ebd7cee0a8760df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xc28c44a5576479521790be58c050df1394c8c9a26e4db0782ebd7cee0a8760df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205665b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205665b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaaa08c887002b1f990698d6efc1891a16e7fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaaa08c887002b1f990698d6efc1891a16e7fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x082f7490699a9d38264ffc7bb2d7522e3583b391b7d582d6a9b76a4017dd18f2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x082f7490699a9d38264ffc7bb2d7522e3583b391b7d582d6a9b76a4017dd18f2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a72fb09e8c28c4acd5b5bb9a9ea26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a72fb09e8c28c4acd5b5bb9a9ea26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x21deafb45f6c1b6c92a053dc20e4c3a7753564a6832c02b262681f30a3b19701) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x21deafb45f6c1b6c92a053dc20e4c3a7753564a6832c02b262681f30a3b19701) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x347f03908050df13f5b20ea460e4c3a73f2f1d154ea8556b5bd0d66d2601294f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x347f03908050df13f5b20ea460e4c3a83f2f1d154ea8556b5bd0d66d2601294f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a60d6a05901f3003f7e974af7da26e1ab1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a70d6a05901f3003f7e974af7da26e1ab1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8ddcc46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8ddcc46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1790be58c050df13b5b20ea460e4c3a62fb09e8c28c4acd4b5bb9a9ea26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xf5b20ea460e4c3a62311bac83fffffffba7b39e5a598aa2253537b6dfebc83b1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xf5b20ea460e4c3a62311bac83fffffffba7b39e5a598aa2253537b6dfebc83b1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a60d6a05901f3003f72974af7da26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3a88ee337ccfdaad3640e16087fd1ae78b74636b990a825fed6704ea66b5723b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3a88ee337ccfdaad3640e16087fd1ae78b74636b990a825fed6704ea66b5723b) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x128c5784fabf23b20173141b1ae1430afb46d7d1d84397cf26c1ef1391979314) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x128c5784fabf23b20173141b1ae1430afb46d7d1d84397cf26c1ef1391979314) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x028c44a5576479531790be58c050df13b70f629e77e25955bb04680f0a8760e1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x028c44a5576479531790be58c050df13b70f629e77e25955bb04680f0a8760e1) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2afb864c97139a3f61deafb45f6c1b6ca9a55d0e58b2555e918fb8916819462e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2afb864c97139a3f61deafb45f6c1b6ca9a55d0e58b2555e918fb8916819462e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fffffffffffffffbfffffffffffffffe64b0d42f8d08159d6cacfa73fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0fffffffffffffffbfffffffffffffffe64b0d42f8d08159d6cacfa73fffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0cda3600f67fb5abf47f03908050df14fc9428b8d249af3067b0eca10bcadd30) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0cda3600f67fb5abf47f03908050df14fc9428b8d249af3067b0eca10bcadd30) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x128c44a557647952d790be58c050df139d5a6fe170b2daaf91cf37b64a8760e0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x128c44a557647952d790be58c050df139d5a6fe170b2daaf91cf37b64a8760e0) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x300000000000000040000000000000003bfb8bb910c42783b57c1b79c0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x300000000000000040000000000000003bfb8bb910c42783b57c1b79c0000002) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xc28c44a5576479521790be58c050df1394c8c9a26e4db0782ebd7cee0a8760df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xc28c44a5576479521790be58c050df1294c8c9a26e4db0782ebd7cee0a8760df) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xd790be58c050df12b5b20ea460e4c3a60d6a05901f3003f72974af7da26e1ab2) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe59dff6d97647950d790be58c050df14a790e41551feb0c014ef2c4086f45243) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe59dff6d97647950d790be58c050df14a790e41551feb0c014ef2c4086f45243) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3a88ee337ccfdaad3640e16087fd1ae70259ff7b72b7dee9bc4b586666b57237) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3a88ee337ccfdaad3640e16087fd1ae70259ff7b72b7dee9bc4b586666b57237) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1bf99934778efe5b8121372b1fae389b63021b0f615daeb32358681291979323) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1bf99934778efe5b8121372b1fae389b63021b0f615daeb32358681291979323) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000012c81a72e3b10047e631af527c6cf163) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000012c81a72e3b10047e631af527c6cf163) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000012c81a72e3b10048e631af527c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000012c81a72e3b10048e631af527c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffc00000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffc00000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000112c81a72e3b10046e631af527c6cf163) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffffc00000000000000112c81a72e3b10046e631af527c6cf163) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffff7ffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x2311bac83fffffff7ffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000004000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x00000000000000004000000000000000224698fc0994a8dd8c46eb2100000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xe311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffe0000000000000000ddb96703f66b572273b914deffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0xbffffffffffffffe0000000000000000ddb96703f66b572273b914deffffffff) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x000000000000000000000000000000000000000000000000ffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x4000000000000000000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x100000000000000000000000000000000891a63f02652a376311bac840000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xfffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0xffffffffffffffff000000000000000000000000000000000000000000000000) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x0000000000000000000000000000000000000000000000000000000000000000) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + +example : + mulMont + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + (Limbs.ofNat 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002) + vestaBaseModulus vestaBaseInv = + (Limbs.ofNat 0x1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f) := by + decide +kernel + + +-- 1052 vectors. + +end CompElliptic.Asm.AArch64 diff --git a/CompElliptic/Asm/AArch64/Semantics.lean b/CompElliptic/Asm/AArch64/Semantics.lean new file mode 100644 index 0000000..c67b3f2 --- /dev/null +++ b/CompElliptic/Asm/AArch64/Semantics.lean @@ -0,0 +1,84 @@ +/- +Copyright (c) 2026 CompElliptic Contributors. +Released under the Apache License, Version 2.0, or the MIT license, at your option, +as described in the files LICENSE-APACHE and LICENSE-MIT. +Authors: Daira-Emma Hopwood +-/ + +/-! +# AArch64 instruction semantics for the Pasta Montgomery routines + +The subset of AArch64 that `pasta_mul-armv8.S` uses: `mul`, `umulh`, `adds`/`adcs`/`adc`, +`subs`/`sbcs`, `lsl`/`lsr` by an immediate, `csel` on the `lo` condition, and `mov`. Loads and +stores are not modelled as memory operations: the generated programs read their operand limbs +where the assembly loads them and return the limbs the assembly stores. + +A register value is a natural number below `2^64`. The bound is maintained by construction: +every instruction reduces its result modulo `2^64`, and the carry flag is the quotient of the +same sum by `2^64`, so it is `0` or `1` whenever the inputs are in range. Working in `Nat` +rather than a fixed-width type keeps the proofs in `omega`'s fragment (`%` and `/` by +literals) and lets the reference vectors be checked by the kernel with `decide`. + +AArch64's carry convention for subtraction is the one modelled here: after `subs`/`sbcs` the +carry is set exactly when no borrow occurred, so `sbcs` subtracts `1 - carry` and `subs` +behaves as `sbcs` with the carry set. The `lo` condition of `csel` is "carry clear". +-/ + +namespace CompElliptic.Asm.AArch64 + +/-- The register width, as the modulus of every register write. -/ +abbrev regMod : Nat := 2^64 + +/-- `mul`: the low 64 bits of the product. -/ +def mulLo (a b : Nat) : Nat := a * b % regMod + +/-- `umulh`: the high 64 bits of the product. -/ +def umulh (a b : Nat) : Nat := a * b / regMod + +/-- `adds`, `adcs`, and `adc`: the low 64 bits of `a + b + c` and the carry-out. `adds` passes +carry-in `0`; `adc` discards the carry-out. -/ +def addc (a b c : Nat) : Nat × Nat := ((a + b + c) % regMod, (a + b + c) / regMod) + +/-- `subs` and `sbcs`: the low 64 bits of `a - b - (1 - c)` and the carry-out, where a carry of +`1` means that no borrow occurred. `subs` passes carry-in `1`. The difference is formed as +`a + 2^64 - b - (1 - c)`, which is nonnegative for in-range operands, so the quotient by `2^64` +is `1` exactly when `a ≥ b + (1 - c)`. -/ +def subc (a b c : Nat) : Nat × Nat := + ((a + regMod - b - (1 - c)) % regMod, (a + regMod - b - (1 - c)) / regMod) + +/-- `lsl` by an immediate. -/ +def lsl (a k : Nat) : Nat := a * 2^k % regMod + +/-- `lsr` by an immediate. -/ +def lsr (a k : Nat) : Nat := a / 2^k + +/-- `csel d, x, y, lo`: `x` when the carry is clear, else `y`. -/ +def cselLo (c x y : Nat) : Nat := if c = 0 then x else y + +/-- Four little-endian 64-bit limbs, the shape of every operand of the routines. -/ +structure Limbs where + /-- Limb of weight `2^0`. -/ + l0 : Nat + /-- Limb of weight `2^64`. -/ + l1 : Nat + /-- Limb of weight `2^128`. -/ + l2 : Nat + /-- Limb of weight `2^192`. -/ + l3 : Nat + deriving DecidableEq, Repr + +namespace Limbs + +/-- The integer that a limb vector represents. -/ +def toNat (x : Limbs) : Nat := x.l0 + 2^64 * x.l1 + 2^128 * x.l2 + 2^192 * x.l3 + +/-- The limbs of a natural number; bits at and above `2^256` are dropped. -/ +def ofNat (n : Nat) : Limbs := + ⟨n % 2^64, n / 2^64 % 2^64, n / 2^128 % 2^64, n / 2^192 % 2^64⟩ + +/-- Every limb is below `2^64`. -/ +def Bounded (x : Limbs) : Prop := x.l0 < 2^64 ∧ x.l1 < 2^64 ∧ x.l2 < 2^64 ∧ x.l3 < 2^64 + +end Limbs + +end CompElliptic.Asm.AArch64 diff --git a/CompElliptic/Asm/AArch64/vendor/SHA256SUMS b/CompElliptic/Asm/AArch64/vendor/SHA256SUMS new file mode 100644 index 0000000..629d149 --- /dev/null +++ b/CompElliptic/Asm/AArch64/vendor/SHA256SUMS @@ -0,0 +1,2 @@ +0bcd5fa67d4aef5043eb536fdefd41ce16e6f7fbac3e5e6ac4f7619b35fd5e85 pasta_mul-armv8.S +4c82813b609fe04a195fcfc6dfaf0ee0396f8dd579f568b9e418a20f0a8dfae8 pasta_mul-armv8-vectors.txt diff --git a/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt b/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt new file mode 100644 index 0000000..cda570f --- /dev/null +++ b/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt @@ -0,0 +1,1052 @@ +FROM Fp 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000000 +SQR Fp 0000000000000000000000000000000000000000000000000000000000000001 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +FROM Fp 0000000000000000000000000000000000000000000000000000000000000001 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000001 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 000000000000000000000000000000000000000000000000ffffffffffffffff 0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f +SQR Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +FROM Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 000000000000000000000000000000000000000000000000ffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 4000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 +SQR Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 +FROM Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 21cce888a6cab566710d6cd04c692c9784379b4cc10e927b1dfc65f6ad0492ae +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 00000000000000000000000000000000891a63f02533e46e64b4c3b400000004 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffff76e59c0fdacc1b9246ac39382e80dd85fde1f4a100000005 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 4000000000000000000000000000000000000000000000000000000000000000 125b506bdee72dc51de5ea66f0f257463e8669ae6516b680c969876800000004 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 36e59c0fdacc1b919b4b3c4bfffffffcefee2ee4411acfc1303c567b00000007 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 125b506bdee72dc51de5ea66f0f25746c7a0cd9e8a4a9aef2e1e4b1c00000008 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 2da4af942118d23ae21a15990f0da8b9e3c02f4da436429acfc3a984fffffffd +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3031b67010dc5f33e1768c975480689a91ad57216c5706a8810c3c6089daf8b6 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3b22a80cd2c81a0c889a01873458140ef909266c546d35f5014930b21f53b554 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 10548582022977317020e583ebc9e08237f899a30131ff72b3387ebd971aec55 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 348bf875968510c9c9602914af00483e46f3b5921d2c02b91578ba31cf7bad4c +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0791f325de14e664b4aa62282e98a644f50840433dbfc7626da70eaaf58145f5 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 08102d3c3c95a063e1e6c2328bbd8e7ed2a208c993640dc0c477d288cfba797a +SQR Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0662a11d61e1a30f915945eff265faff24953adafa8636a3c01ff3639e2aed4c +FROM Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0000000000000000000000000000000000000000000000000000000000000001 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 21cce888a6cab566710d6cd04c692c9784379b4cc10e927b1dfc65f6ad0492ae +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0662a11d61e1a30f915945eff265faff24953adafa8636a3c01ff3639e2aed4c +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3692be50846348eb886856643c36a2e74a738b3e7e3f18340cb44439fffffff2 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 000000000000000000000000000000000000000000000000ffffffffffffffff 2e2a67ec482ca6045b2ef3341a17f2ecf6a3c75cc8bdaf33e0efe592118d23a0 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 4000000000000000000000000000000000000000000000000000000000000000 3ab8c2488b4b664437e344050d4ff50b575e968be1ab27492f434e180ea7843f +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 09595b20624498f13919469f2d8f1ea91d1e34d0388bbd88e9421d36f0da8b8e +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 314b80990faeaf2fc04b9a69498697f27f8b88ce569d4661a2ca61650ea78430 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 05473db774b499bbc81cbbfaf2b00af4cae8027027a1d1d269e9e2d4f1587bc2 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 11059dda0a0984a24c432eaa84cb8a47e785e51edefe7cefa723d05be7cd96b1 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2a8c68e806154a62330fa85f54dedea8453b7a0d756f7860ca191c12c6265afb +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 28b001b79faac705f426b23ca533d40220e19e6209f724ada5c28c17b9f0d326 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3c2c602b7bf8fbf1790afd71b3e16fad0c5531d44cf930398f831a05338f2444 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3d679a6b16f9788e6430d173a58607f8d5e7ec854b246cf10a63c8d6170c9008 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 096a1374bdff44bcdb81d15301f0d099d8fc397f7e24afe149933c9ef8a6efe3 +SQR Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +FROM Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0000000000000000000000000000000000000000000000000000000000000001 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 00000000000000000000000000000000891a63f02533e46e64b4c3b400000004 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3692be50846348eb886856643c36a2e74a738b3e7e3f18340cb44439fffffff2 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 000000000000000000000000000000000000000000000000ffffffffffffffff 31269b682e59de6fd65951678f204af90e79463ab37aa332256c3921cc314cff +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33f +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 31f1c4ff1e2278d570cb2996efc89a65b53160a942cb3a9eb58adac293a769a9 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 075fd91f3b718e08c51be01df5028ccc419bfe790f5b558fc4eb03ea21c2bedc +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3a80d4fab5ba20a8a16195cd72a675e5f66caca2755bd372e73d60d346332931 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 1c2e48522b3388de50ade90d1f25cd139a10bd0f15f3fc4da795b0484e2be97c +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0c942c15724e2a539b07cff51781ad5803eb22a0d9a2d7be0b3215dfda494d90 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 24ec7781e5ebd60e91be9e56ea3634df88c55c71ebc034e1a63b4075c102abe4 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3be85d8069b8128c838e08fd1ed8306682f054442bd65e6f1bbc40a1c35cc5b2 +SQR Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 1acd4a009f399376e232c5736e77fb8c1c35dfa341e703db83392c958598c6be +FROM Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 000000000000000000000000000000000000000000000000ffffffffffffffff +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffff76e59c0fdacc1b9246ac39382e80dd85fde1f4a100000005 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2e2a67ec482ca6045b2ef3341a17f2ecf6a3c75cc8bdaf33e0efe592118d23a0 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 31269b682e59de6fd65951678f204af90e79463ab37aa332256c3921cc314cff +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 1acd4a009f399376e232c5736e77fb8c1c35dfa341e703db83392c958598c6be +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000000891a63f02533e47264b4c3b40000000 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3d000f740db18f02f00e052c4f204af954d1de0b0cab76c3b5b5e0d408b278e3 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 01269b682e59de6fd65951678f204af8f4c4537dac80e85db28a54700c314cfe +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3000000000000000000000000000000019b4f2bd06f9bad472e1e4b1c0000001 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0243f901466f013c8772ef73a588001a8cfd085e39574506f699f0ce0f88f6ff +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 191f3f2d4313aac2ca49e3117da6cccc88309e28da5f78ff277a04b81d1babd3 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0b805f450c0dbbcac5b4d865b01cc2cfdf8b1a0da5a185b347115895fafa0cf5 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 318c5c205acc7cfb9dd944e14c01dc9dc04c7e3f598fcdcf20995458a381f6df +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 132dd92afbb5a12f1cbf9c47baf77e853f10c4c3988db021b3feac2f58b2041e +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 385a54834adfe22620b33bbf39551c1ebe43143dccc4fe9a83b5c6ed6a3d0fe4 +SQR Fp 4000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 +FROM Fp 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 4000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 125b506bdee72dc51de5ea66f0f257463e8669ae6516b680c969876800000004 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3ab8c2488b4b664437e344050d4ff50b575e968be1ab27492f434e180ea7843f +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 100000000000000000000000000000000891a63f02533e47264b4c3b40000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 100000000000000000000000000000004891a63f02533e46e64b4c3b40000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 200000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 30000000000000000000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1f0f0f09f84f08783843fdf0cf348dc097a0b54e3aa246c5b55a5622784f0e97 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3b5460f6403423b40d9318fd6638bebd8e6eef198af3853ff6d6f357647edda2 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 352c1aa827cc3842bae5326c6b8c0507b63abda4f5381c1fba0caf01e03ae083 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa +SQR Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2d0e14a05cd1d9fc243491206fc89a663293063e00578f9e26d1cbe7d1ec3cd7 +FROM Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 00000000000000000000000000000000ffffffffffffffffffffffffffffffff +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 36e59c0fdacc1b919b4b3c4bfffffffcefee2ee4411acfc1303c567b00000007 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 09595b20624498f13919469f2d8f1ea91d1e34d0388bbd88e9421d36f0da8b8e +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33f +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 3d000f740db18f02f00e052c4f204af954d1de0b0cab76c3b5b5e0d408b278e3 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000004891a63f02533e46e64b4c3b40000000 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2d0e14a05cd1d9fc243491206fc89a663293063e00578f9e26d1cbe7d1ec3cd7 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 177feccfbd7a2968ca7fdd5bafc89a662707ba151e1487b414bd60fc52c9d33f +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 2fffffffffffffffffffffffffffffffd9b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 09b6e874ebf7015713395bc67cb37e35bf190f9737a661f2590218bef5ccf20d +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2369223ec0ba778f450631700e279844d7602068e54753affa279ed410cd00c8 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 113537aabc2a7e9a9f170ff0466ace9eb6bd66c2ac39a2cb6bcd60b2cac31dca +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0f65a101a6ce5999439c8a3a3746ccd5da1def3365e774fd07693f94385002f0 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 2fed7572b6ad1fb4518addae8bb2afaca112b6073915376d60bf257769db7f62 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 190d90428434fe44c0c829966224346c7b42f390ed1288f2ffb94f3b3ebd874b +SQR Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 11f1c4ff1e2278d570cb2996efc89a659b7c6dec3bd17fca02a8f610d3a769a8 +FROM Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 125b506bdee72dc51de5ea66f0f25746c7a0cd9e8a4a9aef2e1e4b1c00000008 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 314b80990faeaf2fc04b9a69498697f27f8b88ce569d4661a2ca61650ea78430 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 31f1c4ff1e2278d570cb2996efc89a65b53160a942cb3a9eb58adac293a769a9 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 01269b682e59de6fd65951678f204af8f4c4537dac80e85db28a54700c314cfe +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 200000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 177feccfbd7a2968ca7fdd5bafc89a662707ba151e1487b414bd60fc52c9d33f +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 11f1c4ff1e2278d570cb2996efc89a659b7c6dec3bd17fca02a8f610d3a769a8 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 2000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 266ee82933c09680fd5fde0ec4371a8cd93cb3c749fd9c557a455a0c9a11cd73 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 35d535f0f5ee445caef4aecad8df34a3629502bff7025f9744e7233daab206d2 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 24d18d9e8ac25f467d7768da1b243aff4ec9316f02e7ed32b5910bb626e6e7f1 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 01c046bd9a1a629655ed0261830db25f97df4749c58dfac22c1193f4ba842e12 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 2986a354618709211610cad3a6c0c64806e77df3f7aeb7eef421e1551f863117 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3ea7b13e2bf23d01001eece10c10cec411682c86b78d02cf0553467a8010c1ac +SQR Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 1000000000000000000000000000000000000000000000000000000000000000 +FROM Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000001 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2da4af942118d23ae21a15990f0da8b9e3c02f4da436429acfc3a984fffffffd +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 05473db774b499bbc81cbbfaf2b00af4cae8027027a1d1d269e9e2d4f1587bc2 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 000000000000000000000000000000000000000000000000ffffffffffffffff 3000000000000000000000000000000019b4f2bd06f9bad472e1e4b1c0000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 4000000000000000000000000000000000000000000000000000000000000000 30000000000000000000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2fffffffffffffffffffffffffffffffd9b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 1000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 20f0f0f607b0f787c7bc020f30cb723f8aa5e3adceaab255e3d2daca87b0f16a +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e5973dba2563d959b81225f +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 375cbab3a0712997d3368033040192146d8e249c1c5908368b31d57f2745018c +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0ad3e557d833c7bd451acd939473faf86c0bdb571414dcfbdf2081eb1fc51f7e +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3b65d42d8464cced7badd38343756e97a4247779fd5e760e4b46900da17c7ace +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3d40ac423dc5d58b836f1c1c12c761a293cec0b97d9654bbaf962b14434c0407 +SQR Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3e3eab736edbf3946567e005720448fa968090b33ceae01c4381bc2109eeaf68 +FROM Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000001 38a026e0c48e71f73ae41fe20afd7333e0aa9a82f9f1a38bd4422d02de3d4125 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3031b67010dc5f33e1768c975480689a91ad57216c5706a8810c3c6089daf8b6 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 11059dda0a0984a24c432eaa84cb8a47e785e51edefe7cefa723d05be7cd96b1 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 075fd91f3b718e08c51be01df5028ccc419bfe790f5b558fc4eb03ea21c2bedc +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 000000000000000000000000000000000000000000000000ffffffffffffffff 0243f901466f013c8772ef73a588001a8cfd085e39574506f699f0ce0f88f6ff +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 4000000000000000000000000000000000000000000000000000000000000000 1f0f0f09f84f08783843fdf0cf348dc097a0b54e3aa246c5b55a5622784f0e97 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 09b6e874ebf7015713395bc67cb37e35bf190f9737a661f2590218bef5ccf20d +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 266ee82933c09680fd5fde0ec4371a8cd93cb3c749fd9c557a455a0c9a11cd73 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 20f0f0f607b0f787c7bc020f30cb723f8aa5e3adceaab255e3d2daca87b0f16a +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3e3eab736edbf3946567e005720448fa968090b33ceae01c4381bc2109eeaf68 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3a9fa1eab51f114925de48e933973c839a851f8d16897802cce98a6267201387 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2433c132353f7a7f730575508359403919905b802503b90d7f4089fc0acd1e2a +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 18a27a96677cebda48524b4f66ca32081b52f70b717294b8645d87743ef435db +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1b1d201950d04201d5a13d2f40f232fcf3da86444bfbdd96a840d51974c1a9d7 +MUL Fp 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0fe1bce271b680a3432473b59a47a1c89bb3fa7f9abd3fc2582838316659e21a +SQR Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 23e2d584e303750afbe701cc135a158c167f8e478e3e5fc5d9a12bd944145437 +FROM Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000001 057f2b054a45df575e9e6a328d598a1a2bd9ec5993f125a8b1efd019b9ccd6d0 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3b22a80cd2c81a0c889a01873458140ef909266c546d35f5014930b21f53b554 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2a8c68e806154a62330fa85f54dedea8453b7a0d756f7860ca191c12c6265afb +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3a80d4fab5ba20a8a16195cd72a675e5f66caca2755bd372e73d60d346332931 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 000000000000000000000000000000000000000000000000ffffffffffffffff 191f3f2d4313aac2ca49e3117da6cccc88309e28da5f78ff277a04b81d1babd3 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 4000000000000000000000000000000000000000000000000000000000000000 3b5460f6403423b40d9318fd6638bebd8e6eef198af3853ff6d6f357647edda2 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2369223ec0ba778f450631700e279844d7602068e54753affa279ed410cd00c8 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 35d535f0f5ee445caef4aecad8df34a3629502bff7025f9744e7233daab206d2 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e5973dba2563d959b81225f +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3a9fa1eab51f114925de48e933973c839a851f8d16897802cce98a6267201387 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 23e2d584e303750afbe701cc135a158c167f8e478e3e5fc5d9a12bd944145437 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3ce872d15beb15e7588f5de133d0911cd1c2e096c89f9f45c5e09880d85839c5 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3259897b8dc9480ee45a3263849a285c4956e607a01e8d672e92443b91d4af79 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 13b5bc4323ef673b7d2ebb04dc796bcc0595773c37288657aa1b5b21897e52d4 +MUL Fp 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 241142522c7e16f6adc74f23033257a67598c7dbd63840792ffe83c6b9c1e770 +SQR Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 101375a000c3fbfa17d36b7a1e49055624cd7677331a60db2cc29f483741ff50 +FROM Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000001 23d1b7add4cc7721af5216f2e0da32ec8835dbecf358fccdf19780a4b1d41685 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 10548582022977317020e583ebc9e08237f899a30131ff72b3387ebd971aec55 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 28b001b79faac705f426b23ca533d40220e19e6209f724ada5c28c17b9f0d326 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 1c2e48522b3388de50ade90d1f25cd139a10bd0f15f3fc4da795b0484e2be97c +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 000000000000000000000000000000000000000000000000ffffffffffffffff 0b805f450c0dbbcac5b4d865b01cc2cfdf8b1a0da5a185b347115895fafa0cf5 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 4000000000000000000000000000000000000000000000000000000000000000 08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 113537aabc2a7e9a9f170ff0466ace9eb6bd66c2ac39a2cb6bcd60b2cac31dca +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 24d18d9e8ac25f467d7768da1b243aff4ec9316f02e7ed32b5910bb626e6e7f1 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 375cbab3a0712997d3368033040192146d8e249c1c5908368b31d57f2745018c +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 2433c132353f7a7f730575508359403919905b802503b90d7f4089fc0acd1e2a +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3ce872d15beb15e7588f5de133d0911cd1c2e096c89f9f45c5e09880d85839c5 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 101375a000c3fbfa17d36b7a1e49055624cd7677331a60db2cc29f483741ff50 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 216088e1212a7e3fc1f7dec7525eecdf393fe793f52a875cf043848ad8095cc3 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 35c5000bc6c052e6674d650b37e06a3a0a4fba0c34fd24ce261a45452089bc46 +MUL Fp 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2565d74b6f42ec480e49fae1cd43df66bbb7502f0cef496c28f6c4879667d453 +SQR Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 1677ce27814b54d771a091ab04eef7ad2cdf503fcfe6b9e8dad6ba85e7d8fbc9 +FROM Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000001 336bd3ea8db1d5ac64f8300ae87e52a81e5b765b2faa215d8dfb1b0d25b6b271 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 348bf875968510c9c9602914af00483e46f3b5921d2c02b91578ba31cf7bad4c +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3c2c602b7bf8fbf1790afd71b3e16fad0c5531d44cf930398f831a05338f2444 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0c942c15724e2a539b07cff51781ad5803eb22a0d9a2d7be0b3215dfda494d90 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 000000000000000000000000000000000000000000000000ffffffffffffffff 318c5c205acc7cfb9dd944e14c01dc9dc04c7e3f598fcdcf20995458a381f6df +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 4000000000000000000000000000000000000000000000000000000000000000 352c1aa827cc3842bae5326c6b8c0507b63abda4f5381c1fba0caf01e03ae083 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0f65a101a6ce5999439c8a3a3746ccd5da1def3365e774fd07693f94385002f0 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 01c046bd9a1a629655ed0261830db25f97df4749c58dfac22c1193f4ba842e12 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0ad3e557d833c7bd451acd939473faf86c0bdb571414dcfbdf2081eb1fc51f7e +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 18a27a96677cebda48524b4f66ca32081b52f70b717294b8645d87743ef435db +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3259897b8dc9480ee45a3263849a285c4956e607a01e8d672e92443b91d4af79 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 216088e1212a7e3fc1f7dec7525eecdf393fe793f52a875cf043848ad8095cc3 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 1677ce27814b54d771a091ab04eef7ad2cdf503fcfe6b9e8dad6ba85e7d8fbc9 +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 360e55958d8e8464a1fd7990b64f92ffbfae77cba35ea31dc8f26d8c0274ce1f +MUL Fp 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 12d5679fd842c0fae489e6f8fd950712a6801d77da2000d2e180e73af156d5b3 +SQR Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3ce69b158811c2f8acefdc7b0e5a9df4c9bd80d3b24d8f94654a3efada3cf581 +FROM Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000001 1b13887e1a1429f16e4161a915c9cb2099813c8a1d8cc439f2f1f0773efd541d +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0791f325de14e664b4aa62282e98a644f50840433dbfc7626da70eaaf58145f5 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3d679a6b16f9788e6430d173a58607f8d5e7ec854b246cf10a63c8d6170c9008 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 24ec7781e5ebd60e91be9e56ea3634df88c55c71ebc034e1a63b4075c102abe4 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 000000000000000000000000000000000000000000000000ffffffffffffffff 132dd92afbb5a12f1cbf9c47baf77e853f10c4c3988db021b3feac2f58b2041e +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 4000000000000000000000000000000000000000000000000000000000000000 049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2fed7572b6ad1fb4518addae8bb2afaca112b6073915376d60bf257769db7f62 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2986a354618709211610cad3a6c0c64806e77df3f7aeb7eef421e1551f863117 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3b65d42d8464cced7badd38343756e97a4247779fd5e760e4b46900da17c7ace +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1b1d201950d04201d5a13d2f40f232fcf3da86444bfbdd96a840d51974c1a9d7 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 13b5bc4323ef673b7d2ebb04dc796bcc0595773c37288657aa1b5b21897e52d4 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 35c5000bc6c052e6674d650b37e06a3a0a4fba0c34fd24ce261a45452089bc46 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 360e55958d8e8464a1fd7990b64f92ffbfae77cba35ea31dc8f26d8c0274ce1f +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3ce69b158811c2f8acefdc7b0e5a9df4c9bd80d3b24d8f94654a3efada3cf581 +MUL Fp 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0ce2105c41fe09975371bc977a9cacd087001027e8f2f0eebb02070709dbc6cd +SQR Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0b67e1cebd614788846394194b77a658559fe5bf4d14fa7d808af326b918255d +FROM Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000001 0417a27f9647ed737c71f702e127cf999f5644b7dd769aac7d70f04b3ca33a4f +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 08102d3c3c95a063e1e6c2328bbd8e7ed2a208c993640dc0c477d288cfba797a +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 096a1374bdff44bcdb81d15301f0d099d8fc397f7e24afe149933c9ef8a6efe3 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 3be85d8069b8128c838e08fd1ed8306682f054442bd65e6f1bbc40a1c35cc5b2 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 000000000000000000000000000000000000000000000000ffffffffffffffff 385a54834adfe22620b33bbf39551c1ebe43143dccc4fe9a83b5c6ed6a3d0fe4 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 4000000000000000000000000000000000000000000000000000000000000000 02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 190d90428434fe44c0c829966224346c7b42f390ed1288f2ffb94f3b3ebd874b +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3ea7b13e2bf23d01001eece10c10cec411682c86b78d02cf0553467a8010c1ac +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 3d40ac423dc5d58b836f1c1c12c761a293cec0b97d9654bbaf962b14434c0407 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0fe1bce271b680a3432473b59a47a1c89bb3fa7f9abd3fc2582838316659e21a +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 241142522c7e16f6adc74f23033257a67598c7dbd63840792ffe83c6b9c1e770 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2565d74b6f42ec480e49fae1cd43df66bbb7502f0cef496c28f6c4879667d453 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 12d5679fd842c0fae489e6f8fd950712a6801d77da2000d2e180e73af156d5b3 +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0ce2105c41fe09975371bc977a9cacd087001027e8f2f0eebb02070709dbc6cd +MUL Fp 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0b67e1cebd614788846394194b77a658559fe5bf4d14fa7d808af326b918255d +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffc +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 096d41af7b9cb7147797a99bc3c95d1960ed71adb041c555f12db06700000013 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7b9cb7147797a99bc3c95d1960ed71adb041c555f12db06700000013 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 2175c772b190e1fc67f56678717677141ed3817ddfb7d0ea650cb8e63a9e10ea +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2175c772b190e1fc67f56678717677141ed3817ddfb7d0ea650cb8e63a9e10ea +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a8 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a8 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 31269b682e59de6fd65951678f204af90e79463ab37aa333256c3921cc314cfe +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 31269b682e59de6fd65951678f204af90e79463ab37aa333256c3921cc314cfe +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 0fffffffffffffffffffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0fffffffffffffffffffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 077feccfbd7a2968ca7fdd5bafc89a65de7613d61bc1496d2e7214c112c9d33e +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 077feccfbd7a2968ca7fdd5bafc89a66de7613d61bc1496d2e7214c112c9d33e +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 31f1c4ff1e2278d570cb2996efc89a6492eac7ad397e41831c5da9d593a769a7 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 31f1c4ff1e2278d570cb2996efc89a6592eac7ad397e41831c5da9d593a769a7 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 300000000000000000000000000000003bfb8bb91046b3f04c0f159ec0000002 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 300000000000000000000000000000003bfb8bb91046b3f04c0f159ec0000002 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21f1c4ff1e2278d570cb2996efc89a64ac9fba6a4077fc57cf3f8e8753a769a7 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21f1c4ff1e2278d570cb2996efc89a64ac9fba6a4077fc57cf3f8e8753a769a7 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761ca9 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 30cb2996efc89a659a71d82f60a84f6bc06d0d2b964a52404300865287761caa +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff c83d113a5e2278d430cb2996efc89a647c94c6d6abc5909ccdfc4e25d1062bf3 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff c83d113a5e2278d430cb2996efc89a657c94c6d6abc5909ccdfc4e25d1062bf3 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff e64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000001 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3ffffffffffffffeffffffffffffffff992c350be41914ac34786d38fffffffd +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffff992c350be41914ac34786d38fffffffd +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 096d41af7b9cb71500b20d8be8fd41873c87d1718b0de0eb8c78ecb30000000f +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 096d41af7b9cb71500b20d8be8fd41873c87d1718b0de0eb8c78ecb30000000f +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 334b5f8669643bf80cc67344575e84274a76531d20471ad21d4a04412910ed4b +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 334b5f8669643bf80cc67344575e84274a76531d20471ad21d4a04412910ed4b +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 30cb2996efc89a659a71d82f60a84f6cc06d0d2b964a52414300865287761caa +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 30cb2996efc89a659a71d82f60a84f6cc06d0d2b964a52414300865287761caa +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 165951678f204af8f4268bf420a84f6cf243669771939f57a2330c8c46988640 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 165951678f204af8f4268bf420a84f6cf243669771939f57a2330c8c46988640 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0a7fdd5bafc89a65da71d82f60a84f6cabeacec71862cbc511e964da0a175a5c +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0a7fdd5bafc89a65da71d82f60a84f6dabeacec71862cbc511e964da0a175a5c +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 30cb2996efc89a659a71d82f60a84f6b9e26742f8cfd592569d3556587761ca9 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 30cb2996efc89a659a71d82f60a84f6c9e26742f8cfd592569d3556587761ca9 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000224698fc094cf91bd92d30ed00000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000224698fc094cf91bd92d30ed00000001 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 30cb2996efc89a659a71d82f60a84f6bc06d0d2b964a52404300865287761caa +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761ca9 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 da71d82f60a84f6ba64b4c3b3fffffffabe30d981b69b9cd07a048d940dd9669 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 da71d82f60a84f6ba64b4c3b3fffffffabe30d981b69b9cd07a048d940dd9669 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff f0cb2996efc89a649a71d82f60a84f6b9e26742f8cfd5924a9d3556587761caa +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761caa +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 bffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffc +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2e2205637b9cb7182e2a67ec482ca604fcfe4d7d773c0e0beec288616b306e5a +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 2e2205637b9cb7182e2a67ec482ca604fcfe4d7d773c0e0beec288616b306e5a +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 30c4d737c038663a7d125d564448de03477954dba8c4a49f5592d170b2235101 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 30c4d737c038663a7d125d564448de03477954dba8c4a49f5592d170b2235101 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 083d113a5e2278d530cb2996efc89a659edb5fd2b51289b867297f12d1062bf5 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 083d113a5e2278d530cb2996efc89a659edb5fd2b51289b867297f12d1062bf5 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 1771e7a36e59de6f965951678f204af900b4eba328153093bd5629ad49900f4a +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 1771e7a36e59de6f965951678f204af900b4eba328153093bd5629ad49900f4a +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 0fffffffffffffffbfffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0fffffffffffffffbfffffffffffffffe64b0d42f906452b4d1e1b4e3fffffff +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2dcb390afd7a29688a7fdd5bafc89a66f2f8523a99a8cfe85f8936399028958c +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 2dcb390afd7a29688a7fdd5bafc89a66f2f8523a99a8cfe85f8936399028958c +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 183d113a5e2278d4f0cb2996efc89a6585266d15ae18cee3b4479a6111062bf4 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 183d113a5e2278d4f0cb2996efc89a6585266d15ae18cee3b4479a6111062bf4 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 300000000000000040000000000000003bfb8bb91046b3f04c0f159ec0000002 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 300000000000000040000000000000003bfb8bb91046b3f04c0f159ec0000002 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff c83d113a5e2278d430cb2996efc89a657c94c6d6abc5909ccdfc4e25d1062bf3 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff c83d113a5e2278d430cb2996efc89a647c94c6d6abc5909ccdfc4e25d1062bf3 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f0cb2996efc89a649a71d82f60a84f6c9e26742f8cfd5924a9d3556587761caa +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff f0cb2996efc89a649a71d82f60a84f6b9e26742f8cfd5924a9d3556587761caa +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ee885d759e2278d2f0cb2996efc89a669117053b29ad1718ff136f9e4e64ee41 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ee885d759e2278d2f0cb2996efc89a669117053b29ad1718ff136f9e4e64ee41 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffff000000000000000000000000000000000000000000000000 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd ffffffffffffffff000000000000000000000000000000000000000000000000 3ffffffffffffffeffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 2e2205637b9cb7182e2a67ec482ca60473e3e98d5208299d8a0dc4ad6b306e56 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f ffffffffffffffff000000000000000000000000000000000000000000000000 2e2205637b9cb7182e2a67ec482ca60473e3e98d5208299d8a0dc4ad6b306e56 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 3a3218e73bd51d4ef4aa06f208123b1c1f4c629933d28586e20bbe23b2235110 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 ffffffffffffffff000000000000000000000000000000000000000000000000 3a3218e73bd51d4ef4aa06f208123b1c1f4c629933d28586e20bbe23b2235110 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 264b4c3b3fffffffc00000000000000014823e647de7867c311721787d5ec24d +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 ffffffffffffffff000000000000000000000000000000000000000000000000 264b4c3b3fffffffc00000000000000014823e647de7867c311721787d5ec24d +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 264b4c3b3fffffffc00000000000000014823e647de7867d311721787d5ec24c +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 264b4c3b3fffffffc00000000000000014823e647de7867d311721787d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffc00000000000000000000000000000000000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffc00000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 264b4c3b3fffffffc00000000000000114823e647de7867b311721787d5ec24d +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 264b4c3b3fffffffc00000000000000114823e647de7867b311721787d5ec24d +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 264b4c3b3fffffff7ffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 264b4c3b3fffffff7ffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000004000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000004000000000000000224698fc094cf91b992d30ed00000001 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff e64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e64b4c3b3ffffffebffffffffffffffff23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 bffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffeffffffffffffffffddb96703f6b306e366d2cf1300000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e64b4c3b3ffffffdc000000000000000f23ba568749a8d6097e9f08b7d5ec24c +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffe0000000000000000ddb96703f6b306e466d2cf12ffffffff +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffe0000000000000000ddb96703f6b306e466d2cf12ffffffff +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffff000000000000000000000000000000000000000000000000 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000001 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fp 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 3fffffffffffffffffffffffffffffff992c350be41914ad34786d38fffffffd +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 2ae309222d2d9910df8d1014353fd42cf6a68f3b6ac5b1d1f185a5993a9e10f9 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 096d41af7b9cb7147797a99bc3c95d18d7d30dbd8b0de0e78c78ecb30000000f +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589658 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 000000000000000000000000000000000000000000000000ffffffffffffffff 0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302 +MUL Fp 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0ed96497d1a6219029a6ae9870dfb50713cd52c155d255e973c0f7cb33ceb302 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 3000000000000000000000000000000019b4f2bd06f9bad4b2e1e4b1c0000001 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2 +MUL Fp 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 388013304285d697358022a45037659a43d08525ed8bafae6abb1c2bed362cc2 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658 +MUL Fp 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0e0e3b00e1dd872a8f34d6691037659a6d153852c681be7ce3a2562a6c589658 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 00000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 100000000000000000000000000000000891a63f02533e46e64b4c3b40000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 1e0e3b00e1dd872a8f34d6691037659a75a6de91c8d4fcc3c9eda265ac589659 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0f34d6691037659a658e27d09f57b09361d98bd07302a6da562caa9a7889e357 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 37c2eec5a1dd872acf34d6691037659a836b3929543a6f633203b1da2ef9d40c +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 ffffffffffffffff000000000000000000000000000000000000000000000000 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 19b4b3c4c000000040000000000000000dc45a978b65729f68160f7482a13db4 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000001 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +MUL Fp 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 40000000000000000000000000000000224698fc094cf91b992d30ed00000002 21f1c4ff1e2278d570cb2996efc89a65ac9fba6a4077fc57cf3f8e8753a769a9 +FROM Fq 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000000 +SQR Fq 0000000000000000000000000000000000000000000000000000000000000001 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +FROM Fq 0000000000000000000000000000000000000000000000000000000000000001 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000001 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 000000000000000000000000000000000000000000000000ffffffffffffffff 3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37 +SQR Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +FROM Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 000000000000000000000000000000000000000000000000ffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 4000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 +SQR Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c +FROM Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0000000000000000000000000000000000000000000000000000000000000001 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 2c37a71489ba60888d0f36071632bdabf7abe57547cfa14c569bba29179df5c1 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 00000000000000000000000000000000891a63f02652a376311bac8400000004 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffff76e59c0fd9ad5c8a7a4550682fe74c4fbd6297a500000005 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 4000000000000000000000000000000000000000000000000000000000000000 125b506bdf33f6aa5feb88c401333d642280770e64abaff06237590800000004 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 36e59c0fd9ad5c89cee4537bfffffffcefee2ee443109e0ed5f06de700000007 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 125b506bdf33f6aa5feb88c401333d64ab9adafe8afe53669353058c00000008 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 2da4af9420cc0955a014773bfeccc29bffc621eda4e8f8ed2a0f9218fffffffd +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 20479a657a172f2bd053df0b7b5acf61f516940d35cc6f334c3e480121ca423e +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 16fba5370a930060cff5e6c18f3efbc1986f687608a3b3fcf657e3356e1c9356 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 16a094a2dd10d63d2c60481914864a53c49d67e2fff2361ddc8141f24bcb8913 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 2ac11d8d47008bf94cf18afe7fd17c31bea8fcfadd1b069daf58145a6c87f0c3 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 07945afd7e00a6ecaae30dbeb11ac138e9070a556c84c5f4aef2f319fb865fa2 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0fea57e1d7583502228891684693b1965d038faf2fd53ebf2dc9e5ec41ca2ca0 +SQR Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 038c4c2cb8c23f053299d52676a921b7dd1364fa0ac2fcf0fc84cc799aab7c2c +FROM Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 0000000000000000000000000000000000000000000000000000000000000001 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 2c37a71489ba60888d0f36071632bdabf7abe57547cfa14c569bba29179df5c1 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 038c4c2cb8c23f053299d52676a921b7dd1364fa0ac2fcf0fc84cc799aab7c2c +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 3692be50833025568051dceffb330a6fba8b55be807a91f98fb07221fffffff2 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 000000000000000000000000000000000000000000000000ffffffffffffffff 3640e16087fd1ae6e300af3fd67183a566437c7da4492248e68449fe0cc0954c +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 4000000000000000000000000000000000000000000000000000000000000000 01f765e81b99e4b2223fb3b2e38572d8f84ef69436e904c98022d08709276b93 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 194190a05e6e9e8c2c35db5bf20b9edcb2b5763b2229611dd38eb15feccc29b0 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 388a24389eca0a08a29190a2deb87d48b2da4c52b76396c30fd342a909276b85 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3e089a17e4661b4dddc04c4d1c7a8d2729f7a267d2aba4140c241a99f6d8946e +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 10e39b4454685a50cda5f68d7421d880290d079f1b2efeff5236de2f12b9584d +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3b69e9ea6b3ef352ce65cb0486bf9ee41c235797a8223a9b07f2158afdc4df11 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 30ad74e124fe0fd490a54db31012ffb9eae004a5908bc2fa359cb7410d8e104d +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 091036f343941ce36cbd9dae1bb6b5b9d052a05d8cf4c1e9768fce3835f5853b +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 11a0830b593802f951f6f8fe756548c8d841da513ea0771876a98bb914291f34 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 015fc1fe4f6bc49f7f332185abed51d9d68235db8e6e529e7701dbe27fe1cd65 +SQR Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +FROM Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0000000000000000000000000000000000000000000000000000000000000001 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 00000000000000000000000000000000891a63f02652a376311bac8400000004 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3692be50833025568051dceffb330a6fba8b55be807a91f98fb07221fffffff2 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 000000000000000000000000000000000000000000000000ffffffffffffffff 07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015515ab5e093eebac54cc +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debce +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2f7a89dd176479535790be58c050df13cf1f8766a02b2c22c42b5ea5ce1a6f7f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 08e3f1ac2cec85a9ebd61c12e24187ee5f46bb56d67d7bf1d99ef159d81f27ea +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 02683a9e88d96a42d2525444f0f72fc4cb896e005cffa087873f20021fc330ac +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 1b8c3844ef7c813344df83590724b05d747e3cbeb4846815616d8d7b0972c6ae +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0a4238b7de27388f3c7fefa41b9be8e9c51d89d74ce4065966e9ca9af0679aa4 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1a15faed9b09c8b25320734f25c10a1e2a563b1764b2ccaab523a7b787301dc9 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 027a9d83cb2d151a417ef47f8f8094d51fadc9677dc2151816869bbdd83802ca +SQR Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 260b1bcff7a77ed30f3e5bd83e8757c543ee76f0fb69fb41d53cd52f47fabdcb +FROM Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 000000000000000000000000000000000000000000000000ffffffffffffffff +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffff76e59c0fd9ad5c8a7a4550682fe74c4fbd6297a500000005 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3640e16087fd1ae6e300af3fd67183a566437c7da4492248e68449fe0cc0954c +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015515ab5e093eebac54cc +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 260b1bcff7a77ed30f3e5bd83e8757c543ee76f0fb69fb41d53cd52f47fabdcb +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000000891a63f02652a37a311bac840000000 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 354977a8362ed6983eccf4ec1f6c1b6cef2a2328b319ab393e3c3d23695cc27f +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 17e9cb8457139a3fa1deafb45f6c1b6c9f6ee8da77667f4d4e6fc4072bac54cc +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3000000000000000000000000000000019b4f2bd072f7ea5e9353058c0000001 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1d0dd5994aaafdbb915247b038c80ae3ddd1f438869d7be1b3dfdbb28bd13e92 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3015e65997e23a7e0812ed29f00c525c12f01d43879cddb33c70d9084328d9b8 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 16acb4ebe857d0d5df2227b5ff215a2a8b94f780dddabc16e2473bfbc764cb7b +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0dc24913c28b4fa57ce0e4e232d4db48921ea6321220eb845887d65769047ce1 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 06f5879e7548be9436c2abeb5db509810c5d405277106fec6a6b9256f3574092 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 00fba9043bac804523250acf5718e5fa5f27a4762881d669ede2565604ec5733 +SQR Fq 4000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 +FROM Fq 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 4000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 125b506bdf33f6aa5feb88c401333d642280770e64abaff06237590800000004 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 01f765e81b99e4b2223fb3b2e38572d8f84ef69436e904c98022d08709276b93 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 100000000000000000000000000000000891a63f02652a37a311bac840000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 1000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 100000000000000000000000000000004891a63f02652a376311bac840000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 200000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 30000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1f0f0f09f84f08783843fdf0cf348dc097a0b54e3ab432b63220c4af784f0e97 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3b5460f6403423b40d9318fd6638bebd8e6eef198b2949116d2a3efe647edda2 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 352c1aa827cc3842bae5326c6b8c0507b63abda4f56ddff1305ffaa8e03ae083 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa +SQR Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 34166c94559af205116d48c84050df1451976d5c5294ada2ba72ad0190a1681e +FROM Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 00000000000000000000000000000000ffffffffffffffffffffffffffffffff +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 36e59c0fd9ad5c89cee4537bfffffffcefee2ee443109e0ed5f06de700000007 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 194190a05e6e9e8c2c35db5bf20b9edcb2b5763b2229611dd38eb15feccc29b0 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debce +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 354977a8362ed6983eccf4ec1f6c1b6cef2a2328b319ab393e3c3d23695cc27f +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 100000000000000000000000000000004891a63f02652a376311bac840000000 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 34166c94559af205116d48c84050df1451976d5c5294ada2ba72ad0190a1681e +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 39c87b38b67fb5ac347f03908050df1454a44d80fa9281fe70d7e337cf5debce +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 2fffffffffffffffffffffffffffffffd9b4f2bd072f7ea629353058c0000001 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 2e601d498373089f5f94d5da69f27957ef96481487e5a7b736bd369f612547a4 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3828d38387ee8cda01425d288c785223d5a48e3759503d09e2dc6ea9e39fefc0 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 35cedca1e7792b005e925c002e69b1e8a51bb0eb0cdf91d049b1dd1526058824 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0aa32df5f5602aee07a126de3b6108679a01e1b4e89c2dc62431eeb25ed73e4b +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3db83389d2fdc8153f65cf02c73d84eb4fd4670fd63dec9e876bbf8d1e344642 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2420b3d392c5663f81c5e7e0d2cc98db3cb0725047f4d0c9828c32b1163a561f +SQR Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0f7a89dd176479535790be58c050df13b56a94a998fbad7c9af62e4d0e1a6f7e +FROM Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 125b506bdf33f6aa5feb88c401333d64ab9adafe8afe53669353058c00000008 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 388a24389eca0a08a29190a2deb87d48b2da4c52b76396c30fd342a909276b85 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 2f7a89dd176479535790be58c050df13cf1f8766a02b2c22c42b5ea5ce1a6f7f +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 17e9cb8457139a3fa1deafb45f6c1b6c9f6ee8da77667f4d4e6fc4072bac54cc +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 200000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 39c87b38b67fb5ac347f03908050df1454a44d80fa9281fe70d7e337cf5debce +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0f7a89dd176479535790be58c050df13b56a94a998fbad7c9af62e4d0e1a6f7e +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 2000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 27f300b6253b8e22241a1a03b17615aef6e770a51131aea80bbfb609506e3681 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3dbc9b94c90d8df6dfe56d42572fee8259f85d19e828e998f4695f0084420e4e +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 242f7d914f0b579b71a9032603231e492936b11ea17858fa6f68e8e8e22dc523 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3f6e536005f370d1f76522108727edf17b58477c4251e64a9749c543d0a27b27 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1eb026c016a4fbc4d7729fcbe24b9b86a8785c9970a14fb8030a4896e5b3a2fc +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0539f1418d673f8ebe0fd8637cb93332ae25a1aa0978b978001da19694ebfec4 +SQR Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 1000000000000000000000000000000000000000000000000000000000000000 +FROM Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000001 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 2da4af9420cc0955a014773bfeccc29bffc621eda4e8f8ed2a0f9218fffffffd +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3e089a17e4661b4dddc04c4d1c7a8d2729f7a267d2aba4140c241a99f6d8946e +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 000000000000000000000000000000000000000000000000ffffffffffffffff 3000000000000000000000000000000019b4f2bd072f7ea5e9353058c0000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 4000000000000000000000000000000000000000000000000000000000000000 30000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2fffffffffffffffffffffffffffffffd9b4f2bd072f7ea629353058c0000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 1000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 20f0f0f607b0f787c7bc020f30cb723f8aa5e3adcee076275a26267187b0f16a +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e6b5fcc1f1cac229b81225f +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 375cbab3a0712997d3368033040192146d8e249c1ca0b7f87e4b8fb32745018c +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0ad3e557d833c7bd451acd939473faf86c0bdb571426c8ec5be6f0781fc51f7e +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3b65d42d8464cced7badd38343756e97a4247779fda625d03e604a41a17c7ace +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3d40ac423dc5d58b836f1c1c12c761a293cec0b97dde047da2afe548434c0407 +SQR Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c826e4b14082aff58fa381b66ebb31ffc424a9827324372300385a712a3af71 +FROM Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0000000000000000000000000000000000000000000000000000000000000001 371c0e53d3137a561429e3ed1dbe7811c2ffdda533172cebb2a7f9c727e0d817 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 20479a657a172f2bd053df0b7b5acf61f516940d35cc6f334c3e480121ca423e +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 10e39b4454685a50cda5f68d7421d880290d079f1b2efeff5236de2f12b9584d +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 08e3f1ac2cec85a9ebd61c12e24187ee5f46bb56d67d7bf1d99ef159d81f27ea +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 000000000000000000000000000000000000000000000000ffffffffffffffff 1d0dd5994aaafdbb915247b038c80ae3ddd1f438869d7be1b3dfdbb28bd13e92 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 4000000000000000000000000000000000000000000000000000000000000000 1f0f0f09f84f08783843fdf0cf348dc097a0b54e3ab432b63220c4af784f0e97 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2e601d498373089f5f94d5da69f27957ef96481487e5a7b736bd369f612547a4 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 27f300b6253b8e22241a1a03b17615aef6e770a51131aea80bbfb609506e3681 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 20f0f0f607b0f787c7bc020f30cb723f8aa5e3adcee076275a26267187b0f16a +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3c826e4b14082aff58fa381b66ebb31ffc424a9827324372300385a712a3af71 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 1cc98a7c4a2f2d1577731209ca0bb4345acf26d96e40b1a3621c4b697c1f89a7 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3af6ee59b3b4c38b0c54be9896161e88bd2a6b3048071d6589bd19dad1f26ffb +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 1abad769c6cbad4123a911553b6e7852138fc045cf42b1fb85534fd5c8b7cddd +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0ee9cb3f0c351f50055b7dd7ae3544e2a01c48185ebf81b388f231fab7cab006 +MUL Fq 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3d32c8fb7d3d545107b4a69a4c5b2e75eab93d6f80b3cd86eee20d43663e5339 +SQR Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 071895d90ab40b08c4b42617ac1cdd5513304a1aff12e439c017aaa5c9466628 +FROM Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0000000000000000000000000000000000000000000000000000000000000001 3d97c561772695bd2dadabbb0f08d03b56bd2afbac9508560507cb1ee03ccf55 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 16fba5370a930060cff5e6c18f3efbc1986f687608a3b3fcf657e3356e1c9356 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3b69e9ea6b3ef352ce65cb0486bf9ee41c235797a8223a9b07f2158afdc4df11 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 02683a9e88d96a42d2525444f0f72fc4cb896e005cffa087873f20021fc330ac +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 000000000000000000000000000000000000000000000000ffffffffffffffff 3015e65997e23a7e0812ed29f00c525c12f01d43879cddb33c70d9084328d9b8 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 4000000000000000000000000000000000000000000000000000000000000000 3b5460f6403423b40d9318fd6638bebd8e6eef198b2949116d2a3efe647edda2 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3828d38387ee8cda01425d288c785223d5a48e3759503d09e2dc6ea9e39fefc0 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3dbc9b94c90d8df6dfe56d42572fee8259f85d19e828e998f4695f0084420e4e +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 04ab9f09bfcbdc4bf26ce70299c7414293d7a9e27e6b5fcc1f1cac229b81225f +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1cc98a7c4a2f2d1577731209ca0bb4345acf26d96e40b1a3621c4b697c1f89a7 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 071895d90ab40b08c4b42617ac1cdd5513304a1aff12e439c017aaa5c9466628 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 246419a4981faaddc27e8d0019c448456fd856014fa4b0db941ae20af878ac3a +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3b6909a05dbf22befee2b044abcd8be253ec04353872409056b582ed8ab676e9 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 193b8747b4746b70f877067f44e731bdfa6932f2e629d4909748eb6234c0a751 +MUL Fq 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0209da84c6f912d00000b696ba1b54f5ca8ef4ab4e7d28f5b128d1b75aa555cb +SQR Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 28435f86f478c99d44fc0ad902afe026c9368241bbf2fd91c20583bd78c314ef +FROM Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0000000000000000000000000000000000000000000000000000000000000001 2473c7bb10837eccbb207ca6f8db4fa2adc85c3d551040c82ad95da5f68d3953 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 16a094a2dd10d63d2c60481914864a53c49d67e2fff2361ddc8141f24bcb8913 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 30ad74e124fe0fd490a54db31012ffb9eae004a5908bc2fa359cb7410d8e104d +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1b8c3844ef7c813344df83590724b05d747e3cbeb4846815616d8d7b0972c6ae +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 000000000000000000000000000000000000000000000000ffffffffffffffff 16acb4ebe857d0d5df2227b5ff215a2a8b94f780dddabc16e2473bfbc764cb7b +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 4000000000000000000000000000000000000000000000000000000000000000 08a3454c5f8ed6682cc97fccfbfe6debb4b8745fecf3f0e50dfb5b6dd8bafe75 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 35cedca1e7792b005e925c002e69b1e8a51bb0eb0cdf91d049b1dd1526058824 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 242f7d914f0b579b71a9032603231e492936b11ea17858fa6f68e8e8e22dc523 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 375cbab3a0712997d3368033040192146d8e249c1ca0b7f87e4b8fb32745018c +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3af6ee59b3b4c38b0c54be9896161e88bd2a6b3048071d6589bd19dad1f26ffb +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 246419a4981faaddc27e8d0019c448456fd856014fa4b0db941ae20af878ac3a +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 28435f86f478c99d44fc0ad902afe026c9368241bbf2fd91c20583bd78c314ef +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3f744b5a1aea28e70d8ad46f3327904a134f8a4051fd9dfa111fd1f5d5c938c9 +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 03efd48ce6c15c4f257ad17a20e64d1c1a6215ad1e97f54e0f7e2ce750c5441a +MUL Fq 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3eb73a2da6c346e9eefbb70091ae4f358ab2d0eef6bed877e8232e30747a4648 +SQR Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3d5449b2fe7e68a890240a11344fe522edcaea8796292af2d0d8fb99b79db040 +FROM Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0000000000000000000000000000000000000000000000000000000000000001 35bdc74821d8c770c380105be46417165d290f24bcb0a284255d20860f98655d +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 2ac11d8d47008bf94cf18afe7fd17c31bea8fcfadd1b069daf58145a6c87f0c3 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 091036f343941ce36cbd9dae1bb6b5b9d052a05d8cf4c1e9768fce3835f5853b +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0a4238b7de27388f3c7fefa41b9be8e9c51d89d74ce4065966e9ca9af0679aa4 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 000000000000000000000000000000000000000000000000ffffffffffffffff 0dc24913c28b4fa57ce0e4e232d4db48921ea6321220eb845887d65769047ce1 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 4000000000000000000000000000000000000000000000000000000000000000 352c1aa827cc3842bae5326c6b8c0507b63abda4f56ddff1305ffaa8e03ae083 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0aa32df5f5602aee07a126de3b6108679a01e1b4e89c2dc62431eeb25ed73e4b +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3f6e536005f370d1f76522108727edf17b58477c4251e64a9749c543d0a27b27 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0ad3e557d833c7bd451acd939473faf86c0bdb571426c8ec5be6f0781fc51f7e +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 1abad769c6cbad4123a911553b6e7852138fc045cf42b1fb85534fd5c8b7cddd +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 3b6909a05dbf22befee2b044abcd8be253ec04353872409056b582ed8ab676e9 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3f744b5a1aea28e70d8ad46f3327904a134f8a4051fd9dfa111fd1f5d5c938c9 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3d5449b2fe7e68a890240a11344fe522edcaea8796292af2d0d8fb99b79db040 +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3b3fabae42dffc45164e657541c6b93696e8f3fcdfb4760f33ce254e2256c55b +MUL Fq 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2d7db430e8803ea69f052e2842768f1b94f4de6d72a0fd3c4daac60d51d4d068 +SQR Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 04a79fe0cdfaa798f1a3dd8da208e41b79987431a7264d941832206dceae62b2 +FROM Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0000000000000000000000000000000000000000000000000000000000000001 25ea051264f6374dacdf8cb0da3ef5e1f7f05de4a4e1dc32d723436978cfe238 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 07945afd7e00a6ecaae30dbeb11ac138e9070a556c84c5f4aef2f319fb865fa2 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 11a0830b593802f951f6f8fe756548c8d841da513ea0771876a98bb914291f34 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1a15faed9b09c8b25320734f25c10a1e2a563b1764b2ccaab523a7b787301dc9 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 000000000000000000000000000000000000000000000000ffffffffffffffff 06f5879e7548be9436c2abeb5db509810c5d405277106fec6a6b9256f3574092 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 4000000000000000000000000000000000000000000000000000000000000000 049a2bd27b9b331284522c7cbc8a91687e2221820bee830d4de6a0df5e838533 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 3db83389d2fdc8153f65cf02c73d84eb4fd4670fd63dec9e876bbf8d1e344642 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1eb026c016a4fbc4d7729fcbe24b9b86a8785c9970a14fb8030a4896e5b3a2fc +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3b65d42d8464cced7badd38343756e97a4247779fda625d03e604a41a17c7ace +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 0ee9cb3f0c351f50055b7dd7ae3544e2a01c48185ebf81b388f231fab7cab006 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 193b8747b4746b70f877067f44e731bdfa6932f2e629d4909748eb6234c0a751 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 03efd48ce6c15c4f257ad17a20e64d1c1a6215ad1e97f54e0f7e2ce750c5441a +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 3b3fabae42dffc45164e657541c6b93696e8f3fcdfb4760f33ce254e2256c55b +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 04a79fe0cdfaa798f1a3dd8da208e41b79987431a7264d941832206dceae62b2 +MUL Fq 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3fbc4473858d96888a4cf4f26122be6d5452e97f2372b0740ea8da1591130845 +SQR Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3e0a34d529799ca3bb2cd3d706454717da0139fab7c3ec1918efdc79a0f7527f +FROM Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0000000000000000000000000000000000000000000000000000000000000001 3d85627c34d2eae5be810b80707f6b2b0298cf948bd293c575c04f6327c7fd37 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0fea57e1d7583502228891684693b1965d038faf2fd53ebf2dc9e5ec41ca2ca0 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 015fc1fe4f6bc49f7f332185abed51d9d68235db8e6e529e7701dbe27fe1cd65 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 027a9d83cb2d151a417ef47f8f8094d51fadc9677dc2151816869bbdd83802ca +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 000000000000000000000000000000000000000000000000ffffffffffffffff 00fba9043bac804523250acf5718e5fa5f27a4762881d669ede2565604ec5733 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 4000000000000000000000000000000000000000000000000000000000000000 02bf53bdc23a2a747c90e3e3ed389e5d8e77d8428bb6a45fe99705d8bcb3fbfa +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2420b3d392c5663f81c5e7e0d2cc98db3cb0725047f4d0c9828c32b1163a561f +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0539f1418d673f8ebe0fd8637cb93332ae25a1aa0978b978001da19694ebfec4 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3d40ac423dc5d58b836f1c1c12c761a293cec0b97dde047da2afe548434c0407 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3c3c3c27e13c21e0e10ff7c33cd237023c3c3c3ce13c21fb3c3c279ce13c3a5b 3d32c8fb7d3d545107b4a69a4c5b2e75eab93d6f80b3cd86eee20d43663e5339 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 2d5183d900d08ed0364c63f598e2faf5d2e7f1720fe729ad0fd43a9691fb7685 0209da84c6f912d00000b696ba1b54f5ca8ef4ab4e7d28f5b128d1b75aa555cb +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 228d15317e3b59a0b325ff33eff9b7aed2e1d17fb3cfc39437ed6db762ebf9d4 3eb73a2da6c346e9eefbb70091ae4f358ab2d0eef6bed877e8232e30747a4648 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 14b06aa09f30e10aeb94c9b1ae30141e72172b9fb8f9852c1cab294080eb8209 2d7db430e8803ea69f052e2842768f1b94f4de6d72a0fd3c4daac60d51d4d068 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 1268af49ee6ccc4a1148b1f2f22a45a1f88886082fba0c35379a837d7a0e14cc 3fbc4473858d96888a4cf4f26122be6d5452e97f2372b0740ea8da1591130845 +MUL Fq 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 0afd4ef708e8a9d1f2438f8fb4e2797639df610a2eda917fa65c1762f2cfefe8 3e0a34d529799ca3bb2cd3d706454717da0139fab7c3ec1918efdc79a0f7527f +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffc +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 096d41af7ccfdaa97fae231004ccf590f0d5a72daf6cba5a2db2258300000013 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7ccfdaa97fae231004ccf590f0d5a72daf6cba5a2db2258300000013 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 3e7055f0f197b81f0950abbb8948d5d39bc7300f5c1ea51f903bb43e249dae3e +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3e7055f0f197b81f0950abbb8948d5d39bc7300f5c1ea51f903bb43e249dae3e +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7e +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7e +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015516ab5e093eebac54cb +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 07e9cb8457139a3fa1deafb45f6c1b6c96dd429b75015516ab5e093eebac54cb +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 0fffffffffffffffffffffffffffffffe64b0d42f8d08159d6cacfa73fffffff +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0fffffffffffffffffffffffffffffffe64b0d42f8d08159d6cacfa73fffffff +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 29c87b38b67fb5ac347f03908050df140c12a741f82d57c70dc6286f8f5debcd +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 29c87b38b67fb5ac347f03908050df150c12a741f82d57c70dc6286f8f5debcd +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2f7a89dd176479535790be58c050df12acd8ee6a9696834537e47384ce1a6f7d +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2f7a89dd176479535790be58c050df13acd8ee6a9696834537e47384ce1a6f7d +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 300000000000000000000000000000003bfb8bb910c42783b57c1b79c0000002 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 300000000000000000000000000000003bfb8bb910c42783b57c1b79c0000002 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1f7a89dd176479535790be58c050df12c68de1279dc601eb6119a3dd8e1a6f7d +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1f7a89dd176479535790be58c050df12c68de1279dc601eb6119a3dd8e1a6f7d +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 d790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab1 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1790be58c050df13b5b20ea460e4c3a62fb09e8c28c4acd4b5bb9a9ea26e1ab2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff c28c44a5576479521790be58c050df1294c8c9a26e4db0782ebd7cee0a8760df +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff c28c44a5576479521790be58c050df1394c8c9a26e4db0782ebd7cee0a8760df +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff e311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000001 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3ffffffffffffffeffffffffffffffff992c350be34205665b2b3e9cfffffffd +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffff992c350be34205665b2b3e9cfffffffd +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 096d41af7ccfdaaa08c887002b1f990698d6efc1891a16e7fc9678ff0000000f +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 096d41af7ccfdaaa08c887002b1f990698d6efc1891a16e7fc9678ff0000000f +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 082f7490699a9d38264ffc7bb2d7522e3583b391b7d582d6a9b76a4017dd18f2 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 082f7490699a9d38264ffc7bb2d7522e3583b391b7d582d6a9b76a4017dd18f2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 1790be58c050df13b5b20ea460e4c3a72fb09e8c28c4acd5b5bb9a9ea26e1ab2 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 1790be58c050df13b5b20ea460e4c3a72fb09e8c28c4acd5b5bb9a9ea26e1ab2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 21deafb45f6c1b6c92a053dc20e4c3a7753564a6832c02b262681f30a3b19701 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 21deafb45f6c1b6c92a053dc20e4c3a7753564a6832c02b262681f30a3b19701 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 347f03908050df13f5b20ea460e4c3a73f2f1d154ea8556b5bd0d66d2601294f +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 347f03908050df13f5b20ea460e4c3a83f2f1d154ea8556b5bd0d66d2601294f +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1790be58c050df13b5b20ea460e4c3a60d6a05901f3003f7e974af7da26e1ab1 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 1790be58c050df13b5b20ea460e4c3a70d6a05901f3003f7e974af7da26e1ab1 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000224698fc0994a8ddcc46eb2100000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 00000000000000000000000000000000224698fc0994a8ddcc46eb2100000001 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 1790be58c050df13b5b20ea460e4c3a62fb09e8c28c4acd4b5bb9a9ea26e1ab2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 d790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab1 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f5b20ea460e4c3a62311bac83fffffffba7b39e5a598aa2253537b6dfebc83b1 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 f5b20ea460e4c3a62311bac83fffffffba7b39e5a598aa2253537b6dfebc83b1 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff d790be58c050df12b5b20ea460e4c3a60d6a05901f3003f72974af7da26e1ab2 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 d790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 bffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000001 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffc +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3a88ee337ccfdaad3640e16087fd1ae78b74636b990a825fed6704ea66b5723b +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3a88ee337ccfdaad3640e16087fd1ae78b74636b990a825fed6704ea66b5723b +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 128c5784fabf23b20173141b1ae1430afb46d7d1d84397cf26c1ef1391979314 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 128c5784fabf23b20173141b1ae1430afb46d7d1d84397cf26c1ef1391979314 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 028c44a5576479531790be58c050df13b70f629e77e25955bb04680f0a8760e1 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 028c44a5576479531790be58c050df13b70f629e77e25955bb04680f0a8760e1 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 000000000000000000000000000000000000000000000000ffffffffffffffff 2afb864c97139a3f61deafb45f6c1b6ca9a55d0e58b2555e918fb8916819462e +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 2afb864c97139a3f61deafb45f6c1b6ca9a55d0e58b2555e918fb8916819462e +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 4000000000000000000000000000000000000000000000000000000000000000 0fffffffffffffffbfffffffffffffffe64b0d42f8d08159d6cacfa73fffffff +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0fffffffffffffffbfffffffffffffffe64b0d42f8d08159d6cacfa73fffffff +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0cda3600f67fb5abf47f03908050df14fc9428b8d249af3067b0eca10bcadd30 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0cda3600f67fb5abf47f03908050df14fc9428b8d249af3067b0eca10bcadd30 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 128c44a557647952d790be58c050df139d5a6fe170b2daaf91cf37b64a8760e0 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 128c44a557647952d790be58c050df139d5a6fe170b2daaf91cf37b64a8760e0 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 300000000000000040000000000000003bfb8bb910c42783b57c1b79c0000002 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 300000000000000040000000000000003bfb8bb910c42783b57c1b79c0000002 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff c28c44a5576479521790be58c050df1394c8c9a26e4db0782ebd7cee0a8760df +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff c28c44a5576479521790be58c050df1294c8c9a26e4db0782ebd7cee0a8760df +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 d790be58c050df12b5b20ea460e4c3a70d6a05901f3003f72974af7da26e1ab2 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff d790be58c050df12b5b20ea460e4c3a60d6a05901f3003f72974af7da26e1ab2 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e59dff6d97647950d790be58c050df14a790e41551feb0c014ef2c4086f45243 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e59dff6d97647950d790be58c050df14a790e41551feb0c014ef2c4086f45243 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000001 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 ffffffffffffffff000000000000000000000000000000000000000000000000 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd ffffffffffffffff000000000000000000000000000000000000000000000000 3ffffffffffffffeffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3a88ee337ccfdaad3640e16087fd1ae70259ff7b72b7dee9bc4b586666b57237 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f ffffffffffffffff000000000000000000000000000000000000000000000000 3a88ee337ccfdaad3640e16087fd1ae70259ff7b72b7dee9bc4b586666b57237 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 1bf99934778efe5b8121372b1fae389b63021b0f615daeb32358681291979323 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c ffffffffffffffff000000000000000000000000000000000000000000000000 1bf99934778efe5b8121372b1fae389b63021b0f615daeb32358681291979323 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 2311bac83fffffffc00000000000000012c81a72e3b10047e631af527c6cf163 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 ffffffffffffffff000000000000000000000000000000000000000000000000 2311bac83fffffffc00000000000000012c81a72e3b10047e631af527c6cf163 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000ffffffffffffffff 2311bac83fffffffc00000000000000012c81a72e3b10048e631af527c6cf162 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 2311bac83fffffffc00000000000000012c81a72e3b10048e631af527c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 4000000000000000000000000000000000000000000000000000000000000000 3fffffffffffffffc00000000000000000000000000000000000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffc00000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 2311bac83fffffffc00000000000000112c81a72e3b10046e631af527c6cf163 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 2311bac83fffffffc00000000000000112c81a72e3b10046e631af527c6cf163 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 2311bac83fffffff7ffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 2311bac83fffffff7ffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000004000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffff000000000000000000000000000000000000000000000000 00000000000000004000000000000000224698fc0994a8dd8c46eb2100000001 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff e311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e311bac83ffffffebffffffffffffffff0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 bffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffeffffffffffffffffddb96703f66b572173b914df00000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff e311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffff000000000000000000000000000000000000000000000000 e311bac83ffffffdc000000000000000f0818176da1c576a59eac4317c6cf162 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffe0000000000000000ddb96703f66b572273b914deffffffff +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 ffffffffffffffff000000000000000000000000000000000000000000000000 bffffffffffffffe0000000000000000ddb96703f66b572273b914deffffffff +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffff000000000000000000000000000000000000000000000000 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 000000000000000000000000000000000000000000000000ffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 4000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 ffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 0000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000001 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 0000000000000000000000000000000000000000000000000000000000000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fq 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000001 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3fffffffffffffffffffffffffffffff992c350be34205675b2b3e9cfffffffd +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 07dd97a06e6792c888fececb8e15cb63e13bda50dba41326008b421c249dae4c 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 096d41af7ccfdaa97fae231004ccf59067bb433d891a16e3fc9678ff0000000f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59082 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 000000000000000000000000000000000000000000000000ffffffffffffffff 3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35 +MUL Fq 000000000000000000000000000000000000000000000000ffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3816347ba8ec65c05e21504ba093e4938b695660949353c7e0e8e1e21453ab35 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 4000000000000000000000000000000000000000000000000000000000000000 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 4000000000000000000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3000000000000000000000000000000019b4f2bd072f7ea629353058c0000001 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433 +MUL Fq 00000000000000000000000000000000ffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 163784c749804a53cb80fc6f7faf20ec1633f1ba116751167e80c2b170a21433 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082 +MUL Fq 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 10857622e89b86aca86f41a73faf20ec5327119569697cbac81b8c7b31e59082 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 100000000000000000000000000000000891a63f02652a376311bac840000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 20857622e89b86aca86f41a73faf20ec5bb8b7d46bcea6f22b2d474371e59083 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 286f41a73faf20ec4a4df15b9f1b3c58f295fa6fe0cffc07d68b50825d91e54f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq fffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffff 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 3d73bb5aa89b86ace86f41a73faf20ec6b37365d91b24f87d1428311f5789f20 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 ffffffffffffffff000000000000000000000000000000000000000000000000 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq ffffffffffffffff000000000000000000000000000000000000000000000000 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 1cee4537c000000040000000000000000f7e7e8925e3a895a6153bce83930e9e +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 0000000000000000000000000000000000000000000000000000000000000000 +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f +MUL Fq 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 40000000000000000000000000000000224698fc0994a8dd8c46eb2100000002 1f7a89dd176479535790be58c050df13c68de1279dc601eb6119a3dd8e1a6f7f diff --git a/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S b/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S new file mode 100644 index 0000000..4321cf1 --- /dev/null +++ b/CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S @@ -0,0 +1,474 @@ +// Copyright Supranational LLC +// Licensed under the Apache License, Version 2.0, see LICENSE-APACHE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Adapted from the pre-generated Mach-O assembly in Semolina v0.1.4: +// https://github.com/supranational/semolina/blob/v0.1.4/src/mach-o/pasta_mul-armv8.S +// +// Only Montgomery multiplication, squaring, conversion, and their shared +// reduction helper are retained. Symbols are renamed for this crate. The +// implementation relies on both Pasta moduli having limb 2 equal to zero and +// limb 3 equal to 2^62. + +// All field elements and moduli are four little-endian 64-bit limbs. `inv` is +// -modulus[0]^-1 mod 2^64. The routines implement Montgomery reduction with +// R = 2^256. Registers named as limbs below always list the least-significant +// limb first. +// +// Apple AArch64 argument registers: +// +// - mul: x0 = out, x1 = lhs, x2 = rhs, x3 = modulus, x4 = inv +// - square: x0 = out, x1 = value, x2 = modulus, x3 = inv +// - from_mont: x0 = out, x1 = value, x2 = modulus, x3 = inv +// +// The code has no secret-dependent branches or memory accesses. Conditional +// reductions use `csel` after a full-width subtraction. + +.text + +.globl _pasta_curves_mul_mont_pasta +.private_extern _pasta_curves_mul_mont_pasta + +.align 5 +_pasta_curves_mul_mont_pasta: + stp x29,x30,[sp,#-64]! // Allocate frame; save frame pointer and LR. + add x29,sp,#0 // Set the frame pointer to the new stack top. + stp x19,x20,[sp,#16] // Preserve callee-saved accumulator limbs 0-1. + stp x21,x22,[sp,#32] // Preserve callee-saved accumulator limbs 2-3. + stp x23,x24,[sp,#48] // Preserve the carry limb and paired x24. + + ldp x10,x11,[x1] // Load lhs limbs a[0] and a[1]. + ldr x9,[x2] // Load rhs limb b[0]. + ldp x12,x13,[x1,#16] // Load lhs limbs a[2] and a[3]. + + // Form the five-limb product a * b[0] in x19..x23. + mul x19,x10,x9 // x19 = low(a[0] * b[0]). + ldp x5,x6,[x3] // Load modulus limbs p[0] and p[1]. + mul x20,x11,x9 // x20 = low(a[1] * b[0]). + ldp x7,x8,[x3,#16] // Load p[2] = 0 and p[3] = 2^62. + mul x21,x12,x9 // x21 = low(a[2] * b[0]). + mul x22,x13,x9 // x22 = low(a[3] * b[0]). + + umulh x14,x10,x9 // x14 = high(a[0] * b[0]). + umulh x15,x11,x9 // x15 = high(a[1] * b[0]). + mul x3,x4,x19 // q = x19 * inv mod 2^64. + umulh x16,x12,x9 // x16 = high(a[2] * b[0]). + umulh x17,x13,x9 // x17 = high(a[3] * b[0]). + adds x20,x20,x14 // Add high(a[0] * b[0]) into limb 1. + // low(q * p[0]) cancels x19 and is discarded by the limb shift. + adcs x21,x21,x15 // Add high(a[1] * b[0]) and carry. + mul x15,x6,x3 // x15 = low(q * p[1]). + adcs x22,x22,x16 // Add high(a[2] * b[0]) and carry. + // q * p[2] is zero because p[2] = 0. + adc x23,xzr,x17 // Finish a * b[0] with its fifth limb. + lsl x17,x3,#62 // x17 = low(q * p[3]). + ldr x9,[x2,8*1] // Load rhs limb b[1] for the next round. + // Carry from x19 + low(q*p[0]) is one exactly when x19 is nonzero. + subs xzr,x19,#1 // Set that carry without computing the zero sum. + umulh x14,x5,x3 // x14 = high(q * p[0]). + adcs x20,x20,x15 // Add low(q * p[1]) and cancellation carry. + umulh x15,x6,x3 // x15 = high(q * p[1]). + adcs x21,x21,xzr // Propagate carry; p[2]'s product is zero. + // high(q * p[2]) is zero. + adcs x22,x22,x17 // Add low(q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(q * p[3]). + adc x23,x23,xzr // Propagate carry into the fifth limb. + + // Drop the cancelled low limb: (a*b[0] + q*p) / 2^64. + adds x19,x20,x14 // New limb 0 includes high(q * p[0]). + mul x14,x10,x9 // x14 = low(a[0] * b[1]). + adcs x20,x21,x15 // New limb 1 includes high(q * p[1]). + mul x15,x11,x9 // x15 = low(a[1] * b[1]). + adcs x21,x22,xzr // New limb 2; p[2] contributes zero. + mul x16,x12,x9 // x16 = low(a[2] * b[1]). + adcs x22,x23,x17 // New limb 3 includes high(q * p[3]). + mul x17,x13,x9 // x17 = low(a[3] * b[1]). + adc x23,xzr,xzr // Capture the reduction carry as limb 4. + + // Round 1: add a * b[1] to the reduced accumulator. + adds x19,x19,x14 // Add low(a[0] * b[1]) to limb 0. + umulh x14,x10,x9 // x14 = high(a[0] * b[1]). + adcs x20,x20,x15 // Add low(a[1] * b[1]) and carry. + umulh x15,x11,x9 // x15 = high(a[1] * b[1]). + adcs x21,x21,x16 // Add low(a[2] * b[1]) and carry. + mul x3,x4,x19 // q = current limb 0 * inv mod 2^64. + umulh x16,x12,x9 // x16 = high(a[2] * b[1]). + adcs x22,x22,x17 // Add low(a[3] * b[1]) and carry. + umulh x17,x13,x9 // x17 = high(a[3] * b[1]). + adc x23,x23,xzr // Propagate multiplication carry to limb 4. + + adds x20,x20,x14 // Add high(a[0] * b[1]) to limb 1. + // low(q * p[0]) cancels x19. + adcs x21,x21,x15 // Add high(a[1] * b[1]) and carry. + mul x15,x6,x3 // x15 = low(q * p[1]). + adcs x22,x22,x16 // Add high(a[2] * b[1]) and carry. + // low(q * p[2]) is zero. + adc x23,x23,x17 // Add high(a[3] * b[1]) and final carry. + lsl x17,x3,#62 // x17 = low(q * p[3]). + ldr x9,[x2,8*2] // Load rhs limb b[2] for the next round. + subs xzr,x19,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(q * p[0]). + adcs x20,x20,x15 // Add low(q * p[1]) and cancellation carry. + umulh x15,x6,x3 // x15 = high(q * p[1]). + adcs x21,x21,xzr // Propagate carry across zero p[2]. + // high(q * p[2]) is zero. + adcs x22,x22,x17 // Add low(q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(q * p[3]). + adc x23,x23,xzr // Propagate carry to limb 4. + + // Shift after round 1 while starting a * b[2]. + adds x19,x20,x14 // New limb 0 includes high(q * p[0]). + mul x14,x10,x9 // x14 = low(a[0] * b[2]). + adcs x20,x21,x15 // New limb 1 includes high(q * p[1]). + mul x15,x11,x9 // x15 = low(a[1] * b[2]). + adcs x21,x22,xzr // New limb 2; p[2] contributes zero. + mul x16,x12,x9 // x16 = low(a[2] * b[2]). + adcs x22,x23,x17 // New limb 3 includes high(q * p[3]). + mul x17,x13,x9 // x17 = low(a[3] * b[2]). + adc x23,xzr,xzr // Capture the reduction carry as limb 4. + + // Round 2: add a * b[2] and cancel the resulting low limb. + adds x19,x19,x14 // Add low(a[0] * b[2]) to limb 0. + umulh x14,x10,x9 // x14 = high(a[0] * b[2]). + adcs x20,x20,x15 // Add low(a[1] * b[2]) and carry. + umulh x15,x11,x9 // x15 = high(a[1] * b[2]). + adcs x21,x21,x16 // Add low(a[2] * b[2]) and carry. + mul x3,x4,x19 // q = current limb 0 * inv mod 2^64. + umulh x16,x12,x9 // x16 = high(a[2] * b[2]). + adcs x22,x22,x17 // Add low(a[3] * b[2]) and carry. + umulh x17,x13,x9 // x17 = high(a[3] * b[2]). + adc x23,x23,xzr // Propagate multiplication carry to limb 4. + + adds x20,x20,x14 // Add high(a[0] * b[2]) to limb 1. + // low(q * p[0]) cancels x19. + adcs x21,x21,x15 // Add high(a[1] * b[2]) and carry. + mul x15,x6,x3 // x15 = low(q * p[1]). + adcs x22,x22,x16 // Add high(a[2] * b[2]) and carry. + // low(q * p[2]) is zero. + adc x23,x23,x17 // Add high(a[3] * b[2]) and final carry. + lsl x17,x3,#62 // x17 = low(q * p[3]). + ldr x9,[x2,8*3] // Load rhs limb b[3] for the last round. + subs xzr,x19,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(q * p[0]). + adcs x20,x20,x15 // Add low(q * p[1]) and cancellation carry. + umulh x15,x6,x3 // x15 = high(q * p[1]). + adcs x21,x21,xzr // Propagate carry across zero p[2]. + // high(q * p[2]) is zero. + adcs x22,x22,x17 // Add low(q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(q * p[3]). + adc x23,x23,xzr // Propagate carry to limb 4. + + // Shift after round 2 while starting a * b[3]. + adds x19,x20,x14 // New limb 0 includes high(q * p[0]). + mul x14,x10,x9 // x14 = low(a[0] * b[3]). + adcs x20,x21,x15 // New limb 1 includes high(q * p[1]). + mul x15,x11,x9 // x15 = low(a[1] * b[3]). + adcs x21,x22,xzr // New limb 2; p[2] contributes zero. + mul x16,x12,x9 // x16 = low(a[2] * b[3]). + adcs x22,x23,x17 // New limb 3 includes high(q * p[3]). + mul x17,x13,x9 // x17 = low(a[3] * b[3]). + adc x23,xzr,xzr // Capture the reduction carry as limb 4. + + // Round 3: add a * b[3] and perform the last Montgomery cancellation. + adds x19,x19,x14 // Add low(a[0] * b[3]) to limb 0. + umulh x14,x10,x9 // x14 = high(a[0] * b[3]). + adcs x20,x20,x15 // Add low(a[1] * b[3]) and carry. + umulh x15,x11,x9 // x15 = high(a[1] * b[3]). + adcs x21,x21,x16 // Add low(a[2] * b[3]) and carry. + mul x3,x4,x19 // q = current limb 0 * inv mod 2^64. + umulh x16,x12,x9 // x16 = high(a[2] * b[3]). + adcs x22,x22,x17 // Add low(a[3] * b[3]) and carry. + umulh x17,x13,x9 // x17 = high(a[3] * b[3]). + adc x23,x23,xzr // Propagate multiplication carry to limb 4. + + adds x20,x20,x14 // Add high(a[0] * b[3]) to limb 1. + // low(q * p[0]) cancels x19. + adcs x21,x21,x15 // Add high(a[1] * b[3]) and carry. + mul x15,x6,x3 // x15 = low(q * p[1]). + adcs x22,x22,x16 // Add high(a[2] * b[3]) and carry. + // low(q * p[2]) is zero. + adc x23,x23,x17 // Add high(a[3] * b[3]) and final carry. + lsl x17,x3,#62 // x17 = low(q * p[3]). + subs xzr,x19,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(q * p[0]). + adcs x20,x20,x15 // Add low(q * p[1]) and cancellation carry. + umulh x15,x6,x3 // x15 = high(q * p[1]). + adcs x21,x21,xzr // Propagate carry across zero p[2]. + // high(q * p[2]) is zero. + adcs x22,x22,x17 // Add low(q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(q * p[3]). + adc x23,x23,xzr // Propagate carry to limb 4. + + // Shift out the fourth cancelled limb. x23 records any 257th bit. + adds x19,x20,x14 // Final candidate limb 0. + adcs x20,x21,x15 // Final candidate limb 1. + adcs x21,x22,xzr // Final candidate limb 2. + adcs x22,x23,x17 // Final candidate limb 3. + adc x23,xzr,xzr // Final candidate carry limb. + + // Subtract the five-limb value p = [p0,p1,0,p3,0]. + subs x14,x19,x5 // Tentative result limb 0 = candidate - p[0]. + sbcs x15,x20,x6 // Tentative result limb 1 minus p[1]. + sbcs x16,x21,xzr // Tentative result limb 2; p[2] is zero. + sbcs x17,x22,x8 // Tentative result limb 3 minus p[3]. + sbcs xzr,x23,xzr // Include the carry limb in the comparison. + + // `lo` means subtraction borrowed, so retain the original candidate. + csel x19,x19,x14,lo // Select canonical output limb 0. + csel x20,x20,x15,lo // Select canonical output limb 1. + csel x21,x21,x16,lo // Select canonical output limb 2. + csel x22,x22,x17,lo // Select canonical output limb 3. + + stp x19,x20,[x0] // Store output limbs 0 and 1. + stp x21,x22,[x0,#16] // Store output limbs 2 and 3. + + ldp x19,x20,[x29,#16] // Restore callee-saved x19 and x20. + ldp x21,x22,[x29,#32] // Restore callee-saved x21 and x22. + ldp x23,x24,[x29,#48] // Restore callee-saved x23 and x24. + ldr x29,[sp],#64 // Restore frame pointer and release the frame. + ret // Return; x30 still holds the caller's address. + +.globl _pasta_curves_sqr_mont_pasta +.private_extern _pasta_curves_sqr_mont_pasta + +.align 5 +_pasta_curves_sqr_mont_pasta: + .long 3573752639 // `paciasp`: sign LR with the entry stack pointer. + stp x29,x30,[sp,#-48]! // Allocate frame; save frame pointer and signed LR. + add x29,sp,#0 // Set the frame pointer to the new stack top. + stp x19,x20,[sp,#16] // Preserve callee-saved product limbs 4 and 5. + stp x21,x22,[sp,#32] // Preserve callee-saved product limbs 6 and 7. + + ldp x5,x6,[x1] // Load value limbs a[0] and a[1]. + ldp x7,x8,[x1,#16] // Load value limbs a[2] and a[3]. + mov x4,x3 // Move inv into the helper's expected register. + + //////////////////////////////////////////////////////////////// + // | | | | | |a1*a0| | + // | | | | |a2*a0| | | + // | |a3*a2|a3*a0| | | | + // | | | |a2*a1| | | | + // | | |a3*a1| | | | | + // *| | | | | | | | 2| + // +|a3*a3|a2*a2|a1*a1|a0*a0| + // |--+--+--+--+--+--+--+--| + // |A7|A6|A5|A4|A3|A2|A1|A0| + // A0..A7 map to x10,x11,x12,x13,x19,x20,x21,x22. + // + // "can't overflow" below mark carrying into high part of + // multiplication result, which can't overflow, because it + // can never be all ones. + + mul x11,x6,x5 // x11 = low(a[1] * a[0]). + umulh x15,x6,x5 // x15 = high(a[1] * a[0]). + mul x12,x7,x5 // x12 = low(a[2] * a[0]). + umulh x16,x7,x5 // x16 = high(a[2] * a[0]). + mul x13,x8,x5 // x13 = low(a[3] * a[0]). + umulh x19,x8,x5 // x19 = high(a[3] * a[0]). + + adds x12,x12,x15 // Fold high(a[1] * a[0]) into product limb 2. + mul x14,x7,x6 // x14 = low(a[2] * a[1]). + umulh x15,x7,x6 // x15 = high(a[2] * a[1]). + adcs x13,x13,x16 // Fold high(a[2] * a[0]) into product limb 3. + mul x16,x8,x6 // x16 = low(a[3] * a[1]). + umulh x17,x8,x6 // x17 = high(a[3] * a[1]). + adc x19,x19,xzr // Propagate carry into product limb 4. + + mul x20,x8,x7 // x20 = low(a[3] * a[2]). + umulh x21,x8,x7 // x21 = high(a[3] * a[2]). + + adds x15,x15,x16 // Combine terms contributing to product limb 4. + mul x10,x5,x5 // x10 = low(a[0]^2), product limb 0. + adc x16,x17,xzr // Combine terms contributing to product limb 5. + + adds x13,x13,x14 // Add low(a[2] * a[1]) into product limb 3. + umulh x5,x5,x5 // x5 = high(a[0]^2). + adcs x19,x19,x15 // Accumulate cross terms into product limb 4. + mul x15,x6,x6 // x15 = low(a[1]^2). + adcs x20,x20,x16 // Accumulate cross terms into product limb 5. + umulh x6,x6,x6 // x6 = high(a[1]^2). + adc x21,x21,xzr // Propagate carry into product limb 6. + + adds x11,x11,x11 // Double cross-term product limb 1. + mul x16,x7,x7 // x16 = low(a[2]^2). + adcs x12,x12,x12 // Double cross-term product limb 2. + umulh x7,x7,x7 // x7 = high(a[2]^2). + adcs x13,x13,x13 // Double cross-term product limb 3. + mul x17,x8,x8 // x17 = low(a[3]^2). + adcs x19,x19,x19 // Double cross-term product limb 4. + umulh x8,x8,x8 // x8 = high(a[3]^2). + adcs x20,x20,x20 // Double cross-term product limb 5. + adcs x21,x21,x21 // Double cross-term product limb 6. + adc x22,xzr,xzr // Capture the doubled cross-term carry in limb 7. + + // Add diagonal squares to obtain a^2 in x10,x11,x12,x13,x19..x22. + adds x11,x11,x5 // Add high(a[0]^2) to product limb 1. + adcs x12,x12,x15 // Add low(a[1]^2) to product limb 2. + adcs x13,x13,x6 // Add high(a[1]^2) to product limb 3. + adcs x19,x19,x16 // Add low(a[2]^2) to product limb 4. + adcs x20,x20,x7 // Add high(a[2]^2) to product limb 5. + adcs x21,x21,x17 // Add low(a[3]^2) to product limb 6. + adc x22,x22,x8 // Add high(a[3]^2) to product limb 7. + + // Reduce the lower four limbs; upper limbs remain in callee-saved regs. + bl L$pasta_curves_mul_by_1_mont_pasta // Reduce x10..x13 by R. + ldr x30,[x29,#8] // Restore signed LR clobbered by `bl`. + + // Add the untouched upper half, completing reduction of the 512-bit square. + adds x10,x10,x19 // Add original product limb 4 to result limb 0. + adcs x11,x11,x20 // Add original product limb 5 and carry. + adcs x12,x12,x21 // Add original product limb 6 and carry. + adcs x13,x13,x22 // Add original product limb 7 and carry. + adc x19,xzr,xzr // Capture a possible 257th candidate bit. + + // Tentatively subtract p as a five-limb value. + subs x14,x10,x5 // Tentative result limb 0 = candidate - p[0]. + sbcs x15,x11,x6 // Tentative result limb 1 minus p[1]. + sbcs x16,x12,x7 // Tentative result limb 2 minus p[2] = 0. + sbcs x17,x13,x8 // Tentative result limb 3 minus p[3]. + sbcs xzr,x19,xzr // Include the candidate carry in the comparison. + + // If subtraction borrowed (`lo`), keep the original candidate. + csel x10,x10,x14,lo // Select canonical output limb 0. + csel x11,x11,x15,lo // Select canonical output limb 1. + csel x12,x12,x16,lo // Select canonical output limb 2. + csel x13,x13,x17,lo // Select canonical output limb 3. + + stp x10,x11,[x0] // Store output limbs 0 and 1. + stp x12,x13,[x0,#16] // Store output limbs 2 and 3. + + ldp x19,x20,[x29,#16] // Restore callee-saved x19 and x20. + ldp x21,x22,[x29,#32] // Restore callee-saved x21 and x22. + ldr x29,[sp],#48 // Restore frame pointer and entry stack pointer. + .long 3573752767 // `autiasp`: authenticate LR with entry SP. + ret // Return through the authenticated address. + +.globl _pasta_curves_from_mont_pasta +.private_extern _pasta_curves_from_mont_pasta + +.align 5 +_pasta_curves_from_mont_pasta: + .long 3573752639 // `paciasp`: sign LR with the entry stack pointer. + stp x29,x30,[sp,#-16]! // Allocate frame; save frame pointer and signed LR. + add x29,sp,#0 // Set the frame pointer to the new stack top. + + mov x4,x3 // Move inv into the helper's expected register. + ldp x10,x11,[x1] // Load Montgomery residue limbs 0 and 1. + ldp x12,x13,[x1,#16] // Load Montgomery residue limbs 2 and 3. + + // Montgomery-reduce an implicit zero upper half: value * R^-1 mod p. + bl L$pasta_curves_mul_by_1_mont_pasta // Reduce x10..x13 by R. + ldr x30,[x29,#8] // Restore signed LR clobbered by `bl`. + + // The helper leaves p in x5..x8; one subtraction canonicalizes the result. + subs x14,x10,x5 // Tentative result limb 0 = candidate - p[0]. + sbcs x15,x11,x6 // Tentative result limb 1 minus p[1]. + sbcs x16,x12,x7 // Tentative result limb 2 minus p[2] = 0. + sbcs x17,x13,x8 // Tentative result limb 3 minus p[3]. + + // If subtraction borrowed (`lo`), keep the original candidate. + csel x10,x10,x14,lo // Select canonical integer limb 0. + csel x11,x11,x15,lo // Select canonical integer limb 1. + csel x12,x12,x16,lo // Select canonical integer limb 2. + csel x13,x13,x17,lo // Select canonical integer limb 3. + + stp x10,x11,[x0] // Store canonical integer limbs 0 and 1. + stp x12,x13,[x0,#16] // Store canonical integer limbs 2 and 3. + + ldr x29,[sp],#16 // Restore frame pointer and entry stack pointer. + .long 3573752767 // `autiasp`: authenticate LR with entry SP. + ret // Return through the authenticated address. + +.align 5 +L$pasta_curves_mul_by_1_mont_pasta: + // Entry: x10..x13 = t, x2 = p, x4 = inv. Each iteration chooses q_i + // so the current low limb plus q_i*p[0] is zero modulo 2^64, adds + // q_i*p, and discards that zero limb. On exit, x10..x13 contain + // (t + Q*p) / R, where Q has the four q_i as little-endian limbs. + + // Montgomery cancellation 0. + mul x3,x4,x10 // q = t[0] * inv mod 2^64. + ldp x5,x6,[x2] // Load modulus limbs p[0] and p[1]. + ldp x7,x8,[x2,#16] // Load p[2] = 0 and p[3] = 2^62. + // low(q * p[0]) cancels x10 and is discarded. + mul x15,x6,x3 // x15 = low(q * p[1]). + // q * p[2] is zero because p[2] = 0. + lsl x17,x3,#62 // x17 = low(q * p[3]). + // Carry from x10 + low(q*p[0]) is one exactly when x10 is nonzero. + subs xzr,x10,#1 // Set that cancellation carry. + umulh x14,x5,x3 // x14 = high(q * p[0]). + adcs x11,x11,x15 // Add low(q * p[1]) and cancellation carry. + umulh x15,x6,x3 // x15 = high(q * p[1]). + adcs x12,x12,xzr // Propagate carry across zero p[2]. + // high(q * p[2]) is zero. + adcs x13,x13,x17 // Add low(q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(q * p[3]). + adc x9,xzr,xzr // Save the carry above limb 3. + + // Shift out cancelled limb 0 and start cancellation 1. + adds x10,x11,x14 // New limb 0 includes high(q * p[0]). + adcs x11,x12,x15 // New limb 1 includes high(q * p[1]). + adcs x12,x13,xzr // New limb 2; p[2] contributes zero. + mul x3,x4,x10 // Next q = new limb 0 * inv mod 2^64. + adc x13,x9,x17 // New limb 3 includes high(q * p[3]). + // low(q * p[0]) cancels x10 and is discarded. + mul x15,x6,x3 // x15 = low(next q * p[1]). + // next q * p[2] is zero. + lsl x17,x3,#62 // x17 = low(next q * p[3]). + subs xzr,x10,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(next q * p[0]). + adcs x11,x11,x15 // Add low(next q * p[1]) and carry. + umulh x15,x6,x3 // x15 = high(next q * p[1]). + adcs x12,x12,xzr // Propagate carry across zero p[2]. + // high(next q * p[2]) is zero. + adcs x13,x13,x17 // Add low(next q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(next q * p[3]). + adc x9,xzr,xzr // Save the carry above limb 3. + + // Shift out cancelled limb 1 and start cancellation 2. + adds x10,x11,x14 // New limb 0 includes high(q * p[0]). + adcs x11,x12,x15 // New limb 1 includes high(q * p[1]). + adcs x12,x13,xzr // New limb 2; p[2] contributes zero. + mul x3,x4,x10 // Next q = new limb 0 * inv mod 2^64. + adc x13,x9,x17 // New limb 3 includes high(q * p[3]). + // low(q * p[0]) cancels x10 and is discarded. + mul x15,x6,x3 // x15 = low(next q * p[1]). + // next q * p[2] is zero. + lsl x17,x3,#62 // x17 = low(next q * p[3]). + subs xzr,x10,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(next q * p[0]). + adcs x11,x11,x15 // Add low(next q * p[1]) and carry. + umulh x15,x6,x3 // x15 = high(next q * p[1]). + adcs x12,x12,xzr // Propagate carry across zero p[2]. + // high(next q * p[2]) is zero. + adcs x13,x13,x17 // Add low(next q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(next q * p[3]). + adc x9,xzr,xzr // Save the carry above limb 3. + + // Shift out cancelled limb 2 and start cancellation 3. + adds x10,x11,x14 // New limb 0 includes high(q * p[0]). + adcs x11,x12,x15 // New limb 1 includes high(q * p[1]). + adcs x12,x13,xzr // New limb 2; p[2] contributes zero. + mul x3,x4,x10 // Final q = new limb 0 * inv mod 2^64. + adc x13,x9,x17 // New limb 3 includes high(q * p[3]). + // low(q * p[0]) cancels x10 and is discarded. + mul x15,x6,x3 // x15 = low(final q * p[1]). + // final q * p[2] is zero. + lsl x17,x3,#62 // x17 = low(final q * p[3]). + subs xzr,x10,#1 // Set the low-limb cancellation carry. + umulh x14,x5,x3 // x14 = high(final q * p[0]). + adcs x11,x11,x15 // Add low(final q * p[1]) and carry. + umulh x15,x6,x3 // x15 = high(final q * p[1]). + adcs x12,x12,xzr // Propagate carry across zero p[2]. + // high(final q * p[2]) is zero. + adcs x13,x13,x17 // Add low(final q * p[3]) and carry. + lsr x17,x3,#2 // x17 = high(final q * p[3]). + adc x9,xzr,xzr // Save the carry above limb 3. + + // Shift out cancelled limb 3 to finish division by R = 2^256. + adds x10,x11,x14 // Output limb 0 includes high(q * p[0]). + adcs x11,x12,x15 // Output limb 1 includes high(q * p[1]). + adcs x12,x13,xzr // Output limb 2; p[2] contributes zero. + adc x13,x9,x17 // Output limb 3 includes high(q * p[3]). + + ret // Return to square or from_mont through x30. diff --git a/README.md b/README.md index e450750..eedac95 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,11 @@ Early work in progress. Present so far: together with a natively compilable Montgomery-limb kernel proven against them (`CompElliptic/Curves/Pasta/Fast/`, not imported by `CompElliptic.lean`). These interfaces are provisional: they are not guaranteed to remain public, and may be folded into the existing API - or otherwise changed incompatibly. + or otherwise changed incompatibly; +- a transcription of the AArch64 Pasta Montgomery routines that pasta_curves vendors from + Semolina, generated from the assembly over a small instruction-semantics module, with + reference vectors from the real routines checked by the kernel (`CompElliptic/Asm/AArch64/`; + `design/aarch64-pasta-mul-verification.md` states the intended correctness theorems). The library's general theorems depend only on the standard `propext` / `Classical.choice` / `Quot.sound` axioms. Facts specific to concrete fields and curves additionally depend on diff --git a/design/aarch64-pasta-mul-verification.md b/design/aarch64-pasta-mul-verification.md new file mode 100644 index 0000000..49a79ab --- /dev/null +++ b/design/aarch64-pasta-mul-verification.md @@ -0,0 +1,108 @@ +# Design: verifying pasta_curves' AArch64 Montgomery routines in CompElliptic + + +## Goal + +A machine-checked proof that the three routines zcash/pasta_curves#100 vendors from +Semolina v0.1.4 (`mul_mont_pasta`, `sqr_mont_pasta`, `from_mont_pasta`, plus their +shared `mul_by_1` helper) compute Montgomery multiplication, squaring, and conversion +on the Pasta fields, under the operand contracts they actually have. The proof is +about the instruction stream of `src/asm/pasta_mul-armv8.S` (329 instructions after +comment stripping, blob `4321cf159d9814a14afbdc5cf42265384150822f`, sha256 +`0bcd5fa67d4aef5043eb536fdefd41ce16e6f7fbac3e5e6ac4f7619b35fd5e85`), not about a re-derivation +of the algorithm. + +## Trust story + +What is trusted, beyond Lean's kernel and standard axioms: + +1. The instruction semantics module (`Semantics.lean`): about a dozen AArch64 + instructions modelled over 64-bit registers and the carry flag. Small, reviewable, + and cross-checked by executing the model on vectors produced by the real binary. +2. The transcription of the `.S` into Lean. Generated by a script from the vendored + file, never hand-typed; CI regenerates and diffs (same pattern as the field-file + generators). The generator is the same parser as the Python simulator that found + the accumulator wrap, so it has already been exercised against the hardware. +3. The reference vectors: outputs of the real assembly on an Apple M-series machine at + pasta_curves commit `8ad85e9fab7929f6236960e472f432a4bd9ccd74`, embedded as + kernel-checked examples (`decide +kernel`). These are + concrete closed facts in the sense of the README's trust discipline, and any + independent run of the binary reproduces them. + +Not in the trusted base: the calling convention, stack frame, and memory-safety of +the FFI boundary. The model treats loads and stores as limb inputs and outputs. Those +aspects were reviewed by hand and are recorded as such in the module doc. + +## Layout + +``` +CompElliptic/Asm/AArch64/Semantics.lean registers, carry, instruction functions +CompElliptic/Asm/AArch64/PastaMul.lean GENERATED: the four routines as Lean defs +CompElliptic/Asm/AArch64/PastaMulVectors.lean GENERATED: reference vectors, kernel-checked +CompElliptic/Asm/AArch64/PastaMulSpec.lean the theorems +CompElliptic/Asm/AArch64/Pasta.lean instantiation at the two Pasta primes +CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S vendored, Apache-2.0, hash pinned +scripts/gen_aarch64_pasta_mul.py parser + Lean emitter (+ simulator) +scripts/check_aarch64_pasta_mul.sh regenerate and diff, hash check (CI) +``` + +Namespace `CompElliptic.Asm.AArch64`, mirroring the path. + +## Value representation + +Registers are natural numbers, reduced modulo `2^64` by every instruction, and the +carry is a natural number that is `0` or `1`; each instruction is a function on `Nat` +(`mulLo a b = a * b % 2^64`, `umulh a b = a * b / 2^64`, `addc a b c = ((a+b+c) % 2^64, +(a+b+c) / 2^64)`, `subc` with AArch64's carry-means-no-borrow convention, `cselLo`). +Two reasons over `UInt64`. The reference vectors become kernel-checked theorems +(`by decide +kernel`, the kernel's GMP-accelerated `Nat` arithmetic), which is the +tier the README prefers over evaluation. And the proofs stay in `Nat`: `omega` +understands `%` and `/` by literals, so each carry chain is closed with no `toNat` +plumbing, the products `a * b` being the only atoms it does not see through; the limb +recompositions that relate those atoms are `ring` facts. No native execution speed is +needed, and the modules stay outside the precompiled lane. + +## Program shape + +The generator emits each routine as a chain of `let`s in a single function from the +input limbs (and modulus limbs and `inv`) to the output limbs. The proofs are to be +stated about round functions cut from the same instruction stream at indices given in +the generator's configuration, each cut checked against the instruction text at its +boundary so that an edit to the `.S` that moves a boundary fails loudly rather than +silently shifting a round; the whole-routine definitions are then their composition by +`rfl`. That cut belongs to the proof units and is not emitted yet. + +## Theorems (statements the first proof unit targets) + +With `p = p0 + 2^64 p1 + 2^192 · 2^62` (the modulus limbs are `[p0, p1, 0, 2^62]`, as +the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: + +* `mul_spec`: if `lhs < p` and `rhs < 2^256`, or `lhs < 2^256`, `rhs < p`, and every + `rhs` limb in positions 1 to 3 is at most `2^64 − 4`, then the output is below `p` + and `output · 2^256 ≡ lhs · rhs (mod p)`. The exact wrap boundary (whether + `2^64 − 2` and `2^64 − 3` can wrap) is settled as a by-product of the round lemma + and stated as its own lemma. +* `sqr_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. +* `from_mont_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a (mod p)`. + +`Pasta.lean` instantiates these at `PALLAS_BASE_CARD` and `PALLAS_SCALAR_CARD` with +the crate's `MODULUS`, `INV`, `R2`, `R3` limbs pinned by `decide`, and states the +corollary the crate relies on: `mul lhs R2` and `mul lhs R3` are correct for every +256-bit `lhs`, because no limb 1 to 3 of `R2`/`R3` is above `2^64 − 4`. It also states +the negative: the witness pair is inside `lhs · rhs < 2^256 · p` and the model's +output is not the Montgomery product (by evaluation), documenting why #108's contract +is wrong. + +## Status + +1. Semantics, generator, generated program, vendored `.S` with hash, vectors, CI + check: present. +2. `from_mont` and the helper (four reduction rounds): the smallest proof. +3. `mul`: round invariant, the accumulator no-wrap lemma under each contract, the + final comparison. +4. `sqr`: the cross-term schoolbook, doubling, and the "can't overflow" claims. +5. Pasta instantiation and census entries in `TrustBoundary.lean`. + +Out of scope for now: Zakura's inline-`asm!` transcription (provable later by +instruction-by-instruction correspondence), `sqr_n_mul` (zakura-core/common#65), and the carry-limb +drop (zakura-core/common#132). diff --git a/scripts/check_aarch64_pasta_mul.sh b/scripts/check_aarch64_pasta_mul.sh new file mode 100755 index 0000000..eb2a331 --- /dev/null +++ b/scripts/check_aarch64_pasta_mul.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Check that the transcription of pasta_curves' AArch64 Pasta Montgomery routines is +# current: the vendored assembly and reference vectors match their recorded hashes, and +# regenerating the Lean files from them reproduces the committed files exactly. +# +# Run from the repository root; exits non-zero on violation. +set -euo pipefail +cd "$(dirname "$0")/.." + +(cd CompElliptic/Asm/AArch64/vendor && shasum -a 256 -c SHA256SUMS) + +python3 scripts/gen_aarch64_pasta_mul.py +git diff --exit-code -- \ + CompElliptic/Asm/AArch64/PastaMul.lean CompElliptic/Asm/AArch64/PastaMulVectors.lean +echo "AArch64 Pasta transcription: current." diff --git a/scripts/gen_aarch64_pasta_mul.py b/scripts/gen_aarch64_pasta_mul.py new file mode 100755 index 0000000..443f810 --- /dev/null +++ b/scripts/gen_aarch64_pasta_mul.py @@ -0,0 +1,429 @@ +#!/usr/bin/env python3 +"""Generate the Lean transcription of pasta_curves' AArch64 Pasta Montgomery routines. + +Reads the vendored `CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S` and writes + +- `CompElliptic/Asm/AArch64/PastaMul.lean`: each routine as a Lean definition over the + instruction semantics of `CompElliptic.Asm.AArch64.Semantics`, one `let` per + instruction, in the assembly's order, with the instruction as a trailing comment; +- `CompElliptic/Asm/AArch64/PastaMulVectors.lean`: one kernel-checked example per line of + `vendor/pasta_mul-armv8-vectors.txt`, the outputs of the real routines on an Apple + M-series machine. + +The transcription is deliberately mechanical. Registers become Lean variables of the +same name, rebound by each instruction that writes them. Loads through an argument +pointer become reads of that argument's limbs; stores through the output pointer bind +the result limbs; the stack frame, the return address, and the pointer-authentication +words are not modelled, and the script checks that no instruction depends on them +(a register restored from the frame is treated as unknown, and reading an unknown +register is an error). The `bl` to the shared reduction helper becomes a call of the +helper's own definition, after which the registers the helper clobbers are unknown. + +A binding that nothing later reads is not emitted. For a load this records that the +assembly reads a limb it never uses (it hard-codes `p[2] = 0` and `p[3] = 2^62`), and +the dropped load is left as a comment; for a carry flag it is an ordinary unread flag +write. A computed register that is never read would be dead code in the routine and is +reported as an error, since none is expected. + +Run from the repository root: + + python3 scripts/gen_aarch64_pasta_mul.py + +`scripts/check_aarch64_pasta_mul.sh` regenerates and fails if the output differs from +the committed files. Python 3.9+; stdlib only. +""" +import re +import sys +import textwrap +from pathlib import Path + +ASM = Path("CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S") +VECTORS = Path("CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt") +OUT_PROGRAM = Path("CompElliptic/Asm/AArch64/PastaMul.lean") +OUT_VECTORS = Path("CompElliptic/Asm/AArch64/PastaMulVectors.lean") + +HEADER = """/- +Copyright (c) 2026 CompElliptic Contributors. +Released under the Apache License, Version 2.0, or the MIT license, at your option, +as described in the files LICENSE-APACHE and LICENSE-MIT. +Authors: Daira-Emma Hopwood +-/ +""" + +HELPER_LABEL = "L$pasta_curves_mul_by_1_mont_pasta" + +# Code longer than this does not set the instruction-comment column (see `Routine.text`). +COMMENT_COLUMN_MAX = 40 + +# Registers the helper writes without restoring; after a `bl` they hold nothing the +# caller may read. `x5`-`x8` are also written, to the modulus limbs, and are rebound. +HELPER_CLOBBERS = ["x3", "x9", "x14", "x15", "x17"] + +ROUTINES = [ + # (label, Lean name, docstring, pointer arguments in register order, inv register) + ("_pasta_curves_mul_mont_pasta", "mulMont", + "`_pasta_curves_mul_mont_pasta`: Montgomery multiplication, `lhs * rhs * 2^-256 mod p`, " + "with the result stored through `x0`.", + [("x1", "lhs"), ("x2", "rhs"), ("x3", "modulus")], "x4"), + ("_pasta_curves_sqr_mont_pasta", "sqrMont", + "`_pasta_curves_sqr_mont_pasta`: Montgomery squaring, `value^2 * 2^-256 mod p`.", + [("x1", "value"), ("x2", "modulus")], "x3"), + ("_pasta_curves_from_mont_pasta", "fromMont", + "`_pasta_curves_from_mont_pasta`: conversion out of Montgomery form, " + "`value * 2^-256 mod p`.", + [("x1", "value"), ("x2", "modulus")], "x3"), +] + + +def tokenize(rest): + return re.findall(r"\[[^\]]*\]!?|[^,\s]+", rest) + + +def parse(path): + """The instruction list and the label table; directives and comments dropped.""" + ins, labels = [], {} + for line in path.read_text().splitlines(): + text = line.split("//")[0].strip() + if not text or text.startswith("."): + continue + if text.endswith(":"): + labels[text[:-1]] = len(ins) + continue + m = re.match(r"(\S+)\s*(.*)", text) + assert m is not None + ins.append((m.group(1), tokenize(m.group(2)), re.sub(r"\s+", " ", text))) + return ins, labels + + +def imm(tok): + """An immediate operand such as `#62` or `8*1`, as an integer.""" + s = tok.lstrip("#") + if not re.fullmatch(r"-?[0-9]+(\*[0-9]+)?", s): + raise ValueError(f"unexpected immediate {tok}") + return eval(s) + + +class Emitter: + """Transcribes one routine, from its label to its `ret`, into Lean `let` bindings.""" + + def __init__(self, ins, labels, helper_name): + self.ins, self.labels, self.helper_name = ins, labels, helper_name + self.entries = [] # dicts: name, expr, comment, reads, load (bool) + self.ptrs = {} # register -> argument name it points to + self.known = set() # names holding a value the program may read + self.outputs = {} # output limb index -> bound name + self.cur_reads = set() + + # -- operands ---------------------------------------------------------------- + + def read(self, tok): + if tok == "xzr": + return "0" + if tok.startswith("#"): + return str(imm(tok)) + if tok in self.ptrs: + raise ValueError(f"{tok} is a pointer, read as a value") + if tok not in self.known: + raise ValueError(f"{tok} read before being written") + self.cur_reads.add(tok) + return tok + + def bind(self, name, expr, comment, reads=None, load=False): + if name == "xzr": + return + self.ptrs.pop(name, None) + self.known.add(name) + self.entries.append(dict(name=name, expr=expr, comment=comment, + reads=set(self.cur_reads) if reads is None else set(reads), + load=load)) + + def mem(self, tok): + """(base register, byte offset) of a memory operand, or None for the frame.""" + inner = tok.strip("!").strip("[]") + parts = inner.split(",") + base = parts[0] + off = imm(parts[1]) if len(parts) > 1 else 0 + if base in ("sp", "x29"): + return None + return base, off + + def limb(self, base, off): + if base not in self.ptrs: + raise ValueError(f"load through {base}, which is not an argument pointer") + if off % 8: + raise ValueError(f"unaligned offset {off}") + return f"{self.ptrs[base]}.l{off // 8}" + + # -- instructions -------------------------------------------------------------- + + def step(self, op, t, text): + self.cur_reads = set() + if op in ("ldp", "ldr"): + if len(t) == 3 and op == "ldr": # post-indexed frame release + return + m = self.mem(t[-1]) + if m is None: # restore from the frame: the value is not modelled + for r in t[:-1]: + self.known.discard(r) + self.ptrs.pop(r, None) + return + base, off = m + for i, r in enumerate(t[:-1]): + self.bind(r, self.limb(base, off + 8 * i), text, reads=(), load=True) + elif op in ("stp", "str"): + m = self.mem(t[-1]) + if m is None: # spill to the frame + return + base, off = m + if self.ptrs.get(base) != "out": + raise ValueError(f"store through {base}, which is not the output pointer") + for i, r in enumerate(t[:-1]): + idx = off // 8 + i + self.cur_reads = set() + self.bind(f"out{idx}", self.read(r), text) + self.outputs[idx] = f"out{idx}" + elif op == "add": + if t[1] == "sp": # frame pointer setup + return + raise ValueError(f"unexpected add: {text}") + elif op == "mov": + self.bind(t[0], self.read(t[1]), text) + elif op == "mul": + self.bind(t[0], f"mulLo {self.read(t[1])} {self.read(t[2])}", text) + elif op == "umulh": + self.bind(t[0], f"umulh {self.read(t[1])} {self.read(t[2])}", text) + elif op == "lsl": + self.bind(t[0], f"lsl {self.read(t[1])} {imm(t[2])}", text) + elif op == "lsr": + self.bind(t[0], f"lsr {self.read(t[1])} {imm(t[2])}", text) + elif op in ("adds", "adcs", "adc"): + cin = "0" if op == "adds" else self.read("c") + expr = f"addc {self.read(t[1])} {self.read(t[2])} {cin}" + if op == "adc": + self.bind(t[0], f"({expr}).1", text) + else: + self.bind("s", expr, text) + self.bind(t[0], "s.1", text, reads=("s",)) + self.bind("c", "s.2", text, reads=("s",)) + elif op in ("subs", "sbcs"): + cin = "1" if op == "subs" else self.read("c") + expr = f"subc {self.read(t[1])} {self.read(t[2])} {cin}" + if t[0] == "xzr": + self.bind("c", f"({expr}).2", text) + else: + self.bind("s", expr, text) + self.bind(t[0], "s.1", text, reads=("s",)) + self.bind("c", "s.2", text, reads=("s",)) + elif op == "csel": + if t[3] != "lo": + raise ValueError(f"unexpected condition: {text}") + self.bind(t[0], f"cselLo {self.read('c')} {self.read(t[1])} {self.read(t[2])}", text) + elif op == "bl": + if t[0] != HELPER_LABEL: + raise ValueError(f"unexpected call: {text}") + if self.ptrs.get("x2") != "modulus": + raise ValueError("helper called without the modulus pointer in x2") + args = ", ".join(self.read(r) for r in ("x10", "x11", "x12", "x13")) + self.bind("r", f"{self.helper_name} ⟨{args}⟩ modulus {self.read('x4')}", text) + for i, r in enumerate(("x10", "x11", "x12", "x13")): + self.bind(r, f"r.l{i}", "helper output", reads=("r",)) + for i, r in enumerate(("x5", "x6", "x7", "x8")): + self.bind(r, f"modulus.l{i}", "loaded by the helper", reads=(), load=True) + for r in HELPER_CLOBBERS: + self.known.discard(r) + self.ptrs.pop(r, None) + self.known.discard("c") + else: + raise ValueError(f"unhandled instruction: {text}") + + def run(self, start): + pc = start + while True: + op, t, text = self.ins[pc] + if op == "ret": + return + self.step(op, t, text) + pc += 1 + + # -- output ------------------------------------------------------------------------ + + def render(self, result_names): + """The `let` lines, with bindings that nothing reads dropped (see the module doc).""" + needed = set(result_names) + live = [False] * len(self.entries) + for i in range(len(self.entries) - 1, -1, -1): + e = self.entries[i] + if e["name"] in needed: + live[i] = True + needed.discard(e["name"]) + needed |= e["reads"] + lines = [] # (code, comment): a `let` with its instruction, or (None, whole-line comment) + for e, keep in zip(self.entries, live): + if keep: + lines.append((f" let {e['name']} := {e['expr']}", e["comment"])) + elif e["load"]: + lines.append((None, f" -- {e['comment']}: {e['name']} = {e['expr']} is never read")) + elif e["name"] != "c": + raise ValueError(f"dead computation: {e['name']} := {e['expr']} ({e['comment']})") + return lines + + +def emit_helper(ins, labels): + e = Emitter(ins, labels, "mulBy1") + e.ptrs["x2"] = "modulus" + for i, r in enumerate(("x10", "x11", "x12", "x13")): + e.bind(r, f"t.l{i}", "argument", reads=()) + e.bind("x4", "inv", "argument", reads=()) + e.run(labels[HELPER_LABEL]) + e.cur_reads = set() + result = [e.read(r) for r in ("x10", "x11", "x12", "x13")] + doc = ("The shared reduction helper (`L$pasta_curves_mul_by_1_mont_pasta`): four Montgomery " + "cancellation steps on `t`, returning `(t + Q * p) / 2^256` for the `Q` they choose, " + "without a final conditional subtraction. `x10`-`x13` hold `t` and `x4` holds `inv` on " + "entry; the modulus limbs are loaded through `x2`.") + return Routine(doc, "def mulBy1 (t modulus : Limbs) (inv : Nat) : Limbs :=", e.render(result), + f" ⟨{', '.join(result)}⟩") + + +def emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg): + e = Emitter(ins, labels, "mulBy1") + e.ptrs["x0"] = "out" + for reg, arg in ptr_args: + e.ptrs[reg] = arg + e.bind(inv_reg, "inv", "argument", reads=()) + e.run(labels[label]) + if sorted(e.outputs) != [0, 1, 2, 3]: + raise ValueError(f"{name}: outputs stored: {sorted(e.outputs)}") + result = [e.outputs[i] for i in range(4)] + params = " ".join(arg for _, arg in ptr_args) + return Routine(doc, f"def {name} ({params} : Limbs) (inv : Nat) : Limbs :=", e.render(result), + f" ⟨{', '.join(result)}⟩") + + +class Routine: + """A transcribed routine: docstring, signature line, body lines, and result line.""" + + def __init__(self, doc, signature, lines, result): + self.doc, self.signature, self.lines, self.result = doc, signature, lines, result + + def text(self, column): + """The definition, with the instruction comments aligned at `column`; a line whose code + reaches the column (an outlier, such as the helper call) gets its comment two spaces + after the code instead.""" + body = [] + for code, comment in self.lines: + if code is None: + body.append(comment) + else: + body.append(f"{code.ljust(column) if len(code) + 2 <= column else code + ' '}-- {comment}") + return f"{docstring(self.doc)}\n{self.signature}\n" + "\n".join(body) + f"\n{self.result}\n" + + +def docstring(text, width=100): + """A `/-- ... -/` docstring wrapped to the repository's line width.""" + lines = textwrap.TextWrapper(width=width, break_long_words=False, break_on_hyphens=False, + initial_indent="/-- ").wrap(text) + if len(lines[-1]) + 3 <= width: + lines[-1] += " -/" + else: + lines.append("-/") + return "\n".join(lines) + + +def gen_program(ins, labels): + parts = [HEADER, "import CompElliptic.Asm.AArch64.Semantics\n", """ +/-! +# The Pasta Montgomery routines of `pasta_mul-armv8.S`, transcribed + +GENERATED by `scripts/gen_aarch64_pasta_mul.py` from +`CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S`; do not edit by hand. Each definition +follows its routine instruction by instruction (the instruction is the trailing comment), +over the semantics of `CompElliptic.Asm.AArch64.Semantics`: registers are rebound by the +instructions that write them, `c` is the carry flag, `s` is the (result, carry) pair of the +instruction that last set both, argument limbs are read where the assembly loads them, and +the output limbs are bound where the assembly stores them. Bindings that nothing reads are +left as comments; the stack frame and the return address are not part of the model. See the +generator's docstring for what it checks. +-/ + +namespace CompElliptic.Asm.AArch64 + +"""] + routines = [emit_helper(ins, labels)] + for label, name, doc, ptr_args, inv_reg in ROUTINES: + routines.append(emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg)) + # One comment column for the whole file: two spaces past the widest ordinary `let`. Lines + # longer than COMMENT_COLUMN_MAX are outliers (the helper call) and do not set the column. + column = 2 + max(len(code) for r in routines for code, _ in r.lines + if code is not None and len(code) <= COMMENT_COLUMN_MAX) + parts.append("\n".join(r.text(column) for r in routines)) + parts.append("\nend CompElliptic.Asm.AArch64\n") + return "".join(parts) + + +FIELDS = { + "Fp": ("pallasBase", "⟨0x992d30ed00000001, 0x224698fc094cf91b, 0, 0x4000000000000000⟩", + "0x992d30ecffffffff"), + "Fq": ("vestaBase", "⟨0x8c46eb2100000001, 0x224698fc0994a8dd, 0, 0x4000000000000000⟩", + "0x8c46eb20ffffffff"), +} + + +def gen_vectors(lines): + out = [HEADER, "import CompElliptic.Asm.AArch64.PastaMul\n", """ +/-! +# Reference vectors for the transcribed routines + +GENERATED by `scripts/gen_aarch64_pasta_mul.py` from +`CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8-vectors.txt`; do not edit by hand. Each +vector is the output of the real assembly (pasta_curves `8ad85e9fab7929f6236960e472f432a4bd9ccd74`, +run on an Apple M-series machine) on the given operands, and each example asks the kernel +to evaluate the transcription on the same operands. The vectors cover boundary operands +(zero, one, `R`, `R2`, `R3`, `p - 1`, single all-ones limbs), random canonical operands, +and unreduced operands in both positions, so they also record the routines' behaviour +outside their operand contracts. + +The modulus limbs and `inv` are the crate's constants for its `Fp` (the Pallas base field) +and `Fq` (the Vesta base field). +-/ + +namespace CompElliptic.Asm.AArch64 + +"""] + for key, (prefix, limbs, inv) in FIELDS.items(): + field = "Pallas" if key == "Fp" else "Vesta" + out.append(f"/-- The {field} base field modulus, as the crate's `MODULUS` limbs. -/\n") + out.append(f"def {prefix}Modulus : Limbs := {limbs}\n\n") + out.append(f"/-- `-p^-1 mod 2^64` for the {field} base field, the crate's `INV`. -/\n") + out.append(f"def {prefix}Inv : Nat := {inv}\n\n") + n = 0 + for line in lines: + parts = line.split() + if not parts: + continue + op, key, *vals = parts + prefix = FIELDS[key][0] + vals = [f"(Limbs.ofNat 0x{v})" for v in vals] + fn = {"MUL": "mulMont", "SQR": "sqrMont", "FROM": "fromMont"}.get(op) + if fn is None: + raise ValueError(line) + *operands, r = vals + # One operand per line keeps every line within the repository's width. + out.append(f"example :\n {fn}\n") + for v in operands: + out.append(f" {v}\n") + out.append(f" {prefix}Modulus {prefix}Inv =\n {r} := by\n decide +kernel\n\n") + n += 1 + out.append(f"\n-- {n} vectors.\n\nend CompElliptic.Asm.AArch64\n") + return "".join(out) + + +def main(): + ins, labels = parse(ASM) + OUT_PROGRAM.write_text(gen_program(ins, labels)) + OUT_VECTORS.write_text(gen_vectors(VECTORS.read_text().splitlines())) + print(f"wrote {OUT_PROGRAM} ({len(ins)} instructions parsed) and {OUT_VECTORS}") + + +if __name__ == "__main__": + sys.exit(main()) From b912050eef06ef3cda36c46f6df80d490881ae44 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 03:06:21 +0100 Subject: [PATCH 2/9] asm: generate the mechanical part of the AArch64 correctness proofs `gen_aarch64_pasta_mul.py --skeleton NAME` prints the proof steps of a transcribed routine that follow from its instruction stream alone: unfold the definition, extract its `let`s under unique names, and for every instruction record the defining equation of the result by `rfl`, derive the linear facts that later steps need (the carry-chain equation, the range facts, the product and shift decompositions), clear the `%`/`/` equation, and make the local opaque with `clear_value`. Hand-written annotation blocks (`-- BEGIN ... -- END`) go between the generated groups. `--check-spec FILE` strips the blocks and requires the rest of each proof to be the current skeleton, so an edit to the assembly regenerates the skeleton and fails the check until the annotations are moved. For this, the emitter records with each binding a description of the instruction and its operands, a routine carries its emitter and result names, and the liveness pass is shared with the transcription. Co-authored-by: Claude Fable 5.1 --- scripts/gen_aarch64_pasta_mul.py | 316 +++++++++++++++++++++++++++---- 1 file changed, 279 insertions(+), 37 deletions(-) diff --git a/scripts/gen_aarch64_pasta_mul.py b/scripts/gen_aarch64_pasta_mul.py index 443f810..4e2bad8 100755 --- a/scripts/gen_aarch64_pasta_mul.py +++ b/scripts/gen_aarch64_pasta_mul.py @@ -30,7 +30,13 @@ python3 scripts/gen_aarch64_pasta_mul.py `scripts/check_aarch64_pasta_mul.sh` regenerates and fails if the output differs from -the committed files. Python 3.9+; stdlib only. +the committed files. + +The script also generates the mechanical part of each routine's correctness proof in +`CompElliptic/Asm/AArch64/PastaMulSpec.lean`: `--skeleton NAME` prints it (see +`skeleton`), and `--check-spec FILE` checks that FILE contains every routine's skeleton +verbatim once its `-- BEGIN ... -- END` annotation blocks are removed; the check script +runs that too. Python 3.9+; stdlib only. """ import re import sys @@ -128,14 +134,16 @@ def read(self, tok): self.cur_reads.add(tok) return tok - def bind(self, name, expr, comment, reads=None, load=False): + def bind(self, name, expr, comment, reads=None, load=False, fact=None): + """Record a binding. `fact` is the skeleton's description of it: a tuple whose head + names the kind of instruction and whose remaining items are the operand names.""" if name == "xzr": return self.ptrs.pop(name, None) self.known.add(name) self.entries.append(dict(name=name, expr=expr, comment=comment, reads=set(self.cur_reads) if reads is None else set(reads), - load=load)) + load=load, fact=fact)) def mem(self, tok): """(base register, byte offset) of a memory operand, or None for the frame.""" @@ -169,7 +177,8 @@ def step(self, op, t, text): return base, off = m for i, r in enumerate(t[:-1]): - self.bind(r, self.limb(base, off + 8 * i), text, reads=(), load=True) + self.bind(r, self.limb(base, off + 8 * i), text, reads=(), load=True, + fact=("load", self.ptrs[base], (off + 8 * i) // 8)) elif op in ("stp", "str"): m = self.mem(t[-1]) if m is None: # spill to the frame @@ -180,55 +189,66 @@ def step(self, op, t, text): for i, r in enumerate(t[:-1]): idx = off // 8 + i self.cur_reads = set() - self.bind(f"out{idx}", self.read(r), text) + self.bind(f"out{idx}", self.read(r), text, fact=("out", r)) self.outputs[idx] = f"out{idx}" elif op == "add": if t[1] == "sp": # frame pointer setup return raise ValueError(f"unexpected add: {text}") elif op == "mov": - self.bind(t[0], self.read(t[1]), text) + a = self.read(t[1]) + self.bind(t[0], a, text, fact=("mov", a)) elif op == "mul": - self.bind(t[0], f"mulLo {self.read(t[1])} {self.read(t[2])}", text) + a, b = self.read(t[1]), self.read(t[2]) + self.bind(t[0], f"mulLo {a} {b}", text, fact=("mul", a, b)) elif op == "umulh": - self.bind(t[0], f"umulh {self.read(t[1])} {self.read(t[2])}", text) + a, b = self.read(t[1]), self.read(t[2]) + self.bind(t[0], f"umulh {a} {b}", text, fact=("umulh", a, b)) elif op == "lsl": - self.bind(t[0], f"lsl {self.read(t[1])} {imm(t[2])}", text) + a, k = self.read(t[1]), imm(t[2]) + self.bind(t[0], f"lsl {a} {k}", text, fact=("lsl", a, k)) elif op == "lsr": - self.bind(t[0], f"lsr {self.read(t[1])} {imm(t[2])}", text) + a, k = self.read(t[1]), imm(t[2]) + self.bind(t[0], f"lsr {a} {k}", text, fact=("lsr", a, k)) elif op in ("adds", "adcs", "adc"): cin = "0" if op == "adds" else self.read("c") - expr = f"addc {self.read(t[1])} {self.read(t[2])} {cin}" + a, b = self.read(t[1]), self.read(t[2]) + expr = f"addc {a} {b} {cin}" if op == "adc": - self.bind(t[0], f"({expr}).1", text) + self.bind(t[0], f"({expr}).1", text, fact=("adc", a, b, cin)) else: - self.bind("s", expr, text) - self.bind(t[0], "s.1", text, reads=("s",)) - self.bind("c", "s.2", text, reads=("s",)) + self.bind("s", expr, text, fact=("adds", a, b, cin)) + self.bind(t[0], "s.1", text, reads=("s",), fact=("fst",)) + self.bind("c", "s.2", text, reads=("s",), fact=("snd",)) elif op in ("subs", "sbcs"): cin = "1" if op == "subs" else self.read("c") - expr = f"subc {self.read(t[1])} {self.read(t[2])} {cin}" + a, b = self.read(t[1]), self.read(t[2]) + expr = f"subc {a} {b} {cin}" if t[0] == "xzr": - self.bind("c", f"({expr}).2", text) + self.bind("c", f"({expr}).2", text, fact=("subs_carry", a, b, cin)) else: - self.bind("s", expr, text) - self.bind(t[0], "s.1", text, reads=("s",)) - self.bind("c", "s.2", text, reads=("s",)) + self.bind("s", expr, text, fact=("subs", a, b, cin)) + self.bind(t[0], "s.1", text, reads=("s",), fact=("fst",)) + self.bind("c", "s.2", text, reads=("s",), fact=("snd",)) elif op == "csel": if t[3] != "lo": raise ValueError(f"unexpected condition: {text}") - self.bind(t[0], f"cselLo {self.read('c')} {self.read(t[1])} {self.read(t[2])}", text) + c, a, b = self.read("c"), self.read(t[1]), self.read(t[2]) + self.bind(t[0], f"cselLo {c} {a} {b}", text, fact=("csel", c, a, b)) elif op == "bl": if t[0] != HELPER_LABEL: raise ValueError(f"unexpected call: {text}") if self.ptrs.get("x2") != "modulus": raise ValueError("helper called without the modulus pointer in x2") - args = ", ".join(self.read(r) for r in ("x10", "x11", "x12", "x13")) - self.bind("r", f"{self.helper_name} ⟨{args}⟩ modulus {self.read('x4')}", text) + targs = [self.read(r) for r in ("x10", "x11", "x12", "x13")] + inv = self.read("x4") + self.bind("r", f"{self.helper_name} ⟨{', '.join(targs)}⟩ modulus {inv}", text, + fact=("call", *targs, inv)) for i, r in enumerate(("x10", "x11", "x12", "x13")): - self.bind(r, f"r.l{i}", "helper output", reads=("r",)) + self.bind(r, f"r.l{i}", "helper output", reads=("r",), fact=("callout", i)) for i, r in enumerate(("x5", "x6", "x7", "x8")): - self.bind(r, f"modulus.l{i}", "loaded by the helper", reads=(), load=True) + self.bind(r, f"modulus.l{i}", "loaded by the helper", reads=(), load=True, + fact=("load", "modulus", i)) for r in HELPER_CLOBBERS: self.known.discard(r) self.ptrs.pop(r, None) @@ -247,8 +267,8 @@ def run(self, start): # -- output ------------------------------------------------------------------------ - def render(self, result_names): - """The `let` lines, with bindings that nothing reads dropped (see the module doc).""" + def liveness(self, result_names): + """Which entries something later reads, by a backward pass from the result names.""" needed = set(result_names) live = [False] * len(self.entries) for i in range(len(self.entries) - 1, -1, -1): @@ -257,6 +277,11 @@ def render(self, result_names): live[i] = True needed.discard(e["name"]) needed |= e["reads"] + return live + + def render(self, result_names): + """The `let` lines, with bindings that nothing reads dropped (see the module doc).""" + live = self.liveness(result_names) lines = [] # (code, comment): a `let` with its instruction, or (None, whole-line comment) for e, keep in zip(self.entries, live): if keep: @@ -272,8 +297,8 @@ def emit_helper(ins, labels): e = Emitter(ins, labels, "mulBy1") e.ptrs["x2"] = "modulus" for i, r in enumerate(("x10", "x11", "x12", "x13")): - e.bind(r, f"t.l{i}", "argument", reads=()) - e.bind("x4", "inv", "argument", reads=()) + e.bind(r, f"t.l{i}", "argument", reads=(), fact=("load", "t", i)) + e.bind("x4", "inv", "argument", reads=(), fact=("inv",)) e.run(labels[HELPER_LABEL]) e.cur_reads = set() result = [e.read(r) for r in ("x10", "x11", "x12", "x13")] @@ -282,7 +307,7 @@ def emit_helper(ins, labels): "without a final conditional subtraction. `x10`-`x13` hold `t` and `x4` holds `inv` on " "entry; the modulus limbs are loaded through `x2`.") return Routine(doc, "def mulBy1 (t modulus : Limbs) (inv : Nat) : Limbs :=", e.render(result), - f" ⟨{', '.join(result)}⟩") + f" ⟨{', '.join(result)}⟩", "mulBy1", e, result) def emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg): @@ -290,21 +315,23 @@ def emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg): e.ptrs["x0"] = "out" for reg, arg in ptr_args: e.ptrs[reg] = arg - e.bind(inv_reg, "inv", "argument", reads=()) + e.bind(inv_reg, "inv", "argument", reads=(), fact=("inv",)) e.run(labels[label]) if sorted(e.outputs) != [0, 1, 2, 3]: raise ValueError(f"{name}: outputs stored: {sorted(e.outputs)}") result = [e.outputs[i] for i in range(4)] params = " ".join(arg for _, arg in ptr_args) return Routine(doc, f"def {name} ({params} : Limbs) (inv : Nat) : Limbs :=", e.render(result), - f" ⟨{', '.join(result)}⟩") + f" ⟨{', '.join(result)}⟩", name, e, result) class Routine: - """A transcribed routine: docstring, signature line, body lines, and result line.""" + """A transcribed routine: docstring, signature line, body lines, and result line, plus the + emitter and result names for the proof skeleton.""" - def __init__(self, doc, signature, lines, result): + def __init__(self, doc, signature, lines, result, name, emitter, result_names): self.doc, self.signature, self.lines, self.result = doc, signature, lines, result + self.name, self.emitter, self.result_names = name, emitter, result_names def text(self, column): """The definition, with the instruction comments aligned at `column`; a line whose code @@ -349,9 +376,7 @@ def gen_program(ins, labels): namespace CompElliptic.Asm.AArch64 """] - routines = [emit_helper(ins, labels)] - for label, name, doc, ptr_args, inv_reg in ROUTINES: - routines.append(emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg)) + routines = all_routines(ins, labels) # One comment column for the whole file: two spaces past the widest ordinary `let`. Lines # longer than COMMENT_COLUMN_MAX are outliers (the helper call) and do not set the column. column = 2 + max(len(code) for r in routines for code, _ in r.lines @@ -418,8 +443,225 @@ def gen_vectors(lines): return "".join(out) +# --- proof skeletons -------------------------------------------------------------------- + +# Bounds hypotheses the annotated spec theorems must provide, by argument name. +BOUND_HYPS = {"t": "ht", "modulus": "hm", "lhs": "hlhs", "rhs": "hrhs", "value": "hv"} +INV_BOUND_HYP = "hinv_lt" +PROJ = ["1", "2.1", "2.2.1", "2.2.2"] +SKELETON_WIDTH = 100 + + +def ssa_names(entries): + """Unique names for the live bindings: the first binding of a register keeps its name, + later ones get `_1`, `_2`, ...""" + counts, names = {}, [] + for e in entries: + n = counts.get(e["name"], 0) + counts[e["name"]] = n + 1 + names.append(e["name"] if n == 0 else f"{e['name']}_{n}") + return names + + +def wrap_tactic(head, words, tail, indent=" "): + """`head w1 w2 ... tail`, broken over lines at SKELETON_WIDTH with a 4-space continuation.""" + lines, cur = [], indent + head + for w in words: + if len(cur) + 1 + len(w) > SKELETON_WIDTH: + lines.append(cur) + cur = indent + " " + w + else: + cur += " " + w + lines.append(cur + tail) + return lines + + +def skeleton(routine): + """The generated part of the correctness proof of `routine`: unfold, extract the lets under + SSA names, then per instruction the defining equation (by `rfl`, in `%`/`/` form), the range + fact (by `omega`), and `clear_value`. Hand-written annotations go between the groups.""" + e = routine.emitter + live = e.liveness(routine.result_names) + entries = [en for en, keep in zip(e.entries, live) if keep] + names = ssa_names(entries) + ren = {} # current SSA name of each register at each point: resolved while walking + out = [f" -- generated skeleton for `{routine.name}`: do not edit between the annotations", + f" unfold {routine.name} at hr", " lift_lets at hr"] + out += wrap_tactic("extract_lets", names, " at hr") + out.append(" subst hr") + products, shifts = {}, {} + + def r(op): # operand as written in the entry, renamed to its SSA name at that point + return ren.get(op, op) + + def bound(op): + return None if re.fullmatch(r"[0-9]+", op) else f"b_{op}" + + i = 0 + while i < len(entries): + en, nm = entries[i], names[i] + kind, *ops = en["fact"] + ops = [r(o) if isinstance(o, str) else o for o in ops] + group = [nm] + lines = [] + # Every step records only facts `omega` handles cheaply later: linear equations, bounds, + # and at most a disjunction. The `%`/`/` equations are derived by `rfl`, used to prove + # those facts, and cleared. + if kind == "load": + arg, idx = ops + hyp = BOUND_HYPS[arg] + lines.append(f" have e_{nm} : {nm} = {arg}.l{idx} := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {hyp}.{PROJ[idx]}") + elif kind == "inv": + lines.append(f" have e_{nm} : {nm} = inv := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {INV_BOUND_HYP}") + elif kind == "mov": + (a,) = ops + lines.append(f" have e_{nm} : {nm} = {a} := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + elif kind == "mul": + a, b = ops + lines.append(f" have e_{nm} : {nm} = {a} * {b} % 2^64 := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + products[(a, b)] = nm # its `%` equation is cleared at the matching `umulh` + elif kind == "umulh": + a, b = ops + lines.append(f" have p_{nm} : {a} * {b} < 2^128 :=") + lines.append(f" lt_of_lt_of_eq (Nat.mul_lt_mul'' {bound(a)} {bound(b)}) (by norm_num)") + lines.append(f" have e_{nm} : {nm} = {a} * {b} / 2^64 := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + if (a, b) in products: + lo = products.pop((a, b)) + lines.append(f" have d_{nm} : {lo} + 2^64 * {nm} = {a} * {b} := by omega") + lines.append(f" clear e_{lo} e_{nm}") + else: + # The low half is never computed (its cancellation is arranged by `subs`); name + # it as a ghost so that later steps need no `%`. + lines.append(f" obtain ⟨lo_{nm}, b_lo_{nm}, d_{nm}⟩ :") + lines.append(f" ∃ lo, lo < 2^64 ∧ lo + 2^64 * {nm} = {a} * {b} :=") + lines.append(f" ⟨{a} * {b} % 2^64, by omega, by omega⟩") + lines.append(f" clear e_{nm}") + elif kind == "lsl": + a, k = ops + lines.append(f" have e_{nm} : {nm} = {a} * 2^{k} % 2^64 := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + shifts[(a, k)] = nm + elif kind == "lsr": + a, k = ops + lines.append(f" have e_{nm} : {nm} = {a} / 2^{k} := rfl") + lines.append(f" have b_{nm} : {nm} < 2^{64 - k} := by omega") + if (a, 64 - k) in shifts: + lo = shifts.pop((a, 64 - k)) + lines.append(f" have sh_{nm} : {lo} + 2^64 * {nm} = {a} * 2^{64 - k} := by omega") + lines.append(f" clear e_{lo} e_{nm}") + elif kind in ("adds", "subs"): + a, b, cin = ops + xn, cn = names[i + 1], names[i + 2] + group += [xn, cn] + if kind == "adds": + val = f"({a} + {b} + {cin})" + lin = f"{xn} + 2^64 * {cn} = {a} + {b} + {cin}" + else: + val = f"({a} + 2^64 - {b} - (1 - {cin}))" + lin = f"{xn} + 2^64 * {cn} + {b} + 1 = {a} + 2^64 + {cin}" + lines.append(f" have e_{xn} : {xn} = {val} % 2^64 := rfl") + lines.append(f" have e_{cn} : {cn} = {val} / 2^64 := rfl") + lines.append(f" have l_{xn} : {lin} := by omega") + lines.append(f" have b_{xn} : {xn} < 2^64 := by omega") + lines.append(f" have b_{cn} : {cn} ≤ 1 := by omega") + lines.append(f" clear e_{xn} e_{cn}") + ren[entries[i + 1]["name"]] = xn + ren[entries[i + 2]["name"]] = cn + i += 2 + elif kind == "adc": + a, b, cin = ops + lines.append(f" have e_{nm} : {nm} = ({a} + {b} + {cin}) % 2^64 := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" obtain ⟨k_{nm}, b_k_{nm}, l_{nm}⟩ :") + lines.append(f" ∃ k, k ≤ 1 ∧ {nm} + 2^64 * k = {a} + {b} + {cin} :=") + lines.append(f" ⟨({a} + {b} + {cin}) / 2^64, by omega, by omega⟩") + lines.append(f" clear e_{nm}") + elif kind == "subs_carry": + a, b, cin = ops + lines.append(f" have e_{nm} : {nm} = ({a} + 2^64 - {b} - (1 - {cin})) / 2^64 := rfl") + lines.append(f" have l_{nm} : ({nm} = 1 ∧ {b} + 1 ≤ {a} + {cin})" + f" ∨ ({nm} = 0 ∧ {a} + {cin} < {b} + 1) := by") + lines.append(f" omega") + lines.append(f" clear e_{nm}") + elif kind == "csel": + c, a, b = ops + lines.append(f" have e_{nm} : {nm} = (if {c} = 0 then {a} else {b}) := rfl") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; split <;> omega") + elif kind == "call": + *targs, inv = ops + lines.append(f" have e_{nm} : {nm} = mulBy1 ⟨{', '.join(targs)}⟩ modulus {inv} := rfl") + elif kind == "callout": + (idx,) = ops + lines.append(f" have e_{nm} : {nm} = {r('r')}.l{idx} := rfl") + elif kind == "out": + (x,) = ops + lines.append(f" have e_{nm} : {nm} = {x} := rfl") + else: + raise ValueError(kind) + ren[en["name"]] = nm + out += lines + out.append(f" clear_value {' '.join(group)}") + i += 1 + return out + + +def check_spec(path, routines): + """Verify that each routine's skeleton appears verbatim and contiguously in `path` once its + `-- BEGIN ... -- END` annotation blocks are removed and blank lines dropped. Text outside the + skeletons (theorem statements, lemmas, the closing steps) is free; text between two + skeleton lines must be inside an annotation block.""" + text = Path(path).read_text() + stripped = re.sub(r"(?ms)^\s*-- BEGIN[^\n]*\n.*?^\s*-- END[^\n]*\n", "", text) + remaining = [l for l in stripped.splitlines() if l.strip()] + ok = True + for rt in routines: + sk = [l for l in skeleton(rt) if l.strip()] + n = len(sk) + if sk[1] not in remaining: # `unfold at hr`: the theorem is not in this file + continue + for start in range(len(remaining) - n + 1): + if remaining[start:start + n] == sk: + del remaining[start:start + n] + break + else: + i = remaining.index(sk[1]) + for j, l in enumerate(sk): + if i + j >= len(remaining) or remaining[i + j] != l: + print(f"{path}: skeleton of {rt.name} diverges at skeleton line {j}:", + file=sys.stderr) + print(f" expected: {l}", file=sys.stderr) + print(f" found: {remaining[i + j] if i + j < len(remaining) else ''}", + file=sys.stderr) + break + ok = False + return ok + + +def all_routines(ins, labels): + routines = [emit_helper(ins, labels)] + for label, name, doc, ptr_args, inv_reg in ROUTINES: + routines.append(emit_routine(ins, labels, label, name, doc, ptr_args, inv_reg)) + return routines + + def main(): ins, labels = parse(ASM) + if len(sys.argv) >= 3 and sys.argv[1] == "--skeleton": + for rt in all_routines(ins, labels): + if rt.name == sys.argv[2]: + print("\n".join(skeleton(rt))) + return 0 + print(f"no routine {sys.argv[2]}", file=sys.stderr) + return 1 + if len(sys.argv) >= 3 and sys.argv[1] == "--check-spec": + ok = check_spec(sys.argv[2], all_routines(ins, labels)) + print(f"{sys.argv[2]}: skeletons {'current' if ok else 'STALE'}") + return 0 if ok else 1 OUT_PROGRAM.write_text(gen_program(ins, labels)) OUT_VECTORS.write_text(gen_vectors(VECTORS.read_text().splitlines())) print(f"wrote {OUT_PROGRAM} ({len(ins)} instructions parsed) and {OUT_VECTORS}") From 6afd636a19a9e8ab014f668ce8d8752b9be3930e Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 03:21:31 +0100 Subject: [PATCH 3/9] asm: prove the shared Montgomery reduction helper correct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `mulBy1_spec`: for every four-limb `t`, a modulus with limbs `[p0, p1, 0, 2^62]`, and `inv * p0 ≡ -1 (mod 2^64)`, the helper returns limbs below `2^64` whose value `r` satisfies `2^256 * r = t + Q * p` for some `Q < 2^256`. The proof is the generated skeleton for `mulBy1` with four hand-written round blocks and a conclusion block. A round block rewrites the Montgomery cancellation fact to the linear equation `t0 + lo = 2^64 * c`, via the ghost low product limb and the carry of `subs xzr, t0, #1`; shows that neither `adc` wraps; and obtains the round invariant as a linear combination of the instruction equations, with `omega` run in a context cleared down to those equations. Keeping `%` and `/` out of the invariants' `omega` calls is what makes them fast: with the cancellation fact's `%` terms present, the same call ran for minutes without finishing. The CI check script also runs `--check-spec` on the spec file. The design document describes the proof method, records the helper's theorem as proved, gives the assembly's instruction count as 310 (the count it stated included labels and directives), and says that the FFI boundary is not modelled formally (it had said that the boundary was outside the trusted base); the README's list of what is present mentions the proof. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 568 +++++++++++++++++++++ README.md | 5 +- design/aarch64-pasta-mul-verification.md | 95 ++-- scripts/check_aarch64_pasta_mul.sh | 6 +- 4 files changed, 633 insertions(+), 41 deletions(-) create mode 100644 CompElliptic/Asm/AArch64/PastaMulSpec.lean diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean new file mode 100644 index 0000000..5633108 --- /dev/null +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -0,0 +1,568 @@ +/- +Copyright (c) 2026 CompElliptic Contributors. +Released under the Apache License, Version 2.0, or the MIT license, at your option, +as described in the files LICENSE-APACHE and LICENSE-MIT. +Authors: Daira-Emma Hopwood +-/ +import CompElliptic.Asm.AArch64.PastaMul +import Mathlib.Data.Nat.ModEq +import Mathlib.Tactic.Ring +import Mathlib.Tactic.NormNum +import Mathlib.Tactic.ClearExcept + +/-! +# Correctness of the transcribed Pasta Montgomery routines + +Each theorem here is proved over the transcription in `PastaMul.lean`, instruction by +instruction. The proof of a routine begins by unfolding it and extracting its `let`s under +unique names; then, for every instruction, the defining equation of its result (by `rfl`, in +`%`/`/` form) and its range are recorded and the local's value is cleared, so that each +`omega` call sees one carry step. Those lines are generated by +`scripts/gen_aarch64_pasta_mul.py --skeleton ` and must not be edited; the +hand-written parts are the theorem statements and the `-- BEGIN ... -- END` blocks, which +state the Montgomery round invariants where they hold. `scripts/check_aarch64_pasta_mul.sh` +strips the blocks and checks that what remains is the current skeleton. + +The moduli are assumed in the shape the code hard-codes: limbs `[p0, p1, 0, 2^62]`, with +`inv * p0 ≡ -1 (mod 2^64)`. +-/ + +namespace CompElliptic.Asm.AArch64 + +-- BEGIN cancel_low +/-- The Montgomery cancellation: with `inv * p0 ≡ -1 (mod 2^64)` and `q = inv * t0 mod 2^64`, the +low limb of `t0 + p0 * q` is zero. -/ +theorem cancel_low (t0 inv p0 : Nat) (h : (inv * p0 + 1) % 2^64 = 0) : + (t0 + p0 * (inv * t0 % 2^64) % 2^64) % 2^64 = 0 := by + have key : (t0 + p0 * (inv * t0)) % 2^64 = 0 := by + have : t0 + p0 * (inv * t0) = t0 * (inv * p0 + 1) := by ring + rw [this, Nat.mul_mod, h]; simp + have h1 : inv * t0 % 2^64 ≡ inv * t0 [MOD 2^64] := Nat.mod_modEq _ _ + have h2 : p0 * (inv * t0 % 2^64) % 2^64 ≡ p0 * (inv * t0) [MOD 2^64] := + (Nat.mod_modEq _ _).trans (Nat.ModEq.mul_left p0 h1) + have h3 : t0 + p0 * (inv * t0 % 2^64) % 2^64 ≡ t0 + p0 * (inv * t0) [MOD 2^64] := + Nat.ModEq.add_left t0 h2 + exact Eq.trans h3 key +-- END cancel_low + +-- BEGIN mulBy1_spec statement +/-- The shared reduction helper computes `(t + Q * p) / 2^256` for some `Q < 2^256`, with the +result in range, for any four-limb `t`. Since `Q < 2^256`, the result is congruent to +`t * 2^-256` modulo `p` and is below `p + t / 2^256 < p + 1`. -/ +theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modulus.Bounded) + (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) + (hinv_lt : inv < 2^64) (hinv : (inv * modulus.l0 + 1) % 2^64 = 0) : + ∀ r, r = mulBy1 t modulus inv → + r.Bounded ∧ ∃ Q, Q < 2^256 ∧ 2^256 * r.toNat = t.toNat + Q * modulus.toNat := by + intro r hr +-- END mulBy1_spec statement + -- generated skeleton for `mulBy1`: do not edit between the annotations + unfold mulBy1 at hr + lift_lets at hr + extract_lets x10 x11 x12 x13 x4 x3 x5 x6 x15 x17 c x14 s x11_1 c_1 x15_1 s_1 x12_1 c_2 s_2 x13_1 + c_3 x17_1 x9 s_3 x10_1 c_4 s_4 x11_2 c_5 s_5 x12_2 c_6 x3_1 x13_2 x15_2 x17_2 c_7 x14_1 s_6 + x11_3 c_8 x15_3 s_7 x12_3 c_9 s_8 x13_3 c_10 x17_3 x9_1 s_9 x10_2 c_11 s_10 x11_4 c_12 s_11 + x12_4 c_13 x3_2 x13_4 x15_4 x17_4 c_14 x14_2 s_12 x11_5 c_15 x15_5 s_13 x12_5 c_16 s_14 x13_5 + c_17 x17_5 x9_2 s_15 x10_3 c_18 s_16 x11_6 c_19 s_17 x12_6 c_20 x3_3 x13_6 x15_6 x17_6 c_21 + x14_3 s_18 x11_7 c_22 x15_7 s_19 x12_7 c_23 s_20 x13_7 c_24 x17_7 x9_3 s_21 x10_4 c_25 s_22 + x11_8 c_26 s_23 x12_8 c_27 x13_8 at hr + subst hr + have e_x10 : x10 = t.l0 := rfl + have b_x10 : x10 < 2^64 := by rw [e_x10]; exact ht.1 + clear_value x10 + have e_x11 : x11 = t.l1 := rfl + have b_x11 : x11 < 2^64 := by rw [e_x11]; exact ht.2.1 + clear_value x11 + have e_x12 : x12 = t.l2 := rfl + have b_x12 : x12 < 2^64 := by rw [e_x12]; exact ht.2.2.1 + clear_value x12 + have e_x13 : x13 = t.l3 := rfl + have b_x13 : x13 < 2^64 := by rw [e_x13]; exact ht.2.2.2 + clear_value x13 + have e_x4 : x4 = inv := rfl + have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt + clear_value x4 + have e_x3 : x3 = x4 * x10 % 2^64 := rfl + have b_x3 : x3 < 2^64 := by omega + clear_value x3 + have e_x5 : x5 = modulus.l0 := rfl + have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 + clear_value x5 + have e_x6 : x6 = modulus.l1 := rfl + have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 + clear_value x6 + have e_x15 : x15 = x6 * x3 % 2^64 := rfl + have b_x15 : x15 < 2^64 := by omega + clear_value x15 + have e_x17 : x17 = x3 * 2^62 % 2^64 := rfl + have b_x17 : x17 < 2^64 := by omega + clear_value x17 + have e_c : c = (x10 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have l_c : (c = 1 ∧ 1 + 1 ≤ x10 + 1) ∨ (c = 0 ∧ x10 + 1 < 1 + 1) := by + omega + clear e_c + clear_value c + have p_x14 : x5 * x3 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3) (by norm_num) + have e_x14 : x14 = x5 * x3 / 2^64 := rfl + have b_x14 : x14 < 2^64 := by omega + obtain ⟨lo_x14, b_lo_x14, d_x14⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14 = x5 * x3 := + ⟨x5 * x3 % 2^64, by omega, by omega⟩ + clear e_x14 + clear_value x14 + have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl + have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl + have l_x11_1 : x11_1 + 2^64 * c_1 = x11 + x15 + c := by omega + have b_x11_1 : x11_1 < 2^64 := by omega + have b_c_1 : c_1 ≤ 1 := by omega + clear e_x11_1 e_c_1 + clear_value s x11_1 c_1 + have p_x15_1 : x6 * x3 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3) (by norm_num) + have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl + have b_x15_1 : x15_1 < 2^64 := by omega + have d_x15_1 : x15 + 2^64 * x15_1 = x6 * x3 := by omega + clear e_x15 e_x15_1 + clear_value x15_1 + have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl + have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl + have l_x12_1 : x12_1 + 2^64 * c_2 = x12 + 0 + c_1 := by omega + have b_x12_1 : x12_1 < 2^64 := by omega + have b_c_2 : c_2 ≤ 1 := by omega + clear e_x12_1 e_c_2 + clear_value s_1 x12_1 c_2 + have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl + have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl + have l_x13_1 : x13_1 + 2^64 * c_3 = x13 + x17 + c_2 := by omega + have b_x13_1 : x13_1 < 2^64 := by omega + have b_c_3 : c_3 ≤ 1 := by omega + clear e_x13_1 e_c_3 + clear_value s_2 x13_1 c_3 + have e_x17_1 : x17_1 = x3 / 2^2 := rfl + have b_x17_1 : x17_1 < 2^62 := by omega + have sh_x17_1 : x17 + 2^64 * x17_1 = x3 * 2^62 := by omega + clear e_x17 e_x17_1 + clear_value x17_1 + have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl + have b_x9 : x9 < 2^64 := by omega + obtain ⟨k_x9, b_k_x9, l_x9⟩ : + ∃ k, k ≤ 1 ∧ x9 + 2^64 * k = 0 + 0 + c_3 := + ⟨(0 + 0 + c_3) / 2^64, by omega, by omega⟩ + clear e_x9 + clear_value x9 + have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl + have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl + have l_x10_1 : x10_1 + 2^64 * c_4 = x11_1 + x14 + 0 := by omega + have b_x10_1 : x10_1 < 2^64 := by omega + have b_c_4 : c_4 ≤ 1 := by omega + clear e_x10_1 e_c_4 + clear_value s_3 x10_1 c_4 + have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl + have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl + have l_x11_2 : x11_2 + 2^64 * c_5 = x12_1 + x15_1 + c_4 := by omega + have b_x11_2 : x11_2 < 2^64 := by omega + have b_c_5 : c_5 ≤ 1 := by omega + clear e_x11_2 e_c_5 + clear_value s_4 x11_2 c_5 + have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl + have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl + have l_x12_2 : x12_2 + 2^64 * c_6 = x13_1 + 0 + c_5 := by omega + have b_x12_2 : x12_2 < 2^64 := by omega + have b_c_6 : c_6 ≤ 1 := by omega + clear e_x12_2 e_c_6 + clear_value s_5 x12_2 c_6 + have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl + have b_x3_1 : x3_1 < 2^64 := by omega + clear_value x3_1 + have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl + have b_x13_2 : x13_2 < 2^64 := by omega + obtain ⟨k_x13_2, b_k_x13_2, l_x13_2⟩ : + ∃ k, k ≤ 1 ∧ x13_2 + 2^64 * k = x9 + x17_1 + c_6 := + ⟨(x9 + x17_1 + c_6) / 2^64, by omega, by omega⟩ + clear e_x13_2 + clear_value x13_2 + -- BEGIN round 0 + -- Cancellation: the low limb of `x10 + p0 * x3` is zero, so `x10 + lo_x14` is + -- `0` or `2^64`, and `subs xzr, x10, #1` set the carry exactly when it is `2^64`. + have hc_0 : x10 + lo_x14 = 2^64 * c := by + have h := cancel_low x10 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3, ← d_x14, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14] at h + clear * - h b_x10 b_lo_x14 l_c + omega + -- Neither `adc` wraps: the fifth limb is at most `1`, and the shifted quotient is below + -- `2^62`. + have hk_0 : k_x9 = 0 ∧ k_x13_2 = 0 := by + clear * - l_x9 b_c_3 l_x13_2 b_x17_1 b_c_6 + omega + -- The round invariant is a linear combination of the instruction equations. + have I_0 : 2^64 * (x10_1 + 2^64 * x11_2 + 2^128 * x12_2 + 2^192 * x13_2) + = (x10 + 2^64 * x11 + 2^128 * x12 + 2^192 * x13) + + (x5 * x3 + 2^64 * (x6 * x3) + 2^254 * x3) := by + clear * - hc_0 d_x14 d_x15_1 l_x11_1 l_x12_1 l_x13_1 l_x10_1 l_x11_2 l_x12_2 sh_x17_1 l_x9 + l_x13_2 hk_0 + omega + clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 + b_x10_1 b_x11_2 b_x12_2 b_x13_2 b_x3 b_x3_1 e_x3_1 + -- END round 0 + have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl + have b_x15_2 : x15_2 < 2^64 := by omega + clear_value x15_2 + have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl + have b_x17_2 : x17_2 < 2^64 := by omega + clear_value x17_2 + have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have l_c_7 : (c_7 = 1 ∧ 1 + 1 ≤ x10_1 + 1) ∨ (c_7 = 0 ∧ x10_1 + 1 < 1 + 1) := by + omega + clear e_c_7 + clear_value c_7 + have p_x14_1 : x5 * x3_1 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_1) (by norm_num) + have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl + have b_x14_1 : x14_1 < 2^64 := by omega + obtain ⟨lo_x14_1, b_lo_x14_1, d_x14_1⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_1 = x5 * x3_1 := + ⟨x5 * x3_1 % 2^64, by omega, by omega⟩ + clear e_x14_1 + clear_value x14_1 + have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl + have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl + have l_x11_3 : x11_3 + 2^64 * c_8 = x11_2 + x15_2 + c_7 := by omega + have b_x11_3 : x11_3 < 2^64 := by omega + have b_c_8 : c_8 ≤ 1 := by omega + clear e_x11_3 e_c_8 + clear_value s_6 x11_3 c_8 + have p_x15_3 : x6 * x3_1 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_1) (by norm_num) + have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl + have b_x15_3 : x15_3 < 2^64 := by omega + have d_x15_3 : x15_2 + 2^64 * x15_3 = x6 * x3_1 := by omega + clear e_x15_2 e_x15_3 + clear_value x15_3 + have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl + have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl + have l_x12_3 : x12_3 + 2^64 * c_9 = x12_2 + 0 + c_8 := by omega + have b_x12_3 : x12_3 < 2^64 := by omega + have b_c_9 : c_9 ≤ 1 := by omega + clear e_x12_3 e_c_9 + clear_value s_7 x12_3 c_9 + have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl + have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl + have l_x13_3 : x13_3 + 2^64 * c_10 = x13_2 + x17_2 + c_9 := by omega + have b_x13_3 : x13_3 < 2^64 := by omega + have b_c_10 : c_10 ≤ 1 := by omega + clear e_x13_3 e_c_10 + clear_value s_8 x13_3 c_10 + have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl + have b_x17_3 : x17_3 < 2^62 := by omega + have sh_x17_3 : x17_2 + 2^64 * x17_3 = x3_1 * 2^62 := by omega + clear e_x17_2 e_x17_3 + clear_value x17_3 + have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl + have b_x9_1 : x9_1 < 2^64 := by omega + obtain ⟨k_x9_1, b_k_x9_1, l_x9_1⟩ : + ∃ k, k ≤ 1 ∧ x9_1 + 2^64 * k = 0 + 0 + c_10 := + ⟨(0 + 0 + c_10) / 2^64, by omega, by omega⟩ + clear e_x9_1 + clear_value x9_1 + have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl + have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl + have l_x10_2 : x10_2 + 2^64 * c_11 = x11_3 + x14_1 + 0 := by omega + have b_x10_2 : x10_2 < 2^64 := by omega + have b_c_11 : c_11 ≤ 1 := by omega + clear e_x10_2 e_c_11 + clear_value s_9 x10_2 c_11 + have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl + have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl + have l_x11_4 : x11_4 + 2^64 * c_12 = x12_3 + x15_3 + c_11 := by omega + have b_x11_4 : x11_4 < 2^64 := by omega + have b_c_12 : c_12 ≤ 1 := by omega + clear e_x11_4 e_c_12 + clear_value s_10 x11_4 c_12 + have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl + have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl + have l_x12_4 : x12_4 + 2^64 * c_13 = x13_3 + 0 + c_12 := by omega + have b_x12_4 : x12_4 < 2^64 := by omega + have b_c_13 : c_13 ≤ 1 := by omega + clear e_x12_4 e_c_13 + clear_value s_11 x12_4 c_13 + have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl + have b_x3_2 : x3_2 < 2^64 := by omega + clear_value x3_2 + have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl + have b_x13_4 : x13_4 < 2^64 := by omega + obtain ⟨k_x13_4, b_k_x13_4, l_x13_4⟩ : + ∃ k, k ≤ 1 ∧ x13_4 + 2^64 * k = x9_1 + x17_3 + c_13 := + ⟨(x9_1 + x17_3 + c_13) / 2^64, by omega, by omega⟩ + clear e_x13_4 + clear_value x13_4 + -- BEGIN round 1 + -- Cancellation: the low limb of `x10_1 + p0 * x3_1` is zero, so `x10_1 + lo_x14_1` is + -- `0` or `2^64`, and `subs xzr, x10_1, #1` set the carry exactly when it is `2^64`. + have hc_1 : x10_1 + lo_x14_1 = 2^64 * c_7 := by + have h := cancel_low x10_1 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_1, ← d_x14_1, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_1] at h + clear * - h b_x10_1 b_lo_x14_1 l_c_7 + omega + -- Neither `adc` wraps: the fifth limb is at most `1`, and the shifted quotient is below + -- `2^62`. + have hk_1 : k_x9_1 = 0 ∧ k_x13_4 = 0 := by + clear * - l_x9_1 b_c_10 l_x13_4 b_x17_3 b_c_13 + omega + -- The round invariant is a linear combination of the instruction equations. + have I_1 : 2^64 * (x10_2 + 2^64 * x11_4 + 2^128 * x12_4 + 2^192 * x13_4) + = (x10_1 + 2^64 * x11_2 + 2^128 * x12_2 + 2^192 * x13_2) + + (x5 * x3_1 + 2^64 * (x6 * x3_1) + 2^254 * x3_1) := by + clear * - hc_1 d_x14_1 d_x15_3 l_x11_3 l_x12_3 l_x13_3 l_x10_2 l_x11_4 l_x12_4 sh_x17_3 l_x9_1 + l_x13_4 hk_1 + omega + clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 + b_x10_2 b_x11_4 b_x12_4 b_x13_4 b_x3 b_x3_1 b_x3_2 e_x3_2 + -- END round 1 + have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl + have b_x15_4 : x15_4 < 2^64 := by omega + clear_value x15_4 + have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl + have b_x17_4 : x17_4 < 2^64 := by omega + clear_value x17_4 + have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have l_c_14 : (c_14 = 1 ∧ 1 + 1 ≤ x10_2 + 1) ∨ (c_14 = 0 ∧ x10_2 + 1 < 1 + 1) := by + omega + clear e_c_14 + clear_value c_14 + have p_x14_2 : x5 * x3_2 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_2) (by norm_num) + have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl + have b_x14_2 : x14_2 < 2^64 := by omega + obtain ⟨lo_x14_2, b_lo_x14_2, d_x14_2⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_2 = x5 * x3_2 := + ⟨x5 * x3_2 % 2^64, by omega, by omega⟩ + clear e_x14_2 + clear_value x14_2 + have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl + have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl + have l_x11_5 : x11_5 + 2^64 * c_15 = x11_4 + x15_4 + c_14 := by omega + have b_x11_5 : x11_5 < 2^64 := by omega + have b_c_15 : c_15 ≤ 1 := by omega + clear e_x11_5 e_c_15 + clear_value s_12 x11_5 c_15 + have p_x15_5 : x6 * x3_2 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_2) (by norm_num) + have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl + have b_x15_5 : x15_5 < 2^64 := by omega + have d_x15_5 : x15_4 + 2^64 * x15_5 = x6 * x3_2 := by omega + clear e_x15_4 e_x15_5 + clear_value x15_5 + have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl + have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl + have l_x12_5 : x12_5 + 2^64 * c_16 = x12_4 + 0 + c_15 := by omega + have b_x12_5 : x12_5 < 2^64 := by omega + have b_c_16 : c_16 ≤ 1 := by omega + clear e_x12_5 e_c_16 + clear_value s_13 x12_5 c_16 + have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl + have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl + have l_x13_5 : x13_5 + 2^64 * c_17 = x13_4 + x17_4 + c_16 := by omega + have b_x13_5 : x13_5 < 2^64 := by omega + have b_c_17 : c_17 ≤ 1 := by omega + clear e_x13_5 e_c_17 + clear_value s_14 x13_5 c_17 + have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl + have b_x17_5 : x17_5 < 2^62 := by omega + have sh_x17_5 : x17_4 + 2^64 * x17_5 = x3_2 * 2^62 := by omega + clear e_x17_4 e_x17_5 + clear_value x17_5 + have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl + have b_x9_2 : x9_2 < 2^64 := by omega + obtain ⟨k_x9_2, b_k_x9_2, l_x9_2⟩ : + ∃ k, k ≤ 1 ∧ x9_2 + 2^64 * k = 0 + 0 + c_17 := + ⟨(0 + 0 + c_17) / 2^64, by omega, by omega⟩ + clear e_x9_2 + clear_value x9_2 + have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl + have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl + have l_x10_3 : x10_3 + 2^64 * c_18 = x11_5 + x14_2 + 0 := by omega + have b_x10_3 : x10_3 < 2^64 := by omega + have b_c_18 : c_18 ≤ 1 := by omega + clear e_x10_3 e_c_18 + clear_value s_15 x10_3 c_18 + have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl + have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl + have l_x11_6 : x11_6 + 2^64 * c_19 = x12_5 + x15_5 + c_18 := by omega + have b_x11_6 : x11_6 < 2^64 := by omega + have b_c_19 : c_19 ≤ 1 := by omega + clear e_x11_6 e_c_19 + clear_value s_16 x11_6 c_19 + have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl + have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl + have l_x12_6 : x12_6 + 2^64 * c_20 = x13_5 + 0 + c_19 := by omega + have b_x12_6 : x12_6 < 2^64 := by omega + have b_c_20 : c_20 ≤ 1 := by omega + clear e_x12_6 e_c_20 + clear_value s_17 x12_6 c_20 + have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl + have b_x3_3 : x3_3 < 2^64 := by omega + clear_value x3_3 + have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl + have b_x13_6 : x13_6 < 2^64 := by omega + obtain ⟨k_x13_6, b_k_x13_6, l_x13_6⟩ : + ∃ k, k ≤ 1 ∧ x13_6 + 2^64 * k = x9_2 + x17_5 + c_20 := + ⟨(x9_2 + x17_5 + c_20) / 2^64, by omega, by omega⟩ + clear e_x13_6 + clear_value x13_6 + -- BEGIN round 2 + -- Cancellation: the low limb of `x10_2 + p0 * x3_2` is zero, so `x10_2 + lo_x14_2` is + -- `0` or `2^64`, and `subs xzr, x10_2, #1` set the carry exactly when it is `2^64`. + have hc_2 : x10_2 + lo_x14_2 = 2^64 * c_14 := by + have h := cancel_low x10_2 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_2, ← d_x14_2, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_2] at h + clear * - h b_x10_2 b_lo_x14_2 l_c_14 + omega + -- Neither `adc` wraps: the fifth limb is at most `1`, and the shifted quotient is below + -- `2^62`. + have hk_2 : k_x9_2 = 0 ∧ k_x13_6 = 0 := by + clear * - l_x9_2 b_c_17 l_x13_6 b_x17_5 b_c_20 + omega + -- The round invariant is a linear combination of the instruction equations. + have I_2 : 2^64 * (x10_3 + 2^64 * x11_6 + 2^128 * x12_6 + 2^192 * x13_6) + = (x10_2 + 2^64 * x11_4 + 2^128 * x12_4 + 2^192 * x13_4) + + (x5 * x3_2 + 2^64 * (x6 * x3_2) + 2^254 * x3_2) := by + clear * - hc_2 d_x14_2 d_x15_5 l_x11_5 l_x12_5 l_x13_5 l_x10_3 l_x11_6 l_x12_6 sh_x17_5 l_x9_2 + l_x13_6 hk_2 + omega + clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 + I_2 b_x10_3 b_x11_6 b_x12_6 b_x13_6 b_x3 b_x3_1 b_x3_2 b_x3_3 e_x3_3 + -- END round 2 + have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl + have b_x15_6 : x15_6 < 2^64 := by omega + clear_value x15_6 + have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl + have b_x17_6 : x17_6 < 2^64 := by omega + clear_value x17_6 + have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have l_c_21 : (c_21 = 1 ∧ 1 + 1 ≤ x10_3 + 1) ∨ (c_21 = 0 ∧ x10_3 + 1 < 1 + 1) := by + omega + clear e_c_21 + clear_value c_21 + have p_x14_3 : x5 * x3_3 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_3) (by norm_num) + have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl + have b_x14_3 : x14_3 < 2^64 := by omega + obtain ⟨lo_x14_3, b_lo_x14_3, d_x14_3⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_3 = x5 * x3_3 := + ⟨x5 * x3_3 % 2^64, by omega, by omega⟩ + clear e_x14_3 + clear_value x14_3 + have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl + have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl + have l_x11_7 : x11_7 + 2^64 * c_22 = x11_6 + x15_6 + c_21 := by omega + have b_x11_7 : x11_7 < 2^64 := by omega + have b_c_22 : c_22 ≤ 1 := by omega + clear e_x11_7 e_c_22 + clear_value s_18 x11_7 c_22 + have p_x15_7 : x6 * x3_3 < 2^128 := + lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_3) (by norm_num) + have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl + have b_x15_7 : x15_7 < 2^64 := by omega + have d_x15_7 : x15_6 + 2^64 * x15_7 = x6 * x3_3 := by omega + clear e_x15_6 e_x15_7 + clear_value x15_7 + have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl + have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl + have l_x12_7 : x12_7 + 2^64 * c_23 = x12_6 + 0 + c_22 := by omega + have b_x12_7 : x12_7 < 2^64 := by omega + have b_c_23 : c_23 ≤ 1 := by omega + clear e_x12_7 e_c_23 + clear_value s_19 x12_7 c_23 + have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl + have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl + have l_x13_7 : x13_7 + 2^64 * c_24 = x13_6 + x17_6 + c_23 := by omega + have b_x13_7 : x13_7 < 2^64 := by omega + have b_c_24 : c_24 ≤ 1 := by omega + clear e_x13_7 e_c_24 + clear_value s_20 x13_7 c_24 + have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl + have b_x17_7 : x17_7 < 2^62 := by omega + have sh_x17_7 : x17_6 + 2^64 * x17_7 = x3_3 * 2^62 := by omega + clear e_x17_6 e_x17_7 + clear_value x17_7 + have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl + have b_x9_3 : x9_3 < 2^64 := by omega + obtain ⟨k_x9_3, b_k_x9_3, l_x9_3⟩ : + ∃ k, k ≤ 1 ∧ x9_3 + 2^64 * k = 0 + 0 + c_24 := + ⟨(0 + 0 + c_24) / 2^64, by omega, by omega⟩ + clear e_x9_3 + clear_value x9_3 + have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl + have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl + have l_x10_4 : x10_4 + 2^64 * c_25 = x11_7 + x14_3 + 0 := by omega + have b_x10_4 : x10_4 < 2^64 := by omega + have b_c_25 : c_25 ≤ 1 := by omega + clear e_x10_4 e_c_25 + clear_value s_21 x10_4 c_25 + have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl + have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl + have l_x11_8 : x11_8 + 2^64 * c_26 = x12_7 + x15_7 + c_25 := by omega + have b_x11_8 : x11_8 < 2^64 := by omega + have b_c_26 : c_26 ≤ 1 := by omega + clear e_x11_8 e_c_26 + clear_value s_22 x11_8 c_26 + have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl + have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl + have l_x12_8 : x12_8 + 2^64 * c_27 = x13_7 + 0 + c_26 := by omega + have b_x12_8 : x12_8 < 2^64 := by omega + have b_c_27 : c_27 ≤ 1 := by omega + clear e_x12_8 e_c_27 + clear_value s_23 x12_8 c_27 + have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl + have b_x13_8 : x13_8 < 2^64 := by omega + obtain ⟨k_x13_8, b_k_x13_8, l_x13_8⟩ : + ∃ k, k ≤ 1 ∧ x13_8 + 2^64 * k = x9_3 + x17_7 + c_27 := + ⟨(x9_3 + x17_7 + c_27) / 2^64, by omega, by omega⟩ + clear e_x13_8 + clear_value x13_8 + -- BEGIN round 3 + -- Cancellation: the low limb of `x10_3 + p0 * x3_3` is zero, so `x10_3 + lo_x14_3` is + -- `0` or `2^64`, and `subs xzr, x10_3, #1` set the carry exactly when it is `2^64`. + have hc_3 : x10_3 + lo_x14_3 = 2^64 * c_21 := by + have h := cancel_low x10_3 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_3, ← d_x14_3, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_3] at h + clear * - h b_x10_3 b_lo_x14_3 l_c_21 + omega + -- Neither `adc` wraps: the fifth limb is at most `1`, and the shifted quotient is below + -- `2^62`. + have hk_3 : k_x9_3 = 0 ∧ k_x13_8 = 0 := by + clear * - l_x9_3 b_c_24 l_x13_8 b_x17_7 b_c_27 + omega + -- The round invariant is a linear combination of the instruction equations. + have I_3 : 2^64 * (x10_4 + 2^64 * x11_8 + 2^128 * x12_8 + 2^192 * x13_8) + = (x10_3 + 2^64 * x11_6 + 2^128 * x12_6 + 2^192 * x13_6) + + (x5 * x3_3 + 2^64 * (x6 * x3_3) + 2^254 * x3_3) := by + clear * - hc_3 d_x14_3 d_x15_7 l_x11_7 l_x12_7 l_x13_7 l_x10_4 l_x11_8 l_x12_8 sh_x17_7 l_x9_3 + l_x13_8 hk_3 + omega + clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 + I_2 I_3 b_x10_4 b_x11_8 b_x12_8 b_x13_8 b_x3 b_x3_1 b_x3_2 b_x3_3 + -- END round 3 + -- BEGIN conclusion + subst e_x5 e_x6 + refine ⟨⟨b_x10_4, b_x11_8, b_x12_8, b_x13_8⟩, x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3, + by clear * - b_x3 b_x3_1 b_x3_2 b_x3_3; omega, ?_⟩ + -- `Q * p`, with the modulus in the shape the code assumes, as the sum of the four rounds' + -- contributions. + have hQp : (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) * modulus.toNat + = (modulus.l0 * x3 + 2^64 * (modulus.l1 * x3) + 2^254 * x3) + + 2^64 * (modulus.l0 * x3_1 + 2^64 * (modulus.l1 * x3_1) + 2^254 * x3_1) + + 2^128 * (modulus.l0 * x3_2 + 2^64 * (modulus.l1 * x3_2) + 2^254 * x3_2) + + 2^192 * (modulus.l0 * x3_3 + 2^64 * (modulus.l1 * x3_3) + 2^254 * x3_3) := by + simp only [Limbs.toNat, hshape.1, hshape.2]; ring + simp only [Limbs.toNat] at hQp ⊢ + clear * - I_0 I_1 I_2 I_3 hQp e_x10 e_x11 e_x12 e_x13 + omega + -- END conclusion + +end CompElliptic.Asm.AArch64 diff --git a/README.md b/README.md index eedac95..9d53dc8 100644 --- a/README.md +++ b/README.md @@ -143,8 +143,9 @@ Early work in progress. Present so far: or otherwise changed incompatibly; - a transcription of the AArch64 Pasta Montgomery routines that pasta_curves vendors from Semolina, generated from the assembly over a small instruction-semantics module, with - reference vectors from the real routines checked by the kernel (`CompElliptic/Asm/AArch64/`; - `design/aarch64-pasta-mul-verification.md` states the intended correctness theorems). + reference vectors from the real routines checked by the kernel, and an instruction-by-instruction + correctness proof of their shared reduction helper (`CompElliptic/Asm/AArch64/`; + `design/aarch64-pasta-mul-verification.md` states the remaining correctness theorems). The library's general theorems depend only on the standard `propext` / `Classical.choice` / `Quot.sound` axioms. Facts specific to concrete fields and curves additionally depend on diff --git a/design/aarch64-pasta-mul-verification.md b/design/aarch64-pasta-mul-verification.md index 49a79ab..4eb5d41 100644 --- a/design/aarch64-pasta-mul-verification.md +++ b/design/aarch64-pasta-mul-verification.md @@ -7,10 +7,10 @@ A machine-checked proof that the three routines zcash/pasta_curves#100 vendors f Semolina v0.1.4 (`mul_mont_pasta`, `sqr_mont_pasta`, `from_mont_pasta`, plus their shared `mul_by_1` helper) compute Montgomery multiplication, squaring, and conversion on the Pasta fields, under the operand contracts they actually have. The proof is -about the instruction stream of `src/asm/pasta_mul-armv8.S` (329 instructions after -comment stripping, blob `4321cf159d9814a14afbdc5cf42265384150822f`, sha256 -`0bcd5fa67d4aef5043eb536fdefd41ce16e6f7fbac3e5e6ac4f7619b35fd5e85`), not about a re-derivation -of the algorithm. +about the instruction stream of `src/asm/pasta_mul-armv8.S` (310 instructions, blob +`4321cf159d9814a14afbdc5cf42265384150822f`, sha256 +`0bcd5fa67d4aef5043eb536fdefd41ce16e6f7fbac3e5e6ac4f7619b35fd5e85`), not about a +re-derivation of the algorithm. ## Trust story @@ -23,27 +23,27 @@ What is trusted, beyond Lean's kernel and standard axioms: file, never hand-typed; CI regenerates and diffs (same pattern as the field-file generators). The generator is the same parser as the Python simulator that found the accumulator wrap, so it has already been exercised against the hardware. -3. The reference vectors: outputs of the real assembly on an Apple M-series machine at - pasta_curves commit `8ad85e9fab7929f6236960e472f432a4bd9ccd74`, embedded as - kernel-checked examples (`decide +kernel`). These are - concrete closed facts in the sense of the README's trust discipline, and any - independent run of the binary reproduces them. +3. The reference vectors: outputs of the real assembly on an Apple M-series machine + at pasta_curves commit `8ad85e9fab7929f6236960e472f432a4bd9ccd74`, embedded as + kernel-checked examples (`decide +kernel`). These are concrete closed facts in + the sense of the README's trust discipline, and any independent run of the binary + reproduces them. -Not in the trusted base: the calling convention, stack frame, and memory-safety of -the FFI boundary. The model treats loads and stores as limb inputs and outputs. Those -aspects were reviewed by hand and are recorded as such in the module doc. +Not modelled formally: the calling convention, stack frame, and memory-safety of +the FFI boundary. The model treats loads and stores as limb inputs and outputs. +Those aspects were reviewed by hand and are recorded as such in the module doc. ## Layout ``` -CompElliptic/Asm/AArch64/Semantics.lean registers, carry, instruction functions -CompElliptic/Asm/AArch64/PastaMul.lean GENERATED: the four routines as Lean defs -CompElliptic/Asm/AArch64/PastaMulVectors.lean GENERATED: reference vectors, kernel-checked -CompElliptic/Asm/AArch64/PastaMulSpec.lean the theorems -CompElliptic/Asm/AArch64/Pasta.lean instantiation at the two Pasta primes +CompElliptic/Asm/AArch64/Semantics.lean registers, carry, instruction functions +CompElliptic/Asm/AArch64/PastaMul.lean GENERATED: the four routines as Lean defs +CompElliptic/Asm/AArch64/PastaMulVectors.lean GENERATED: reference vectors, kernel-checked +CompElliptic/Asm/AArch64/PastaMulSpec.lean the theorems +CompElliptic/Asm/AArch64/Pasta.lean instantiation at the two Pasta primes CompElliptic/Asm/AArch64/vendor/pasta_mul-armv8.S vendored, Apache-2.0, hash pinned -scripts/gen_aarch64_pasta_mul.py parser + Lean emitter (+ simulator) -scripts/check_aarch64_pasta_mul.sh regenerate and diff, hash check (CI) +scripts/gen_aarch64_pasta_mul.py parser + Lean emitter (+ simulator) +scripts/check_aarch64_pasta_mul.sh regenerate and diff, hash check (CI) ``` Namespace `CompElliptic.Asm.AArch64`, mirroring the path. @@ -62,26 +62,46 @@ plumbing, the products `a * b` being the only atoms it does not see through; the recompositions that relate those atoms are `ring` facts. No native execution speed is needed, and the modules stay outside the precompiled lane. -## Program shape +## Program shape and proof method The generator emits each routine as a chain of `let`s in a single function from the -input limbs (and modulus limbs and `inv`) to the output limbs. The proofs are to be -stated about round functions cut from the same instruction stream at indices given in -the generator's configuration, each cut checked against the instruction text at its -boundary so that an edit to the `.S` that moves a boundary fails loudly rather than -silently shifting a round; the whole-routine definitions are then their composition by -`rfl`. That cut belongs to the proof units and is not emitted yet. - -## Theorems (statements the first proof unit targets) +input limbs (and modulus limbs and `inv`) to the output limbs. The proofs in +`PastaMulSpec.lean` follow that chain instruction by instruction, and their mechanical +part is generated too (`gen_aarch64_pasta_mul.py --skeleton `). The skeleton +unfolds the routine and extracts its `let`s under unique names. Then, for every +instruction, it records the defining equation of the result (by `rfl`, in `%`/`/` form), +derives from it the facts that later steps need (the carry-chain equation +`x + 2^64 * c = a + b + cin`, the range facts, the product decomposition +`lo + 2^64 * hi = a * b`), clears the `%`/`/` equation, and makes the local opaque with +`clear_value`. The hand-written parts are the theorem statements and the +`-- BEGIN ... -- END` annotation blocks between instructions. A block states the +Montgomery round invariant that holds at that point and derives it from the facts it +names. `gen_aarch64_pasta_mul.py --check-spec` strips the blocks and requires the rest +of the proof to be the current skeleton, so an edit to the `.S` regenerates the skeleton +and the check fails loudly until the annotations are moved. + +Two measurements fixed this shape. `omega` given a whole reduction round at once, or +given the cancellation fact with its `%` terms still in it, runs for minutes without +finishing; given one carry step at a time, or linear equations only, it answers in +milliseconds. So each round block first rewrites the cancellation fact +`(t0 + p0 * q % 2^64) % 2^64 = 0` to the linear `t0 + lo = 2^64 * c`, using the ghost +low limb and the carry of `subs xzr, t0, #1`; it then shows that neither `adc` wraps; +and the invariant is a linear combination of the instruction equations, proved by +`omega` in a context cleared down to exactly those equations. + +## Theorems With `p = p0 + 2^64 p1 + 2^192 · 2^62` (the modulus limbs are `[p0, p1, 0, 2^62]`, as the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: +* `mulBy1_spec` (proved): for every four-limb `t`, the shared reduction helper returns + limbs `r` below `2^64` with `2^256 · r = t + Q · p` for some `Q < 2^256`. So `r` is + congruent to `t · 2^−256` modulo `p`, and `r ≤ p`. * `mul_spec`: if `lhs < p` and `rhs < 2^256`, or `lhs < 2^256`, `rhs < p`, and every `rhs` limb in positions 1 to 3 is at most `2^64 − 4`, then the output is below `p` - and `output · 2^256 ≡ lhs · rhs (mod p)`. The exact wrap boundary (whether - `2^64 − 2` and `2^64 − 3` can wrap) is settled as a by-product of the round lemma - and stated as its own lemma. + and `output · 2^256 ≡ lhs · rhs (mod p)`. The exact wrap boundary (whether `2^64 − 2` + and `2^64 − 3` can wrap) is settled as a by-product of the round lemma and stated as + its own lemma. * `sqr_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. * `from_mont_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a (mod p)`. @@ -89,20 +109,21 @@ the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: the crate's `MODULUS`, `INV`, `R2`, `R3` limbs pinned by `decide`, and states the corollary the crate relies on: `mul lhs R2` and `mul lhs R3` are correct for every 256-bit `lhs`, because no limb 1 to 3 of `R2`/`R3` is above `2^64 − 4`. It also states -the negative: the witness pair is inside `lhs · rhs < 2^256 · p` and the model's -output is not the Montgomery product (by evaluation), documenting why #108's contract -is wrong. +the negative: the witness pair is inside `lhs · rhs < 2^256 · p` and the model's output +is not the Montgomery product (by evaluation), documenting why #108's contract is +wrong. ## Status 1. Semantics, generator, generated program, vendored `.S` with hash, vectors, CI check: present. -2. `from_mont` and the helper (four reduction rounds): the smallest proof. +2. The helper (four reduction rounds): proved. `from_mont` (the helper and a + conditional subtraction): the smallest remaining proof. 3. `mul`: round invariant, the accumulator no-wrap lemma under each contract, the final comparison. 4. `sqr`: the cross-term schoolbook, doubling, and the "can't overflow" claims. 5. Pasta instantiation and census entries in `TrustBoundary.lean`. Out of scope for now: Zakura's inline-`asm!` transcription (provable later by -instruction-by-instruction correspondence), `sqr_n_mul` (zakura-core/common#65), and the carry-limb -drop (zakura-core/common#132). +instruction-by-instruction correspondence), `sqr_n_mul` (zakura-core/common#65), and +the carry-limb drop (zakura-core/common#132). diff --git a/scripts/check_aarch64_pasta_mul.sh b/scripts/check_aarch64_pasta_mul.sh index eb2a331..6e0902d 100755 --- a/scripts/check_aarch64_pasta_mul.sh +++ b/scripts/check_aarch64_pasta_mul.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # Check that the transcription of pasta_curves' AArch64 Pasta Montgomery routines is -# current: the vendored assembly and reference vectors match their recorded hashes, and -# regenerating the Lean files from them reproduces the committed files exactly. +# current: the vendored assembly and reference vectors match their recorded hashes, +# regenerating the Lean files from them reproduces the committed files exactly, and the +# generated parts of the proofs in PastaMulSpec.lean are the ones the generator produces. # # Run from the repository root; exits non-zero on violation. set -euo pipefail @@ -12,4 +13,5 @@ cd "$(dirname "$0")/.." python3 scripts/gen_aarch64_pasta_mul.py git diff --exit-code -- \ CompElliptic/Asm/AArch64/PastaMul.lean CompElliptic/Asm/AArch64/PastaMulVectors.lean +python3 scripts/gen_aarch64_pasta_mul.py --check-spec CompElliptic/Asm/AArch64/PastaMulSpec.lean echo "AArch64 Pasta transcription: current." From 3b3e39c67970a2c4f886a4f30a510b2d8e1e9ee0 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 03:40:11 +0100 Subject: [PATCH 4/9] asm: prove the conversion out of Montgomery form correct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `fromMont_spec`: for every four-limb `value`, the routine returns limbs below `2^64` whose value `r` is below `p` and satisfies `2^256 * r ≡ value (mod p)`. No bound on `value` below `p` is needed: by `mulBy1_spec` the helper's result is at most `p`, and the conditional subtraction removes the one excess case. The proof is the generated skeleton for `fromMont` with two blocks. The first applies the helper's theorem, which yields the bounds on the helper's output limbs and the equation `2^256 * r = value + Q * p`. The conclusion splits on the final carry, which is clear exactly when `r < p`, and reads the congruence off an equation `a + k * p = b + l * p` with `modEq_of_add_mul`. The spec module's doc says what the annotation blocks supply beyond the round invariants; the design document records the theorem as proved, and the README's list of what is present mentions it. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 155 ++++++++++++++++++++- README.md | 7 +- design/aarch64-pasta-mul-verification.md | 8 +- 3 files changed, 162 insertions(+), 8 deletions(-) diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean index 5633108..0ab971e 100644 --- a/CompElliptic/Asm/AArch64/PastaMulSpec.lean +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -20,8 +20,10 @@ unique names; then, for every instruction, the defining equation of its result ( `omega` call sees one carry step. Those lines are generated by `scripts/gen_aarch64_pasta_mul.py --skeleton ` and must not be edited; the hand-written parts are the theorem statements and the `-- BEGIN ... -- END` blocks, which -state the Montgomery round invariants where they hold. `scripts/check_aarch64_pasta_mul.sh` -strips the blocks and checks that what remains is the current skeleton. +supply what the instruction stream alone does not: the Montgomery round invariants where they +hold, the contract of a called routine, and the final case analysis. +`scripts/check_aarch64_pasta_mul.sh` strips the blocks and checks that what remains is the +current skeleton. The moduli are assumed in the shape the code hard-codes: limbs `[p0, p1, 0, 2^62]`, with `inv * p0 ≡ -1 (mod 2^64)`. @@ -565,4 +567,153 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul omega -- END conclusion +-- BEGIN modEq_of_add_mul +/-- `a ≡ b (mod n)` from `a + k * n = b + l * n`, the form in which a final conditional +subtraction leaves a result. -/ +theorem modEq_of_add_mul (a b k l n : Nat) (h : a + k * n = b + l * n) : a ≡ b [MOD n] := by + unfold Nat.ModEq + rw [← Nat.add_mul_mod_self_right a k n, h, Nat.add_mul_mod_self_right] +-- END modEq_of_add_mul + +-- BEGIN fromMont_spec statement +/-- Conversion out of Montgomery form: for any four-limb `value`, the result is below `p` and +`2^256 * result ≡ value (mod p)`. The helper returns at most `p` for any four-limb input and the +conditional subtraction removes the one excess case, so `value` need not be below `p`. -/ +theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) + (hm : modulus.Bounded) (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) + (hinv_lt : inv < 2^64) (hinv : (inv * modulus.l0 + 1) % 2^64 = 0) : + ∀ r, r = fromMont value modulus inv → + r.Bounded ∧ r.toNat < modulus.toNat ∧ 2^256 * r.toNat ≡ value.toNat [MOD modulus.toNat] := by + intro r hr +-- END fromMont_spec statement + -- generated skeleton for `fromMont`: do not edit between the annotations + unfold fromMont at hr + lift_lets at hr + extract_lets x3 x4 x10 x11 x12 x13 r x10_1 x11_1 x12_1 x13_1 x5 x6 x7 x8 s x14 c s_1 x15 c_1 s_2 + x16 c_2 s_3 x17 c_3 x10_2 x11_2 x12_2 x13_2 out0 out1 out2 out3 at hr + subst hr + have e_x3 : x3 = inv := rfl + have b_x3 : x3 < 2^64 := by rw [e_x3]; exact hinv_lt + clear_value x3 + have e_x4 : x4 = x3 := rfl + have b_x4 : x4 < 2^64 := by omega + clear_value x4 + have e_x10 : x10 = value.l0 := rfl + have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hv.1 + clear_value x10 + have e_x11 : x11 = value.l1 := rfl + have b_x11 : x11 < 2^64 := by rw [e_x11]; exact hv.2.1 + clear_value x11 + have e_x12 : x12 = value.l2 := rfl + have b_x12 : x12 < 2^64 := by rw [e_x12]; exact hv.2.2.1 + clear_value x12 + have e_x13 : x13 = value.l3 := rfl + have b_x13 : x13 < 2^64 := by rw [e_x13]; exact hv.2.2.2 + clear_value x13 + have e_r : r = mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 := rfl + clear_value r + have e_x10_1 : x10_1 = r.l0 := rfl + clear_value x10_1 + have e_x11_1 : x11_1 = r.l1 := rfl + clear_value x11_1 + have e_x12_1 : x12_1 = r.l2 := rfl + clear_value x12_1 + have e_x13_1 : x13_1 = r.l3 := rfl + clear_value x13_1 + have e_x5 : x5 = modulus.l0 := rfl + have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 + clear_value x5 + have e_x6 : x6 = modulus.l1 := rfl + have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 + clear_value x6 + have e_x7 : x7 = modulus.l2 := rfl + have b_x7 : x7 < 2^64 := by rw [e_x7]; exact hm.2.2.1 + clear_value x7 + have e_x8 : x8 = modulus.l3 := rfl + have b_x8 : x8 < 2^64 := by rw [e_x8]; exact hm.2.2.2 + clear_value x8 + -- BEGIN helper + -- The helper's contract on `t = value`: its result limbs are bounded, and `2^256 * r = t + Q * p` + -- for some `Q < 2^256`. + obtain ⟨⟨b_x10_1, b_x11_1, b_x12_1, b_x13_1⟩, Q, hQ, hmain⟩ : + (x10_1 < 2^64 ∧ x11_1 < 2^64 ∧ x12_1 < 2^64 ∧ x13_1 < 2^64) ∧ ∃ Q, Q < 2^256 ∧ + 2^256 * (x10_1 + 2^64 * x11_1 + 2^128 * x12_1 + 2^192 * x13_1) + = (x10 + 2^64 * x11 + 2^128 * x12 + 2^192 * x13) + Q * modulus.toNat := by + have hr : r = ⟨x10_1, x11_1, x12_1, x13_1⟩ := by rw [e_x10_1, e_x11_1, e_x12_1, e_x13_1] + subst hr + exact mulBy1_spec ⟨x10, x11, x12, x13⟩ modulus x4 ⟨b_x10, b_x11, b_x12, b_x13⟩ hm hshape b_x4 + (by rw [e_x4, e_x3]; exact hinv) _ e_r + clear e_r e_x10_1 e_x11_1 e_x12_1 e_x13_1 + -- END helper + have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl + have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl + have l_x14 : x14 + 2^64 * c + x5 + 1 = x10_1 + 2^64 + 1 := by omega + have b_x14 : x14 < 2^64 := by omega + have b_c : c ≤ 1 := by omega + clear e_x14 e_c + clear_value s x14 c + have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl + have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl + have l_x15 : x15 + 2^64 * c_1 + x6 + 1 = x11_1 + 2^64 + c := by omega + have b_x15 : x15 < 2^64 := by omega + have b_c_1 : c_1 ≤ 1 := by omega + clear e_x15 e_c_1 + clear_value s_1 x15 c_1 + have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl + have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl + have l_x16 : x16 + 2^64 * c_2 + x7 + 1 = x12_1 + 2^64 + c_1 := by omega + have b_x16 : x16 < 2^64 := by omega + have b_c_2 : c_2 ≤ 1 := by omega + clear e_x16 e_c_2 + clear_value s_2 x16 c_2 + have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl + have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl + have l_x17 : x17 + 2^64 * c_3 + x8 + 1 = x13_1 + 2^64 + c_2 := by omega + have b_x17 : x17 < 2^64 := by omega + have b_c_3 : c_3 ≤ 1 := by omega + clear e_x17 e_c_3 + clear_value s_3 x17 c_3 + have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl + have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; split <;> omega + clear_value x10_2 + have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl + have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; split <;> omega + clear_value x11_2 + have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl + have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; split <;> omega + clear_value x12_2 + have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl + have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; split <;> omega + clear_value x13_2 + have e_out0 : out0 = x10_2 := rfl + clear_value out0 + have e_out1 : out1 = x11_2 := rfl + clear_value out1 + have e_out2 : out2 = x12_2 := rfl + clear_value out2 + have e_out3 : out3 = x13_2 := rfl + clear_value out3 + -- BEGIN conclusion + subst out0 out1 out2 out3 + have hV : value.toNat = x10 + 2^64 * x11 + 2^128 * x12 + 2^192 * x13 := by + simp only [Limbs.toNat, e_x10, e_x11, e_x12, e_x13] + have hP : modulus.toNat = x5 + 2^64 * x6 + 2^128 * x7 + 2^192 * x8 := by + simp only [Limbs.toNat, e_x5, e_x6, e_x7, e_x8] + have hP_pos : 0 < modulus.toNat := by simp only [Limbs.toNat, hshape.2]; omega + -- `Q < 2^256` bounds `Q * p` linearly; with `t < 2^256` it puts the helper's result at + -- most `p`. + have hQP : Q * modulus.toNat + modulus.toNat ≤ 2^256 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ hQ + refine ⟨⟨b_x10_2, b_x11_2, b_x12_2, b_x13_2⟩, ?_⟩ + show x10_2 + 2^64 * x11_2 + 2^128 * x12_2 + 2^192 * x13_2 < modulus.toNat ∧ + 2^256 * (x10_2 + 2^64 * x11_2 + 2^128 * x12_2 + 2^192 * x13_2) ≡ value.toNat [MOD modulus.toNat] + -- The subtraction chain computes `r - p`, and its final borrow is set (`c_3 = 0`) exactly when + -- `r < p`. Then the result is `r`; otherwise it is `r - p`, which is `0` because `r ≤ p`. + obtain hc | hc : c_3 = 0 ∨ c_3 = 1 := by omega + · rw [if_pos hc] at e_x10_2 e_x11_2 e_x12_2 e_x13_2 + exact ⟨by omega, modEq_of_add_mul _ _ 0 Q _ (by omega)⟩ + · rw [if_neg (by omega)] at e_x10_2 e_x11_2 e_x12_2 e_x13_2 + exact ⟨by omega, modEq_of_add_mul _ _ (2^256) Q _ (by omega)⟩ + -- END conclusion + end CompElliptic.Asm.AArch64 diff --git a/README.md b/README.md index 9d53dc8..c281a69 100644 --- a/README.md +++ b/README.md @@ -143,9 +143,10 @@ Early work in progress. Present so far: or otherwise changed incompatibly; - a transcription of the AArch64 Pasta Montgomery routines that pasta_curves vendors from Semolina, generated from the assembly over a small instruction-semantics module, with - reference vectors from the real routines checked by the kernel, and an instruction-by-instruction - correctness proof of their shared reduction helper (`CompElliptic/Asm/AArch64/`; - `design/aarch64-pasta-mul-verification.md` states the remaining correctness theorems). + reference vectors from the real routines checked by the kernel, and instruction-by-instruction + correctness proofs of their shared reduction helper and of the conversion out of Montgomery + form (`CompElliptic/Asm/AArch64/`; `design/aarch64-pasta-mul-verification.md` states the + remaining correctness theorems). The library's general theorems depend only on the standard `propext` / `Classical.choice` / `Quot.sound` axioms. Facts specific to concrete fields and curves additionally depend on diff --git a/design/aarch64-pasta-mul-verification.md b/design/aarch64-pasta-mul-verification.md index 4eb5d41..b98abae 100644 --- a/design/aarch64-pasta-mul-verification.md +++ b/design/aarch64-pasta-mul-verification.md @@ -103,7 +103,9 @@ the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: and `2^64 − 3` can wrap) is settled as a by-product of the round lemma and stated as its own lemma. * `sqr_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. -* `from_mont_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a (mod p)`. +* `fromMont_spec` (proved): for every four-limb `a`, the output is below `p` and + `output · 2^256 ≡ a (mod p)`. No bound on `a` below `p` is needed: the helper's result is + at most `p`, and the conditional subtraction removes the one excess case. `Pasta.lean` instantiates these at `PALLAS_BASE_CARD` and `PALLAS_SCALAR_CARD` with the crate's `MODULUS`, `INV`, `R2`, `R3` limbs pinned by `decide`, and states the @@ -117,8 +119,8 @@ wrong. 1. Semantics, generator, generated program, vendored `.S` with hash, vectors, CI check: present. -2. The helper (four reduction rounds): proved. `from_mont` (the helper and a - conditional subtraction): the smallest remaining proof. +2. The helper (four reduction rounds) and `from_mont` (the helper and a conditional + subtraction): proved. 3. `mul`: round invariant, the accumulator no-wrap lemma under each contract, the final comparison. 4. `sqr`: the cross-term schoolbook, doubling, and the "can't overflow" claims. From 96f83c6df14301c07b7f6a03a55c7d4395923efd Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 05:07:57 +0100 Subject: [PATCH 5/9] asm: derive the skeleton's per-instruction facts from lemmas, not omega Each generated step now proves its range fact, carry-chain equation, product or shift decomposition, and ghost witness by instantiating one lemma (`Nat.mod_add_div`, `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, `Nat.mul_lt_mul''`, or one of five small lemmas in the spec file's preamble) instead of calling `omega`. Every `omega` sees the whole local context, so in a long proof the per-step calls slowed as facts accumulated, and the multiplication routine's proof exhausted the per-declaration heartbeat budget. The skeleton's cost is now independent of its position in the proof, `omega` is left to the annotation blocks, and the spec module compiles in 7 s instead of 20. `lsr` results, bounded by `2^62`, are weakened where a `2^64` bound is needed, and the `csel` bounds name their hypotheses instead of searching the context. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 442 +++++++++++++-------- scripts/gen_aarch64_pasta_mul.py | 85 ++-- 2 files changed, 336 insertions(+), 191 deletions(-) diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean index 0ab971e..3b9a26e 100644 --- a/CompElliptic/Asm/AArch64/PastaMulSpec.lean +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -16,8 +16,8 @@ import Mathlib.Tactic.ClearExcept Each theorem here is proved over the transcription in `PastaMul.lean`, instruction by instruction. The proof of a routine begins by unfolding it and extracting its `let`s under unique names; then, for every instruction, the defining equation of its result (by `rfl`, in -`%`/`/` form) and its range are recorded and the local's value is cleared, so that each -`omega` call sees one carry step. Those lines are generated by +`%`/`/` form) and the linear facts that follow from it (each an instance of one lemma) are +recorded and the local's value is cleared. Those lines are generated by `scripts/gen_aarch64_pasta_mul.py --skeleton ` and must not be edited; the hand-written parts are the theorem statements and the `-- BEGIN ... -- END` blocks, which supply what the instruction stream alone does not: the Montgomery round invariants where they @@ -47,6 +47,34 @@ theorem cancel_low (t0 inv p0 : Nat) (h : (inv * p0 + 1) % 2^64 = 0) : exact Eq.trans h3 key -- END cancel_low +-- BEGIN skeleton lemmas +/-! The generated skeleton derives its per-instruction facts from these lemmas and from +`Nat.mod_add_div`, `Nat.mod_lt`, and `Nat.div_lt_of_lt_mul`. -/ + +/-- The carry out of an addition of two limbs and a carry is at most `1`. -/ +theorem addc_carry_le_one (a b cin : Nat) (ha : a < 2^64) (hb : b < 2^64) (hc : cin ≤ 1) : + (a + b + cin) / 2^64 ≤ 1 := by omega + +/-- A subtraction with borrow, as the assembly's `subs`/`sbcs` form it: its result and carry +satisfy `result + 2^64 * carry + b + 1 = a + 2^64 + cin`, since `b + (1 - cin) ≤ a + 2^64` keeps +the difference from truncating. -/ +theorem subc_lin (a b cin : Nat) (hb : b < 2^64) (hc : cin ≤ 1) : + (a + 2^64 - b - (1 - cin)) % 2^64 + 2^64 * ((a + 2^64 - b - (1 - cin)) / 2^64) + b + 1 + = a + 2^64 + cin := by omega + +/-- The carry (no-borrow flag) of a subtraction is at most `1`. -/ +theorem subc_carry_le_one (a b cin : Nat) (ha : a < 2^64) : + (a + 2^64 - b - (1 - cin)) / 2^64 ≤ 1 := by omega + +/-- The carry of a subtraction is set exactly when no borrow occurs. -/ +theorem subc_carry_cases (a b cin c : Nat) (hc : c = (a + 2^64 - b - (1 - cin)) / 2^64) + (ha : a < 2^64) (hb : b < 2^64) (hcin : cin ≤ 1) : + (c = 1 ∧ b + 1 ≤ a + cin) ∨ (c = 0 ∧ a + cin < b + 1) := by omega + +/-- `lsl #62` and `lsr #2` split a limb at its second bit. -/ +theorem lsl62_lsr2_split (a : Nat) : a * 2^62 % 2^64 + 2^64 * (a / 2^2) = a * 2^62 := by omega +-- END skeleton lemmas + -- BEGIN mulBy1_spec statement /-- The shared reduction helper computes `(t + Q * p) / 2^256` for some `Q < 2^256`, with the result in range, for any four-limb `t`. Since `Q < 2^256`, the result is congruent to @@ -85,7 +113,7 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt clear_value x4 have e_x3 : x3 = x4 * x10 % 2^64 := rfl - have b_x3 : x3 < 2^64 := by omega + have b_x3 : x3 < 2^64 := by rw [e_x3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x3 have e_x5 : x5 = modulus.l0 := rfl have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 @@ -94,94 +122,111 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 clear_value x6 have e_x15 : x15 = x6 * x3 % 2^64 := rfl - have b_x15 : x15 < 2^64 := by omega + have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x15 have e_x17 : x17 = x3 * 2^62 % 2^64 := rfl - have b_x17 : x17 < 2^64 := by omega + have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x17 have e_c : c = (x10 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have l_c : (c = 1 ∧ 1 + 1 ≤ x10 + 1) ∨ (c = 0 ∧ x10 + 1 < 1 + 1) := by - omega + have b_c : c ≤ 1 := by rw [e_c]; exact subc_carry_le_one _ _ _ b_x10 + have l_c : (c = 1 ∧ 1 + 1 ≤ x10 + 1) ∨ (c = 0 ∧ x10 + 1 < 1 + 1) := + subc_carry_cases _ _ _ _ e_c b_x10 (by decide) (by decide) clear e_c clear_value c - have p_x14 : x5 * x3 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3) (by norm_num) + have p_x14 : x5 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3 have e_x14 : x14 = x5 * x3 / 2^64 := rfl - have b_x14 : x14 < 2^64 := by omega + have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.div_lt_of_lt_mul p_x14 obtain ⟨lo_x14, b_lo_x14, d_x14⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14 = x5 * x3 := - ⟨x5 * x3 % 2^64, by omega, by omega⟩ + ⟨x5 * x3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14]; exact Nat.mod_add_div _ _⟩ clear e_x14 clear_value x14 have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl - have l_x11_1 : x11_1 + 2^64 * c_1 = x11 + x15 + c := by omega - have b_x11_1 : x11_1 < 2^64 := by omega - have b_c_1 : c_1 ≤ 1 := by omega + have l_x11_1 : x11_1 + 2^64 * c_1 = x11 + x15 + c := by + rw [e_x11_1, e_c_1]; exact Nat.mod_add_div _ _ + have b_x11_1 : x11_1 < 2^64 := by rw [e_x11_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_1 : c_1 ≤ 1 := by + rw [e_c_1]; exact addc_carry_le_one _ _ _ b_x11 b_x15 b_c clear e_x11_1 e_c_1 clear_value s x11_1 c_1 - have p_x15_1 : x6 * x3 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3) (by norm_num) + have p_x15_1 : x6 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3 have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl - have b_x15_1 : x15_1 < 2^64 := by omega - have d_x15_1 : x15 + 2^64 * x15_1 = x6 * x3 := by omega + have b_x15_1 : x15_1 < 2^64 := by rw [e_x15_1]; exact Nat.div_lt_of_lt_mul p_x15_1 + have d_x15_1 : x15 + 2^64 * x15_1 = x6 * x3 := by + rw [e_x15, e_x15_1]; exact Nat.mod_add_div _ _ clear e_x15 e_x15_1 clear_value x15_1 have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl - have l_x12_1 : x12_1 + 2^64 * c_2 = x12 + 0 + c_1 := by omega - have b_x12_1 : x12_1 < 2^64 := by omega - have b_c_2 : c_2 ≤ 1 := by omega + have l_x12_1 : x12_1 + 2^64 * c_2 = x12 + 0 + c_1 := by + rw [e_x12_1, e_c_2]; exact Nat.mod_add_div _ _ + have b_x12_1 : x12_1 < 2^64 := by rw [e_x12_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_2 : c_2 ≤ 1 := by + rw [e_c_2]; exact addc_carry_le_one _ _ _ b_x12 (by decide) b_c_1 clear e_x12_1 e_c_2 clear_value s_1 x12_1 c_2 have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl - have l_x13_1 : x13_1 + 2^64 * c_3 = x13 + x17 + c_2 := by omega - have b_x13_1 : x13_1 < 2^64 := by omega - have b_c_3 : c_3 ≤ 1 := by omega + have l_x13_1 : x13_1 + 2^64 * c_3 = x13 + x17 + c_2 := by + rw [e_x13_1, e_c_3]; exact Nat.mod_add_div _ _ + have b_x13_1 : x13_1 < 2^64 := by rw [e_x13_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_3 : c_3 ≤ 1 := by + rw [e_c_3]; exact addc_carry_le_one _ _ _ b_x13 b_x17 b_c_2 clear e_x13_1 e_c_3 clear_value s_2 x13_1 c_3 have e_x17_1 : x17_1 = x3 / 2^2 := rfl - have b_x17_1 : x17_1 < 2^62 := by omega - have sh_x17_1 : x17 + 2^64 * x17_1 = x3 * 2^62 := by omega + have b_x17_1 : x17_1 < 2^62 := by + rw [e_x17_1]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3 (by norm_num)) + have sh_x17_1 : x17 + 2^64 * x17_1 = x3 * 2^62 := by + rw [e_x17, e_x17_1]; exact lsl62_lsr2_split _ clear e_x17 e_x17_1 clear_value x17_1 have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl - have b_x9 : x9 < 2^64 := by omega + have b_x9 : x9 < 2^64 := by rw [e_x9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9, b_k_x9, l_x9⟩ : ∃ k, k ≤ 1 ∧ x9 + 2^64 * k = 0 + 0 + c_3 := - ⟨(0 + 0 + c_3) / 2^64, by omega, by omega⟩ + ⟨(0 + 0 + c_3) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_3, + by rw [e_x9]; exact Nat.mod_add_div _ _⟩ clear e_x9 clear_value x9 have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl - have l_x10_1 : x10_1 + 2^64 * c_4 = x11_1 + x14 + 0 := by omega - have b_x10_1 : x10_1 < 2^64 := by omega - have b_c_4 : c_4 ≤ 1 := by omega + have l_x10_1 : x10_1 + 2^64 * c_4 = x11_1 + x14 + 0 := by + rw [e_x10_1, e_c_4]; exact Nat.mod_add_div _ _ + have b_x10_1 : x10_1 < 2^64 := by rw [e_x10_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_4 : c_4 ≤ 1 := by + rw [e_c_4]; exact addc_carry_le_one _ _ _ b_x11_1 b_x14 (by decide) clear e_x10_1 e_c_4 clear_value s_3 x10_1 c_4 have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl - have l_x11_2 : x11_2 + 2^64 * c_5 = x12_1 + x15_1 + c_4 := by omega - have b_x11_2 : x11_2 < 2^64 := by omega - have b_c_5 : c_5 ≤ 1 := by omega + have l_x11_2 : x11_2 + 2^64 * c_5 = x12_1 + x15_1 + c_4 := by + rw [e_x11_2, e_c_5]; exact Nat.mod_add_div _ _ + have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_5 : c_5 ≤ 1 := by + rw [e_c_5]; exact addc_carry_le_one _ _ _ b_x12_1 b_x15_1 b_c_4 clear e_x11_2 e_c_5 clear_value s_4 x11_2 c_5 have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl - have l_x12_2 : x12_2 + 2^64 * c_6 = x13_1 + 0 + c_5 := by omega - have b_x12_2 : x12_2 < 2^64 := by omega - have b_c_6 : c_6 ≤ 1 := by omega + have l_x12_2 : x12_2 + 2^64 * c_6 = x13_1 + 0 + c_5 := by + rw [e_x12_2, e_c_6]; exact Nat.mod_add_div _ _ + have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_6 : c_6 ≤ 1 := by + rw [e_c_6]; exact addc_carry_le_one _ _ _ b_x13_1 (by decide) b_c_5 clear e_x12_2 e_c_6 clear_value s_5 x12_2 c_6 have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl - have b_x3_1 : x3_1 < 2^64 := by omega + have b_x3_1 : x3_1 < 2^64 := by rw [e_x3_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x3_1 have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl - have b_x13_2 : x13_2 < 2^64 := by omega + have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_2, b_k_x13_2, l_x13_2⟩ : ∃ k, k ≤ 1 ∧ x13_2 + 2^64 * k = x9 + x17_1 + c_6 := - ⟨(x9 + x17_1 + c_6) / 2^64, by omega, by omega⟩ + ⟨(x9 + x17_1 + c_6) / 2^64, addc_carry_le_one _ _ _ b_x9 (lt_of_lt_of_le b_x17_1 (by norm_num)) b_c_6, + by rw [e_x13_2]; exact Nat.mod_add_div _ _⟩ clear e_x13_2 clear_value x13_2 -- BEGIN round 0 @@ -209,94 +254,111 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul b_x10_1 b_x11_2 b_x12_2 b_x13_2 b_x3 b_x3_1 e_x3_1 -- END round 0 have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl - have b_x15_2 : x15_2 < 2^64 := by omega + have b_x15_2 : x15_2 < 2^64 := by rw [e_x15_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x15_2 have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl - have b_x17_2 : x17_2 < 2^64 := by omega + have b_x17_2 : x17_2 < 2^64 := by rw [e_x17_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x17_2 have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have l_c_7 : (c_7 = 1 ∧ 1 + 1 ≤ x10_1 + 1) ∨ (c_7 = 0 ∧ x10_1 + 1 < 1 + 1) := by - omega + have b_c_7 : c_7 ≤ 1 := by rw [e_c_7]; exact subc_carry_le_one _ _ _ b_x10_1 + have l_c_7 : (c_7 = 1 ∧ 1 + 1 ≤ x10_1 + 1) ∨ (c_7 = 0 ∧ x10_1 + 1 < 1 + 1) := + subc_carry_cases _ _ _ _ e_c_7 b_x10_1 (by decide) (by decide) clear e_c_7 clear_value c_7 - have p_x14_1 : x5 * x3_1 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_1) (by norm_num) + have p_x14_1 : x5 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_1 have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl - have b_x14_1 : x14_1 < 2^64 := by omega + have b_x14_1 : x14_1 < 2^64 := by rw [e_x14_1]; exact Nat.div_lt_of_lt_mul p_x14_1 obtain ⟨lo_x14_1, b_lo_x14_1, d_x14_1⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_1 = x5 * x3_1 := - ⟨x5 * x3_1 % 2^64, by omega, by omega⟩ + ⟨x5 * x3_1 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_1]; exact Nat.mod_add_div _ _⟩ clear e_x14_1 clear_value x14_1 have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl - have l_x11_3 : x11_3 + 2^64 * c_8 = x11_2 + x15_2 + c_7 := by omega - have b_x11_3 : x11_3 < 2^64 := by omega - have b_c_8 : c_8 ≤ 1 := by omega + have l_x11_3 : x11_3 + 2^64 * c_8 = x11_2 + x15_2 + c_7 := by + rw [e_x11_3, e_c_8]; exact Nat.mod_add_div _ _ + have b_x11_3 : x11_3 < 2^64 := by rw [e_x11_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_8 : c_8 ≤ 1 := by + rw [e_c_8]; exact addc_carry_le_one _ _ _ b_x11_2 b_x15_2 b_c_7 clear e_x11_3 e_c_8 clear_value s_6 x11_3 c_8 - have p_x15_3 : x6 * x3_1 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_1) (by norm_num) + have p_x15_3 : x6 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_1 have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl - have b_x15_3 : x15_3 < 2^64 := by omega - have d_x15_3 : x15_2 + 2^64 * x15_3 = x6 * x3_1 := by omega + have b_x15_3 : x15_3 < 2^64 := by rw [e_x15_3]; exact Nat.div_lt_of_lt_mul p_x15_3 + have d_x15_3 : x15_2 + 2^64 * x15_3 = x6 * x3_1 := by + rw [e_x15_2, e_x15_3]; exact Nat.mod_add_div _ _ clear e_x15_2 e_x15_3 clear_value x15_3 have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl - have l_x12_3 : x12_3 + 2^64 * c_9 = x12_2 + 0 + c_8 := by omega - have b_x12_3 : x12_3 < 2^64 := by omega - have b_c_9 : c_9 ≤ 1 := by omega + have l_x12_3 : x12_3 + 2^64 * c_9 = x12_2 + 0 + c_8 := by + rw [e_x12_3, e_c_9]; exact Nat.mod_add_div _ _ + have b_x12_3 : x12_3 < 2^64 := by rw [e_x12_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_9 : c_9 ≤ 1 := by + rw [e_c_9]; exact addc_carry_le_one _ _ _ b_x12_2 (by decide) b_c_8 clear e_x12_3 e_c_9 clear_value s_7 x12_3 c_9 have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl - have l_x13_3 : x13_3 + 2^64 * c_10 = x13_2 + x17_2 + c_9 := by omega - have b_x13_3 : x13_3 < 2^64 := by omega - have b_c_10 : c_10 ≤ 1 := by omega + have l_x13_3 : x13_3 + 2^64 * c_10 = x13_2 + x17_2 + c_9 := by + rw [e_x13_3, e_c_10]; exact Nat.mod_add_div _ _ + have b_x13_3 : x13_3 < 2^64 := by rw [e_x13_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_10 : c_10 ≤ 1 := by + rw [e_c_10]; exact addc_carry_le_one _ _ _ b_x13_2 b_x17_2 b_c_9 clear e_x13_3 e_c_10 clear_value s_8 x13_3 c_10 have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl - have b_x17_3 : x17_3 < 2^62 := by omega - have sh_x17_3 : x17_2 + 2^64 * x17_3 = x3_1 * 2^62 := by omega + have b_x17_3 : x17_3 < 2^62 := by + rw [e_x17_3]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_1 (by norm_num)) + have sh_x17_3 : x17_2 + 2^64 * x17_3 = x3_1 * 2^62 := by + rw [e_x17_2, e_x17_3]; exact lsl62_lsr2_split _ clear e_x17_2 e_x17_3 clear_value x17_3 have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl - have b_x9_1 : x9_1 < 2^64 := by omega + have b_x9_1 : x9_1 < 2^64 := by rw [e_x9_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_1, b_k_x9_1, l_x9_1⟩ : ∃ k, k ≤ 1 ∧ x9_1 + 2^64 * k = 0 + 0 + c_10 := - ⟨(0 + 0 + c_10) / 2^64, by omega, by omega⟩ + ⟨(0 + 0 + c_10) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_10, + by rw [e_x9_1]; exact Nat.mod_add_div _ _⟩ clear e_x9_1 clear_value x9_1 have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl - have l_x10_2 : x10_2 + 2^64 * c_11 = x11_3 + x14_1 + 0 := by omega - have b_x10_2 : x10_2 < 2^64 := by omega - have b_c_11 : c_11 ≤ 1 := by omega + have l_x10_2 : x10_2 + 2^64 * c_11 = x11_3 + x14_1 + 0 := by + rw [e_x10_2, e_c_11]; exact Nat.mod_add_div _ _ + have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_11 : c_11 ≤ 1 := by + rw [e_c_11]; exact addc_carry_le_one _ _ _ b_x11_3 b_x14_1 (by decide) clear e_x10_2 e_c_11 clear_value s_9 x10_2 c_11 have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl - have l_x11_4 : x11_4 + 2^64 * c_12 = x12_3 + x15_3 + c_11 := by omega - have b_x11_4 : x11_4 < 2^64 := by omega - have b_c_12 : c_12 ≤ 1 := by omega + have l_x11_4 : x11_4 + 2^64 * c_12 = x12_3 + x15_3 + c_11 := by + rw [e_x11_4, e_c_12]; exact Nat.mod_add_div _ _ + have b_x11_4 : x11_4 < 2^64 := by rw [e_x11_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_12 : c_12 ≤ 1 := by + rw [e_c_12]; exact addc_carry_le_one _ _ _ b_x12_3 b_x15_3 b_c_11 clear e_x11_4 e_c_12 clear_value s_10 x11_4 c_12 have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl - have l_x12_4 : x12_4 + 2^64 * c_13 = x13_3 + 0 + c_12 := by omega - have b_x12_4 : x12_4 < 2^64 := by omega - have b_c_13 : c_13 ≤ 1 := by omega + have l_x12_4 : x12_4 + 2^64 * c_13 = x13_3 + 0 + c_12 := by + rw [e_x12_4, e_c_13]; exact Nat.mod_add_div _ _ + have b_x12_4 : x12_4 < 2^64 := by rw [e_x12_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_13 : c_13 ≤ 1 := by + rw [e_c_13]; exact addc_carry_le_one _ _ _ b_x13_3 (by decide) b_c_12 clear e_x12_4 e_c_13 clear_value s_11 x12_4 c_13 have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl - have b_x3_2 : x3_2 < 2^64 := by omega + have b_x3_2 : x3_2 < 2^64 := by rw [e_x3_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x3_2 have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl - have b_x13_4 : x13_4 < 2^64 := by omega + have b_x13_4 : x13_4 < 2^64 := by rw [e_x13_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_4, b_k_x13_4, l_x13_4⟩ : ∃ k, k ≤ 1 ∧ x13_4 + 2^64 * k = x9_1 + x17_3 + c_13 := - ⟨(x9_1 + x17_3 + c_13) / 2^64, by omega, by omega⟩ + ⟨(x9_1 + x17_3 + c_13) / 2^64, addc_carry_le_one _ _ _ b_x9_1 (lt_of_lt_of_le b_x17_3 (by norm_num)) b_c_13, + by rw [e_x13_4]; exact Nat.mod_add_div _ _⟩ clear e_x13_4 clear_value x13_4 -- BEGIN round 1 @@ -324,94 +386,111 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul b_x10_2 b_x11_4 b_x12_4 b_x13_4 b_x3 b_x3_1 b_x3_2 e_x3_2 -- END round 1 have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl - have b_x15_4 : x15_4 < 2^64 := by omega + have b_x15_4 : x15_4 < 2^64 := by rw [e_x15_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x15_4 have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl - have b_x17_4 : x17_4 < 2^64 := by omega + have b_x17_4 : x17_4 < 2^64 := by rw [e_x17_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x17_4 have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have l_c_14 : (c_14 = 1 ∧ 1 + 1 ≤ x10_2 + 1) ∨ (c_14 = 0 ∧ x10_2 + 1 < 1 + 1) := by - omega + have b_c_14 : c_14 ≤ 1 := by rw [e_c_14]; exact subc_carry_le_one _ _ _ b_x10_2 + have l_c_14 : (c_14 = 1 ∧ 1 + 1 ≤ x10_2 + 1) ∨ (c_14 = 0 ∧ x10_2 + 1 < 1 + 1) := + subc_carry_cases _ _ _ _ e_c_14 b_x10_2 (by decide) (by decide) clear e_c_14 clear_value c_14 - have p_x14_2 : x5 * x3_2 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_2) (by norm_num) + have p_x14_2 : x5 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_2 have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl - have b_x14_2 : x14_2 < 2^64 := by omega + have b_x14_2 : x14_2 < 2^64 := by rw [e_x14_2]; exact Nat.div_lt_of_lt_mul p_x14_2 obtain ⟨lo_x14_2, b_lo_x14_2, d_x14_2⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_2 = x5 * x3_2 := - ⟨x5 * x3_2 % 2^64, by omega, by omega⟩ + ⟨x5 * x3_2 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_2]; exact Nat.mod_add_div _ _⟩ clear e_x14_2 clear_value x14_2 have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl - have l_x11_5 : x11_5 + 2^64 * c_15 = x11_4 + x15_4 + c_14 := by omega - have b_x11_5 : x11_5 < 2^64 := by omega - have b_c_15 : c_15 ≤ 1 := by omega + have l_x11_5 : x11_5 + 2^64 * c_15 = x11_4 + x15_4 + c_14 := by + rw [e_x11_5, e_c_15]; exact Nat.mod_add_div _ _ + have b_x11_5 : x11_5 < 2^64 := by rw [e_x11_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_15 : c_15 ≤ 1 := by + rw [e_c_15]; exact addc_carry_le_one _ _ _ b_x11_4 b_x15_4 b_c_14 clear e_x11_5 e_c_15 clear_value s_12 x11_5 c_15 - have p_x15_5 : x6 * x3_2 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_2) (by norm_num) + have p_x15_5 : x6 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_2 have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl - have b_x15_5 : x15_5 < 2^64 := by omega - have d_x15_5 : x15_4 + 2^64 * x15_5 = x6 * x3_2 := by omega + have b_x15_5 : x15_5 < 2^64 := by rw [e_x15_5]; exact Nat.div_lt_of_lt_mul p_x15_5 + have d_x15_5 : x15_4 + 2^64 * x15_5 = x6 * x3_2 := by + rw [e_x15_4, e_x15_5]; exact Nat.mod_add_div _ _ clear e_x15_4 e_x15_5 clear_value x15_5 have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl - have l_x12_5 : x12_5 + 2^64 * c_16 = x12_4 + 0 + c_15 := by omega - have b_x12_5 : x12_5 < 2^64 := by omega - have b_c_16 : c_16 ≤ 1 := by omega + have l_x12_5 : x12_5 + 2^64 * c_16 = x12_4 + 0 + c_15 := by + rw [e_x12_5, e_c_16]; exact Nat.mod_add_div _ _ + have b_x12_5 : x12_5 < 2^64 := by rw [e_x12_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_16 : c_16 ≤ 1 := by + rw [e_c_16]; exact addc_carry_le_one _ _ _ b_x12_4 (by decide) b_c_15 clear e_x12_5 e_c_16 clear_value s_13 x12_5 c_16 have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl - have l_x13_5 : x13_5 + 2^64 * c_17 = x13_4 + x17_4 + c_16 := by omega - have b_x13_5 : x13_5 < 2^64 := by omega - have b_c_17 : c_17 ≤ 1 := by omega + have l_x13_5 : x13_5 + 2^64 * c_17 = x13_4 + x17_4 + c_16 := by + rw [e_x13_5, e_c_17]; exact Nat.mod_add_div _ _ + have b_x13_5 : x13_5 < 2^64 := by rw [e_x13_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_17 : c_17 ≤ 1 := by + rw [e_c_17]; exact addc_carry_le_one _ _ _ b_x13_4 b_x17_4 b_c_16 clear e_x13_5 e_c_17 clear_value s_14 x13_5 c_17 have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl - have b_x17_5 : x17_5 < 2^62 := by omega - have sh_x17_5 : x17_4 + 2^64 * x17_5 = x3_2 * 2^62 := by omega + have b_x17_5 : x17_5 < 2^62 := by + rw [e_x17_5]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_2 (by norm_num)) + have sh_x17_5 : x17_4 + 2^64 * x17_5 = x3_2 * 2^62 := by + rw [e_x17_4, e_x17_5]; exact lsl62_lsr2_split _ clear e_x17_4 e_x17_5 clear_value x17_5 have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl - have b_x9_2 : x9_2 < 2^64 := by omega + have b_x9_2 : x9_2 < 2^64 := by rw [e_x9_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_2, b_k_x9_2, l_x9_2⟩ : ∃ k, k ≤ 1 ∧ x9_2 + 2^64 * k = 0 + 0 + c_17 := - ⟨(0 + 0 + c_17) / 2^64, by omega, by omega⟩ + ⟨(0 + 0 + c_17) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_17, + by rw [e_x9_2]; exact Nat.mod_add_div _ _⟩ clear e_x9_2 clear_value x9_2 have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl - have l_x10_3 : x10_3 + 2^64 * c_18 = x11_5 + x14_2 + 0 := by omega - have b_x10_3 : x10_3 < 2^64 := by omega - have b_c_18 : c_18 ≤ 1 := by omega + have l_x10_3 : x10_3 + 2^64 * c_18 = x11_5 + x14_2 + 0 := by + rw [e_x10_3, e_c_18]; exact Nat.mod_add_div _ _ + have b_x10_3 : x10_3 < 2^64 := by rw [e_x10_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_18 : c_18 ≤ 1 := by + rw [e_c_18]; exact addc_carry_le_one _ _ _ b_x11_5 b_x14_2 (by decide) clear e_x10_3 e_c_18 clear_value s_15 x10_3 c_18 have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl - have l_x11_6 : x11_6 + 2^64 * c_19 = x12_5 + x15_5 + c_18 := by omega - have b_x11_6 : x11_6 < 2^64 := by omega - have b_c_19 : c_19 ≤ 1 := by omega + have l_x11_6 : x11_6 + 2^64 * c_19 = x12_5 + x15_5 + c_18 := by + rw [e_x11_6, e_c_19]; exact Nat.mod_add_div _ _ + have b_x11_6 : x11_6 < 2^64 := by rw [e_x11_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_19 : c_19 ≤ 1 := by + rw [e_c_19]; exact addc_carry_le_one _ _ _ b_x12_5 b_x15_5 b_c_18 clear e_x11_6 e_c_19 clear_value s_16 x11_6 c_19 have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl - have l_x12_6 : x12_6 + 2^64 * c_20 = x13_5 + 0 + c_19 := by omega - have b_x12_6 : x12_6 < 2^64 := by omega - have b_c_20 : c_20 ≤ 1 := by omega + have l_x12_6 : x12_6 + 2^64 * c_20 = x13_5 + 0 + c_19 := by + rw [e_x12_6, e_c_20]; exact Nat.mod_add_div _ _ + have b_x12_6 : x12_6 < 2^64 := by rw [e_x12_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_20 : c_20 ≤ 1 := by + rw [e_c_20]; exact addc_carry_le_one _ _ _ b_x13_5 (by decide) b_c_19 clear e_x12_6 e_c_20 clear_value s_17 x12_6 c_20 have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl - have b_x3_3 : x3_3 < 2^64 := by omega + have b_x3_3 : x3_3 < 2^64 := by rw [e_x3_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x3_3 have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl - have b_x13_6 : x13_6 < 2^64 := by omega + have b_x13_6 : x13_6 < 2^64 := by rw [e_x13_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_6, b_k_x13_6, l_x13_6⟩ : ∃ k, k ≤ 1 ∧ x13_6 + 2^64 * k = x9_2 + x17_5 + c_20 := - ⟨(x9_2 + x17_5 + c_20) / 2^64, by omega, by omega⟩ + ⟨(x9_2 + x17_5 + c_20) / 2^64, addc_carry_le_one _ _ _ b_x9_2 (lt_of_lt_of_le b_x17_5 (by norm_num)) b_c_20, + by rw [e_x13_6]; exact Nat.mod_add_div _ _⟩ clear e_x13_6 clear_value x13_6 -- BEGIN round 2 @@ -439,91 +518,108 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul I_2 b_x10_3 b_x11_6 b_x12_6 b_x13_6 b_x3 b_x3_1 b_x3_2 b_x3_3 e_x3_3 -- END round 2 have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl - have b_x15_6 : x15_6 < 2^64 := by omega + have b_x15_6 : x15_6 < 2^64 := by rw [e_x15_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x15_6 have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl - have b_x17_6 : x17_6 < 2^64 := by omega + have b_x17_6 : x17_6 < 2^64 := by rw [e_x17_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) clear_value x17_6 have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have l_c_21 : (c_21 = 1 ∧ 1 + 1 ≤ x10_3 + 1) ∨ (c_21 = 0 ∧ x10_3 + 1 < 1 + 1) := by - omega + have b_c_21 : c_21 ≤ 1 := by rw [e_c_21]; exact subc_carry_le_one _ _ _ b_x10_3 + have l_c_21 : (c_21 = 1 ∧ 1 + 1 ≤ x10_3 + 1) ∨ (c_21 = 0 ∧ x10_3 + 1 < 1 + 1) := + subc_carry_cases _ _ _ _ e_c_21 b_x10_3 (by decide) (by decide) clear e_c_21 clear_value c_21 - have p_x14_3 : x5 * x3_3 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x5 b_x3_3) (by norm_num) + have p_x14_3 : x5 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_3 have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl - have b_x14_3 : x14_3 < 2^64 := by omega + have b_x14_3 : x14_3 < 2^64 := by rw [e_x14_3]; exact Nat.div_lt_of_lt_mul p_x14_3 obtain ⟨lo_x14_3, b_lo_x14_3, d_x14_3⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_3 = x5 * x3_3 := - ⟨x5 * x3_3 % 2^64, by omega, by omega⟩ + ⟨x5 * x3_3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_3]; exact Nat.mod_add_div _ _⟩ clear e_x14_3 clear_value x14_3 have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl - have l_x11_7 : x11_7 + 2^64 * c_22 = x11_6 + x15_6 + c_21 := by omega - have b_x11_7 : x11_7 < 2^64 := by omega - have b_c_22 : c_22 ≤ 1 := by omega + have l_x11_7 : x11_7 + 2^64 * c_22 = x11_6 + x15_6 + c_21 := by + rw [e_x11_7, e_c_22]; exact Nat.mod_add_div _ _ + have b_x11_7 : x11_7 < 2^64 := by rw [e_x11_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_22 : c_22 ≤ 1 := by + rw [e_c_22]; exact addc_carry_le_one _ _ _ b_x11_6 b_x15_6 b_c_21 clear e_x11_7 e_c_22 clear_value s_18 x11_7 c_22 - have p_x15_7 : x6 * x3_3 < 2^128 := - lt_of_lt_of_eq (Nat.mul_lt_mul'' b_x6 b_x3_3) (by norm_num) + have p_x15_7 : x6 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_3 have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl - have b_x15_7 : x15_7 < 2^64 := by omega - have d_x15_7 : x15_6 + 2^64 * x15_7 = x6 * x3_3 := by omega + have b_x15_7 : x15_7 < 2^64 := by rw [e_x15_7]; exact Nat.div_lt_of_lt_mul p_x15_7 + have d_x15_7 : x15_6 + 2^64 * x15_7 = x6 * x3_3 := by + rw [e_x15_6, e_x15_7]; exact Nat.mod_add_div _ _ clear e_x15_6 e_x15_7 clear_value x15_7 have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl - have l_x12_7 : x12_7 + 2^64 * c_23 = x12_6 + 0 + c_22 := by omega - have b_x12_7 : x12_7 < 2^64 := by omega - have b_c_23 : c_23 ≤ 1 := by omega + have l_x12_7 : x12_7 + 2^64 * c_23 = x12_6 + 0 + c_22 := by + rw [e_x12_7, e_c_23]; exact Nat.mod_add_div _ _ + have b_x12_7 : x12_7 < 2^64 := by rw [e_x12_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_23 : c_23 ≤ 1 := by + rw [e_c_23]; exact addc_carry_le_one _ _ _ b_x12_6 (by decide) b_c_22 clear e_x12_7 e_c_23 clear_value s_19 x12_7 c_23 have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl - have l_x13_7 : x13_7 + 2^64 * c_24 = x13_6 + x17_6 + c_23 := by omega - have b_x13_7 : x13_7 < 2^64 := by omega - have b_c_24 : c_24 ≤ 1 := by omega + have l_x13_7 : x13_7 + 2^64 * c_24 = x13_6 + x17_6 + c_23 := by + rw [e_x13_7, e_c_24]; exact Nat.mod_add_div _ _ + have b_x13_7 : x13_7 < 2^64 := by rw [e_x13_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_24 : c_24 ≤ 1 := by + rw [e_c_24]; exact addc_carry_le_one _ _ _ b_x13_6 b_x17_6 b_c_23 clear e_x13_7 e_c_24 clear_value s_20 x13_7 c_24 have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl - have b_x17_7 : x17_7 < 2^62 := by omega - have sh_x17_7 : x17_6 + 2^64 * x17_7 = x3_3 * 2^62 := by omega + have b_x17_7 : x17_7 < 2^62 := by + rw [e_x17_7]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_3 (by norm_num)) + have sh_x17_7 : x17_6 + 2^64 * x17_7 = x3_3 * 2^62 := by + rw [e_x17_6, e_x17_7]; exact lsl62_lsr2_split _ clear e_x17_6 e_x17_7 clear_value x17_7 have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl - have b_x9_3 : x9_3 < 2^64 := by omega + have b_x9_3 : x9_3 < 2^64 := by rw [e_x9_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_3, b_k_x9_3, l_x9_3⟩ : ∃ k, k ≤ 1 ∧ x9_3 + 2^64 * k = 0 + 0 + c_24 := - ⟨(0 + 0 + c_24) / 2^64, by omega, by omega⟩ + ⟨(0 + 0 + c_24) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_24, + by rw [e_x9_3]; exact Nat.mod_add_div _ _⟩ clear e_x9_3 clear_value x9_3 have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl - have l_x10_4 : x10_4 + 2^64 * c_25 = x11_7 + x14_3 + 0 := by omega - have b_x10_4 : x10_4 < 2^64 := by omega - have b_c_25 : c_25 ≤ 1 := by omega + have l_x10_4 : x10_4 + 2^64 * c_25 = x11_7 + x14_3 + 0 := by + rw [e_x10_4, e_c_25]; exact Nat.mod_add_div _ _ + have b_x10_4 : x10_4 < 2^64 := by rw [e_x10_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_25 : c_25 ≤ 1 := by + rw [e_c_25]; exact addc_carry_le_one _ _ _ b_x11_7 b_x14_3 (by decide) clear e_x10_4 e_c_25 clear_value s_21 x10_4 c_25 have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl - have l_x11_8 : x11_8 + 2^64 * c_26 = x12_7 + x15_7 + c_25 := by omega - have b_x11_8 : x11_8 < 2^64 := by omega - have b_c_26 : c_26 ≤ 1 := by omega + have l_x11_8 : x11_8 + 2^64 * c_26 = x12_7 + x15_7 + c_25 := by + rw [e_x11_8, e_c_26]; exact Nat.mod_add_div _ _ + have b_x11_8 : x11_8 < 2^64 := by rw [e_x11_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_26 : c_26 ≤ 1 := by + rw [e_c_26]; exact addc_carry_le_one _ _ _ b_x12_7 b_x15_7 b_c_25 clear e_x11_8 e_c_26 clear_value s_22 x11_8 c_26 have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl - have l_x12_8 : x12_8 + 2^64 * c_27 = x13_7 + 0 + c_26 := by omega - have b_x12_8 : x12_8 < 2^64 := by omega - have b_c_27 : c_27 ≤ 1 := by omega + have l_x12_8 : x12_8 + 2^64 * c_27 = x13_7 + 0 + c_26 := by + rw [e_x12_8, e_c_27]; exact Nat.mod_add_div _ _ + have b_x12_8 : x12_8 < 2^64 := by rw [e_x12_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_27 : c_27 ≤ 1 := by + rw [e_c_27]; exact addc_carry_le_one _ _ _ b_x13_7 (by decide) b_c_26 clear e_x12_8 e_c_27 clear_value s_23 x12_8 c_27 have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl - have b_x13_8 : x13_8 < 2^64 := by omega + have b_x13_8 : x13_8 < 2^64 := by rw [e_x13_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_8, b_k_x13_8, l_x13_8⟩ : ∃ k, k ≤ 1 ∧ x13_8 + 2^64 * k = x9_3 + x17_7 + c_27 := - ⟨(x9_3 + x17_7 + c_27) / 2^64, by omega, by omega⟩ + ⟨(x9_3 + x17_7 + c_27) / 2^64, addc_carry_le_one _ _ _ b_x9_3 (lt_of_lt_of_le b_x17_7 (by norm_num)) b_c_27, + by rw [e_x13_8]; exact Nat.mod_add_div _ _⟩ clear e_x13_8 clear_value x13_8 -- BEGIN round 3 @@ -596,7 +692,7 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) have b_x3 : x3 < 2^64 := by rw [e_x3]; exact hinv_lt clear_value x3 have e_x4 : x4 = x3 := rfl - have b_x4 : x4 < 2^64 := by omega + have b_x4 : x4 < 2^64 := by rw [e_x4]; exact b_x3 clear_value x4 have e_x10 : x10 = value.l0 := rfl have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hv.1 @@ -647,43 +743,55 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) -- END helper have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl - have l_x14 : x14 + 2^64 * c + x5 + 1 = x10_1 + 2^64 + 1 := by omega - have b_x14 : x14 < 2^64 := by omega - have b_c : c ≤ 1 := by omega + have l_x14 : x14 + 2^64 * c + x5 + 1 = x10_1 + 2^64 + 1 := by + rw [e_x14, e_c]; exact subc_lin _ _ _ b_x5 (by decide) + have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c : c ≤ 1 := by + rw [e_c]; exact subc_carry_le_one _ _ _ b_x10_1 clear e_x14 e_c clear_value s x14 c have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl - have l_x15 : x15 + 2^64 * c_1 + x6 + 1 = x11_1 + 2^64 + c := by omega - have b_x15 : x15 < 2^64 := by omega - have b_c_1 : c_1 ≤ 1 := by omega + have l_x15 : x15 + 2^64 * c_1 + x6 + 1 = x11_1 + 2^64 + c := by + rw [e_x15, e_c_1]; exact subc_lin _ _ _ b_x6 b_c + have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_1 : c_1 ≤ 1 := by + rw [e_c_1]; exact subc_carry_le_one _ _ _ b_x11_1 clear e_x15 e_c_1 clear_value s_1 x15 c_1 have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl - have l_x16 : x16 + 2^64 * c_2 + x7 + 1 = x12_1 + 2^64 + c_1 := by omega - have b_x16 : x16 < 2^64 := by omega - have b_c_2 : c_2 ≤ 1 := by omega + have l_x16 : x16 + 2^64 * c_2 + x7 + 1 = x12_1 + 2^64 + c_1 := by + rw [e_x16, e_c_2]; exact subc_lin _ _ _ b_x7 b_c_1 + have b_x16 : x16 < 2^64 := by rw [e_x16]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_2 : c_2 ≤ 1 := by + rw [e_c_2]; exact subc_carry_le_one _ _ _ b_x12_1 clear e_x16 e_c_2 clear_value s_2 x16 c_2 have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl - have l_x17 : x17 + 2^64 * c_3 + x8 + 1 = x13_1 + 2^64 + c_2 := by omega - have b_x17 : x17 < 2^64 := by omega - have b_c_3 : c_3 ≤ 1 := by omega + have l_x17 : x17 + 2^64 * c_3 + x8 + 1 = x13_1 + 2^64 + c_2 := by + rw [e_x17, e_c_3]; exact subc_lin _ _ _ b_x8 b_c_2 + have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_3 : c_3 ≤ 1 := by + rw [e_c_3]; exact subc_carry_le_one _ _ _ b_x13_1 clear e_x17 e_c_3 clear_value s_3 x17 c_3 have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl - have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; split <;> omega + have b_x10_2 : x10_2 < 2^64 := by + rw [e_x10_2]; split <;> first | exact b_x10_1 | exact b_x14 clear_value x10_2 have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl - have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; split <;> omega + have b_x11_2 : x11_2 < 2^64 := by + rw [e_x11_2]; split <;> first | exact b_x11_1 | exact b_x15 clear_value x11_2 have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl - have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; split <;> omega + have b_x12_2 : x12_2 < 2^64 := by + rw [e_x12_2]; split <;> first | exact b_x12_1 | exact b_x16 clear_value x12_2 have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl - have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; split <;> omega + have b_x13_2 : x13_2 < 2^64 := by + rw [e_x13_2]; split <;> first | exact b_x13_1 | exact b_x17 clear_value x13_2 have e_out0 : out0 = x10_2 := rfl clear_value out0 diff --git a/scripts/gen_aarch64_pasta_mul.py b/scripts/gen_aarch64_pasta_mul.py index 4e2bad8..1790632 100755 --- a/scripts/gen_aarch64_pasta_mul.py +++ b/scripts/gen_aarch64_pasta_mul.py @@ -478,13 +478,18 @@ def wrap_tactic(head, words, tail, indent=" "): def skeleton(routine): """The generated part of the correctness proof of `routine`: unfold, extract the lets under - SSA names, then per instruction the defining equation (by `rfl`, in `%`/`/` form), the range - fact (by `omega`), and `clear_value`. Hand-written annotations go between the groups.""" + SSA names, then per instruction the defining equation (by `rfl`, in `%`/`/` form), the linear + facts derived from it, and `clear_value`. Each derived fact is an instance of one lemma + (`Nat.mod_add_div`, `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, or a carry lemma from the spec + file's preamble), so a step costs nothing wherever it sits and names the facts it rests on; + `omega` is left to the hand-written annotations between the groups.""" e = routine.emitter live = e.liveness(routine.result_names) entries = [en for en, keep in zip(e.entries, live) if keep] names = ssa_names(entries) ren = {} # current SSA name of each register at each point: resolved while walking + bnd = {} # SSA name -> the fact bounding it below 2^64 (registers) or by 1 (carries) + narrow = set() # `lsr` results, whose bound is below 2^64 and needs weakening out = [f" -- generated skeleton for `{routine.name}`: do not edit between the annotations", f" unfold {routine.name} at hr", " lift_lets at hr"] out += wrap_tactic("extract_lets", names, " at hr") @@ -494,8 +499,15 @@ def skeleton(routine): def r(op): # operand as written in the entry, renamed to its SSA name at that point return ren.get(op, op) - def bound(op): - return None if re.fullmatch(r"[0-9]+", op) else f"b_{op}" + def lt64(op): # a proof that the operand is below 2^64 + if re.fullmatch(r"[0-9]+", op): + return "(by decide)" + if op in narrow: + return f"(lt_of_lt_of_le {bnd[op]} (by norm_num))" + return bnd[op] + + def le1(op): # a proof that the carry operand is at most 1 + return "(by decide)" if re.fullmatch(r"[0-9]+", op) else bnd[op] i = 0 while i < len(entries): @@ -512,47 +524,60 @@ def bound(op): hyp = BOUND_HYPS[arg] lines.append(f" have e_{nm} : {nm} = {arg}.l{idx} := rfl") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {hyp}.{PROJ[idx]}") + bnd[nm] = f"b_{nm}" elif kind == "inv": lines.append(f" have e_{nm} : {nm} = inv := rfl") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {INV_BOUND_HYP}") + bnd[nm] = f"b_{nm}" elif kind == "mov": (a,) = ops lines.append(f" have e_{nm} : {nm} = {a} := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {lt64(a)}") + bnd[nm] = f"b_{nm}" elif kind == "mul": a, b = ops lines.append(f" have e_{nm} : {nm} = {a} * {b} % 2^64 := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") + bnd[nm] = f"b_{nm}" products[(a, b)] = nm # its `%` equation is cleared at the matching `umulh` elif kind == "umulh": a, b = ops - lines.append(f" have p_{nm} : {a} * {b} < 2^128 :=") - lines.append(f" lt_of_lt_of_eq (Nat.mul_lt_mul'' {bound(a)} {bound(b)}) (by norm_num)") + lines.append(f" have p_{nm} : {a} * {b} < 2^64 * 2^64 := Nat.mul_lt_mul'' {lt64(a)} {lt64(b)}") lines.append(f" have e_{nm} : {nm} = {a} * {b} / 2^64 := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.div_lt_of_lt_mul p_{nm}") + bnd[nm] = f"b_{nm}" if (a, b) in products: lo = products.pop((a, b)) - lines.append(f" have d_{nm} : {lo} + 2^64 * {nm} = {a} * {b} := by omega") + lines.append(f" have d_{nm} : {lo} + 2^64 * {nm} = {a} * {b} := by") + lines.append(f" rw [e_{lo}, e_{nm}]; exact Nat.mod_add_div _ _") lines.append(f" clear e_{lo} e_{nm}") else: # The low half is never computed (its cancellation is arranged by `subs`); name # it as a ghost so that later steps need no `%`. lines.append(f" obtain ⟨lo_{nm}, b_lo_{nm}, d_{nm}⟩ :") lines.append(f" ∃ lo, lo < 2^64 ∧ lo + 2^64 * {nm} = {a} * {b} :=") - lines.append(f" ⟨{a} * {b} % 2^64, by omega, by omega⟩") + lines.append(f" ⟨{a} * {b} % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _),") + lines.append(f" by rw [e_{nm}]; exact Nat.mod_add_div _ _⟩") lines.append(f" clear e_{nm}") elif kind == "lsl": a, k = ops lines.append(f" have e_{nm} : {nm} = {a} * 2^{k} % 2^64 := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") + bnd[nm] = f"b_{nm}" shifts[(a, k)] = nm elif kind == "lsr": a, k = ops lines.append(f" have e_{nm} : {nm} = {a} / 2^{k} := rfl") - lines.append(f" have b_{nm} : {nm} < 2^{64 - k} := by omega") + lines.append(f" have b_{nm} : {nm} < 2^{64 - k} := by") + lines.append(f" rw [e_{nm}]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq {lt64(a)} (by norm_num))") + bnd[nm] = f"b_{nm}" + narrow.add(nm) if (a, 64 - k) in shifts: lo = shifts.pop((a, 64 - k)) - lines.append(f" have sh_{nm} : {lo} + 2^64 * {nm} = {a} * 2^{64 - k} := by omega") + if k != 2: + raise ValueError(f"lsl/lsr split by {64 - k}/{k}: add a lemma to the spec preamble") + lines.append(f" have sh_{nm} : {lo} + 2^64 * {nm} = {a} * 2^{64 - k} := by") + lines.append(f" rw [e_{lo}, e_{nm}]; exact lsl62_lsr2_split _") lines.append(f" clear e_{lo} e_{nm}") elif kind in ("adds", "subs"): a, b, cin = ops @@ -561,43 +586,56 @@ def bound(op): if kind == "adds": val = f"({a} + {b} + {cin})" lin = f"{xn} + 2^64 * {cn} = {a} + {b} + {cin}" + lin_proof = "Nat.mod_add_div _ _" + carry_proof = f"addc_carry_le_one _ _ _ {lt64(a)} {lt64(b)} {le1(cin)}" else: val = f"({a} + 2^64 - {b} - (1 - {cin}))" lin = f"{xn} + 2^64 * {cn} + {b} + 1 = {a} + 2^64 + {cin}" + lin_proof = f"subc_lin _ _ _ {lt64(b)} {le1(cin)}" + carry_proof = f"subc_carry_le_one _ _ _ {lt64(a)}" lines.append(f" have e_{xn} : {xn} = {val} % 2^64 := rfl") lines.append(f" have e_{cn} : {cn} = {val} / 2^64 := rfl") - lines.append(f" have l_{xn} : {lin} := by omega") - lines.append(f" have b_{xn} : {xn} < 2^64 := by omega") - lines.append(f" have b_{cn} : {cn} ≤ 1 := by omega") + lines.append(f" have l_{xn} : {lin} := by") + lines.append(f" rw [e_{xn}, e_{cn}]; exact {lin_proof}") + lines.append(f" have b_{xn} : {xn} < 2^64 := by rw [e_{xn}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") + lines.append(f" have b_{cn} : {cn} ≤ 1 := by") + lines.append(f" rw [e_{cn}]; exact {carry_proof}") lines.append(f" clear e_{xn} e_{cn}") ren[entries[i + 1]["name"]] = xn ren[entries[i + 2]["name"]] = cn + bnd[xn], bnd[cn] = f"b_{xn}", f"b_{cn}" i += 2 elif kind == "adc": a, b, cin = ops lines.append(f" have e_{nm} : {nm} = ({a} + {b} + {cin}) % 2^64 := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") lines.append(f" obtain ⟨k_{nm}, b_k_{nm}, l_{nm}⟩ :") lines.append(f" ∃ k, k ≤ 1 ∧ {nm} + 2^64 * k = {a} + {b} + {cin} :=") - lines.append(f" ⟨({a} + {b} + {cin}) / 2^64, by omega, by omega⟩") + lines.append(f" ⟨({a} + {b} + {cin}) / 2^64, addc_carry_le_one _ _ _ {lt64(a)} {lt64(b)} {le1(cin)},") + lines.append(f" by rw [e_{nm}]; exact Nat.mod_add_div _ _⟩") lines.append(f" clear e_{nm}") + bnd[nm] = f"b_{nm}" elif kind == "subs_carry": a, b, cin = ops lines.append(f" have e_{nm} : {nm} = ({a} + 2^64 - {b} - (1 - {cin})) / 2^64 := rfl") - lines.append(f" have l_{nm} : ({nm} = 1 ∧ {b} + 1 ≤ {a} + {cin})" - f" ∨ ({nm} = 0 ∧ {a} + {cin} < {b} + 1) := by") - lines.append(f" omega") + lines.append(f" have b_{nm} : {nm} ≤ 1 := by rw [e_{nm}]; exact subc_carry_le_one _ _ _ {lt64(a)}") + lines.append(f" have l_{nm} : ({nm} = 1 ∧ {b} + 1 ≤ {a} + {cin}) ∨ ({nm} = 0 ∧ {a} + {cin} < {b} + 1) :=") + lines.append(f" subc_carry_cases _ _ _ _ e_{nm} {lt64(a)} {lt64(b)} {le1(cin)}") lines.append(f" clear e_{nm}") + bnd[nm] = f"b_{nm}" elif kind == "csel": c, a, b = ops lines.append(f" have e_{nm} : {nm} = (if {c} = 0 then {a} else {b}) := rfl") - lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; split <;> omega") + lines.append(f" have b_{nm} : {nm} < 2^64 := by") + lines.append(f" rw [e_{nm}]; split <;> first | exact {lt64(a)} | exact {lt64(b)}") + bnd[nm] = f"b_{nm}" elif kind == "call": *targs, inv = ops lines.append(f" have e_{nm} : {nm} = mulBy1 ⟨{', '.join(targs)}⟩ modulus {inv} := rfl") elif kind == "callout": (idx,) = ops lines.append(f" have e_{nm} : {nm} = {r('r')}.l{idx} := rfl") + bnd[nm] = f"b_{nm}" # supplied by the annotation that applies the callee's theorem elif kind == "out": (x,) = ops lines.append(f" have e_{nm} : {nm} = {x} := rfl") @@ -609,7 +647,6 @@ def bound(op): i += 1 return out - def check_spec(path, routines): """Verify that each routine's skeleton appears verbatim and contiguously in `path` once its `-- BEGIN ... -- END` annotation blocks are removed and blank lines dropped. Text outside the From 0072b3f243fddd7b3fa067bf00dd0744f75d7329 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 05:16:09 +0100 Subject: [PATCH 6/9] asm: say which units of the verification remain The design document's status list marked only its first two items as present or proved, so the other three read as done; it now separates what is present from what remains, and the two theorems not yet proved are marked as such. Co-authored-by: Claude Fable 5.1 --- design/aarch64-pasta-mul-verification.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/design/aarch64-pasta-mul-verification.md b/design/aarch64-pasta-mul-verification.md index b98abae..dacfbf1 100644 --- a/design/aarch64-pasta-mul-verification.md +++ b/design/aarch64-pasta-mul-verification.md @@ -97,12 +97,12 @@ the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: * `mulBy1_spec` (proved): for every four-limb `t`, the shared reduction helper returns limbs `r` below `2^64` with `2^256 · r = t + Q · p` for some `Q < 2^256`. So `r` is congruent to `t · 2^−256` modulo `p`, and `r ≤ p`. -* `mul_spec`: if `lhs < p` and `rhs < 2^256`, or `lhs < 2^256`, `rhs < p`, and every +* `mul_spec` (to prove): if `lhs < p` and `rhs < 2^256`, or `lhs < 2^256`, `rhs < p`, and every `rhs` limb in positions 1 to 3 is at most `2^64 − 4`, then the output is below `p` and `output · 2^256 ≡ lhs · rhs (mod p)`. The exact wrap boundary (whether `2^64 − 2` and `2^64 − 3` can wrap) is settled as a by-product of the round lemma and stated as its own lemma. -* `sqr_spec`: if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. +* `sqr_spec` (to prove): if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. * `fromMont_spec` (proved): for every four-limb `a`, the output is below `p` and `output · 2^256 ≡ a (mod p)`. No bound on `a` below `p` is needed: the helper's result is at most `p`, and the conditional subtraction removes the one excess case. @@ -117,14 +117,16 @@ wrong. ## Status -1. Semantics, generator, generated program, vendored `.S` with hash, vectors, CI - check: present. -2. The helper (four reduction rounds) and `from_mont` (the helper and a conditional - subtraction): proved. -3. `mul`: round invariant, the accumulator no-wrap lemma under each contract, the +Present: the semantics, the generator, the generated program, the vendored `.S` with its +hash, the vectors, and the CI check; the proofs of the helper (four reduction rounds) and +of `from_mont` (the helper and a conditional subtraction). + +Remaining, in order: + +1. `mul`: the round invariant, the accumulator no-wrap lemma under each contract, and the final comparison. -4. `sqr`: the cross-term schoolbook, doubling, and the "can't overflow" claims. -5. Pasta instantiation and census entries in `TrustBoundary.lean`. +2. `sqr`: the cross-term schoolbook, the doubling, and the "can't overflow" claims. +3. The Pasta instantiation and the census entries in `TrustBoundary.lean`. Out of scope for now: Zakura's inline-`asm!` transcription (provable later by instruction-by-instruction correspondence), `sqr_n_mul` (zakura-core/common#65), and From d0ab9c7bc2d6e16e9029b9299c01e925dff4f38d Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 13:08:22 +0100 Subject: [PATCH 7/9] asm: make the skeleton's locals opaque in one step The generated skeleton records every instruction's defining equation first, then clears all the locals' values in one `clear_value`, last local first, and only then derives the per-instruction facts. Clearing a local's value reverts every later local whose value mentions it, so one `clear_value` per instruction was quadratic in the length of the chain: harmless for the helper's 150 locals, over a minute for the multiplication routine's 380. Annotation blocks now follow the group they need, identified by its marker comment `-- : `, instead of the `clear_value` line that used to end it, and the round blocks of the helper's proof no longer clear the context at their end, which would now remove equations that later groups use. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 435 +++++++++++---------- scripts/gen_aarch64_pasta_mul.py | 64 +-- 2 files changed, 257 insertions(+), 242 deletions(-) diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean index 3b9a26e..b5c9427 100644 --- a/CompElliptic/Asm/AArch64/PastaMulSpec.lean +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -98,137 +98,206 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul x11_8 c_26 s_23 x12_8 c_27 x13_8 at hr subst hr have e_x10 : x10 = t.l0 := rfl - have b_x10 : x10 < 2^64 := by rw [e_x10]; exact ht.1 - clear_value x10 have e_x11 : x11 = t.l1 := rfl - have b_x11 : x11 < 2^64 := by rw [e_x11]; exact ht.2.1 - clear_value x11 have e_x12 : x12 = t.l2 := rfl - have b_x12 : x12 < 2^64 := by rw [e_x12]; exact ht.2.2.1 - clear_value x12 have e_x13 : x13 = t.l3 := rfl - have b_x13 : x13 < 2^64 := by rw [e_x13]; exact ht.2.2.2 - clear_value x13 have e_x4 : x4 = inv := rfl - have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt - clear_value x4 have e_x3 : x3 = x4 * x10 % 2^64 := rfl - have b_x3 : x3 < 2^64 := by rw [e_x3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x3 have e_x5 : x5 = modulus.l0 := rfl - have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 - clear_value x5 have e_x6 : x6 = modulus.l1 := rfl - have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 - clear_value x6 have e_x15 : x15 = x6 * x3 % 2^64 := rfl - have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x15 have e_x17 : x17 = x3 * 2^62 % 2^64 := rfl - have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x17 have e_c : c = (x10 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have e_x14 : x14 = x5 * x3 / 2^64 := rfl + have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl + have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl + have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl + have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl + have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl + have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl + have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl + have e_x17_1 : x17_1 = x3 / 2^2 := rfl + have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl + have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl + have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl + have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl + have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl + have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl + have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl + have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl + have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl + have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl + have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl + have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl + have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl + have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl + have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl + have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl + have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl + have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl + have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl + have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl + have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl + have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl + have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl + have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl + have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl + have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl + have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl + have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl + have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl + have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl + have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl + have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl + have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl + have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl + have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl + have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl + have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl + have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl + have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl + have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl + have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl + have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl + have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl + have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl + have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl + have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl + have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl + have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl + have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl + have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl + have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl + have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl + have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl + have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl + have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl + have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl + have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl + have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl + have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl + have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl + have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl + have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl + have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl + have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl + have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl + have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl + have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl + have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl + clear_value x13_8 c_27 x12_8 s_23 c_26 x11_8 s_22 c_25 x10_4 s_21 x9_3 x17_7 c_24 x13_7 s_20 c_23 + x12_7 s_19 x15_7 c_22 x11_7 s_18 x14_3 c_21 x17_6 x15_6 x13_6 x3_3 c_20 x12_6 s_17 c_19 x11_6 + s_16 c_18 x10_3 s_15 x9_2 x17_5 c_17 x13_5 s_14 c_16 x12_5 s_13 x15_5 c_15 x11_5 s_12 x14_2 + c_14 x17_4 x15_4 x13_4 x3_2 c_13 x12_4 s_11 c_12 x11_4 s_10 c_11 x10_2 s_9 x9_1 x17_3 c_10 + x13_3 s_8 c_9 x12_3 s_7 x15_3 c_8 x11_3 s_6 x14_1 c_7 x17_2 x15_2 x13_2 x3_1 c_6 x12_2 s_5 c_5 + x11_2 s_4 c_4 x10_1 s_3 x9 x17_1 c_3 x13_1 s_2 c_2 x12_1 s_1 x15_1 c_1 x11_1 s x14 c x17 x15 + x6 x5 x3 x4 x13 x12 x11 x10 + -- x10: argument + have b_x10 : x10 < 2^64 := by rw [e_x10]; exact ht.1 + -- x11: argument + have b_x11 : x11 < 2^64 := by rw [e_x11]; exact ht.2.1 + -- x12: argument + have b_x12 : x12 < 2^64 := by rw [e_x12]; exact ht.2.2.1 + -- x13: argument + have b_x13 : x13 < 2^64 := by rw [e_x13]; exact ht.2.2.2 + -- x4: argument + have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt + -- x3: mul x3,x4,x10 + have b_x3 : x3 < 2^64 := by rw [e_x3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x5: ldp x5,x6,[x2] + have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 + -- x6: ldp x5,x6,[x2] + have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 + -- x15: mul x15,x6,x3 + have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x17: lsl x17,x3,#62 + have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- c: subs xzr,x10,#1 have b_c : c ≤ 1 := by rw [e_c]; exact subc_carry_le_one _ _ _ b_x10 have l_c : (c = 1 ∧ 1 + 1 ≤ x10 + 1) ∨ (c = 0 ∧ x10 + 1 < 1 + 1) := subc_carry_cases _ _ _ _ e_c b_x10 (by decide) (by decide) clear e_c - clear_value c + -- x14: umulh x14,x5,x3 have p_x14 : x5 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3 - have e_x14 : x14 = x5 * x3 / 2^64 := rfl have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.div_lt_of_lt_mul p_x14 obtain ⟨lo_x14, b_lo_x14, d_x14⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14 = x5 * x3 := ⟨x5 * x3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), by rw [e_x14]; exact Nat.mod_add_div _ _⟩ clear e_x14 - clear_value x14 - have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl - have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl + -- x11_1: adcs x11,x11,x15 have l_x11_1 : x11_1 + 2^64 * c_1 = x11 + x15 + c := by rw [e_x11_1, e_c_1]; exact Nat.mod_add_div _ _ have b_x11_1 : x11_1 < 2^64 := by rw [e_x11_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_1 : c_1 ≤ 1 := by rw [e_c_1]; exact addc_carry_le_one _ _ _ b_x11 b_x15 b_c clear e_x11_1 e_c_1 - clear_value s x11_1 c_1 + -- x15_1: umulh x15,x6,x3 have p_x15_1 : x6 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3 - have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl have b_x15_1 : x15_1 < 2^64 := by rw [e_x15_1]; exact Nat.div_lt_of_lt_mul p_x15_1 have d_x15_1 : x15 + 2^64 * x15_1 = x6 * x3 := by rw [e_x15, e_x15_1]; exact Nat.mod_add_div _ _ clear e_x15 e_x15_1 - clear_value x15_1 - have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl - have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl + -- x12_1: adcs x12,x12,xzr have l_x12_1 : x12_1 + 2^64 * c_2 = x12 + 0 + c_1 := by rw [e_x12_1, e_c_2]; exact Nat.mod_add_div _ _ have b_x12_1 : x12_1 < 2^64 := by rw [e_x12_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_2 : c_2 ≤ 1 := by rw [e_c_2]; exact addc_carry_le_one _ _ _ b_x12 (by decide) b_c_1 clear e_x12_1 e_c_2 - clear_value s_1 x12_1 c_2 - have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl - have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl + -- x13_1: adcs x13,x13,x17 have l_x13_1 : x13_1 + 2^64 * c_3 = x13 + x17 + c_2 := by rw [e_x13_1, e_c_3]; exact Nat.mod_add_div _ _ have b_x13_1 : x13_1 < 2^64 := by rw [e_x13_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_3 : c_3 ≤ 1 := by rw [e_c_3]; exact addc_carry_le_one _ _ _ b_x13 b_x17 b_c_2 clear e_x13_1 e_c_3 - clear_value s_2 x13_1 c_3 - have e_x17_1 : x17_1 = x3 / 2^2 := rfl + -- x17_1: lsr x17,x3,#2 have b_x17_1 : x17_1 < 2^62 := by rw [e_x17_1]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3 (by norm_num)) have sh_x17_1 : x17 + 2^64 * x17_1 = x3 * 2^62 := by rw [e_x17, e_x17_1]; exact lsl62_lsr2_split _ clear e_x17 e_x17_1 - clear_value x17_1 - have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl + -- x9: adc x9,xzr,xzr have b_x9 : x9 < 2^64 := by rw [e_x9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9, b_k_x9, l_x9⟩ : ∃ k, k ≤ 1 ∧ x9 + 2^64 * k = 0 + 0 + c_3 := ⟨(0 + 0 + c_3) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_3, by rw [e_x9]; exact Nat.mod_add_div _ _⟩ clear e_x9 - clear_value x9 - have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl - have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl + -- x10_1: adds x10,x11,x14 have l_x10_1 : x10_1 + 2^64 * c_4 = x11_1 + x14 + 0 := by rw [e_x10_1, e_c_4]; exact Nat.mod_add_div _ _ have b_x10_1 : x10_1 < 2^64 := by rw [e_x10_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_4 : c_4 ≤ 1 := by rw [e_c_4]; exact addc_carry_le_one _ _ _ b_x11_1 b_x14 (by decide) clear e_x10_1 e_c_4 - clear_value s_3 x10_1 c_4 - have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl - have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl + -- x11_2: adcs x11,x12,x15 have l_x11_2 : x11_2 + 2^64 * c_5 = x12_1 + x15_1 + c_4 := by rw [e_x11_2, e_c_5]; exact Nat.mod_add_div _ _ have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_5 : c_5 ≤ 1 := by rw [e_c_5]; exact addc_carry_le_one _ _ _ b_x12_1 b_x15_1 b_c_4 clear e_x11_2 e_c_5 - clear_value s_4 x11_2 c_5 - have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl - have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl + -- x12_2: adcs x12,x13,xzr have l_x12_2 : x12_2 + 2^64 * c_6 = x13_1 + 0 + c_5 := by rw [e_x12_2, e_c_6]; exact Nat.mod_add_div _ _ have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_6 : c_6 ≤ 1 := by rw [e_c_6]; exact addc_carry_le_one _ _ _ b_x13_1 (by decide) b_c_5 clear e_x12_2 e_c_6 - clear_value s_5 x12_2 c_6 - have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl + -- x3_1: mul x3,x4,x10 have b_x3_1 : x3_1 < 2^64 := by rw [e_x3_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x3_1 - have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl + -- x13_2: adc x13,x9,x17 have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_2, b_k_x13_2, l_x13_2⟩ : ∃ k, k ≤ 1 ∧ x13_2 + 2^64 * k = x9 + x17_1 + c_6 := ⟨(x9 + x17_1 + c_6) / 2^64, addc_carry_le_one _ _ _ b_x9 (lt_of_lt_of_le b_x17_1 (by norm_num)) b_c_6, by rw [e_x13_2]; exact Nat.mod_add_div _ _⟩ clear e_x13_2 - clear_value x13_2 -- BEGIN round 0 -- Cancellation: the low limb of `x10 + p0 * x3` is zero, so `x10 + lo_x14` is -- `0` or `2^64`, and `subs xzr, x10, #1` set the carry exactly when it is `2^64`. @@ -250,117 +319,94 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul clear * - hc_0 d_x14 d_x15_1 l_x11_1 l_x12_1 l_x13_1 l_x10_1 l_x11_2 l_x12_2 sh_x17_1 l_x9 l_x13_2 hk_0 omega - clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 - b_x10_1 b_x11_2 b_x12_2 b_x13_2 b_x3 b_x3_1 e_x3_1 -- END round 0 - have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl + -- x15_2: mul x15,x6,x3 have b_x15_2 : x15_2 < 2^64 := by rw [e_x15_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x15_2 - have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl + -- x17_2: lsl x17,x3,#62 have b_x17_2 : x17_2 < 2^64 := by rw [e_x17_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x17_2 - have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + -- c_7: subs xzr,x10,#1 have b_c_7 : c_7 ≤ 1 := by rw [e_c_7]; exact subc_carry_le_one _ _ _ b_x10_1 have l_c_7 : (c_7 = 1 ∧ 1 + 1 ≤ x10_1 + 1) ∨ (c_7 = 0 ∧ x10_1 + 1 < 1 + 1) := subc_carry_cases _ _ _ _ e_c_7 b_x10_1 (by decide) (by decide) clear e_c_7 - clear_value c_7 + -- x14_1: umulh x14,x5,x3 have p_x14_1 : x5 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_1 - have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl have b_x14_1 : x14_1 < 2^64 := by rw [e_x14_1]; exact Nat.div_lt_of_lt_mul p_x14_1 obtain ⟨lo_x14_1, b_lo_x14_1, d_x14_1⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_1 = x5 * x3_1 := ⟨x5 * x3_1 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), by rw [e_x14_1]; exact Nat.mod_add_div _ _⟩ clear e_x14_1 - clear_value x14_1 - have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl - have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl + -- x11_3: adcs x11,x11,x15 have l_x11_3 : x11_3 + 2^64 * c_8 = x11_2 + x15_2 + c_7 := by rw [e_x11_3, e_c_8]; exact Nat.mod_add_div _ _ have b_x11_3 : x11_3 < 2^64 := by rw [e_x11_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_8 : c_8 ≤ 1 := by rw [e_c_8]; exact addc_carry_le_one _ _ _ b_x11_2 b_x15_2 b_c_7 clear e_x11_3 e_c_8 - clear_value s_6 x11_3 c_8 + -- x15_3: umulh x15,x6,x3 have p_x15_3 : x6 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_1 - have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl have b_x15_3 : x15_3 < 2^64 := by rw [e_x15_3]; exact Nat.div_lt_of_lt_mul p_x15_3 have d_x15_3 : x15_2 + 2^64 * x15_3 = x6 * x3_1 := by rw [e_x15_2, e_x15_3]; exact Nat.mod_add_div _ _ clear e_x15_2 e_x15_3 - clear_value x15_3 - have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl - have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl + -- x12_3: adcs x12,x12,xzr have l_x12_3 : x12_3 + 2^64 * c_9 = x12_2 + 0 + c_8 := by rw [e_x12_3, e_c_9]; exact Nat.mod_add_div _ _ have b_x12_3 : x12_3 < 2^64 := by rw [e_x12_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_9 : c_9 ≤ 1 := by rw [e_c_9]; exact addc_carry_le_one _ _ _ b_x12_2 (by decide) b_c_8 clear e_x12_3 e_c_9 - clear_value s_7 x12_3 c_9 - have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl - have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl + -- x13_3: adcs x13,x13,x17 have l_x13_3 : x13_3 + 2^64 * c_10 = x13_2 + x17_2 + c_9 := by rw [e_x13_3, e_c_10]; exact Nat.mod_add_div _ _ have b_x13_3 : x13_3 < 2^64 := by rw [e_x13_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_10 : c_10 ≤ 1 := by rw [e_c_10]; exact addc_carry_le_one _ _ _ b_x13_2 b_x17_2 b_c_9 clear e_x13_3 e_c_10 - clear_value s_8 x13_3 c_10 - have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl + -- x17_3: lsr x17,x3,#2 have b_x17_3 : x17_3 < 2^62 := by rw [e_x17_3]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_1 (by norm_num)) have sh_x17_3 : x17_2 + 2^64 * x17_3 = x3_1 * 2^62 := by rw [e_x17_2, e_x17_3]; exact lsl62_lsr2_split _ clear e_x17_2 e_x17_3 - clear_value x17_3 - have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl + -- x9_1: adc x9,xzr,xzr have b_x9_1 : x9_1 < 2^64 := by rw [e_x9_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_1, b_k_x9_1, l_x9_1⟩ : ∃ k, k ≤ 1 ∧ x9_1 + 2^64 * k = 0 + 0 + c_10 := ⟨(0 + 0 + c_10) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_10, by rw [e_x9_1]; exact Nat.mod_add_div _ _⟩ clear e_x9_1 - clear_value x9_1 - have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl - have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl + -- x10_2: adds x10,x11,x14 have l_x10_2 : x10_2 + 2^64 * c_11 = x11_3 + x14_1 + 0 := by rw [e_x10_2, e_c_11]; exact Nat.mod_add_div _ _ have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_11 : c_11 ≤ 1 := by rw [e_c_11]; exact addc_carry_le_one _ _ _ b_x11_3 b_x14_1 (by decide) clear e_x10_2 e_c_11 - clear_value s_9 x10_2 c_11 - have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl - have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl + -- x11_4: adcs x11,x12,x15 have l_x11_4 : x11_4 + 2^64 * c_12 = x12_3 + x15_3 + c_11 := by rw [e_x11_4, e_c_12]; exact Nat.mod_add_div _ _ have b_x11_4 : x11_4 < 2^64 := by rw [e_x11_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_12 : c_12 ≤ 1 := by rw [e_c_12]; exact addc_carry_le_one _ _ _ b_x12_3 b_x15_3 b_c_11 clear e_x11_4 e_c_12 - clear_value s_10 x11_4 c_12 - have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl - have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl + -- x12_4: adcs x12,x13,xzr have l_x12_4 : x12_4 + 2^64 * c_13 = x13_3 + 0 + c_12 := by rw [e_x12_4, e_c_13]; exact Nat.mod_add_div _ _ have b_x12_4 : x12_4 < 2^64 := by rw [e_x12_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_13 : c_13 ≤ 1 := by rw [e_c_13]; exact addc_carry_le_one _ _ _ b_x13_3 (by decide) b_c_12 clear e_x12_4 e_c_13 - clear_value s_11 x12_4 c_13 - have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl + -- x3_2: mul x3,x4,x10 have b_x3_2 : x3_2 < 2^64 := by rw [e_x3_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x3_2 - have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl + -- x13_4: adc x13,x9,x17 have b_x13_4 : x13_4 < 2^64 := by rw [e_x13_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_4, b_k_x13_4, l_x13_4⟩ : ∃ k, k ≤ 1 ∧ x13_4 + 2^64 * k = x9_1 + x17_3 + c_13 := ⟨(x9_1 + x17_3 + c_13) / 2^64, addc_carry_le_one _ _ _ b_x9_1 (lt_of_lt_of_le b_x17_3 (by norm_num)) b_c_13, by rw [e_x13_4]; exact Nat.mod_add_div _ _⟩ clear e_x13_4 - clear_value x13_4 -- BEGIN round 1 -- Cancellation: the low limb of `x10_1 + p0 * x3_1` is zero, so `x10_1 + lo_x14_1` is -- `0` or `2^64`, and `subs xzr, x10_1, #1` set the carry exactly when it is `2^64`. @@ -382,117 +428,94 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul clear * - hc_1 d_x14_1 d_x15_3 l_x11_3 l_x12_3 l_x13_3 l_x10_2 l_x11_4 l_x12_4 sh_x17_3 l_x9_1 l_x13_4 hk_1 omega - clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 - b_x10_2 b_x11_4 b_x12_4 b_x13_4 b_x3 b_x3_1 b_x3_2 e_x3_2 -- END round 1 - have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl + -- x15_4: mul x15,x6,x3 have b_x15_4 : x15_4 < 2^64 := by rw [e_x15_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x15_4 - have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl + -- x17_4: lsl x17,x3,#62 have b_x17_4 : x17_4 < 2^64 := by rw [e_x17_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x17_4 - have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + -- c_14: subs xzr,x10,#1 have b_c_14 : c_14 ≤ 1 := by rw [e_c_14]; exact subc_carry_le_one _ _ _ b_x10_2 have l_c_14 : (c_14 = 1 ∧ 1 + 1 ≤ x10_2 + 1) ∨ (c_14 = 0 ∧ x10_2 + 1 < 1 + 1) := subc_carry_cases _ _ _ _ e_c_14 b_x10_2 (by decide) (by decide) clear e_c_14 - clear_value c_14 + -- x14_2: umulh x14,x5,x3 have p_x14_2 : x5 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_2 - have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl have b_x14_2 : x14_2 < 2^64 := by rw [e_x14_2]; exact Nat.div_lt_of_lt_mul p_x14_2 obtain ⟨lo_x14_2, b_lo_x14_2, d_x14_2⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_2 = x5 * x3_2 := ⟨x5 * x3_2 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), by rw [e_x14_2]; exact Nat.mod_add_div _ _⟩ clear e_x14_2 - clear_value x14_2 - have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl - have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl + -- x11_5: adcs x11,x11,x15 have l_x11_5 : x11_5 + 2^64 * c_15 = x11_4 + x15_4 + c_14 := by rw [e_x11_5, e_c_15]; exact Nat.mod_add_div _ _ have b_x11_5 : x11_5 < 2^64 := by rw [e_x11_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_15 : c_15 ≤ 1 := by rw [e_c_15]; exact addc_carry_le_one _ _ _ b_x11_4 b_x15_4 b_c_14 clear e_x11_5 e_c_15 - clear_value s_12 x11_5 c_15 + -- x15_5: umulh x15,x6,x3 have p_x15_5 : x6 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_2 - have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl have b_x15_5 : x15_5 < 2^64 := by rw [e_x15_5]; exact Nat.div_lt_of_lt_mul p_x15_5 have d_x15_5 : x15_4 + 2^64 * x15_5 = x6 * x3_2 := by rw [e_x15_4, e_x15_5]; exact Nat.mod_add_div _ _ clear e_x15_4 e_x15_5 - clear_value x15_5 - have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl - have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl + -- x12_5: adcs x12,x12,xzr have l_x12_5 : x12_5 + 2^64 * c_16 = x12_4 + 0 + c_15 := by rw [e_x12_5, e_c_16]; exact Nat.mod_add_div _ _ have b_x12_5 : x12_5 < 2^64 := by rw [e_x12_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_16 : c_16 ≤ 1 := by rw [e_c_16]; exact addc_carry_le_one _ _ _ b_x12_4 (by decide) b_c_15 clear e_x12_5 e_c_16 - clear_value s_13 x12_5 c_16 - have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl - have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl + -- x13_5: adcs x13,x13,x17 have l_x13_5 : x13_5 + 2^64 * c_17 = x13_4 + x17_4 + c_16 := by rw [e_x13_5, e_c_17]; exact Nat.mod_add_div _ _ have b_x13_5 : x13_5 < 2^64 := by rw [e_x13_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_17 : c_17 ≤ 1 := by rw [e_c_17]; exact addc_carry_le_one _ _ _ b_x13_4 b_x17_4 b_c_16 clear e_x13_5 e_c_17 - clear_value s_14 x13_5 c_17 - have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl + -- x17_5: lsr x17,x3,#2 have b_x17_5 : x17_5 < 2^62 := by rw [e_x17_5]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_2 (by norm_num)) have sh_x17_5 : x17_4 + 2^64 * x17_5 = x3_2 * 2^62 := by rw [e_x17_4, e_x17_5]; exact lsl62_lsr2_split _ clear e_x17_4 e_x17_5 - clear_value x17_5 - have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl + -- x9_2: adc x9,xzr,xzr have b_x9_2 : x9_2 < 2^64 := by rw [e_x9_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_2, b_k_x9_2, l_x9_2⟩ : ∃ k, k ≤ 1 ∧ x9_2 + 2^64 * k = 0 + 0 + c_17 := ⟨(0 + 0 + c_17) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_17, by rw [e_x9_2]; exact Nat.mod_add_div _ _⟩ clear e_x9_2 - clear_value x9_2 - have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl - have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl + -- x10_3: adds x10,x11,x14 have l_x10_3 : x10_3 + 2^64 * c_18 = x11_5 + x14_2 + 0 := by rw [e_x10_3, e_c_18]; exact Nat.mod_add_div _ _ have b_x10_3 : x10_3 < 2^64 := by rw [e_x10_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_18 : c_18 ≤ 1 := by rw [e_c_18]; exact addc_carry_le_one _ _ _ b_x11_5 b_x14_2 (by decide) clear e_x10_3 e_c_18 - clear_value s_15 x10_3 c_18 - have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl - have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl + -- x11_6: adcs x11,x12,x15 have l_x11_6 : x11_6 + 2^64 * c_19 = x12_5 + x15_5 + c_18 := by rw [e_x11_6, e_c_19]; exact Nat.mod_add_div _ _ have b_x11_6 : x11_6 < 2^64 := by rw [e_x11_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_19 : c_19 ≤ 1 := by rw [e_c_19]; exact addc_carry_le_one _ _ _ b_x12_5 b_x15_5 b_c_18 clear e_x11_6 e_c_19 - clear_value s_16 x11_6 c_19 - have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl - have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl + -- x12_6: adcs x12,x13,xzr have l_x12_6 : x12_6 + 2^64 * c_20 = x13_5 + 0 + c_19 := by rw [e_x12_6, e_c_20]; exact Nat.mod_add_div _ _ have b_x12_6 : x12_6 < 2^64 := by rw [e_x12_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_20 : c_20 ≤ 1 := by rw [e_c_20]; exact addc_carry_le_one _ _ _ b_x13_5 (by decide) b_c_19 clear e_x12_6 e_c_20 - clear_value s_17 x12_6 c_20 - have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl + -- x3_3: mul x3,x4,x10 have b_x3_3 : x3_3 < 2^64 := by rw [e_x3_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x3_3 - have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl + -- x13_6: adc x13,x9,x17 have b_x13_6 : x13_6 < 2^64 := by rw [e_x13_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_6, b_k_x13_6, l_x13_6⟩ : ∃ k, k ≤ 1 ∧ x13_6 + 2^64 * k = x9_2 + x17_5 + c_20 := ⟨(x9_2 + x17_5 + c_20) / 2^64, addc_carry_le_one _ _ _ b_x9_2 (lt_of_lt_of_le b_x17_5 (by norm_num)) b_c_20, by rw [e_x13_6]; exact Nat.mod_add_div _ _⟩ clear e_x13_6 - clear_value x13_6 -- BEGIN round 2 -- Cancellation: the low limb of `x10_2 + p0 * x3_2` is zero, so `x10_2 + lo_x14_2` is -- `0` or `2^64`, and `subs xzr, x10_2, #1` set the carry exactly when it is `2^64`. @@ -514,114 +537,92 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul clear * - hc_2 d_x14_2 d_x15_5 l_x11_5 l_x12_5 l_x13_5 l_x10_3 l_x11_6 l_x12_6 sh_x17_5 l_x9_2 l_x13_6 hk_2 omega - clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 - I_2 b_x10_3 b_x11_6 b_x12_6 b_x13_6 b_x3 b_x3_1 b_x3_2 b_x3_3 e_x3_3 -- END round 2 - have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl + -- x15_6: mul x15,x6,x3 have b_x15_6 : x15_6 < 2^64 := by rw [e_x15_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x15_6 - have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl + -- x17_6: lsl x17,x3,#62 have b_x17_6 : x17_6 < 2^64 := by rw [e_x17_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) - clear_value x17_6 - have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + -- c_21: subs xzr,x10,#1 have b_c_21 : c_21 ≤ 1 := by rw [e_c_21]; exact subc_carry_le_one _ _ _ b_x10_3 have l_c_21 : (c_21 = 1 ∧ 1 + 1 ≤ x10_3 + 1) ∨ (c_21 = 0 ∧ x10_3 + 1 < 1 + 1) := subc_carry_cases _ _ _ _ e_c_21 b_x10_3 (by decide) (by decide) clear e_c_21 - clear_value c_21 + -- x14_3: umulh x14,x5,x3 have p_x14_3 : x5 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_3 - have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl have b_x14_3 : x14_3 < 2^64 := by rw [e_x14_3]; exact Nat.div_lt_of_lt_mul p_x14_3 obtain ⟨lo_x14_3, b_lo_x14_3, d_x14_3⟩ : ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_3 = x5 * x3_3 := ⟨x5 * x3_3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), by rw [e_x14_3]; exact Nat.mod_add_div _ _⟩ clear e_x14_3 - clear_value x14_3 - have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl - have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl + -- x11_7: adcs x11,x11,x15 have l_x11_7 : x11_7 + 2^64 * c_22 = x11_6 + x15_6 + c_21 := by rw [e_x11_7, e_c_22]; exact Nat.mod_add_div _ _ have b_x11_7 : x11_7 < 2^64 := by rw [e_x11_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_22 : c_22 ≤ 1 := by rw [e_c_22]; exact addc_carry_le_one _ _ _ b_x11_6 b_x15_6 b_c_21 clear e_x11_7 e_c_22 - clear_value s_18 x11_7 c_22 + -- x15_7: umulh x15,x6,x3 have p_x15_7 : x6 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_3 - have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl have b_x15_7 : x15_7 < 2^64 := by rw [e_x15_7]; exact Nat.div_lt_of_lt_mul p_x15_7 have d_x15_7 : x15_6 + 2^64 * x15_7 = x6 * x3_3 := by rw [e_x15_6, e_x15_7]; exact Nat.mod_add_div _ _ clear e_x15_6 e_x15_7 - clear_value x15_7 - have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl - have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl + -- x12_7: adcs x12,x12,xzr have l_x12_7 : x12_7 + 2^64 * c_23 = x12_6 + 0 + c_22 := by rw [e_x12_7, e_c_23]; exact Nat.mod_add_div _ _ have b_x12_7 : x12_7 < 2^64 := by rw [e_x12_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_23 : c_23 ≤ 1 := by rw [e_c_23]; exact addc_carry_le_one _ _ _ b_x12_6 (by decide) b_c_22 clear e_x12_7 e_c_23 - clear_value s_19 x12_7 c_23 - have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl - have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl + -- x13_7: adcs x13,x13,x17 have l_x13_7 : x13_7 + 2^64 * c_24 = x13_6 + x17_6 + c_23 := by rw [e_x13_7, e_c_24]; exact Nat.mod_add_div _ _ have b_x13_7 : x13_7 < 2^64 := by rw [e_x13_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_24 : c_24 ≤ 1 := by rw [e_c_24]; exact addc_carry_le_one _ _ _ b_x13_6 b_x17_6 b_c_23 clear e_x13_7 e_c_24 - clear_value s_20 x13_7 c_24 - have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl + -- x17_7: lsr x17,x3,#2 have b_x17_7 : x17_7 < 2^62 := by rw [e_x17_7]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_3 (by norm_num)) have sh_x17_7 : x17_6 + 2^64 * x17_7 = x3_3 * 2^62 := by rw [e_x17_6, e_x17_7]; exact lsl62_lsr2_split _ clear e_x17_6 e_x17_7 - clear_value x17_7 - have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl + -- x9_3: adc x9,xzr,xzr have b_x9_3 : x9_3 < 2^64 := by rw [e_x9_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_3, b_k_x9_3, l_x9_3⟩ : ∃ k, k ≤ 1 ∧ x9_3 + 2^64 * k = 0 + 0 + c_24 := ⟨(0 + 0 + c_24) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_24, by rw [e_x9_3]; exact Nat.mod_add_div _ _⟩ clear e_x9_3 - clear_value x9_3 - have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl - have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl + -- x10_4: adds x10,x11,x14 have l_x10_4 : x10_4 + 2^64 * c_25 = x11_7 + x14_3 + 0 := by rw [e_x10_4, e_c_25]; exact Nat.mod_add_div _ _ have b_x10_4 : x10_4 < 2^64 := by rw [e_x10_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_25 : c_25 ≤ 1 := by rw [e_c_25]; exact addc_carry_le_one _ _ _ b_x11_7 b_x14_3 (by decide) clear e_x10_4 e_c_25 - clear_value s_21 x10_4 c_25 - have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl - have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl + -- x11_8: adcs x11,x12,x15 have l_x11_8 : x11_8 + 2^64 * c_26 = x12_7 + x15_7 + c_25 := by rw [e_x11_8, e_c_26]; exact Nat.mod_add_div _ _ have b_x11_8 : x11_8 < 2^64 := by rw [e_x11_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_26 : c_26 ≤ 1 := by rw [e_c_26]; exact addc_carry_le_one _ _ _ b_x12_7 b_x15_7 b_c_25 clear e_x11_8 e_c_26 - clear_value s_22 x11_8 c_26 - have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl - have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl + -- x12_8: adcs x12,x13,xzr have l_x12_8 : x12_8 + 2^64 * c_27 = x13_7 + 0 + c_26 := by rw [e_x12_8, e_c_27]; exact Nat.mod_add_div _ _ have b_x12_8 : x12_8 < 2^64 := by rw [e_x12_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_27 : c_27 ≤ 1 := by rw [e_c_27]; exact addc_carry_le_one _ _ _ b_x13_7 (by decide) b_c_26 clear e_x12_8 e_c_27 - clear_value s_23 x12_8 c_27 - have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl + -- x13_8: adc x13,x9,x17 have b_x13_8 : x13_8 < 2^64 := by rw [e_x13_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_8, b_k_x13_8, l_x13_8⟩ : ∃ k, k ≤ 1 ∧ x13_8 + 2^64 * k = x9_3 + x17_7 + c_27 := ⟨(x9_3 + x17_7 + c_27) / 2^64, addc_carry_le_one _ _ _ b_x9_3 (lt_of_lt_of_le b_x17_7 (by norm_num)) b_c_27, by rw [e_x13_8]; exact Nat.mod_add_div _ _⟩ clear e_x13_8 - clear_value x13_8 -- BEGIN round 3 -- Cancellation: the low limb of `x10_3 + p0 * x3_3` is zero, so `x10_3 + lo_x14_3` is -- `0` or `2^64`, and `subs xzr, x10_3, #1` set the carry exactly when it is `2^64`. @@ -643,8 +644,6 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul clear * - hc_3 d_x14_3 d_x15_7 l_x11_7 l_x12_7 l_x13_7 l_x10_4 l_x11_8 l_x12_8 sh_x17_7 l_x9_3 l_x13_8 hk_3 omega - clear * - ht hm hshape hinv hinv_lt e_x4 e_x5 e_x6 b_x4 b_x5 b_x6 e_x10 e_x11 e_x12 e_x13 I_0 I_1 - I_2 I_3 b_x10_4 b_x11_8 b_x12_8 b_x13_8 b_x3 b_x3_1 b_x3_2 b_x3_3 -- END round 3 -- BEGIN conclusion subst e_x5 e_x6 @@ -689,45 +688,63 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) x16 c_2 s_3 x17 c_3 x10_2 x11_2 x12_2 x13_2 out0 out1 out2 out3 at hr subst hr have e_x3 : x3 = inv := rfl - have b_x3 : x3 < 2^64 := by rw [e_x3]; exact hinv_lt - clear_value x3 have e_x4 : x4 = x3 := rfl - have b_x4 : x4 < 2^64 := by rw [e_x4]; exact b_x3 - clear_value x4 have e_x10 : x10 = value.l0 := rfl - have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hv.1 - clear_value x10 have e_x11 : x11 = value.l1 := rfl - have b_x11 : x11 < 2^64 := by rw [e_x11]; exact hv.2.1 - clear_value x11 have e_x12 : x12 = value.l2 := rfl - have b_x12 : x12 < 2^64 := by rw [e_x12]; exact hv.2.2.1 - clear_value x12 have e_x13 : x13 = value.l3 := rfl - have b_x13 : x13 < 2^64 := by rw [e_x13]; exact hv.2.2.2 - clear_value x13 have e_r : r = mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 := rfl - clear_value r have e_x10_1 : x10_1 = r.l0 := rfl - clear_value x10_1 have e_x11_1 : x11_1 = r.l1 := rfl - clear_value x11_1 have e_x12_1 : x12_1 = r.l2 := rfl - clear_value x12_1 have e_x13_1 : x13_1 = r.l3 := rfl - clear_value x13_1 have e_x5 : x5 = modulus.l0 := rfl - have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 - clear_value x5 have e_x6 : x6 = modulus.l1 := rfl - have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 - clear_value x6 have e_x7 : x7 = modulus.l2 := rfl - have b_x7 : x7 < 2^64 := by rw [e_x7]; exact hm.2.2.1 - clear_value x7 have e_x8 : x8 = modulus.l3 := rfl + have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl + have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl + have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl + have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl + have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl + have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl + have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl + have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl + have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl + have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl + have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl + have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl + have e_out0 : out0 = x10_2 := rfl + have e_out1 : out1 = x11_2 := rfl + have e_out2 : out2 = x12_2 := rfl + have e_out3 : out3 = x13_2 := rfl + clear_value out3 out2 out1 out0 x13_2 x12_2 x11_2 x10_2 c_3 x17 s_3 c_2 x16 s_2 c_1 x15 s_1 c x14 + s x8 x7 x6 x5 x13_1 x12_1 x11_1 x10_1 r x13 x12 x11 x10 x4 x3 + -- x3: argument + have b_x3 : x3 < 2^64 := by rw [e_x3]; exact hinv_lt + -- x4: mov x4,x3 + have b_x4 : x4 < 2^64 := by rw [e_x4]; exact b_x3 + -- x10: ldp x10,x11,[x1] + have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hv.1 + -- x11: ldp x10,x11,[x1] + have b_x11 : x11 < 2^64 := by rw [e_x11]; exact hv.2.1 + -- x12: ldp x12,x13,[x1,#16] + have b_x12 : x12 < 2^64 := by rw [e_x12]; exact hv.2.2.1 + -- x13: ldp x12,x13,[x1,#16] + have b_x13 : x13 < 2^64 := by rw [e_x13]; exact hv.2.2.2 + -- r: bl L$pasta_curves_mul_by_1_mont_pasta + -- x10_1: helper output + -- x11_1: helper output + -- x12_1: helper output + -- x13_1: helper output + -- x5: loaded by the helper + have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 + -- x6: loaded by the helper + have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 + -- x7: loaded by the helper + have b_x7 : x7 < 2^64 := by rw [e_x7]; exact hm.2.2.1 + -- x8: loaded by the helper have b_x8 : x8 < 2^64 := by rw [e_x8]; exact hm.2.2.2 - clear_value x8 -- BEGIN helper -- The helper's contract on `t = value`: its result limbs are bounded, and `2^256 * r = t + Q * p` -- for some `Q < 2^256`. @@ -741,66 +758,50 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) (by rw [e_x4, e_x3]; exact hinv) _ e_r clear e_r e_x10_1 e_x11_1 e_x12_1 e_x13_1 -- END helper - have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl - have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl + -- x14: subs x14,x10,x5 have l_x14 : x14 + 2^64 * c + x5 + 1 = x10_1 + 2^64 + 1 := by rw [e_x14, e_c]; exact subc_lin _ _ _ b_x5 (by decide) have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c : c ≤ 1 := by rw [e_c]; exact subc_carry_le_one _ _ _ b_x10_1 clear e_x14 e_c - clear_value s x14 c - have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl - have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl + -- x15: sbcs x15,x11,x6 have l_x15 : x15 + 2^64 * c_1 + x6 + 1 = x11_1 + 2^64 + c := by rw [e_x15, e_c_1]; exact subc_lin _ _ _ b_x6 b_c have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_1 : c_1 ≤ 1 := by rw [e_c_1]; exact subc_carry_le_one _ _ _ b_x11_1 clear e_x15 e_c_1 - clear_value s_1 x15 c_1 - have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl - have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl + -- x16: sbcs x16,x12,x7 have l_x16 : x16 + 2^64 * c_2 + x7 + 1 = x12_1 + 2^64 + c_1 := by rw [e_x16, e_c_2]; exact subc_lin _ _ _ b_x7 b_c_1 have b_x16 : x16 < 2^64 := by rw [e_x16]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_2 : c_2 ≤ 1 := by rw [e_c_2]; exact subc_carry_le_one _ _ _ b_x12_1 clear e_x16 e_c_2 - clear_value s_2 x16 c_2 - have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl - have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl + -- x17: sbcs x17,x13,x8 have l_x17 : x17 + 2^64 * c_3 + x8 + 1 = x13_1 + 2^64 + c_2 := by rw [e_x17, e_c_3]; exact subc_lin _ _ _ b_x8 b_c_2 have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_3 : c_3 ≤ 1 := by rw [e_c_3]; exact subc_carry_le_one _ _ _ b_x13_1 clear e_x17 e_c_3 - clear_value s_3 x17 c_3 - have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl + -- x10_2: csel x10,x10,x14,lo have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; split <;> first | exact b_x10_1 | exact b_x14 - clear_value x10_2 - have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl + -- x11_2: csel x11,x11,x15,lo have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; split <;> first | exact b_x11_1 | exact b_x15 - clear_value x11_2 - have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl + -- x12_2: csel x12,x12,x16,lo have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; split <;> first | exact b_x12_1 | exact b_x16 - clear_value x12_2 - have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl + -- x13_2: csel x13,x13,x17,lo have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; split <;> first | exact b_x13_1 | exact b_x17 - clear_value x13_2 - have e_out0 : out0 = x10_2 := rfl - clear_value out0 - have e_out1 : out1 = x11_2 := rfl - clear_value out1 - have e_out2 : out2 = x12_2 := rfl - clear_value out2 - have e_out3 : out3 = x13_2 := rfl - clear_value out3 + -- out0: stp x10,x11,[x0] + -- out1: stp x10,x11,[x0] + -- out2: stp x12,x13,[x0,#16] + -- out3: stp x12,x13,[x0,#16] -- BEGIN conclusion subst out0 out1 out2 out3 have hV : value.toNat = x10 + 2^64 * x11 + 2^128 * x12 + 2^192 * x13 := by diff --git a/scripts/gen_aarch64_pasta_mul.py b/scripts/gen_aarch64_pasta_mul.py index 1790632..4c16375 100755 --- a/scripts/gen_aarch64_pasta_mul.py +++ b/scripts/gen_aarch64_pasta_mul.py @@ -478,11 +478,17 @@ def wrap_tactic(head, words, tail, indent=" "): def skeleton(routine): """The generated part of the correctness proof of `routine`: unfold, extract the lets under - SSA names, then per instruction the defining equation (by `rfl`, in `%`/`/` form), the linear - facts derived from it, and `clear_value`. Each derived fact is an instance of one lemma - (`Nat.mod_add_div`, `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, or a carry lemma from the spec - file's preamble), so a step costs nothing wherever it sits and names the facts it rests on; - `omega` is left to the hand-written annotations between the groups.""" + SSA names, record every instruction's defining equation (by `rfl`, in `%`/`/` form), make + all the locals opaque, then per instruction derive the linear facts from its equation and + clear the equation. Each derived fact is an instance of one lemma (`Nat.mod_add_div`, + `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, or a carry lemma from the spec file's preamble), so a + step costs nothing wherever it sits and names the facts it rests on; `omega` is left to the + hand-written annotations, which go after the facts of the group whose marker + (`-- : `) names the register they need. + + The values are cleared in one `clear_value`, last local first: clearing a local reverts + every later local whose value mentions it, so one call per local is quadratic in the length + of the chain, and the multiplication routine's chain of 380 locals took over a minute.""" e = routine.emitter live = e.liveness(routine.result_names) entries = [en for en, keep in zip(e.entries, live) if keep] @@ -495,6 +501,8 @@ def skeleton(routine): out += wrap_tactic("extract_lets", names, " at hr") out.append(" subst hr") products, shifts = {}, {} + eqs = [] # the `have e_… := rfl` lines, emitted before the single `clear_value` + facts = [] # the derived-fact lines, per group, emitted after it def r(op): # operand as written in the entry, renamed to its SSA name at that point return ren.get(op, op) @@ -509,41 +517,46 @@ def lt64(op): # a proof that the operand is below 2^64 def le1(op): # a proof that the carry operand is at most 1 return "(by decide)" if re.fullmatch(r"[0-9]+", op) else bnd[op] + def eq(nm, rhs): + eqs.append(f" have e_{nm} : {nm} = {rhs} := rfl") + i = 0 while i < len(entries): en, nm = entries[i], names[i] kind, *ops = en["fact"] ops = [r(o) if isinstance(o, str) else o for o in ops] - group = [nm] - lines = [] + # The group's marker: the register it writes, then the instruction. Annotation blocks + # are placed after the group they name. + label = names[i + 1] if kind in ("adds", "subs") else nm + lines = [f" -- {label}: {en['comment']}"] # Every step records only facts `omega` handles cheaply later: linear equations, bounds, # and at most a disjunction. The `%`/`/` equations are derived by `rfl`, used to prove # those facts, and cleared. if kind == "load": arg, idx = ops hyp = BOUND_HYPS[arg] - lines.append(f" have e_{nm} : {nm} = {arg}.l{idx} := rfl") + eq(nm, f"{arg}.l{idx}") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {hyp}.{PROJ[idx]}") bnd[nm] = f"b_{nm}" elif kind == "inv": - lines.append(f" have e_{nm} : {nm} = inv := rfl") + eq(nm, "inv") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {INV_BOUND_HYP}") bnd[nm] = f"b_{nm}" elif kind == "mov": (a,) = ops - lines.append(f" have e_{nm} : {nm} = {a} := rfl") + eq(nm, a) lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact {lt64(a)}") bnd[nm] = f"b_{nm}" elif kind == "mul": a, b = ops - lines.append(f" have e_{nm} : {nm} = {a} * {b} % 2^64 := rfl") + eq(nm, f"{a} * {b} % 2^64") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") bnd[nm] = f"b_{nm}" products[(a, b)] = nm # its `%` equation is cleared at the matching `umulh` elif kind == "umulh": a, b = ops + eq(nm, f"{a} * {b} / 2^64") lines.append(f" have p_{nm} : {a} * {b} < 2^64 * 2^64 := Nat.mul_lt_mul'' {lt64(a)} {lt64(b)}") - lines.append(f" have e_{nm} : {nm} = {a} * {b} / 2^64 := rfl") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.div_lt_of_lt_mul p_{nm}") bnd[nm] = f"b_{nm}" if (a, b) in products: @@ -561,13 +574,13 @@ def le1(op): # a proof that the carry operand is at most 1 lines.append(f" clear e_{nm}") elif kind == "lsl": a, k = ops - lines.append(f" have e_{nm} : {nm} = {a} * 2^{k} % 2^64 := rfl") + eq(nm, f"{a} * 2^{k} % 2^64") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") bnd[nm] = f"b_{nm}" shifts[(a, k)] = nm elif kind == "lsr": a, k = ops - lines.append(f" have e_{nm} : {nm} = {a} / 2^{k} := rfl") + eq(nm, f"{a} / 2^{k}") lines.append(f" have b_{nm} : {nm} < 2^{64 - k} := by") lines.append(f" rw [e_{nm}]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq {lt64(a)} (by norm_num))") bnd[nm] = f"b_{nm}" @@ -582,7 +595,6 @@ def le1(op): # a proof that the carry operand is at most 1 elif kind in ("adds", "subs"): a, b, cin = ops xn, cn = names[i + 1], names[i + 2] - group += [xn, cn] if kind == "adds": val = f"({a} + {b} + {cin})" lin = f"{xn} + 2^64 * {cn} = {a} + {b} + {cin}" @@ -593,8 +605,8 @@ def le1(op): # a proof that the carry operand is at most 1 lin = f"{xn} + 2^64 * {cn} + {b} + 1 = {a} + 2^64 + {cin}" lin_proof = f"subc_lin _ _ _ {lt64(b)} {le1(cin)}" carry_proof = f"subc_carry_le_one _ _ _ {lt64(a)}" - lines.append(f" have e_{xn} : {xn} = {val} % 2^64 := rfl") - lines.append(f" have e_{cn} : {cn} = {val} / 2^64 := rfl") + eq(xn, f"{val} % 2^64") + eq(cn, f"{val} / 2^64") lines.append(f" have l_{xn} : {lin} := by") lines.append(f" rw [e_{xn}, e_{cn}]; exact {lin_proof}") lines.append(f" have b_{xn} : {xn} < 2^64 := by rw [e_{xn}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") @@ -607,7 +619,7 @@ def le1(op): # a proof that the carry operand is at most 1 i += 2 elif kind == "adc": a, b, cin = ops - lines.append(f" have e_{nm} : {nm} = ({a} + {b} + {cin}) % 2^64 := rfl") + eq(nm, f"({a} + {b} + {cin}) % 2^64") lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") lines.append(f" obtain ⟨k_{nm}, b_k_{nm}, l_{nm}⟩ :") lines.append(f" ∃ k, k ≤ 1 ∧ {nm} + 2^64 * k = {a} + {b} + {cin} :=") @@ -617,7 +629,7 @@ def le1(op): # a proof that the carry operand is at most 1 bnd[nm] = f"b_{nm}" elif kind == "subs_carry": a, b, cin = ops - lines.append(f" have e_{nm} : {nm} = ({a} + 2^64 - {b} - (1 - {cin})) / 2^64 := rfl") + eq(nm, f"({a} + 2^64 - {b} - (1 - {cin})) / 2^64") lines.append(f" have b_{nm} : {nm} ≤ 1 := by rw [e_{nm}]; exact subc_carry_le_one _ _ _ {lt64(a)}") lines.append(f" have l_{nm} : ({nm} = 1 ∧ {b} + 1 ≤ {a} + {cin}) ∨ ({nm} = 0 ∧ {a} + {cin} < {b} + 1) :=") lines.append(f" subc_carry_cases _ _ _ _ e_{nm} {lt64(a)} {lt64(b)} {le1(cin)}") @@ -625,26 +637,28 @@ def le1(op): # a proof that the carry operand is at most 1 bnd[nm] = f"b_{nm}" elif kind == "csel": c, a, b = ops - lines.append(f" have e_{nm} : {nm} = (if {c} = 0 then {a} else {b}) := rfl") + eq(nm, f"(if {c} = 0 then {a} else {b})") lines.append(f" have b_{nm} : {nm} < 2^64 := by") lines.append(f" rw [e_{nm}]; split <;> first | exact {lt64(a)} | exact {lt64(b)}") bnd[nm] = f"b_{nm}" elif kind == "call": *targs, inv = ops - lines.append(f" have e_{nm} : {nm} = mulBy1 ⟨{', '.join(targs)}⟩ modulus {inv} := rfl") + eq(nm, f"mulBy1 ⟨{', '.join(targs)}⟩ modulus {inv}") elif kind == "callout": (idx,) = ops - lines.append(f" have e_{nm} : {nm} = {r('r')}.l{idx} := rfl") + eq(nm, f"{r('r')}.l{idx}") bnd[nm] = f"b_{nm}" # supplied by the annotation that applies the callee's theorem elif kind == "out": (x,) = ops - lines.append(f" have e_{nm} : {nm} = {x} := rfl") + eq(nm, x) else: raise ValueError(kind) ren[en["name"]] = nm - out += lines - out.append(f" clear_value {' '.join(group)}") + facts += lines i += 1 + out += eqs + out += wrap_tactic("clear_value", list(reversed(names)), "") + out += facts return out def check_spec(path, routines): From bbc7a9ed37a47730dc97e848d9fc7c23b938cc25 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 22:36:08 +0100 Subject: [PATCH 8/9] asm: extract each instruction's lets from the folded hypothesis The generated skeleton unfolds the routine in the hypothesis that names its result and then, instruction by instruction, extracts that instruction's lets from it (`extract_lets +onlyGivenNames`), records their defining equations, clears their values, and derives the facts. With every let extracted up front, each `clear_value` reverted and re-checked all the later locals and equations, which is quadratic in the length of the chain and exhausted the heartbeat budget on the multiplication routine's 264 locals; with the rest of the chain still folded in the hypothesis, a clear reverts one small equation and one hypothesis. The carry lemmas are applied with their operands explicit, since a literal operand left as a placeholder is not inferred. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 559 ++++++++++++++------- scripts/gen_aarch64_pasta_mul.py | 57 ++- 2 files changed, 395 insertions(+), 221 deletions(-) diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean index b5c9427..b293c8f 100644 --- a/CompElliptic/Asm/AArch64/PastaMulSpec.lean +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -14,10 +14,11 @@ import Mathlib.Tactic.ClearExcept # Correctness of the transcribed Pasta Montgomery routines Each theorem here is proved over the transcription in `PastaMul.lean`, instruction by -instruction. The proof of a routine begins by unfolding it and extracting its `let`s under -unique names; then, for every instruction, the defining equation of its result (by `rfl`, in -`%`/`/` form) and the linear facts that follow from it (each an instance of one lemma) are -recorded and the local's value is cleared. Those lines are generated by +instruction. The proof of a routine begins by unfolding it in the hypothesis that names its +result; then, for every instruction, its `let`s are extracted from that hypothesis under unique +names, the defining equation of its result (by `rfl`, in `%`/`/` form) and the linear facts that +follow from it (each an instance of one lemma) are recorded, and the locals' values are cleared. +Those lines are generated by `scripts/gen_aarch64_pasta_mul.py --skeleton ` and must not be edited; the hand-written parts are the theorem statements and the `-- BEGIN ... -- END` blocks, which supply what the instruction stream alone does not: the Montgomery round invariants where they @@ -89,138 +90,68 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul -- generated skeleton for `mulBy1`: do not edit between the annotations unfold mulBy1 at hr lift_lets at hr - extract_lets x10 x11 x12 x13 x4 x3 x5 x6 x15 x17 c x14 s x11_1 c_1 x15_1 s_1 x12_1 c_2 s_2 x13_1 - c_3 x17_1 x9 s_3 x10_1 c_4 s_4 x11_2 c_5 s_5 x12_2 c_6 x3_1 x13_2 x15_2 x17_2 c_7 x14_1 s_6 - x11_3 c_8 x15_3 s_7 x12_3 c_9 s_8 x13_3 c_10 x17_3 x9_1 s_9 x10_2 c_11 s_10 x11_4 c_12 s_11 - x12_4 c_13 x3_2 x13_4 x15_4 x17_4 c_14 x14_2 s_12 x11_5 c_15 x15_5 s_13 x12_5 c_16 s_14 x13_5 - c_17 x17_5 x9_2 s_15 x10_3 c_18 s_16 x11_6 c_19 s_17 x12_6 c_20 x3_3 x13_6 x15_6 x17_6 c_21 - x14_3 s_18 x11_7 c_22 x15_7 s_19 x12_7 c_23 s_20 x13_7 c_24 x17_7 x9_3 s_21 x10_4 c_25 s_22 - x11_8 c_26 s_23 x12_8 c_27 x13_8 at hr - subst hr - have e_x10 : x10 = t.l0 := rfl - have e_x11 : x11 = t.l1 := rfl - have e_x12 : x12 = t.l2 := rfl - have e_x13 : x13 = t.l3 := rfl - have e_x4 : x4 = inv := rfl - have e_x3 : x3 = x4 * x10 % 2^64 := rfl - have e_x5 : x5 = modulus.l0 := rfl - have e_x6 : x6 = modulus.l1 := rfl - have e_x15 : x15 = x6 * x3 % 2^64 := rfl - have e_x17 : x17 = x3 * 2^62 % 2^64 := rfl - have e_c : c = (x10 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have e_x14 : x14 = x5 * x3 / 2^64 := rfl - have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl - have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl - have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl - have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl - have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl - have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl - have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl - have e_x17_1 : x17_1 = x3 / 2^2 := rfl - have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl - have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl - have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl - have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl - have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl - have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl - have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl - have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl - have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl - have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl - have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl - have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl - have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl - have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl - have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl - have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl - have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl - have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl - have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl - have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl - have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl - have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl - have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl - have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl - have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl - have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl - have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl - have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl - have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl - have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl - have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl - have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl - have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl - have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl - have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl - have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl - have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl - have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl - have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl - have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl - have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl - have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl - have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl - have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl - have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl - have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl - have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl - have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl - have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl - have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl - have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl - have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl - have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl - have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl - have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl - have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl - have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl - have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl - have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl - have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl - have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl - have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl - have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl - have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl - have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl - have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl - have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl - have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl - have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl - clear_value x13_8 c_27 x12_8 s_23 c_26 x11_8 s_22 c_25 x10_4 s_21 x9_3 x17_7 c_24 x13_7 s_20 c_23 - x12_7 s_19 x15_7 c_22 x11_7 s_18 x14_3 c_21 x17_6 x15_6 x13_6 x3_3 c_20 x12_6 s_17 c_19 x11_6 - s_16 c_18 x10_3 s_15 x9_2 x17_5 c_17 x13_5 s_14 c_16 x12_5 s_13 x15_5 c_15 x11_5 s_12 x14_2 - c_14 x17_4 x15_4 x13_4 x3_2 c_13 x12_4 s_11 c_12 x11_4 s_10 c_11 x10_2 s_9 x9_1 x17_3 c_10 - x13_3 s_8 c_9 x12_3 s_7 x15_3 c_8 x11_3 s_6 x14_1 c_7 x17_2 x15_2 x13_2 x3_1 c_6 x12_2 s_5 c_5 - x11_2 s_4 c_4 x10_1 s_3 x9 x17_1 c_3 x13_1 s_2 c_2 x12_1 s_1 x15_1 c_1 x11_1 s x14 c x17 x15 - x6 x5 x3 x4 x13 x12 x11 x10 -- x10: argument + extract_lets +onlyGivenNames x10 at hr + have e_x10 : x10 = t.l0 := rfl + clear_value x10 have b_x10 : x10 < 2^64 := by rw [e_x10]; exact ht.1 -- x11: argument + extract_lets +onlyGivenNames x11 at hr + have e_x11 : x11 = t.l1 := rfl + clear_value x11 have b_x11 : x11 < 2^64 := by rw [e_x11]; exact ht.2.1 -- x12: argument + extract_lets +onlyGivenNames x12 at hr + have e_x12 : x12 = t.l2 := rfl + clear_value x12 have b_x12 : x12 < 2^64 := by rw [e_x12]; exact ht.2.2.1 -- x13: argument + extract_lets +onlyGivenNames x13 at hr + have e_x13 : x13 = t.l3 := rfl + clear_value x13 have b_x13 : x13 < 2^64 := by rw [e_x13]; exact ht.2.2.2 -- x4: argument + extract_lets +onlyGivenNames x4 at hr + have e_x4 : x4 = inv := rfl + clear_value x4 have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt -- x3: mul x3,x4,x10 + extract_lets +onlyGivenNames x3 at hr + have e_x3 : x3 = x4 * x10 % 2^64 := rfl + clear_value x3 have b_x3 : x3 < 2^64 := by rw [e_x3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x5: ldp x5,x6,[x2] + extract_lets +onlyGivenNames x5 at hr + have e_x5 : x5 = modulus.l0 := rfl + clear_value x5 have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 -- x6: ldp x5,x6,[x2] + extract_lets +onlyGivenNames x6 at hr + have e_x6 : x6 = modulus.l1 := rfl + clear_value x6 have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 -- x15: mul x15,x6,x3 + extract_lets +onlyGivenNames x15 at hr + have e_x15 : x15 = x6 * x3 % 2^64 := rfl + clear_value x15 have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x17: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17 at hr + have e_x17 : x17 = x3 * 2^62 % 2^64 := rfl + clear_value x17 have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- c: subs xzr,x10,#1 - have b_c : c ≤ 1 := by rw [e_c]; exact subc_carry_le_one _ _ _ b_x10 + extract_lets +onlyGivenNames c at hr + have e_c : c = (x10 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c + have b_c : c ≤ 1 := by rw [e_c]; exact subc_carry_le_one x10 1 1 b_x10 have l_c : (c = 1 ∧ 1 + 1 ≤ x10 + 1) ∨ (c = 0 ∧ x10 + 1 < 1 + 1) := - subc_carry_cases _ _ _ _ e_c b_x10 (by decide) (by decide) + subc_carry_cases x10 1 1 _ e_c b_x10 (by decide) (by decide) clear e_c -- x14: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14 at hr + have e_x14 : x14 = x5 * x3 / 2^64 := rfl + clear_value x14 have p_x14 : x5 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3 have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.div_lt_of_lt_mul p_x14 obtain ⟨lo_x14, b_lo_x14, d_x14⟩ : @@ -229,73 +160,112 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul by rw [e_x14]; exact Nat.mod_add_div _ _⟩ clear e_x14 -- x11_1: adcs x11,x11,x15 + extract_lets +onlyGivenNames s x11_1 c_1 at hr + have e_x11_1 : x11_1 = (x11 + x15 + c) % 2^64 := rfl + have e_c_1 : c_1 = (x11 + x15 + c) / 2^64 := rfl + clear_value s x11_1 c_1 have l_x11_1 : x11_1 + 2^64 * c_1 = x11 + x15 + c := by rw [e_x11_1, e_c_1]; exact Nat.mod_add_div _ _ have b_x11_1 : x11_1 < 2^64 := by rw [e_x11_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_1 : c_1 ≤ 1 := by - rw [e_c_1]; exact addc_carry_le_one _ _ _ b_x11 b_x15 b_c + rw [e_c_1]; exact addc_carry_le_one x11 x15 c b_x11 b_x15 b_c clear e_x11_1 e_c_1 -- x15_1: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_1 at hr + have e_x15_1 : x15_1 = x6 * x3 / 2^64 := rfl + clear_value x15_1 have p_x15_1 : x6 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3 have b_x15_1 : x15_1 < 2^64 := by rw [e_x15_1]; exact Nat.div_lt_of_lt_mul p_x15_1 have d_x15_1 : x15 + 2^64 * x15_1 = x6 * x3 := by rw [e_x15, e_x15_1]; exact Nat.mod_add_div _ _ clear e_x15 e_x15_1 -- x12_1: adcs x12,x12,xzr + extract_lets +onlyGivenNames s_1 x12_1 c_2 at hr + have e_x12_1 : x12_1 = (x12 + 0 + c_1) % 2^64 := rfl + have e_c_2 : c_2 = (x12 + 0 + c_1) / 2^64 := rfl + clear_value s_1 x12_1 c_2 have l_x12_1 : x12_1 + 2^64 * c_2 = x12 + 0 + c_1 := by rw [e_x12_1, e_c_2]; exact Nat.mod_add_div _ _ have b_x12_1 : x12_1 < 2^64 := by rw [e_x12_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_2 : c_2 ≤ 1 := by - rw [e_c_2]; exact addc_carry_le_one _ _ _ b_x12 (by decide) b_c_1 + rw [e_c_2]; exact addc_carry_le_one x12 0 c_1 b_x12 (by decide) b_c_1 clear e_x12_1 e_c_2 -- x13_1: adcs x13,x13,x17 + extract_lets +onlyGivenNames s_2 x13_1 c_3 at hr + have e_x13_1 : x13_1 = (x13 + x17 + c_2) % 2^64 := rfl + have e_c_3 : c_3 = (x13 + x17 + c_2) / 2^64 := rfl + clear_value s_2 x13_1 c_3 have l_x13_1 : x13_1 + 2^64 * c_3 = x13 + x17 + c_2 := by rw [e_x13_1, e_c_3]; exact Nat.mod_add_div _ _ have b_x13_1 : x13_1 < 2^64 := by rw [e_x13_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_3 : c_3 ≤ 1 := by - rw [e_c_3]; exact addc_carry_le_one _ _ _ b_x13 b_x17 b_c_2 + rw [e_c_3]; exact addc_carry_le_one x13 x17 c_2 b_x13 b_x17 b_c_2 clear e_x13_1 e_c_3 -- x17_1: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_1 at hr + have e_x17_1 : x17_1 = x3 / 2^2 := rfl + clear_value x17_1 have b_x17_1 : x17_1 < 2^62 := by rw [e_x17_1]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3 (by norm_num)) have sh_x17_1 : x17 + 2^64 * x17_1 = x3 * 2^62 := by rw [e_x17, e_x17_1]; exact lsl62_lsr2_split _ clear e_x17 e_x17_1 -- x9: adc x9,xzr,xzr + extract_lets +onlyGivenNames x9 at hr + have e_x9 : x9 = (0 + 0 + c_3) % 2^64 := rfl + clear_value x9 have b_x9 : x9 < 2^64 := by rw [e_x9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9, b_k_x9, l_x9⟩ : ∃ k, k ≤ 1 ∧ x9 + 2^64 * k = 0 + 0 + c_3 := - ⟨(0 + 0 + c_3) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_3, + ⟨(0 + 0 + c_3) / 2^64, addc_carry_le_one 0 0 c_3 (by decide) (by decide) b_c_3, by rw [e_x9]; exact Nat.mod_add_div _ _⟩ clear e_x9 -- x10_1: adds x10,x11,x14 + extract_lets +onlyGivenNames s_3 x10_1 c_4 at hr + have e_x10_1 : x10_1 = (x11_1 + x14 + 0) % 2^64 := rfl + have e_c_4 : c_4 = (x11_1 + x14 + 0) / 2^64 := rfl + clear_value s_3 x10_1 c_4 have l_x10_1 : x10_1 + 2^64 * c_4 = x11_1 + x14 + 0 := by rw [e_x10_1, e_c_4]; exact Nat.mod_add_div _ _ have b_x10_1 : x10_1 < 2^64 := by rw [e_x10_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_4 : c_4 ≤ 1 := by - rw [e_c_4]; exact addc_carry_le_one _ _ _ b_x11_1 b_x14 (by decide) + rw [e_c_4]; exact addc_carry_le_one x11_1 x14 0 b_x11_1 b_x14 (by decide) clear e_x10_1 e_c_4 -- x11_2: adcs x11,x12,x15 + extract_lets +onlyGivenNames s_4 x11_2 c_5 at hr + have e_x11_2 : x11_2 = (x12_1 + x15_1 + c_4) % 2^64 := rfl + have e_c_5 : c_5 = (x12_1 + x15_1 + c_4) / 2^64 := rfl + clear_value s_4 x11_2 c_5 have l_x11_2 : x11_2 + 2^64 * c_5 = x12_1 + x15_1 + c_4 := by rw [e_x11_2, e_c_5]; exact Nat.mod_add_div _ _ have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_5 : c_5 ≤ 1 := by - rw [e_c_5]; exact addc_carry_le_one _ _ _ b_x12_1 b_x15_1 b_c_4 + rw [e_c_5]; exact addc_carry_le_one x12_1 x15_1 c_4 b_x12_1 b_x15_1 b_c_4 clear e_x11_2 e_c_5 -- x12_2: adcs x12,x13,xzr + extract_lets +onlyGivenNames s_5 x12_2 c_6 at hr + have e_x12_2 : x12_2 = (x13_1 + 0 + c_5) % 2^64 := rfl + have e_c_6 : c_6 = (x13_1 + 0 + c_5) / 2^64 := rfl + clear_value s_5 x12_2 c_6 have l_x12_2 : x12_2 + 2^64 * c_6 = x13_1 + 0 + c_5 := by rw [e_x12_2, e_c_6]; exact Nat.mod_add_div _ _ have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_6 : c_6 ≤ 1 := by - rw [e_c_6]; exact addc_carry_le_one _ _ _ b_x13_1 (by decide) b_c_5 + rw [e_c_6]; exact addc_carry_le_one x13_1 0 c_5 b_x13_1 (by decide) b_c_5 clear e_x12_2 e_c_6 -- x3_1: mul x3,x4,x10 + extract_lets +onlyGivenNames x3_1 at hr + have e_x3_1 : x3_1 = x4 * x10_1 % 2^64 := rfl + clear_value x3_1 have b_x3_1 : x3_1 < 2^64 := by rw [e_x3_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x13_2: adc x13,x9,x17 + extract_lets +onlyGivenNames x13_2 at hr + have e_x13_2 : x13_2 = (x9 + x17_1 + c_6) % 2^64 := rfl + clear_value x13_2 have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_2, b_k_x13_2, l_x13_2⟩ : ∃ k, k ≤ 1 ∧ x13_2 + 2^64 * k = x9 + x17_1 + c_6 := - ⟨(x9 + x17_1 + c_6) / 2^64, addc_carry_le_one _ _ _ b_x9 (lt_of_lt_of_le b_x17_1 (by norm_num)) b_c_6, + ⟨(x9 + x17_1 + c_6) / 2^64, addc_carry_le_one x9 x17_1 c_6 b_x9 (lt_of_lt_of_le b_x17_1 (by norm_num)) b_c_6, by rw [e_x13_2]; exact Nat.mod_add_div _ _⟩ clear e_x13_2 -- BEGIN round 0 @@ -321,15 +291,27 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul omega -- END round 0 -- x15_2: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_2 at hr + have e_x15_2 : x15_2 = x6 * x3_1 % 2^64 := rfl + clear_value x15_2 have b_x15_2 : x15_2 < 2^64 := by rw [e_x15_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x17_2: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_2 at hr + have e_x17_2 : x17_2 = x3_1 * 2^62 % 2^64 := rfl + clear_value x17_2 have b_x17_2 : x17_2 < 2^64 := by rw [e_x17_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- c_7: subs xzr,x10,#1 - have b_c_7 : c_7 ≤ 1 := by rw [e_c_7]; exact subc_carry_le_one _ _ _ b_x10_1 + extract_lets +onlyGivenNames c_7 at hr + have e_c_7 : c_7 = (x10_1 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_7 + have b_c_7 : c_7 ≤ 1 := by rw [e_c_7]; exact subc_carry_le_one x10_1 1 1 b_x10_1 have l_c_7 : (c_7 = 1 ∧ 1 + 1 ≤ x10_1 + 1) ∨ (c_7 = 0 ∧ x10_1 + 1 < 1 + 1) := - subc_carry_cases _ _ _ _ e_c_7 b_x10_1 (by decide) (by decide) + subc_carry_cases x10_1 1 1 _ e_c_7 b_x10_1 (by decide) (by decide) clear e_c_7 -- x14_1: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_1 at hr + have e_x14_1 : x14_1 = x5 * x3_1 / 2^64 := rfl + clear_value x14_1 have p_x14_1 : x5 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_1 have b_x14_1 : x14_1 < 2^64 := by rw [e_x14_1]; exact Nat.div_lt_of_lt_mul p_x14_1 obtain ⟨lo_x14_1, b_lo_x14_1, d_x14_1⟩ : @@ -338,73 +320,112 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul by rw [e_x14_1]; exact Nat.mod_add_div _ _⟩ clear e_x14_1 -- x11_3: adcs x11,x11,x15 + extract_lets +onlyGivenNames s_6 x11_3 c_8 at hr + have e_x11_3 : x11_3 = (x11_2 + x15_2 + c_7) % 2^64 := rfl + have e_c_8 : c_8 = (x11_2 + x15_2 + c_7) / 2^64 := rfl + clear_value s_6 x11_3 c_8 have l_x11_3 : x11_3 + 2^64 * c_8 = x11_2 + x15_2 + c_7 := by rw [e_x11_3, e_c_8]; exact Nat.mod_add_div _ _ have b_x11_3 : x11_3 < 2^64 := by rw [e_x11_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_8 : c_8 ≤ 1 := by - rw [e_c_8]; exact addc_carry_le_one _ _ _ b_x11_2 b_x15_2 b_c_7 + rw [e_c_8]; exact addc_carry_le_one x11_2 x15_2 c_7 b_x11_2 b_x15_2 b_c_7 clear e_x11_3 e_c_8 -- x15_3: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_3 at hr + have e_x15_3 : x15_3 = x6 * x3_1 / 2^64 := rfl + clear_value x15_3 have p_x15_3 : x6 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_1 have b_x15_3 : x15_3 < 2^64 := by rw [e_x15_3]; exact Nat.div_lt_of_lt_mul p_x15_3 have d_x15_3 : x15_2 + 2^64 * x15_3 = x6 * x3_1 := by rw [e_x15_2, e_x15_3]; exact Nat.mod_add_div _ _ clear e_x15_2 e_x15_3 -- x12_3: adcs x12,x12,xzr + extract_lets +onlyGivenNames s_7 x12_3 c_9 at hr + have e_x12_3 : x12_3 = (x12_2 + 0 + c_8) % 2^64 := rfl + have e_c_9 : c_9 = (x12_2 + 0 + c_8) / 2^64 := rfl + clear_value s_7 x12_3 c_9 have l_x12_3 : x12_3 + 2^64 * c_9 = x12_2 + 0 + c_8 := by rw [e_x12_3, e_c_9]; exact Nat.mod_add_div _ _ have b_x12_3 : x12_3 < 2^64 := by rw [e_x12_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_9 : c_9 ≤ 1 := by - rw [e_c_9]; exact addc_carry_le_one _ _ _ b_x12_2 (by decide) b_c_8 + rw [e_c_9]; exact addc_carry_le_one x12_2 0 c_8 b_x12_2 (by decide) b_c_8 clear e_x12_3 e_c_9 -- x13_3: adcs x13,x13,x17 + extract_lets +onlyGivenNames s_8 x13_3 c_10 at hr + have e_x13_3 : x13_3 = (x13_2 + x17_2 + c_9) % 2^64 := rfl + have e_c_10 : c_10 = (x13_2 + x17_2 + c_9) / 2^64 := rfl + clear_value s_8 x13_3 c_10 have l_x13_3 : x13_3 + 2^64 * c_10 = x13_2 + x17_2 + c_9 := by rw [e_x13_3, e_c_10]; exact Nat.mod_add_div _ _ have b_x13_3 : x13_3 < 2^64 := by rw [e_x13_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_10 : c_10 ≤ 1 := by - rw [e_c_10]; exact addc_carry_le_one _ _ _ b_x13_2 b_x17_2 b_c_9 + rw [e_c_10]; exact addc_carry_le_one x13_2 x17_2 c_9 b_x13_2 b_x17_2 b_c_9 clear e_x13_3 e_c_10 -- x17_3: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_3 at hr + have e_x17_3 : x17_3 = x3_1 / 2^2 := rfl + clear_value x17_3 have b_x17_3 : x17_3 < 2^62 := by rw [e_x17_3]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_1 (by norm_num)) have sh_x17_3 : x17_2 + 2^64 * x17_3 = x3_1 * 2^62 := by rw [e_x17_2, e_x17_3]; exact lsl62_lsr2_split _ clear e_x17_2 e_x17_3 -- x9_1: adc x9,xzr,xzr + extract_lets +onlyGivenNames x9_1 at hr + have e_x9_1 : x9_1 = (0 + 0 + c_10) % 2^64 := rfl + clear_value x9_1 have b_x9_1 : x9_1 < 2^64 := by rw [e_x9_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_1, b_k_x9_1, l_x9_1⟩ : ∃ k, k ≤ 1 ∧ x9_1 + 2^64 * k = 0 + 0 + c_10 := - ⟨(0 + 0 + c_10) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_10, + ⟨(0 + 0 + c_10) / 2^64, addc_carry_le_one 0 0 c_10 (by decide) (by decide) b_c_10, by rw [e_x9_1]; exact Nat.mod_add_div _ _⟩ clear e_x9_1 -- x10_2: adds x10,x11,x14 + extract_lets +onlyGivenNames s_9 x10_2 c_11 at hr + have e_x10_2 : x10_2 = (x11_3 + x14_1 + 0) % 2^64 := rfl + have e_c_11 : c_11 = (x11_3 + x14_1 + 0) / 2^64 := rfl + clear_value s_9 x10_2 c_11 have l_x10_2 : x10_2 + 2^64 * c_11 = x11_3 + x14_1 + 0 := by rw [e_x10_2, e_c_11]; exact Nat.mod_add_div _ _ have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_11 : c_11 ≤ 1 := by - rw [e_c_11]; exact addc_carry_le_one _ _ _ b_x11_3 b_x14_1 (by decide) + rw [e_c_11]; exact addc_carry_le_one x11_3 x14_1 0 b_x11_3 b_x14_1 (by decide) clear e_x10_2 e_c_11 -- x11_4: adcs x11,x12,x15 + extract_lets +onlyGivenNames s_10 x11_4 c_12 at hr + have e_x11_4 : x11_4 = (x12_3 + x15_3 + c_11) % 2^64 := rfl + have e_c_12 : c_12 = (x12_3 + x15_3 + c_11) / 2^64 := rfl + clear_value s_10 x11_4 c_12 have l_x11_4 : x11_4 + 2^64 * c_12 = x12_3 + x15_3 + c_11 := by rw [e_x11_4, e_c_12]; exact Nat.mod_add_div _ _ have b_x11_4 : x11_4 < 2^64 := by rw [e_x11_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_12 : c_12 ≤ 1 := by - rw [e_c_12]; exact addc_carry_le_one _ _ _ b_x12_3 b_x15_3 b_c_11 + rw [e_c_12]; exact addc_carry_le_one x12_3 x15_3 c_11 b_x12_3 b_x15_3 b_c_11 clear e_x11_4 e_c_12 -- x12_4: adcs x12,x13,xzr + extract_lets +onlyGivenNames s_11 x12_4 c_13 at hr + have e_x12_4 : x12_4 = (x13_3 + 0 + c_12) % 2^64 := rfl + have e_c_13 : c_13 = (x13_3 + 0 + c_12) / 2^64 := rfl + clear_value s_11 x12_4 c_13 have l_x12_4 : x12_4 + 2^64 * c_13 = x13_3 + 0 + c_12 := by rw [e_x12_4, e_c_13]; exact Nat.mod_add_div _ _ have b_x12_4 : x12_4 < 2^64 := by rw [e_x12_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_13 : c_13 ≤ 1 := by - rw [e_c_13]; exact addc_carry_le_one _ _ _ b_x13_3 (by decide) b_c_12 + rw [e_c_13]; exact addc_carry_le_one x13_3 0 c_12 b_x13_3 (by decide) b_c_12 clear e_x12_4 e_c_13 -- x3_2: mul x3,x4,x10 + extract_lets +onlyGivenNames x3_2 at hr + have e_x3_2 : x3_2 = x4 * x10_2 % 2^64 := rfl + clear_value x3_2 have b_x3_2 : x3_2 < 2^64 := by rw [e_x3_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x13_4: adc x13,x9,x17 + extract_lets +onlyGivenNames x13_4 at hr + have e_x13_4 : x13_4 = (x9_1 + x17_3 + c_13) % 2^64 := rfl + clear_value x13_4 have b_x13_4 : x13_4 < 2^64 := by rw [e_x13_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_4, b_k_x13_4, l_x13_4⟩ : ∃ k, k ≤ 1 ∧ x13_4 + 2^64 * k = x9_1 + x17_3 + c_13 := - ⟨(x9_1 + x17_3 + c_13) / 2^64, addc_carry_le_one _ _ _ b_x9_1 (lt_of_lt_of_le b_x17_3 (by norm_num)) b_c_13, + ⟨(x9_1 + x17_3 + c_13) / 2^64, addc_carry_le_one x9_1 x17_3 c_13 b_x9_1 (lt_of_lt_of_le b_x17_3 (by norm_num)) b_c_13, by rw [e_x13_4]; exact Nat.mod_add_div _ _⟩ clear e_x13_4 -- BEGIN round 1 @@ -430,15 +451,27 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul omega -- END round 1 -- x15_4: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_4 at hr + have e_x15_4 : x15_4 = x6 * x3_2 % 2^64 := rfl + clear_value x15_4 have b_x15_4 : x15_4 < 2^64 := by rw [e_x15_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x17_4: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_4 at hr + have e_x17_4 : x17_4 = x3_2 * 2^62 % 2^64 := rfl + clear_value x17_4 have b_x17_4 : x17_4 < 2^64 := by rw [e_x17_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- c_14: subs xzr,x10,#1 - have b_c_14 : c_14 ≤ 1 := by rw [e_c_14]; exact subc_carry_le_one _ _ _ b_x10_2 + extract_lets +onlyGivenNames c_14 at hr + have e_c_14 : c_14 = (x10_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_14 + have b_c_14 : c_14 ≤ 1 := by rw [e_c_14]; exact subc_carry_le_one x10_2 1 1 b_x10_2 have l_c_14 : (c_14 = 1 ∧ 1 + 1 ≤ x10_2 + 1) ∨ (c_14 = 0 ∧ x10_2 + 1 < 1 + 1) := - subc_carry_cases _ _ _ _ e_c_14 b_x10_2 (by decide) (by decide) + subc_carry_cases x10_2 1 1 _ e_c_14 b_x10_2 (by decide) (by decide) clear e_c_14 -- x14_2: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_2 at hr + have e_x14_2 : x14_2 = x5 * x3_2 / 2^64 := rfl + clear_value x14_2 have p_x14_2 : x5 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_2 have b_x14_2 : x14_2 < 2^64 := by rw [e_x14_2]; exact Nat.div_lt_of_lt_mul p_x14_2 obtain ⟨lo_x14_2, b_lo_x14_2, d_x14_2⟩ : @@ -447,73 +480,112 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul by rw [e_x14_2]; exact Nat.mod_add_div _ _⟩ clear e_x14_2 -- x11_5: adcs x11,x11,x15 + extract_lets +onlyGivenNames s_12 x11_5 c_15 at hr + have e_x11_5 : x11_5 = (x11_4 + x15_4 + c_14) % 2^64 := rfl + have e_c_15 : c_15 = (x11_4 + x15_4 + c_14) / 2^64 := rfl + clear_value s_12 x11_5 c_15 have l_x11_5 : x11_5 + 2^64 * c_15 = x11_4 + x15_4 + c_14 := by rw [e_x11_5, e_c_15]; exact Nat.mod_add_div _ _ have b_x11_5 : x11_5 < 2^64 := by rw [e_x11_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_15 : c_15 ≤ 1 := by - rw [e_c_15]; exact addc_carry_le_one _ _ _ b_x11_4 b_x15_4 b_c_14 + rw [e_c_15]; exact addc_carry_le_one x11_4 x15_4 c_14 b_x11_4 b_x15_4 b_c_14 clear e_x11_5 e_c_15 -- x15_5: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_5 at hr + have e_x15_5 : x15_5 = x6 * x3_2 / 2^64 := rfl + clear_value x15_5 have p_x15_5 : x6 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_2 have b_x15_5 : x15_5 < 2^64 := by rw [e_x15_5]; exact Nat.div_lt_of_lt_mul p_x15_5 have d_x15_5 : x15_4 + 2^64 * x15_5 = x6 * x3_2 := by rw [e_x15_4, e_x15_5]; exact Nat.mod_add_div _ _ clear e_x15_4 e_x15_5 -- x12_5: adcs x12,x12,xzr + extract_lets +onlyGivenNames s_13 x12_5 c_16 at hr + have e_x12_5 : x12_5 = (x12_4 + 0 + c_15) % 2^64 := rfl + have e_c_16 : c_16 = (x12_4 + 0 + c_15) / 2^64 := rfl + clear_value s_13 x12_5 c_16 have l_x12_5 : x12_5 + 2^64 * c_16 = x12_4 + 0 + c_15 := by rw [e_x12_5, e_c_16]; exact Nat.mod_add_div _ _ have b_x12_5 : x12_5 < 2^64 := by rw [e_x12_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_16 : c_16 ≤ 1 := by - rw [e_c_16]; exact addc_carry_le_one _ _ _ b_x12_4 (by decide) b_c_15 + rw [e_c_16]; exact addc_carry_le_one x12_4 0 c_15 b_x12_4 (by decide) b_c_15 clear e_x12_5 e_c_16 -- x13_5: adcs x13,x13,x17 + extract_lets +onlyGivenNames s_14 x13_5 c_17 at hr + have e_x13_5 : x13_5 = (x13_4 + x17_4 + c_16) % 2^64 := rfl + have e_c_17 : c_17 = (x13_4 + x17_4 + c_16) / 2^64 := rfl + clear_value s_14 x13_5 c_17 have l_x13_5 : x13_5 + 2^64 * c_17 = x13_4 + x17_4 + c_16 := by rw [e_x13_5, e_c_17]; exact Nat.mod_add_div _ _ have b_x13_5 : x13_5 < 2^64 := by rw [e_x13_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_17 : c_17 ≤ 1 := by - rw [e_c_17]; exact addc_carry_le_one _ _ _ b_x13_4 b_x17_4 b_c_16 + rw [e_c_17]; exact addc_carry_le_one x13_4 x17_4 c_16 b_x13_4 b_x17_4 b_c_16 clear e_x13_5 e_c_17 -- x17_5: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_5 at hr + have e_x17_5 : x17_5 = x3_2 / 2^2 := rfl + clear_value x17_5 have b_x17_5 : x17_5 < 2^62 := by rw [e_x17_5]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_2 (by norm_num)) have sh_x17_5 : x17_4 + 2^64 * x17_5 = x3_2 * 2^62 := by rw [e_x17_4, e_x17_5]; exact lsl62_lsr2_split _ clear e_x17_4 e_x17_5 -- x9_2: adc x9,xzr,xzr + extract_lets +onlyGivenNames x9_2 at hr + have e_x9_2 : x9_2 = (0 + 0 + c_17) % 2^64 := rfl + clear_value x9_2 have b_x9_2 : x9_2 < 2^64 := by rw [e_x9_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_2, b_k_x9_2, l_x9_2⟩ : ∃ k, k ≤ 1 ∧ x9_2 + 2^64 * k = 0 + 0 + c_17 := - ⟨(0 + 0 + c_17) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_17, + ⟨(0 + 0 + c_17) / 2^64, addc_carry_le_one 0 0 c_17 (by decide) (by decide) b_c_17, by rw [e_x9_2]; exact Nat.mod_add_div _ _⟩ clear e_x9_2 -- x10_3: adds x10,x11,x14 + extract_lets +onlyGivenNames s_15 x10_3 c_18 at hr + have e_x10_3 : x10_3 = (x11_5 + x14_2 + 0) % 2^64 := rfl + have e_c_18 : c_18 = (x11_5 + x14_2 + 0) / 2^64 := rfl + clear_value s_15 x10_3 c_18 have l_x10_3 : x10_3 + 2^64 * c_18 = x11_5 + x14_2 + 0 := by rw [e_x10_3, e_c_18]; exact Nat.mod_add_div _ _ have b_x10_3 : x10_3 < 2^64 := by rw [e_x10_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_18 : c_18 ≤ 1 := by - rw [e_c_18]; exact addc_carry_le_one _ _ _ b_x11_5 b_x14_2 (by decide) + rw [e_c_18]; exact addc_carry_le_one x11_5 x14_2 0 b_x11_5 b_x14_2 (by decide) clear e_x10_3 e_c_18 -- x11_6: adcs x11,x12,x15 + extract_lets +onlyGivenNames s_16 x11_6 c_19 at hr + have e_x11_6 : x11_6 = (x12_5 + x15_5 + c_18) % 2^64 := rfl + have e_c_19 : c_19 = (x12_5 + x15_5 + c_18) / 2^64 := rfl + clear_value s_16 x11_6 c_19 have l_x11_6 : x11_6 + 2^64 * c_19 = x12_5 + x15_5 + c_18 := by rw [e_x11_6, e_c_19]; exact Nat.mod_add_div _ _ have b_x11_6 : x11_6 < 2^64 := by rw [e_x11_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_19 : c_19 ≤ 1 := by - rw [e_c_19]; exact addc_carry_le_one _ _ _ b_x12_5 b_x15_5 b_c_18 + rw [e_c_19]; exact addc_carry_le_one x12_5 x15_5 c_18 b_x12_5 b_x15_5 b_c_18 clear e_x11_6 e_c_19 -- x12_6: adcs x12,x13,xzr + extract_lets +onlyGivenNames s_17 x12_6 c_20 at hr + have e_x12_6 : x12_6 = (x13_5 + 0 + c_19) % 2^64 := rfl + have e_c_20 : c_20 = (x13_5 + 0 + c_19) / 2^64 := rfl + clear_value s_17 x12_6 c_20 have l_x12_6 : x12_6 + 2^64 * c_20 = x13_5 + 0 + c_19 := by rw [e_x12_6, e_c_20]; exact Nat.mod_add_div _ _ have b_x12_6 : x12_6 < 2^64 := by rw [e_x12_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_20 : c_20 ≤ 1 := by - rw [e_c_20]; exact addc_carry_le_one _ _ _ b_x13_5 (by decide) b_c_19 + rw [e_c_20]; exact addc_carry_le_one x13_5 0 c_19 b_x13_5 (by decide) b_c_19 clear e_x12_6 e_c_20 -- x3_3: mul x3,x4,x10 + extract_lets +onlyGivenNames x3_3 at hr + have e_x3_3 : x3_3 = x4 * x10_3 % 2^64 := rfl + clear_value x3_3 have b_x3_3 : x3_3 < 2^64 := by rw [e_x3_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x13_6: adc x13,x9,x17 + extract_lets +onlyGivenNames x13_6 at hr + have e_x13_6 : x13_6 = (x9_2 + x17_5 + c_20) % 2^64 := rfl + clear_value x13_6 have b_x13_6 : x13_6 < 2^64 := by rw [e_x13_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_6, b_k_x13_6, l_x13_6⟩ : ∃ k, k ≤ 1 ∧ x13_6 + 2^64 * k = x9_2 + x17_5 + c_20 := - ⟨(x9_2 + x17_5 + c_20) / 2^64, addc_carry_le_one _ _ _ b_x9_2 (lt_of_lt_of_le b_x17_5 (by norm_num)) b_c_20, + ⟨(x9_2 + x17_5 + c_20) / 2^64, addc_carry_le_one x9_2 x17_5 c_20 b_x9_2 (lt_of_lt_of_le b_x17_5 (by norm_num)) b_c_20, by rw [e_x13_6]; exact Nat.mod_add_div _ _⟩ clear e_x13_6 -- BEGIN round 2 @@ -539,15 +611,27 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul omega -- END round 2 -- x15_6: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_6 at hr + have e_x15_6 : x15_6 = x6 * x3_3 % 2^64 := rfl + clear_value x15_6 have b_x15_6 : x15_6 < 2^64 := by rw [e_x15_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- x17_6: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_6 at hr + have e_x17_6 : x17_6 = x3_3 * 2^62 % 2^64 := rfl + clear_value x17_6 have b_x17_6 : x17_6 < 2^64 := by rw [e_x17_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) -- c_21: subs xzr,x10,#1 - have b_c_21 : c_21 ≤ 1 := by rw [e_c_21]; exact subc_carry_le_one _ _ _ b_x10_3 + extract_lets +onlyGivenNames c_21 at hr + have e_c_21 : c_21 = (x10_3 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_21 + have b_c_21 : c_21 ≤ 1 := by rw [e_c_21]; exact subc_carry_le_one x10_3 1 1 b_x10_3 have l_c_21 : (c_21 = 1 ∧ 1 + 1 ≤ x10_3 + 1) ∨ (c_21 = 0 ∧ x10_3 + 1 < 1 + 1) := - subc_carry_cases _ _ _ _ e_c_21 b_x10_3 (by decide) (by decide) + subc_carry_cases x10_3 1 1 _ e_c_21 b_x10_3 (by decide) (by decide) clear e_c_21 -- x14_3: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_3 at hr + have e_x14_3 : x14_3 = x5 * x3_3 / 2^64 := rfl + clear_value x14_3 have p_x14_3 : x5 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_3 have b_x14_3 : x14_3 < 2^64 := by rw [e_x14_3]; exact Nat.div_lt_of_lt_mul p_x14_3 obtain ⟨lo_x14_3, b_lo_x14_3, d_x14_3⟩ : @@ -556,73 +640,110 @@ theorem mulBy1_spec (t modulus : Limbs) (inv : Nat) (ht : t.Bounded) (hm : modul by rw [e_x14_3]; exact Nat.mod_add_div _ _⟩ clear e_x14_3 -- x11_7: adcs x11,x11,x15 + extract_lets +onlyGivenNames s_18 x11_7 c_22 at hr + have e_x11_7 : x11_7 = (x11_6 + x15_6 + c_21) % 2^64 := rfl + have e_c_22 : c_22 = (x11_6 + x15_6 + c_21) / 2^64 := rfl + clear_value s_18 x11_7 c_22 have l_x11_7 : x11_7 + 2^64 * c_22 = x11_6 + x15_6 + c_21 := by rw [e_x11_7, e_c_22]; exact Nat.mod_add_div _ _ have b_x11_7 : x11_7 < 2^64 := by rw [e_x11_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_22 : c_22 ≤ 1 := by - rw [e_c_22]; exact addc_carry_le_one _ _ _ b_x11_6 b_x15_6 b_c_21 + rw [e_c_22]; exact addc_carry_le_one x11_6 x15_6 c_21 b_x11_6 b_x15_6 b_c_21 clear e_x11_7 e_c_22 -- x15_7: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_7 at hr + have e_x15_7 : x15_7 = x6 * x3_3 / 2^64 := rfl + clear_value x15_7 have p_x15_7 : x6 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_3 have b_x15_7 : x15_7 < 2^64 := by rw [e_x15_7]; exact Nat.div_lt_of_lt_mul p_x15_7 have d_x15_7 : x15_6 + 2^64 * x15_7 = x6 * x3_3 := by rw [e_x15_6, e_x15_7]; exact Nat.mod_add_div _ _ clear e_x15_6 e_x15_7 -- x12_7: adcs x12,x12,xzr + extract_lets +onlyGivenNames s_19 x12_7 c_23 at hr + have e_x12_7 : x12_7 = (x12_6 + 0 + c_22) % 2^64 := rfl + have e_c_23 : c_23 = (x12_6 + 0 + c_22) / 2^64 := rfl + clear_value s_19 x12_7 c_23 have l_x12_7 : x12_7 + 2^64 * c_23 = x12_6 + 0 + c_22 := by rw [e_x12_7, e_c_23]; exact Nat.mod_add_div _ _ have b_x12_7 : x12_7 < 2^64 := by rw [e_x12_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_23 : c_23 ≤ 1 := by - rw [e_c_23]; exact addc_carry_le_one _ _ _ b_x12_6 (by decide) b_c_22 + rw [e_c_23]; exact addc_carry_le_one x12_6 0 c_22 b_x12_6 (by decide) b_c_22 clear e_x12_7 e_c_23 -- x13_7: adcs x13,x13,x17 + extract_lets +onlyGivenNames s_20 x13_7 c_24 at hr + have e_x13_7 : x13_7 = (x13_6 + x17_6 + c_23) % 2^64 := rfl + have e_c_24 : c_24 = (x13_6 + x17_6 + c_23) / 2^64 := rfl + clear_value s_20 x13_7 c_24 have l_x13_7 : x13_7 + 2^64 * c_24 = x13_6 + x17_6 + c_23 := by rw [e_x13_7, e_c_24]; exact Nat.mod_add_div _ _ have b_x13_7 : x13_7 < 2^64 := by rw [e_x13_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_24 : c_24 ≤ 1 := by - rw [e_c_24]; exact addc_carry_le_one _ _ _ b_x13_6 b_x17_6 b_c_23 + rw [e_c_24]; exact addc_carry_le_one x13_6 x17_6 c_23 b_x13_6 b_x17_6 b_c_23 clear e_x13_7 e_c_24 -- x17_7: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_7 at hr + have e_x17_7 : x17_7 = x3_3 / 2^2 := rfl + clear_value x17_7 have b_x17_7 : x17_7 < 2^62 := by rw [e_x17_7]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_3 (by norm_num)) have sh_x17_7 : x17_6 + 2^64 * x17_7 = x3_3 * 2^62 := by rw [e_x17_6, e_x17_7]; exact lsl62_lsr2_split _ clear e_x17_6 e_x17_7 -- x9_3: adc x9,xzr,xzr + extract_lets +onlyGivenNames x9_3 at hr + have e_x9_3 : x9_3 = (0 + 0 + c_24) % 2^64 := rfl + clear_value x9_3 have b_x9_3 : x9_3 < 2^64 := by rw [e_x9_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x9_3, b_k_x9_3, l_x9_3⟩ : ∃ k, k ≤ 1 ∧ x9_3 + 2^64 * k = 0 + 0 + c_24 := - ⟨(0 + 0 + c_24) / 2^64, addc_carry_le_one _ _ _ (by decide) (by decide) b_c_24, + ⟨(0 + 0 + c_24) / 2^64, addc_carry_le_one 0 0 c_24 (by decide) (by decide) b_c_24, by rw [e_x9_3]; exact Nat.mod_add_div _ _⟩ clear e_x9_3 -- x10_4: adds x10,x11,x14 + extract_lets +onlyGivenNames s_21 x10_4 c_25 at hr + have e_x10_4 : x10_4 = (x11_7 + x14_3 + 0) % 2^64 := rfl + have e_c_25 : c_25 = (x11_7 + x14_3 + 0) / 2^64 := rfl + clear_value s_21 x10_4 c_25 have l_x10_4 : x10_4 + 2^64 * c_25 = x11_7 + x14_3 + 0 := by rw [e_x10_4, e_c_25]; exact Nat.mod_add_div _ _ have b_x10_4 : x10_4 < 2^64 := by rw [e_x10_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_25 : c_25 ≤ 1 := by - rw [e_c_25]; exact addc_carry_le_one _ _ _ b_x11_7 b_x14_3 (by decide) + rw [e_c_25]; exact addc_carry_le_one x11_7 x14_3 0 b_x11_7 b_x14_3 (by decide) clear e_x10_4 e_c_25 -- x11_8: adcs x11,x12,x15 + extract_lets +onlyGivenNames s_22 x11_8 c_26 at hr + have e_x11_8 : x11_8 = (x12_7 + x15_7 + c_25) % 2^64 := rfl + have e_c_26 : c_26 = (x12_7 + x15_7 + c_25) / 2^64 := rfl + clear_value s_22 x11_8 c_26 have l_x11_8 : x11_8 + 2^64 * c_26 = x12_7 + x15_7 + c_25 := by rw [e_x11_8, e_c_26]; exact Nat.mod_add_div _ _ have b_x11_8 : x11_8 < 2^64 := by rw [e_x11_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_26 : c_26 ≤ 1 := by - rw [e_c_26]; exact addc_carry_le_one _ _ _ b_x12_7 b_x15_7 b_c_25 + rw [e_c_26]; exact addc_carry_le_one x12_7 x15_7 c_25 b_x12_7 b_x15_7 b_c_25 clear e_x11_8 e_c_26 -- x12_8: adcs x12,x13,xzr + extract_lets +onlyGivenNames s_23 x12_8 c_27 at hr + have e_x12_8 : x12_8 = (x13_7 + 0 + c_26) % 2^64 := rfl + have e_c_27 : c_27 = (x13_7 + 0 + c_26) / 2^64 := rfl + clear_value s_23 x12_8 c_27 have l_x12_8 : x12_8 + 2^64 * c_27 = x13_7 + 0 + c_26 := by rw [e_x12_8, e_c_27]; exact Nat.mod_add_div _ _ have b_x12_8 : x12_8 < 2^64 := by rw [e_x12_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_27 : c_27 ≤ 1 := by - rw [e_c_27]; exact addc_carry_le_one _ _ _ b_x13_7 (by decide) b_c_26 + rw [e_c_27]; exact addc_carry_le_one x13_7 0 c_26 b_x13_7 (by decide) b_c_26 clear e_x12_8 e_c_27 -- x13_8: adc x13,x9,x17 + extract_lets +onlyGivenNames x13_8 at hr + have e_x13_8 : x13_8 = (x9_3 + x17_7 + c_27) % 2^64 := rfl + clear_value x13_8 have b_x13_8 : x13_8 < 2^64 := by rw [e_x13_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) obtain ⟨k_x13_8, b_k_x13_8, l_x13_8⟩ : ∃ k, k ≤ 1 ∧ x13_8 + 2^64 * k = x9_3 + x17_7 + c_27 := - ⟨(x9_3 + x17_7 + c_27) / 2^64, addc_carry_le_one _ _ _ b_x9_3 (lt_of_lt_of_le b_x17_7 (by norm_num)) b_c_27, + ⟨(x9_3 + x17_7 + c_27) / 2^64, addc_carry_le_one x9_3 x17_7 c_27 b_x9_3 (lt_of_lt_of_le b_x17_7 (by norm_num)) b_c_27, by rw [e_x13_8]; exact Nat.mod_add_div _ _⟩ clear e_x13_8 + subst hr -- BEGIN round 3 -- Cancellation: the low limb of `x10_3 + p0 * x3_3` is zero, so `x10_3 + lo_x14_3` is -- `0` or `2^64`, and `subs xzr, x10_3, #1` set the carry exactly when it is `2^64`. @@ -684,66 +805,75 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) -- generated skeleton for `fromMont`: do not edit between the annotations unfold fromMont at hr lift_lets at hr - extract_lets x3 x4 x10 x11 x12 x13 r x10_1 x11_1 x12_1 x13_1 x5 x6 x7 x8 s x14 c s_1 x15 c_1 s_2 - x16 c_2 s_3 x17 c_3 x10_2 x11_2 x12_2 x13_2 out0 out1 out2 out3 at hr - subst hr - have e_x3 : x3 = inv := rfl - have e_x4 : x4 = x3 := rfl - have e_x10 : x10 = value.l0 := rfl - have e_x11 : x11 = value.l1 := rfl - have e_x12 : x12 = value.l2 := rfl - have e_x13 : x13 = value.l3 := rfl - have e_r : r = mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 := rfl - have e_x10_1 : x10_1 = r.l0 := rfl - have e_x11_1 : x11_1 = r.l1 := rfl - have e_x12_1 : x12_1 = r.l2 := rfl - have e_x13_1 : x13_1 = r.l3 := rfl - have e_x5 : x5 = modulus.l0 := rfl - have e_x6 : x6 = modulus.l1 := rfl - have e_x7 : x7 = modulus.l2 := rfl - have e_x8 : x8 = modulus.l3 := rfl - have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl - have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl - have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl - have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl - have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl - have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl - have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl - have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl - have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl - have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl - have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl - have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl - have e_out0 : out0 = x10_2 := rfl - have e_out1 : out1 = x11_2 := rfl - have e_out2 : out2 = x12_2 := rfl - have e_out3 : out3 = x13_2 := rfl - clear_value out3 out2 out1 out0 x13_2 x12_2 x11_2 x10_2 c_3 x17 s_3 c_2 x16 s_2 c_1 x15 s_1 c x14 - s x8 x7 x6 x5 x13_1 x12_1 x11_1 x10_1 r x13 x12 x11 x10 x4 x3 -- x3: argument + extract_lets +onlyGivenNames x3 at hr + have e_x3 : x3 = inv := rfl + clear_value x3 have b_x3 : x3 < 2^64 := by rw [e_x3]; exact hinv_lt -- x4: mov x4,x3 + extract_lets +onlyGivenNames x4 at hr + have e_x4 : x4 = x3 := rfl + clear_value x4 have b_x4 : x4 < 2^64 := by rw [e_x4]; exact b_x3 -- x10: ldp x10,x11,[x1] + extract_lets +onlyGivenNames x10 at hr + have e_x10 : x10 = value.l0 := rfl + clear_value x10 have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hv.1 -- x11: ldp x10,x11,[x1] + extract_lets +onlyGivenNames x11 at hr + have e_x11 : x11 = value.l1 := rfl + clear_value x11 have b_x11 : x11 < 2^64 := by rw [e_x11]; exact hv.2.1 -- x12: ldp x12,x13,[x1,#16] + extract_lets +onlyGivenNames x12 at hr + have e_x12 : x12 = value.l2 := rfl + clear_value x12 have b_x12 : x12 < 2^64 := by rw [e_x12]; exact hv.2.2.1 -- x13: ldp x12,x13,[x1,#16] + extract_lets +onlyGivenNames x13 at hr + have e_x13 : x13 = value.l3 := rfl + clear_value x13 have b_x13 : x13 < 2^64 := by rw [e_x13]; exact hv.2.2.2 -- r: bl L$pasta_curves_mul_by_1_mont_pasta + extract_lets +onlyGivenNames r at hr + have e_r : r = mulBy1 ⟨x10, x11, x12, x13⟩ modulus x4 := rfl + clear_value r -- x10_1: helper output + extract_lets +onlyGivenNames x10_1 at hr + have e_x10_1 : x10_1 = r.l0 := rfl + clear_value x10_1 -- x11_1: helper output + extract_lets +onlyGivenNames x11_1 at hr + have e_x11_1 : x11_1 = r.l1 := rfl + clear_value x11_1 -- x12_1: helper output + extract_lets +onlyGivenNames x12_1 at hr + have e_x12_1 : x12_1 = r.l2 := rfl + clear_value x12_1 -- x13_1: helper output + extract_lets +onlyGivenNames x13_1 at hr + have e_x13_1 : x13_1 = r.l3 := rfl + clear_value x13_1 -- x5: loaded by the helper + extract_lets +onlyGivenNames x5 at hr + have e_x5 : x5 = modulus.l0 := rfl + clear_value x5 have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 -- x6: loaded by the helper + extract_lets +onlyGivenNames x6 at hr + have e_x6 : x6 = modulus.l1 := rfl + clear_value x6 have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 -- x7: loaded by the helper + extract_lets +onlyGivenNames x7 at hr + have e_x7 : x7 = modulus.l2 := rfl + clear_value x7 have b_x7 : x7 < 2^64 := by rw [e_x7]; exact hm.2.2.1 -- x8: loaded by the helper + extract_lets +onlyGivenNames x8 at hr + have e_x8 : x8 = modulus.l3 := rfl + clear_value x8 have b_x8 : x8 < 2^64 := by rw [e_x8]; exact hm.2.2.2 -- BEGIN helper -- The helper's contract on `t = value`: its result limbs are bounded, and `2^256 * r = t + Q * p` @@ -759,49 +889,90 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) clear e_r e_x10_1 e_x11_1 e_x12_1 e_x13_1 -- END helper -- x14: subs x14,x10,x5 + extract_lets +onlyGivenNames s x14 c at hr + have e_x14 : x14 = (x10_1 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl + have e_c : c = (x10_1 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl + clear_value s x14 c have l_x14 : x14 + 2^64 * c + x5 + 1 = x10_1 + 2^64 + 1 := by - rw [e_x14, e_c]; exact subc_lin _ _ _ b_x5 (by decide) + rw [e_x14, e_c]; exact subc_lin x10_1 x5 1 b_x5 (by decide) have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c : c ≤ 1 := by - rw [e_c]; exact subc_carry_le_one _ _ _ b_x10_1 + rw [e_c]; exact subc_carry_le_one x10_1 x5 1 b_x10_1 clear e_x14 e_c -- x15: sbcs x15,x11,x6 + extract_lets +onlyGivenNames s_1 x15 c_1 at hr + have e_x15 : x15 = (x11_1 + 2^64 - x6 - (1 - c)) % 2^64 := rfl + have e_c_1 : c_1 = (x11_1 + 2^64 - x6 - (1 - c)) / 2^64 := rfl + clear_value s_1 x15 c_1 have l_x15 : x15 + 2^64 * c_1 + x6 + 1 = x11_1 + 2^64 + c := by - rw [e_x15, e_c_1]; exact subc_lin _ _ _ b_x6 b_c + rw [e_x15, e_c_1]; exact subc_lin x11_1 x6 c b_x6 b_c have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_1 : c_1 ≤ 1 := by - rw [e_c_1]; exact subc_carry_le_one _ _ _ b_x11_1 + rw [e_c_1]; exact subc_carry_le_one x11_1 x6 c b_x11_1 clear e_x15 e_c_1 -- x16: sbcs x16,x12,x7 + extract_lets +onlyGivenNames s_2 x16 c_2 at hr + have e_x16 : x16 = (x12_1 + 2^64 - x7 - (1 - c_1)) % 2^64 := rfl + have e_c_2 : c_2 = (x12_1 + 2^64 - x7 - (1 - c_1)) / 2^64 := rfl + clear_value s_2 x16 c_2 have l_x16 : x16 + 2^64 * c_2 + x7 + 1 = x12_1 + 2^64 + c_1 := by - rw [e_x16, e_c_2]; exact subc_lin _ _ _ b_x7 b_c_1 + rw [e_x16, e_c_2]; exact subc_lin x12_1 x7 c_1 b_x7 b_c_1 have b_x16 : x16 < 2^64 := by rw [e_x16]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_2 : c_2 ≤ 1 := by - rw [e_c_2]; exact subc_carry_le_one _ _ _ b_x12_1 + rw [e_c_2]; exact subc_carry_le_one x12_1 x7 c_1 b_x12_1 clear e_x16 e_c_2 -- x17: sbcs x17,x13,x8 + extract_lets +onlyGivenNames s_3 x17 c_3 at hr + have e_x17 : x17 = (x13_1 + 2^64 - x8 - (1 - c_2)) % 2^64 := rfl + have e_c_3 : c_3 = (x13_1 + 2^64 - x8 - (1 - c_2)) / 2^64 := rfl + clear_value s_3 x17 c_3 have l_x17 : x17 + 2^64 * c_3 + x8 + 1 = x13_1 + 2^64 + c_2 := by - rw [e_x17, e_c_3]; exact subc_lin _ _ _ b_x8 b_c_2 + rw [e_x17, e_c_3]; exact subc_lin x13_1 x8 c_2 b_x8 b_c_2 have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.mod_lt _ (Nat.two_pow_pos _) have b_c_3 : c_3 ≤ 1 := by - rw [e_c_3]; exact subc_carry_le_one _ _ _ b_x13_1 + rw [e_c_3]; exact subc_carry_le_one x13_1 x8 c_2 b_x13_1 clear e_x17 e_c_3 -- x10_2: csel x10,x10,x14,lo + extract_lets +onlyGivenNames x10_2 at hr + have e_x10_2 : x10_2 = (if c_3 = 0 then x10_1 else x14) := rfl + clear_value x10_2 have b_x10_2 : x10_2 < 2^64 := by rw [e_x10_2]; split <;> first | exact b_x10_1 | exact b_x14 -- x11_2: csel x11,x11,x15,lo + extract_lets +onlyGivenNames x11_2 at hr + have e_x11_2 : x11_2 = (if c_3 = 0 then x11_1 else x15) := rfl + clear_value x11_2 have b_x11_2 : x11_2 < 2^64 := by rw [e_x11_2]; split <;> first | exact b_x11_1 | exact b_x15 -- x12_2: csel x12,x12,x16,lo + extract_lets +onlyGivenNames x12_2 at hr + have e_x12_2 : x12_2 = (if c_3 = 0 then x12_1 else x16) := rfl + clear_value x12_2 have b_x12_2 : x12_2 < 2^64 := by rw [e_x12_2]; split <;> first | exact b_x12_1 | exact b_x16 -- x13_2: csel x13,x13,x17,lo + extract_lets +onlyGivenNames x13_2 at hr + have e_x13_2 : x13_2 = (if c_3 = 0 then x13_1 else x17) := rfl + clear_value x13_2 have b_x13_2 : x13_2 < 2^64 := by rw [e_x13_2]; split <;> first | exact b_x13_1 | exact b_x17 -- out0: stp x10,x11,[x0] + extract_lets +onlyGivenNames out0 at hr + have e_out0 : out0 = x10_2 := rfl + clear_value out0 -- out1: stp x10,x11,[x0] + extract_lets +onlyGivenNames out1 at hr + have e_out1 : out1 = x11_2 := rfl + clear_value out1 -- out2: stp x12,x13,[x0,#16] + extract_lets +onlyGivenNames out2 at hr + have e_out2 : out2 = x12_2 := rfl + clear_value out2 -- out3: stp x12,x13,[x0,#16] + extract_lets +onlyGivenNames out3 at hr + have e_out3 : out3 = x13_2 := rfl + clear_value out3 + subst hr -- BEGIN conclusion subst out0 out1 out2 out3 have hV : value.toNat = x10 + 2^64 * x11 + 2^128 * x12 + 2^192 * x13 := by diff --git a/scripts/gen_aarch64_pasta_mul.py b/scripts/gen_aarch64_pasta_mul.py index 4c16375..d931c71 100755 --- a/scripts/gen_aarch64_pasta_mul.py +++ b/scripts/gen_aarch64_pasta_mul.py @@ -477,18 +477,21 @@ def wrap_tactic(head, words, tail, indent=" "): def skeleton(routine): - """The generated part of the correctness proof of `routine`: unfold, extract the lets under - SSA names, record every instruction's defining equation (by `rfl`, in `%`/`/` form), make - all the locals opaque, then per instruction derive the linear facts from its equation and - clear the equation. Each derived fact is an instance of one lemma (`Nat.mod_add_div`, - `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, or a carry lemma from the spec file's preamble), so a - step costs nothing wherever it sits and names the facts it rests on; `omega` is left to the - hand-written annotations, which go after the facts of the group whose marker - (`-- : `) names the register they need. - - The values are cleared in one `clear_value`, last local first: clearing a local reverts - every later local whose value mentions it, so one call per local is quadratic in the length - of the chain, and the multiplication routine's chain of 380 locals took over a minute.""" + """The generated part of the correctness proof of `routine`: unfold the routine in `hr` and + lift its lets to the top; then, instruction by instruction, extract that instruction's lets + from `hr` under SSA names, record their defining equations (by `rfl`, in `%`/`/` form), make + the locals opaque, and derive the linear facts from the equations, clearing the equations + the later steps do not need. Each derived fact is an instance of one lemma + (`Nat.mod_add_div`, `Nat.mod_lt`, `Nat.div_lt_of_lt_mul`, or a carry lemma from the spec + file's preamble), so a step costs nothing wherever it sits and names the facts it rests on; + `omega` is left to the hand-written annotations, which go after the facts of the group whose + marker (`-- : `) names the register they need. + + Extracting one instruction at a time (`extract_lets +onlyGivenNames`) keeps the rest of the + chain folded inside `hr`, so that `clear_value` has one hypothesis to revert and re-check. + With every let extracted up front, each `clear_value` re-checks all the later locals and + equations, which is quadratic in the chain's length and exhausted the heartbeat budget on + the multiplication routine's 264 locals.""" e = routine.emitter live = e.liveness(routine.result_names) entries = [en for en, keep in zip(e.entries, live) if keep] @@ -498,11 +501,8 @@ def skeleton(routine): narrow = set() # `lsr` results, whose bound is below 2^64 and needs weakening out = [f" -- generated skeleton for `{routine.name}`: do not edit between the annotations", f" unfold {routine.name} at hr", " lift_lets at hr"] - out += wrap_tactic("extract_lets", names, " at hr") - out.append(" subst hr") products, shifts = {}, {} - eqs = [] # the `have e_… := rfl` lines, emitted before the single `clear_value` - facts = [] # the derived-fact lines, per group, emitted after it + eqs = [] # the current group's `have e_… := rfl` lines def r(op): # operand as written in the entry, renamed to its SSA name at that point return ren.get(op, op) @@ -528,7 +528,8 @@ def eq(nm, rhs): # The group's marker: the register it writes, then the instruction. Annotation blocks # are placed after the group they name. label = names[i + 1] if kind in ("adds", "subs") else nm - lines = [f" -- {label}: {en['comment']}"] + group = names[i:i + 3] if kind in ("adds", "subs") else [nm] + eqs, lines = [], [] # Every step records only facts `omega` handles cheaply later: linear equations, bounds, # and at most a disjunction. The `%`/`/` equations are derived by `rfl`, used to prove # those facts, and cleared. @@ -599,12 +600,12 @@ def eq(nm, rhs): val = f"({a} + {b} + {cin})" lin = f"{xn} + 2^64 * {cn} = {a} + {b} + {cin}" lin_proof = "Nat.mod_add_div _ _" - carry_proof = f"addc_carry_le_one _ _ _ {lt64(a)} {lt64(b)} {le1(cin)}" + carry_proof = f"addc_carry_le_one {a} {b} {cin} {lt64(a)} {lt64(b)} {le1(cin)}" else: val = f"({a} + 2^64 - {b} - (1 - {cin}))" lin = f"{xn} + 2^64 * {cn} + {b} + 1 = {a} + 2^64 + {cin}" - lin_proof = f"subc_lin _ _ _ {lt64(b)} {le1(cin)}" - carry_proof = f"subc_carry_le_one _ _ _ {lt64(a)}" + lin_proof = f"subc_lin {a} {b} {cin} {lt64(b)} {le1(cin)}" + carry_proof = f"subc_carry_le_one {a} {b} {cin} {lt64(a)}" eq(xn, f"{val} % 2^64") eq(cn, f"{val} / 2^64") lines.append(f" have l_{xn} : {lin} := by") @@ -623,16 +624,16 @@ def eq(nm, rhs): lines.append(f" have b_{nm} : {nm} < 2^64 := by rw [e_{nm}]; exact Nat.mod_lt _ (Nat.two_pow_pos _)") lines.append(f" obtain ⟨k_{nm}, b_k_{nm}, l_{nm}⟩ :") lines.append(f" ∃ k, k ≤ 1 ∧ {nm} + 2^64 * k = {a} + {b} + {cin} :=") - lines.append(f" ⟨({a} + {b} + {cin}) / 2^64, addc_carry_le_one _ _ _ {lt64(a)} {lt64(b)} {le1(cin)},") + lines.append(f" ⟨({a} + {b} + {cin}) / 2^64, addc_carry_le_one {a} {b} {cin} {lt64(a)} {lt64(b)} {le1(cin)},") lines.append(f" by rw [e_{nm}]; exact Nat.mod_add_div _ _⟩") lines.append(f" clear e_{nm}") bnd[nm] = f"b_{nm}" elif kind == "subs_carry": a, b, cin = ops eq(nm, f"({a} + 2^64 - {b} - (1 - {cin})) / 2^64") - lines.append(f" have b_{nm} : {nm} ≤ 1 := by rw [e_{nm}]; exact subc_carry_le_one _ _ _ {lt64(a)}") + lines.append(f" have b_{nm} : {nm} ≤ 1 := by rw [e_{nm}]; exact subc_carry_le_one {a} {b} {cin} {lt64(a)}") lines.append(f" have l_{nm} : ({nm} = 1 ∧ {b} + 1 ≤ {a} + {cin}) ∨ ({nm} = 0 ∧ {a} + {cin} < {b} + 1) :=") - lines.append(f" subc_carry_cases _ _ _ _ e_{nm} {lt64(a)} {lt64(b)} {le1(cin)}") + lines.append(f" subc_carry_cases {a} {b} {cin} _ e_{nm} {lt64(a)} {lt64(b)} {le1(cin)}") lines.append(f" clear e_{nm}") bnd[nm] = f"b_{nm}" elif kind == "csel": @@ -654,11 +655,13 @@ def eq(nm, rhs): else: raise ValueError(kind) ren[en["name"]] = nm - facts += lines + out.append(f" -- {label}: {en['comment']}") + out += wrap_tactic("extract_lets +onlyGivenNames", group, " at hr") + out += eqs + out.append(f" clear_value {' '.join(group)}") + out += lines i += 1 - out += eqs - out += wrap_tactic("clear_value", list(reversed(names)), "") - out += facts + out.append(" subst hr") return out def check_spec(path, routines): From bd96831a986d4036ae6768e7673bf6021a655ff4 Mon Sep 17 00:00:00 2001 From: Daira-Emma Hopwood Date: Wed, 9 Sep 2026 22:36:08 +0100 Subject: [PATCH 9/9] asm: prove the Montgomery multiplication correct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `mulMont_spec`: the result is below `p` and `2^256 * r ≡ lhs * rhs (mod p)`, under two arithmetic conditions. The first, for each of `rhs_1`, `rhs_2`, `rhs_3`, is `lhs * (rhs_i + 1) + p + 3 * 2^254 + 2^128 ≤ 2^320`: it keeps the five-limb accumulator, which enters each round below `lhs + p`, below `2^320` through the round's `adc`s, the last of which discards its carry. The second, `lhs * rhs < 2^256 * p`, keeps the final accumulator below `2 * p`, which one conditional subtraction reduces. The corollaries `mulMont_spec_of_lhs_lt` (`lhs < p`, any four-limb `rhs`) and `mulMont_spec_of_rhs_lt` (any four-limb `lhs`, `rhs < p` with limbs 1 to 3 at most `2^64 - 3`) are the two operand contracts. The proof is the generated skeleton with a fold block and a reduction block per round and a conclusion block: each fold block sums the two carry chains, shows that neither `adc` wraps, and states the accumulator as the previous one plus `lhs * rhs_i`; each reduction block rewrites the cancellation fact to a linear equation, shows that the reduction's `adc`s do not wrap, states the round invariant, and bounds the shifted accumulator below `lhs + p`. The theorem raises its heartbeat budget: its sixty-odd `clear * -` calls in a context of a thousand hypotheses exceed the default in total although none is slow. The design document records the theorem and the sharpened limb bound, and the README's list of what is present mentions the proof. Co-authored-by: Claude Fable 5.1 --- CompElliptic/Asm/AArch64/PastaMulSpec.lean | 1738 ++++++++++++++++++++ README.md | 7 +- design/aarch64-pasta-mul-verification.md | 63 +- 3 files changed, 1779 insertions(+), 29 deletions(-) diff --git a/CompElliptic/Asm/AArch64/PastaMulSpec.lean b/CompElliptic/Asm/AArch64/PastaMulSpec.lean index b293c8f..22973cb 100644 --- a/CompElliptic/Asm/AArch64/PastaMulSpec.lean +++ b/CompElliptic/Asm/AArch64/PastaMulSpec.lean @@ -996,4 +996,1742 @@ theorem fromMont_spec (value modulus : Limbs) (inv : Nat) (hv : value.Bounded) exact ⟨by omega, modEq_of_add_mul _ _ (2^256) Q _ (by omega)⟩ -- END conclusion +-- BEGIN mulMont_spec statement +-- The proof is about 1600 lines of small steps: the generated skeleton is cheap, but its +-- annotation blocks run some sixty `clear * -` calls in a context of a thousand hypotheses, +-- and their total exceeds the default per-declaration budget. +set_option maxHeartbeats 1000000 in +/-- Montgomery multiplication: the result is below `p` and `2^256 * result ≡ lhs * rhs (mod p)`, +under two arithmetic conditions that each operand contract implies (`mulMont_spec_of_lhs_lt` and +`mulMont_spec_of_rhs_lt`). `hsafe` keeps the five-limb accumulator below `2^320` in rounds 1 to 3, +where it holds the previous round's result (below `lhs + p`) plus `lhs * rhs_i`, and then the low +limbs of the reduction; without it the `adc` that closes each fold can drop a carry. `hfinal` keeps +the final accumulator below `2 * p`, which one conditional subtraction reduces. -/ +theorem mulMont_spec (lhs rhs modulus : Limbs) (inv : Nat) (hlhs : lhs.Bounded) + (hrhs : rhs.Bounded) (hm : modulus.Bounded) (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) + (hinv_lt : inv < 2^64) (hinv : (inv * modulus.l0 + 1) % 2^64 = 0) + (hsafe : lhs.toNat * (rhs.l1 + 1) + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320 ∧ + lhs.toNat * (rhs.l2 + 1) + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320 ∧ + lhs.toNat * (rhs.l3 + 1) + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320) + (hfinal : lhs.toNat * rhs.toNat < 2^256 * modulus.toNat) : + ∀ r, r = mulMont lhs rhs modulus inv → + r.Bounded ∧ r.toNat < modulus.toNat ∧ + 2^256 * r.toNat ≡ lhs.toNat * rhs.toNat [MOD modulus.toNat] := by + intro r hr +-- END mulMont_spec statement + -- generated skeleton for `mulMont`: do not edit between the annotations + unfold mulMont at hr + lift_lets at hr + -- x4: argument + extract_lets +onlyGivenNames x4 at hr + have e_x4 : x4 = inv := rfl + clear_value x4 + have b_x4 : x4 < 2^64 := by rw [e_x4]; exact hinv_lt + -- x10: ldp x10,x11,[x1] + extract_lets +onlyGivenNames x10 at hr + have e_x10 : x10 = lhs.l0 := rfl + clear_value x10 + have b_x10 : x10 < 2^64 := by rw [e_x10]; exact hlhs.1 + -- x11: ldp x10,x11,[x1] + extract_lets +onlyGivenNames x11 at hr + have e_x11 : x11 = lhs.l1 := rfl + clear_value x11 + have b_x11 : x11 < 2^64 := by rw [e_x11]; exact hlhs.2.1 + -- x9: ldr x9,[x2] + extract_lets +onlyGivenNames x9 at hr + have e_x9 : x9 = rhs.l0 := rfl + clear_value x9 + have b_x9 : x9 < 2^64 := by rw [e_x9]; exact hrhs.1 + -- x12: ldp x12,x13,[x1,#16] + extract_lets +onlyGivenNames x12 at hr + have e_x12 : x12 = lhs.l2 := rfl + clear_value x12 + have b_x12 : x12 < 2^64 := by rw [e_x12]; exact hlhs.2.2.1 + -- x13: ldp x12,x13,[x1,#16] + extract_lets +onlyGivenNames x13 at hr + have e_x13 : x13 = lhs.l3 := rfl + clear_value x13 + have b_x13 : x13 < 2^64 := by rw [e_x13]; exact hlhs.2.2.2 + -- x19: mul x19,x10,x9 + extract_lets +onlyGivenNames x19 at hr + have e_x19 : x19 = x10 * x9 % 2^64 := rfl + clear_value x19 + have b_x19 : x19 < 2^64 := by rw [e_x19]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x5: ldp x5,x6,[x3] + extract_lets +onlyGivenNames x5 at hr + have e_x5 : x5 = modulus.l0 := rfl + clear_value x5 + have b_x5 : x5 < 2^64 := by rw [e_x5]; exact hm.1 + -- x6: ldp x5,x6,[x3] + extract_lets +onlyGivenNames x6 at hr + have e_x6 : x6 = modulus.l1 := rfl + clear_value x6 + have b_x6 : x6 < 2^64 := by rw [e_x6]; exact hm.2.1 + -- x20: mul x20,x11,x9 + extract_lets +onlyGivenNames x20 at hr + have e_x20 : x20 = x11 * x9 % 2^64 := rfl + clear_value x20 + have b_x20 : x20 < 2^64 := by rw [e_x20]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x8: ldp x7,x8,[x3,#16] + extract_lets +onlyGivenNames x8 at hr + have e_x8 : x8 = modulus.l3 := rfl + clear_value x8 + have b_x8 : x8 < 2^64 := by rw [e_x8]; exact hm.2.2.2 + -- x21: mul x21,x12,x9 + extract_lets +onlyGivenNames x21 at hr + have e_x21 : x21 = x12 * x9 % 2^64 := rfl + clear_value x21 + have b_x21 : x21 < 2^64 := by rw [e_x21]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22: mul x22,x13,x9 + extract_lets +onlyGivenNames x22 at hr + have e_x22 : x22 = x13 * x9 % 2^64 := rfl + clear_value x22 + have b_x22 : x22 < 2^64 := by rw [e_x22]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x14: umulh x14,x10,x9 + extract_lets +onlyGivenNames x14 at hr + have e_x14 : x14 = x10 * x9 / 2^64 := rfl + clear_value x14 + have p_x14 : x10 * x9 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x10 b_x9 + have b_x14 : x14 < 2^64 := by rw [e_x14]; exact Nat.div_lt_of_lt_mul p_x14 + have d_x14 : x19 + 2^64 * x14 = x10 * x9 := by + rw [e_x19, e_x14]; exact Nat.mod_add_div _ _ + clear e_x19 e_x14 + -- x15: umulh x15,x11,x9 + extract_lets +onlyGivenNames x15 at hr + have e_x15 : x15 = x11 * x9 / 2^64 := rfl + clear_value x15 + have p_x15 : x11 * x9 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x11 b_x9 + have b_x15 : x15 < 2^64 := by rw [e_x15]; exact Nat.div_lt_of_lt_mul p_x15 + have d_x15 : x20 + 2^64 * x15 = x11 * x9 := by + rw [e_x20, e_x15]; exact Nat.mod_add_div _ _ + clear e_x20 e_x15 + -- x3: mul x3,x4,x19 + extract_lets +onlyGivenNames x3 at hr + have e_x3 : x3 = x4 * x19 % 2^64 := rfl + clear_value x3 + have b_x3 : x3 < 2^64 := by rw [e_x3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x16: umulh x16,x12,x9 + extract_lets +onlyGivenNames x16 at hr + have e_x16 : x16 = x12 * x9 / 2^64 := rfl + clear_value x16 + have p_x16 : x12 * x9 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x12 b_x9 + have b_x16 : x16 < 2^64 := by rw [e_x16]; exact Nat.div_lt_of_lt_mul p_x16 + have d_x16 : x21 + 2^64 * x16 = x12 * x9 := by + rw [e_x21, e_x16]; exact Nat.mod_add_div _ _ + clear e_x21 e_x16 + -- x17: umulh x17,x13,x9 + extract_lets +onlyGivenNames x17 at hr + have e_x17 : x17 = x13 * x9 / 2^64 := rfl + clear_value x17 + have p_x17 : x13 * x9 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x13 b_x9 + have b_x17 : x17 < 2^64 := by rw [e_x17]; exact Nat.div_lt_of_lt_mul p_x17 + have d_x17 : x22 + 2^64 * x17 = x13 * x9 := by + rw [e_x22, e_x17]; exact Nat.mod_add_div _ _ + clear e_x22 e_x17 + -- x20_1: adds x20,x20,x14 + extract_lets +onlyGivenNames s x20_1 c at hr + have e_x20_1 : x20_1 = (x20 + x14 + 0) % 2^64 := rfl + have e_c : c = (x20 + x14 + 0) / 2^64 := rfl + clear_value s x20_1 c + have l_x20_1 : x20_1 + 2^64 * c = x20 + x14 + 0 := by + rw [e_x20_1, e_c]; exact Nat.mod_add_div _ _ + have b_x20_1 : x20_1 < 2^64 := by rw [e_x20_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c : c ≤ 1 := by + rw [e_c]; exact addc_carry_le_one x20 x14 0 b_x20 b_x14 (by decide) + clear e_x20_1 e_c + -- x21_1: adcs x21,x21,x15 + extract_lets +onlyGivenNames s_1 x21_1 c_1 at hr + have e_x21_1 : x21_1 = (x21 + x15 + c) % 2^64 := rfl + have e_c_1 : c_1 = (x21 + x15 + c) / 2^64 := rfl + clear_value s_1 x21_1 c_1 + have l_x21_1 : x21_1 + 2^64 * c_1 = x21 + x15 + c := by + rw [e_x21_1, e_c_1]; exact Nat.mod_add_div _ _ + have b_x21_1 : x21_1 < 2^64 := by rw [e_x21_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_1 : c_1 ≤ 1 := by + rw [e_c_1]; exact addc_carry_le_one x21 x15 c b_x21 b_x15 b_c + clear e_x21_1 e_c_1 + -- x15_1: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_1 at hr + have e_x15_1 : x15_1 = x6 * x3 % 2^64 := rfl + clear_value x15_1 + have b_x15_1 : x15_1 < 2^64 := by rw [e_x15_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_1: adcs x22,x22,x16 + extract_lets +onlyGivenNames s_2 x22_1 c_2 at hr + have e_x22_1 : x22_1 = (x22 + x16 + c_1) % 2^64 := rfl + have e_c_2 : c_2 = (x22 + x16 + c_1) / 2^64 := rfl + clear_value s_2 x22_1 c_2 + have l_x22_1 : x22_1 + 2^64 * c_2 = x22 + x16 + c_1 := by + rw [e_x22_1, e_c_2]; exact Nat.mod_add_div _ _ + have b_x22_1 : x22_1 < 2^64 := by rw [e_x22_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_2 : c_2 ≤ 1 := by + rw [e_c_2]; exact addc_carry_le_one x22 x16 c_1 b_x22 b_x16 b_c_1 + clear e_x22_1 e_c_2 + -- x23: adc x23,xzr,x17 + extract_lets +onlyGivenNames x23 at hr + have e_x23 : x23 = (0 + x17 + c_2) % 2^64 := rfl + clear_value x23 + have b_x23 : x23 < 2^64 := by rw [e_x23]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23, b_k_x23, l_x23⟩ : + ∃ k, k ≤ 1 ∧ x23 + 2^64 * k = 0 + x17 + c_2 := + ⟨(0 + x17 + c_2) / 2^64, addc_carry_le_one 0 x17 c_2 (by decide) b_x17 b_c_2, + by rw [e_x23]; exact Nat.mod_add_div _ _⟩ + clear e_x23 + -- BEGIN round 0 fold + have hP : modulus.toNat = x5 + 2^64 * x6 + 2^192 * 2^62 := by + rw [e_x5, e_x6]; simp only [Limbs.toNat, hshape.1, hshape.2, Nat.mul_zero, Nat.add_zero] + have hP_lt : modulus.toNat < 2^255 := by clear * - hP b_x5 b_x6; omega + have hL256 : lhs.toNat < 2^256 := by + clear * - e_x10 e_x11 e_x12 e_x13 b_x10 b_x11 b_x12 b_x13 + simp only [Limbs.toNat]; omega + -- `lhs * rhs_0` as the sum of the limb products. + have hL_0 : lhs.toNat * x9 + = x10 * x9 + 2^64 * (x11 * x9) + 2^128 * (x12 * x9) + 2^192 * (x13 * x9) := by + rw [e_x10, e_x11, e_x12, e_x13]; simp only [Limbs.toNat]; ring + -- The one `adc` of this round's fold cannot wrap: the high half of a product of two limbs + -- is at most `2^64 - 2`. + have hx17 : x13 * x9 ≤ (2^64 - 1) * (2^64 - 1) := + Nat.mul_le_mul (Nat.le_sub_one_of_lt b_x13) (Nat.le_sub_one_of_lt b_x9) + norm_num at hx17 + have hk_0 : k_x23 = 0 := by + clear * - l_x23 d_x17 hx17 b_c_2 + omega + have F_0 : x19 + 2^64 * x20_1 + 2^128 * x21_1 + 2^192 * x22_1 + 2^256 * x23 = lhs.toNat * x9 := by + clear * - l_x20_1 l_x21_1 l_x22_1 l_x23 d_x14 d_x15 d_x16 d_x17 hL_0 hk_0 + omega + -- END round 0 fold + -- x17_1: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_1 at hr + have e_x17_1 : x17_1 = x3 * 2^62 % 2^64 := rfl + clear_value x17_1 + have b_x17_1 : x17_1 < 2^64 := by rw [e_x17_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x9_1: ldr x9,[x2,8*1] + extract_lets +onlyGivenNames x9_1 at hr + have e_x9_1 : x9_1 = rhs.l1 := rfl + clear_value x9_1 + have b_x9_1 : x9_1 < 2^64 := by rw [e_x9_1]; exact hrhs.2.1 + -- c_3: subs xzr,x19,#1 + extract_lets +onlyGivenNames c_3 at hr + have e_c_3 : c_3 = (x19 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_3 + have b_c_3 : c_3 ≤ 1 := by rw [e_c_3]; exact subc_carry_le_one x19 1 1 b_x19 + have l_c_3 : (c_3 = 1 ∧ 1 + 1 ≤ x19 + 1) ∨ (c_3 = 0 ∧ x19 + 1 < 1 + 1) := + subc_carry_cases x19 1 1 _ e_c_3 b_x19 (by decide) (by decide) + clear e_c_3 + -- x14_1: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_1 at hr + have e_x14_1 : x14_1 = x5 * x3 / 2^64 := rfl + clear_value x14_1 + have p_x14_1 : x5 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3 + have b_x14_1 : x14_1 < 2^64 := by rw [e_x14_1]; exact Nat.div_lt_of_lt_mul p_x14_1 + obtain ⟨lo_x14_1, b_lo_x14_1, d_x14_1⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_1 = x5 * x3 := + ⟨x5 * x3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_1]; exact Nat.mod_add_div _ _⟩ + clear e_x14_1 + -- x20_2: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_3 x20_2 c_4 at hr + have e_x20_2 : x20_2 = (x20_1 + x15_1 + c_3) % 2^64 := rfl + have e_c_4 : c_4 = (x20_1 + x15_1 + c_3) / 2^64 := rfl + clear_value s_3 x20_2 c_4 + have l_x20_2 : x20_2 + 2^64 * c_4 = x20_1 + x15_1 + c_3 := by + rw [e_x20_2, e_c_4]; exact Nat.mod_add_div _ _ + have b_x20_2 : x20_2 < 2^64 := by rw [e_x20_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_4 : c_4 ≤ 1 := by + rw [e_c_4]; exact addc_carry_le_one x20_1 x15_1 c_3 b_x20_1 b_x15_1 b_c_3 + clear e_x20_2 e_c_4 + -- x15_2: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_2 at hr + have e_x15_2 : x15_2 = x6 * x3 / 2^64 := rfl + clear_value x15_2 + have p_x15_2 : x6 * x3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3 + have b_x15_2 : x15_2 < 2^64 := by rw [e_x15_2]; exact Nat.div_lt_of_lt_mul p_x15_2 + have d_x15_2 : x15_1 + 2^64 * x15_2 = x6 * x3 := by + rw [e_x15_1, e_x15_2]; exact Nat.mod_add_div _ _ + clear e_x15_1 e_x15_2 + -- x21_2: adcs x21,x21,xzr + extract_lets +onlyGivenNames s_4 x21_2 c_5 at hr + have e_x21_2 : x21_2 = (x21_1 + 0 + c_4) % 2^64 := rfl + have e_c_5 : c_5 = (x21_1 + 0 + c_4) / 2^64 := rfl + clear_value s_4 x21_2 c_5 + have l_x21_2 : x21_2 + 2^64 * c_5 = x21_1 + 0 + c_4 := by + rw [e_x21_2, e_c_5]; exact Nat.mod_add_div _ _ + have b_x21_2 : x21_2 < 2^64 := by rw [e_x21_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_5 : c_5 ≤ 1 := by + rw [e_c_5]; exact addc_carry_le_one x21_1 0 c_4 b_x21_1 (by decide) b_c_4 + clear e_x21_2 e_c_5 + -- x22_2: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_5 x22_2 c_6 at hr + have e_x22_2 : x22_2 = (x22_1 + x17_1 + c_5) % 2^64 := rfl + have e_c_6 : c_6 = (x22_1 + x17_1 + c_5) / 2^64 := rfl + clear_value s_5 x22_2 c_6 + have l_x22_2 : x22_2 + 2^64 * c_6 = x22_1 + x17_1 + c_5 := by + rw [e_x22_2, e_c_6]; exact Nat.mod_add_div _ _ + have b_x22_2 : x22_2 < 2^64 := by rw [e_x22_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_6 : c_6 ≤ 1 := by + rw [e_c_6]; exact addc_carry_le_one x22_1 x17_1 c_5 b_x22_1 b_x17_1 b_c_5 + clear e_x22_2 e_c_6 + -- x17_2: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_2 at hr + have e_x17_2 : x17_2 = x3 / 2^2 := rfl + clear_value x17_2 + have b_x17_2 : x17_2 < 2^62 := by + rw [e_x17_2]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3 (by norm_num)) + have sh_x17_2 : x17_1 + 2^64 * x17_2 = x3 * 2^62 := by + rw [e_x17_1, e_x17_2]; exact lsl62_lsr2_split _ + clear e_x17_1 e_x17_2 + -- x23_1: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_1 at hr + have e_x23_1 : x23_1 = (x23 + 0 + c_6) % 2^64 := rfl + clear_value x23_1 + have b_x23_1 : x23_1 < 2^64 := by rw [e_x23_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_1, b_k_x23_1, l_x23_1⟩ : + ∃ k, k ≤ 1 ∧ x23_1 + 2^64 * k = x23 + 0 + c_6 := + ⟨(x23 + 0 + c_6) / 2^64, addc_carry_le_one x23 0 c_6 b_x23 (by decide) b_c_6, + by rw [e_x23_1]; exact Nat.mod_add_div _ _⟩ + clear e_x23_1 + -- x19_1: adds x19,x20,x14 + extract_lets +onlyGivenNames s_6 x19_1 c_7 at hr + have e_x19_1 : x19_1 = (x20_2 + x14_1 + 0) % 2^64 := rfl + have e_c_7 : c_7 = (x20_2 + x14_1 + 0) / 2^64 := rfl + clear_value s_6 x19_1 c_7 + have l_x19_1 : x19_1 + 2^64 * c_7 = x20_2 + x14_1 + 0 := by + rw [e_x19_1, e_c_7]; exact Nat.mod_add_div _ _ + have b_x19_1 : x19_1 < 2^64 := by rw [e_x19_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_7 : c_7 ≤ 1 := by + rw [e_c_7]; exact addc_carry_le_one x20_2 x14_1 0 b_x20_2 b_x14_1 (by decide) + clear e_x19_1 e_c_7 + -- x14_2: mul x14,x10,x9 + extract_lets +onlyGivenNames x14_2 at hr + have e_x14_2 : x14_2 = x10 * x9_1 % 2^64 := rfl + clear_value x14_2 + have b_x14_2 : x14_2 < 2^64 := by rw [e_x14_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x20_3: adcs x20,x21,x15 + extract_lets +onlyGivenNames s_7 x20_3 c_8 at hr + have e_x20_3 : x20_3 = (x21_2 + x15_2 + c_7) % 2^64 := rfl + have e_c_8 : c_8 = (x21_2 + x15_2 + c_7) / 2^64 := rfl + clear_value s_7 x20_3 c_8 + have l_x20_3 : x20_3 + 2^64 * c_8 = x21_2 + x15_2 + c_7 := by + rw [e_x20_3, e_c_8]; exact Nat.mod_add_div _ _ + have b_x20_3 : x20_3 < 2^64 := by rw [e_x20_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_8 : c_8 ≤ 1 := by + rw [e_c_8]; exact addc_carry_le_one x21_2 x15_2 c_7 b_x21_2 b_x15_2 b_c_7 + clear e_x20_3 e_c_8 + -- x15_3: mul x15,x11,x9 + extract_lets +onlyGivenNames x15_3 at hr + have e_x15_3 : x15_3 = x11 * x9_1 % 2^64 := rfl + clear_value x15_3 + have b_x15_3 : x15_3 < 2^64 := by rw [e_x15_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x21_3: adcs x21,x22,xzr + extract_lets +onlyGivenNames s_8 x21_3 c_9 at hr + have e_x21_3 : x21_3 = (x22_2 + 0 + c_8) % 2^64 := rfl + have e_c_9 : c_9 = (x22_2 + 0 + c_8) / 2^64 := rfl + clear_value s_8 x21_3 c_9 + have l_x21_3 : x21_3 + 2^64 * c_9 = x22_2 + 0 + c_8 := by + rw [e_x21_3, e_c_9]; exact Nat.mod_add_div _ _ + have b_x21_3 : x21_3 < 2^64 := by rw [e_x21_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_9 : c_9 ≤ 1 := by + rw [e_c_9]; exact addc_carry_le_one x22_2 0 c_8 b_x22_2 (by decide) b_c_8 + clear e_x21_3 e_c_9 + -- x16_1: mul x16,x12,x9 + extract_lets +onlyGivenNames x16_1 at hr + have e_x16_1 : x16_1 = x12 * x9_1 % 2^64 := rfl + clear_value x16_1 + have b_x16_1 : x16_1 < 2^64 := by rw [e_x16_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_3: adcs x22,x23,x17 + extract_lets +onlyGivenNames s_9 x22_3 c_10 at hr + have e_x22_3 : x22_3 = (x23_1 + x17_2 + c_9) % 2^64 := rfl + have e_c_10 : c_10 = (x23_1 + x17_2 + c_9) / 2^64 := rfl + clear_value s_9 x22_3 c_10 + have l_x22_3 : x22_3 + 2^64 * c_10 = x23_1 + x17_2 + c_9 := by + rw [e_x22_3, e_c_10]; exact Nat.mod_add_div _ _ + have b_x22_3 : x22_3 < 2^64 := by rw [e_x22_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_10 : c_10 ≤ 1 := by + rw [e_c_10]; exact addc_carry_le_one x23_1 x17_2 c_9 b_x23_1 (lt_of_lt_of_le b_x17_2 (by norm_num)) b_c_9 + clear e_x22_3 e_c_10 + -- x17_3: mul x17,x13,x9 + extract_lets +onlyGivenNames x17_3 at hr + have e_x17_3 : x17_3 = x13 * x9_1 % 2^64 := rfl + clear_value x17_3 + have b_x17_3 : x17_3 < 2^64 := by rw [e_x17_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x23_2: adc x23,xzr,xzr + extract_lets +onlyGivenNames x23_2 at hr + have e_x23_2 : x23_2 = (0 + 0 + c_10) % 2^64 := rfl + clear_value x23_2 + have b_x23_2 : x23_2 < 2^64 := by rw [e_x23_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_2, b_k_x23_2, l_x23_2⟩ : + ∃ k, k ≤ 1 ∧ x23_2 + 2^64 * k = 0 + 0 + c_10 := + ⟨(0 + 0 + c_10) / 2^64, addc_carry_le_one 0 0 c_10 (by decide) (by decide) b_c_10, + by rw [e_x23_2]; exact Nat.mod_add_div _ _⟩ + clear e_x23_2 + -- BEGIN round 0 reduction + -- Cancellation: the low limb of `x19 + p0 * x3` is zero, so `x19 + lo_x14_1` is + -- `0` or `2^64`, and `subs xzr, x19, #1` set the carry exactly when it is `2^64`. + have hc_0 : x19 + lo_x14_1 = 2^64 * c_3 := by + have h := cancel_low x19 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3, ← d_x14_1, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_1] at h + clear * - h b_x19 b_lo_x14_1 l_c_3 + omega + have bc_0 : c_3 ≤ 1 := by clear * - l_c_3; omega + have hPq_0 : x3 * modulus.toNat = x5 * x3 + 2^64 * (x6 * x3) + 2^254 * x3 := by + rw [hP]; ring + -- `x17_1` is the low two bits of `x3` at the top of a limb. + have hsh_0 : x17_1 ≤ 3 * 2^62 := by + clear * - sh_x17_2 b_x17_1 b_x17_2; omega + -- The reduction's carry chain, summed with the limb weights. + have hsum'_0 : x19 + 2^64 * x20_2 + 2^128 * x21_2 + 2^192 * x22_2 + 2^256 * x23_1 + + 2^320 * k_x23_1 + = x19 + 2^64 * x20_1 + 2^128 * x21_1 + 2^192 * x22_1 + 2^256 * x23 + + 2^64 * x15_1 + 2^64 * c_3 + 2^192 * x17_1 := by + clear * - l_x20_2 l_x21_2 l_x22_2 l_x23_1 + omega + -- Neither `adc` of the reduction wraps: `lhs * rhs_0` is below `2^320 - 2^256`, and the + -- reduction adds less than `2^256` to the five-limb accumulator before the shift. + have hF0b : lhs.toNat * x9 ≤ (2^256 - 1) * (2^64 - 1) := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hL256) (Nat.le_sub_one_of_lt b_x9) + norm_num at hF0b + have hkr_0 : k_x23_1 = 0 := by + clear * - hsum'_0 F_0 hF0b b_x15_1 bc_0 hsh_0 + omega + have hks_0 : k_x23_2 = 0 := by clear * - l_x23_2 b_c_10; omega + have I_0 : 2^64 * (x19_1 + 2^64 * x20_3 + 2^128 * x21_3 + 2^192 * x22_3 + 2^256 * x23_2) + = x19 + 2^64 * x20_1 + 2^128 * x21_1 + 2^192 * x22_1 + 2^256 * x23 + + x3 * modulus.toNat := by + clear * - hc_0 d_x14_1 d_x15_2 sh_x17_2 l_x20_2 l_x21_2 l_x22_2 l_x23_1 l_x19_1 l_x20_3 l_x21_3 + l_x22_3 l_x23_2 hkr_0 hks_0 hPq_0 + omega + -- The shifted accumulator stays below `lhs + p`. + have hLx_0 : lhs.toNat * x9 + lhs.toNat ≤ lhs.toNat * 2^64 := by + rw [← Nat.mul_succ]; exact Nat.mul_le_mul_left _ b_x9 + have hqP_0 : x3 * modulus.toNat + modulus.toNat ≤ 2^64 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ b_x3 + have B_0 : x19_1 + 2^64 * x20_3 + 2^128 * x21_3 + 2^192 * x22_3 + 2^256 * x23_2 + < lhs.toNat + modulus.toNat := by + clear * - I_0 F_0 hLx_0 hqP_0 hP + omega + have t_0 : x23_2 ≤ 1 := by clear * - l_x23_2 hks_0 b_c_10; omega + -- END round 0 reduction + -- x19_2: adds x19,x19,x14 + extract_lets +onlyGivenNames s_10 x19_2 c_11 at hr + have e_x19_2 : x19_2 = (x19_1 + x14_2 + 0) % 2^64 := rfl + have e_c_11 : c_11 = (x19_1 + x14_2 + 0) / 2^64 := rfl + clear_value s_10 x19_2 c_11 + have l_x19_2 : x19_2 + 2^64 * c_11 = x19_1 + x14_2 + 0 := by + rw [e_x19_2, e_c_11]; exact Nat.mod_add_div _ _ + have b_x19_2 : x19_2 < 2^64 := by rw [e_x19_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_11 : c_11 ≤ 1 := by + rw [e_c_11]; exact addc_carry_le_one x19_1 x14_2 0 b_x19_1 b_x14_2 (by decide) + clear e_x19_2 e_c_11 + -- x14_3: umulh x14,x10,x9 + extract_lets +onlyGivenNames x14_3 at hr + have e_x14_3 : x14_3 = x10 * x9_1 / 2^64 := rfl + clear_value x14_3 + have p_x14_3 : x10 * x9_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x10 b_x9_1 + have b_x14_3 : x14_3 < 2^64 := by rw [e_x14_3]; exact Nat.div_lt_of_lt_mul p_x14_3 + have d_x14_3 : x14_2 + 2^64 * x14_3 = x10 * x9_1 := by + rw [e_x14_2, e_x14_3]; exact Nat.mod_add_div _ _ + clear e_x14_2 e_x14_3 + -- x20_4: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_11 x20_4 c_12 at hr + have e_x20_4 : x20_4 = (x20_3 + x15_3 + c_11) % 2^64 := rfl + have e_c_12 : c_12 = (x20_3 + x15_3 + c_11) / 2^64 := rfl + clear_value s_11 x20_4 c_12 + have l_x20_4 : x20_4 + 2^64 * c_12 = x20_3 + x15_3 + c_11 := by + rw [e_x20_4, e_c_12]; exact Nat.mod_add_div _ _ + have b_x20_4 : x20_4 < 2^64 := by rw [e_x20_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_12 : c_12 ≤ 1 := by + rw [e_c_12]; exact addc_carry_le_one x20_3 x15_3 c_11 b_x20_3 b_x15_3 b_c_11 + clear e_x20_4 e_c_12 + -- x15_4: umulh x15,x11,x9 + extract_lets +onlyGivenNames x15_4 at hr + have e_x15_4 : x15_4 = x11 * x9_1 / 2^64 := rfl + clear_value x15_4 + have p_x15_4 : x11 * x9_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x11 b_x9_1 + have b_x15_4 : x15_4 < 2^64 := by rw [e_x15_4]; exact Nat.div_lt_of_lt_mul p_x15_4 + have d_x15_4 : x15_3 + 2^64 * x15_4 = x11 * x9_1 := by + rw [e_x15_3, e_x15_4]; exact Nat.mod_add_div _ _ + clear e_x15_3 e_x15_4 + -- x21_4: adcs x21,x21,x16 + extract_lets +onlyGivenNames s_12 x21_4 c_13 at hr + have e_x21_4 : x21_4 = (x21_3 + x16_1 + c_12) % 2^64 := rfl + have e_c_13 : c_13 = (x21_3 + x16_1 + c_12) / 2^64 := rfl + clear_value s_12 x21_4 c_13 + have l_x21_4 : x21_4 + 2^64 * c_13 = x21_3 + x16_1 + c_12 := by + rw [e_x21_4, e_c_13]; exact Nat.mod_add_div _ _ + have b_x21_4 : x21_4 < 2^64 := by rw [e_x21_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_13 : c_13 ≤ 1 := by + rw [e_c_13]; exact addc_carry_le_one x21_3 x16_1 c_12 b_x21_3 b_x16_1 b_c_12 + clear e_x21_4 e_c_13 + -- x3_1: mul x3,x4,x19 + extract_lets +onlyGivenNames x3_1 at hr + have e_x3_1 : x3_1 = x4 * x19_2 % 2^64 := rfl + clear_value x3_1 + have b_x3_1 : x3_1 < 2^64 := by rw [e_x3_1]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x16_2: umulh x16,x12,x9 + extract_lets +onlyGivenNames x16_2 at hr + have e_x16_2 : x16_2 = x12 * x9_1 / 2^64 := rfl + clear_value x16_2 + have p_x16_2 : x12 * x9_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x12 b_x9_1 + have b_x16_2 : x16_2 < 2^64 := by rw [e_x16_2]; exact Nat.div_lt_of_lt_mul p_x16_2 + have d_x16_2 : x16_1 + 2^64 * x16_2 = x12 * x9_1 := by + rw [e_x16_1, e_x16_2]; exact Nat.mod_add_div _ _ + clear e_x16_1 e_x16_2 + -- x22_4: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_13 x22_4 c_14 at hr + have e_x22_4 : x22_4 = (x22_3 + x17_3 + c_13) % 2^64 := rfl + have e_c_14 : c_14 = (x22_3 + x17_3 + c_13) / 2^64 := rfl + clear_value s_13 x22_4 c_14 + have l_x22_4 : x22_4 + 2^64 * c_14 = x22_3 + x17_3 + c_13 := by + rw [e_x22_4, e_c_14]; exact Nat.mod_add_div _ _ + have b_x22_4 : x22_4 < 2^64 := by rw [e_x22_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_14 : c_14 ≤ 1 := by + rw [e_c_14]; exact addc_carry_le_one x22_3 x17_3 c_13 b_x22_3 b_x17_3 b_c_13 + clear e_x22_4 e_c_14 + -- x17_4: umulh x17,x13,x9 + extract_lets +onlyGivenNames x17_4 at hr + have e_x17_4 : x17_4 = x13 * x9_1 / 2^64 := rfl + clear_value x17_4 + have p_x17_4 : x13 * x9_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x13 b_x9_1 + have b_x17_4 : x17_4 < 2^64 := by rw [e_x17_4]; exact Nat.div_lt_of_lt_mul p_x17_4 + have d_x17_4 : x17_3 + 2^64 * x17_4 = x13 * x9_1 := by + rw [e_x17_3, e_x17_4]; exact Nat.mod_add_div _ _ + clear e_x17_3 e_x17_4 + -- x23_3: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_3 at hr + have e_x23_3 : x23_3 = (x23_2 + 0 + c_14) % 2^64 := rfl + clear_value x23_3 + have b_x23_3 : x23_3 < 2^64 := by rw [e_x23_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_3, b_k_x23_3, l_x23_3⟩ : + ∃ k, k ≤ 1 ∧ x23_3 + 2^64 * k = x23_2 + 0 + c_14 := + ⟨(x23_2 + 0 + c_14) / 2^64, addc_carry_le_one x23_2 0 c_14 b_x23_2 (by decide) b_c_14, + by rw [e_x23_3]; exact Nat.mod_add_div _ _⟩ + clear e_x23_3 + -- x20_5: adds x20,x20,x14 + extract_lets +onlyGivenNames s_14 x20_5 c_15 at hr + have e_x20_5 : x20_5 = (x20_4 + x14_3 + 0) % 2^64 := rfl + have e_c_15 : c_15 = (x20_4 + x14_3 + 0) / 2^64 := rfl + clear_value s_14 x20_5 c_15 + have l_x20_5 : x20_5 + 2^64 * c_15 = x20_4 + x14_3 + 0 := by + rw [e_x20_5, e_c_15]; exact Nat.mod_add_div _ _ + have b_x20_5 : x20_5 < 2^64 := by rw [e_x20_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_15 : c_15 ≤ 1 := by + rw [e_c_15]; exact addc_carry_le_one x20_4 x14_3 0 b_x20_4 b_x14_3 (by decide) + clear e_x20_5 e_c_15 + -- x21_5: adcs x21,x21,x15 + extract_lets +onlyGivenNames s_15 x21_5 c_16 at hr + have e_x21_5 : x21_5 = (x21_4 + x15_4 + c_15) % 2^64 := rfl + have e_c_16 : c_16 = (x21_4 + x15_4 + c_15) / 2^64 := rfl + clear_value s_15 x21_5 c_16 + have l_x21_5 : x21_5 + 2^64 * c_16 = x21_4 + x15_4 + c_15 := by + rw [e_x21_5, e_c_16]; exact Nat.mod_add_div _ _ + have b_x21_5 : x21_5 < 2^64 := by rw [e_x21_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_16 : c_16 ≤ 1 := by + rw [e_c_16]; exact addc_carry_le_one x21_4 x15_4 c_15 b_x21_4 b_x15_4 b_c_15 + clear e_x21_5 e_c_16 + -- x15_5: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_5 at hr + have e_x15_5 : x15_5 = x6 * x3_1 % 2^64 := rfl + clear_value x15_5 + have b_x15_5 : x15_5 < 2^64 := by rw [e_x15_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_5: adcs x22,x22,x16 + extract_lets +onlyGivenNames s_16 x22_5 c_17 at hr + have e_x22_5 : x22_5 = (x22_4 + x16_2 + c_16) % 2^64 := rfl + have e_c_17 : c_17 = (x22_4 + x16_2 + c_16) / 2^64 := rfl + clear_value s_16 x22_5 c_17 + have l_x22_5 : x22_5 + 2^64 * c_17 = x22_4 + x16_2 + c_16 := by + rw [e_x22_5, e_c_17]; exact Nat.mod_add_div _ _ + have b_x22_5 : x22_5 < 2^64 := by rw [e_x22_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_17 : c_17 ≤ 1 := by + rw [e_c_17]; exact addc_carry_le_one x22_4 x16_2 c_16 b_x22_4 b_x16_2 b_c_16 + clear e_x22_5 e_c_17 + -- x23_4: adc x23,x23,x17 + extract_lets +onlyGivenNames x23_4 at hr + have e_x23_4 : x23_4 = (x23_3 + x17_4 + c_17) % 2^64 := rfl + clear_value x23_4 + have b_x23_4 : x23_4 < 2^64 := by rw [e_x23_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_4, b_k_x23_4, l_x23_4⟩ : + ∃ k, k ≤ 1 ∧ x23_4 + 2^64 * k = x23_3 + x17_4 + c_17 := + ⟨(x23_3 + x17_4 + c_17) / 2^64, addc_carry_le_one x23_3 x17_4 c_17 b_x23_3 b_x17_4 b_c_17, + by rw [e_x23_4]; exact Nat.mod_add_div _ _⟩ + clear e_x23_4 + -- BEGIN round 1 fold + -- `lhs * rhs_1` as the sum of the limb products. + have hL_1 : lhs.toNat * x9_1 + = x10 * x9_1 + 2^64 * (x11 * x9_1) + 2^128 * (x12 * x9_1) + 2^192 * (x13 * x9_1) := by + rw [e_x10, e_x11, e_x12, e_x13]; simp only [Limbs.toNat]; ring + have hs_1 : lhs.toNat * x9_1 + lhs.toNat + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320 := by + rw [e_x9_1, ← Nat.mul_add_one]; exact hsafe.1 + -- The fold's two carry chains, summed with the limb weights. + have hsum_1 : x19_2 + 2^64 * x20_5 + 2^128 * x21_5 + 2^192 * x22_5 + 2^256 * x23_4 + + 2^320 * (k_x23_3 + k_x23_4) + = x19_1 + 2^64 * x20_3 + 2^128 * x21_3 + 2^192 * x22_3 + 2^256 * x23_2 + + lhs.toNat * x9_1 := by + clear * - l_x19_2 l_x20_4 l_x21_4 l_x22_4 l_x23_3 l_x20_5 l_x21_5 l_x22_5 l_x23_4 d_x14_3 + d_x15_4 d_x16_2 d_x17_4 hL_1 + omega + -- Neither `adc` of the fold wraps: the accumulator entering the round is below + -- `lhs + p`, and `hs_1` bounds it plus `lhs * rhs_1` below `2^320`. + have hk_1 : k_x23_3 = 0 ∧ k_x23_4 = 0 := by + clear * - hsum_1 B_0 hs_1 + omega + have F_1 : x19_2 + 2^64 * x20_5 + 2^128 * x21_5 + 2^192 * x22_5 + 2^256 * x23_4 + = x19_1 + 2^64 * x20_3 + 2^128 * x21_3 + 2^192 * x22_3 + 2^256 * x23_2 + + lhs.toNat * x9_1 := by + clear * - hsum_1 hk_1 + omega + -- END round 1 fold + -- x17_5: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_5 at hr + have e_x17_5 : x17_5 = x3_1 * 2^62 % 2^64 := rfl + clear_value x17_5 + have b_x17_5 : x17_5 < 2^64 := by rw [e_x17_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x9_2: ldr x9,[x2,8*2] + extract_lets +onlyGivenNames x9_2 at hr + have e_x9_2 : x9_2 = rhs.l2 := rfl + clear_value x9_2 + have b_x9_2 : x9_2 < 2^64 := by rw [e_x9_2]; exact hrhs.2.2.1 + -- c_18: subs xzr,x19,#1 + extract_lets +onlyGivenNames c_18 at hr + have e_c_18 : c_18 = (x19_2 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_18 + have b_c_18 : c_18 ≤ 1 := by rw [e_c_18]; exact subc_carry_le_one x19_2 1 1 b_x19_2 + have l_c_18 : (c_18 = 1 ∧ 1 + 1 ≤ x19_2 + 1) ∨ (c_18 = 0 ∧ x19_2 + 1 < 1 + 1) := + subc_carry_cases x19_2 1 1 _ e_c_18 b_x19_2 (by decide) (by decide) + clear e_c_18 + -- x14_4: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_4 at hr + have e_x14_4 : x14_4 = x5 * x3_1 / 2^64 := rfl + clear_value x14_4 + have p_x14_4 : x5 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_1 + have b_x14_4 : x14_4 < 2^64 := by rw [e_x14_4]; exact Nat.div_lt_of_lt_mul p_x14_4 + obtain ⟨lo_x14_4, b_lo_x14_4, d_x14_4⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_4 = x5 * x3_1 := + ⟨x5 * x3_1 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_4]; exact Nat.mod_add_div _ _⟩ + clear e_x14_4 + -- x20_6: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_17 x20_6 c_19 at hr + have e_x20_6 : x20_6 = (x20_5 + x15_5 + c_18) % 2^64 := rfl + have e_c_19 : c_19 = (x20_5 + x15_5 + c_18) / 2^64 := rfl + clear_value s_17 x20_6 c_19 + have l_x20_6 : x20_6 + 2^64 * c_19 = x20_5 + x15_5 + c_18 := by + rw [e_x20_6, e_c_19]; exact Nat.mod_add_div _ _ + have b_x20_6 : x20_6 < 2^64 := by rw [e_x20_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_19 : c_19 ≤ 1 := by + rw [e_c_19]; exact addc_carry_le_one x20_5 x15_5 c_18 b_x20_5 b_x15_5 b_c_18 + clear e_x20_6 e_c_19 + -- x15_6: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_6 at hr + have e_x15_6 : x15_6 = x6 * x3_1 / 2^64 := rfl + clear_value x15_6 + have p_x15_6 : x6 * x3_1 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_1 + have b_x15_6 : x15_6 < 2^64 := by rw [e_x15_6]; exact Nat.div_lt_of_lt_mul p_x15_6 + have d_x15_6 : x15_5 + 2^64 * x15_6 = x6 * x3_1 := by + rw [e_x15_5, e_x15_6]; exact Nat.mod_add_div _ _ + clear e_x15_5 e_x15_6 + -- x21_6: adcs x21,x21,xzr + extract_lets +onlyGivenNames s_18 x21_6 c_20 at hr + have e_x21_6 : x21_6 = (x21_5 + 0 + c_19) % 2^64 := rfl + have e_c_20 : c_20 = (x21_5 + 0 + c_19) / 2^64 := rfl + clear_value s_18 x21_6 c_20 + have l_x21_6 : x21_6 + 2^64 * c_20 = x21_5 + 0 + c_19 := by + rw [e_x21_6, e_c_20]; exact Nat.mod_add_div _ _ + have b_x21_6 : x21_6 < 2^64 := by rw [e_x21_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_20 : c_20 ≤ 1 := by + rw [e_c_20]; exact addc_carry_le_one x21_5 0 c_19 b_x21_5 (by decide) b_c_19 + clear e_x21_6 e_c_20 + -- x22_6: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_19 x22_6 c_21 at hr + have e_x22_6 : x22_6 = (x22_5 + x17_5 + c_20) % 2^64 := rfl + have e_c_21 : c_21 = (x22_5 + x17_5 + c_20) / 2^64 := rfl + clear_value s_19 x22_6 c_21 + have l_x22_6 : x22_6 + 2^64 * c_21 = x22_5 + x17_5 + c_20 := by + rw [e_x22_6, e_c_21]; exact Nat.mod_add_div _ _ + have b_x22_6 : x22_6 < 2^64 := by rw [e_x22_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_21 : c_21 ≤ 1 := by + rw [e_c_21]; exact addc_carry_le_one x22_5 x17_5 c_20 b_x22_5 b_x17_5 b_c_20 + clear e_x22_6 e_c_21 + -- x17_6: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_6 at hr + have e_x17_6 : x17_6 = x3_1 / 2^2 := rfl + clear_value x17_6 + have b_x17_6 : x17_6 < 2^62 := by + rw [e_x17_6]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_1 (by norm_num)) + have sh_x17_6 : x17_5 + 2^64 * x17_6 = x3_1 * 2^62 := by + rw [e_x17_5, e_x17_6]; exact lsl62_lsr2_split _ + clear e_x17_5 e_x17_6 + -- x23_5: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_5 at hr + have e_x23_5 : x23_5 = (x23_4 + 0 + c_21) % 2^64 := rfl + clear_value x23_5 + have b_x23_5 : x23_5 < 2^64 := by rw [e_x23_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_5, b_k_x23_5, l_x23_5⟩ : + ∃ k, k ≤ 1 ∧ x23_5 + 2^64 * k = x23_4 + 0 + c_21 := + ⟨(x23_4 + 0 + c_21) / 2^64, addc_carry_le_one x23_4 0 c_21 b_x23_4 (by decide) b_c_21, + by rw [e_x23_5]; exact Nat.mod_add_div _ _⟩ + clear e_x23_5 + -- x19_3: adds x19,x20,x14 + extract_lets +onlyGivenNames s_20 x19_3 c_22 at hr + have e_x19_3 : x19_3 = (x20_6 + x14_4 + 0) % 2^64 := rfl + have e_c_22 : c_22 = (x20_6 + x14_4 + 0) / 2^64 := rfl + clear_value s_20 x19_3 c_22 + have l_x19_3 : x19_3 + 2^64 * c_22 = x20_6 + x14_4 + 0 := by + rw [e_x19_3, e_c_22]; exact Nat.mod_add_div _ _ + have b_x19_3 : x19_3 < 2^64 := by rw [e_x19_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_22 : c_22 ≤ 1 := by + rw [e_c_22]; exact addc_carry_le_one x20_6 x14_4 0 b_x20_6 b_x14_4 (by decide) + clear e_x19_3 e_c_22 + -- x14_5: mul x14,x10,x9 + extract_lets +onlyGivenNames x14_5 at hr + have e_x14_5 : x14_5 = x10 * x9_2 % 2^64 := rfl + clear_value x14_5 + have b_x14_5 : x14_5 < 2^64 := by rw [e_x14_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x20_7: adcs x20,x21,x15 + extract_lets +onlyGivenNames s_21 x20_7 c_23 at hr + have e_x20_7 : x20_7 = (x21_6 + x15_6 + c_22) % 2^64 := rfl + have e_c_23 : c_23 = (x21_6 + x15_6 + c_22) / 2^64 := rfl + clear_value s_21 x20_7 c_23 + have l_x20_7 : x20_7 + 2^64 * c_23 = x21_6 + x15_6 + c_22 := by + rw [e_x20_7, e_c_23]; exact Nat.mod_add_div _ _ + have b_x20_7 : x20_7 < 2^64 := by rw [e_x20_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_23 : c_23 ≤ 1 := by + rw [e_c_23]; exact addc_carry_le_one x21_6 x15_6 c_22 b_x21_6 b_x15_6 b_c_22 + clear e_x20_7 e_c_23 + -- x15_7: mul x15,x11,x9 + extract_lets +onlyGivenNames x15_7 at hr + have e_x15_7 : x15_7 = x11 * x9_2 % 2^64 := rfl + clear_value x15_7 + have b_x15_7 : x15_7 < 2^64 := by rw [e_x15_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x21_7: adcs x21,x22,xzr + extract_lets +onlyGivenNames s_22 x21_7 c_24 at hr + have e_x21_7 : x21_7 = (x22_6 + 0 + c_23) % 2^64 := rfl + have e_c_24 : c_24 = (x22_6 + 0 + c_23) / 2^64 := rfl + clear_value s_22 x21_7 c_24 + have l_x21_7 : x21_7 + 2^64 * c_24 = x22_6 + 0 + c_23 := by + rw [e_x21_7, e_c_24]; exact Nat.mod_add_div _ _ + have b_x21_7 : x21_7 < 2^64 := by rw [e_x21_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_24 : c_24 ≤ 1 := by + rw [e_c_24]; exact addc_carry_le_one x22_6 0 c_23 b_x22_6 (by decide) b_c_23 + clear e_x21_7 e_c_24 + -- x16_3: mul x16,x12,x9 + extract_lets +onlyGivenNames x16_3 at hr + have e_x16_3 : x16_3 = x12 * x9_2 % 2^64 := rfl + clear_value x16_3 + have b_x16_3 : x16_3 < 2^64 := by rw [e_x16_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_7: adcs x22,x23,x17 + extract_lets +onlyGivenNames s_23 x22_7 c_25 at hr + have e_x22_7 : x22_7 = (x23_5 + x17_6 + c_24) % 2^64 := rfl + have e_c_25 : c_25 = (x23_5 + x17_6 + c_24) / 2^64 := rfl + clear_value s_23 x22_7 c_25 + have l_x22_7 : x22_7 + 2^64 * c_25 = x23_5 + x17_6 + c_24 := by + rw [e_x22_7, e_c_25]; exact Nat.mod_add_div _ _ + have b_x22_7 : x22_7 < 2^64 := by rw [e_x22_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_25 : c_25 ≤ 1 := by + rw [e_c_25]; exact addc_carry_le_one x23_5 x17_6 c_24 b_x23_5 (lt_of_lt_of_le b_x17_6 (by norm_num)) b_c_24 + clear e_x22_7 e_c_25 + -- x17_7: mul x17,x13,x9 + extract_lets +onlyGivenNames x17_7 at hr + have e_x17_7 : x17_7 = x13 * x9_2 % 2^64 := rfl + clear_value x17_7 + have b_x17_7 : x17_7 < 2^64 := by rw [e_x17_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x23_6: adc x23,xzr,xzr + extract_lets +onlyGivenNames x23_6 at hr + have e_x23_6 : x23_6 = (0 + 0 + c_25) % 2^64 := rfl + clear_value x23_6 + have b_x23_6 : x23_6 < 2^64 := by rw [e_x23_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_6, b_k_x23_6, l_x23_6⟩ : + ∃ k, k ≤ 1 ∧ x23_6 + 2^64 * k = 0 + 0 + c_25 := + ⟨(0 + 0 + c_25) / 2^64, addc_carry_le_one 0 0 c_25 (by decide) (by decide) b_c_25, + by rw [e_x23_6]; exact Nat.mod_add_div _ _⟩ + clear e_x23_6 + -- BEGIN round 1 reduction + -- Cancellation: the low limb of `x19_2 + p0 * x3_1` is zero, so `x19_2 + lo_x14_4` is + -- `0` or `2^64`, and `subs xzr, x19_2, #1` set the carry exactly when it is `2^64`. + have hc_1 : x19_2 + lo_x14_4 = 2^64 * c_18 := by + have h := cancel_low x19_2 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_1, ← d_x14_4, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_4] at h + clear * - h b_x19_2 b_lo_x14_4 l_c_18 + omega + have bc_1 : c_18 ≤ 1 := by clear * - l_c_18; omega + have hPq_1 : x3_1 * modulus.toNat = x5 * x3_1 + 2^64 * (x6 * x3_1) + 2^254 * x3_1 := by + rw [hP]; ring + -- `x17_5` is the low two bits of `x3_1` at the top of a limb. + have hsh_1 : x17_5 ≤ 3 * 2^62 := by + clear * - sh_x17_6 b_x17_5 b_x17_6; omega + -- The reduction's carry chain, summed with the limb weights. + have hsum'_1 : x19_2 + 2^64 * x20_6 + 2^128 * x21_6 + 2^192 * x22_6 + 2^256 * x23_5 + + 2^320 * k_x23_5 + = x19_2 + 2^64 * x20_5 + 2^128 * x21_5 + 2^192 * x22_5 + 2^256 * x23_4 + + 2^64 * x15_5 + 2^64 * c_18 + 2^192 * x17_5 := by + clear * - l_x20_6 l_x21_6 l_x22_6 l_x23_5 + omega + -- Neither `adc` of the reduction wraps: the five-limb accumulator is below + -- `2^320 - 3 * 2^254 - 2^128` by `hs_1`, and the reduction adds less than that before + -- the shift. + have hkr_1 : k_x23_5 = 0 := by + clear * - hsum'_1 F_1 B_0 hs_1 b_x15_5 bc_1 hsh_1 + omega + have hks_1 : k_x23_6 = 0 := by clear * - l_x23_6 b_c_25; omega + have I_1 : 2^64 * (x19_3 + 2^64 * x20_7 + 2^128 * x21_7 + 2^192 * x22_7 + 2^256 * x23_6) + = x19_2 + 2^64 * x20_5 + 2^128 * x21_5 + 2^192 * x22_5 + 2^256 * x23_4 + + x3_1 * modulus.toNat := by + clear * - hc_1 d_x14_4 d_x15_6 sh_x17_6 l_x20_6 l_x21_6 l_x22_6 l_x23_5 l_x19_3 l_x20_7 l_x21_7 + l_x22_7 l_x23_6 hkr_1 hks_1 hPq_1 + omega + -- The shifted accumulator stays below `lhs + p`. + have hLx_1 : lhs.toNat * x9_1 + lhs.toNat ≤ lhs.toNat * 2^64 := by + rw [← Nat.mul_succ]; exact Nat.mul_le_mul_left _ b_x9_1 + have hqP_1 : x3_1 * modulus.toNat + modulus.toNat ≤ 2^64 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ b_x3_1 + have B_1 : x19_3 + 2^64 * x20_7 + 2^128 * x21_7 + 2^192 * x22_7 + 2^256 * x23_6 + < lhs.toNat + modulus.toNat := by + clear * - I_1 F_1 hLx_1 hqP_1 B_0 + omega + have t_1 : x23_6 ≤ 1 := by clear * - l_x23_6 hks_1 b_c_25; omega + -- END round 1 reduction + -- x19_4: adds x19,x19,x14 + extract_lets +onlyGivenNames s_24 x19_4 c_26 at hr + have e_x19_4 : x19_4 = (x19_3 + x14_5 + 0) % 2^64 := rfl + have e_c_26 : c_26 = (x19_3 + x14_5 + 0) / 2^64 := rfl + clear_value s_24 x19_4 c_26 + have l_x19_4 : x19_4 + 2^64 * c_26 = x19_3 + x14_5 + 0 := by + rw [e_x19_4, e_c_26]; exact Nat.mod_add_div _ _ + have b_x19_4 : x19_4 < 2^64 := by rw [e_x19_4]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_26 : c_26 ≤ 1 := by + rw [e_c_26]; exact addc_carry_le_one x19_3 x14_5 0 b_x19_3 b_x14_5 (by decide) + clear e_x19_4 e_c_26 + -- x14_6: umulh x14,x10,x9 + extract_lets +onlyGivenNames x14_6 at hr + have e_x14_6 : x14_6 = x10 * x9_2 / 2^64 := rfl + clear_value x14_6 + have p_x14_6 : x10 * x9_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x10 b_x9_2 + have b_x14_6 : x14_6 < 2^64 := by rw [e_x14_6]; exact Nat.div_lt_of_lt_mul p_x14_6 + have d_x14_6 : x14_5 + 2^64 * x14_6 = x10 * x9_2 := by + rw [e_x14_5, e_x14_6]; exact Nat.mod_add_div _ _ + clear e_x14_5 e_x14_6 + -- x20_8: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_25 x20_8 c_27 at hr + have e_x20_8 : x20_8 = (x20_7 + x15_7 + c_26) % 2^64 := rfl + have e_c_27 : c_27 = (x20_7 + x15_7 + c_26) / 2^64 := rfl + clear_value s_25 x20_8 c_27 + have l_x20_8 : x20_8 + 2^64 * c_27 = x20_7 + x15_7 + c_26 := by + rw [e_x20_8, e_c_27]; exact Nat.mod_add_div _ _ + have b_x20_8 : x20_8 < 2^64 := by rw [e_x20_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_27 : c_27 ≤ 1 := by + rw [e_c_27]; exact addc_carry_le_one x20_7 x15_7 c_26 b_x20_7 b_x15_7 b_c_26 + clear e_x20_8 e_c_27 + -- x15_8: umulh x15,x11,x9 + extract_lets +onlyGivenNames x15_8 at hr + have e_x15_8 : x15_8 = x11 * x9_2 / 2^64 := rfl + clear_value x15_8 + have p_x15_8 : x11 * x9_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x11 b_x9_2 + have b_x15_8 : x15_8 < 2^64 := by rw [e_x15_8]; exact Nat.div_lt_of_lt_mul p_x15_8 + have d_x15_8 : x15_7 + 2^64 * x15_8 = x11 * x9_2 := by + rw [e_x15_7, e_x15_8]; exact Nat.mod_add_div _ _ + clear e_x15_7 e_x15_8 + -- x21_8: adcs x21,x21,x16 + extract_lets +onlyGivenNames s_26 x21_8 c_28 at hr + have e_x21_8 : x21_8 = (x21_7 + x16_3 + c_27) % 2^64 := rfl + have e_c_28 : c_28 = (x21_7 + x16_3 + c_27) / 2^64 := rfl + clear_value s_26 x21_8 c_28 + have l_x21_8 : x21_8 + 2^64 * c_28 = x21_7 + x16_3 + c_27 := by + rw [e_x21_8, e_c_28]; exact Nat.mod_add_div _ _ + have b_x21_8 : x21_8 < 2^64 := by rw [e_x21_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_28 : c_28 ≤ 1 := by + rw [e_c_28]; exact addc_carry_le_one x21_7 x16_3 c_27 b_x21_7 b_x16_3 b_c_27 + clear e_x21_8 e_c_28 + -- x3_2: mul x3,x4,x19 + extract_lets +onlyGivenNames x3_2 at hr + have e_x3_2 : x3_2 = x4 * x19_4 % 2^64 := rfl + clear_value x3_2 + have b_x3_2 : x3_2 < 2^64 := by rw [e_x3_2]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x16_4: umulh x16,x12,x9 + extract_lets +onlyGivenNames x16_4 at hr + have e_x16_4 : x16_4 = x12 * x9_2 / 2^64 := rfl + clear_value x16_4 + have p_x16_4 : x12 * x9_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x12 b_x9_2 + have b_x16_4 : x16_4 < 2^64 := by rw [e_x16_4]; exact Nat.div_lt_of_lt_mul p_x16_4 + have d_x16_4 : x16_3 + 2^64 * x16_4 = x12 * x9_2 := by + rw [e_x16_3, e_x16_4]; exact Nat.mod_add_div _ _ + clear e_x16_3 e_x16_4 + -- x22_8: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_27 x22_8 c_29 at hr + have e_x22_8 : x22_8 = (x22_7 + x17_7 + c_28) % 2^64 := rfl + have e_c_29 : c_29 = (x22_7 + x17_7 + c_28) / 2^64 := rfl + clear_value s_27 x22_8 c_29 + have l_x22_8 : x22_8 + 2^64 * c_29 = x22_7 + x17_7 + c_28 := by + rw [e_x22_8, e_c_29]; exact Nat.mod_add_div _ _ + have b_x22_8 : x22_8 < 2^64 := by rw [e_x22_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_29 : c_29 ≤ 1 := by + rw [e_c_29]; exact addc_carry_le_one x22_7 x17_7 c_28 b_x22_7 b_x17_7 b_c_28 + clear e_x22_8 e_c_29 + -- x17_8: umulh x17,x13,x9 + extract_lets +onlyGivenNames x17_8 at hr + have e_x17_8 : x17_8 = x13 * x9_2 / 2^64 := rfl + clear_value x17_8 + have p_x17_8 : x13 * x9_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x13 b_x9_2 + have b_x17_8 : x17_8 < 2^64 := by rw [e_x17_8]; exact Nat.div_lt_of_lt_mul p_x17_8 + have d_x17_8 : x17_7 + 2^64 * x17_8 = x13 * x9_2 := by + rw [e_x17_7, e_x17_8]; exact Nat.mod_add_div _ _ + clear e_x17_7 e_x17_8 + -- x23_7: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_7 at hr + have e_x23_7 : x23_7 = (x23_6 + 0 + c_29) % 2^64 := rfl + clear_value x23_7 + have b_x23_7 : x23_7 < 2^64 := by rw [e_x23_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_7, b_k_x23_7, l_x23_7⟩ : + ∃ k, k ≤ 1 ∧ x23_7 + 2^64 * k = x23_6 + 0 + c_29 := + ⟨(x23_6 + 0 + c_29) / 2^64, addc_carry_le_one x23_6 0 c_29 b_x23_6 (by decide) b_c_29, + by rw [e_x23_7]; exact Nat.mod_add_div _ _⟩ + clear e_x23_7 + -- x20_9: adds x20,x20,x14 + extract_lets +onlyGivenNames s_28 x20_9 c_30 at hr + have e_x20_9 : x20_9 = (x20_8 + x14_6 + 0) % 2^64 := rfl + have e_c_30 : c_30 = (x20_8 + x14_6 + 0) / 2^64 := rfl + clear_value s_28 x20_9 c_30 + have l_x20_9 : x20_9 + 2^64 * c_30 = x20_8 + x14_6 + 0 := by + rw [e_x20_9, e_c_30]; exact Nat.mod_add_div _ _ + have b_x20_9 : x20_9 < 2^64 := by rw [e_x20_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_30 : c_30 ≤ 1 := by + rw [e_c_30]; exact addc_carry_le_one x20_8 x14_6 0 b_x20_8 b_x14_6 (by decide) + clear e_x20_9 e_c_30 + -- x21_9: adcs x21,x21,x15 + extract_lets +onlyGivenNames s_29 x21_9 c_31 at hr + have e_x21_9 : x21_9 = (x21_8 + x15_8 + c_30) % 2^64 := rfl + have e_c_31 : c_31 = (x21_8 + x15_8 + c_30) / 2^64 := rfl + clear_value s_29 x21_9 c_31 + have l_x21_9 : x21_9 + 2^64 * c_31 = x21_8 + x15_8 + c_30 := by + rw [e_x21_9, e_c_31]; exact Nat.mod_add_div _ _ + have b_x21_9 : x21_9 < 2^64 := by rw [e_x21_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_31 : c_31 ≤ 1 := by + rw [e_c_31]; exact addc_carry_le_one x21_8 x15_8 c_30 b_x21_8 b_x15_8 b_c_30 + clear e_x21_9 e_c_31 + -- x15_9: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_9 at hr + have e_x15_9 : x15_9 = x6 * x3_2 % 2^64 := rfl + clear_value x15_9 + have b_x15_9 : x15_9 < 2^64 := by rw [e_x15_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_9: adcs x22,x22,x16 + extract_lets +onlyGivenNames s_30 x22_9 c_32 at hr + have e_x22_9 : x22_9 = (x22_8 + x16_4 + c_31) % 2^64 := rfl + have e_c_32 : c_32 = (x22_8 + x16_4 + c_31) / 2^64 := rfl + clear_value s_30 x22_9 c_32 + have l_x22_9 : x22_9 + 2^64 * c_32 = x22_8 + x16_4 + c_31 := by + rw [e_x22_9, e_c_32]; exact Nat.mod_add_div _ _ + have b_x22_9 : x22_9 < 2^64 := by rw [e_x22_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_32 : c_32 ≤ 1 := by + rw [e_c_32]; exact addc_carry_le_one x22_8 x16_4 c_31 b_x22_8 b_x16_4 b_c_31 + clear e_x22_9 e_c_32 + -- x23_8: adc x23,x23,x17 + extract_lets +onlyGivenNames x23_8 at hr + have e_x23_8 : x23_8 = (x23_7 + x17_8 + c_32) % 2^64 := rfl + clear_value x23_8 + have b_x23_8 : x23_8 < 2^64 := by rw [e_x23_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_8, b_k_x23_8, l_x23_8⟩ : + ∃ k, k ≤ 1 ∧ x23_8 + 2^64 * k = x23_7 + x17_8 + c_32 := + ⟨(x23_7 + x17_8 + c_32) / 2^64, addc_carry_le_one x23_7 x17_8 c_32 b_x23_7 b_x17_8 b_c_32, + by rw [e_x23_8]; exact Nat.mod_add_div _ _⟩ + clear e_x23_8 + -- BEGIN round 2 fold + -- `lhs * rhs_2` as the sum of the limb products. + have hL_2 : lhs.toNat * x9_2 + = x10 * x9_2 + 2^64 * (x11 * x9_2) + 2^128 * (x12 * x9_2) + 2^192 * (x13 * x9_2) := by + rw [e_x10, e_x11, e_x12, e_x13]; simp only [Limbs.toNat]; ring + have hs_2 : lhs.toNat * x9_2 + lhs.toNat + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320 := by + rw [e_x9_2, ← Nat.mul_add_one]; exact hsafe.2.1 + -- The fold's two carry chains, summed with the limb weights. + have hsum_2 : x19_4 + 2^64 * x20_9 + 2^128 * x21_9 + 2^192 * x22_9 + 2^256 * x23_8 + + 2^320 * (k_x23_7 + k_x23_8) + = x19_3 + 2^64 * x20_7 + 2^128 * x21_7 + 2^192 * x22_7 + 2^256 * x23_6 + + lhs.toNat * x9_2 := by + clear * - l_x19_4 l_x20_8 l_x21_8 l_x22_8 l_x23_7 l_x20_9 l_x21_9 l_x22_9 l_x23_8 d_x14_6 + d_x15_8 d_x16_4 d_x17_8 hL_2 + omega + -- Neither `adc` of the fold wraps: the accumulator entering the round is below + -- `lhs + p`, and `hs_2` bounds it plus `lhs * rhs_2` below `2^320`. + have hk_2 : k_x23_7 = 0 ∧ k_x23_8 = 0 := by + clear * - hsum_2 B_1 hs_2 + omega + have F_2 : x19_4 + 2^64 * x20_9 + 2^128 * x21_9 + 2^192 * x22_9 + 2^256 * x23_8 + = x19_3 + 2^64 * x20_7 + 2^128 * x21_7 + 2^192 * x22_7 + 2^256 * x23_6 + + lhs.toNat * x9_2 := by + clear * - hsum_2 hk_2 + omega + -- END round 2 fold + -- x17_9: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_9 at hr + have e_x17_9 : x17_9 = x3_2 * 2^62 % 2^64 := rfl + clear_value x17_9 + have b_x17_9 : x17_9 < 2^64 := by rw [e_x17_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x9_3: ldr x9,[x2,8*3] + extract_lets +onlyGivenNames x9_3 at hr + have e_x9_3 : x9_3 = rhs.l3 := rfl + clear_value x9_3 + have b_x9_3 : x9_3 < 2^64 := by rw [e_x9_3]; exact hrhs.2.2.2 + -- c_33: subs xzr,x19,#1 + extract_lets +onlyGivenNames c_33 at hr + have e_c_33 : c_33 = (x19_4 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_33 + have b_c_33 : c_33 ≤ 1 := by rw [e_c_33]; exact subc_carry_le_one x19_4 1 1 b_x19_4 + have l_c_33 : (c_33 = 1 ∧ 1 + 1 ≤ x19_4 + 1) ∨ (c_33 = 0 ∧ x19_4 + 1 < 1 + 1) := + subc_carry_cases x19_4 1 1 _ e_c_33 b_x19_4 (by decide) (by decide) + clear e_c_33 + -- x14_7: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_7 at hr + have e_x14_7 : x14_7 = x5 * x3_2 / 2^64 := rfl + clear_value x14_7 + have p_x14_7 : x5 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_2 + have b_x14_7 : x14_7 < 2^64 := by rw [e_x14_7]; exact Nat.div_lt_of_lt_mul p_x14_7 + obtain ⟨lo_x14_7, b_lo_x14_7, d_x14_7⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_7 = x5 * x3_2 := + ⟨x5 * x3_2 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_7]; exact Nat.mod_add_div _ _⟩ + clear e_x14_7 + -- x20_10: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_31 x20_10 c_34 at hr + have e_x20_10 : x20_10 = (x20_9 + x15_9 + c_33) % 2^64 := rfl + have e_c_34 : c_34 = (x20_9 + x15_9 + c_33) / 2^64 := rfl + clear_value s_31 x20_10 c_34 + have l_x20_10 : x20_10 + 2^64 * c_34 = x20_9 + x15_9 + c_33 := by + rw [e_x20_10, e_c_34]; exact Nat.mod_add_div _ _ + have b_x20_10 : x20_10 < 2^64 := by rw [e_x20_10]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_34 : c_34 ≤ 1 := by + rw [e_c_34]; exact addc_carry_le_one x20_9 x15_9 c_33 b_x20_9 b_x15_9 b_c_33 + clear e_x20_10 e_c_34 + -- x15_10: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_10 at hr + have e_x15_10 : x15_10 = x6 * x3_2 / 2^64 := rfl + clear_value x15_10 + have p_x15_10 : x6 * x3_2 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_2 + have b_x15_10 : x15_10 < 2^64 := by rw [e_x15_10]; exact Nat.div_lt_of_lt_mul p_x15_10 + have d_x15_10 : x15_9 + 2^64 * x15_10 = x6 * x3_2 := by + rw [e_x15_9, e_x15_10]; exact Nat.mod_add_div _ _ + clear e_x15_9 e_x15_10 + -- x21_10: adcs x21,x21,xzr + extract_lets +onlyGivenNames s_32 x21_10 c_35 at hr + have e_x21_10 : x21_10 = (x21_9 + 0 + c_34) % 2^64 := rfl + have e_c_35 : c_35 = (x21_9 + 0 + c_34) / 2^64 := rfl + clear_value s_32 x21_10 c_35 + have l_x21_10 : x21_10 + 2^64 * c_35 = x21_9 + 0 + c_34 := by + rw [e_x21_10, e_c_35]; exact Nat.mod_add_div _ _ + have b_x21_10 : x21_10 < 2^64 := by rw [e_x21_10]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_35 : c_35 ≤ 1 := by + rw [e_c_35]; exact addc_carry_le_one x21_9 0 c_34 b_x21_9 (by decide) b_c_34 + clear e_x21_10 e_c_35 + -- x22_10: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_33 x22_10 c_36 at hr + have e_x22_10 : x22_10 = (x22_9 + x17_9 + c_35) % 2^64 := rfl + have e_c_36 : c_36 = (x22_9 + x17_9 + c_35) / 2^64 := rfl + clear_value s_33 x22_10 c_36 + have l_x22_10 : x22_10 + 2^64 * c_36 = x22_9 + x17_9 + c_35 := by + rw [e_x22_10, e_c_36]; exact Nat.mod_add_div _ _ + have b_x22_10 : x22_10 < 2^64 := by rw [e_x22_10]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_36 : c_36 ≤ 1 := by + rw [e_c_36]; exact addc_carry_le_one x22_9 x17_9 c_35 b_x22_9 b_x17_9 b_c_35 + clear e_x22_10 e_c_36 + -- x17_10: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_10 at hr + have e_x17_10 : x17_10 = x3_2 / 2^2 := rfl + clear_value x17_10 + have b_x17_10 : x17_10 < 2^62 := by + rw [e_x17_10]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_2 (by norm_num)) + have sh_x17_10 : x17_9 + 2^64 * x17_10 = x3_2 * 2^62 := by + rw [e_x17_9, e_x17_10]; exact lsl62_lsr2_split _ + clear e_x17_9 e_x17_10 + -- x23_9: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_9 at hr + have e_x23_9 : x23_9 = (x23_8 + 0 + c_36) % 2^64 := rfl + clear_value x23_9 + have b_x23_9 : x23_9 < 2^64 := by rw [e_x23_9]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_9, b_k_x23_9, l_x23_9⟩ : + ∃ k, k ≤ 1 ∧ x23_9 + 2^64 * k = x23_8 + 0 + c_36 := + ⟨(x23_8 + 0 + c_36) / 2^64, addc_carry_le_one x23_8 0 c_36 b_x23_8 (by decide) b_c_36, + by rw [e_x23_9]; exact Nat.mod_add_div _ _⟩ + clear e_x23_9 + -- x19_5: adds x19,x20,x14 + extract_lets +onlyGivenNames s_34 x19_5 c_37 at hr + have e_x19_5 : x19_5 = (x20_10 + x14_7 + 0) % 2^64 := rfl + have e_c_37 : c_37 = (x20_10 + x14_7 + 0) / 2^64 := rfl + clear_value s_34 x19_5 c_37 + have l_x19_5 : x19_5 + 2^64 * c_37 = x20_10 + x14_7 + 0 := by + rw [e_x19_5, e_c_37]; exact Nat.mod_add_div _ _ + have b_x19_5 : x19_5 < 2^64 := by rw [e_x19_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_37 : c_37 ≤ 1 := by + rw [e_c_37]; exact addc_carry_le_one x20_10 x14_7 0 b_x20_10 b_x14_7 (by decide) + clear e_x19_5 e_c_37 + -- x14_8: mul x14,x10,x9 + extract_lets +onlyGivenNames x14_8 at hr + have e_x14_8 : x14_8 = x10 * x9_3 % 2^64 := rfl + clear_value x14_8 + have b_x14_8 : x14_8 < 2^64 := by rw [e_x14_8]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x20_11: adcs x20,x21,x15 + extract_lets +onlyGivenNames s_35 x20_11 c_38 at hr + have e_x20_11 : x20_11 = (x21_10 + x15_10 + c_37) % 2^64 := rfl + have e_c_38 : c_38 = (x21_10 + x15_10 + c_37) / 2^64 := rfl + clear_value s_35 x20_11 c_38 + have l_x20_11 : x20_11 + 2^64 * c_38 = x21_10 + x15_10 + c_37 := by + rw [e_x20_11, e_c_38]; exact Nat.mod_add_div _ _ + have b_x20_11 : x20_11 < 2^64 := by rw [e_x20_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_38 : c_38 ≤ 1 := by + rw [e_c_38]; exact addc_carry_le_one x21_10 x15_10 c_37 b_x21_10 b_x15_10 b_c_37 + clear e_x20_11 e_c_38 + -- x15_11: mul x15,x11,x9 + extract_lets +onlyGivenNames x15_11 at hr + have e_x15_11 : x15_11 = x11 * x9_3 % 2^64 := rfl + clear_value x15_11 + have b_x15_11 : x15_11 < 2^64 := by rw [e_x15_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x21_11: adcs x21,x22,xzr + extract_lets +onlyGivenNames s_36 x21_11 c_39 at hr + have e_x21_11 : x21_11 = (x22_10 + 0 + c_38) % 2^64 := rfl + have e_c_39 : c_39 = (x22_10 + 0 + c_38) / 2^64 := rfl + clear_value s_36 x21_11 c_39 + have l_x21_11 : x21_11 + 2^64 * c_39 = x22_10 + 0 + c_38 := by + rw [e_x21_11, e_c_39]; exact Nat.mod_add_div _ _ + have b_x21_11 : x21_11 < 2^64 := by rw [e_x21_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_39 : c_39 ≤ 1 := by + rw [e_c_39]; exact addc_carry_le_one x22_10 0 c_38 b_x22_10 (by decide) b_c_38 + clear e_x21_11 e_c_39 + -- x16_5: mul x16,x12,x9 + extract_lets +onlyGivenNames x16_5 at hr + have e_x16_5 : x16_5 = x12 * x9_3 % 2^64 := rfl + clear_value x16_5 + have b_x16_5 : x16_5 < 2^64 := by rw [e_x16_5]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_11: adcs x22,x23,x17 + extract_lets +onlyGivenNames s_37 x22_11 c_40 at hr + have e_x22_11 : x22_11 = (x23_9 + x17_10 + c_39) % 2^64 := rfl + have e_c_40 : c_40 = (x23_9 + x17_10 + c_39) / 2^64 := rfl + clear_value s_37 x22_11 c_40 + have l_x22_11 : x22_11 + 2^64 * c_40 = x23_9 + x17_10 + c_39 := by + rw [e_x22_11, e_c_40]; exact Nat.mod_add_div _ _ + have b_x22_11 : x22_11 < 2^64 := by rw [e_x22_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_40 : c_40 ≤ 1 := by + rw [e_c_40]; exact addc_carry_le_one x23_9 x17_10 c_39 b_x23_9 (lt_of_lt_of_le b_x17_10 (by norm_num)) b_c_39 + clear e_x22_11 e_c_40 + -- x17_11: mul x17,x13,x9 + extract_lets +onlyGivenNames x17_11 at hr + have e_x17_11 : x17_11 = x13 * x9_3 % 2^64 := rfl + clear_value x17_11 + have b_x17_11 : x17_11 < 2^64 := by rw [e_x17_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x23_10: adc x23,xzr,xzr + extract_lets +onlyGivenNames x23_10 at hr + have e_x23_10 : x23_10 = (0 + 0 + c_40) % 2^64 := rfl + clear_value x23_10 + have b_x23_10 : x23_10 < 2^64 := by rw [e_x23_10]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_10, b_k_x23_10, l_x23_10⟩ : + ∃ k, k ≤ 1 ∧ x23_10 + 2^64 * k = 0 + 0 + c_40 := + ⟨(0 + 0 + c_40) / 2^64, addc_carry_le_one 0 0 c_40 (by decide) (by decide) b_c_40, + by rw [e_x23_10]; exact Nat.mod_add_div _ _⟩ + clear e_x23_10 + -- BEGIN round 2 reduction + -- Cancellation: the low limb of `x19_4 + p0 * x3_2` is zero, so `x19_4 + lo_x14_7` is + -- `0` or `2^64`, and `subs xzr, x19_4, #1` set the carry exactly when it is `2^64`. + have hc_2 : x19_4 + lo_x14_7 = 2^64 * c_33 := by + have h := cancel_low x19_4 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_2, ← d_x14_7, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_7] at h + clear * - h b_x19_4 b_lo_x14_7 l_c_33 + omega + have bc_2 : c_33 ≤ 1 := by clear * - l_c_33; omega + have hPq_2 : x3_2 * modulus.toNat = x5 * x3_2 + 2^64 * (x6 * x3_2) + 2^254 * x3_2 := by + rw [hP]; ring + -- `x17_9` is the low two bits of `x3_2` at the top of a limb. + have hsh_2 : x17_9 ≤ 3 * 2^62 := by + clear * - sh_x17_10 b_x17_9 b_x17_10; omega + -- The reduction's carry chain, summed with the limb weights. + have hsum'_2 : x19_4 + 2^64 * x20_10 + 2^128 * x21_10 + 2^192 * x22_10 + 2^256 * x23_9 + + 2^320 * k_x23_9 + = x19_4 + 2^64 * x20_9 + 2^128 * x21_9 + 2^192 * x22_9 + 2^256 * x23_8 + + 2^64 * x15_9 + 2^64 * c_33 + 2^192 * x17_9 := by + clear * - l_x20_10 l_x21_10 l_x22_10 l_x23_9 + omega + -- Neither `adc` of the reduction wraps: the five-limb accumulator is below + -- `2^320 - 3 * 2^254 - 2^128` by `hs_2`, and the reduction adds less than that before + -- the shift. + have hkr_2 : k_x23_9 = 0 := by + clear * - hsum'_2 F_2 B_1 hs_2 b_x15_9 bc_2 hsh_2 + omega + have hks_2 : k_x23_10 = 0 := by clear * - l_x23_10 b_c_40; omega + have I_2 : 2^64 * (x19_5 + 2^64 * x20_11 + 2^128 * x21_11 + 2^192 * x22_11 + 2^256 * x23_10) + = x19_4 + 2^64 * x20_9 + 2^128 * x21_9 + 2^192 * x22_9 + 2^256 * x23_8 + + x3_2 * modulus.toNat := by + clear * - hc_2 d_x14_7 d_x15_10 sh_x17_10 l_x20_10 l_x21_10 l_x22_10 l_x23_9 l_x19_5 l_x20_11 + l_x21_11 l_x22_11 l_x23_10 hkr_2 hks_2 hPq_2 + omega + -- The shifted accumulator stays below `lhs + p`. + have hLx_2 : lhs.toNat * x9_2 + lhs.toNat ≤ lhs.toNat * 2^64 := by + rw [← Nat.mul_succ]; exact Nat.mul_le_mul_left _ b_x9_2 + have hqP_2 : x3_2 * modulus.toNat + modulus.toNat ≤ 2^64 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ b_x3_2 + have B_2 : x19_5 + 2^64 * x20_11 + 2^128 * x21_11 + 2^192 * x22_11 + 2^256 * x23_10 + < lhs.toNat + modulus.toNat := by + clear * - I_2 F_2 hLx_2 hqP_2 B_1 + omega + have t_2 : x23_10 ≤ 1 := by clear * - l_x23_10 hks_2 b_c_40; omega + -- END round 2 reduction + -- x19_6: adds x19,x19,x14 + extract_lets +onlyGivenNames s_38 x19_6 c_41 at hr + have e_x19_6 : x19_6 = (x19_5 + x14_8 + 0) % 2^64 := rfl + have e_c_41 : c_41 = (x19_5 + x14_8 + 0) / 2^64 := rfl + clear_value s_38 x19_6 c_41 + have l_x19_6 : x19_6 + 2^64 * c_41 = x19_5 + x14_8 + 0 := by + rw [e_x19_6, e_c_41]; exact Nat.mod_add_div _ _ + have b_x19_6 : x19_6 < 2^64 := by rw [e_x19_6]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_41 : c_41 ≤ 1 := by + rw [e_c_41]; exact addc_carry_le_one x19_5 x14_8 0 b_x19_5 b_x14_8 (by decide) + clear e_x19_6 e_c_41 + -- x14_9: umulh x14,x10,x9 + extract_lets +onlyGivenNames x14_9 at hr + have e_x14_9 : x14_9 = x10 * x9_3 / 2^64 := rfl + clear_value x14_9 + have p_x14_9 : x10 * x9_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x10 b_x9_3 + have b_x14_9 : x14_9 < 2^64 := by rw [e_x14_9]; exact Nat.div_lt_of_lt_mul p_x14_9 + have d_x14_9 : x14_8 + 2^64 * x14_9 = x10 * x9_3 := by + rw [e_x14_8, e_x14_9]; exact Nat.mod_add_div _ _ + clear e_x14_8 e_x14_9 + -- x20_12: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_39 x20_12 c_42 at hr + have e_x20_12 : x20_12 = (x20_11 + x15_11 + c_41) % 2^64 := rfl + have e_c_42 : c_42 = (x20_11 + x15_11 + c_41) / 2^64 := rfl + clear_value s_39 x20_12 c_42 + have l_x20_12 : x20_12 + 2^64 * c_42 = x20_11 + x15_11 + c_41 := by + rw [e_x20_12, e_c_42]; exact Nat.mod_add_div _ _ + have b_x20_12 : x20_12 < 2^64 := by rw [e_x20_12]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_42 : c_42 ≤ 1 := by + rw [e_c_42]; exact addc_carry_le_one x20_11 x15_11 c_41 b_x20_11 b_x15_11 b_c_41 + clear e_x20_12 e_c_42 + -- x15_12: umulh x15,x11,x9 + extract_lets +onlyGivenNames x15_12 at hr + have e_x15_12 : x15_12 = x11 * x9_3 / 2^64 := rfl + clear_value x15_12 + have p_x15_12 : x11 * x9_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x11 b_x9_3 + have b_x15_12 : x15_12 < 2^64 := by rw [e_x15_12]; exact Nat.div_lt_of_lt_mul p_x15_12 + have d_x15_12 : x15_11 + 2^64 * x15_12 = x11 * x9_3 := by + rw [e_x15_11, e_x15_12]; exact Nat.mod_add_div _ _ + clear e_x15_11 e_x15_12 + -- x21_12: adcs x21,x21,x16 + extract_lets +onlyGivenNames s_40 x21_12 c_43 at hr + have e_x21_12 : x21_12 = (x21_11 + x16_5 + c_42) % 2^64 := rfl + have e_c_43 : c_43 = (x21_11 + x16_5 + c_42) / 2^64 := rfl + clear_value s_40 x21_12 c_43 + have l_x21_12 : x21_12 + 2^64 * c_43 = x21_11 + x16_5 + c_42 := by + rw [e_x21_12, e_c_43]; exact Nat.mod_add_div _ _ + have b_x21_12 : x21_12 < 2^64 := by rw [e_x21_12]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_43 : c_43 ≤ 1 := by + rw [e_c_43]; exact addc_carry_le_one x21_11 x16_5 c_42 b_x21_11 b_x16_5 b_c_42 + clear e_x21_12 e_c_43 + -- x3_3: mul x3,x4,x19 + extract_lets +onlyGivenNames x3_3 at hr + have e_x3_3 : x3_3 = x4 * x19_6 % 2^64 := rfl + clear_value x3_3 + have b_x3_3 : x3_3 < 2^64 := by rw [e_x3_3]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x16_6: umulh x16,x12,x9 + extract_lets +onlyGivenNames x16_6 at hr + have e_x16_6 : x16_6 = x12 * x9_3 / 2^64 := rfl + clear_value x16_6 + have p_x16_6 : x12 * x9_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x12 b_x9_3 + have b_x16_6 : x16_6 < 2^64 := by rw [e_x16_6]; exact Nat.div_lt_of_lt_mul p_x16_6 + have d_x16_6 : x16_5 + 2^64 * x16_6 = x12 * x9_3 := by + rw [e_x16_5, e_x16_6]; exact Nat.mod_add_div _ _ + clear e_x16_5 e_x16_6 + -- x22_12: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_41 x22_12 c_44 at hr + have e_x22_12 : x22_12 = (x22_11 + x17_11 + c_43) % 2^64 := rfl + have e_c_44 : c_44 = (x22_11 + x17_11 + c_43) / 2^64 := rfl + clear_value s_41 x22_12 c_44 + have l_x22_12 : x22_12 + 2^64 * c_44 = x22_11 + x17_11 + c_43 := by + rw [e_x22_12, e_c_44]; exact Nat.mod_add_div _ _ + have b_x22_12 : x22_12 < 2^64 := by rw [e_x22_12]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_44 : c_44 ≤ 1 := by + rw [e_c_44]; exact addc_carry_le_one x22_11 x17_11 c_43 b_x22_11 b_x17_11 b_c_43 + clear e_x22_12 e_c_44 + -- x17_12: umulh x17,x13,x9 + extract_lets +onlyGivenNames x17_12 at hr + have e_x17_12 : x17_12 = x13 * x9_3 / 2^64 := rfl + clear_value x17_12 + have p_x17_12 : x13 * x9_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x13 b_x9_3 + have b_x17_12 : x17_12 < 2^64 := by rw [e_x17_12]; exact Nat.div_lt_of_lt_mul p_x17_12 + have d_x17_12 : x17_11 + 2^64 * x17_12 = x13 * x9_3 := by + rw [e_x17_11, e_x17_12]; exact Nat.mod_add_div _ _ + clear e_x17_11 e_x17_12 + -- x23_11: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_11 at hr + have e_x23_11 : x23_11 = (x23_10 + 0 + c_44) % 2^64 := rfl + clear_value x23_11 + have b_x23_11 : x23_11 < 2^64 := by rw [e_x23_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_11, b_k_x23_11, l_x23_11⟩ : + ∃ k, k ≤ 1 ∧ x23_11 + 2^64 * k = x23_10 + 0 + c_44 := + ⟨(x23_10 + 0 + c_44) / 2^64, addc_carry_le_one x23_10 0 c_44 b_x23_10 (by decide) b_c_44, + by rw [e_x23_11]; exact Nat.mod_add_div _ _⟩ + clear e_x23_11 + -- x20_13: adds x20,x20,x14 + extract_lets +onlyGivenNames s_42 x20_13 c_45 at hr + have e_x20_13 : x20_13 = (x20_12 + x14_9 + 0) % 2^64 := rfl + have e_c_45 : c_45 = (x20_12 + x14_9 + 0) / 2^64 := rfl + clear_value s_42 x20_13 c_45 + have l_x20_13 : x20_13 + 2^64 * c_45 = x20_12 + x14_9 + 0 := by + rw [e_x20_13, e_c_45]; exact Nat.mod_add_div _ _ + have b_x20_13 : x20_13 < 2^64 := by rw [e_x20_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_45 : c_45 ≤ 1 := by + rw [e_c_45]; exact addc_carry_le_one x20_12 x14_9 0 b_x20_12 b_x14_9 (by decide) + clear e_x20_13 e_c_45 + -- x21_13: adcs x21,x21,x15 + extract_lets +onlyGivenNames s_43 x21_13 c_46 at hr + have e_x21_13 : x21_13 = (x21_12 + x15_12 + c_45) % 2^64 := rfl + have e_c_46 : c_46 = (x21_12 + x15_12 + c_45) / 2^64 := rfl + clear_value s_43 x21_13 c_46 + have l_x21_13 : x21_13 + 2^64 * c_46 = x21_12 + x15_12 + c_45 := by + rw [e_x21_13, e_c_46]; exact Nat.mod_add_div _ _ + have b_x21_13 : x21_13 < 2^64 := by rw [e_x21_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_46 : c_46 ≤ 1 := by + rw [e_c_46]; exact addc_carry_le_one x21_12 x15_12 c_45 b_x21_12 b_x15_12 b_c_45 + clear e_x21_13 e_c_46 + -- x15_13: mul x15,x6,x3 + extract_lets +onlyGivenNames x15_13 at hr + have e_x15_13 : x15_13 = x6 * x3_3 % 2^64 := rfl + clear_value x15_13 + have b_x15_13 : x15_13 < 2^64 := by rw [e_x15_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- x22_13: adcs x22,x22,x16 + extract_lets +onlyGivenNames s_44 x22_13 c_47 at hr + have e_x22_13 : x22_13 = (x22_12 + x16_6 + c_46) % 2^64 := rfl + have e_c_47 : c_47 = (x22_12 + x16_6 + c_46) / 2^64 := rfl + clear_value s_44 x22_13 c_47 + have l_x22_13 : x22_13 + 2^64 * c_47 = x22_12 + x16_6 + c_46 := by + rw [e_x22_13, e_c_47]; exact Nat.mod_add_div _ _ + have b_x22_13 : x22_13 < 2^64 := by rw [e_x22_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_47 : c_47 ≤ 1 := by + rw [e_c_47]; exact addc_carry_le_one x22_12 x16_6 c_46 b_x22_12 b_x16_6 b_c_46 + clear e_x22_13 e_c_47 + -- x23_12: adc x23,x23,x17 + extract_lets +onlyGivenNames x23_12 at hr + have e_x23_12 : x23_12 = (x23_11 + x17_12 + c_47) % 2^64 := rfl + clear_value x23_12 + have b_x23_12 : x23_12 < 2^64 := by rw [e_x23_12]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_12, b_k_x23_12, l_x23_12⟩ : + ∃ k, k ≤ 1 ∧ x23_12 + 2^64 * k = x23_11 + x17_12 + c_47 := + ⟨(x23_11 + x17_12 + c_47) / 2^64, addc_carry_le_one x23_11 x17_12 c_47 b_x23_11 b_x17_12 b_c_47, + by rw [e_x23_12]; exact Nat.mod_add_div _ _⟩ + clear e_x23_12 + -- BEGIN round 3 fold + -- `lhs * rhs_3` as the sum of the limb products. + have hL_3 : lhs.toNat * x9_3 + = x10 * x9_3 + 2^64 * (x11 * x9_3) + 2^128 * (x12 * x9_3) + 2^192 * (x13 * x9_3) := by + rw [e_x10, e_x11, e_x12, e_x13]; simp only [Limbs.toNat]; ring + have hs_3 : lhs.toNat * x9_3 + lhs.toNat + modulus.toNat + 3 * 2^254 + 2^128 ≤ 2^320 := by + rw [e_x9_3, ← Nat.mul_add_one]; exact hsafe.2.2 + -- The fold's two carry chains, summed with the limb weights. + have hsum_3 : x19_6 + 2^64 * x20_13 + 2^128 * x21_13 + 2^192 * x22_13 + 2^256 * x23_12 + + 2^320 * (k_x23_11 + k_x23_12) + = x19_5 + 2^64 * x20_11 + 2^128 * x21_11 + 2^192 * x22_11 + 2^256 * x23_10 + + lhs.toNat * x9_3 := by + clear * - l_x19_6 l_x20_12 l_x21_12 l_x22_12 l_x23_11 l_x20_13 l_x21_13 l_x22_13 l_x23_12 + d_x14_9 d_x15_12 d_x16_6 d_x17_12 hL_3 + omega + -- Neither `adc` of the fold wraps: the accumulator entering the round is below + -- `lhs + p`, and `hs_3` bounds it plus `lhs * rhs_3` below `2^320`. + have hk_3 : k_x23_11 = 0 ∧ k_x23_12 = 0 := by + clear * - hsum_3 B_2 hs_3 + omega + have F_3 : x19_6 + 2^64 * x20_13 + 2^128 * x21_13 + 2^192 * x22_13 + 2^256 * x23_12 + = x19_5 + 2^64 * x20_11 + 2^128 * x21_11 + 2^192 * x22_11 + 2^256 * x23_10 + + lhs.toNat * x9_3 := by + clear * - hsum_3 hk_3 + omega + -- END round 3 fold + -- x17_13: lsl x17,x3,#62 + extract_lets +onlyGivenNames x17_13 at hr + have e_x17_13 : x17_13 = x3_3 * 2^62 % 2^64 := rfl + clear_value x17_13 + have b_x17_13 : x17_13 < 2^64 := by rw [e_x17_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + -- c_48: subs xzr,x19,#1 + extract_lets +onlyGivenNames c_48 at hr + have e_c_48 : c_48 = (x19_6 + 2^64 - 1 - (1 - 1)) / 2^64 := rfl + clear_value c_48 + have b_c_48 : c_48 ≤ 1 := by rw [e_c_48]; exact subc_carry_le_one x19_6 1 1 b_x19_6 + have l_c_48 : (c_48 = 1 ∧ 1 + 1 ≤ x19_6 + 1) ∨ (c_48 = 0 ∧ x19_6 + 1 < 1 + 1) := + subc_carry_cases x19_6 1 1 _ e_c_48 b_x19_6 (by decide) (by decide) + clear e_c_48 + -- x14_10: umulh x14,x5,x3 + extract_lets +onlyGivenNames x14_10 at hr + have e_x14_10 : x14_10 = x5 * x3_3 / 2^64 := rfl + clear_value x14_10 + have p_x14_10 : x5 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x5 b_x3_3 + have b_x14_10 : x14_10 < 2^64 := by rw [e_x14_10]; exact Nat.div_lt_of_lt_mul p_x14_10 + obtain ⟨lo_x14_10, b_lo_x14_10, d_x14_10⟩ : + ∃ lo, lo < 2^64 ∧ lo + 2^64 * x14_10 = x5 * x3_3 := + ⟨x5 * x3_3 % 2^64, Nat.mod_lt _ (Nat.two_pow_pos _), + by rw [e_x14_10]; exact Nat.mod_add_div _ _⟩ + clear e_x14_10 + -- x20_14: adcs x20,x20,x15 + extract_lets +onlyGivenNames s_45 x20_14 c_49 at hr + have e_x20_14 : x20_14 = (x20_13 + x15_13 + c_48) % 2^64 := rfl + have e_c_49 : c_49 = (x20_13 + x15_13 + c_48) / 2^64 := rfl + clear_value s_45 x20_14 c_49 + have l_x20_14 : x20_14 + 2^64 * c_49 = x20_13 + x15_13 + c_48 := by + rw [e_x20_14, e_c_49]; exact Nat.mod_add_div _ _ + have b_x20_14 : x20_14 < 2^64 := by rw [e_x20_14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_49 : c_49 ≤ 1 := by + rw [e_c_49]; exact addc_carry_le_one x20_13 x15_13 c_48 b_x20_13 b_x15_13 b_c_48 + clear e_x20_14 e_c_49 + -- x15_14: umulh x15,x6,x3 + extract_lets +onlyGivenNames x15_14 at hr + have e_x15_14 : x15_14 = x6 * x3_3 / 2^64 := rfl + clear_value x15_14 + have p_x15_14 : x6 * x3_3 < 2^64 * 2^64 := Nat.mul_lt_mul'' b_x6 b_x3_3 + have b_x15_14 : x15_14 < 2^64 := by rw [e_x15_14]; exact Nat.div_lt_of_lt_mul p_x15_14 + have d_x15_14 : x15_13 + 2^64 * x15_14 = x6 * x3_3 := by + rw [e_x15_13, e_x15_14]; exact Nat.mod_add_div _ _ + clear e_x15_13 e_x15_14 + -- x21_14: adcs x21,x21,xzr + extract_lets +onlyGivenNames s_46 x21_14 c_50 at hr + have e_x21_14 : x21_14 = (x21_13 + 0 + c_49) % 2^64 := rfl + have e_c_50 : c_50 = (x21_13 + 0 + c_49) / 2^64 := rfl + clear_value s_46 x21_14 c_50 + have l_x21_14 : x21_14 + 2^64 * c_50 = x21_13 + 0 + c_49 := by + rw [e_x21_14, e_c_50]; exact Nat.mod_add_div _ _ + have b_x21_14 : x21_14 < 2^64 := by rw [e_x21_14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_50 : c_50 ≤ 1 := by + rw [e_c_50]; exact addc_carry_le_one x21_13 0 c_49 b_x21_13 (by decide) b_c_49 + clear e_x21_14 e_c_50 + -- x22_14: adcs x22,x22,x17 + extract_lets +onlyGivenNames s_47 x22_14 c_51 at hr + have e_x22_14 : x22_14 = (x22_13 + x17_13 + c_50) % 2^64 := rfl + have e_c_51 : c_51 = (x22_13 + x17_13 + c_50) / 2^64 := rfl + clear_value s_47 x22_14 c_51 + have l_x22_14 : x22_14 + 2^64 * c_51 = x22_13 + x17_13 + c_50 := by + rw [e_x22_14, e_c_51]; exact Nat.mod_add_div _ _ + have b_x22_14 : x22_14 < 2^64 := by rw [e_x22_14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_51 : c_51 ≤ 1 := by + rw [e_c_51]; exact addc_carry_le_one x22_13 x17_13 c_50 b_x22_13 b_x17_13 b_c_50 + clear e_x22_14 e_c_51 + -- x17_14: lsr x17,x3,#2 + extract_lets +onlyGivenNames x17_14 at hr + have e_x17_14 : x17_14 = x3_3 / 2^2 := rfl + clear_value x17_14 + have b_x17_14 : x17_14 < 2^62 := by + rw [e_x17_14]; exact Nat.div_lt_of_lt_mul (lt_of_lt_of_eq b_x3_3 (by norm_num)) + have sh_x17_14 : x17_13 + 2^64 * x17_14 = x3_3 * 2^62 := by + rw [e_x17_13, e_x17_14]; exact lsl62_lsr2_split _ + clear e_x17_13 e_x17_14 + -- x23_13: adc x23,x23,xzr + extract_lets +onlyGivenNames x23_13 at hr + have e_x23_13 : x23_13 = (x23_12 + 0 + c_51) % 2^64 := rfl + clear_value x23_13 + have b_x23_13 : x23_13 < 2^64 := by rw [e_x23_13]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_13, b_k_x23_13, l_x23_13⟩ : + ∃ k, k ≤ 1 ∧ x23_13 + 2^64 * k = x23_12 + 0 + c_51 := + ⟨(x23_12 + 0 + c_51) / 2^64, addc_carry_le_one x23_12 0 c_51 b_x23_12 (by decide) b_c_51, + by rw [e_x23_13]; exact Nat.mod_add_div _ _⟩ + clear e_x23_13 + -- x19_7: adds x19,x20,x14 + extract_lets +onlyGivenNames s_48 x19_7 c_52 at hr + have e_x19_7 : x19_7 = (x20_14 + x14_10 + 0) % 2^64 := rfl + have e_c_52 : c_52 = (x20_14 + x14_10 + 0) / 2^64 := rfl + clear_value s_48 x19_7 c_52 + have l_x19_7 : x19_7 + 2^64 * c_52 = x20_14 + x14_10 + 0 := by + rw [e_x19_7, e_c_52]; exact Nat.mod_add_div _ _ + have b_x19_7 : x19_7 < 2^64 := by rw [e_x19_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_52 : c_52 ≤ 1 := by + rw [e_c_52]; exact addc_carry_le_one x20_14 x14_10 0 b_x20_14 b_x14_10 (by decide) + clear e_x19_7 e_c_52 + -- x20_15: adcs x20,x21,x15 + extract_lets +onlyGivenNames s_49 x20_15 c_53 at hr + have e_x20_15 : x20_15 = (x21_14 + x15_14 + c_52) % 2^64 := rfl + have e_c_53 : c_53 = (x21_14 + x15_14 + c_52) / 2^64 := rfl + clear_value s_49 x20_15 c_53 + have l_x20_15 : x20_15 + 2^64 * c_53 = x21_14 + x15_14 + c_52 := by + rw [e_x20_15, e_c_53]; exact Nat.mod_add_div _ _ + have b_x20_15 : x20_15 < 2^64 := by rw [e_x20_15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_53 : c_53 ≤ 1 := by + rw [e_c_53]; exact addc_carry_le_one x21_14 x15_14 c_52 b_x21_14 b_x15_14 b_c_52 + clear e_x20_15 e_c_53 + -- x21_15: adcs x21,x22,xzr + extract_lets +onlyGivenNames s_50 x21_15 c_54 at hr + have e_x21_15 : x21_15 = (x22_14 + 0 + c_53) % 2^64 := rfl + have e_c_54 : c_54 = (x22_14 + 0 + c_53) / 2^64 := rfl + clear_value s_50 x21_15 c_54 + have l_x21_15 : x21_15 + 2^64 * c_54 = x22_14 + 0 + c_53 := by + rw [e_x21_15, e_c_54]; exact Nat.mod_add_div _ _ + have b_x21_15 : x21_15 < 2^64 := by rw [e_x21_15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_54 : c_54 ≤ 1 := by + rw [e_c_54]; exact addc_carry_le_one x22_14 0 c_53 b_x22_14 (by decide) b_c_53 + clear e_x21_15 e_c_54 + -- x22_15: adcs x22,x23,x17 + extract_lets +onlyGivenNames s_51 x22_15 c_55 at hr + have e_x22_15 : x22_15 = (x23_13 + x17_14 + c_54) % 2^64 := rfl + have e_c_55 : c_55 = (x23_13 + x17_14 + c_54) / 2^64 := rfl + clear_value s_51 x22_15 c_55 + have l_x22_15 : x22_15 + 2^64 * c_55 = x23_13 + x17_14 + c_54 := by + rw [e_x22_15, e_c_55]; exact Nat.mod_add_div _ _ + have b_x22_15 : x22_15 < 2^64 := by rw [e_x22_15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_55 : c_55 ≤ 1 := by + rw [e_c_55]; exact addc_carry_le_one x23_13 x17_14 c_54 b_x23_13 (lt_of_lt_of_le b_x17_14 (by norm_num)) b_c_54 + clear e_x22_15 e_c_55 + -- x23_14: adc x23,xzr,xzr + extract_lets +onlyGivenNames x23_14 at hr + have e_x23_14 : x23_14 = (0 + 0 + c_55) % 2^64 := rfl + clear_value x23_14 + have b_x23_14 : x23_14 < 2^64 := by rw [e_x23_14]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + obtain ⟨k_x23_14, b_k_x23_14, l_x23_14⟩ : + ∃ k, k ≤ 1 ∧ x23_14 + 2^64 * k = 0 + 0 + c_55 := + ⟨(0 + 0 + c_55) / 2^64, addc_carry_le_one 0 0 c_55 (by decide) (by decide) b_c_55, + by rw [e_x23_14]; exact Nat.mod_add_div _ _⟩ + clear e_x23_14 + -- BEGIN round 3 reduction + -- Cancellation: the low limb of `x19_6 + p0 * x3_3` is zero, so `x19_6 + lo_x14_10` is + -- `0` or `2^64`, and `subs xzr, x19_6, #1` set the carry exactly when it is `2^64`. + have hc_3 : x19_6 + lo_x14_10 = 2^64 * c_48 := by + have h := cancel_low x19_6 inv modulus.l0 hinv + rw [← e_x5, ← e_x4, ← e_x3_3, ← d_x14_10, Nat.add_mul_mod_self_left, + Nat.mod_eq_of_lt b_lo_x14_10] at h + clear * - h b_x19_6 b_lo_x14_10 l_c_48 + omega + have bc_3 : c_48 ≤ 1 := by clear * - l_c_48; omega + have hPq_3 : x3_3 * modulus.toNat = x5 * x3_3 + 2^64 * (x6 * x3_3) + 2^254 * x3_3 := by + rw [hP]; ring + -- `x17_13` is the low two bits of `x3_3` at the top of a limb. + have hsh_3 : x17_13 ≤ 3 * 2^62 := by + clear * - sh_x17_14 b_x17_13 b_x17_14; omega + -- The reduction's carry chain, summed with the limb weights. + have hsum'_3 : x19_6 + 2^64 * x20_14 + 2^128 * x21_14 + 2^192 * x22_14 + 2^256 * x23_13 + + 2^320 * k_x23_13 + = x19_6 + 2^64 * x20_13 + 2^128 * x21_13 + 2^192 * x22_13 + 2^256 * x23_12 + + 2^64 * x15_13 + 2^64 * c_48 + 2^192 * x17_13 := by + clear * - l_x20_14 l_x21_14 l_x22_14 l_x23_13 + omega + -- Neither `adc` of the reduction wraps: the five-limb accumulator is below + -- `2^320 - 3 * 2^254 - 2^128` by `hs_3`, and the reduction adds less than that before + -- the shift. + have hkr_3 : k_x23_13 = 0 := by + clear * - hsum'_3 F_3 B_2 hs_3 b_x15_13 bc_3 hsh_3 + omega + have hks_3 : k_x23_14 = 0 := by clear * - l_x23_14 b_c_55; omega + have I_3 : 2^64 * (x19_7 + 2^64 * x20_15 + 2^128 * x21_15 + 2^192 * x22_15 + 2^256 * x23_14) + = x19_6 + 2^64 * x20_13 + 2^128 * x21_13 + 2^192 * x22_13 + 2^256 * x23_12 + + x3_3 * modulus.toNat := by + clear * - hc_3 d_x14_10 d_x15_14 sh_x17_14 l_x20_14 l_x21_14 l_x22_14 l_x23_13 l_x19_7 l_x20_15 + l_x21_15 l_x22_15 l_x23_14 hkr_3 hks_3 hPq_3 + omega + -- The shifted accumulator stays below `lhs + p`. + have hLx_3 : lhs.toNat * x9_3 + lhs.toNat ≤ lhs.toNat * 2^64 := by + rw [← Nat.mul_succ]; exact Nat.mul_le_mul_left _ b_x9_3 + have hqP_3 : x3_3 * modulus.toNat + modulus.toNat ≤ 2^64 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ b_x3_3 + have B_3 : x19_7 + 2^64 * x20_15 + 2^128 * x21_15 + 2^192 * x22_15 + 2^256 * x23_14 + < lhs.toNat + modulus.toNat := by + clear * - I_3 F_3 hLx_3 hqP_3 B_2 + omega + have t_3 : x23_14 ≤ 1 := by clear * - l_x23_14 hks_3 b_c_55; omega + -- END round 3 reduction + -- x14_11: subs x14,x19,x5 + extract_lets +onlyGivenNames s_52 x14_11 c_56 at hr + have e_x14_11 : x14_11 = (x19_7 + 2^64 - x5 - (1 - 1)) % 2^64 := rfl + have e_c_56 : c_56 = (x19_7 + 2^64 - x5 - (1 - 1)) / 2^64 := rfl + clear_value s_52 x14_11 c_56 + have l_x14_11 : x14_11 + 2^64 * c_56 + x5 + 1 = x19_7 + 2^64 + 1 := by + rw [e_x14_11, e_c_56]; exact subc_lin x19_7 x5 1 b_x5 (by decide) + have b_x14_11 : x14_11 < 2^64 := by rw [e_x14_11]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_56 : c_56 ≤ 1 := by + rw [e_c_56]; exact subc_carry_le_one x19_7 x5 1 b_x19_7 + clear e_x14_11 e_c_56 + -- x15_15: sbcs x15,x20,x6 + extract_lets +onlyGivenNames s_53 x15_15 c_57 at hr + have e_x15_15 : x15_15 = (x20_15 + 2^64 - x6 - (1 - c_56)) % 2^64 := rfl + have e_c_57 : c_57 = (x20_15 + 2^64 - x6 - (1 - c_56)) / 2^64 := rfl + clear_value s_53 x15_15 c_57 + have l_x15_15 : x15_15 + 2^64 * c_57 + x6 + 1 = x20_15 + 2^64 + c_56 := by + rw [e_x15_15, e_c_57]; exact subc_lin x20_15 x6 c_56 b_x6 b_c_56 + have b_x15_15 : x15_15 < 2^64 := by rw [e_x15_15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_57 : c_57 ≤ 1 := by + rw [e_c_57]; exact subc_carry_le_one x20_15 x6 c_56 b_x20_15 + clear e_x15_15 e_c_57 + -- x16_7: sbcs x16,x21,xzr + extract_lets +onlyGivenNames s_54 x16_7 c_58 at hr + have e_x16_7 : x16_7 = (x21_15 + 2^64 - 0 - (1 - c_57)) % 2^64 := rfl + have e_c_58 : c_58 = (x21_15 + 2^64 - 0 - (1 - c_57)) / 2^64 := rfl + clear_value s_54 x16_7 c_58 + have l_x16_7 : x16_7 + 2^64 * c_58 + 0 + 1 = x21_15 + 2^64 + c_57 := by + rw [e_x16_7, e_c_58]; exact subc_lin x21_15 0 c_57 (by decide) b_c_57 + have b_x16_7 : x16_7 < 2^64 := by rw [e_x16_7]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_58 : c_58 ≤ 1 := by + rw [e_c_58]; exact subc_carry_le_one x21_15 0 c_57 b_x21_15 + clear e_x16_7 e_c_58 + -- x17_15: sbcs x17,x22,x8 + extract_lets +onlyGivenNames s_55 x17_15 c_59 at hr + have e_x17_15 : x17_15 = (x22_15 + 2^64 - x8 - (1 - c_58)) % 2^64 := rfl + have e_c_59 : c_59 = (x22_15 + 2^64 - x8 - (1 - c_58)) / 2^64 := rfl + clear_value s_55 x17_15 c_59 + have l_x17_15 : x17_15 + 2^64 * c_59 + x8 + 1 = x22_15 + 2^64 + c_58 := by + rw [e_x17_15, e_c_59]; exact subc_lin x22_15 x8 c_58 b_x8 b_c_58 + have b_x17_15 : x17_15 < 2^64 := by rw [e_x17_15]; exact Nat.mod_lt _ (Nat.two_pow_pos _) + have b_c_59 : c_59 ≤ 1 := by + rw [e_c_59]; exact subc_carry_le_one x22_15 x8 c_58 b_x22_15 + clear e_x17_15 e_c_59 + -- c_60: sbcs xzr,x23,xzr + extract_lets +onlyGivenNames c_60 at hr + have e_c_60 : c_60 = (x23_14 + 2^64 - 0 - (1 - c_59)) / 2^64 := rfl + clear_value c_60 + have b_c_60 : c_60 ≤ 1 := by rw [e_c_60]; exact subc_carry_le_one x23_14 0 c_59 b_x23_14 + have l_c_60 : (c_60 = 1 ∧ 0 + 1 ≤ x23_14 + c_59) ∨ (c_60 = 0 ∧ x23_14 + c_59 < 0 + 1) := + subc_carry_cases x23_14 0 c_59 _ e_c_60 b_x23_14 (by decide) b_c_59 + clear e_c_60 + -- x19_8: csel x19,x19,x14,lo + extract_lets +onlyGivenNames x19_8 at hr + have e_x19_8 : x19_8 = (if c_60 = 0 then x19_7 else x14_11) := rfl + clear_value x19_8 + have b_x19_8 : x19_8 < 2^64 := by + rw [e_x19_8]; split <;> first | exact b_x19_7 | exact b_x14_11 + -- x20_16: csel x20,x20,x15,lo + extract_lets +onlyGivenNames x20_16 at hr + have e_x20_16 : x20_16 = (if c_60 = 0 then x20_15 else x15_15) := rfl + clear_value x20_16 + have b_x20_16 : x20_16 < 2^64 := by + rw [e_x20_16]; split <;> first | exact b_x20_15 | exact b_x15_15 + -- x21_16: csel x21,x21,x16,lo + extract_lets +onlyGivenNames x21_16 at hr + have e_x21_16 : x21_16 = (if c_60 = 0 then x21_15 else x16_7) := rfl + clear_value x21_16 + have b_x21_16 : x21_16 < 2^64 := by + rw [e_x21_16]; split <;> first | exact b_x21_15 | exact b_x16_7 + -- x22_16: csel x22,x22,x17,lo + extract_lets +onlyGivenNames x22_16 at hr + have e_x22_16 : x22_16 = (if c_60 = 0 then x22_15 else x17_15) := rfl + clear_value x22_16 + have b_x22_16 : x22_16 < 2^64 := by + rw [e_x22_16]; split <;> first | exact b_x22_15 | exact b_x17_15 + -- out0: stp x19,x20,[x0] + extract_lets +onlyGivenNames out0 at hr + have e_out0 : out0 = x19_8 := rfl + clear_value out0 + -- out1: stp x19,x20,[x0] + extract_lets +onlyGivenNames out1 at hr + have e_out1 : out1 = x20_16 := rfl + clear_value out1 + -- out2: stp x21,x22,[x0,#16] + extract_lets +onlyGivenNames out2 at hr + have e_out2 : out2 = x21_16 := rfl + clear_value out2 + -- out3: stp x21,x22,[x0,#16] + extract_lets +onlyGivenNames out3 at hr + have e_out3 : out3 = x22_16 := rfl + clear_value out3 + subst hr + -- BEGIN conclusion + subst out0 out1 out2 out3 + have hLR : lhs.toNat * rhs.toNat + = lhs.toNat * x9 + 2^64 * (lhs.toNat * x9_1) + 2^128 * (lhs.toNat * x9_2) + + 2^192 * (lhs.toNat * x9_3) := by + rw [e_x9, e_x9_1, e_x9_2, e_x9_3]; simp only [Limbs.toNat]; ring + have hQ : x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3 < 2^256 := by + clear * - b_x3 b_x3_1 b_x3_2 b_x3_3; omega + have hQP : (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) * modulus.toNat + = x3 * modulus.toNat + 2^64 * (x3_1 * modulus.toNat) + 2^128 * (x3_2 * modulus.toNat) + + 2^192 * (x3_3 * modulus.toNat) := by + ring + -- The four rounds compose to `2^256 * acc = lhs * rhs + Q * p`. + have hmain : 2^256 * (x19_7 + 2^64 * x20_15 + 2^128 * x21_15 + 2^192 * x22_15 + 2^256 * x23_14) + = lhs.toNat * rhs.toNat + + (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) * modulus.toNat := by + clear * - F_0 F_1 F_2 F_3 I_0 I_1 I_2 I_3 hLR hQP + omega + have hQPle : (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) * modulus.toNat + modulus.toNat + ≤ 2^256 * modulus.toNat := by + rw [← Nat.succ_mul]; exact Nat.mul_le_mul_right _ hQ + -- `hfinal` puts the accumulator below `2 * p`, hence below `2^256`: its fifth limb is `0` and the + -- five-limb comparison is the four-limb one. The carry is set (`c_60 = 1`) exactly when the + -- accumulator is at least `p`; then the result is the difference, otherwise the accumulator. + have hA : x19_7 + 2^64 * x20_15 + 2^128 * x21_15 + 2^192 * x22_15 + 2^256 * x23_14 + < 2 * modulus.toNat := by + clear * - hmain hfinal hQPle; omega + have hx23 : x23_14 = 0 := by clear * - hA hP_lt; omega + have e_x8' : x8 = 2^62 := by rw [e_x8]; exact hshape.2 + have hD : x14_11 + 2^64 * x15_15 + 2^128 * x16_7 + 2^192 * x17_15 + + (x5 + 2^64 * x6 + 2^192 * x8) + 2^256 * c_59 + = x19_7 + 2^64 * x20_15 + 2^128 * x21_15 + 2^192 * x22_15 + 2^256 := by + clear * - l_x14_11 l_x15_15 l_x16_7 l_x17_15; omega + have hc59 : c_59 = c_60 := by clear * - l_c_60 hx23 b_c_59; omega + refine ⟨⟨b_x19_8, b_x20_16, b_x21_16, b_x22_16⟩, ?_⟩ + show x19_8 + 2^64 * x20_16 + 2^128 * x21_16 + 2^192 * x22_16 < modulus.toNat ∧ + 2^256 * (x19_8 + 2^64 * x20_16 + 2^128 * x21_16 + 2^192 * x22_16) + ≡ lhs.toNat * rhs.toNat [MOD modulus.toNat] + obtain hc | hc : c_60 = 0 ∨ c_60 = 1 := by clear * - l_c_60; omega + · rw [if_pos hc] at e_x19_8 e_x20_16 e_x21_16 e_x22_16 + refine ⟨?_, modEq_of_add_mul _ _ 0 (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) _ (by + clear * - hmain hx23 e_x19_8 e_x20_16 e_x21_16 e_x22_16 + omega)⟩ + · clear * - hD hc59 hc hx23 hP e_x8' b_x14_11 b_x15_15 b_x16_7 b_x17_15 e_x19_8 e_x20_16 + e_x21_16 e_x22_16 + omega + · rw [if_neg (by clear * - hc; omega)] at e_x19_8 e_x20_16 e_x21_16 e_x22_16 + refine ⟨?_, modEq_of_add_mul _ _ (2^256) (x3 + 2^64 * x3_1 + 2^128 * x3_2 + 2^192 * x3_3) _ (by + clear * - hmain hD hc59 hc hx23 hP e_x8' e_x19_8 e_x20_16 e_x21_16 e_x22_16 + omega)⟩ + · clear * - hD hc59 hc hx23 hA hP e_x8' e_x19_8 e_x20_16 e_x21_16 e_x22_16 + omega + -- END conclusion + +-- BEGIN mulMont_spec corollaries +/-- Below `2^256`, by the limb bounds. -/ +theorem Limbs.toNat_lt (x : Limbs) (hx : x.Bounded) : x.toNat < 2^256 := by + obtain ⟨h0, h1, h2, h3⟩ := hx + simp only [Limbs.toNat]; omega + +/-- With the modulus in the shape the code assumes, `p < 2^255`. -/ +theorem Limbs.toNat_lt_of_shape (modulus : Limbs) (hm : modulus.Bounded) + (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) : modulus.toNat < 2^255 := by + obtain ⟨h0, h1, _, _⟩ := hm + simp only [Limbs.toNat, hshape.1, hshape.2]; omega + +/-- The contract the crate's callers use: a canonical left operand and any four-limb right +operand. -/ +theorem mulMont_spec_of_lhs_lt (lhs rhs modulus : Limbs) (inv : Nat) (hlhs : lhs.Bounded) + (hrhs : rhs.Bounded) (hm : modulus.Bounded) (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) + (hinv_lt : inv < 2^64) (hinv : (inv * modulus.l0 + 1) % 2^64 = 0) + (hlt : lhs.toNat < modulus.toNat) : + ∀ r, r = mulMont lhs rhs modulus inv → + r.Bounded ∧ r.toNat < modulus.toNat ∧ + 2^256 * r.toNat ≡ lhs.toNat * rhs.toNat [MOD modulus.toNat] := by + have hP := Limbs.toNat_lt_of_shape modulus hm hshape + have hR := Limbs.toNat_lt rhs hrhs + -- `lhs * (rhs_i + 1) ≤ (p - 1) * 2^64`, and `lhs * rhs < p * 2^256`. + have s1 : lhs.toNat * (rhs.l1 + 1) ≤ (modulus.toNat - 1) * 2^64 := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hlt) hrhs.2.1 + have s2 : lhs.toNat * (rhs.l2 + 1) ≤ (modulus.toNat - 1) * 2^64 := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hlt) hrhs.2.2.1 + have s3 : lhs.toNat * (rhs.l3 + 1) ≤ (modulus.toNat - 1) * 2^64 := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hlt) hrhs.2.2.2 + have f : (lhs.toNat + 1) * (rhs.toNat + 1) ≤ modulus.toNat * 2^256 := Nat.mul_le_mul hlt hR + rw [Nat.add_one_mul, Nat.mul_add_one] at f + exact mulMont_spec lhs rhs modulus inv hlhs hrhs hm hshape hinv_lt hinv + ⟨by omega, by omega, by omega⟩ (by omega) + +/-- The other safe contract: any four-limb left operand, a canonical right operand whose limbs 1 +to 3 are at most `2^64 - 3`. -/ +theorem mulMont_spec_of_rhs_lt (lhs rhs modulus : Limbs) (inv : Nat) (hlhs : lhs.Bounded) + (hrhs : rhs.Bounded) (hm : modulus.Bounded) (hshape : modulus.l2 = 0 ∧ modulus.l3 = 2^62) + (hinv_lt : inv < 2^64) (hinv : (inv * modulus.l0 + 1) % 2^64 = 0) + (hlt : rhs.toNat < modulus.toNat) + (hlimbs : rhs.l1 + 3 ≤ 2^64 ∧ rhs.l2 + 3 ≤ 2^64 ∧ rhs.l3 + 3 ≤ 2^64) : + ∀ r, r = mulMont lhs rhs modulus inv → + r.Bounded ∧ r.toNat < modulus.toNat ∧ + 2^256 * r.toNat ≡ lhs.toNat * rhs.toNat [MOD modulus.toNat] := by + have hP := Limbs.toNat_lt_of_shape modulus hm hshape + have hL := Limbs.toNat_lt lhs hlhs + -- `lhs * (rhs_i + 1) ≤ (2^256 - 1) * (2^64 - 2)`, and `lhs * rhs < 2^256 * p`. + have c1 : rhs.l1 + 1 ≤ 2^64 - 2 := by omega + have c2 : rhs.l2 + 1 ≤ 2^64 - 2 := by omega + have c3 : rhs.l3 + 1 ≤ 2^64 - 2 := by omega + have s1 : lhs.toNat * (rhs.l1 + 1) ≤ (2^256 - 1) * (2^64 - 2) := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hL) c1 + have s2 : lhs.toNat * (rhs.l2 + 1) ≤ (2^256 - 1) * (2^64 - 2) := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hL) c2 + have s3 : lhs.toNat * (rhs.l3 + 1) ≤ (2^256 - 1) * (2^64 - 2) := + Nat.mul_le_mul (Nat.le_sub_one_of_lt hL) c3 + norm_num at s1 s2 s3 + have f : (lhs.toNat + 1) * (rhs.toNat + 1) ≤ 2^256 * modulus.toNat := Nat.mul_le_mul hL hlt + rw [Nat.add_one_mul, Nat.mul_add_one] at f + exact mulMont_spec lhs rhs modulus inv hlhs hrhs hm hshape hinv_lt hinv + ⟨by omega, by omega, by omega⟩ (by omega) +-- END mulMont_spec corollaries + end CompElliptic.Asm.AArch64 diff --git a/README.md b/README.md index c281a69..4a5ab9f 100644 --- a/README.md +++ b/README.md @@ -144,9 +144,10 @@ Early work in progress. Present so far: - a transcription of the AArch64 Pasta Montgomery routines that pasta_curves vendors from Semolina, generated from the assembly over a small instruction-semantics module, with reference vectors from the real routines checked by the kernel, and instruction-by-instruction - correctness proofs of their shared reduction helper and of the conversion out of Montgomery - form (`CompElliptic/Asm/AArch64/`; `design/aarch64-pasta-mul-verification.md` states the - remaining correctness theorems). + correctness proofs of the multiplication, of its shared reduction helper, and of the conversion + out of Montgomery form, the multiplication under each of its two operand contracts + (`CompElliptic/Asm/AArch64/`; `design/aarch64-pasta-mul-verification.md` states the remaining + correctness theorems). The library's general theorems depend only on the standard `propext` / `Classical.choice` / `Quot.sound` axioms. Facts specific to concrete fields and curves additionally depend on diff --git a/design/aarch64-pasta-mul-verification.md b/design/aarch64-pasta-mul-verification.md index dacfbf1..5d139ba 100644 --- a/design/aarch64-pasta-mul-verification.md +++ b/design/aarch64-pasta-mul-verification.md @@ -68,26 +68,33 @@ The generator emits each routine as a chain of `let`s in a single function from input limbs (and modulus limbs and `inv`) to the output limbs. The proofs in `PastaMulSpec.lean` follow that chain instruction by instruction, and their mechanical part is generated too (`gen_aarch64_pasta_mul.py --skeleton `). The skeleton -unfolds the routine and extracts its `let`s under unique names. Then, for every -instruction, it records the defining equation of the result (by `rfl`, in `%`/`/` form), -derives from it the facts that later steps need (the carry-chain equation -`x + 2^64 * c = a + b + cin`, the range facts, the product decomposition -`lo + 2^64 * hi = a * b`), clears the `%`/`/` equation, and makes the local opaque with -`clear_value`. The hand-written parts are the theorem statements and the -`-- BEGIN ... -- END` annotation blocks between instructions. A block states the -Montgomery round invariant that holds at that point and derives it from the facts it -names. `gen_aarch64_pasta_mul.py --check-spec` strips the blocks and requires the rest -of the proof to be the current skeleton, so an edit to the `.S` regenerates the skeleton -and the check fails loudly until the annotations are moved. - -Two measurements fixed this shape. `omega` given a whole reduction round at once, or +unfolds the routine in the hypothesis that names its result. Then, for every +instruction, it extracts that instruction's `let`s from the hypothesis under unique +names, records the defining equation of the result (by `rfl`, in `%`/`/` form), makes +the locals opaque with `clear_value`, and derives from the equation the facts that later +steps need (the carry-chain equation `x + 2^64 * c = a + b + cin`, the range facts, the +product decomposition `lo + 2^64 * hi = a * b`), each an instance of one lemma, clearing +the `%`/`/` equation when nothing later needs it. The hand-written parts are the theorem +statements and the `-- BEGIN ... -- END` annotation blocks between instructions. A +block states the Montgomery round invariant that holds at that point and derives it +from the facts it names. `gen_aarch64_pasta_mul.py --check-spec` strips the blocks and +requires the rest of the proof to be the current skeleton, so an edit to the `.S` +regenerates the skeleton and the check fails loudly until the annotations are moved. + +Three measurements fixed this shape. `omega` given a whole reduction round at once, or given the cancellation fact with its `%` terms still in it, runs for minutes without finishing; given one carry step at a time, or linear equations only, it answers in milliseconds. So each round block first rewrites the cancellation fact `(t0 + p0 * q % 2^64) % 2^64 = 0` to the linear `t0 + lo = 2^64 * c`, using the ghost low limb and the carry of `subs xzr, t0, #1`; it then shows that neither `adc` wraps; and the invariant is a linear combination of the instruction equations, proved by -`omega` in a context cleared down to exactly those equations. +`omega` in a context cleared down to exactly those equations. `clear_value` reverts +every later local and re-checks the reverted context, so extracting all the `let`s up +front made each clear quadratic in the chain's length; the multiplication routine's 264 +locals exhausted the heartbeat budget, and extracting one instruction at a time, with +the rest of the chain still folded in the hypothesis, is what keeps every clear cheap. +What remains of the multiplication's cost is its sixty-odd `clear * -` calls in a +context of a thousand hypotheses, so that theorem raises its heartbeat budget. ## Theorems @@ -97,11 +104,15 @@ the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: * `mulBy1_spec` (proved): for every four-limb `t`, the shared reduction helper returns limbs `r` below `2^64` with `2^256 · r = t + Q · p` for some `Q < 2^256`. So `r` is congruent to `t · 2^−256` modulo `p`, and `r ≤ p`. -* `mul_spec` (to prove): if `lhs < p` and `rhs < 2^256`, or `lhs < 2^256`, `rhs < p`, and every - `rhs` limb in positions 1 to 3 is at most `2^64 − 4`, then the output is below `p` - and `output · 2^256 ≡ lhs · rhs (mod p)`. The exact wrap boundary (whether `2^64 − 2` - and `2^64 − 3` can wrap) is settled as a by-product of the round lemma and stated as - its own lemma. +* `mulMont_spec` (proved): the output is below `p` and `output · 2^256 ≡ lhs · rhs (mod p)` + under two arithmetic conditions: `lhs · (rhs_i + 1) + p + 3 · 2^254 + 2^128 ≤ 2^320` + for each of `rhs_1`, `rhs_2`, `rhs_3` (the five-limb accumulator, which enters each + round below `lhs + p`, stays below `2^320` through the round's `adc`s), and + `lhs · rhs < 2^256 · p` (the final accumulator is below `2 · p`, which one conditional + subtraction reduces). Its two corollaries are the operand contracts: + `mulMont_spec_of_lhs_lt`, for `lhs < p` and any four-limb `rhs`, and + `mulMont_spec_of_rhs_lt`, for any four-limb `lhs` and `rhs < p` whose limbs 1 to 3 are + at most `2^64 − 3`. Whether `2^64 − 2` can wrap is not settled by these conditions. * `sqr_spec` (to prove): if `a < p`, the output is below `p` and `output · 2^256 ≡ a² (mod p)`. * `fromMont_spec` (proved): for every four-limb `a`, the output is below `p` and `output · 2^256 ≡ a (mod p)`. No bound on `a` below `p` is needed: the helper's result is @@ -110,7 +121,7 @@ the code assumes) and `inv · p0 ≡ −1 (mod 2^64)`: `Pasta.lean` instantiates these at `PALLAS_BASE_CARD` and `PALLAS_SCALAR_CARD` with the crate's `MODULUS`, `INV`, `R2`, `R3` limbs pinned by `decide`, and states the corollary the crate relies on: `mul lhs R2` and `mul lhs R3` are correct for every -256-bit `lhs`, because no limb 1 to 3 of `R2`/`R3` is above `2^64 − 4`. It also states +256-bit `lhs`, because no limb 1 to 3 of `R2`/`R3` is above `2^64 − 3`. It also states the negative: the witness pair is inside `lhs · rhs < 2^256 · p` and the model's output is not the Montgomery product (by evaluation), documenting why #108's contract is wrong. @@ -118,15 +129,15 @@ wrong. ## Status Present: the semantics, the generator, the generated program, the vendored `.S` with its -hash, the vectors, and the CI check; the proofs of the helper (four reduction rounds) and -of `from_mont` (the helper and a conditional subtraction). +hash, the vectors, and the CI check; the proofs of the helper (four reduction rounds), of +`from_mont` (the helper and a conditional subtraction), and of `mul` (four rounds of +schoolbook fold and reduction, the accumulator no-wrap conditions, the final comparison, +and the two operand contracts as corollaries). Remaining, in order: -1. `mul`: the round invariant, the accumulator no-wrap lemma under each contract, and the - final comparison. -2. `sqr`: the cross-term schoolbook, the doubling, and the "can't overflow" claims. -3. The Pasta instantiation and the census entries in `TrustBoundary.lean`. +1. `sqr`: the cross-term schoolbook, the doubling, and the "can't overflow" claims. +2. The Pasta instantiation and the census entries in `TrustBoundary.lean`. Out of scope for now: Zakura's inline-`asm!` transcription (provable later by instruction-by-instruction correspondence), `sqr_n_mul` (zakura-core/common#65), and