MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
algebra.cpp
1 /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 /* based on Wei Dai's algebra.cpp from CryptoPP */
17 #undef NDEBUG
18 #define DEBUG // GCC 4.0 bug if NDEBUG and Optimize > 1
19 
20 #include "runtime.hpp"
21 #include "algebra.hpp"
22 #ifdef USE_SYS_STL
23  #include <vector>
24 #else
25  #include "vector.hpp"
26 #endif
27 
28 
29 namespace STL = STL_NAMESPACE;
30 
31 
32 namespace TaoCrypt {
33 
34 
35 const Integer& AbstractGroup::Double(const Element &a) const
36 {
37  return Add(a, a);
38 }
39 
40 const Integer& AbstractGroup::Subtract(const Element &a, const Element &b) const
41 {
42  // make copy of a in case Inverse() overwrites it
43  Element a1(a);
44  return Add(a1, Inverse(b));
45 }
46 
47 Integer& AbstractGroup::Accumulate(Element &a, const Element &b) const
48 {
49  return a = Add(a, b);
50 }
51 
52 Integer& AbstractGroup::Reduce(Element &a, const Element &b) const
53 {
54  return a = Subtract(a, b);
55 }
56 
57 const Integer& AbstractRing::Square(const Element &a) const
58 {
59  return Multiply(a, a);
60 }
61 
62 
63 const Integer& AbstractRing::Divide(const Element &a, const Element &b) const
64 {
65  // make copy of a in case MultiplicativeInverse() overwrites it
66  Element a1(a);
67  return Multiply(a1, MultiplicativeInverse(b));
68 }
69 
70 
71 const Integer& AbstractEuclideanDomain::Mod(const Element &a,
72  const Element &b) const
73 {
74  Element q;
75  DivisionAlgorithm(result, q, a, b);
76  return result;
77 }
78 
79 const Integer& AbstractEuclideanDomain::Gcd(const Element &a,
80  const Element &b) const
81 {
82  STL::vector<Element> g(3);
83  g[0]= b;
84  g[1]= a;
85  unsigned int i0=0, i1=1, i2=2;
86 
87  while (!Equal(g[i1], this->Identity()))
88  {
89  g[i2] = Mod(g[i0], g[i1]);
90  unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
91  }
92 
93  return result = g[i0];
94 }
95 
96 
97 Integer AbstractGroup::ScalarMultiply(const Element &base,
98  const Integer &exponent) const
99 {
100  Element result;
101  SimultaneousMultiply(&result, base, &exponent, 1);
102  return result;
103 }
104 
105 
106 Integer AbstractGroup::CascadeScalarMultiply(const Element &x,
107  const Integer &e1, const Element &y, const Integer &e2) const
108 {
109  const unsigned expLen = max(e1.BitCount(), e2.BitCount());
110  if (expLen==0)
111  return Identity();
112 
113  const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
114  const unsigned tableSize = 1<<w;
115  STL::vector<Element> powerTable(tableSize << w);
116 
117  powerTable[1] = x;
118  powerTable[tableSize] = y;
119  if (w==1)
120  powerTable[3] = Add(x,y);
121  else
122  {
123  powerTable[2] = Double(x);
124  powerTable[2*tableSize] = Double(y);
125 
126  unsigned i, j;
127 
128  for (i=3; i<tableSize; i+=2)
129  powerTable[i] = Add(powerTable[i-2], powerTable[2]);
130  for (i=1; i<tableSize; i+=2)
131  for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
132  powerTable[j] = Add(powerTable[j-tableSize], y);
133 
134  for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
135  powerTable[i] = Add(powerTable[i-2*tableSize],
136  powerTable[2*tableSize]);
137  for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
138  for (j=i+2; j<i+tableSize; j+=2)
139  powerTable[j] = Add(powerTable[j-1], x);
140  }
141 
142  Element result;
143  unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
144  bool firstTime = true;
145 
146  for (int i = expLen-1; i>=0; i--)
147  {
148  power1 = 2*power1 + e1.GetBit(i);
149  power2 = 2*power2 + e2.GetBit(i);
150 
151  if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
152  {
153  unsigned squaresBefore = prevPosition-i;
154  unsigned squaresAfter = 0;
155  prevPosition = i;
156  while ((power1 || power2) && power1%2 == 0 && power2%2==0)
157  {
158  power1 /= 2;
159  power2 /= 2;
160  squaresBefore--;
161  squaresAfter++;
162  }
163  if (firstTime)
164  {
165  result = powerTable[(power2<<w) + power1];
166  firstTime = false;
167  }
168  else
169  {
170  while (squaresBefore--)
171  result = Double(result);
172  if (power1 || power2)
173  Accumulate(result, powerTable[(power2<<w) + power1]);
174  }
175  while (squaresAfter--)
176  result = Double(result);
177  power1 = power2 = 0;
178  }
179  }
180  return result;
181 }
182 
183 
185 {
186  WindowSlider(const Integer &expIn, bool fastNegateIn,
187  unsigned int windowSizeIn=0)
188  : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn),
189  windowBegin(0), fastNegate(fastNegateIn), firstTime(true),
190  finished(false)
191  {
192  if (windowSize == 0)
193  {
194  unsigned int expLen = exp.BitCount();
195  windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 :
196  (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 :
197  (expLen <= 1434 ? 6 : 7)))));
198  }
199  windowModulus <<= windowSize;
200  }
201 
202  void FindNextWindow()
203  {
204  unsigned int expLen = exp.WordCount() * WORD_BITS;
205  unsigned int skipCount = firstTime ? 0 : windowSize;
206  firstTime = false;
207  while (!exp.GetBit(skipCount))
208  {
209  if (skipCount >= expLen)
210  {
211  finished = true;
212  return;
213  }
214  skipCount++;
215  }
216 
217  exp >>= skipCount;
218  windowBegin += skipCount;
219  expWindow = exp % (1 << windowSize);
220 
221  if (fastNegate && exp.GetBit(windowSize))
222  {
223  negateNext = true;
224  expWindow = (1 << windowSize) - expWindow;
225  exp += windowModulus;
226  }
227  else
228  negateNext = false;
229  }
230 
231  Integer exp, windowModulus;
232  unsigned int windowSize, windowBegin, expWindow;
233  bool fastNegate, negateNext, firstTime, finished;
234 };
235 
236 
237 void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base,
238  const Integer *expBegin, unsigned int expCount) const
239 {
240  STL::vector<STL::vector<Element> > buckets(expCount);
241  STL::vector<WindowSlider> exponents;
242  exponents.reserve(expCount);
243  unsigned int i;
244 
245  for (i=0; i<expCount; i++)
246  {
247  exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
248  exponents[i].FindNextWindow();
249  buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
250  }
251 
252  unsigned int expBitPosition = 0;
253  Element g = base;
254  bool notDone = true;
255 
256  while (notDone)
257  {
258  notDone = false;
259  for (i=0; i<expCount; i++)
260  {
261  if (!exponents[i].finished && expBitPosition ==
262  exponents[i].windowBegin)
263  {
264  Element &bucket = buckets[i][exponents[i].expWindow/2];
265  if (exponents[i].negateNext)
266  Accumulate(bucket, Inverse(g));
267  else
268  Accumulate(bucket, g);
269  exponents[i].FindNextWindow();
270  }
271  notDone = notDone || !exponents[i].finished;
272  }
273 
274  if (notDone)
275  {
276  g = Double(g);
277  expBitPosition++;
278  }
279  }
280 
281  for (i=0; i<expCount; i++)
282  {
283  Element &r = *results++;
284  r = buckets[i][buckets[i].size()-1];
285  if (buckets[i].size() > 1)
286  {
287  for (size_t j = buckets[i].size()-2; j >= 1; j--)
288  {
289  Accumulate(buckets[i][j], buckets[i][j+1]);
290  Accumulate(r, buckets[i][j]);
291  }
292  Accumulate(buckets[i][0], buckets[i][1]);
293  r = Add(Double(r), buckets[i][0]);
294  }
295  }
296 }
297 
298 Integer AbstractRing::Exponentiate(const Element &base,
299  const Integer &exponent) const
300 {
301  Element result;
302  SimultaneousExponentiate(&result, base, &exponent, 1);
303  return result;
304 }
305 
306 
307 Integer AbstractRing::CascadeExponentiate(const Element &x,
308  const Integer &e1, const Element &y, const Integer &e2) const
309 {
310  return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(
311  x, e1, y, e2);
312 }
313 
314 
315 void AbstractRing::SimultaneousExponentiate(Integer *results,
316  const Integer &base,
317  const Integer *exponents, unsigned int expCount) const
318 {
319  MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base,
320  exponents, expCount);
321 }
322 
323 
324 } // namespace
325 
326 
327 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
328 namespace mySTL {
329 template TaoCrypt::WindowSlider* uninit_copy<TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
330 template void destroy<TaoCrypt::WindowSlider*>(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*);
331 template TaoCrypt::WindowSlider* GetArrayMemory<TaoCrypt::WindowSlider>(size_t);
332 template void FreeArrayMemory<TaoCrypt::WindowSlider>(TaoCrypt::WindowSlider*);
333 }
334 #endif
335