Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
8.9 KiB

  1. // algebra.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice
  4. #define CRYPTOPP_ALGEBRA_CPP
  5. #include "algebra.h"
  6. #include "integer.h"
  7. #include <vector>
  8. NAMESPACE_BEGIN(CryptoPP)
  9. template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
  10. {
  11. return Add(a, a);
  12. }
  13. template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
  14. {
  15. // make copy of a in case Inverse() overwrites it
  16. Element a1(a);
  17. return Add(a1, Inverse(b));
  18. }
  19. template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
  20. {
  21. return a = Add(a, b);
  22. }
  23. template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
  24. {
  25. return a = Subtract(a, b);
  26. }
  27. template <class T> const T& AbstractRing<T>::Square(const Element &a) const
  28. {
  29. return Multiply(a, a);
  30. }
  31. template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
  32. {
  33. // make copy of a in case MultiplicativeInverse() overwrites it
  34. Element a1(a);
  35. return Multiply(a1, MultiplicativeInverse(b));
  36. }
  37. template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
  38. {
  39. Element q;
  40. DivisionAlgorithm(result, q, a, b);
  41. return result;
  42. }
  43. template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
  44. {
  45. Element g[3]={b, a};
  46. unsigned int i0=0, i1=1, i2=2;
  47. while (!Equal(g[i1], this->Identity()))
  48. {
  49. g[i2] = Mod(g[i0], g[i1]);
  50. unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
  51. }
  52. return result = g[i0];
  53. }
  54. template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
  55. {
  56. Element g[3]={m_modulus, a};
  57. Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
  58. Element y;
  59. unsigned int i0=0, i1=1, i2=2;
  60. while (!Equal(g[i1], Identity()))
  61. {
  62. // y = g[i0] / g[i1];
  63. // g[i2] = g[i0] % g[i1];
  64. m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
  65. // v[i2] = v[i0] - (v[i1] * y);
  66. v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
  67. unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
  68. }
  69. return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
  70. }
  71. template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
  72. {
  73. Element result;
  74. SimultaneousMultiply(&result, base, &exponent, 1);
  75. return result;
  76. }
  77. template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
  78. {
  79. const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
  80. if (expLen==0)
  81. return Identity();
  82. const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
  83. const unsigned tableSize = 1<<w;
  84. std::vector<Element> powerTable(tableSize << w);
  85. powerTable[1] = x;
  86. powerTable[tableSize] = y;
  87. if (w==1)
  88. powerTable[3] = Add(x,y);
  89. else
  90. {
  91. powerTable[2] = Double(x);
  92. powerTable[2*tableSize] = Double(y);
  93. unsigned i, j;
  94. for (i=3; i<tableSize; i+=2)
  95. powerTable[i] = Add(powerTable[i-2], powerTable[2]);
  96. for (i=1; i<tableSize; i+=2)
  97. for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
  98. powerTable[j] = Add(powerTable[j-tableSize], y);
  99. for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
  100. powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
  101. for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
  102. for (j=i+2; j<i+tableSize; j+=2)
  103. powerTable[j] = Add(powerTable[j-1], x);
  104. }
  105. Element result;
  106. unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
  107. bool firstTime = true;
  108. for (int i = expLen-1; i>=0; i--)
  109. {
  110. power1 = 2*power1 + e1.GetBit(i);
  111. power2 = 2*power2 + e2.GetBit(i);
  112. if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
  113. {
  114. unsigned squaresBefore = prevPosition-i;
  115. unsigned squaresAfter = 0;
  116. prevPosition = i;
  117. while ((power1 || power2) && power1%2 == 0 && power2%2==0)
  118. {
  119. power1 /= 2;
  120. power2 /= 2;
  121. squaresBefore--;
  122. squaresAfter++;
  123. }
  124. if (firstTime)
  125. {
  126. result = powerTable[(power2<<w) + power1];
  127. firstTime = false;
  128. }
  129. else
  130. {
  131. while (squaresBefore--)
  132. result = Double(result);
  133. if (power1 || power2)
  134. Accumulate(result, powerTable[(power2<<w) + power1]);
  135. }
  136. while (squaresAfter--)
  137. result = Double(result);
  138. power1 = power2 = 0;
  139. }
  140. }
  141. return result;
  142. }
  143. template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
  144. {
  145. if (end-begin == 1)
  146. return group.ScalarMultiply(begin->base, begin->exponent);
  147. else if (end-begin == 2)
  148. return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
  149. else
  150. {
  151. Integer q, t;
  152. Iterator last = end;
  153. --last;
  154. std::make_heap(begin, end);
  155. std::pop_heap(begin, end);
  156. while (!!begin->exponent)
  157. {
  158. // last->exponent is largest exponent, begin->exponent is next largest
  159. t = last->exponent;
  160. Integer::Divide(last->exponent, q, t, begin->exponent);
  161. if (q == Integer::One())
  162. group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
  163. else
  164. group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
  165. std::push_heap(begin, end);
  166. std::pop_heap(begin, end);
  167. }
  168. return group.ScalarMultiply(last->base, last->exponent);
  169. }
  170. }
  171. struct WindowSlider
  172. {
  173. WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0)
  174. : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
  175. {
  176. if (windowSize == 0)
  177. {
  178. unsigned int expLen = exp.BitCount();
  179. windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
  180. }
  181. windowModulus <<= windowSize;
  182. }
  183. void FindNextWindow()
  184. {
  185. unsigned int expLen = exp.WordCount() * WORD_BITS;
  186. unsigned int skipCount = firstTime ? 0 : windowSize;
  187. firstTime = false;
  188. while (!exp.GetBit(skipCount))
  189. {
  190. if (skipCount >= expLen)
  191. {
  192. finished = true;
  193. return;
  194. }
  195. skipCount++;
  196. }
  197. exp >>= skipCount;
  198. windowBegin += skipCount;
  199. expWindow = word32(exp % (word(1) << windowSize));
  200. if (fastNegate && exp.GetBit(windowSize))
  201. {
  202. negateNext = true;
  203. expWindow = (word32(1) << windowSize) - expWindow;
  204. exp += windowModulus;
  205. }
  206. else
  207. negateNext = false;
  208. }
  209. Integer exp, windowModulus;
  210. unsigned int windowSize, windowBegin;
  211. word32 expWindow;
  212. bool fastNegate, negateNext, firstTime, finished;
  213. };
  214. template <class T>
  215. void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
  216. {
  217. std::vector<std::vector<Element> > buckets(expCount);
  218. std::vector<WindowSlider> exponents;
  219. exponents.reserve(expCount);
  220. unsigned int i;
  221. for (i=0; i<expCount; i++)
  222. {
  223. assert(expBegin->NotNegative());
  224. exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
  225. exponents[i].FindNextWindow();
  226. buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
  227. }
  228. unsigned int expBitPosition = 0;
  229. Element g = base;
  230. bool notDone = true;
  231. while (notDone)
  232. {
  233. notDone = false;
  234. for (i=0; i<expCount; i++)
  235. {
  236. if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
  237. {
  238. Element &bucket = buckets[i][exponents[i].expWindow/2];
  239. if (exponents[i].negateNext)
  240. Accumulate(bucket, Inverse(g));
  241. else
  242. Accumulate(bucket, g);
  243. exponents[i].FindNextWindow();
  244. }
  245. notDone = notDone || !exponents[i].finished;
  246. }
  247. if (notDone)
  248. {
  249. g = Double(g);
  250. expBitPosition++;
  251. }
  252. }
  253. for (i=0; i<expCount; i++)
  254. {
  255. Element &r = *results++;
  256. r = buckets[i][buckets[i].size()-1];
  257. if (buckets[i].size() > 1)
  258. {
  259. for (int j = (int)buckets[i].size()-2; j >= 1; j--)
  260. {
  261. Accumulate(buckets[i][j], buckets[i][j+1]);
  262. Accumulate(r, buckets[i][j]);
  263. }
  264. Accumulate(buckets[i][0], buckets[i][1]);
  265. r = Add(Double(r), buckets[i][0]);
  266. }
  267. }
  268. }
  269. template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
  270. {
  271. Element result;
  272. SimultaneousExponentiate(&result, base, &exponent, 1);
  273. return result;
  274. }
  275. template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
  276. {
  277. return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
  278. }
  279. template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
  280. {
  281. return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
  282. }
  283. template <class T>
  284. void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
  285. {
  286. MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
  287. }
  288. NAMESPACE_END
  289. #endif