kronecker_substitution.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2020-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_MATH_KRONECKER_SUBSTITUTION_HPP
27 #define CRYPTO3_MATH_KRONECKER_SUBSTITUTION_HPP
28 
29 #include <vector>
30 #include <algorithm>
31 #include <cmath>
32 
33 #include <boost/math/tools/polynomial.hpp>
34 
35 namespace nil {
36  namespace crypto3 {
37  namespace math {
38  namespace polynomial {
46  template<typename FieldType>
47  void kronecker_substitution(std::vector<typename FieldType::value_type>& v3,
48  const std::vector<typename FieldType::value_type>& v1,
49  const std::vector<typename FieldType::value_type>& v2) {
50  typedef typename FieldType::value_type value_type;
51 
52  // Initialize
53  bool square = (v1 == v2) ? 1 : 0;
54 
55  // Polynomial length
56  std::size_t n1 = v1.size();
57  std::size_t n2 = v2.size();
58  std::size_t n3 = n1 + n2 - 1;
59 
60  // Determine number of bits needed
61  value_type v1_max = *max_element(std::begin(v1), std::end(v1));
62  value_type v2_max = *max_element(std::begin(v2), std::end(v2));
63  /*size_t b = 2 * (v1_max * v2_max).as_bigint().num_bits() + 1;
64 
65 
66  // Number of limbs needed in total
67  std::size_t k1 = (n1 * b + (GMP_NUMB_BITS)-1) / GMP_NUMB_BITS;
68  std::size_t k2 = (n2 * b + (GMP_NUMB_BITS)-1) / GMP_NUMB_BITS;
69 
70 
71  // Output polynomial
72  v3.resize(n3, value_type::zero());
73 
74  // Allocate all MP_LIMB_T space once and store the reference pointer M1
75  // to free memory afterwards. P1, P2, and P3 will remain fixed pointers
76  // to the start of their respective polynomials as reference.
77  mp_limb_t* m1 = (mp_limb_t*)malloc(sizeof(mp_limb_t) * 2 * (k1 + k2));
78  mp_limb_t* p1 = m1;
79  mp_limb_t* p2 = p1 + k1;
80  mp_limb_t* p3 = p2 + k2;
81 
82  // Helper variables
83  mp_limb_t* ref;
84  mp_limb_t limb;
85  unsigned long val;
86  unsigned long mask;
87  unsigned long limb_b;
88  unsigned long delta;
89  unsigned long delta_b;
90 
91  // Construct P1 limb
92  ref = p1;
93  limb = 0;
94  limb_b = 0;
95  for (std::size_t i = 0; i < n1; i++) {
96  val = v1[i].as_ulong();
97  limb += (val << limb_b);
98 
99  // If the next iteration of LIMB_B is >= to the GMP_LIMB_BITS, then
100  // write it out to MP_LIMB_T* and reset LIMB. If VAL has remaining
101  // bits due to GMP_LIMB_BITS boundary, set it in LIMB and proceed.
102  if (limb_b + b >= GMP_LIMB_BITS) {
103  *ref++ = limb;
104  limb = limb_b ? (val >> (GMP_LIMB_BITS - limb_b)) : 0;
105  limb_b -= GMP_LIMB_BITS;
106  }
107  limb_b += b;
108  }
109  if (limb_b)
110  *ref++ = limb;
111 
112  // Construct P2 limb. If V2 == V1, then P2 = P1 - square case.
113  if (square)
114  p2 = p1;
115  else {
116  ref = p2;
117  limb = 0;
118  limb_b = 0;
119  for (std::size_t i = 0; i < n2; i++) {
120  val = v2[i].as_ulong();
121  limb += (val << limb_b);
122 
123  // If the next iteration of LIMB_B is >= to the GMP_LIMB_BITS, then
124  // write it out to MP_LIMB_T* and reset LIMB. If VAL has remaining
125  // bits due to GMP_LIMB_BITS boundary, set it in LIMB and proceed.
126  if (limb_b + b >= GMP_LIMB_BITS) {
127  *ref++ = limb;
128  limb = limb_b ? (val >> (GMP_LIMB_BITS - limb_b)) : 0;
129  limb_b -= GMP_LIMB_BITS;
130  }
131  limb_b += b;
132  }
133  if (limb_b)
134  *ref++ = limb;
135  }
136 
137  // Multiply P1 and P2 limbs and store result in P3 limb.
138  mpn_mul(p3, p1, k1, p2, k2);
139 
140  // Perfect alignment case: bits B is equivalent to GMP_LIMB_BITS
141  if (b == GMP_LIMB_BITS)
142  for (std::size_t i = 0; i < n3; i++)
143  v3[i] = value_type(*p3++);
144  // Non-alignment case
145  else {
146  // Mask of 2^b - 1
147  mask = (1UL << b) - 1;
148 
149  limb = 0;
150  limb_b = 0;
151  for (std::size_t i = 0; i < n3; i++) {
152 
153  // If the coefficient's bit length is contained in LIMB, then
154  // write the masked value out to vector V3 and decrement LIMB
155  // by B bits.
156  if (b <= limb_b) {
157  v3[i] = value_type(limb & mask);
158 
159  delta = b;
160  delta_b = limb_b - delta;
161  }
162 
163  // If the remaining coefficient is across two LIMBs, then write
164  // to vector V3 the current limb's value and add upper bits from
165  // the second part. Lastly, decrement LIMB by the coefficient's
166  // upper portion bit length.
167  else {
168  v3[i] = value_type(limb);
169  v3[i] += value_type(((limb = *p3++) << limb_b) & mask);
170 
171  delta = b - limb_b;
172  delta_b = GMP_LIMB_BITS - delta;
173  }
174 
175  limb >>= delta;
176  limb_b = delta_b;
177  }
178  }
179 
180  // Free memory
181  free(m1);
182 
183  _condense(v3);*/
184  }
185 
190  template<typename FieldType>
191  void multiplication_on_kronecker(std::vector<typename FieldType::value_type>& c,
192  const std::vector<typename FieldType::value_type>& a,
193  const std::vector<typename FieldType::value_type>& b) {
194  kronecker_substitution<FieldType>(c, a, b);
195  }
196  } // namespace polynomial
197  } // namespace fft
198  } // namespace crypto3
199 } // namespace nil
200 
201 #endif // ALGEBRA_FFT_KRONECKER_SUBSTITUTION_HPP
Definition: polynomial.hpp:38
container_type::value_type value_type
Definition: polynomial.hpp:44
void kronecker_substitution(std::vector< typename FieldType::value_type > &v3, const std::vector< typename FieldType::value_type > &v1, const std::vector< typename FieldType::value_type > &v2)
Given two polynomial vectors, A and B, the function performs polynomial multiplication and returns th...
Definition: kronecker_substitution.hpp:47
void multiplication_on_kronecker(std::vector< typename FieldType::value_type > &c, const std::vector< typename FieldType::value_type > &a, const std::vector< typename FieldType::value_type > &b)
Definition: kronecker_substitution.hpp:191
Definition: pair.hpp:31