Clearmatics Libff  0.1
C++ library for Finite Fields and Elliptic Curves
wnaf.tcc
Go to the documentation of this file.
1 /** @file
2  *****************************************************************************
3 
4  Implementation of interfaces for wNAF ("weighted Non-Adjacent Form")
5  exponentiation routines.
6 
7  See wnaf.hpp .
8 
9  *****************************************************************************
10  * @author This file is part of libff, developed by SCIPR Lab
11  * and contributors (see AUTHORS).
12  * @copyright MIT license (see LICENSE file)
13  *****************************************************************************/
14 
15 #ifndef WNAF_TCC_
16 #define WNAF_TCC_
17 
18 #include <gmp.h>
19 
20 namespace libff
21 {
22 
23 template<mp_size_t n>
24 void update_wnaf(
25  std::vector<long> &wnaf, const size_t window_size, const bigint<n> &scalar)
26 {
27  const size_t length = scalar.max_bits(); // upper bound
28  wnaf.resize(length + 1);
29  bigint<n> c = scalar;
30  long j = 0;
31  while (!c.is_zero()) {
32  long u;
33  if ((c.data[0] & 1) == 1) {
34  u = c.data[0] % (1u << (window_size + 1));
35  if (u > (1 << window_size)) {
36  u = u - (1 << (window_size + 1));
37  }
38 
39  if (u > 0) {
40  mpn_sub_1(c.data, c.data, n, u);
41  } else {
42  mpn_add_1(c.data, c.data, n, -u);
43  }
44  } else {
45  u = 0;
46  }
47  wnaf[j] = u;
48  ++j;
49 
50  mpn_rshift(c.data, c.data, n, 1); // c = c/2
51  }
52 
53  wnaf.resize(j);
54 }
55 
56 template<mp_size_t n>
57 std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
58 {
59  std::vector<long> res;
60  update_wnaf(res, window_size, scalar);
61  return res;
62 }
63 
64 template<typename T> size_t wnaf_opt_window_size(const size_t scalar_bits)
65 {
66  for (long i = T::wnaf_window_table.size() - 1; i >= 0; --i) {
67  if (scalar_bits >= T::wnaf_window_table[i]) {
68  return i + 1;
69  }
70  }
71 
72  return 0;
73 }
74 
75 template<typename T>
76 T fixed_window_wnaf_exp(
77  const size_t window_size, const T &base, const std::vector<long> &naf)
78 {
79  std::vector<T> table(1ul << (window_size - 1));
80  T tmp = base;
81  T dbl = base.dbl();
82  for (size_t i = 0; i < 1ul << (window_size - 1); ++i) {
83  table[i] = tmp;
84  tmp = tmp + dbl;
85  }
86 
87  T res = T::zero();
88  bool found_nonzero = false;
89  for (long i = naf.size() - 1; i >= 0; --i) {
90  if (found_nonzero) {
91  res = res.dbl();
92  }
93 
94  if (naf[i] != 0) {
95  found_nonzero = true;
96  if (naf[i] > 0) {
97  res = res + table[naf[i] / 2];
98  } else {
99  res = res - table[(-naf[i]) / 2];
100  }
101  }
102  }
103 
104  return res;
105 }
106 
107 template<typename T, mp_size_t n>
108 T fixed_window_wnaf_exp(
109  const size_t window_size, const T &base, const bigint<n> &scalar)
110 {
111  std::vector<long> naf = find_wnaf(window_size, scalar);
112  return fixed_window_wnaf_exp<T>(window_size, base, naf);
113 }
114 
115 template<typename T, mp_size_t n>
116 T opt_window_wnaf_exp(
117  const T &base, const bigint<n> &scalar, const size_t scalar_bits)
118 {
119  const size_t best = wnaf_opt_window_size<T>(scalar_bits);
120  if (best > 0) {
121  return fixed_window_wnaf_exp(best, base, scalar);
122  } else {
123  return scalar * base;
124  }
125 }
126 
127 } // namespace libff
128 
129 #endif // WNAF_TCC_