Coverage Report

Created: 2025-04-24 07:09

/src/mcl/include/mcl/ec.hpp
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
/**
3
  @file
4
  @brief elliptic curve
5
  @author MITSUNARI Shigeo(@herumi)
6
  @license modified new BSD license
7
  http://opensource.org/licenses/BSD-3-Clause
8
*/
9
#include <stdlib.h>
10
#include <mcl/fp.hpp>
11
#include <mcl/ecparam.hpp>
12
#include <mcl/window_method.hpp>
13
14
#ifdef _MSC_VER
15
  #pragma warning(push)
16
  #pragma warning(disable : 4458)
17
#endif
18
#ifdef MCL_USE_OMP
19
#include <omp.h>
20
#endif
21
22
namespace mcl {
23
24
template<class _Fp> class Fp2T;
25
26
namespace ec {
27
28
enum Mode {
29
  Jacobi = 0,
30
  Proj = 1,
31
  Affine
32
};
33
34
namespace local {
35
36
enum ModeCoeffA {
37
  Zero,
38
  Minus3,
39
  GenericA
40
};
41
42
enum ModeCoeffB {
43
  Plus1,
44
  Plus4,
45
  GenericB
46
};
47
48
template<class Ec, class Vec>
49
void addTbl(Ec& Q, const Ec *tbl, const Vec& naf, size_t i)
50
1.23M
{
51
1.23M
  if (i >= naf.size()) return;
52
1.07M
  int n = naf[i];
53
1.07M
  if (n > 0) {
54
90.4k
    Q += tbl[(n - 1) >> 1];
55
988k
  } else if (n < 0) {
56
69.6k
    Q -= tbl[(-n - 1) >> 1];
57
69.6k
  }
58
1.07M
}
void mcl::ec::local::addTbl<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FixedArray<signed char, 130ul> >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::FixedArray<signed char, 130ul> const&, unsigned long)
Line
Count
Source
50
440k
{
51
440k
  if (i >= naf.size()) return;
52
351k
  int n = naf[i];
53
351k
  if (n > 0) {
54
30.5k
    Q += tbl[(n - 1) >> 1];
55
320k
  } else if (n < 0) {
56
25.1k
    Q -= tbl[(-n - 1) >> 1];
57
25.1k
  }
58
351k
}
void mcl::ec::local::addTbl<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FixedArray<signed char, 385ul> >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::FixedArray<signed char, 385ul> const&, unsigned long)
Line
Count
Source
50
525k
{
51
525k
  if (i >= naf.size()) return;
52
525k
  int n = naf[i];
53
525k
  if (n > 0) {
54
53.0k
    Q += tbl[(n - 1) >> 1];
55
472k
  } else if (n < 0) {
56
32.1k
    Q -= tbl[(-n - 1) >> 1];
57
32.1k
  }
58
525k
}
void mcl::ec::local::addTbl<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FixedArray<signed char, 68ul> >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::FixedArray<signed char, 68ul> const&, unsigned long)
Line
Count
Source
50
129k
{
51
129k
  if (i >= naf.size()) return;
52
58.1k
  int n = naf[i];
53
58.1k
  if (n > 0) {
54
4.58k
    Q += tbl[(n - 1) >> 1];
55
53.5k
  } else if (n < 0) {
56
4.69k
    Q -= tbl[(-n - 1) >> 1];
57
4.69k
  }
58
58.1k
}
void mcl::ec::local::addTbl<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FixedArray<signed char, 769ul> >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::FixedArray<signed char, 769ul> const&, unsigned long)
Line
Count
Source
50
144k
{
51
144k
  if (i >= naf.size()) return;
52
144k
  int n = naf[i];
53
144k
  if (n > 0) {
54
2.33k
    Q += tbl[(n - 1) >> 1];
55
142k
  } else if (n < 0) {
56
7.68k
    Q -= tbl[(-n - 1) >> 1];
57
7.68k
  }
58
144k
}
Unexecuted instantiation: void mcl::ec::local::addTbl<mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >, mcl::FixedArray<signed char, 68ul> >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const*, mcl::FixedArray<signed char, 68ul> const&, unsigned long)
59
60
/*
61
  elliptic class E must have
62
  member variables of type Fp x, y, z
63
  static member a_, b_, specialA_
64
*/
65
// x is negative <=> x < half(:=(p+1)/2) <=> a = 1
66
template<class F>
67
bool get_a_flag(const F& x)
68
0
{
69
0
  return x.isNegative();
70
0
}
71
72
// Im(x) is negative <=> Im(x) < half(:=(p+1)/2) <=> a = 1
73
74
template<class F>
75
bool get_a_flag(const mcl::Fp2T<F>& x)
76
0
{
77
0
  return get_a_flag(x.b); // x = a + bi
78
0
}
79
80
template<class F>
81
void mul3(F& x)
82
{
83
  F t;
84
  F::add(t, x, x);
85
  F::add(x, t, x); // 3x
86
}
87
88
template<class F>
89
void mul4(F& x)
90
213
{
91
213
  F::add(x, x, x);
92
213
  F::add(x, x, x);
93
213
}
void mcl::ec::local::mul4<mcl::FpT<mcl::bn::local::FpTag, 384ul> >(mcl::FpT<mcl::bn::local::FpTag, 384ul>&)
Line
Count
Source
90
213
{
91
213
  F::add(x, x, x);
92
213
  F::add(x, x, x);
93
213
}
Unexecuted instantiation: void mcl::ec::local::mul4<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >(mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&)
94
95
template<class F>
96
void mul12(F& x)
97
{
98
  F t;
99
  F::add(t, x, x);
100
  F::add(x, t, x); // 3x
101
  mul4(x);
102
}
103
104
/*
105
  Q = x P
106
  splitN = 2(G1) or 4(G2)
107
  w : window size
108
*/
109
template<class GLV, class G>
110
void mulGLV_CT(G& Q, const G& P, const void *yVec)
111
0
{
112
0
  const size_t w = 4;
113
0
  typedef typename GLV::Fr F;
114
0
  fp::getMpzAtType getMpzAt = fp::getMpzAtT<F>;
115
0
  const int splitN = GLV::splitN;
116
0
  const size_t tblSize = 1 << w;
117
0
  G tbl[splitN][tblSize];
118
0
  bool negTbl[splitN];
119
0
  mpz_class u[splitN], y;
120
0
  getMpzAt(y, yVec, 0);
121
0
  GLV::split(u, y);
122
0
  for (int i = 0; i < splitN; i++) {
123
0
    if (u[i] < 0) {
124
0
      gmp::neg(u[i], u[i]);
125
0
      negTbl[i] = true;
126
0
    } else {
127
0
      negTbl[i] = false;
128
0
    }
129
0
    tbl[i][0].clear();
130
0
  }
131
0
  tbl[0][1] = P;
132
0
  for (size_t j = 2; j < tblSize; j++) {
133
0
    G::add(tbl[0][j], tbl[0][j - 1], P);
134
0
  }
135
0
  for (int i = 1; i < splitN; i++) {
136
0
    for (size_t j = 1; j < tblSize; j++) {
137
0
      GLV::mulLambda(tbl[i][j], tbl[i - 1][j]);
138
0
    }
139
0
  }
140
0
  for (int i = 0; i < splitN; i++) {
141
0
    if (negTbl[i]) {
142
0
      for (size_t j = 0; j < tblSize; j++) {
143
0
        G::neg(tbl[i][j], tbl[i][j]);
144
0
      }
145
0
    }
146
0
  }
147
0
  mcl::FixedArray<uint8_t, sizeof(F) * 8 / w + 1> vTbl[splitN];
148
0
  size_t loopN = 0;
149
0
  {
150
0
    size_t maxBitSize = 0;
151
0
    fp::BitIterator<Unit> itr[splitN];
152
0
    for (int i = 0; i < splitN; i++) {
153
0
      itr[i].init(gmp::getUnit(u[i]), gmp::getUnitSize(u[i]));
154
0
      size_t bitSize = itr[i].getBitSize();
155
0
      if (bitSize > maxBitSize) maxBitSize = bitSize;
156
0
    }
157
0
    loopN = (maxBitSize + w - 1) / w;
158
0
    for (int i = 0; i < splitN; i++) {
159
0
      bool b = vTbl[i].resize(loopN);
160
0
      assert(b);
161
0
      (void)b;
162
0
      for (size_t j = 0; j < loopN; j++) {
163
0
        vTbl[i][loopN - 1 - j] = (uint8_t)itr[i].getNext(w);
164
0
      }
165
0
    }
166
0
  }
167
0
  Q.clear();
168
0
  for (size_t k = 0; k < loopN; k++) {
169
0
    for (size_t i = 0; i < w; i++) {
170
0
      G::dbl(Q, Q);
171
0
    }
172
0
    for (size_t i = 0; i < splitN; i++) {
173
0
      uint8_t v = vTbl[i][k];
174
0
      G::add(Q, Q, tbl[i][v]);
175
0
    }
176
0
  }
177
0
}
Unexecuted instantiation: void mcl::ec::local::mulGLV_CT<mcl::bn::local::GLV1, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, void const*)
Unexecuted instantiation: void mcl::ec::local::mulGLV_CT<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, void const*)
Unexecuted instantiation: void mcl::ec::local::mulGLV_CT<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const&, void const*)
Unexecuted instantiation: void mcl::ec::local::mulGLV_CT<mcl::GLV1T<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, void const*)
178
179
// AsArrayOfFp[i] gets P[i].z
180
template<class E>
181
struct AsArrayOfFp {
182
  typedef typename E::Fp Fp;
183
  const E* P;
184
3.98k
  AsArrayOfFp(const E* P) : P(P) {}
mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::AsArrayOfFp(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*)
Line
Count
Source
184
778
  AsArrayOfFp(const E* P) : P(P) {}
mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::AsArrayOfFp(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*)
Line
Count
Source
184
3.21k
  AsArrayOfFp(const E* P) : P(P) {}
185
187k
  const Fp& operator[](size_t i) const { return P[i].z; }
mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::operator[](unsigned long) const
Line
Count
Source
185
36.7k
  const Fp& operator[](size_t i) const { return P[i].z; }
mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::operator[](unsigned long) const
Line
Count
Source
185
150k
  const Fp& operator[](size_t i) const { return P[i].z; }
186
0
  void operator+=(size_t n) { P += n; }
Unexecuted instantiation: mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::operator+=(unsigned long)
Unexecuted instantiation: mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >::operator+=(unsigned long)
187
};
188
189
template<class E>
190
void _normalizeJacobi(E& Q, const E& P, typename E::Fp& inv)
191
33.5k
{
192
33.5k
  typedef typename E::Fp F;
193
33.5k
  F inv2;
194
33.5k
  F::sqr(inv2, inv);
195
33.5k
  F::mul(Q.x, P.x, inv2);
196
33.5k
  F::mul(Q.y, P.y, inv2);
197
33.5k
  Q.y *= inv;
198
33.5k
  Q.z = 1;
199
33.5k
}
void mcl::ec::local::_normalizeJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
Line
Count
Source
191
6.98k
{
192
6.98k
  typedef typename E::Fp F;
193
6.98k
  F inv2;
194
6.98k
  F::sqr(inv2, inv);
195
6.98k
  F::mul(Q.x, P.x, inv2);
196
6.98k
  F::mul(Q.y, P.y, inv2);
197
6.98k
  Q.y *= inv;
198
6.98k
  Q.z = 1;
199
6.98k
}
void mcl::ec::local::_normalizeJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
Line
Count
Source
191
26.2k
{
192
26.2k
  typedef typename E::Fp F;
193
26.2k
  F inv2;
194
26.2k
  F::sqr(inv2, inv);
195
26.2k
  F::mul(Q.x, P.x, inv2);
196
26.2k
  F::mul(Q.y, P.y, inv2);
197
26.2k
  Q.y *= inv;
198
26.2k
  Q.z = 1;
199
26.2k
}
void mcl::ec::local::_normalizeJacobi<mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >(mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&, mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> >::Fp&)
Line
Count
Source
191
323
{
192
323
  typedef typename E::Fp F;
193
323
  F inv2;
194
323
  F::sqr(inv2, inv);
195
323
  F::mul(Q.x, P.x, inv2);
196
323
  F::mul(Q.y, P.y, inv2);
197
323
  Q.y *= inv;
198
323
  Q.z = 1;
199
323
}
200
201
template<class E>
202
void _normalizeProj(E& Q, const E& P, typename E::Fp& inv)
203
0
{
204
0
  typedef typename E::Fp F;
205
0
  F::mul(Q.x, P.x, inv);
206
0
  F::mul(Q.y, P.y, inv);
207
0
  Q.z = 1;
208
0
}
Unexecuted instantiation: void mcl::ec::local::_normalizeProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
Unexecuted instantiation: void mcl::ec::local::_normalizeProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
209
210
template<class E>
211
void _normalize(E& Q, const E& P, typename E::Fp& inv)
212
28.1k
{
213
28.1k
  switch (E::mode_) {
214
28.1k
  case ec::Jacobi:
215
28.1k
    _normalizeJacobi(Q, P, inv);
216
28.1k
    break;
217
0
  case ec::Proj:
218
0
    _normalizeProj(Q, P, inv);
219
0
    break;
220
0
  default:
221
0
    assert(0);
222
0
    break;
223
28.1k
  }
224
28.1k
}
void mcl::ec::local::_normalize<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
Line
Count
Source
212
5.67k
{
213
5.67k
  switch (E::mode_) {
214
5.67k
  case ec::Jacobi:
215
5.67k
    _normalizeJacobi(Q, P, inv);
216
5.67k
    break;
217
0
  case ec::Proj:
218
0
    _normalizeProj(Q, P, inv);
219
0
    break;
220
0
  default:
221
0
    assert(0);
222
0
    break;
223
5.67k
  }
224
5.67k
}
void mcl::ec::local::_normalize<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp&)
Line
Count
Source
212
22.4k
{
213
22.4k
  switch (E::mode_) {
214
22.4k
  case ec::Jacobi:
215
22.4k
    _normalizeJacobi(Q, P, inv);
216
22.4k
    break;
217
0
  case ec::Proj:
218
0
    _normalizeProj(Q, P, inv);
219
0
    break;
220
0
  default:
221
0
    assert(0);
222
0
    break;
223
22.4k
  }
224
22.4k
}
225
226
/*
227
  Q[i] = normalize(P[i]) for i = 0, ..., n-1
228
  AsArray : Pz[i] to access like as F[i] in invVecT
229
  N : alloc size
230
*/
231
template<class F, class Eout, class Ein, class AsArrayOfFp>
232
void normalizeVecT(Eout& Q, Ein& P, size_t n, size_t N = 256)
233
3.98k
{
234
3.98k
  F *inv = (F*)CYBOZU_ALLOCA(sizeof(F) * N);
235
3.98k
  bool PisEqualToQ = &P[0] == &Q[0];
236
3.98k
  for (;;) {
237
3.98k
    size_t doneN = (n < N) ? n : N;
238
3.98k
    AsArrayOfFp Pz(P);
239
3.98k
    invVecT<F>(inv, Pz, doneN, N);
240
35.9k
    for (size_t i = 0; i < doneN; i++) {
241
31.9k
      if (P[i].z.isZero() || P[i].z.isOne()) {
242
3.75k
        if (!PisEqualToQ) Q[i] = P[i];
243
28.1k
      } else {
244
28.1k
        local::_normalize(Q[i], P[i], inv[i]);
245
28.1k
      }
246
31.9k
    }
247
3.98k
    n -= doneN;
248
3.98k
    if (n == 0) return;
249
0
    Q += doneN;
250
0
    P += doneN;
251
0
  }
252
3.98k
}
void mcl::ec::local::normalizeVecT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*&, unsigned long, unsigned long)
Line
Count
Source
233
778
{
234
778
  F *inv = (F*)CYBOZU_ALLOCA(sizeof(F) * N);
235
778
  bool PisEqualToQ = &P[0] == &Q[0];
236
778
  for (;;) {
237
778
    size_t doneN = (n < N) ? n : N;
238
778
    AsArrayOfFp Pz(P);
239
778
    invVecT<F>(inv, Pz, doneN, N);
240
7.00k
    for (size_t i = 0; i < doneN; i++) {
241
6.22k
      if (P[i].z.isZero() || P[i].z.isOne()) {
242
548
        if (!PisEqualToQ) Q[i] = P[i];
243
5.67k
      } else {
244
5.67k
        local::_normalize(Q[i], P[i], inv[i]);
245
5.67k
      }
246
6.22k
    }
247
778
    n -= doneN;
248
778
    if (n == 0) return;
249
0
    Q += doneN;
250
0
    P += doneN;
251
0
  }
252
778
}
void mcl::ec::local::normalizeVecT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, mcl::ec::local::AsArrayOfFp<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*&, unsigned long, unsigned long)
Line
Count
Source
233
3.21k
{
234
3.21k
  F *inv = (F*)CYBOZU_ALLOCA(sizeof(F) * N);
235
3.21k
  bool PisEqualToQ = &P[0] == &Q[0];
236
3.21k
  for (;;) {
237
3.21k
    size_t doneN = (n < N) ? n : N;
238
3.21k
    AsArrayOfFp Pz(P);
239
3.21k
    invVecT<F>(inv, Pz, doneN, N);
240
28.8k
    for (size_t i = 0; i < doneN; i++) {
241
25.6k
      if (P[i].z.isZero() || P[i].z.isOne()) {
242
3.21k
        if (!PisEqualToQ) Q[i] = P[i];
243
22.4k
      } else {
244
22.4k
        local::_normalize(Q[i], P[i], inv[i]);
245
22.4k
      }
246
25.6k
    }
247
3.21k
    n -= doneN;
248
3.21k
    if (n == 0) return;
249
0
    Q += doneN;
250
0
    P += doneN;
251
0
  }
252
3.21k
}
253
254
/*
255
  split x in [0, r-1] to (a, b) such that x = a + b L, 0 <= a < L, 0 <= b <= L+1
256
  a[] : 128 bit
257
  b[] : 128 bit
258
  x[] : 256 bit
259
*/
260
inline void optimizedSplitRawForBLS12_381(Unit *a, Unit *b, const Unit *x)
261
3.21k
{
262
  /*
263
    z = -0xd201000000010000
264
    L = z^2-1 = 0xac45a4010001a40200000000ffffffff
265
    s=255
266
    q = (1<<s)//L = 0xbe35f678f00fd56eb1fb72917b67f718
267
    H = 1<<128
268
  */
269
3.21k
  static const Unit L[] = { MCL_U64_TO_UNIT(0x00000000ffffffff), MCL_U64_TO_UNIT(0xac45a4010001a402) };
270
3.21k
  static const Unit q[] = { MCL_U64_TO_UNIT(0xb1fb72917b67f718), MCL_U64_TO_UNIT(0xbe35f678f00fd56e) };
271
3.21k
  static const Unit one[] = { MCL_U64_TO_UNIT(1), MCL_U64_TO_UNIT(0) };
272
3.21k
  static const size_t n = 128 / mcl::UnitBitSize;
273
3.21k
  Unit xH[n+1]; // x = xH * (H/2) + xL
274
3.21k
  mcl::bint::shrT<n+1>(xH, x+n-1, mcl::UnitBitSize-1); // >>127
275
3.21k
  Unit t[n*2];
276
3.21k
  mcl::bint::mulT<n>(t, xH, q);
277
3.21k
  mcl::bint::copyT<n>(b, t+n); // (xH * q)/H
278
3.21k
  mcl::bint::mulT<n>(t, b, L); // bL
279
3.21k
  mcl::bint::subT<n*2>(t, x, t); // x - bL
280
3.21k
  Unit d = mcl::bint::subT<n>(a, t, L);
281
3.21k
  if (t[n] - d == 0) {
282
428
    mcl::bint::addT<n>(b, b, one);
283
2.78k
  } else {
284
2.78k
    mcl::bint::copyT<n>(a, t);
285
2.78k
  }
286
3.21k
}
287
288
inline void optimizedSplitRawForBLS12_377(Unit *a, Unit *b, const Unit *x)
289
0
{
290
  /*
291
    z = -0xd201000000010000
292
    L = z^2-1 = 0x452217cc900000010a11800000000000
293
    s=254
294
    q = (1<<s)//L = 0xecfdeaa5a7f4dc581fdcbb4cabe4060b
295
    H = 1<<128
296
  */
297
0
  static const Unit L[] = { MCL_U64_TO_UNIT(0x0a11800000000000), MCL_U64_TO_UNIT(0x452217cc90000001) };
298
0
  static const Unit q[] = { MCL_U64_TO_UNIT(0x1fdcbb4cabe4060b), MCL_U64_TO_UNIT(0xecfdeaa5a7f4dc58) };
299
0
  static const Unit one[] = { MCL_U64_TO_UNIT(1), MCL_U64_TO_UNIT(0) };
300
0
  static const size_t n = 128 / mcl::UnitBitSize;
301
0
  Unit xH[n+1]; // x = xH * (H/4) + xL
302
0
  mcl::bint::shrT<n+1>(xH, x+n-1, mcl::UnitBitSize-2); // >>126
303
0
  Unit t[n*2];
304
0
  mcl::bint::mulT<n>(t, xH, q);
305
0
  mcl::bint::copyT<n>(b, t+n); // (xH * q)/H
306
0
  mcl::bint::mulT<n>(t, b, L); // bL
307
0
  mcl::bint::subT<n*2>(t, x, t); // x - bL
308
0
  Unit d = mcl::bint::subT<n>(a, t, L);
309
0
  if (d == 0) {
310
0
    mcl::bint::addT<n>(b, b, one);
311
0
  } else {
312
0
    mcl::bint::copyT<n>(a, t);
313
0
  }
314
0
}
315
316
} // mcl::ec::local
317
318
// [X:Y:Z] as Proj = (X/Z, Y/Z) as Affine = [XZ:YZ^2:Z] as Jacobi
319
// Remark. convert P = [*:*:0] to Q = [0:0:0]
320
template<class E>
321
void ProjToJacobi(E& Q, const E& P)
322
{
323
  typedef typename E::Fp F;
324
  F::mul(Q.x, P.x, P.z);
325
  F::mul(Q.y, P.y, P.z);
326
  F::mul(Q.y, Q.y, P.z);
327
  Q.z = P.z;
328
}
329
330
// [X:Y:Z] as Jacobi = (X/Z^2, Y/Z^3) as Affine = [XZ:Y:Z^3] as Proj
331
// Remark. convert P = [*:1:0] to Q = [0:1:0]
332
template<class E>
333
void JacobiToProj(E& Q, const E& P)
334
{
335
  typedef typename E::Fp F;
336
  F::mul(Q.x, P.x, P.z);
337
  Q.y = P.y;
338
  F t;
339
  F::sqr(t, P.z);
340
  F::mul(Q.z, P.z, t);
341
}
342
343
template<class E>
344
void normalizeJacobi(E& P)
345
10.6k
{
346
10.6k
  if (P.z.isZero() || P.z.isOne()) return;
347
5.35k
  typedef typename E::Fp F;
348
5.35k
  F::inv(P.z, P.z);
349
5.35k
  local::_normalizeJacobi(P, P, P.z);
350
5.35k
}
void mcl::ec::normalizeJacobi<mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >(mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&)
Line
Count
Source
345
329
{
346
329
  if (P.z.isZero() || P.z.isOne()) return;
347
323
  typedef typename E::Fp F;
348
323
  F::inv(P.z, P.z);
349
323
  local::_normalizeJacobi(P, P, P.z);
350
323
}
void mcl::ec::normalizeJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&)
Line
Count
Source
345
2.72k
{
346
2.72k
  if (P.z.isZero() || P.z.isOne()) return;
347
1.30k
  typedef typename E::Fp F;
348
1.30k
  F::inv(P.z, P.z);
349
1.30k
  local::_normalizeJacobi(P, P, P.z);
350
1.30k
}
void mcl::ec::normalizeJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&)
Line
Count
Source
345
7.57k
{
346
7.57k
  if (P.z.isZero() || P.z.isOne()) return;
347
3.72k
  typedef typename E::Fp F;
348
3.72k
  F::inv(P.z, P.z);
349
3.72k
  local::_normalizeJacobi(P, P, P.z);
350
3.72k
}
351
352
/*
353
  Q[i] = normalize(P[i]) for i = 0, ..., n-1
354
  AsArray : Pz[i] to access like as F[i] in invVecT
355
  N : alloc size
356
*/
357
template<class E>
358
void normalizeVec(E *Q, const E *P, size_t n)
359
3.98k
{
360
3.98k
  local::normalizeVecT<typename E::Fp, E*, const E*, local::AsArrayOfFp<E> >(Q, P, n);
361
3.98k
}
void mcl::ec::normalizeVec<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long)
Line
Count
Source
359
778
{
360
778
  local::normalizeVecT<typename E::Fp, E*, const E*, local::AsArrayOfFp<E> >(Q, P, n);
361
778
}
void mcl::ec::normalizeVec<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long)
Line
Count
Source
359
3.21k
{
360
3.21k
  local::normalizeVecT<typename E::Fp, E*, const E*, local::AsArrayOfFp<E> >(Q, P, n);
361
3.21k
}
362
363
// (x/z^2, y/z^3)
364
template<class E>
365
bool isEqualJacobi(const E& P1, const E& P2)
366
4.93k
{
367
4.93k
  typedef typename E::Fp F;
368
4.93k
  bool zero1 = P1.isZero();
369
4.93k
  bool zero2 = P2.isZero();
370
4.93k
  if (zero1) {
371
133
    return zero2;
372
133
  }
373
4.80k
  if (zero2) return false;
374
4.80k
  F s1, s2, t1, t2;
375
4.80k
  F::sqr(s1, P1.z);
376
4.80k
  F::sqr(s2, P2.z);
377
4.80k
  F::mul(t1, P1.x, s2);
378
4.80k
  F::mul(t2, P2.x, s1);
379
4.80k
  if (t1 != t2) return false;
380
4.71k
  F::mul(t1, P1.y, s2);
381
4.71k
  F::mul(t2, P2.y, s1);
382
4.71k
  t1 *= P2.z;
383
4.71k
  t2 *= P1.z;
384
4.71k
  return t1 == t2;
385
4.80k
}
bool mcl::ec::isEqualJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
366
957
{
367
957
  typedef typename E::Fp F;
368
957
  bool zero1 = P1.isZero();
369
957
  bool zero2 = P2.isZero();
370
957
  if (zero1) {
371
6
    return zero2;
372
6
  }
373
951
  if (zero2) return false;
374
951
  F s1, s2, t1, t2;
375
951
  F::sqr(s1, P1.z);
376
951
  F::sqr(s2, P2.z);
377
951
  F::mul(t1, P1.x, s2);
378
951
  F::mul(t2, P2.x, s1);
379
951
  if (t1 != t2) return false;
380
914
  F::mul(t1, P1.y, s2);
381
914
  F::mul(t2, P2.y, s1);
382
914
  t1 *= P2.z;
383
914
  t2 *= P1.z;
384
914
  return t1 == t2;
385
951
}
bool mcl::ec::isEqualJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
366
3.98k
{
367
3.98k
  typedef typename E::Fp F;
368
3.98k
  bool zero1 = P1.isZero();
369
3.98k
  bool zero2 = P2.isZero();
370
3.98k
  if (zero1) {
371
127
    return zero2;
372
127
  }
373
3.85k
  if (zero2) return false;
374
3.85k
  F s1, s2, t1, t2;
375
3.85k
  F::sqr(s1, P1.z);
376
3.85k
  F::sqr(s2, P2.z);
377
3.85k
  F::mul(t1, P1.x, s2);
378
3.85k
  F::mul(t2, P2.x, s1);
379
3.85k
  if (t1 != t2) return false;
380
3.80k
  F::mul(t1, P1.y, s2);
381
3.80k
  F::mul(t2, P2.y, s1);
382
3.80k
  t1 *= P2.z;
383
3.80k
  t2 *= P1.z;
384
3.80k
  return t1 == t2;
385
3.85k
}
386
387
// return (P1 == P2) ? 1 : (P1 == -P2) ? -1 : 0
388
template<class E>
389
int isEqualOrMinusJacobi(const E& P1, const E& P2)
390
{
391
  typedef typename E::Fp F;
392
  bool zero1 = P1.isZero();
393
  bool zero2 = P2.isZero();
394
  if (zero1) {
395
    return zero2 ? 1 : 0;
396
  }
397
  if (zero2) return 0;
398
  F s1, s2, t1, t2;
399
  F::sqr(s1, P1.z);
400
  F::sqr(s2, P2.z);
401
  F::mul(t1, P1.x, s2);
402
  F::mul(t2, P2.x, s1);
403
  if (t1 != t2) return 0;
404
  F::mul(t1, P1.y, s2);
405
  F::mul(t2, P2.y, s1);
406
  t1 *= P2.z;
407
  t2 *= P1.z;
408
  if (t1 == t2) return 1;
409
  F::neg(t1, t1);
410
  if (t1 == t2) return -1;
411
  return 0;
412
}
413
414
// Y^2 == X(X^2 + aZ^4) + bZ^6
415
template<class E>
416
bool isValidJacobi(const E& P)
417
378
{
418
378
  typedef typename E::Fp F;
419
378
  F y2, x2, z2, z4, t;
420
378
  F::sqr(x2, P.x);
421
378
  F::sqr(y2, P.y);
422
378
  F::sqr(z2, P.z);
423
378
  F::sqr(z4, z2);
424
378
  F::mul(t, z4, E::a_);
425
378
  t += x2;
426
378
  t *= P.x;
427
378
  z4 *= z2;
428
378
  if (E::specialB_ == ec::local::Plus1) {
429
    // pass
430
0
  } else
431
378
  if (E::specialB_ == ec::local::Plus4) {
432
213
    local::mul4(z4);
433
213
  } else
434
165
  {
435
165
    z4 *= E::b_;
436
165
  }
437
378
  t += z4;
438
378
  return y2 == t;
439
378
}
bool mcl::ec::isValidJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
417
213
{
418
213
  typedef typename E::Fp F;
419
213
  F y2, x2, z2, z4, t;
420
213
  F::sqr(x2, P.x);
421
213
  F::sqr(y2, P.y);
422
213
  F::sqr(z2, P.z);
423
213
  F::sqr(z4, z2);
424
213
  F::mul(t, z4, E::a_);
425
213
  t += x2;
426
213
  t *= P.x;
427
213
  z4 *= z2;
428
213
  if (E::specialB_ == ec::local::Plus1) {
429
    // pass
430
0
  } else
431
213
  if (E::specialB_ == ec::local::Plus4) {
432
213
    local::mul4(z4);
433
213
  } else
434
0
  {
435
0
    z4 *= E::b_;
436
0
  }
437
213
  t += z4;
438
213
  return y2 == t;
439
213
}
bool mcl::ec::isValidJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
417
165
{
418
165
  typedef typename E::Fp F;
419
165
  F y2, x2, z2, z4, t;
420
165
  F::sqr(x2, P.x);
421
165
  F::sqr(y2, P.y);
422
165
  F::sqr(z2, P.z);
423
165
  F::sqr(z4, z2);
424
165
  F::mul(t, z4, E::a_);
425
165
  t += x2;
426
165
  t *= P.x;
427
165
  z4 *= z2;
428
165
  if (E::specialB_ == ec::local::Plus1) {
429
    // pass
430
0
  } else
431
165
  if (E::specialB_ == ec::local::Plus4) {
432
0
    local::mul4(z4);
433
0
  } else
434
165
  {
435
165
    z4 *= E::b_;
436
165
  }
437
165
  t += z4;
438
165
  return y2 == t;
439
165
}
440
441
/*
442
  M > S + A
443
  a = 0   2M + 5S + 14A
444
  a = -3  2M + 7S + 15A
445
  generic 3M + 7S + 15A
446
  M == S
447
  a = 0   3M + 4S + 13A
448
  a = -3  3M + 6S + 14A
449
  generic 4M + 6S + 14A
450
*/
451
template<class E>
452
void dblJacobi(E& R, const E& P)
453
938k
{
454
938k
  typedef typename E::Fp F;
455
938k
  if (P.isZero()) {
456
28.2k
    R.clear();
457
28.2k
    return;
458
28.2k
  }
459
910k
  const bool isPzOne = P.z.isOne();
460
910k
  F x2, y2, xy, t;
461
910k
  F::sqr(x2, P.x);
462
910k
  F::sqr(y2, P.y);
463
910k
  if (sizeof(F) <= 32) { // M == S
464
0
    F::mul(xy, P.x, y2);
465
0
    xy += xy;
466
0
    F::sqr(y2, y2);
467
910k
  } else { // M > S + A
468
910k
    F::add(xy, P.x, y2);
469
910k
    F::sqr(y2, y2);
470
910k
    F::sqr(xy, xy);
471
910k
    xy -= x2;
472
910k
    xy -= y2;
473
910k
  }
474
910k
  xy += xy; // 4xy^2
475
910k
  switch (E::specialA_) {
476
910k
  case local::Zero:
477
910k
    F::mul2(t, x2);
478
910k
    x2 += t;
479
910k
    break;
480
0
  case local::Minus3:
481
0
    if (isPzOne) {
482
0
      x2 -= P.z;
483
0
    } else {
484
0
      F::sqr(t, P.z);
485
0
      F::sqr(t, t);
486
0
      x2 -= t;
487
0
    }
488
0
    F::mul2(t, x2);
489
0
    x2 += t;
490
0
    break;
491
71
  case local::GenericA:
492
71
  default:
493
71
    if (isPzOne) {
494
0
      t = E::a_;
495
71
    } else {
496
71
      F::sqr(t, P.z);
497
71
      F::sqr(t, t);
498
71
      t *= E::a_;
499
71
    }
500
71
    t += x2;
501
71
    F::mul2(x2, x2);
502
71
    x2 += t;
503
71
    break;
504
910k
  }
505
910k
  F::sqr(R.x, x2);
506
910k
  R.x -= xy;
507
910k
  R.x -= xy;
508
910k
  if (isPzOne) {
509
12.2k
    R.z = P.y;
510
898k
  } else {
511
898k
    F::mul(R.z, P.y, P.z);
512
898k
  }
513
910k
  F::mul2(R.z, R.z);
514
910k
  F::sub(R.y, xy, R.x);
515
910k
  R.y *= x2;
516
910k
  F::mul2(y2, y2);
517
910k
  F::mul2(y2, y2);
518
910k
  F::mul2(y2, y2);
519
910k
  R.y -= y2;
520
910k
}
void mcl::ec::dblJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
453
181k
{
454
181k
  typedef typename E::Fp F;
455
181k
  if (P.isZero()) {
456
4.23k
    R.clear();
457
4.23k
    return;
458
4.23k
  }
459
177k
  const bool isPzOne = P.z.isOne();
460
177k
  F x2, y2, xy, t;
461
177k
  F::sqr(x2, P.x);
462
177k
  F::sqr(y2, P.y);
463
177k
  if (sizeof(F) <= 32) { // M == S
464
0
    F::mul(xy, P.x, y2);
465
0
    xy += xy;
466
0
    F::sqr(y2, y2);
467
177k
  } else { // M > S + A
468
177k
    F::add(xy, P.x, y2);
469
177k
    F::sqr(y2, y2);
470
177k
    F::sqr(xy, xy);
471
177k
    xy -= x2;
472
177k
    xy -= y2;
473
177k
  }
474
177k
  xy += xy; // 4xy^2
475
177k
  switch (E::specialA_) {
476
177k
  case local::Zero:
477
177k
    F::mul2(t, x2);
478
177k
    x2 += t;
479
177k
    break;
480
0
  case local::Minus3:
481
0
    if (isPzOne) {
482
0
      x2 -= P.z;
483
0
    } else {
484
0
      F::sqr(t, P.z);
485
0
      F::sqr(t, t);
486
0
      x2 -= t;
487
0
    }
488
0
    F::mul2(t, x2);
489
0
    x2 += t;
490
0
    break;
491
0
  case local::GenericA:
492
0
  default:
493
0
    if (isPzOne) {
494
0
      t = E::a_;
495
0
    } else {
496
0
      F::sqr(t, P.z);
497
0
      F::sqr(t, t);
498
0
      t *= E::a_;
499
0
    }
500
0
    t += x2;
501
0
    F::mul2(x2, x2);
502
0
    x2 += t;
503
0
    break;
504
177k
  }
505
177k
  F::sqr(R.x, x2);
506
177k
  R.x -= xy;
507
177k
  R.x -= xy;
508
177k
  if (isPzOne) {
509
2.15k
    R.z = P.y;
510
174k
  } else {
511
174k
    F::mul(R.z, P.y, P.z);
512
174k
  }
513
177k
  F::mul2(R.z, R.z);
514
177k
  F::sub(R.y, xy, R.x);
515
177k
  R.y *= x2;
516
177k
  F::mul2(y2, y2);
517
177k
  F::mul2(y2, y2);
518
177k
  F::mul2(y2, y2);
519
177k
  R.y -= y2;
520
177k
}
void mcl::ec::dblJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
453
757k
{
454
757k
  typedef typename E::Fp F;
455
757k
  if (P.isZero()) {
456
23.9k
    R.clear();
457
23.9k
    return;
458
23.9k
  }
459
733k
  const bool isPzOne = P.z.isOne();
460
733k
  F x2, y2, xy, t;
461
733k
  F::sqr(x2, P.x);
462
733k
  F::sqr(y2, P.y);
463
733k
  if (sizeof(F) <= 32) { // M == S
464
0
    F::mul(xy, P.x, y2);
465
0
    xy += xy;
466
0
    F::sqr(y2, y2);
467
733k
  } else { // M > S + A
468
733k
    F::add(xy, P.x, y2);
469
733k
    F::sqr(y2, y2);
470
733k
    F::sqr(xy, xy);
471
733k
    xy -= x2;
472
733k
    xy -= y2;
473
733k
  }
474
733k
  xy += xy; // 4xy^2
475
733k
  switch (E::specialA_) {
476
733k
  case local::Zero:
477
733k
    F::mul2(t, x2);
478
733k
    x2 += t;
479
733k
    break;
480
0
  case local::Minus3:
481
0
    if (isPzOne) {
482
0
      x2 -= P.z;
483
0
    } else {
484
0
      F::sqr(t, P.z);
485
0
      F::sqr(t, t);
486
0
      x2 -= t;
487
0
    }
488
0
    F::mul2(t, x2);
489
0
    x2 += t;
490
0
    break;
491
0
  case local::GenericA:
492
0
  default:
493
0
    if (isPzOne) {
494
0
      t = E::a_;
495
0
    } else {
496
0
      F::sqr(t, P.z);
497
0
      F::sqr(t, t);
498
0
      t *= E::a_;
499
0
    }
500
0
    t += x2;
501
0
    F::mul2(x2, x2);
502
0
    x2 += t;
503
0
    break;
504
733k
  }
505
733k
  F::sqr(R.x, x2);
506
733k
  R.x -= xy;
507
733k
  R.x -= xy;
508
733k
  if (isPzOne) {
509
10.1k
    R.z = P.y;
510
723k
  } else {
511
723k
    F::mul(R.z, P.y, P.z);
512
723k
  }
513
733k
  F::mul2(R.z, R.z);
514
733k
  F::sub(R.y, xy, R.x);
515
733k
  R.y *= x2;
516
733k
  F::mul2(y2, y2);
517
733k
  F::mul2(y2, y2);
518
733k
  F::mul2(y2, y2);
519
733k
  R.y -= y2;
520
733k
}
void mcl::ec::dblJacobi<mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >(mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&, mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&)
Line
Count
Source
453
39
{
454
39
  typedef typename E::Fp F;
455
39
  if (P.isZero()) {
456
0
    R.clear();
457
0
    return;
458
0
  }
459
39
  const bool isPzOne = P.z.isOne();
460
39
  F x2, y2, xy, t;
461
39
  F::sqr(x2, P.x);
462
39
  F::sqr(y2, P.y);
463
39
  if (sizeof(F) <= 32) { // M == S
464
0
    F::mul(xy, P.x, y2);
465
0
    xy += xy;
466
0
    F::sqr(y2, y2);
467
39
  } else { // M > S + A
468
39
    F::add(xy, P.x, y2);
469
39
    F::sqr(y2, y2);
470
39
    F::sqr(xy, xy);
471
39
    xy -= x2;
472
39
    xy -= y2;
473
39
  }
474
39
  xy += xy; // 4xy^2
475
39
  switch (E::specialA_) {
476
0
  case local::Zero:
477
0
    F::mul2(t, x2);
478
0
    x2 += t;
479
0
    break;
480
0
  case local::Minus3:
481
0
    if (isPzOne) {
482
0
      x2 -= P.z;
483
0
    } else {
484
0
      F::sqr(t, P.z);
485
0
      F::sqr(t, t);
486
0
      x2 -= t;
487
0
    }
488
0
    F::mul2(t, x2);
489
0
    x2 += t;
490
0
    break;
491
39
  case local::GenericA:
492
39
  default:
493
39
    if (isPzOne) {
494
0
      t = E::a_;
495
39
    } else {
496
39
      F::sqr(t, P.z);
497
39
      F::sqr(t, t);
498
39
      t *= E::a_;
499
39
    }
500
39
    t += x2;
501
39
    F::mul2(x2, x2);
502
39
    x2 += t;
503
39
    break;
504
39
  }
505
39
  F::sqr(R.x, x2);
506
39
  R.x -= xy;
507
39
  R.x -= xy;
508
39
  if (isPzOne) {
509
0
    R.z = P.y;
510
39
  } else {
511
39
    F::mul(R.z, P.y, P.z);
512
39
  }
513
39
  F::mul2(R.z, R.z);
514
39
  F::sub(R.y, xy, R.x);
515
39
  R.y *= x2;
516
39
  F::mul2(y2, y2);
517
39
  F::mul2(y2, y2);
518
39
  F::mul2(y2, y2);
519
39
  R.y -= y2;
520
39
}
void mcl::ec::dblJacobi<mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > > >(mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >&, mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > > const&)
Line
Count
Source
453
32
{
454
32
  typedef typename E::Fp F;
455
32
  if (P.isZero()) {
456
0
    R.clear();
457
0
    return;
458
0
  }
459
32
  const bool isPzOne = P.z.isOne();
460
32
  F x2, y2, xy, t;
461
32
  F::sqr(x2, P.x);
462
32
  F::sqr(y2, P.y);
463
32
  if (sizeof(F) <= 32) { // M == S
464
0
    F::mul(xy, P.x, y2);
465
0
    xy += xy;
466
0
    F::sqr(y2, y2);
467
32
  } else { // M > S + A
468
32
    F::add(xy, P.x, y2);
469
32
    F::sqr(y2, y2);
470
32
    F::sqr(xy, xy);
471
32
    xy -= x2;
472
32
    xy -= y2;
473
32
  }
474
32
  xy += xy; // 4xy^2
475
32
  switch (E::specialA_) {
476
0
  case local::Zero:
477
0
    F::mul2(t, x2);
478
0
    x2 += t;
479
0
    break;
480
0
  case local::Minus3:
481
0
    if (isPzOne) {
482
0
      x2 -= P.z;
483
0
    } else {
484
0
      F::sqr(t, P.z);
485
0
      F::sqr(t, t);
486
0
      x2 -= t;
487
0
    }
488
0
    F::mul2(t, x2);
489
0
    x2 += t;
490
0
    break;
491
32
  case local::GenericA:
492
32
  default:
493
32
    if (isPzOne) {
494
0
      t = E::a_;
495
32
    } else {
496
32
      F::sqr(t, P.z);
497
32
      F::sqr(t, t);
498
32
      t *= E::a_;
499
32
    }
500
32
    t += x2;
501
32
    F::mul2(x2, x2);
502
32
    x2 += t;
503
32
    break;
504
32
  }
505
32
  F::sqr(R.x, x2);
506
32
  R.x -= xy;
507
32
  R.x -= xy;
508
32
  if (isPzOne) {
509
0
    R.z = P.y;
510
32
  } else {
511
32
    F::mul(R.z, P.y, P.z);
512
32
  }
513
32
  F::mul2(R.z, R.z);
514
32
  F::sub(R.y, xy, R.x);
515
32
  R.y *= x2;
516
32
  F::mul2(y2, y2);
517
32
  F::mul2(y2, y2);
518
32
  F::mul2(y2, y2);
519
32
  R.y -= y2;
520
32
}
521
522
/*
523
  J + J : 12mul + 4sqr + 7add
524
  J + A : 8mul + 3sqr + 7add
525
  A + A : 4mul + 2sqr + 7add
526
*/
527
template<class E>
528
void addJacobi(E& R, const E& P, const E& Q)
529
220k
{
530
220k
  typedef typename E::Fp F;
531
220k
  if (P.isZero()) { R = Q; return; }
532
206k
  if (Q.isZero()) { R = P; return; }
533
206k
  bool isPzOne = P.z.isOne();
534
206k
  bool isQzOne = Q.z.isOne();
535
206k
  F r, U1, S1, H, H3;
536
206k
  if (isPzOne) {
537
    // r = 1;
538
200k
  } else {
539
200k
    F::sqr(r, P.z);
540
200k
  }
541
206k
  if (isQzOne) {
542
70.3k
    U1 = P.x;
543
70.3k
    if (isPzOne) {
544
364
      H = Q.x;
545
69.9k
    } else {
546
69.9k
      F::mul(H, Q.x, r);
547
69.9k
    }
548
70.3k
    H -= U1;
549
70.3k
    S1 = P.y;
550
136k
  } else {
551
136k
    F::sqr(S1, Q.z);
552
136k
    F::mul(U1, P.x, S1);
553
136k
    if (isPzOne) {
554
5.36k
      H = Q.x;
555
130k
    } else {
556
130k
      F::mul(H, Q.x, r);
557
130k
    }
558
136k
    H -= U1;
559
136k
    S1 *= Q.z;
560
136k
    S1 *= P.y;
561
136k
  }
562
206k
  if (isPzOne) {
563
5.73k
    r = Q.y;
564
200k
  } else {
565
200k
    r *= P.z;
566
200k
    r *= Q.y;
567
200k
  }
568
206k
  r -= S1;
569
206k
  if (H.isZero()) {
570
351
    if (r.isZero()) {
571
205
      ec::dblJacobi(R, P);
572
205
    } else {
573
146
      R.clear();
574
146
    }
575
351
    return;
576
351
  }
577
206k
  if (isPzOne) {
578
5.71k
    if (isQzOne) {
579
350
      R.z = H;
580
5.36k
    } else {
581
5.36k
      F::mul(R.z, H, Q.z);
582
5.36k
    }
583
200k
  } else {
584
200k
    if (isQzOne) {
585
69.7k
      F::mul(R.z, P.z, H);
586
130k
    } else {
587
130k
      F::mul(R.z, P.z, Q.z);
588
130k
      R.z *= H;
589
130k
    }
590
200k
  }
591
206k
  F::sqr(H3, H); // H^2
592
206k
  F::sqr(R.y, r); // r^2
593
206k
  U1 *= H3; // U1 H^2
594
206k
  H3 *= H; // H^3
595
206k
  R.y -= U1;
596
206k
  R.y -= U1;
597
206k
  F::sub(R.x, R.y, H3);
598
206k
  U1 -= R.x;
599
206k
  U1 *= r;
600
206k
  H3 *= S1;
601
206k
  F::sub(R.y, U1, H3);
602
206k
}
void mcl::ec::addJacobi<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
529
34.9k
{
530
34.9k
  typedef typename E::Fp F;
531
34.9k
  if (P.isZero()) { R = Q; return; }
532
31.6k
  if (Q.isZero()) { R = P; return; }
533
31.6k
  bool isPzOne = P.z.isOne();
534
31.6k
  bool isQzOne = Q.z.isOne();
535
31.6k
  F r, U1, S1, H, H3;
536
31.6k
  if (isPzOne) {
537
    // r = 1;
538
29.4k
  } else {
539
29.4k
    F::sqr(r, P.z);
540
29.4k
  }
541
31.6k
  if (isQzOne) {
542
10.1k
    U1 = P.x;
543
10.1k
    if (isPzOne) {
544
59
      H = Q.x;
545
10.1k
    } else {
546
10.1k
      F::mul(H, Q.x, r);
547
10.1k
    }
548
10.1k
    H -= U1;
549
10.1k
    S1 = P.y;
550
21.4k
  } else {
551
21.4k
    F::sqr(S1, Q.z);
552
21.4k
    F::mul(U1, P.x, S1);
553
21.4k
    if (isPzOne) {
554
2.15k
      H = Q.x;
555
19.3k
    } else {
556
19.3k
      F::mul(H, Q.x, r);
557
19.3k
    }
558
21.4k
    H -= U1;
559
21.4k
    S1 *= Q.z;
560
21.4k
    S1 *= P.y;
561
21.4k
  }
562
31.6k
  if (isPzOne) {
563
2.21k
    r = Q.y;
564
29.4k
  } else {
565
29.4k
    r *= P.z;
566
29.4k
    r *= Q.y;
567
29.4k
  }
568
31.6k
  r -= S1;
569
31.6k
  if (H.isZero()) {
570
7
    if (r.isZero()) {
571
5
      ec::dblJacobi(R, P);
572
5
    } else {
573
2
      R.clear();
574
2
    }
575
7
    return;
576
7
  }
577
31.6k
  if (isPzOne) {
578
2.21k
    if (isQzOne) {
579
52
      R.z = H;
580
2.15k
    } else {
581
2.15k
      F::mul(R.z, H, Q.z);
582
2.15k
    }
583
29.4k
  } else {
584
29.4k
    if (isQzOne) {
585
10.1k
      F::mul(R.z, P.z, H);
586
19.3k
    } else {
587
19.3k
      F::mul(R.z, P.z, Q.z);
588
19.3k
      R.z *= H;
589
19.3k
    }
590
29.4k
  }
591
31.6k
  F::sqr(H3, H); // H^2
592
31.6k
  F::sqr(R.y, r); // r^2
593
31.6k
  U1 *= H3; // U1 H^2
594
31.6k
  H3 *= H; // H^3
595
31.6k
  R.y -= U1;
596
31.6k
  R.y -= U1;
597
31.6k
  F::sub(R.x, R.y, H3);
598
31.6k
  U1 -= R.x;
599
31.6k
  U1 *= r;
600
31.6k
  H3 *= S1;
601
31.6k
  F::sub(R.y, U1, H3);
602
31.6k
}
void mcl::ec::addJacobi<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
529
184k
{
530
184k
  typedef typename E::Fp F;
531
184k
  if (P.isZero()) { R = Q; return; }
532
173k
  if (Q.isZero()) { R = P; return; }
533
173k
  bool isPzOne = P.z.isOne();
534
173k
  bool isQzOne = Q.z.isOne();
535
173k
  F r, U1, S1, H, H3;
536
173k
  if (isPzOne) {
537
    // r = 1;
538
170k
  } else {
539
170k
    F::sqr(r, P.z);
540
170k
  }
541
173k
  if (isQzOne) {
542
60.1k
    U1 = P.x;
543
60.1k
    if (isPzOne) {
544
305
      H = Q.x;
545
59.8k
    } else {
546
59.8k
      F::mul(H, Q.x, r);
547
59.8k
    }
548
60.1k
    H -= U1;
549
60.1k
    S1 = P.y;
550
113k
  } else {
551
113k
    F::sqr(S1, Q.z);
552
113k
    F::mul(U1, P.x, S1);
553
113k
    if (isPzOne) {
554
3.21k
      H = Q.x;
555
110k
    } else {
556
110k
      F::mul(H, Q.x, r);
557
110k
    }
558
113k
    H -= U1;
559
113k
    S1 *= Q.z;
560
113k
    S1 *= P.y;
561
113k
  }
562
173k
  if (isPzOne) {
563
3.51k
    r = Q.y;
564
170k
  } else {
565
170k
    r *= P.z;
566
170k
    r *= Q.y;
567
170k
  }
568
173k
  r -= S1;
569
173k
  if (H.isZero()) {
570
261
    if (r.isZero()) {
571
129
      ec::dblJacobi(R, P);
572
132
    } else {
573
132
      R.clear();
574
132
    }
575
261
    return;
576
261
  }
577
173k
  if (isPzOne) {
578
3.50k
    if (isQzOne) {
579
298
      R.z = H;
580
3.21k
    } else {
581
3.21k
      F::mul(R.z, H, Q.z);
582
3.21k
    }
583
170k
  } else {
584
170k
    if (isQzOne) {
585
59.6k
      F::mul(R.z, P.z, H);
586
110k
    } else {
587
110k
      F::mul(R.z, P.z, Q.z);
588
110k
      R.z *= H;
589
110k
    }
590
170k
  }
591
173k
  F::sqr(H3, H); // H^2
592
173k
  F::sqr(R.y, r); // r^2
593
173k
  U1 *= H3; // U1 H^2
594
173k
  H3 *= H; // H^3
595
173k
  R.y -= U1;
596
173k
  R.y -= U1;
597
173k
  F::sub(R.x, R.y, H3);
598
173k
  U1 -= R.x;
599
173k
  U1 *= r;
600
173k
  H3 *= S1;
601
173k
  F::sub(R.y, U1, H3);
602
173k
}
void mcl::ec::addJacobi<mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >(mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&, mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::local::PointT<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&)
Line
Count
Source
529
329
{
530
329
  typedef typename E::Fp F;
531
329
  if (P.isZero()) { R = Q; return; }
532
329
  if (Q.isZero()) { R = P; return; }
533
329
  bool isPzOne = P.z.isOne();
534
329
  bool isQzOne = Q.z.isOne();
535
329
  F r, U1, S1, H, H3;
536
329
  if (isPzOne) {
537
    // r = 1;
538
329
  } else {
539
329
    F::sqr(r, P.z);
540
329
  }
541
329
  if (isQzOne) {
542
0
    U1 = P.x;
543
0
    if (isPzOne) {
544
0
      H = Q.x;
545
0
    } else {
546
0
      F::mul(H, Q.x, r);
547
0
    }
548
0
    H -= U1;
549
0
    S1 = P.y;
550
329
  } else {
551
329
    F::sqr(S1, Q.z);
552
329
    F::mul(U1, P.x, S1);
553
329
    if (isPzOne) {
554
0
      H = Q.x;
555
329
    } else {
556
329
      F::mul(H, Q.x, r);
557
329
    }
558
329
    H -= U1;
559
329
    S1 *= Q.z;
560
329
    S1 *= P.y;
561
329
  }
562
329
  if (isPzOne) {
563
0
    r = Q.y;
564
329
  } else {
565
329
    r *= P.z;
566
329
    r *= Q.y;
567
329
  }
568
329
  r -= S1;
569
329
  if (H.isZero()) {
570
45
    if (r.isZero()) {
571
39
      ec::dblJacobi(R, P);
572
39
    } else {
573
6
      R.clear();
574
6
    }
575
45
    return;
576
45
  }
577
284
  if (isPzOne) {
578
0
    if (isQzOne) {
579
0
      R.z = H;
580
0
    } else {
581
0
      F::mul(R.z, H, Q.z);
582
0
    }
583
284
  } else {
584
284
    if (isQzOne) {
585
0
      F::mul(R.z, P.z, H);
586
284
    } else {
587
284
      F::mul(R.z, P.z, Q.z);
588
284
      R.z *= H;
589
284
    }
590
284
  }
591
284
  F::sqr(H3, H); // H^2
592
284
  F::sqr(R.y, r); // r^2
593
284
  U1 *= H3; // U1 H^2
594
284
  H3 *= H; // H^3
595
284
  R.y -= U1;
596
284
  R.y -= U1;
597
284
  F::sub(R.x, R.y, H3);
598
284
  U1 -= R.x;
599
284
  U1 *= r;
600
284
  H3 *= S1;
601
284
  F::sub(R.y, U1, H3);
602
284
}
void mcl::ec::addJacobi<mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > > >(mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > >&, mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > > const&, mcl::local::PointT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > > const&)
Line
Count
Source
529
688
{
530
688
  typedef typename E::Fp F;
531
688
  if (P.isZero()) { R = Q; return; }
532
688
  if (Q.isZero()) { R = P; return; }
533
688
  bool isPzOne = P.z.isOne();
534
688
  bool isQzOne = Q.z.isOne();
535
688
  F r, U1, S1, H, H3;
536
688
  if (isPzOne) {
537
    // r = 1;
538
688
  } else {
539
688
    F::sqr(r, P.z);
540
688
  }
541
688
  if (isQzOne) {
542
0
    U1 = P.x;
543
0
    if (isPzOne) {
544
0
      H = Q.x;
545
0
    } else {
546
0
      F::mul(H, Q.x, r);
547
0
    }
548
0
    H -= U1;
549
0
    S1 = P.y;
550
688
  } else {
551
688
    F::sqr(S1, Q.z);
552
688
    F::mul(U1, P.x, S1);
553
688
    if (isPzOne) {
554
0
      H = Q.x;
555
688
    } else {
556
688
      F::mul(H, Q.x, r);
557
688
    }
558
688
    H -= U1;
559
688
    S1 *= Q.z;
560
688
    S1 *= P.y;
561
688
  }
562
688
  if (isPzOne) {
563
0
    r = Q.y;
564
688
  } else {
565
688
    r *= P.z;
566
688
    r *= Q.y;
567
688
  }
568
688
  r -= S1;
569
688
  if (H.isZero()) {
570
38
    if (r.isZero()) {
571
32
      ec::dblJacobi(R, P);
572
32
    } else {
573
6
      R.clear();
574
6
    }
575
38
    return;
576
38
  }
577
650
  if (isPzOne) {
578
0
    if (isQzOne) {
579
0
      R.z = H;
580
0
    } else {
581
0
      F::mul(R.z, H, Q.z);
582
0
    }
583
650
  } else {
584
650
    if (isQzOne) {
585
0
      F::mul(R.z, P.z, H);
586
650
    } else {
587
650
      F::mul(R.z, P.z, Q.z);
588
650
      R.z *= H;
589
650
    }
590
650
  }
591
650
  F::sqr(H3, H); // H^2
592
650
  F::sqr(R.y, r); // r^2
593
650
  U1 *= H3; // U1 H^2
594
650
  H3 *= H; // H^3
595
650
  R.y -= U1;
596
650
  R.y -= U1;
597
650
  F::sub(R.x, R.y, H3);
598
650
  U1 -= R.x;
599
650
  U1 *= r;
600
650
  H3 *= S1;
601
650
  F::sub(R.y, U1, H3);
602
650
}
603
604
/*
605
  accept P == Q
606
  https://eprint.iacr.org/2015/1060
607
  (x, y, z) is zero <=> x = 0, y = 1, z = 0
608
*/
609
610
// (b=4) 12M+27A
611
// (generic) 14M+19A
612
// Q.z = 1 if mixed
613
template<class E>
614
void addCTProj(E& R, const E& P, const E& Q, bool mixed = false)
615
{
616
  typedef typename E::Fp F;
617
  assert(E::a_ == 0);
618
  F t0, t1, t2, t3, t4, x3, y3;
619
  F::mul(t0, P.x, Q.x);
620
  F::mul(t1, P.y, Q.y);
621
  if (mixed) {
622
    t2 = P.z;
623
  } else {
624
    F::mul(t2, P.z, Q.z);
625
  }
626
  F::add(t3, P.x, P.y);
627
  F::add(t4, Q.x, Q.y);
628
  F::mul(t3, t3, t4);
629
  F::add(t4, t0, t1);
630
  F::sub(t3, t3, t4);
631
  F::add(t4, P.y, P.z);
632
  F::add(x3, Q.y, Q.z);
633
  F::mul(t4, t4, x3);
634
  F::add(x3, t1, t2);
635
  F::sub(t4, t4, x3);
636
  F::add(x3, P.x, P.z);
637
  F::add(y3, Q.x, Q.z);
638
  F::mul(x3, x3, y3);
639
  F::add(y3, t0, t2);
640
  F::sub(y3, x3, y3);
641
  F::add(x3, t0, t0);
642
  F::add(t0, t0, x3);
643
  if (E::specialB_ == ec::local::Plus1) {
644
    local::mul3(t2);
645
  } else
646
  if (E::specialB_ == ec::local::Plus4) {
647
    local::mul12(t2);
648
  } else
649
  {
650
    F::mul(t2, t2, E::b3_);
651
  }
652
  F::add(R.z, t1, t2);
653
  F::sub(t1, t1, t2);
654
  if (E::specialB_ == ec::local::Plus1) {
655
    local::mul3(y3);
656
  } else
657
  if (E::specialB_ == ec::local::Plus4) {
658
    local::mul12(y3);
659
  } else
660
  {
661
    F::mul(y3, y3, E::b3_);
662
  }
663
  F::mul(x3, y3, t4);
664
  F::mul(t2, t3, t1);
665
  F::sub(R.x, t2, x3);
666
  F::mul(y3, y3, t0);
667
  F::mul(t1, t1, R.z);
668
  F::add(R.y, y3, t1);
669
  F::mul(t0, t0, t3);
670
  F::mul(R.z, R.z, t4);
671
  F::add(R.z, R.z, t0);
672
}
673
// (b = 4) 6M+2S+13A
674
// (generic) 7M+2S+9A
675
template<class E>
676
void dblCTProj(E& R, const E& P)
677
{
678
  typedef typename E::Fp F;
679
  assert(E::a_ == 0);
680
  F t0, t1, t2, x3, y3;
681
  F::sqr(t0, P.y);
682
  F::mul(t1, P.y, P.z);
683
  F::sqr(t2, P.z);
684
  F::add(R.z, t0, t0);
685
  F::add(R.z, R.z, R.z);
686
  F::add(R.z, R.z, R.z);
687
  if (E::specialB_ == ec::local::Plus1) {
688
    local::mul3(t2);
689
  } else
690
  if (E::specialB_ == ec::local::Plus4) {
691
    local::mul12(t2);
692
  } else
693
  {
694
    F::mul(t2, t2, E::b3_);
695
  }
696
  F::mul(x3, t2, R.z);
697
  F::add(y3, t0, t2);
698
  F::mul(R.z, R.z, t1);
699
  F::add(t1, t2, t2);
700
  F::add(t2, t2, t1);
701
  F::mul(t1, P.x, P.y);
702
  F::sub(t0, t0, t2);
703
  F::mul(R.y, y3, t0);
704
  F::add(R.y, R.y, x3);
705
  F::mul(R.x, t0, t1);
706
  F::add(R.x, R.x, R.x);
707
}
708
709
template<class E>
710
void normalizeProj(E& P)
711
0
{
712
0
  if (P.z.isZero() || P.z.isOne()) return;
713
0
  typedef typename E::Fp F;
714
0
  F::inv(P.z, P.z);
715
0
  local::_normalizeProj(P, P, P.z);
716
0
}
Unexecuted instantiation: void mcl::ec::normalizeProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&)
Unexecuted instantiation: void mcl::ec::normalizeProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&)
717
718
// (Y^2 - bZ^2)Z = X(X^2 + aZ^2)
719
template<class E>
720
bool isValidProj(const E& P)
721
0
{
722
0
  typedef typename E::Fp F;
723
0
  F y2, x2, z2, t;
724
0
  F::sqr(x2, P.x);
725
0
  F::sqr(y2, P.y);
726
0
  F::sqr(z2, P.z);
727
0
  F::mul(t, E::a_, z2);
728
0
  t += x2;
729
0
  t *= P.x;
730
0
  z2 *= E::b_;
731
0
  y2 -= z2;
732
0
  y2 *= P.z;
733
0
  return y2 == t;
734
0
}
Unexecuted instantiation: bool mcl::ec::isValidProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: bool mcl::ec::isValidProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
735
736
// (x/z, y/z)
737
template<class E>
738
bool isEqualProj(const E& P1, const E& P2)
739
0
{
740
0
  typedef typename E::Fp F;
741
0
  bool zero1 = P1.isZero();
742
0
  bool zero2 = P2.isZero();
743
0
  if (zero1) {
744
0
    return zero2;
745
0
  }
746
0
  if (zero2) return false;
747
0
  F t1, t2;
748
0
  F::mul(t1, P1.x, P2.z);
749
0
  F::mul(t2, P2.x, P1.z);
750
0
  if (t1 != t2) return false;
751
0
  F::mul(t1, P1.y, P2.z);
752
0
  F::mul(t2, P2.y, P1.z);
753
0
  return t1 == t2;
754
0
}
Unexecuted instantiation: bool mcl::ec::isEqualProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: bool mcl::ec::isEqualProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
755
756
// return (P1 == P2) ? 1 : (P1 == -P2) ? -1 : 0
757
template<class E>
758
int isEqualOrMinusProj(const E& P1, const E& P2)
759
{
760
  typedef typename E::Fp F;
761
  bool zero1 = P1.isZero();
762
  bool zero2 = P2.isZero();
763
  if (zero1) {
764
    return zero2 ? 1 : 0;
765
  }
766
  if (zero2) return 0;
767
  F t1, t2;
768
  F::mul(t1, P1.x, P2.z);
769
  F::mul(t2, P2.x, P1.z);
770
  if (t1 != t2) return 0;
771
  F::mul(t1, P1.y, P2.z);
772
  F::mul(t2, P2.y, P1.z);
773
  if (t1 == t2) return 1;
774
  F::neg(t1, t1);
775
  if (t1 == t2) return -1;
776
  return 0;
777
}
778
779
/*
780
     |a=0|-3| generic
781
  mul|  8| 8| 9
782
  sqr|  4| 5| 5
783
  add| 11|12|12
784
*/
785
template<class E>
786
void dblProj(E& R, const E& P)
787
0
{
788
0
  typedef typename E::Fp F;
789
0
  if (P.isZero()) {
790
0
    R.clear();
791
0
    return;
792
0
  }
793
0
  const bool isPzOne = P.z.isOne();
794
0
  F w, t, h;
795
0
  switch (E::specialA_) {
796
0
  case local::Zero:
797
0
    F::sqr(w, P.x);
798
0
    F::add(t, w, w);
799
0
    w += t;
800
0
    break;
801
0
  case local::Minus3:
802
0
    F::sqr(w, P.x);
803
0
    if (isPzOne) {
804
0
      w -= P.z;
805
0
    } else {
806
0
      F::sqr(t, P.z);
807
0
      w -= t;
808
0
    }
809
0
    F::add(t, w, w);
810
0
    w += t;
811
0
    break;
812
0
  case local::GenericA:
813
0
  default:
814
0
    if (isPzOne) {
815
0
      w = E::a_;
816
0
    } else {
817
0
      F::sqr(w, P.z);
818
0
      w *= E::a_;
819
0
    }
820
0
    F::sqr(t, P.x);
821
0
    w += t;
822
0
    w += t;
823
0
    w += t; // w = a z^2 + 3x^2
824
0
    break;
825
0
  }
826
0
  if (isPzOne) {
827
0
    R.z = P.y;
828
0
  } else {
829
0
    F::mul(R.z, P.y, P.z); // s = yz
830
0
  }
831
0
  F::mul(t, R.z, P.x);
832
0
  t *= P.y; // xys
833
0
  t += t;
834
0
  t += t; // 4(xys) ; 4B
835
0
  F::sqr(h, w);
836
0
  h -= t;
837
0
  h -= t; // w^2 - 8B
838
0
  F::mul(R.x, h, R.z);
839
0
  t -= h; // h is free
840
0
  t *= w;
841
0
  F::sqr(w, P.y);
842
0
  R.x += R.x;
843
0
  R.z += R.z;
844
0
  F::sqr(h, R.z);
845
0
  w *= h;
846
0
  R.z *= h;
847
0
  F::sub(R.y, t, w);
848
0
  R.y -= w;
849
0
}
Unexecuted instantiation: void mcl::ec::dblProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: void mcl::ec::dblProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
850
851
/*
852
  mul| 12
853
  sqr|  2
854
  add|  7
855
*/
856
template<class E>
857
void addProj(E& R, const E& P, const E& Q)
858
0
{
859
0
  typedef typename E::Fp F;
860
0
  if (P.isZero()) { R = Q; return; }
861
0
  if (Q.isZero()) { R = P; return; }
862
0
  bool isPzOne = P.z.isOne();
863
0
  bool isQzOne = Q.z.isOne();
864
0
  F r, PyQz, v, A, vv;
865
0
  if (isQzOne) {
866
0
    r = P.x;
867
0
    PyQz = P.y;
868
0
  } else {
869
0
    F::mul(r, P.x, Q.z);
870
0
    F::mul(PyQz, P.y, Q.z);
871
0
  }
872
0
  if (isPzOne) {
873
0
    A = Q.y;
874
0
    v = Q.x;
875
0
  } else {
876
0
    F::mul(A, Q.y, P.z);
877
0
    F::mul(v, Q.x, P.z);
878
0
  }
879
0
  v -= r;
880
0
  if (v.isZero()) {
881
0
    if (A == PyQz) {
882
0
      dblProj(R, P);
883
0
    } else {
884
0
      R.clear();
885
0
    }
886
0
    return;
887
0
  }
888
0
  F::sub(R.y, A, PyQz);
889
0
  F::sqr(A, R.y);
890
0
  F::sqr(vv, v);
891
0
  r *= vv;
892
0
  vv *= v;
893
0
  if (isQzOne) {
894
0
    R.z = P.z;
895
0
  } else {
896
0
    if (isPzOne) {
897
0
      R.z = Q.z;
898
0
    } else {
899
0
      F::mul(R.z, P.z, Q.z);
900
0
    }
901
0
  }
902
  // R.z = 1 if isPzOne && isQzOne
903
0
  if (isPzOne && isQzOne) {
904
0
    R.z = vv;
905
0
  } else {
906
0
    A *= R.z;
907
0
    R.z *= vv;
908
0
  }
909
0
  A -= vv;
910
0
  vv *= PyQz;
911
0
  A -= r;
912
0
  A -= r;
913
0
  F::mul(R.x, v, A);
914
0
  r -= A;
915
0
  R.y *= r;
916
0
  R.y -= vv;
917
0
}
Unexecuted instantiation: void mcl::ec::addProj<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: void mcl::ec::addProj<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
918
919
// y^2 == (x^2 + a)x + b
920
template<class E>
921
bool isValidAffine(const E& P)
922
27.7k
{
923
27.7k
  typedef typename E::Fp F;
924
27.7k
  assert(!P.z.isZero());
925
27.7k
  F y2, t;
926
27.7k
  F::sqr(y2, P.y);
927
27.7k
  F::sqr(t, P.x);
928
27.7k
  t += E::a_;
929
27.7k
  t *= P.x;
930
27.7k
  t += E::b_;
931
27.7k
  return y2 == t;
932
27.7k
}
bool mcl::ec::isValidAffine<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
922
13.2k
{
923
13.2k
  typedef typename E::Fp F;
924
13.2k
  assert(!P.z.isZero());
925
13.2k
  F y2, t;
926
13.2k
  F::sqr(y2, P.y);
927
13.2k
  F::sqr(t, P.x);
928
13.2k
  t += E::a_;
929
13.2k
  t *= P.x;
930
13.2k
  t += E::b_;
931
13.2k
  return y2 == t;
932
13.2k
}
bool mcl::ec::isValidAffine<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
922
14.4k
{
923
14.4k
  typedef typename E::Fp F;
924
14.4k
  assert(!P.z.isZero());
925
14.4k
  F y2, t;
926
14.4k
  F::sqr(y2, P.y);
927
14.4k
  F::sqr(t, P.x);
928
14.4k
  t += E::a_;
929
14.4k
  t *= P.x;
930
14.4k
  t += E::b_;
931
14.4k
  return y2 == t;
932
14.4k
}
933
934
// y^2 = x^3 + ax + b
935
template<class E>
936
static inline void dblAffine(E& R, const E& P)
937
0
{
938
0
  typedef typename E::Fp F;
939
0
  if (P.isZero()) {
940
0
    R.clear();
941
0
    return;
942
0
  }
943
0
  if (P.y.isZero()) {
944
0
    R.clear();
945
0
    return;
946
0
  }
947
0
  F t, s;
948
0
  F::sqr(t, P.x);
949
0
  F::add(s, t, t);
950
0
  t += s;
951
0
  t += E::a_;
952
0
  F::add(s, P.y, P.y);
953
0
  t /= s;
954
0
  F::sqr(s, t);
955
0
  s -= P.x;
956
0
  F x3;
957
0
  F::sub(x3, s, P.x);
958
0
  F::sub(s, P.x, x3);
959
0
  s *= t;
960
0
  F::sub(R.y, s, P.y);
961
0
  R.x = x3;
962
0
  R.z = 1;
963
0
}
Unexecuted instantiation: module.cpp:void mcl::ec::dblAffine<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: module.cpp:void mcl::ec::dblAffine<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
964
965
template<class E>
966
void addAffine(E& R, const E& P, const E& Q)
967
0
{
968
0
  typedef typename E::Fp F;
969
0
  if (P.isZero()) { R = Q; return; }
970
0
  if (Q.isZero()) { R = P; return; }
971
0
  F t;
972
0
  F::sub(t, Q.x, P.x);
973
0
  if (t.isZero()) {
974
0
    if (P.y == Q.y) {
975
0
      dblAffine(R, P);
976
0
    } else {
977
0
      R.clear();
978
0
    }
979
0
    return;
980
0
  }
981
0
  F s;
982
0
  F::sub(s, Q.y, P.y);
983
0
  F::div(t, s, t);
984
0
  R.z = 1;
985
0
  F x3;
986
0
  F::sqr(x3, t);
987
0
  x3 -= P.x;
988
0
  x3 -= Q.x;
989
0
  F::sub(s, P.x, x3);
990
0
  s *= t;
991
0
  F::sub(R.y, s, P.y);
992
0
  R.x = x3;
993
0
}
Unexecuted instantiation: void mcl::ec::addAffine<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Unexecuted instantiation: void mcl::ec::addAffine<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
994
995
template<class E>
996
void tryAndIncMapTo(E& P, const typename E::Fp& t)
997
0
{
998
0
  typedef typename E::Fp F;
999
0
  F x = t;
1000
0
  for (;;) {
1001
0
    F y;
1002
0
    E::getWeierstrass(y, x);
1003
0
    if (F::squareRoot(y, y)) {
1004
0
      bool b;
1005
0
      P.set(&b, x, y, false);
1006
0
      assert(b);
1007
0
      return;
1008
0
    }
1009
0
    *x.getFp0() += F::BaseFp::one();
1010
0
  }
1011
0
}
Unexecuted instantiation: void mcl::ec::tryAndIncMapTo<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp const&)
Unexecuted instantiation: void mcl::ec::tryAndIncMapTo<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::Fp const&)
1012
1013
inline size_t ilog2(size_t n)
1014
0
{
1015
0
  if (n == 0) return 0;
1016
0
  return cybozu::bsr(n) + 1;
1017
0
}
1018
1019
// The number of ADD for n-elements with bucket size b
1020
inline size_t glvCost(size_t n, size_t b)
1021
0
{
1022
0
  return (n + (size_t(1)<<(b+1))-1)/b;
1023
0
}
1024
// approximate value such that argmin { b : glvCost(n, b) }
1025
inline size_t estimateBucketSize(size_t n)
1026
0
{
1027
0
  if (n <= 16) return 2;
1028
0
  size_t log2n = ilog2(n);
1029
0
  return log2n - ilog2(log2n);
1030
0
}
1031
1032
/*
1033
  First, get approximate value x and compute glvCost of x-1 and x+1,
1034
  and return the minimum value.
1035
*/
1036
inline size_t glvGetTheoreticBucketSize(size_t n)
1037
0
{
1038
0
  size_t x = estimateBucketSize(n);
1039
0
  size_t vm1 = x > 1 ? glvCost(n, x-1) : n;
1040
0
  size_t v0 = glvCost(n, x);
1041
0
  size_t vp1 = glvCost(n, x+1);
1042
0
  if (vm1 <= v0) return x-1;
1043
0
  if (vp1 < v0) return x+1;
1044
0
  return x;
1045
0
}
1046
1047
//  return heuristic backet size which is faster than glvGetTheoreticBucketSize
1048
inline size_t glvGetBucketSize(size_t n)
1049
0
{
1050
0
  if (n <= 2) return 2;
1051
0
  size_t log2n = mcl::ec::ilog2(n);
1052
0
  const size_t tblMin = 8;
1053
0
  if (log2n < tblMin) return 3;
1054
  // n >= 2^tblMin
1055
0
  static const size_t tbl[] = {
1056
0
    3, 4, 5, 5, 8, 8, 9, 10, 11, 12, 13, 13, 13, 16, 16, 16, 18, 19, 19, 19, 19, 19
1057
0
  };
1058
0
  if (log2n >= CYBOZU_NUM_OF_ARRAY(tbl)) return 19;
1059
0
  size_t ret = tbl[log2n - tblMin];
1060
0
  return ret;
1061
0
}
1062
1063
#ifndef MCL_MAX_N_TO_USE_STACK_FOR_MUL_VEC
1064
  // use (1 << glvGetBucketSize(n)) * sizeof(G) bytes stack + alpha
