aboutsummaryrefslogtreecommitdiff
path: root/src/CompleteEdwardsCurve/DoubleAndAdd.v
blob: 7c1e173eeec48a76e5465ffcdf0d881483b5f27d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Require Import Crypto.Tactics.VerdiTactics.
Require Import Crypto.Spec.CompleteEdwardsCurve Crypto.BoundedIterOp.
Require Import Crypto.CompleteEdwardsCurve.CompleteEdwardsCurveTheorems.
Require Import BinNums NArith Nnat ZArith.

Section EdwardsDoubleAndAdd.
  Context {prm:TwistedEdwardsParams}.
  Definition doubleAndAdd (b n : nat) (P : point) : point :=
    match N.of_nat n with
    | 0%N => zero
    | N.pos p => iter_op unifiedAdd zero b p b P
    end.

  Lemma scalarMult_double : forall n P, scalarMult (n + n) P = scalarMult n (P + P)%E.
  Proof.
    intros.
    replace (n + n)%nat with (n * 2)%nat by omega.
    induction n; simpl; auto.
    rewrite twistedAddAssoc.
    f_equal; auto.
  Qed.

  Lemma iter_op_double : forall p P,
    Pos.iter_op unifiedAdd (p + p) P = Pos.iter_op unifiedAdd p (P + P)%E.
  Proof.
    intros.
    rewrite Pos.add_diag.
    unfold Pos.iter_op; simpl.
    auto.
  Qed.

  Lemma doubleAndAdd_spec : forall n b P, (Pos.size_nat (Pos.of_nat n) <= b) ->
    scalarMult n P = doubleAndAdd b n P.
  Proof.
    induction n; auto; intros.
    unfold doubleAndAdd; simpl.
    rewrite Pos.of_nat_succ.
    rewrite iter_op_spec by (auto using zeroIsIdentity).
    case_eq (Pos.of_nat (S n)); intros. {
      simpl; f_equal.
      rewrite (IHn b) by (pose proof (size_of_succ n); omega).
      unfold doubleAndAdd.
      rewrite H0 in H.
      rewrite <- Pos.of_nat_succ in H0.
      rewrite <- (xI_is_succ n p) by apply H0.
      rewrite Znat.positive_nat_N; simpl.
      rewrite iter_op_spec; auto using zeroIsIdentity.
    } {
      simpl; f_equal.
      rewrite (IHn b) by (pose proof (size_of_succ n); omega).
      unfold doubleAndAdd.
      rewrite <- (xO_is_succ n p) by (rewrite Pos.of_nat_succ; auto).
      rewrite Znat.positive_nat_N; simpl.
      rewrite <- Pos.succ_pred_double in H0.
      rewrite H0 in H.
      rewrite iter_op_spec by (auto using zeroIsIdentity;
        pose proof (Pos.lt_succ_diag_r (Pos.pred_double p));
        apply Pos.size_nat_monotone in H1; omega; auto).
      rewrite <- iter_op_double.
      rewrite Pos.add_diag.
      rewrite <- Pos.succ_pred_double.
      rewrite Pos.iter_op_succ by apply twistedAddAssoc; auto.
    } {
      rewrite <- Pnat.Pos2Nat.inj_iff in H0.
      rewrite Pnat.Nat2Pos.id in H0 by auto.
      rewrite Pnat.Pos2Nat.inj_1 in H0.
      assert (n = 0)%nat by omega; subst.
      auto using zeroIsIdentity.
    }
  Qed.
End EdwardsDoubleAndAdd.