1065
  // about 18KiB (G1) or 36KiB (G2) for n = 1024
1066
  // you can decrease this value but this algorithm is slow if n < 256
1067
0
  #define MCL_MAX_N_TO_USE_STACK_FOR_MUL_VEC 1024
1068
#endif
1069
1070
/*
1071
  Extract w bits from yVec[i] starting at the pos-th bit, assign this value to v.
1072
  tbl[v-1] += xVec[i]
1073
  win = xVec[0] + 2 xVec[1] + 3 xVec[2] + ... + tblN xVec[tblN-1]
1074
*/
1075
template<class G>
1076
void mulVecUpdateTable(G& win, G *tbl, size_t tblN, const G *xVec, const Unit *yVec, size_t yUnitSize, size_t next, size_t pos, size_t n, bool first)
1077
0
{
1078
0
  for (size_t i = 0; i < tblN; i++) {
1079
0
    tbl[i].clear();
1080
0
  }
1081
0
  for (size_t i = 0; i < n; i++) {
1082
0
    Unit v = fp::getUnitAt(yVec + next * i, yUnitSize, pos) & tblN;
1083
0
    if (v) {
1084
0
      tbl[v - 1] += xVec[i];
1085
0
    }
1086
0
  }
1087
0
  G sum = tbl[tblN - 1];
1088
0
  if (first) {
1089
0
    win = sum;
1090
0
  } else {
1091
0
    win += sum;
1092
0
  }
1093
0
  for (size_t i = 1; i < tblN; i++) {
1094
0
    sum += tbl[tblN - 1 - i];
1095
0
    win += sum;
1096
0
  }
1097
0
}
Unexecuted instantiation: void mcl::ec::mulVecUpdateTable<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: void mcl::ec::mulVecUpdateTable<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: void mcl::ec::mulVecUpdateTable<mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >*, unsigned long, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
1098
/*
1099
  z = sum_{i=0}^{n-1} xVec[i] * yVec[i]
1100
  yVec[i] means yVec[i*next:(i+1)*next+yUnitSize]
1101
  return numbers of done, which may be smaller than n if malloc fails
1102
  @note xVec may be normlized
1103
  fast for n >= 256
1104
*/
1105
template<class G>
1106
size_t mulVecCore(G& z, G *xVec, const Unit *yVec, size_t yUnitSize, size_t next, size_t n, size_t b, bool doNormalize)
1107
0
{
1108
0
  if (n == 0) {
1109
0
    z.clear();
1110
0
    return 0;
1111
0
  }
1112
0
  if (n == 1) {
1113
0
    G::mulArray(z, xVec[0], yVec, yUnitSize);
1114
0
    return 1;
1115
0
  }
1116
1117
0
  size_t tblN;
1118
0
  G *tbl = 0;
1119
1120
0
#ifndef MCL_DONT_USE_MALLOC
1121
0
  G *tbl_ = 0; // malloc is used if tbl_ != 0
1122
  // if n is large then try to use malloc
1123
0
  if (n > MCL_MAX_N_TO_USE_STACK_FOR_MUL_VEC) {
1124
0
    if (b == 0) b = glvGetBucketSize(n);
1125
0
    tblN = (1 << b) - 1;
1126
0
    tbl_ = (G*)malloc(sizeof(G) * tblN);
1127
0
    if (tbl_) {
1128
0
      tbl = tbl_;
1129
0
      goto main;
1130
0
    }
1131
0
  }
1132
0
#endif
1133
  // n is small or malloc fails so use stack
1134
0
  if (n > MCL_MAX_N_TO_USE_STACK_FOR_MUL_VEC) n = MCL_MAX_N_TO_USE_STACK_FOR_MUL_VEC;
1135
0
  if (b == 0) b = glvGetBucketSize(n);
1136
0
  tblN = (1 << b) - 1;
1137
0
  tbl = (G*)CYBOZU_ALLOCA(sizeof(G) * tblN);
1138
  // keep tbl_ = 0
1139
0
#ifndef MCL_DONT_USE_MALLOC
1140
0
main:
1141
0
#endif
1142
0
  const size_t maxBitSize = sizeof(Unit) * yUnitSize * 8;
1143
0
  const size_t winN = (maxBitSize + b-1) / b;
1144
1145
  // about 10% faster
1146
0
  if (doNormalize) G::normalizeVec(xVec, xVec, n);
1147
1148
0
  mulVecUpdateTable(z, tbl, tblN, xVec, yVec, yUnitSize, next, b * (winN-1), n, true);
1149
0
  for (size_t w = 1; w < winN; w++) {
1150
0
    for (size_t i = 0; i < b; i++) {
1151
0
      G::dbl(z, z);
1152
0
    }
1153
0
    mulVecUpdateTable(z, tbl, tblN, xVec, yVec, yUnitSize, next, b * (winN-1-w), n, false);
1154
0
  }
1155
0
#ifndef MCL_DONT_USE_MALLOC
1156
0
  if (tbl_) free(tbl_);
1157
0
#endif
1158
0
  return n;
1159
0
}
Unexecuted instantiation: unsigned long mcl::ec::mulVecCore<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: unsigned long mcl::ec::mulVecCore<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: unsigned long mcl::ec::mulVecCore<mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
1160
template<class G>
1161
void mulVecLong(G& z, G *xVec, const Unit *yVec, size_t yUnitSize, size_t next, size_t n, size_t b, bool doNormalize)
1162
0
{
1163
0
  size_t done = mulVecCore(z, xVec, yVec, yUnitSize, next, n, b, doNormalize);
1164
0
  if (done == n) return;
1165
0
  do {
1166
0
    xVec += done;
1167
0
    yVec += next * done;
1168
0
    n -= done;
1169
0
    G t;
1170
0
    done = mulVecCore(t, xVec, yVec, yUnitSize, next, n, b, doNormalize);
1171
0
    z += t;
1172
0
  } while (done < n);
1173
0
}
Unexecuted instantiation: void mcl::ec::mulVecLong<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: void mcl::ec::mulVecLong<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
Unexecuted instantiation: void mcl::ec::mulVecLong<mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >*, unsigned long const*, unsigned long, unsigned long, unsigned long, unsigned long, bool)
1174
1175
// for n >= 128
1176
template<class GLV, class G>
1177
bool mulVecGLVlarge(G& z, const G *xVec, const void *yVec, size_t n, size_t bucket)
1178
0
{
1179
0
  const int splitN = GLV::splitN;
1180
0
  assert(n > 0);
1181
0
  typedef typename GLV::Fr F;
1182
0
  fp::getMpzAtType getMpzAt = fp::getMpzAtT<F>;
1183
0
  typedef mcl::Unit Unit;
1184
0
  const size_t next = F::getUnitSize();
1185
0
  mpz_class u[splitN], y;
1186
1187
0
  const size_t tblByteSize = sizeof(G) * splitN * n;
1188
0
  const size_t ypByteSize = sizeof(Unit) * next * splitN * n;
1189
0
  G *tbl = (G*)malloc(tblByteSize + ypByteSize);
1190
0
  if (tbl == 0) return false;
1191
1192
0
  Unit *yp = (Unit *)(tbl + splitN * n);
1193
1194
0
  G::normalizeVec(tbl, xVec, n);
1195
0
  for (int i = 1; i < splitN; i++) {
1196
0
    for (size_t j = 0; j < n; j++) {
1197
0
      GLV::mulLambda(tbl[i * n + j], tbl[(i - 1) * n + j]);
1198
0
    }
1199
0
  }
1200
0
  for (size_t i = 0; i < n; i++) {
1201
0
    getMpzAt(y, yVec, i);
1202
0
    GLV::split(u, y);
1203
0
    for (size_t j = 0; j < splitN; j++) {
1204
0
      size_t idx = j * n + i;
1205
0
      if (u[j] < 0) {
1206
0
        u[j] = -u[j];
1207
0
        G::neg(tbl[idx], tbl[idx]);
1208
0
      }
1209
0
      bool b;
1210
0
      mcl::gmp::getArray(&b, &yp[idx * next], next, u[j]);
1211
0
      assert(b); (void)b;
1212
0
    }
1213
0
  }
1214
0
  mulVecLong(z, tbl, yp, next, next, n * splitN, false, bucket);
1215
0
  free(tbl);
1216
0
  return true;
1217
0
}
Unexecuted instantiation: bool mcl::ec::mulVecGLVlarge<mcl::bn::local::GLV1, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, unsigned long)
Unexecuted instantiation: bool mcl::ec::mulVecGLVlarge<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, unsigned long)
Unexecuted instantiation: bool mcl::ec::mulVecGLVlarge<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const*, void const*, unsigned long, unsigned long)
Unexecuted instantiation: bool mcl::ec::mulVecGLVlarge<mcl::GLV1T<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, unsigned long)
1218
1219
template<class G>
1220
bool mulSmallInt(G& z, const G& x, Unit y, bool isNegative)
1221
5.34k
{
1222
5.34k
  switch (y) {
1223
19
  case 0: z.clear(); return true;
1224
51
  case 1: z = x; break;
1225
26
  case 2: G::dbl(z, x); break;
1226
12
  case 3: {
1227
12
    G t;
1228
12
    G::dbl(t, x);
1229
12
    G::add(z, t, x);
1230
12
    break;
1231
0
  }
1232
55
  case 4: {
1233
55
    G::dbl(z, x);
1234
55
    G::dbl(z, z);
1235
55
    break;
1236
0
  }
1237
37
  case 5: {
1238
37
    G t;
1239
37
    G::dbl(t, x);
1240
37
    G::dbl(t, t);
1241
37
    G::add(z, t, x);
1242
37
    break;
1243
0
  }
1244
107
  case 6: {
1245
107
    G t;
1246
107
    G::dbl(t, x);
1247
107
    G::add(z, t, x);
1248
107
    G::dbl(z, z);
1249
107
    break;
1250
0
  }
1251
46
  case 7: {
1252
46
    G t;
1253
46
    G::dbl(t, x);
1254
46
    G::dbl(t, t);
1255
46
    G::dbl(t, t);
1256
46
    G::sub(z, t, x);
1257
46
    break;
1258
0
  }
1259
27
  case 8: {
1260
27
    G::dbl(z, x);
1261
27
    G::dbl(z, z);
1262
27
    G::dbl(z, z);
1263
27
    break;
1264
0
  }
1265
15
  case 9: {
1266
15
    G t;
1267
15
    G::dbl(t, x);
1268
15
    G::dbl(t, t);
1269
15
    G::dbl(t, t);
1270
15
    G::add(z, t, x);
1271
15
    break;
1272
0
  }
1273
6
  case 10: {
1274
6
    G t;
1275
6
    G::dbl(t, x);
1276
6
    G::dbl(t, t);
1277
6
    G::add(z, t, x);
1278
6
    G::dbl(z, z);
1279
6
    break;
1280
0
  }
1281
7
  case 11: {
1282
7
    G t1, t2;
1283
7
    G::dbl(t1, x); // 2x
1284
7
    G::dbl(t2, t1);
1285
7
    G::dbl(t2, t2); // 8x
1286
7
    G::add(t2, t2, t1);
1287
7
    G::add(z, t2, x);
1288
7
    break;
1289
0
  }
1290
5
  case 12: {
1291
5
    G t1, t2;
1292
5
    G::dbl(t1, x);
1293
5
    G::dbl(t1, t1); // 4x
1294
5
    G::dbl(t2, t1); // 8x
1295
5
    G::add(z, t1, t2);
1296
5
    break;
1297
0
  }
1298
6
  case 13: {
1299
6
    G t1, t2;
1300
6
    G::dbl(t1, x);
1301
6
    G::dbl(t1, t1); // 4x
1302
6
    G::dbl(t2, t1); // 8x
1303
6
    G::add(t1, t1, t2); // 12x
1304
6
    G::add(z, t1, x);
1305
6
    break;
1306
0
  }
1307
10
  case 14: {
1308
10
    G t;
1309
    // (8 - 1) * 2
1310
10
    G::dbl(t, x);
1311
10
    G::dbl(t, t);
1312
10
    G::dbl(t, t);
1313
10
    G::sub(t, t, x);
1314
10
    G::dbl(z, t);
1315
10
    break;
1316
0
  }
1317
13
  case 15: {
1318
13
    G t;
1319
13
    G::dbl(t, x);
1320
13
    G::dbl(t, t);
1321
13
    G::dbl(t, t);
1322
13
    G::dbl(t, t);
1323
13
    G::sub(z, t, x);
1324
13
    break;
1325
0
  }
1326
6
  case 16: {
1327
6
    G::dbl(z, x);
1328
6
    G::dbl(z, z);
1329
6
    G::dbl(z, z);
1330
6
    G::dbl(z, z);
1331
6
    break;
1332
0
  }
1333
4.89k
  default:
1334
4.89k
    return false;
1335
5.34k
  }
1336
429
  if (isNegative) {
1337
0
    G::neg(z, z);
1338
0
  }
1339
429
  return true;
1340
5.34k
}
bool mcl::ec::mulSmallInt<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long, bool)
Line
Count
Source
1221
2.22k
{
1222
2.22k
  switch (y) {
1223
10
  case 0: z.clear(); return true;
1224
25
  case 1: z = x; break;
1225
13
  case 2: G::dbl(z, x); break;
1226
6
  case 3: {
1227
6
    G t;
1228
6
    G::dbl(t, x);
1229
6
    G::add(z, t, x);
1230
6
    break;
1231
0
  }
1232
28
  case 4: {
1233
28
    G::dbl(z, x);
1234
28
    G::dbl(z, z);
1235
28
    break;
1236
0
  }
1237
17
  case 5: {
1238
17
    G t;
1239
17
    G::dbl(t, x);
1240
17
    G::dbl(t, t);
1241
17
    G::add(z, t, x);
1242
17
    break;
1243
0
  }
1244
51
  case 6: {
1245
51
    G t;
1246
51
    G::dbl(t, x);
1247
51
    G::add(z, t, x);
1248
51
    G::dbl(z, z);
1249
51
    break;
1250
0
  }
1251
23
  case 7: {
1252
23
    G t;
1253
23
    G::dbl(t, x);
1254
23
    G::dbl(t, t);
1255
23
    G::dbl(t, t);
1256
23
    G::sub(z, t, x);
1257
23
    break;
1258
0
  }
1259
13
  case 8: {
1260
13
    G::dbl(z, x);
1261
13
    G::dbl(z, z);
1262
13
    G::dbl(z, z);
1263
13
    break;
1264
0
  }
1265
8
  case 9: {
1266
8
    G t;
1267
8
    G::dbl(t, x);
1268
8
    G::dbl(t, t);
1269
8
    G::dbl(t, t);
1270
8
    G::add(z, t, x);
1271
8
    break;
1272
0
  }
1273
3
  case 10: {
1274
3
    G t;
1275
3
    G::dbl(t, x);
1276
3
    G::dbl(t, t);
1277
3
    G::add(z, t, x);
1278
3
    G::dbl(z, z);
1279
3
    break;
1280
0
  }
1281
3
  case 11: {
1282
3
    G t1, t2;
1283
3
    G::dbl(t1, x); // 2x
1284
3
    G::dbl(t2, t1);
1285
3
    G::dbl(t2, t2); // 8x
1286
3
    G::add(t2, t2, t1);
1287
3
    G::add(z, t2, x);
1288
3
    break;
1289
0
  }
1290
2
  case 12: {
1291
2
    G t1, t2;
1292
2
    G::dbl(t1, x);
1293
2
    G::dbl(t1, t1); // 4x
1294
2
    G::dbl(t2, t1); // 8x
1295
2
    G::add(z, t1, t2);
1296
2
    break;
1297
0
  }
1298
3
  case 13: {
1299
3
    G t1, t2;
1300
3
    G::dbl(t1, x);
1301
3
    G::dbl(t1, t1); // 4x
1302
3
    G::dbl(t2, t1); // 8x
1303
3
    G::add(t1, t1, t2); // 12x
1304
3
    G::add(z, t1, x);
1305
3
    break;
1306
0
  }
1307
3
  case 14: {
1308
3
    G t;
1309
    // (8 - 1) * 2
1310
3
    G::dbl(t, x);
1311
3
    G::dbl(t, t);
1312
3
    G::dbl(t, t);
1313
3
    G::sub(t, t, x);
1314
3
    G::dbl(z, t);
1315
3
    break;
1316
0
  }
1317
7
  case 15: {
1318
7
    G t;
1319
7
    G::dbl(t, x);
1320
7
    G::dbl(t, t);
1321
7
    G::dbl(t, t);
1322
7
    G::dbl(t, t);
1323
7
    G::sub(z, t, x);
1324
7
    break;
1325
0
  }
1326
2
  case 16: {
1327
2
    G::dbl(z, x);
1328
2
    G::dbl(z, z);
1329
2
    G::dbl(z, z);
1330
2
    G::dbl(z, z);
1331
2
    break;
1332
0
  }
1333
2.01k
  default:
1334
2.01k
    return false;
1335
2.22k
  }
1336
207
  if (isNegative) {
1337
0
    G::neg(z, z);
1338
0
  }
1339
207
  return true;
1340
2.22k
}
bool mcl::ec::mulSmallInt<mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long, bool)
Line
Count
Source
1221
3.11k
{
1222
3.11k
  switch (y) {
1223
9
  case 0: z.clear(); return true;
1224
26
  case 1: z = x; break;
1225
13
  case 2: G::dbl(z, x); break;
1226
6
  case 3: {
1227
6
    G t;
1228
6
    G::dbl(t, x);
1229
6
    G::add(z, t, x);
1230
6
    break;
1231
0
  }
1232
27
  case 4: {
1233
27
    G::dbl(z, x);
1234
27
    G::dbl(z, z);
1235
27
    break;
1236
0
  }
1237
20
  case 5: {
1238
20
    G t;
1239
20
    G::dbl(t, x);
1240
20
    G::dbl(t, t);
1241
20
    G::add(z, t, x);
1242
20
    break;
1243
0
  }
1244
56
  case 6: {
1245
56
    G t;
1246
56
    G::dbl(t, x);
1247
56
    G::add(z, t, x);
1248
56
    G::dbl(z, z);
1249
56
    break;
1250
0
  }
1251
23
  case 7: {
1252
23
    G t;
1253
23
    G::dbl(t, x);
1254
23
    G::dbl(t, t);
1255
23
    G::dbl(t, t);
1256
23
    G::sub(z, t, x);
1257
23
    break;
1258
0
  }
1259
14
  case 8: {
1260
14
    G::dbl(z, x);
1261
14
    G::dbl(z, z);
1262
14
    G::dbl(z, z);
1263
14
    break;
1264
0
  }
1265
7
  case 9: {
1266
7
    G t;
1267
7
    G::dbl(t, x);
1268
7
    G::dbl(t, t);
1269
7
    G::dbl(t, t);
1270
7
    G::add(z, t, x);
1271
7
    break;
1272
0
  }
1273
3
  case 10: {
1274
3
    G t;
1275
3
    G::dbl(t, x);
1276
3
    G::dbl(t, t);
1277
3
    G::add(z, t, x);
1278
3
    G::dbl(z, z);
1279
3
    break;
1280
0
  }
1281
4
  case 11: {
1282
4
    G t1, t2;
1283
4
    G::dbl(t1, x); // 2x
1284
4
    G::dbl(t2, t1);
1285
4
    G::dbl(t2, t2); // 8x
1286
4
    G::add(t2, t2, t1);
1287
4
    G::add(z, t2, x);
1288
4
    break;
1289
0
  }
1290
3
  case 12: {
1291
3
    G t1, t2;
1292
3
    G::dbl(t1, x);
1293
3
    G::dbl(t1, t1); // 4x
1294
3
    G::dbl(t2, t1); // 8x
1295
3
    G::add(z, t1, t2);
1296
3
    break;
1297
0
  }
1298
3
  case 13: {
1299
3
    G t1, t2;
1300
3
    G::dbl(t1, x);
1301
3
    G::dbl(t1, t1); // 4x
1302
3
    G::dbl(t2, t1); // 8x
1303
3
    G::add(t1, t1, t2); // 12x
1304
3
    G::add(z, t1, x);
1305
3
    break;
1306
0
  }
1307
7
  case 14: {
1308
7
    G t;
1309
    // (8 - 1) * 2
1310
7
    G::dbl(t, x);
1311
7
    G::dbl(t, t);
1312
7
    G::dbl(t, t);
1313
7
    G::sub(t, t, x);
1314
7
    G::dbl(z, t);
1315
7
    break;
1316
0
  }
1317
6
  case 15: {
1318
6
    G t;
1319
6
    G::dbl(t, x);
1320
6
    G::dbl(t, t);
1321
6
    G::dbl(t, t);
1322
6
    G::dbl(t, t);
1323
6
    G::sub(z, t, x);
1324
6
    break;
1325
0
  }
1326
4
  case 16: {
1327
4
    G::dbl(z, x);
1328
4
    G::dbl(z, z);
1329
4
    G::dbl(z, z);
1330
4
    G::dbl(z, z);
1331
4
    break;
1332
0
  }
1333
2.88k
  default:
1334
2.88k
    return false;
1335
3.11k
  }
1336
222
  if (isNegative) {
1337
0
    G::neg(z, z);
1338
0
  }
1339
222
  return true;
1340
3.11k
}
Unexecuted instantiation: bool mcl::ec::mulSmallInt<mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const&, unsigned long, bool)
1341
1342
/*
1343
  z += xVec[i] * yVec[i] for i = 0, ..., min(N, n)
1344
  splitN = 2(G1) or 4(G2)
1345
  w : window size
1346
  for n <= 16
1347
*/
1348
template<class GLV, class G, int w>
1349
static void mulVecGLVsmall(G& z, const G *xVec, const void* yVec, size_t n)
1350
4.43k
{
1351
4.43k
  assert(n <= mcl::fp::maxMulVecNGLV);
1352
4.43k
  const int splitN = GLV::splitN;
1353
4.43k
  const size_t tblSize = 1 << (w - 2);
1354
4.43k
  typedef typename GLV::Fr F;
1355
4.43k
  fp::getMpzAtType getMpzAt = fp::getMpzAtT<F>;
1356
4.43k
  typedef mcl::FixedArray<int8_t, sizeof(typename GLV::Fr) * 8 / splitN + splitN> NafArray;
1357
4.43k
  NafArray (*naf)[splitN] = (NafArray (*)[splitN])CYBOZU_ALLOCA(sizeof(NafArray) * n * splitN);
1358
  // layout tbl[splitN][n][tblSize];
1359
4.43k
  G (*tbl)[tblSize] = (G (*)[tblSize])CYBOZU_ALLOCA(sizeof(G) * splitN * n * tblSize);
1360
4.43k
  mpz_class u[splitN], y;
1361
4.43k
  size_t maxBit = 0;
1362
1363
8.42k
  for (size_t i = 0; i < n; i++) {
1364
4.43k
    getMpzAt(y, yVec, i);
1365
4.43k
    if (n == 1) {
1366
4.43k
      const Unit *y0 = mcl::gmp::getUnit(y);
1367
4.43k
      size_t yn = mcl::gmp::getUnitSize(y);
1368
4.43k
      yn = bint::getRealSize(y0, yn);
1369
4.43k
      if (yn <= 1 && mulSmallInt(z, xVec[0], *y0, false)) return;
1370
4.43k
    }
1371
3.98k
    GLV::split(u, y);
1372
1373
13.5k
    for (int j = 0; j < splitN; j++) {
1374
9.53k
      bool b;
1375
9.53k
      gmp::getNAFwidth(&b, naf[i][j], u[j], w);
1376
9.53k
      assert(b); (void)b;
1377
9.53k
      if (naf[i][j].size() > maxBit) maxBit = naf[i][j].size();
1378
9.53k
    }
1379
1380
3.98k
    G P2;
1381
3.98k
    G::dbl(P2, xVec[i]);
1382
3.98k
    tbl[0 * n + i][0] = xVec[i];
1383
31.9k
    for (size_t j = 1; j < tblSize; j++) {
1384
27.9k
      G::add(tbl[0 * n + i][j], tbl[0 * n + i][j - 1], P2);
1385
27.9k
    }
1386
3.98k
  }
1387
3.98k
  G::normalizeVec(&tbl[0][0], &tbl[0][0], n * tblSize);
1388
7.97k
  for (size_t i = 0; i < n; i++) {
1389
9.53k
    for (int k = 1; k < splitN; k++) {
1390
5.54k
      GLV::mulLambda(tbl[k * n + i][0], tbl[(k - 1) * n + i][0]);
1391
5.54k
    }
1392
31.9k
    for (size_t j = 1; j < tblSize; j++) {
1393
66.7k
      for (int k = 1; k < splitN; k++) {
1394
38.8k
        GLV::mulLambda(tbl[k * n + i][j], tbl[(k - 1) * n + i][j]);
1395
38.8k
      }
1396
27.9k
    }
1397
3.98k
  }
1398
3.98k
  z.clear();
1399
256k
  for (size_t i = 0; i < maxBit; i++) {
1400
252k
    const size_t bit = maxBit - 1 - i;
1401
252k
    G::dbl(z, z);
1402
504k
    for (size_t j = 0; j < n; j++) {
1403
822k
      for (int k = 0; k < splitN; k++) {
1404
569k
        local::addTbl(z, tbl[k * n + j], naf[j][k], bit);
1405
569k
      }
1406
252k
    }
1407
252k
  }
1408
3.98k
}
module.cpp:void mcl::ec::mulVecGLVsmall<mcl::bn::local::GLV1, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, 5>(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long)
Line
Count
Source
1350
3.42k
{
1351
3.42k
  assert(n <= mcl::fp::maxMulVecNGLV);
1352
3.42k
  const int splitN = GLV::splitN;
1353
3.42k
  const size_t tblSize = 1 << (w - 2);
1354
3.42k
  typedef typename GLV::Fr F;
1355
3.42k
  fp::getMpzAtType getMpzAt = fp::getMpzAtT<F>;
1356
3.42k
  typedef mcl::FixedArray<int8_t, sizeof(typename GLV::Fr) * 8 / splitN + splitN> NafArray;
1357
3.42k
  NafArray (*naf)[splitN] = (NafArray (*)[splitN])CYBOZU_ALLOCA(sizeof(NafArray) * n * splitN);
1358
  // layout tbl[splitN][n][tblSize];
1359
3.42k
  G (*tbl)[tblSize] = (G (*)[tblSize])CYBOZU_ALLOCA(sizeof(G) * splitN * n * tblSize);
1360
3.42k
  mpz_class u[splitN], y;
1361
3.42k
  size_t maxBit = 0;
1362
1363
6.63k
  for (size_t i = 0; i < n; i++) {
1364
3.42k
    getMpzAt(y, yVec, i);
1365
3.42k
    if (n == 1) {
1366
3.42k
      const Unit *y0 = mcl::gmp::getUnit(y);
1367
3.42k
      size_t yn = mcl::gmp::getUnitSize(y);
1368
3.42k
      yn = bint::getRealSize(y0, yn);
1369
3.42k
      if (yn <= 1 && mulSmallInt(z, xVec[0], *y0, false)) return;
1370
3.42k
    }
1371
3.21k
    GLV::split(u, y);
1372
1373
9.63k
    for (int j = 0; j < splitN; j++) {
1374
6.42k
      bool b;
1375
6.42k
      gmp::getNAFwidth(&b, naf[i][j], u[j], w);
1376
6.42k
      assert(b); (void)b;
1377
6.42k
      if (naf[i][j].size() > maxBit) maxBit = naf[i][j].size();
1378
6.42k
    }
1379
1380
3.21k
    G P2;
1381
3.21k
    G::dbl(P2, xVec[i]);
1382
3.21k
    tbl[0 * n + i][0] = xVec[i];
1383
25.6k
    for (size_t j = 1; j < tblSize; j++) {
1384
22.4k
      G::add(tbl[0 * n + i][j], tbl[0 * n + i][j - 1], P2);
1385
22.4k
    }
1386
3.21k
  }
1387
3.21k
  G::normalizeVec(&tbl[0][0], &tbl[0][0], n * tblSize);
1388
6.42k
  for (size_t i = 0; i < n; i++) {
1389
6.42k
    for (int k = 1; k < splitN; k++) {
1390
3.21k
      GLV::mulLambda(tbl[k * n + i][0], tbl[(k - 1) * n + i][0]);
1391
3.21k
    }
1392
25.6k
    for (size_t j = 1; j < tblSize; j++) {
1393
44.9k
      for (int k = 1; k < splitN; k++) {
1394
22.4k
        GLV::mulLambda(tbl[k * n + i][j], tbl[(k - 1) * n + i][j]);
1395
22.4k
      }
1396
22.4k
    }
1397
3.21k
  }
1398
3.21k
  z.clear();
1399
223k
  for (size_t i = 0; i < maxBit; i++) {
1400
220k
    const size_t bit = maxBit - 1 - i;
1401
220k
    G::dbl(z, z);
1402
440k
    for (size_t j = 0; j < n; j++) {
1403
660k
      for (int k = 0; k < splitN; k++) {
1404
440k
        local::addTbl(z, tbl[k * n + j], naf[j][k], bit);
1405
440k
      }
1406
220k
    }
1407
220k
  }
1408
3.21k
}
module.cpp:void mcl::ec::mulVecGLVsmall<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, 5>(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long)
Line
Count
Source
1350
1.00k
{
1351
1.00k
  assert(n <= mcl::fp::maxMulVecNGLV);
1352
1.00k
  const int splitN = GLV::splitN;
1353
1.00k
  const size_t tblSize = 1 << (w - 2);
1354
1.00k
  typedef typename GLV::Fr F;
1355
1.00k
  fp::getMpzAtType getMpzAt = fp::getMpzAtT<F>;
1356
1.00k
  typedef mcl::FixedArray<int8_t, sizeof(typename GLV::Fr) * 8 / splitN + splitN> NafArray;
1357
1.00k
  NafArray (*naf)[splitN] = (NafArray (*)[splitN])CYBOZU_ALLOCA(sizeof(NafArray) * n * splitN);
1358
  // layout tbl[splitN][n][tblSize];
1359
1.00k
  G (*tbl)[tblSize] = (G (*)[tblSize])CYBOZU_ALLOCA(sizeof(G) * splitN * n * tblSize);
1360
1.00k
  mpz_class u[splitN], y;
1361
1.00k
  size_t maxBit = 0;
1362
1363
1.78k
  for (size_t i = 0; i < n; i++) {
1364
1.00k
    getMpzAt(y, yVec, i);
1365
1.00k
    if (n == 1) {
1366
1.00k
      const Unit *y0 = mcl::gmp::getUnit(y);
1367
1.00k
      size_t yn = mcl::gmp::getUnitSize(y);
1368
1.00k
      yn = bint::getRealSize(y0, yn);
1369
1.00k
      if (yn <= 1 && mulSmallInt(z, xVec[0], *y0, false)) return;
1370
1.00k
    }
1371
778
    GLV::split(u, y);
1372
1373
3.89k
    for (int j = 0; j < splitN; j++) {
1374
3.11k
      bool b;
1375
3.11k
      gmp::getNAFwidth(&b, naf[i][j], u[j], w);
1376
3.11k
      assert(b); (void)b;
1377
3.11k
      if (naf[i][j].size() > maxBit) maxBit = naf[i][j].size();
1378
3.11k
    }
1379
1380
778
    G P2;
1381
778
    G::dbl(P2, xVec[i]);
1382
778
    tbl[0 * n + i][0] = xVec[i];
1383
6.22k
    for (size_t j = 1; j < tblSize; j++) {
1384
5.44k
      G::add(tbl[0 * n + i][j], tbl[0 * n + i][j - 1], P2);
1385
5.44k
    }
1386
778
  }
1387
778
  G::normalizeVec(&tbl[0][0], &tbl[0][0], n * tblSize);
1388
1.55k
  for (size_t i = 0; i < n; i++) {
1389
3.11k
    for (int k = 1; k < splitN; k++) {
1390
2.33k
      GLV::mulLambda(tbl[k * n + i][0], tbl[(k - 1) * n + i][0]);
1391
2.33k
    }
1392
6.22k
    for (size_t j = 1; j < tblSize; j++) {
1393
21.7k
      for (int k = 1; k < splitN; k++) {
1394
16.3k
        GLV::mulLambda(tbl[k * n + i][j], tbl[(k - 1) * n + i][j]);
1395
16.3k
      }
1396
5.44k
    }
1397
778
  }
1398
778
  z.clear();
1399
33.1k
  for (size_t i = 0; i < maxBit; i++) {
1400
32.3k
    const size_t bit = maxBit - 1 - i;
1401
32.3k
    G::dbl(z, z);
1402
64.7k
    for (size_t j = 0; j < n; j++) {
1403
161k
      for (int k = 0; k < splitN; k++) {
1404
129k
        local::addTbl(z, tbl[k * n + j], naf[j][k], bit);
1405
129k
      }
1406
32.3k
    }
1407
32.3k
  }
1408
778
}
Unexecuted instantiation: module.cpp:void mcl::ec::mulVecGLVsmall<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >, 5>(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const*, void const*, unsigned long)
Unexecuted instantiation: module.cpp:void mcl::ec::mulVecGLVsmall<mcl::GLV1T<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, 5>(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long)
1409
1410
// return false if malloc fails or n is not in a target range
1411
template<class GLV, class G, class F>
1412
bool mulVecGLVT(G& z, const G *xVec, const void *yVec, size_t n, bool constTime = false, size_t b = 0)
1413
4.43k
{
1414
4.43k
  if (n == 1 && constTime) {
1415
0
    local::mulGLV_CT<GLV, G>(z, xVec[0], yVec);
1416
0
    return true;
1417
0
  }
1418
4.43k
  if (n <= mcl::fp::maxMulVecNGLV) {
1419
4.43k
    mulVecGLVsmall<GLV, G, 5>(z, xVec, yVec, n);
1420
4.43k
    return true;
1421
4.43k
  }
1422
0
  if (n >= 128) {
1423
0
    return mulVecGLVlarge<GLV, G>(z, xVec, yVec, n, b);
1424
0
  }
1425
0
  return false;
1426
0
}
bool mcl::ec::mulVecGLVT<mcl::bn::local::GLV1, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, bool, unsigned long)
Line
Count
Source
1413
3.42k
{
1414
3.42k
  if (n == 1 && constTime) {
1415
0
    local::mulGLV_CT<GLV, G>(z, xVec[0], yVec);
1416
0
    return true;
1417
0
  }
1418
3.42k
  if (n <= mcl::fp::maxMulVecNGLV) {
1419
3.42k
    mulVecGLVsmall<GLV, G, 5>(z, xVec, yVec, n);
1420
3.42k
    return true;
1421
3.42k
  }
1422
0
  if (n >= 128) {
1423
0
    return mulVecGLVlarge<GLV, G>(z, xVec, yVec, n, b);
1424
0
  }
1425
0
  return false;
1426
0
}
bool mcl::ec::mulVecGLVT<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, bool, unsigned long)
Line
Count
Source
1413
1.00k
{
1414
1.00k
  if (n == 1 && constTime) {
1415
0
    local::mulGLV_CT<GLV, G>(z, xVec[0], yVec);
1416
0
    return true;
1417
0
  }
1418
1.00k
  if (n <= mcl::fp::maxMulVecNGLV) {
1419
1.00k
    mulVecGLVsmall<GLV, G, 5>(z, xVec, yVec, n);
1420
1.00k
    return true;
1421
1.00k
  }
1422
0
  if (n >= 128) {
1423
0
    return mulVecGLVlarge<GLV, G>(z, xVec, yVec, n, b);
1424
0
  }
1425
0
  return false;
1426
0
}
Unexecuted instantiation: bool mcl::ec::mulVecGLVT<mcl::bn::local::GLV2T<mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > >&, mcl::GroupMtoA<mcl::Fp12T<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > > const*, void const*, unsigned long, bool, unsigned long)
Unexecuted instantiation: bool mcl::ec::mulVecGLVT<mcl::GLV1T<mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, bool, unsigned long)
1427
1428
} // mcl::ec
1429
1430
/*
1431
  elliptic curve
1432
  y^2 = x^3 + ax + b (affine)
1433
  y^2 = x^3 + az^4 + bz^6 (Jacobi) x = X/Z^2, y = Y/Z^3
1434
*/
1435
template<class _Fp, class _Fr>
1436
class EcT : public fp::Serializable<EcT<_Fp, _Fr> > {
1437
public:
1438
  typedef _Fp Fp; // definition field
1439
  typedef _Fr Fr; // group order
1440
  typedef _Fp BaseFp;
1441
  Fp x, y, z;
1442
  static int mode_;
1443
  static Fp a_;
1444
  static Fp b_;
1445
  static Fp b3_;
1446
  static int specialA_;
1447
  static int specialB_;
1448
  static int ioMode_;
1449
  /*
1450
    order_ is the order of G2 which is the subgroup of EcT<Fp2, Fr>.
1451
    check the order of the elements if verifyOrder_ is true
1452
  */
1453
  static bool verifyOrder_;
1454
  static mpz_class order_;
1455
  static bool (*mulVecGLV)(EcT& z, const EcT *xVec, const void *yVec, size_t n, bool constTime, size_t b);
1456
  static void (*mulVecOpti)(Unit *z, Unit *xVec, const Unit *yVec, size_t n, size_t b);
1457
  static void (*mulEachOpti)(Unit *xVec, const Unit *yVec, size_t n);
1458
  static bool (*isValidOrderFast)(const EcT& x);
1459
  /* default constructor is undefined value */
1460
160k
  EcT() {}
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::EcT()
Line
Count
Source
1460
41.1k
  EcT() {}
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::EcT()
Line
Count
Source
1460
119k
  EcT() {}
1461
  EcT(const Fp& _x, const Fp& _y)
1462
27.7k
  {
1463
27.7k
    set(_x, _y);
1464
27.7k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::EcT(mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&)
Line
Count
Source
1462
13.2k
  {
1463
13.2k
    set(_x, _y);
1464
13.2k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::EcT(mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&)
Line
Count
Source
1462
14.4k
  {
1463
14.4k
    set(_x, _y);
1464
14.4k
  }
1465
  bool isNormalized() const
1466
  {
1467
    return isZero() || z.isOne();
1468
  }
1469
private:
1470
  bool isValidAffine() const
1471
27.7k
  {
1472
27.7k
    return ec::isValidAffine(*this);
1473
27.7k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValidAffine() const
Line
Count
Source
1471
13.2k
  {
1472
13.2k
    return ec::isValidAffine(*this);
1473
13.2k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValidAffine() const
Line
Count
Source
1471
14.4k
  {
1472
14.4k
    return ec::isValidAffine(*this);
1473
14.4k
  }
1474
public:
1475
  void normalize()
1476
10.3k
  {
1477
10.3k
    switch (mode_) {
1478
10.3k
    case ec::Jacobi:
1479
10.3k
      ec::normalizeJacobi(*this);
1480
10.3k
      break;
1481
0
    case ec::Proj:
1482
0
      ec::normalizeProj(*this);
1483
0
      break;
1484
10.3k
    }
1485
10.3k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalize()
Line
Count
Source
1476
2.72k
  {
1477
2.72k
    switch (mode_) {
1478
2.72k
    case ec::Jacobi:
1479
2.72k
      ec::normalizeJacobi(*this);
1480
2.72k
      break;
1481
0
    case ec::Proj:
1482
0
      ec::normalizeProj(*this);
1483
0
      break;
1484
2.72k
    }
1485
2.72k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalize()
Line
Count
Source
1476
7.57k
  {
1477
7.57k
    switch (mode_) {
1478
7.57k
    case ec::Jacobi:
1479
7.57k
      ec::normalizeJacobi(*this);
1480
7.57k
      break;
1481
0
    case ec::Proj:
1482
0
      ec::normalizeProj(*this);
1483
0
      break;
1484
7.57k
    }
1485
7.57k
  }
1486
  static void normalize(EcT& y, const EcT& x)
1487
33
  {
1488
33
    y = x;
1489
33
    y.normalize();
1490
33
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalize(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1487
21
  {
1488
21
    y = x;
1489
21
    y.normalize();
1490
21
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalize(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1487
12
  {
1488
12
    y = x;
1489
12
    y.normalize();
1490
12
  }
1491
  static void normalizeVec(EcT *y, const EcT *x, size_t n)
1492
3.98k
  {
1493
3.98k
    if (mode_ == ec::Affine) {
1494
0
      if (y == x) return;
1495
0
      for (size_t i = 0; i < n; i++) {
1496
0
        y[i] = x[i];
1497
0
      }
1498
0
      return;
1499
0
    }
1500
3.98k
    ec::normalizeVec(y, x, n);
1501
3.98k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalizeVec(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long)
Line
Count
Source
1492
3.21k
  {
1493
3.21k
    if (mode_ == ec::Affine) {
1494
0
      if (y == x) return;
1495
0
      for (size_t i = 0; i < n; i++) {
1496
0
        y[i] = x[i];
1497
0
      }
1498
0
      return;
1499
0
    }
1500
3.21k
    ec::normalizeVec(y, x, n);
1501
3.21k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::normalizeVec(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >*, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, unsigned long)
Line
Count
Source
1492
778
  {
1493
778
    if (mode_ == ec::Affine) {
1494
0
      if (y == x) return;
1495
0
      for (size_t i = 0; i < n; i++) {
1496
0
        y[i] = x[i];
1497
0
      }
1498
0
      return;
1499
0
    }
1500
778
    ec::normalizeVec(y, x, n);
1501
778
  }
1502
  static inline void init(const Fp& a, const Fp& b, int mode = ec::Jacobi)
1503
8
  {
1504
8
    a_ = a;
1505
8
    b_ = b;
1506
8
    b3_ = b * 3;
1507
8
    if (a_.isZero()) {
1508
8
      specialA_ = ec::local::Zero;
1509
8
    } else if (a_ == -3) {
1510
0
      specialA_ = ec::local::Minus3;
1511
0
    } else {
1512
0
      specialA_ = ec::local::GenericA;
1513
0
    }
1514
8
    if (b_ == 1) {
1515
0
      specialB_ = ec::local::Plus1;
1516
0
    } else
1517
8
    if (b_ == 4) {
1518
4
      specialB_ = ec::local::Plus4;
1519
4
    } else
1520
4
    {
1521
4
      specialB_ = ec::local::GenericB;
1522
4
    }
1523
8
    ioMode_ = 0;
1524
8
    verifyOrder_ = false;
1525
8
    order_ = 0;
1526
8
    mulVecGLV = 0;
1527
8
    mulVecOpti = 0;
1528
8
    mulEachOpti = 0;
1529
8
    isValidOrderFast = 0;
1530
8
    mode_ = mode;
1531
8
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::init(mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, int)
Line
Count
Source
1503
4
  {
1504
4
    a_ = a;
1505
4
    b_ = b;
1506
4
    b3_ = b * 3;
1507
4
    if (a_.isZero()) {
1508
4
      specialA_ = ec::local::Zero;
1509
4
    } else if (a_ == -3) {
1510
0
      specialA_ = ec::local::Minus3;
1511
0
    } else {
1512
0
      specialA_ = ec::local::GenericA;
1513
0
    }
1514
4
    if (b_ == 1) {
1515
0
      specialB_ = ec::local::Plus1;
1516
0
    } else
1517
4
    if (b_ == 4) {
1518
4
      specialB_ = ec::local::Plus4;
1519
4
    } else
1520
0
    {
1521
0
      specialB_ = ec::local::GenericB;
1522
0
    }
1523
4
    ioMode_ = 0;
1524
4
    verifyOrder_ = false;
1525
4
    order_ = 0;
1526
4
    mulVecGLV = 0;
1527
4
    mulVecOpti = 0;
1528
4
    mulEachOpti = 0;
1529
4
    isValidOrderFast = 0;
1530
4
    mode_ = mode;
1531
4
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::init(mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, int)
Line
Count
Source
1503
4
  {
1504
4
    a_ = a;
1505
4
    b_ = b;
1506
4
    b3_ = b * 3;
1507
4
    if (a_.isZero()) {
1508
4
      specialA_ = ec::local::Zero;
1509
4
    } else if (a_ == -3) {
1510
0
      specialA_ = ec::local::Minus3;
1511
0
    } else {
1512
0
      specialA_ = ec::local::GenericA;
1513
0
    }
1514
4
    if (b_ == 1) {
1515
0
      specialB_ = ec::local::Plus1;
1516
0
    } else
1517
4
    if (b_ == 4) {
1518
0
      specialB_ = ec::local::Plus4;
1519
0
    } else
1520
4
    {
1521
4
      specialB_ = ec::local::GenericB;
1522
4
    }
1523
4
    ioMode_ = 0;
1524
4
    verifyOrder_ = false;
1525
4
    order_ = 0;
1526
4
    mulVecGLV = 0;
1527
4
    mulVecOpti = 0;
1528
4
    mulEachOpti = 0;
1529
4
    isValidOrderFast = 0;
1530
4
    mode_ = mode;
1531
4
  }
1532
  static inline int getMode() { return mode_; }
1533
  /*
1534
    verify the order of *this is equal to order if order != 0
1535
    in constructor, set, setStr, operator<<().
1536
  */
1537
  static void setOrder(const mpz_class& order)
1538
24
  {
1539
24
    if (order != 0) {
1540
16
      verifyOrder_ = true;
1541
16
      order_ = order;
1542
16
    } else {
1543
8
      verifyOrder_ = false;
1544
      // don't clear order_ because it is used for isValidOrder()
1545
8
    }
1546
24
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setOrder(mcl::Vint const&)
Line
Count
Source
1538
12
  {
1539
12
    if (order != 0) {
1540
8
      verifyOrder_ = true;
1541
8
      order_ = order;
1542
8
    } else {
1543
4
      verifyOrder_ = false;
1544
      // don't clear order_ because it is used for isValidOrder()
1545
4
    }
1546
12
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setOrder(mcl::Vint const&)
Line
Count
Source
1538
12
  {
1539
12
    if (order != 0) {
1540
8
      verifyOrder_ = true;
1541
8
      order_ = order;
1542
8
    } else {
1543
4
      verifyOrder_ = false;
1544
      // don't clear order_ because it is used for isValidOrder()
1545
4
    }
1546
12
  }
1547
  static void setVerifyOrderFunc(bool f(const EcT&))
1548
8
  {
1549
8
    isValidOrderFast = f;
1550
8
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setVerifyOrderFunc(bool (*)(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&))
Line
Count
Source
1548
4
  {
1549
4
    isValidOrderFast = f;
1550
4
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setVerifyOrderFunc(bool (*)(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&))
Line
Count
Source
1548
4
  {
1549
4
    isValidOrderFast = f;
1550
4
  }
1551
  static void setMulVecGLV(bool f(EcT& z, const EcT *xVec, const void *yVec, size_t yn, bool constTime, size_t b))
1552
8
  {
1553
8
    mulVecGLV = f;
1554
8
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setMulVecGLV(bool (*)(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, bool, unsigned long))
Line
Count
Source
1552
4
  {
1553
4
    mulVecGLV = f;
1554
4
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setMulVecGLV(bool (*)(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const*, void const*, unsigned long, bool, unsigned long))
Line
Count
Source
1552
4
  {
1553
4
    mulVecGLV = f;
1554
4
  }
1555
  static void setMulVecOpti(void f(Unit* _z, Unit *_xVec, const Unit *_yVec, size_t yn, size_t b))
1556
0
  {
1557
0
    mulVecOpti = f;
1558
0
  }
1559
  static void setMulEachOpti(void f(Unit *_xVec, const Unit *_yVec, size_t yn))
1560
0
  {
1561
0
    mulEachOpti = f;
1562
0
  }
1563
  static inline void init(bool *pb, const char *astr, const char *bstr, int mode = ec::Jacobi)
1564
0
  {
1565
0
    Fp a, b;
1566
0
    a.setStr(pb, astr);
1567
0
    if (!*pb) return;
1568
0
    b.setStr(pb, bstr);
1569
0
    if (!*pb) return;
1570
0
    init(a, b, mode);
1571
0
  }
1572
  // verify the order
1573
  bool isValidOrder() const
1574
4.92k
  {
1575
4.92k
    if (isValidOrderFast) {
1576
4.92k
      return isValidOrderFast(*this);
1577
4.92k
    }
1578
0
    EcT Q;
1579
0
    EcT::mulGeneric(Q, *this, order_);
1580
0
    return Q.isZero();
1581
4.92k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValidOrder() const
Line
Count
Source
1574
3.97k
  {
1575
3.97k
    if (isValidOrderFast) {
1576
3.97k
      return isValidOrderFast(*this);
1577
3.97k
    }
1578
0
    EcT Q;
1579
0
    EcT::mulGeneric(Q, *this, order_);
1580
0
    return Q.isZero();
1581
3.97k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValidOrder() const
Line
Count
Source
1574
952
  {
1575
952
    if (isValidOrderFast) {
1576
952
      return isValidOrderFast(*this);
1577
952
    }
1578
0
    EcT Q;
1579
0
    EcT::mulGeneric(Q, *this, order_);
1580
0
    return Q.isZero();
1581
952
  }
1582
  bool isValid() const
1583
378
  {
1584
378
    switch (mode_) {
1585
378
    case ec::Jacobi:
1586
378
      if (!ec::isValidJacobi(*this)) return false;
1587
372
      break;
1588
372
    case ec::Proj:
1589
0
      if (!ec::isValidProj(*this)) return false;
1590
0
      break;
1591
0
    case ec::Affine:
1592
0
      if (z.isZero()) return true;
1593
0
      if (!isValidAffine()) return false;
1594
0
      break;
1595
378
    }
1596
372
    if (verifyOrder_) return isValidOrder();
1597
0
    return true;
1598
372
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValid() const
Line
Count
Source
1583
213
  {
1584
213
    switch (mode_) {
1585
213
    case ec::Jacobi:
1586
213
      if (!ec::isValidJacobi(*this)) return false;
1587
207
      break;
1588
207
    case ec::Proj:
1589
0
      if (!ec::isValidProj(*this)) return false;
1590
0
      break;
1591
0
    case ec::Affine:
1592
0
      if (z.isZero()) return true;
1593
0
      if (!isValidAffine()) return false;
1594
0
      break;
1595
213
    }
1596
207
    if (verifyOrder_) return isValidOrder();
1597
0
    return true;
1598
207
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isValid() const
Line
Count
Source
1583
165
  {
1584
165
    switch (mode_) {
1585
165
    case ec::Jacobi:
1586
165
      if (!ec::isValidJacobi(*this)) return false;
1587
165
      break;
1588
165
    case ec::Proj:
1589
0
      if (!ec::isValidProj(*this)) return false;
1590
0
      break;
1591
0
    case ec::Affine:
1592
0
      if (z.isZero()) return true;
1593
0
      if (!isValidAffine()) return false;
1594
0
      break;
1595
165
    }
1596
165
    if (verifyOrder_) return isValidOrder();
1597
0
    return true;
1598
165
  }
1599
  void set(bool *pb, const Fp& x, const Fp& y, bool verify = true)
1600
27.7k
  {
1601
27.7k
    this->x = x;
1602
27.7k
    this->y = y;
1603
27.7k
    z = 1;
1604
27.7k
    if (!verify || (isValidAffine() && (!verifyOrder_ || isValidOrder()))) {
1605
4.34k
      *pb = true;
1606
4.34k
      return;
1607
4.34k
    }
1608
23.3k
    *pb = false;
1609
23.3k
    clear();
1610
23.3k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::set(bool*, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, bool)
Line
Count
Source
1600
13.2k
  {
1601
13.2k
    this->x = x;
1602
13.2k
    this->y = y;
1603
13.2k
    z = 1;
1604
13.2k
    if (!verify || (isValidAffine() && (!verifyOrder_ || isValidOrder()))) {
1605
3.59k
      *pb = true;
1606
3.59k
      return;
1607
3.59k
    }
1608
9.70k
    *pb = false;
1609
9.70k
    clear();
1610
9.70k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::set(bool*, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, bool)
Line
Count
Source
1600
14.4k
  {
1601
14.4k
    this->x = x;
1602
14.4k
    this->y = y;
1603
14.4k
    z = 1;
1604
14.4k
    if (!verify || (isValidAffine() && (!verifyOrder_ || isValidOrder()))) {
1605
751
      *pb = true;
1606
751
      return;
1607
751
    }
1608
13.6k
    *pb = false;
1609
13.6k
    clear();
1610
13.6k
  }
1611
  void clear()
1612
63.4k
  {
1613
63.4k
    if (mode_ == ec::Jacobi) {
1614
63.4k
      x = 0;
1615
63.4k
      y = 0;
1616
63.4k
      z.clear();
1617
63.4k
    } else { // ec::Proj
1618
0
      x.clear();
1619
0
      y = 1;
1620
0
      z.clear();
1621
0
    }
1622
63.4k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::clear()
Line
Count
Source
1612
42.3k
  {
1613
42.3k
    if (mode_ == ec::Jacobi) {
1614
42.3k
      x = 0;
1615
42.3k
      y = 0;
1616
42.3k
      z.clear();
1617
42.3k
    } else { // ec::Proj
1618
0
      x.clear();
1619
0
      y = 1;
1620
0
      z.clear();
1621
0
    }
1622
42.3k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::clear()
Line
Count
Source
1612
21.0k
  {
1613
21.0k
    if (mode_ == ec::Jacobi) {
1614
21.0k
      x = 0;
1615
21.0k
      y = 0;
1616
21.0k
      z.clear();
1617
21.0k
    } else { // ec::Proj
1618
0
      x.clear();
1619
0
      y = 1;
1620
0
      z.clear();
1621
0
    }
1622
21.0k
  }
1623
  static inline void clear(EcT& P)
1624
0
  {
1625
0
    P.clear();
1626
0
  }
1627
  static inline void dbl(EcT& R, const EcT& P)
1628
938k
  {
1629
938k
    switch (mode_) {
1630
938k
    case ec::Jacobi:
1631
938k
      ec::dblJacobi(R, P);
1632
938k
      break;
1633
0
    case ec::Proj:
1634
0
      ec::dblProj(R, P);
1635
0
      break;
1636
0
    case ec::Affine:
1637
0
      ec::dblAffine(R, P);
1638
0
      break;
1639
938k
    }
1640
938k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::dbl(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1628
181k
  {
1629
181k
    switch (mode_) {
1630
181k
    case ec::Jacobi:
1631
181k
      ec::dblJacobi(R, P);
1632
181k
      break;
1633
0
    case ec::Proj:
1634
0
      ec::dblProj(R, P);
1635
0
      break;
1636
0
    case ec::Affine:
1637
0
      ec::dblAffine(R, P);
1638
0
      break;
1639
181k
    }
1640
181k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::dbl(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1628
757k
  {
1629
757k
    switch (mode_) {
1630
757k
    case ec::Jacobi:
1631
757k
      ec::dblJacobi(R, P);
1632
757k
      break;
1633
0
    case ec::Proj:
1634
0
      ec::dblProj(R, P);
1635
0
      break;
1636
0
    case ec::Affine:
1637
0
      ec::dblAffine(R, P);
1638
0
      break;
1639
757k
    }
1640
757k
  }
1641
  static inline void add(EcT& R, const EcT& P, const EcT& Q)
1642
219k
  {
1643
219k
    switch (mode_) {
1644
219k
    case ec::Jacobi:
1645
219k
      ec::addJacobi(R, P, Q);
1646
219k
      break;
1647
0
    case ec::Proj:
1648
0
      ec::addProj(R, P, Q);
1649
0
      break;
1650
0
    case ec::Affine:
1651
0
      ec::addAffine(R, P, Q);
1652
0
      break;
1653
219k
    }
1654
219k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::add(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1642
34.9k
  {
1643
34.9k
    switch (mode_) {
1644
34.9k
    case ec::Jacobi:
1645
34.9k
      ec::addJacobi(R, P, Q);
1646
34.9k
      break;
1647
0
    case ec::Proj:
1648
0
      ec::addProj(R, P, Q);
1649
0
      break;
1650
0
    case ec::Affine:
1651
0
      ec::addAffine(R, P, Q);
1652
0
      break;
1653
34.9k
    }
1654
34.9k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::add(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1642
184k
  {
1643
184k
    switch (mode_) {
1644
184k
    case ec::Jacobi:
1645
184k
      ec::addJacobi(R, P, Q);
1646
184k
      break;
1647
0
    case ec::Proj:
1648
0
      ec::addProj(R, P, Q);
1649
0
      break;
1650
0
    case ec::Affine:
1651
0
      ec::addAffine(R, P, Q);
1652
0
      break;
1653
184k
    }
1654
184k
  }
1655
  static inline void sub(EcT& R, const EcT& P, const EcT& Q)
1656
79.3k
  {
1657
79.3k
    EcT nQ;
1658
79.3k
    neg(nQ, Q);
1659
79.3k
    add(R, P, nQ);
1660
79.3k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::sub(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1656
65.2k
  {
1657
65.2k
    EcT nQ;
1658
65.2k
    neg(nQ, Q);
1659
65.2k
    add(R, P, nQ);
1660
65.2k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::sub(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1656
14.0k
  {
1657
14.0k
    EcT nQ;
1658
14.0k
    neg(nQ, Q);
1659
14.0k
    add(R, P, nQ);
1660
14.0k
  }
1661
  static inline void neg(EcT& R, const EcT& P)
1662
79.3k
  {
1663
79.3k
    if (P.isZero()) {
1664
1.08k
      R.clear();
1665
1.08k
      return;
1666
1.08k
    }
1667
78.2k
    R.x = P.x;
1668
78.2k
    Fp::neg(R.y, P.y);
1669
78.2k
    R.z = P.z;
1670
78.2k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::neg(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1662
65.2k
  {
1663
65.2k
    if (P.isZero()) {
1664
1.01k
      R.clear();
1665
1.01k
      return;
1666
1.01k
    }
1667
64.2k
    R.x = P.x;
1668
64.2k
    Fp::neg(R.y, P.y);
1669
64.2k
    R.z = P.z;
1670
64.2k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::neg(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
1662
14.0k
  {
1663
14.0k
    if (P.isZero()) {
1664
72
      R.clear();
1665
72
      return;
1666
72
    }
1667
14.0k
    R.x = P.x;
1668
14.0k
    Fp::neg(R.y, P.y);
1669
14.0k
    R.z = P.z;
1670
14.0k
  }
1671
  static inline void mul(EcT& z, const EcT& x, const EcT::Fr& y, bool constTime = false)
1672
4.43k
  {
1673
4.43k
    if (mulVecGLV) {
1674
4.43k
      mulVecGLV(z, &x, &y, 1, constTime, 0);
1675
4.43k
      return;
1676
4.43k
    }
1677
0
    fp::Block b;
1678
0
    y.getBlock(b);
1679
0
    mulArray(z, x, b.p, b.n, false, constTime);
1680
0
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mul(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::FpT<mcl::bn::local::FrTag, 256ul> const&, bool)
Line
Count
Source
1672
3.42k
  {
1673
3.42k
    if (mulVecGLV) {
1674
3.42k
      mulVecGLV(z, &x, &y, 1, constTime, 0);
1675
3.42k
      return;
1676
3.42k
    }
1677
0
    fp::Block b;
1678
0
    y.getBlock(b);
1679
0
    mulArray(z, x, b.p, b.n, false, constTime);
1680
0
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mul(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::FpT<mcl::bn::local::FrTag, 256ul> const&, bool)
Line
Count
Source
1672
1.00k
  {
1673
1.00k
    if (mulVecGLV) {
1674
1.00k
      mulVecGLV(z, &x, &y, 1, constTime, 0);
1675
1.00k
      return;
1676
1.00k
    }
1677
0
    fp::Block b;
1678
0
    y.getBlock(b);
1679
0
    mulArray(z, x, b.p, b.n, false, constTime);
1680
0
  }
1681
  static inline void mul(EcT& z, const EcT& x, int64_t y)
1682
  {
1683
    const uint64_t u = fp::abs_(y);
1684
#if MCL_SIZEOF_UNIT == 8
1685
    const uint64_t *ua = &u;
1686
    const size_t un = 1;
1687
#else
1688
    uint32_t ua[2] = { uint32_t(u), uint32_t(u >> 32) };
1689
    const size_t un = ua[1] ? 2 : 1;
1690
#endif
1691
    mulArray(z, x, ua, un, y < 0);
1692
  }
1693
  static inline void mul(EcT& z, const EcT& x, const mpz_class& y)
1694
  {
1695
    mulArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0);
1696
  }
1697
  // not const time
1698
  static inline void mulCT(EcT& z, const EcT& x, const EcT::Fr& y)
1699
  {
1700
    mul(z, x, y, true);
1701
  }
1702
  static inline void mulCT(EcT& z, const EcT& x, const mpz_class& y)
1703
  {
1704
    mulArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0, true);
1705
  }
1706
  /*
1707
    0 <= P for any P
1708
    (Px, Py) <= (P'x, P'y) iff Px < P'x or Px == P'x and Py <= P'y
1709
    @note compare function calls normalize()
1710
  */
1711
  template<class F>
1712
  static inline int compareFunc(const EcT& P_, const EcT& Q_, F comp)
1713
  {
1714
    const bool QisZero = Q_.isZero();
1715
    if (P_.isZero()) {
1716
      if (QisZero) return 0;
1717
      return -1;
1718
    }
1719
    if (QisZero) return 1;
1720
    EcT P(P_), Q(Q_);
1721
    P.normalize();
1722
    Q.normalize();
1723
    int c = comp(P.x, Q.x);
1724
    if (c > 0) return 1;
1725
    if (c < 0) return -1;
1726
    return comp(P.y, Q.y);
1727
  }
1728
  static inline int compare(const EcT& P, const EcT& Q)
1729
  {
1730
    return compareFunc(P, Q, Fp::compare);
1731
  }
1732
  static inline int compareRaw(const EcT& P, const EcT& Q)
1733
  {
1734
    return compareFunc(P, Q, Fp::compareRaw);
1735
  }
1736
  bool isZero() const
1737
1.45M
  {
1738
1.45M
    return z.isZero();
1739
1.45M
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isZero() const
Line
Count
Source
1737
1.19M
  {
1738
1.19M
    return z.isZero();
1739
1.19M
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isZero() const
Line
Count
Source
1737
265k
  {
1738
265k
    return z.isZero();
1739
265k
  }
1740
  static inline bool isMSBserialize()
1741
0
  {
1742
0
    return !b_.isZero() && (Fp::BaseFp::getBitSize() & 7) != 0;
1743
0
  }
Unexecuted instantiation: mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isMSBserialize()
Unexecuted instantiation: mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::isMSBserialize()
1744
  // return serialized byte size
1745
  static inline size_t getSerializedByteSize()
1746
  {
1747
    const size_t n = Fp::getByteSize();
1748
    const size_t adj = isMSBserialize() ? 0 : 1;
1749
    return n + adj;
1750
  }
1751
  template<class OutputStream>
1752
  void save(bool *pb, OutputStream& os, int ioMode) const
1753
5.12k
  {
1754
5.12k
    const char sep = *fp::getIoSeparator(ioMode);
1755
5.12k
    if (ioMode & IoEcProj) {
1756
0
      cybozu::writeChar(pb, os, '4'); if (!*pb) return;
1757
0
      if (sep) {
1758
0
        cybozu::writeChar(pb, os, sep);
1759
0
        if (!*pb) return;
1760
0
      }
1761
0
      x.save(pb, os, ioMode); if (!*pb) return;
1762
0
      if (sep) {
1763
0
        cybozu::writeChar(pb, os, sep);
1764
0
        if (!*pb) return;
1765
0
      }
1766
0
      y.save(pb, os, ioMode); if (!*pb) return;
1767
0
      if (sep) {
1768
0
        cybozu::writeChar(pb, os, sep);
1769
0
        if (!*pb) return;
1770
0
      }
1771
0
      z.save(pb, os, ioMode);
1772
0
      return;
1773
0
    }
1774
5.12k
    EcT P(*this);
1775
5.12k
    P.normalize();
1776
5.12k
    if (ioMode & IoEcAffineSerialize) {
1777
0
      if (b_ == 0) { // assume Zero if x = y = 0
1778
0
        *pb = false;
1779
0
        return;
1780
0
      }
1781
0
      if (isZero()) {
1782
        // all zero
1783
0
        P.z.save(pb, os, IoSerialize);
1784
0
        if (!*pb) return;
1785
0
        P.z.save(pb, os, IoSerialize);
1786
0
        return;
1787
0
      }
1788
0
      P.x.save(pb, os, IoSerialize);
1789
0
      if (!*pb) return;
1790
0
      P.y.save(pb, os, IoSerialize);
1791
0
      return;
1792
0
    }
1793
5.12k
    if (ioMode & (IoSerialize | IoSerializeHexStr)) {
1794
0
      const size_t n = Fp::getByteSize();
1795
0
      const size_t adj = isMSBserialize() ? 0 : 1;
1796
0
      uint8_t buf[sizeof(Fp) + 1];
1797
0
      if (Fp::BaseFp::getETHserialization()) {
1798
0
        const uint8_t c_flag = 0x80;
1799
0
        const uint8_t b_flag = 0x40;
1800
0
        const uint8_t a_flag = 0x20;
1801
0
        if (P.isZero()) {
1802
0
          buf[0] = c_flag | b_flag;
1803
0
          memset(buf + 1, 0, n - 1);
1804
0
        } else {
1805
0
          cybozu::MemoryOutputStream mos(buf, n);
1806
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1807
0
          uint8_t cba = c_flag;
1808
0
          if (ec::local::get_a_flag(P.y)) cba |= a_flag;
1809
0
          buf[0] |= cba;
1810
0
        }
1811
0
      } else {
1812
        /*
1813
          if (isMSBserialize()) {
1814
            // n bytes
1815
            x | (y.isOdd ? 0x80 : 0)
1816
          } else {
1817
            // n + 1 bytes
1818
            (y.isOdd ? 3 : 2), x
1819
          }
1820
        */
1821
0
        if (isZero()) {
1822
0
          memset(buf, 0, n + adj);
1823
0
        } else {
1824
0
          cybozu::MemoryOutputStream mos(buf + adj, n);
1825
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1826
0
          if (adj) {
1827
0
            buf[0] = P.y.isOdd() ? 3 : 2;
1828
0
          } else {
1829
0
            if (P.y.isOdd()) {
1830
0
              buf[n - 1] |= 0x80;
1831
0
            }
1832
0
          }
1833
0
        }
1834
0
      }
1835
0
      if (ioMode & IoSerializeHexStr) {
1836
0
        mcl::fp::writeHexStr(pb, os, buf, n + adj);
1837
0
      } else {
1838
0
        cybozu::write(pb, os, buf, n + adj);
1839
0
      }
1840
0
      return;
1841
0
    }
1842
5.12k
    if (isZero()) {
1843
32
      cybozu::writeChar(pb, os, '0');
1844
32
      return;
1845
32
    }
1846
5.09k
    if (ioMode & IoEcCompY) {
1847
0
      cybozu::writeChar(pb, os, P.y.isOdd() ? '3' : '2');
1848
0
      if (!*pb) return;
1849
0
      if (sep) {
1850
0
        cybozu::writeChar(pb, os, sep);
1851
0
        if (!*pb) return;
1852
0
      }
1853
0
      P.x.save(pb, os, ioMode);
1854
5.09k
    } else {
1855
5.09k
      cybozu::writeChar(pb, os, '1'); if (!*pb) return;
1856
5.09k
      if (sep) {
1857
5.09k
        cybozu::writeChar(pb, os, sep);
1858
5.09k
        if (!*pb) return;
1859
5.09k
      }
1860
5.09k
      P.x.save(pb, os, ioMode); if (!*pb) return;
1861
5.09k
      if (sep) {
1862
5.09k
        cybozu::writeChar(pb, os, sep);
1863
5.09k
        if (!*pb) return;
1864
5.09k
      }
1865
5.09k
      P.y.save(pb, os, ioMode);
1866
5.09k
    }
1867
5.09k
  }
void mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::save<cybozu::StringOutputStream>(bool*, cybozu::StringOutputStream&, int) const
Line
Count
Source
1753
3.77k
  {
1754
3.77k
    const char sep = *fp::getIoSeparator(ioMode);
1755
3.77k
    if (ioMode & IoEcProj) {
1756
0
      cybozu::writeChar(pb, os, '4'); if (!*pb) return;
1757
0
      if (sep) {
1758
0
        cybozu::writeChar(pb, os, sep);
1759
0
        if (!*pb) return;
1760
0
      }
1761
0
      x.save(pb, os, ioMode); if (!*pb) return;
1762
0
      if (sep) {
1763
0
        cybozu::writeChar(pb, os, sep);
1764
0
        if (!*pb) return;
1765
0
      }
1766
0
      y.save(pb, os, ioMode); if (!*pb) return;
1767
0
      if (sep) {
1768
0
        cybozu::writeChar(pb, os, sep);
1769
0
        if (!*pb) return;
1770
0
      }
1771
0
      z.save(pb, os, ioMode);
1772
0
      return;
1773
0
    }
1774
3.77k
    EcT P(*this);
1775
3.77k
    P.normalize();
1776
3.77k
    if (ioMode & IoEcAffineSerialize) {
1777
0
      if (b_ == 0) { // assume Zero if x = y = 0
1778
0
        *pb = false;
1779
0
        return;
1780
0
      }
1781
0
      if (isZero()) {
1782
        // all zero
1783
0
        P.z.save(pb, os, IoSerialize);
1784
0
        if (!*pb) return;
1785
0
        P.z.save(pb, os, IoSerialize);
1786
0
        return;
1787
0
      }
1788
0
      P.x.save(pb, os, IoSerialize);
1789
0
      if (!*pb) return;
1790
0
      P.y.save(pb, os, IoSerialize);
1791
0
      return;
1792
0
    }
1793
3.77k
    if (ioMode & (IoSerialize | IoSerializeHexStr)) {
1794
0
      const size_t n = Fp::getByteSize();
1795
0
      const size_t adj = isMSBserialize() ? 0 : 1;
1796
0
      uint8_t buf[sizeof(Fp) + 1];
1797
0
      if (Fp::BaseFp::getETHserialization()) {
1798
0
        const uint8_t c_flag = 0x80;
1799
0
        const uint8_t b_flag = 0x40;
1800
0
        const uint8_t a_flag = 0x20;
1801
0
        if (P.isZero()) {
1802
0
          buf[0] = c_flag | b_flag;
1803
0
          memset(buf + 1, 0, n - 1);
1804
0
        } else {
1805
0
          cybozu::MemoryOutputStream mos(buf, n);
1806
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1807
0
          uint8_t cba = c_flag;
1808
0
          if (ec::local::get_a_flag(P.y)) cba |= a_flag;
1809
0
          buf[0] |= cba;
1810
0
        }
1811
0
      } else {
1812
        /*
1813
          if (isMSBserialize()) {
1814
            // n bytes
1815
            x | (y.isOdd ? 0x80 : 0)
1816
          } else {
1817
            // n + 1 bytes
1818
            (y.isOdd ? 3 : 2), x
1819
          }
1820
        */
1821
0
        if (isZero()) {
1822
0
          memset(buf, 0, n + adj);
1823
0
        } else {
1824
0
          cybozu::MemoryOutputStream mos(buf + adj, n);
1825
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1826
0
          if (adj) {
1827
0
            buf[0] = P.y.isOdd() ? 3 : 2;
1828
0
          } else {
1829
0
            if (P.y.isOdd()) {
1830
0
              buf[n - 1] |= 0x80;
1831
0
            }
1832
0
          }
1833
0
        }
1834
0
      }
1835
0
      if (ioMode & IoSerializeHexStr) {
1836
0
        mcl::fp::writeHexStr(pb, os, buf, n + adj);
1837
0
      } else {
1838
0
        cybozu::write(pb, os, buf, n + adj);
1839
0
      }
1840
0
      return;
1841
0
    }
1842
3.77k
    if (isZero()) {
1843
15
      cybozu::writeChar(pb, os, '0');
1844
15
      return;
1845
15
    }
1846
3.76k
    if (ioMode & IoEcCompY) {
1847
0
      cybozu::writeChar(pb, os, P.y.isOdd() ? '3' : '2');
1848
0
      if (!*pb) return;
1849
0
      if (sep) {
1850
0
        cybozu::writeChar(pb, os, sep);
1851
0
        if (!*pb) return;
1852
0
      }
1853
0
      P.x.save(pb, os, ioMode);
1854
3.76k
    } else {
1855
3.76k
      cybozu::writeChar(pb, os, '1'); if (!*pb) return;
1856
3.76k
      if (sep) {
1857
3.76k
        cybozu::writeChar(pb, os, sep);
1858
3.76k
        if (!*pb) return;
1859
3.76k
      }
1860
3.76k
      P.x.save(pb, os, ioMode); if (!*pb) return;
1861
3.76k
      if (sep) {
1862
3.76k
        cybozu::writeChar(pb, os, sep);
1863
3.76k
        if (!*pb) return;
1864
3.76k
      }
1865
3.76k
      P.y.save(pb, os, ioMode);
1866
3.76k
    }
1867
3.76k
  }
void mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::save<cybozu::StringOutputStream>(bool*, cybozu::StringOutputStream&, int) const
Line
Count
Source
1753
1.35k
  {
1754
1.35k
    const char sep = *fp::getIoSeparator(ioMode);
1755
1.35k
    if (ioMode & IoEcProj) {
1756
0
      cybozu::writeChar(pb, os, '4'); if (!*pb) return;
1757
0
      if (sep) {
1758
0
        cybozu::writeChar(pb, os, sep);
1759
0
        if (!*pb) return;
1760
0
      }
1761
0
      x.save(pb, os, ioMode); if (!*pb) return;
1762
0
      if (sep) {
1763
0
        cybozu::writeChar(pb, os, sep);
1764
0
        if (!*pb) return;
1765
0
      }
1766
0
      y.save(pb, os, ioMode); if (!*pb) return;
1767
0
      if (sep) {
1768
0
        cybozu::writeChar(pb, os, sep);
1769
0
        if (!*pb) return;
1770
0
      }
1771
0
      z.save(pb, os, ioMode);
1772
0
      return;
1773
0
    }
1774
1.35k
    EcT P(*this);
1775
1.35k
    P.normalize();
1776
1.35k
    if (ioMode & IoEcAffineSerialize) {
1777
0
      if (b_ == 0) { // assume Zero if x = y = 0
1778
0
        *pb = false;
1779
0
        return;
1780
0
      }
1781
0
      if (isZero()) {
1782
        // all zero
1783
0
        P.z.save(pb, os, IoSerialize);
1784
0
        if (!*pb) return;
1785
0
        P.z.save(pb, os, IoSerialize);
1786
0
        return;
1787
0
      }
1788
0
      P.x.save(pb, os, IoSerialize);
1789
0
      if (!*pb) return;
1790
0
      P.y.save(pb, os, IoSerialize);
1791
0
      return;
1792
0
    }
1793
1.35k
    if (ioMode & (IoSerialize | IoSerializeHexStr)) {
1794
0
      const size_t n = Fp::getByteSize();
1795
0
      const size_t adj = isMSBserialize() ? 0 : 1;
1796
0
      uint8_t buf[sizeof(Fp) + 1];
1797
0
      if (Fp::BaseFp::getETHserialization()) {
1798
0
        const uint8_t c_flag = 0x80;
1799
0
        const uint8_t b_flag = 0x40;
1800
0
        const uint8_t a_flag = 0x20;
1801
0
        if (P.isZero()) {
1802
0
          buf[0] = c_flag | b_flag;
1803
0
          memset(buf + 1, 0, n - 1);
1804
0
        } else {
1805
0
          cybozu::MemoryOutputStream mos(buf, n);
1806
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1807
0
          uint8_t cba = c_flag;
1808
0
          if (ec::local::get_a_flag(P.y)) cba |= a_flag;
1809
0
          buf[0] |= cba;
1810
0
        }
1811
0
      } else {
1812
        /*
1813
          if (isMSBserialize()) {
1814
            // n bytes
1815
            x | (y.isOdd ? 0x80 : 0)
1816
          } else {
1817
            // n + 1 bytes
1818
            (y.isOdd ? 3 : 2), x
1819
          }
1820
        */
1821
0
        if (isZero()) {
1822
0
          memset(buf, 0, n + adj);
1823
0
        } else {
1824
0
          cybozu::MemoryOutputStream mos(buf + adj, n);
1825
0
          P.x.save(pb, mos, IoSerialize); if (!*pb) return;
1826
0
          if (adj) {
1827
0
            buf[0] = P.y.isOdd() ? 3 : 2;
1828
0
          } else {
1829
0
            if (P.y.isOdd()) {
1830
0
              buf[n - 1] |= 0x80;
1831
0
            }
1832
0
          }
1833
0
        }
1834
0
      }
1835
0
      if (ioMode & IoSerializeHexStr) {
1836
0
        mcl::fp::writeHexStr(pb, os, buf, n + adj);
1837
0
      } else {
1838
0
        cybozu::write(pb, os, buf, n + adj);
1839
0
      }
1840
0
      return;
1841
0
    }
1842
1.35k
    if (isZero()) {
1843
17
      cybozu::writeChar(pb, os, '0');
1844
17
      return;
1845
17
    }
1846
1.33k
    if (ioMode & IoEcCompY) {
1847
0
      cybozu::writeChar(pb, os, P.y.isOdd() ? '3' : '2');
1848
0
      if (!*pb) return;
1849
0
      if (sep) {
1850
0
        cybozu::writeChar(pb, os, sep);
1851
0
        if (!*pb) return;
1852
0
      }
1853
0
      P.x.save(pb, os, ioMode);
1854
1.33k
    } else {
1855
1.33k
      cybozu::writeChar(pb, os, '1'); if (!*pb) return;
1856
1.33k
      if (sep) {
1857
1.33k
        cybozu::writeChar(pb, os, sep);
1858
1.33k
        if (!*pb) return;
1859
1.33k
      }
1860
1.33k
      P.x.save(pb, os, ioMode); if (!*pb) return;
1861
1.33k
      if (sep) {
1862
1.33k
        cybozu::writeChar(pb, os, sep);
1863
1.33k
        if (!*pb) return;
1864
1.33k
      }
1865
1.33k
      P.y.save(pb, os, ioMode);
1866
1.33k
    }
1867
1.33k
  }
1868
  template<class InputStream>
1869
  void load(bool *pb, InputStream& is, int ioMode)
1870
  {
1871
    z = 1;
1872
    if (ioMode & IoEcAffineSerialize) {
1873
      if (b_ == 0) { // assume Zero if x = y = 0
1874
        *pb = false;
1875
        return;
1876
      }
1877
      x.load(pb, is, IoSerialize);
1878
      if (!*pb) return;
1879
      y.load(pb, is, IoSerialize);
1880
      if (!*pb) return;
1881
      if (x.isZero() && y.isZero()) {
1882
        z.clear();
1883
        return;
1884
      }
1885
      goto verifyValidAffine;
1886
    }
1887
    if (ioMode & (IoSerialize | IoSerializeHexStr)) {
1888
      const size_t n = Fp::getByteSize();
1889
      const size_t adj = isMSBserialize() ? 0 : 1;
1890
      const size_t n1 = n + adj;
1891
      uint8_t buf[sizeof(Fp) + 1];
1892
      size_t readSize;
1893
      if (ioMode & IoSerializeHexStr) {
1894
        readSize = mcl::fp::readHexStr(buf, n1, is);
1895
      } else {
1896
        readSize = cybozu::readSome(buf, n1, is);
1897
      }
1898
      if (readSize != n1) {
1899
        *pb = false;
1900
        return;
1901
      }
1902
      if (Fp::BaseFp::getETHserialization()) {
1903
        const uint8_t c_flag = 0x80;
1904
        const uint8_t b_flag = 0x40;
1905
        const uint8_t a_flag = 0x20;
1906
        *pb = false;
1907
        if ((buf[0] & c_flag) == 0) { // assume compressed
1908
          return;
1909
        }
1910
        if (buf[0] & b_flag) { // infinity
1911
          if (buf[0] != (c_flag | b_flag)) return;
1912
          for (size_t i = 1; i < n - 1; i++) {
1913
            if (buf[i]) return;
1914
          }
1915
          clear();
1916
          *pb = true;
1917
          return;
1918
        }
1919
        bool a = (buf[0] & a_flag) != 0;
1920
        buf[0] &= ~(c_flag | b_flag | a_flag);
1921
        mcl::fp::local::byteSwap(buf, n);
1922
        x.setArray(pb, buf, n);
1923
        if (!*pb) return;
1924
        getWeierstrass(y, x);
1925
        if (!Fp::squareRoot(y, y)) {
1926
          *pb = false;
1927
          return;
1928
        }
1929
        if (ec::local::get_a_flag(y) ^ a) {
1930
          Fp::neg(y, y);
1931
        }
1932
        goto verifyOrder;
1933
      }
1934
      if (bint::isZeroN(buf, n1)) {
1935
        clear();
1936
        *pb = true;
1937
        return;
1938
      }
1939
      bool isYodd;
1940
      if (adj) {
1941
        char c = buf[0];
1942
        if (c != 2 && c != 3) {
1943
          *pb = false;
1944
          return;
1945
        }
1946
        isYodd = c == 3;
1947
      } else {
1948
        isYodd = (buf[n - 1] >> 7) != 0;
1949
        buf[n - 1] &= 0x7f;
1950
      }
1951
      x.setArray(pb, buf + adj, n);
1952
      if (!*pb) return;
1953
      *pb = getYfromX(y, x, isYodd);
1954
      if (!*pb) return;
1955
    } else {
1956
      char c = 0;
1957
      if (!fp::local::skipSpace(&c, is)) {
1958
        *pb = false;
1959
        return;
1960
      }
1961
      if (c == '0') {
1962
        clear();
1963
        *pb = true;
1964
        return;
1965
      }
1966
      x.load(pb, is, ioMode); if (!*pb) return;
1967
      if (c == '1') {
1968
        y.load(pb, is, ioMode); if (!*pb) return;
1969
        goto verifyValidAffine;
1970
      } else if (c == '2' || c == '3') {
1971
        bool isYodd = c == '3';
1972
        *pb = getYfromX(y, x, isYodd);
1973
        if (!*pb) return;
1974
      } else if (c == '4') {
1975
        y.load(pb, is, ioMode); if (!*pb) return;
1976
        z.load(pb, is, ioMode); if (!*pb) return;
1977
        if (mode_ == ec::Affine) {
1978
          if (!z.isZero() && !z.isOne()) {
1979
            *pb = false;
1980
            return;
1981
          }
1982
        }
1983
        *pb = isValid();
1984
        return;
1985
      } else {
1986
        *pb = false;
1987
        return;
1988
      }
1989
    }
1990
  verifyOrder:
1991
    if (verifyOrder_ && !isValidOrder()) {
1992
      *pb = false;
1993
    } else {
1994
      *pb = true;
1995
    }
1996
    return;
1997
  verifyValidAffine:
1998
    if (!isValidAffine()) {
1999
      *pb = false;
2000
      return;
2001
    }
2002
    goto verifyOrder;
2003
  }
2004
  // deplicated
2005
  static void setCompressedExpression(bool compressedExpression = true)
2006
8
  {
2007
8
    if (compressedExpression) {
2008
8
      ioMode_ |= IoEcCompY;
2009
8
    } else {
2010
0
      ioMode_ &= ~IoEcCompY;
2011
0
    }
2012
8
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setCompressedExpression(bool)
Line
Count
Source
2006
4
  {
2007
4
    if (compressedExpression) {
2008
4
      ioMode_ |= IoEcCompY;
2009
4
    } else {
2010
0
      ioMode_ &= ~IoEcCompY;
2011
0
    }
2012
4
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::setCompressedExpression(bool)
Line
Count
Source
2006
4
  {
2007
4
    if (compressedExpression) {
2008
4
      ioMode_ |= IoEcCompY;
2009
4
    } else {
2010
0
      ioMode_ &= ~IoEcCompY;
2011
0
    }
2012
4
  }
2013
  /*
2014
    set IoMode for operator<<(), or operator>>()
2015
  */
2016
  static void setIoMode(int ioMode)
2017
  {
2018
    assert(!(ioMode & 0xff));
2019
    ioMode_ = ioMode;
2020
  }
2021
  static inline int getIoMode() { return Fp::BaseFp::getIoMode() | ioMode_; }
2022
  static inline void getWeierstrass(Fp& yy, const Fp& x)
2023
0
  {
2024
0
    Fp t;
2025
0
    Fp::sqr(t, x);
2026
0
    t += a_;
2027
0
    t *= x;
2028
0
    Fp::add(yy, t, b_);
2029
0
  }
Unexecuted instantiation: mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::getWeierstrass(mcl::FpT<mcl::bn::local::FpTag, 384ul>&, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&)
Unexecuted instantiation: mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::getWeierstrass(mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >&, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&)
2030
  static inline bool getYfromX(Fp& y, const Fp& x, bool isYodd)
2031
  {
2032
    getWeierstrass(y, x);
2033
    if (!Fp::squareRoot(y, y)) {
2034
      return false;
2035
    }
2036
    if (y.isOdd() ^ isYodd) {
2037
      Fp::neg(y, y);
2038
    }
2039
    return true;
2040
  }
2041
26
  inline friend EcT operator+(const EcT& x, const EcT& y) { EcT z; add(z, x, y); return z; }
mcl::operator+(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2041
15
  inline friend EcT operator+(const EcT& x, const EcT& y) { EcT z; add(z, x, y); return z; }
mcl::operator+(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2041
11
  inline friend EcT operator+(const EcT& x, const EcT& y) { EcT z; add(z, x, y); return z; }
2042
  inline friend EcT operator-(const EcT& x, const EcT& y) { EcT z; sub(z, x, y); return z; }
2043
  template<class INT>
2044
88
  inline friend EcT operator*(const EcT& x, const INT& y) { EcT z; mul(z, x, y); return z; }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > mcl::operator*<mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::FpT<mcl::bn::local::FrTag, 256ul> const&)
Line
Count
Source
2044
68
  inline friend EcT operator*(const EcT& x, const INT& y) { EcT z; mul(z, x, y); return z; }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > mcl::operator*<mcl::FpT<mcl::bn::local::FrTag, 256ul> >(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::FpT<mcl::bn::local::FrTag, 256ul> const&)
Line
Count
Source
2044
20
  inline friend EcT operator*(const EcT& x, const INT& y) { EcT z; mul(z, x, y); return z; }
2045
91.1k
  EcT& operator+=(const EcT& x) { add(*this, *this, x); return *this; }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator+=(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2045
83.5k
  EcT& operator+=(const EcT& x) { add(*this, *this, x); return *this; }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator+=(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2045
7.60k
  EcT& operator+=(const EcT& x) { add(*this, *this, x); return *this; }
2046
79.2k
  EcT& operator-=(const EcT& x) { sub(*this, *this, x); return *this; }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator-=(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2046
65.2k
  EcT& operator-=(const EcT& x) { sub(*this, *this, x); return *this; }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator-=(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&)
Line
Count
Source
2046
14.0k
  EcT& operator-=(const EcT& x) { sub(*this, *this, x); return *this; }
2047
  template<class INT>
2048
0
  EcT& operator*=(const INT& x) { mul(*this, *this, x); return *this; }
2049
25
  EcT operator-() const { EcT x; neg(x, *this); return x; }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator-() const
Line
Count
Source
2049
12
  EcT operator-() const { EcT x; neg(x, *this); return x; }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator-() const
Line
Count
Source
2049
13
  EcT operator-() const { EcT x; neg(x, *this); return x; }
2050
  bool operator==(const EcT& rhs) const
2051
4.93k
  {
2052
4.93k
    switch (mode_) {
2053
4.93k
    case ec::Jacobi:
2054
4.93k
      return ec::isEqualJacobi(*this, rhs);
2055
0
    case ec::Proj:
2056
0
      return ec::isEqualProj(*this, rhs);
2057
0
    case ec::Affine:
2058
0
    default:
2059
0
      return x == rhs.x && y == rhs.y && z == rhs.z;
2060
4.93k
    }
2061
4.93k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator==(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&) const
Line
Count
Source
2051
957
  {
2052
957
    switch (mode_) {
2053
957
    case ec::Jacobi:
2054
957
      return ec::isEqualJacobi(*this, rhs);
2055
0
    case ec::Proj:
2056
0
      return ec::isEqualProj(*this, rhs);
2057
0
    case ec::Affine:
2058
0
    default:
2059
0
      return x == rhs.x && y == rhs.y && z == rhs.z;
2060
957
    }
2061
957
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::operator==(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&) const
Line
Count
Source
2051
3.98k
  {
2052
3.98k
    switch (mode_) {
2053
3.98k
    case ec::Jacobi:
2054
3.98k
      return ec::isEqualJacobi(*this, rhs);
2055
0
    case ec::Proj:
2056
0
      return ec::isEqualProj(*this, rhs);
2057
0
    case ec::Affine:
2058
0
    default:
2059
0
      return x == rhs.x && y == rhs.y && z == rhs.z;
2060
3.98k
    }
2061
3.98k
  }
2062
  // return (==rhs) ? 1 : (==-rhs) ? -1 : 0
2063
  int isEqualOrMinus(const EcT& rhs) const
2064
  {
2065
    switch (mode_) {
2066
    case ec::Jacobi:
2067
      return ec::isEqualOrMinusJacobi(*this, rhs);
2068
    case ec::Proj:
2069
      return ec::isEqualOrMinusProj(*this, rhs);
2070
    case ec::Affine:
2071
    default:
2072
      if (x == rhs.x && z == rhs.z) {
2073
        if (y == rhs.y) return 1;
2074
        if (y == -rhs.y) return -1;
2075
      }
2076
      return 0;
2077
    }
2078
  }
2079
  bool operator!=(const EcT& rhs) const { return !operator==(rhs); }
2080
  bool operator<(const EcT& rhs) const
2081
  {
2082
    return compare(*this, rhs) < 0;
2083
  }
2084
  bool operator>=(const EcT& rhs) const { return !operator<(rhs); }
2085
  bool operator>(const EcT& rhs) const { return rhs < *this; }
2086
  bool operator<=(const EcT& rhs) const { return !operator>(rhs); }
2087
  static inline void mulArrayCT(EcT& z, const EcT& x, const Unit *y, size_t yn, bool isNegative)
2088
0
  {
2089
0
    const int w = 4; // don't change
2090
0
    const size_t tblSize = 1u << w;
2091
0
    const size_t mask = tblSize - 1;
2092
0
    const size_t m = sizeof(Unit) * 8 / w;
2093
0
    EcT tbl[tblSize];
2094
0
    tbl[0].clear();
2095
0
    tbl[1] = x;
2096
0
    for (size_t i = 2; i < tblSize; i++) {
2097
0
      add(tbl[i], tbl[i - 1], x);
2098
0
    }
2099
0
    z.clear();
2100
0
    for (size_t i = 0; i < yn; i++) {
2101
0
      Unit v = y[yn - 1 - i];
2102
0
      for (size_t j = 0; j < m; j++) {
2103
0
        for (size_t k = 0; k < w; k++) {
2104
0
          EcT::dbl(z, z);
2105
0
        }
2106
0
        z += tbl[(v >> ((m - 1 - j) * w)) & mask];
2107
0
      }
2108
0
    }
2109
0
    if (isNegative) {
2110
0
      EcT::neg(z, z);
2111
0
    }
2112
0
  }
Unexecuted instantiation: mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulArrayCT(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long const*, unsigned long, bool)
Unexecuted instantiation: mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulArrayCT(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long const*, unsigned long, bool)
2113
2114
  static inline void mulArray(EcT& z, const EcT& x, const Unit *y, size_t yn, bool isNegative = false, bool constTime = false)
2115
6.63k
  {
2116
6.63k
    if (constTime) {
2117
0
      mulArrayCT(z, x, y, yn, isNegative);
2118
0
      return;
2119
0
    }
2120
6.63k
    if (yn == 0) {
2121
0
      z.clear();
2122
0
      return;
2123
0
    }
2124
6.63k
    yn = bint::getRealSize(y, yn);
2125
6.63k
    if (yn <= 1 && mcl::ec::mulSmallInt(z, x, *y, isNegative)) return;
2126
6.63k
    mpz_class v;
2127
6.63k
    bool b;
2128
6.63k
    gmp::setArray(&b, v, y, yn);
2129
6.63k
    assert(b); (void)b;
2130
6.63k
    if (isNegative) v = -v;
2131
6.63k
    const int maxW = 5;
2132
6.63k
    const int maxTblSize = 1 << (maxW - 2);
2133
    /*
2134
      L = log2(y), w = (L <= 32) ? 3 : (L <= 128) ? 4 : 5;
2135
    */
2136
6.63k
    const int w = (yn == 1 && *y <= (1ull << 32)) ? 3 : (yn * sizeof(Unit) > 16) ? 5 : 4;
2137
6.63k
    const size_t tblSize = size_t(1) << (w - 2);
2138
6.63k
    typedef mcl::FixedArray<int8_t, sizeof(EcT::Fp) * 8 + 1> NafArray;
2139
6.63k
    NafArray naf;
2140
6.63k
    EcT tbl[maxTblSize];
2141
6.63k
    gmp::getNAFwidth(&b, naf, v, w);
2142
6.63k
    assert(b); (void)b;
2143
6.63k
    EcT P2;
2144
6.63k
    dbl(P2, x);
2145
6.63k
    tbl[0] = x;
2146
26.5k
    for (size_t i = 1; i < tblSize; i++) {
2147
19.9k
      add(tbl[i], tbl[i - 1], P2);
2148
19.9k
    }
2149
6.63k
    z.clear();
2150
676k
    for (size_t i = 0; i < naf.size(); i++) {
2151
669k
      EcT::dbl(z, z);
2152
669k
      ec::local::addTbl(z, tbl, naf, naf.size() - 1 - i);
2153
669k
    }
2154
6.63k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulArray(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long const*, unsigned long, bool, bool)
Line
Count
Source
2115
4.30k
  {
2116
4.30k
    if (constTime) {
2117
0
      mulArrayCT(z, x, y, yn, isNegative);
2118
0
      return;
2119
0
    }
2120
4.30k
    if (yn == 0) {
2121
0
      z.clear();
2122
0
      return;
2123
0
    }
2124
4.30k
    yn = bint::getRealSize(y, yn);
2125
4.30k
    if (yn <= 1 && mcl::ec::mulSmallInt(z, x, *y, isNegative)) return;
2126
4.30k
    mpz_class v;
2127
4.30k
    bool b;
2128
4.30k
    gmp::setArray(&b, v, y, yn);
2129
4.30k
    assert(b); (void)b;
2130
4.30k
    if (isNegative) v = -v;
2131
4.30k
    const int maxW = 5;
2132
4.30k
    const int maxTblSize = 1 << (maxW - 2);
2133
    /*
2134
      L = log2(y), w = (L <= 32) ? 3 : (L <= 128) ? 4 : 5;
2135
    */
2136
4.30k
    const int w = (yn == 1 && *y <= (1ull << 32)) ? 3 : (yn * sizeof(Unit) > 16) ? 5 : 4;
2137
4.30k
    const size_t tblSize = size_t(1) << (w - 2);
2138
4.30k
    typedef mcl::FixedArray<int8_t, sizeof(EcT::Fp) * 8 + 1> NafArray;
2139
4.30k
    NafArray naf;
2140
4.30k
    EcT tbl[maxTblSize];
2141
4.30k
    gmp::getNAFwidth(&b, naf, v, w);
2142
4.30k
    assert(b); (void)b;
2143
4.30k
    EcT P2;
2144
4.30k
    dbl(P2, x);
2145
4.30k
    tbl[0] = x;
2146
17.2k
    for (size_t i = 1; i < tblSize; i++) {
2147
12.9k
      add(tbl[i], tbl[i - 1], P2);
2148
12.9k
    }
2149
4.30k
    z.clear();
2150
529k
    for (size_t i = 0; i < naf.size(); i++) {
2151
525k
      EcT::dbl(z, z);
2152
525k
      ec::local::addTbl(z, tbl, naf, naf.size() - 1 - i);
2153
525k
    }
2154
4.30k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulArray(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, unsigned long const*, unsigned long, bool, bool)
Line
Count
Source
2115
2.33k
  {
2116
2.33k
    if (constTime) {
2117
0
      mulArrayCT(z, x, y, yn, isNegative);
2118
0
      return;
2119
0
    }
2120
2.33k
    if (yn == 0) {
2121
0
      z.clear();
2122
0
      return;
2123
0
    }
2124
2.33k
    yn = bint::getRealSize(y, yn);
2125
2.33k
    if (yn <= 1 && mcl::ec::mulSmallInt(z, x, *y, isNegative)) return;
2126
2.33k
    mpz_class v;
2127
2.33k
    bool b;
2128
2.33k
    gmp::setArray(&b, v, y, yn);
2129
2.33k
    assert(b); (void)b;
2130
2.33k
    if (isNegative) v = -v;
2131
2.33k
    const int maxW = 5;
2132
2.33k
    const int maxTblSize = 1 << (maxW - 2);
2133
    /*
2134
      L = log2(y), w = (L <= 32) ? 3 : (L <= 128) ? 4 : 5;
2135
    */
2136
2.33k
    const int w = (yn == 1 && *y <= (1ull << 32)) ? 3 : (yn * sizeof(Unit) > 16) ? 5 : 4;
2137
2.33k
    const size_t tblSize = size_t(1) << (w - 2);
2138
2.33k
    typedef mcl::FixedArray<int8_t, sizeof(EcT::Fp) * 8 + 1> NafArray;
2139
2.33k
    NafArray naf;
2140
2.33k
    EcT tbl[maxTblSize];
2141
2.33k
    gmp::getNAFwidth(&b, naf, v, w);
2142
2.33k
    assert(b); (void)b;
2143
2.33k
    EcT P2;
2144
2.33k
    dbl(P2, x);
2145
2.33k
    tbl[0] = x;
2146
9.32k
    for (size_t i = 1; i < tblSize; i++) {
2147
6.99k
      add(tbl[i], tbl[i - 1], P2);
2148
6.99k
    }
2149
2.33k
    z.clear();
2150
146k
    for (size_t i = 0; i < naf.size(); i++) {
2151
144k
      EcT::dbl(z, z);
2152
144k
      ec::local::addTbl(z, tbl, naf, naf.size() - 1 - i);
2153
144k
    }
2154
2.33k
  }
2155
  static inline bool mulSmallInt(EcT& z, const EcT& x, Unit y, bool isNegative)
2156
  {
2157
    return mcl::ec::mulSmallInt(z, x, y, isNegative);
2158
  }
2159
  /*
2160
    generic mul
2161
    GLV can't be applied in Fp12 - GT
2162
  */
2163
  static inline void mulGeneric(EcT& z, const EcT& x, const mpz_class& y)
2164
6.63k
  {
2165
6.63k
    mulArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0);
2166
6.63k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulGeneric(mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::Vint const&)
Line
Count
Source
2164
4.30k
  {
2165
4.30k
    mulArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0);
2166
4.30k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::mulGeneric(mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >&, mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> > const&, mcl::Vint const&)
Line
Count
Source
2164
2.33k
  {
2165
2.33k
    mulArray(z, x, gmp::getUnit(y), gmp::getUnitSize(y), y < 0);
2166
2.33k
  }
2167
  /*
2168
    z = sum_{i=0}^{n-1} xVec[i] * yVec[i]
2169
    return min(N, n)
2170
    @note &z != xVec[i]
2171
  */
2172
private:
2173
  static inline size_t mulVecN(EcT& z, const EcT *xVec, const EcT::Fr *yVec, size_t n)
2174
  {
2175
    const size_t N = mcl::fp::maxMulVecN;
2176
    if (n > N) n = N;
2177
    const int w = 5;
2178
    const size_t tblSize = 1 << (w - 2);
2179
    typedef mcl::FixedArray<int8_t, sizeof(EcT::Fp) * 8 + 1> NafArray;
2180
    NafArray naf[N];
2181
    EcT tbl[N][tblSize];
2182
    size_t maxBit = 0;
2183
    mpz_class y;
2184
    for (size_t i = 0; i < n; i++) {
2185
      bool b;
2186
      yVec[i].getMpz(&b, y);
2187
      assert(b); (void)b;
2188
      gmp::getNAFwidth(&b, naf[i], y, w);
2189
      assert(b); (void)b;
2190
      if (naf[i].size() > maxBit) maxBit = naf[i].size();
2191
      EcT P2;
2192
      EcT::dbl(P2, xVec[i]);
2193
      tbl[i][0] = xVec[i];
2194
      for (size_t j = 1; j < tblSize; j++) {
2195
        EcT::add(tbl[i][j], tbl[i][j - 1], P2);
2196
      }
2197
    }
2198
    z.clear();
2199
    EcT::normalizeVec(&tbl[0][0], &tbl[0][0], n * tblSize);
2200
    for (size_t i = 0; i < maxBit; i++) {
2201
      EcT::dbl(z, z);
2202
      for (size_t j = 0; j < n; j++) {
2203
        ec::local::addTbl(z, tbl[j], naf[j], maxBit - 1 - i);
2204
      }
2205
    }
2206
    return n;
2207
  }
2208
2209
public:
2210
  /*
2211
    estimation for n multVec
2212
    GLV method x n-times
2213
    L : bitsize (=256 for Fr)
2214
    w : withdow size (=5 for L=256)
2215
    S : splitSize (=2 for G1, =4 for G2)
2216
    #DBL = L/S, #ADD = ((2^(w-2) + (L/(Sw)S)) * n
2217
    mulVecLong
2218
    c = 5 (for n <= 256), c = 6 for n = 512
2219
    #DBL = L, #ADD = (n + 2^(c+1)-1)*(L/c)
2220
2221
    #ADD
2222
    n = 128, 256, 512
2223
    GLV : 7680, 15360, 30720
2224
    Long: 9779, 16322, 24533
2225
  */
2226
  static inline void mulVec(EcT& z, EcT *xVec, const EcT::Fr *yVec, size_t n, size_t b = 0)
2227
  {
2228
    if (n == 0) {
2229
      z.clear();
2230
      return;
2231
    }
2232
    if (mulVecOpti && n >= 128) {
2233
      mulVecOpti((Unit*)&z, (Unit*)xVec, yVec[0].getUnit(), n, b);
2234
      return;
2235
    }
2236
    if (mulVecGLV && mulVecGLV(z, xVec, yVec, n, false, b)) {
2237
      return;
2238
    }
2239
    EcT r;
2240
    r.clear();
2241
    while (n > 0) {
2242
      EcT t;
2243
      size_t done = mulVecN(t, xVec, yVec, n);
2244
      r += t;
2245
      xVec += done;
2246
      yVec += done;
2247
      n -= done;
2248
    }
2249
    z = r;
2250
  }
2251
  // multi thread version of mulVec
2252
  // the num of thread is automatically detected if cpuN = 0
2253
  static inline void mulVecMT(EcT& z, EcT *xVec, const EcT::Fr *yVec, size_t n, size_t cpuN = 0)
2254
  {
2255
#ifdef MCL_USE_OMP
2256
  const size_t minN = mcl::fp::maxMulVecN;
2257
  if (cpuN == 0) {
2258
    cpuN = omp_get_num_procs();
2259
    if (n < minN * cpuN) {
2260
      cpuN = (n + minN - 1) / minN;
2261
    }
2262
  }
2263
  if (cpuN <= 1 || n <= cpuN) {
2264
    mulVec(z, xVec, yVec, n);
2265
    return;
2266
  }
2267
  EcT *zs = (EcT*)CYBOZU_ALLOCA(sizeof(EcT) * cpuN);
2268
  size_t q = n / cpuN;
2269
  size_t r = n % cpuN;
2270
  #pragma omp parallel for
2271
  for (size_t i = 0; i < cpuN; i++) {
2272
    size_t adj = q * i + fp::min_(i, r);
2273
    mulVec(zs[i], xVec + adj, yVec + adj, q + (i < r));
2274
  }
2275
  z.clear();
2276
//  #pragma omp declare reduction(red:EcT:omp_out *= omp_in) initializer(omp_priv = omp_orig)
2277
//  #pragma omp parallel for reduction(red:z)
2278
  for (size_t i = 0; i < cpuN; i++) {
2279
    z += zs[i];
2280
  }
2281
#else
2282
    (void)cpuN;
2283
    mulVec(z, xVec, yVec, n);
2284
#endif
2285
  }
2286
  // xVec[i] *= yVec[i]
2287
  static void mulEach(EcT *xVec, const EcT::Fr *yVec, size_t n)
2288
  {
2289
    if (mulEachOpti && n >= 16) {
2290
      size_t n16 = n & ~size_t(16-1);
2291
      mulEachOpti((Unit*)xVec, yVec[0].getUnit(), n16);
2292
      xVec += n16;
2293
      yVec += n16;
2294
      n -= n16;
2295
    }
2296
    for (size_t i = 0; i < n; i++) {
2297
      xVec[i] *= yVec[i];
2298
    }
2299
  }
2300
#ifndef CYBOZU_DONT_USE_EXCEPTION
2301
  static inline void init(const std::string& astr, const std::string& bstr, int mode = ec::Jacobi)
2302
  {
2303
    bool b;
2304
    init(&b, astr.c_str(), bstr.c_str(), mode);
2305
    if (!b) throw cybozu::Exception("mcl:EcT:init");
2306
  }
2307
  void set(const Fp& _x, const Fp& _y, bool verify = true)
2308
27.7k
  {
2309
27.7k
    bool b;
2310
27.7k
    set(&b, _x, _y, verify);
2311
27.7k
    if (!b) throw cybozu::Exception("ec:EcT:set") << _x << _y;
2312
27.7k
  }
mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::set(mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, mcl::FpT<mcl::bn::local::FpTag, 384ul> const&, bool)
Line
Count
Source
2308
13.2k
  {
2309
13.2k
    bool b;
2310
13.2k
    set(&b, _x, _y, verify);
2311
13.2k
    if (!b) throw cybozu::Exception("ec:EcT:set") << _x << _y;
2312
13.2k
  }
mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::set(mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> > const&, bool)
Line
Count
Source
2308
14.4k
  {
2309
14.4k
    bool b;
2310
14.4k
    set(&b, _x, _y, verify);
2311
14.4k
    if (!b) throw cybozu::Exception("ec:EcT:set") << _x << _y;
2312
14.4k
  }
2313
  template<class OutputStream>
2314
  void save(OutputStream& os, int ioMode = IoSerialize) const
2315
5.12k
  {
2316
5.12k
    bool b;
2317
5.12k
    save(&b, os, ioMode);
2318
5.12k
    if (!b) throw cybozu::Exception("EcT:save");
2319
5.12k
  }
void mcl::EcT<mcl::FpT<mcl::bn::local::FpTag, 384ul>, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::save<cybozu::StringOutputStream>(cybozu::StringOutputStream&, int) const
Line
Count
Source
2315
3.77k
  {
2316
3.77k
    bool b;
2317
3.77k
    save(&b, os, ioMode);
2318
3.77k
    if (!b) throw cybozu::Exception("EcT:save");
2319
3.77k
  }
void mcl::EcT<mcl::Fp2T<mcl::FpT<mcl::bn::local::FpTag, 384ul> >, mcl::FpT<mcl::bn::local::FrTag, 256ul> >::save<cybozu::StringOutputStream>(cybozu::StringOutputStream&, int) const
Line
Count
Source
2315
1.35k
  {
2316
1.35k
    bool b;
2317
1.35k
    save(&b, os, ioMode);
2318
1.35k
    if (!b) throw cybozu::Exception("EcT:save");
2319
1.35k
  }
2320
  template<class InputStream>
2321
  void load(InputStream& is, int ioMode = IoSerialize)
2322
  {
2323
    bool b;
2324
    load(&b, is, ioMode);
2325
    if (!b) throw cybozu::Exception("EcT:load");
2326
  }
2327
#endif
2328
#ifndef CYBOZU_DONT_USE_STRING
2329
  // backward compatilibity
2330
  static inline void setParam(const std::string& astr, const std::string& bstr, int mode = ec::Jacobi)
2331
  {
2332
    init(astr, bstr, mode);
2333
  }
2334
  friend inline std::istream& operator>>(std::istream& is, EcT& self)
2335
  {
2336
    self.load(is, fp::detectIoMode(getIoMode(), is));
2337
    return is;
2338
  }
2339
  friend inline std::ostream& operator<<(std::ostream& os, const EcT& self)
2340
  {
2341
    self.save(os, fp::detectIoMode(getIoMode(), os));
2342
    return os;
2343
  }
2344
#endif
2345
};
2346
2347
template<class Fp, class Fr> Fp EcT<Fp, Fr>::a_;
2348
template<class Fp, class Fr> Fp EcT<Fp, Fr>::b_;
2349
template<class Fp, class Fr> Fp EcT<Fp, Fr>::b3_;
2350
template<class Fp, class Fr> int EcT<Fp, Fr>::specialA_;
2351
template<class Fp, class Fr> int EcT<Fp, Fr>::specialB_;
2352
template<class Fp, class Fr> int EcT<Fp, Fr>::ioMode_;
2353
template<class Fp, class Fr> bool EcT<Fp, Fr>::verifyOrder_;
2354
template<class Fp, class Fr> mpz_class EcT<Fp, Fr>::order_;
2355
template<class Fp, class Fr> bool (*EcT<Fp, Fr>::mulVecGLV)(EcT& z, const EcT *xVec, const void *yVec, size_t n, bool constTime, size_t b);
2356
template<class Fp, class Fr> void (*EcT<Fp, Fr>::mulVecOpti)(Unit *z, Unit *xVec, const Unit *yVec, size_t n, size_t b);
2357
template<class Fp, class Fr> bool (*EcT<Fp, Fr>::isValidOrderFast)(const EcT& x);
2358
template<class Fp, class Fr> int EcT<Fp, Fr>::mode_;
2359
template<class Fp, class Fr> void (*EcT<Fp, Fr>::mulEachOpti)(Unit *xVec, const Unit *yVec, size_t n);
2360
2361
// r = the order of Ec
2362
template<class Ec, class _Fr>
2363
struct GLV1T {
2364
  typedef GLV1T<Ec, _Fr> GLV1;
2365
  typedef typename Ec::Fp Fp;
2366
  typedef _Fr Fr;
2367
  static const int splitN = 2;
2368
  static Fp rw; // rw = 1 / w = (-1 - sqrt(-3)) / 2
2369
  static size_t rBitSize;
2370
  static mpz_class v0, v1;
2371
  static mpz_class B[2][2];
2372
  static void (*optimizedSplit)(mpz_class u[2], const mpz_class& x);
2373
public:
2374
#ifndef CYBOZU_DONT_USE_STRING
2375
  static void dump(const mpz_class& x)
2376
  {
2377
    printf("\"%s\",\n", mcl::gmp::getStr(x, 16).c_str());
2378
  }
2379
  static void dump()
2380
  {
2381
    printf("\"%s\",\n", rw.getStr(16).c_str());
2382
    printf("%d,\n", (int)rBitSize);
2383
    dump(v0);
2384
    dump(v1);
2385
    dump(B[0][0]); dump(B[0][1]); dump(B[1][0]); dump(B[1][1]);
2386
  }
2387
#endif
2388
  /*
2389
    L (x, y) = (rw x, y)
2390
  */
2391
  static void mulLambda(Ec& Q, const Ec& P)
2392
25.6k
  {
2393
25.6k
    Fp::mul(Q.x, P.x, rw);
2394
25.6k
    Q.y = P.y;
2395
25.6k
    Q.z = P.z;
2396
25.6k
  }
2397
  /*
2398
    x = u[0] + u[1] * lambda mod r
2399
  */
2400
  static void split(mpz_class u[2], mpz_class& x)
2401
3.21k
  {
2402
3.21k
    Fr::getOp().modp.modp(x, x);
2403
3.21k
    if (optimizedSplit) {
2404
3.21k
      optimizedSplit(u, x);
2405
3.21k
      return;
2406
3.21k
    }
2407
0
    mpz_class& a = u[0];
2408
0
    mpz_class& b = u[1];
2409
0
    mpz_class t;
2410
0
    t = (x * v0) >> rBitSize;
2411
0
    b = (x * v1) >> rBitSize;
2412
0
    a = x - (t * B[0][0] + b * B[1][0]);
2413
0
    b = - (t * B[0][1] + b * B[1][1]);
2414
0
  }
2415
  /*
2416
    init() is defined in bn.hpp
2417
  */
2418
  static void initForSecp256k1()
2419
0
  {
2420
0
    bool b = Fp::squareRoot(rw, -3);
2421
0
    assert(b);
2422
0
    (void)b;
2423
0
    rw = -(rw + 1) / 2;
2424
0
    rBitSize = Fr::getOp().bitSize;
2425
0
    rBitSize = (rBitSize + UnitBitSize - 1) & ~(UnitBitSize - 1);
2426
0
    gmp::setStr(&b, B[0][0], "0x3086d221a7d46bcde86c90e49284eb15");
2427
0
    assert(b); (void)b;
2428
0
    gmp::setStr(&b, B[0][1], "-0xe4437ed6010e88286f547fa90abfe4c3");
2429
0
    assert(b); (void)b;
2430
0
    gmp::setStr(&b, B[1][0], "0x114ca50f7a8e2f3f657c1108d9d44cfd8");
2431
0
    assert(b); (void)b;
2432
0
    B[1][1] = B[0][0];
2433
0
    const mpz_class& r = Fr::getOp().mp;
2434
0
    v0 = ((B[1][1]) << rBitSize) / r;
2435
0
    v1 = ((-B[0][1]) << rBitSize) / r;
2436
0
    optimizedSplit = 0;
2437
0
  }
2438
};
2439
2440
// rw = 1 / w = (-1 - sqrt(-3)) / 2
2441
template<class Ec, class Fr> typename Ec::Fp GLV1T<Ec, Fr>::rw;
2442
template<class Ec, class Fr> size_t GLV1T<Ec, Fr>::rBitSize;
2443
template<class Ec, class Fr> mpz_class GLV1T<Ec, Fr>::v0;
2444
template<class Ec, class Fr> mpz_class GLV1T<Ec, Fr>::v1;
2445
template<class Ec, class Fr> mpz_class GLV1T<Ec, Fr>::B[2][2];
2446
template<class Ec, class Fr> void (*GLV1T<Ec, Fr>::optimizedSplit)(mpz_class u[2], const mpz_class& x);
2447
2448
/*
2449
  Ec : elliptic curve
2450
  Zn : cyclic group of the order |Ec|
2451
  set P the generator of Ec if P != 0
2452
*/
2453
template<class Ec>
2454
void initCurve(bool *pb, int curveType, Ec *P = 0, mcl::fp::Mode mode = fp::FP_AUTO, mcl::ec::Mode ecMode = ec::Jacobi)
2455
0
{
2456
0
  typedef typename Ec::Fp Fp;
2457
0
  typedef typename Ec::Fr Zn;
2458
0
  *pb = false;
2459
0
  const EcParam *ecParam = getEcParam(curveType);
2460
0
  if (ecParam == 0) return;
2461
0
2462
0
  Zn::init(pb, ecParam->n, mode);
2463
0
  if (!*pb) return;
2464
0
  Fp::init(pb, ecParam->p, mode);
2465
0
  if (!*pb) return;
2466
0
  Ec::init(pb, ecParam->a, ecParam->b, ecMode);
2467
0
  if (!*pb) return;
2468
0
  if (P) {
2469
0
    Fp x, y;
2470
0
    x.setStr(pb, ecParam->gx);
2471
0
    if (!*pb) return;
2472
0
    y.setStr(pb, ecParam->gy);
2473
0
    if (!*pb) return;
2474
0
    P->set(pb, x, y);
2475
0
    if (!*pb) return;
2476
0
  }
2477
0
  if (curveType == MCL_SECP256K1) {
2478
0
    typedef GLV1T<Ec, Zn> GLV1;
2479
0
    GLV1::initForSecp256k1();
2480
0
    Ec::setMulVecGLV(mcl::ec::mulVecGLVT<GLV1, Ec, Zn>);
2481
0
  } else {
2482
0
    Ec::setMulVecGLV(0);
2483
0
  }
2484
0
}
2485
2486
#ifndef CYBOZU_DONT_USE_EXCEPTION
2487
template<class Ec>
2488
void initCurve(int curveType, Ec *P = 0, mcl::fp::Mode mode = fp::FP_AUTO, mcl::ec::Mode ecMode = ec::Jacobi)
2489
{
2490
  bool b;
2491
  initCurve<Ec>(&b, curveType, P, mode, ecMode);
2492
  if (!b) throw cybozu::Exception("mcl:initCurve") << curveType << mode << ecMode;
2493
}
2494
#endif
2495
2496
} // mcl
2497
2498
#ifndef CYBOZU_DONT_USE_EXCEPTION
2499
#ifdef CYBOZU_USE_BOOST
2500
namespace mcl {
2501
template<class Fp, class Fr>
2502
size_t hash_value(const mcl::EcT<Fp, Fr>& P_)
2503
{
2504
  if (P_.isZero()) return 0;
2505
  mcl::EcT<Fp, Fr> P(P_); P.normalize();
2506
  return mcl::hash_value(P.y, mcl::hash_value(P.x));
2507
}
2508
2509
}
2510
#else
2511
namespace std { CYBOZU_NAMESPACE_TR1_BEGIN
2512
2513
template<class Fp, class Fr>
2514
struct hash<mcl::EcT<Fp, Fr> > {
2515
  size_t operator()(const mcl::EcT<Fp, Fr>& P_) const
2516
  {
2517
    if (P_.isZero()) return 0;
2518
    mcl::EcT<Fp, Fr> P(P_); P.normalize();
2519
    return hash<Fp>()(P.y, hash<Fp>()(P.x));
2520
  }
2521
};
2522
2523
CYBOZU_NAMESPACE_TR1_END } // std
2524
#endif
2525
#endif
2526
2527
#ifdef _MSC_VER
2528
  #pragma warning(pop)
2529
#endif