algebra.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. // algebra.h - originally written and placed in the public domain by Wei Dai
  2. /// \file algebra.h
  3. /// \brief Classes for performing mathematics over different fields
  4. #ifndef CRYPTOPP_ALGEBRA_H
  5. #define CRYPTOPP_ALGEBRA_H
  6. #include "config.h"
  7. #include "integer.h"
  8. #include "misc.h"
  9. NAMESPACE_BEGIN(CryptoPP)
  10. class Integer;
  11. /// \brief Abstract group
  12. /// \tparam T element class or type
  13. /// \details <tt>const Element&</tt> returned by member functions are references
  14. /// to internal data members. Since each object may have only
  15. /// one such data member for holding results, the following code
  16. /// will produce incorrect results:
  17. /// <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
  18. /// But this should be fine:
  19. /// <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
  20. template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
  21. {
  22. public:
  23. typedef T Element;
  24. virtual ~AbstractGroup() {}
  25. /// \brief Compare two elements for equality
  26. /// \param a first element
  27. /// \param b second element
  28. /// \return true if the elements are equal, false otherwise
  29. /// \details Equal() tests the elements for equality using <tt>a==b</tt>
  30. virtual bool Equal(const Element &a, const Element &b) const =0;
  31. /// \brief Provides the Identity element
  32. /// \return the Identity element
  33. virtual const Element& Identity() const =0;
  34. /// \brief Adds elements in the group
  35. /// \param a first element
  36. /// \param b second element
  37. /// \return the sum of <tt>a</tt> and <tt>b</tt>
  38. virtual const Element& Add(const Element &a, const Element &b) const =0;
  39. /// \brief Inverts the element in the group
  40. /// \param a first element
  41. /// \return the inverse of the element
  42. virtual const Element& Inverse(const Element &a) const =0;
  43. /// \brief Determine if inversion is fast
  44. /// \return true if inversion is fast, false otherwise
  45. virtual bool InversionIsFast() const {return false;}
  46. /// \brief Doubles an element in the group
  47. /// \param a the element
  48. /// \return the element doubled
  49. virtual const Element& Double(const Element &a) const;
  50. /// \brief Subtracts elements in the group
  51. /// \param a first element
  52. /// \param b second element
  53. /// \return the difference of <tt>a</tt> and <tt>b</tt>. The element <tt>a</tt> must provide a Subtract member function.
  54. virtual const Element& Subtract(const Element &a, const Element &b) const;
  55. /// \brief TODO
  56. /// \param a first element
  57. /// \param b second element
  58. /// \return TODO
  59. virtual Element& Accumulate(Element &a, const Element &b) const;
  60. /// \brief Reduces an element in the congruence class
  61. /// \param a element to reduce
  62. /// \param b the congruence class
  63. /// \return the reduced element
  64. virtual Element& Reduce(Element &a, const Element &b) const;
  65. /// \brief Performs a scalar multiplication
  66. /// \param a multiplicand
  67. /// \param e multiplier
  68. /// \return the product
  69. virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
  70. /// \brief TODO
  71. /// \param x first multiplicand
  72. /// \param e1 the first multiplier
  73. /// \param y second multiplicand
  74. /// \param e2 the second multiplier
  75. /// \return TODO
  76. virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
  77. /// \brief Multiplies a base to multiple exponents in a group
  78. /// \param results an array of Elements
  79. /// \param base the base to raise to the exponents
  80. /// \param exponents an array of exponents
  81. /// \param exponentsCount the number of exponents in the array
  82. /// \details SimultaneousMultiply() multiplies the base to each exponent in the exponents array and stores the
  83. /// result at the respective position in the results array.
  84. /// \details SimultaneousMultiply() must be implemented in a derived class.
  85. /// \pre <tt>COUNTOF(results) == exponentsCount</tt>
  86. /// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
  87. virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
  88. };
  89. /// \brief Abstract ring
  90. /// \tparam T element class or type
  91. /// \details <tt>const Element&</tt> returned by member functions are references
  92. /// to internal data members. Since each object may have only
  93. /// one such data member for holding results, the following code
  94. /// will produce incorrect results:
  95. /// <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
  96. /// But this should be fine:
  97. /// <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
  98. template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
  99. {
  100. public:
  101. typedef T Element;
  102. /// \brief Construct an AbstractRing
  103. AbstractRing() {m_mg.m_pRing = this;}
  104. /// \brief Copy construct an AbstractRing
  105. /// \param source other AbstractRing
  106. AbstractRing(const AbstractRing &source)
  107. {CRYPTOPP_UNUSED(source); m_mg.m_pRing = this;}
  108. /// \brief Assign an AbstractRing
  109. /// \param source other AbstractRing
  110. AbstractRing& operator=(const AbstractRing &source)
  111. {CRYPTOPP_UNUSED(source); return *this;}
  112. /// \brief Determines whether an element is a unit in the group
  113. /// \param a the element
  114. /// \return true if the element is a unit after reduction, false otherwise.
  115. virtual bool IsUnit(const Element &a) const =0;
  116. /// \brief Retrieves the multiplicative identity
  117. /// \return the multiplicative identity
  118. virtual const Element& MultiplicativeIdentity() const =0;
  119. /// \brief Multiplies elements in the group
  120. /// \param a the multiplicand
  121. /// \param b the multiplier
  122. /// \return the product of a and b
  123. virtual const Element& Multiply(const Element &a, const Element &b) const =0;
  124. /// \brief Calculate the multiplicative inverse of an element in the group
  125. /// \param a the element
  126. virtual const Element& MultiplicativeInverse(const Element &a) const =0;
  127. /// \brief Square an element in the group
  128. /// \param a the element
  129. /// \return the element squared
  130. virtual const Element& Square(const Element &a) const;
  131. /// \brief Divides elements in the group
  132. /// \param a the dividend
  133. /// \param b the divisor
  134. /// \return the quotient
  135. virtual const Element& Divide(const Element &a, const Element &b) const;
  136. /// \brief Raises a base to an exponent in the group
  137. /// \param a the base
  138. /// \param e the exponent
  139. /// \return the exponentiation
  140. virtual Element Exponentiate(const Element &a, const Integer &e) const;
  141. /// \brief TODO
  142. /// \param x first element
  143. /// \param e1 first exponent
  144. /// \param y second element
  145. /// \param e2 second exponent
  146. /// \return TODO
  147. virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
  148. /// \brief Exponentiates a base to multiple exponents in the Ring
  149. /// \param results an array of Elements
  150. /// \param base the base to raise to the exponents
  151. /// \param exponents an array of exponents
  152. /// \param exponentsCount the number of exponents in the array
  153. /// \details SimultaneousExponentiate() raises the base to each exponent in the exponents array and stores the
  154. /// result at the respective position in the results array.
  155. /// \details SimultaneousExponentiate() must be implemented in a derived class.
  156. /// \pre <tt>COUNTOF(results) == exponentsCount</tt>
  157. /// \pre <tt>COUNTOF(exponents) == exponentsCount</tt>
  158. virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
  159. /// \brief Retrieves the multiplicative group
  160. /// \return the multiplicative group
  161. virtual const AbstractGroup<T>& MultiplicativeGroup() const
  162. {return m_mg;}
  163. private:
  164. class MultiplicativeGroupT : public AbstractGroup<T>
  165. {
  166. public:
  167. const AbstractRing<T>& GetRing() const
  168. {return *m_pRing;}
  169. bool Equal(const Element &a, const Element &b) const
  170. {return GetRing().Equal(a, b);}
  171. const Element& Identity() const
  172. {return GetRing().MultiplicativeIdentity();}
  173. const Element& Add(const Element &a, const Element &b) const
  174. {return GetRing().Multiply(a, b);}
  175. Element& Accumulate(Element &a, const Element &b) const
  176. {return a = GetRing().Multiply(a, b);}
  177. const Element& Inverse(const Element &a) const
  178. {return GetRing().MultiplicativeInverse(a);}
  179. const Element& Subtract(const Element &a, const Element &b) const
  180. {return GetRing().Divide(a, b);}
  181. Element& Reduce(Element &a, const Element &b) const
  182. {return a = GetRing().Divide(a, b);}
  183. const Element& Double(const Element &a) const
  184. {return GetRing().Square(a);}
  185. Element ScalarMultiply(const Element &a, const Integer &e) const
  186. {return GetRing().Exponentiate(a, e);}
  187. Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
  188. {return GetRing().CascadeExponentiate(x, e1, y, e2);}
  189. void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
  190. {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
  191. const AbstractRing<T> *m_pRing;
  192. };
  193. MultiplicativeGroupT m_mg;
  194. };
  195. // ********************************************************
  196. /// \brief Base and exponent
  197. /// \tparam T base class or type
  198. /// \tparam E exponent class or type
  199. template <class T, class E = Integer>
  200. struct BaseAndExponent
  201. {
  202. public:
  203. BaseAndExponent() {}
  204. BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
  205. bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
  206. T base;
  207. E exponent;
  208. };
  209. // VC60 workaround: incomplete member template support
  210. template <class Element, class Iterator>
  211. Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
  212. template <class Element, class Iterator>
  213. Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
  214. // ********************************************************
  215. /// \brief Abstract Euclidean domain
  216. /// \tparam T element class or type
  217. /// \details <tt>const Element&</tt> returned by member functions are references
  218. /// to internal data members. Since each object may have only
  219. /// one such data member for holding results, the following code
  220. /// will produce incorrect results:
  221. /// <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
  222. /// But this should be fine:
  223. /// <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
  224. template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
  225. {
  226. public:
  227. typedef T Element;
  228. /// \brief Performs the division algorithm on two elements in the ring
  229. /// \param r the remainder
  230. /// \param q the quotient
  231. /// \param a the dividend
  232. /// \param d the divisor
  233. virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
  234. /// \brief Performs a modular reduction in the ring
  235. /// \param a the element
  236. /// \param b the modulus
  237. /// \return the result of <tt>a%b</tt>.
  238. virtual const Element& Mod(const Element &a, const Element &b) const =0;
  239. /// \brief Calculates the greatest common denominator in the ring
  240. /// \param a the first element
  241. /// \param b the second element
  242. /// \return the greatest common denominator of a and b.
  243. virtual const Element& Gcd(const Element &a, const Element &b) const;
  244. protected:
  245. mutable Element result;
  246. };
  247. // ********************************************************
  248. /// \brief Euclidean domain
  249. /// \tparam T element class or type
  250. /// \details <tt>const Element&</tt> returned by member functions are references
  251. /// to internal data members. Since each object may have only
  252. /// one such data member for holding results, the following code
  253. /// will produce incorrect results:
  254. /// <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
  255. /// But this should be fine:
  256. /// <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
  257. template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
  258. {
  259. public:
  260. typedef T Element;
  261. EuclideanDomainOf() {}
  262. bool Equal(const Element &a, const Element &b) const
  263. {return a==b;}
  264. const Element& Identity() const
  265. {return Element::Zero();}
  266. const Element& Add(const Element &a, const Element &b) const
  267. {return result = a+b;}
  268. Element& Accumulate(Element &a, const Element &b) const
  269. {return a+=b;}
  270. const Element& Inverse(const Element &a) const
  271. {return result = -a;}
  272. const Element& Subtract(const Element &a, const Element &b) const
  273. {return result = a-b;}
  274. Element& Reduce(Element &a, const Element &b) const
  275. {return a-=b;}
  276. const Element& Double(const Element &a) const
  277. {return result = a.Doubled();}
  278. const Element& MultiplicativeIdentity() const
  279. {return Element::One();}
  280. const Element& Multiply(const Element &a, const Element &b) const
  281. {return result = a*b;}
  282. const Element& Square(const Element &a) const
  283. {return result = a.Squared();}
  284. bool IsUnit(const Element &a) const
  285. {return a.IsUnit();}
  286. const Element& MultiplicativeInverse(const Element &a) const
  287. {return result = a.MultiplicativeInverse();}
  288. const Element& Divide(const Element &a, const Element &b) const
  289. {return result = a/b;}
  290. const Element& Mod(const Element &a, const Element &b) const
  291. {return result = a%b;}
  292. void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
  293. {Element::Divide(r, q, a, d);}
  294. bool operator==(const EuclideanDomainOf<T> &rhs) const
  295. {CRYPTOPP_UNUSED(rhs); return true;}
  296. private:
  297. mutable Element result;
  298. };
  299. /// \brief Quotient ring
  300. /// \tparam T element class or type
  301. /// \details <tt>const Element&</tt> returned by member functions are references
  302. /// to internal data members. Since each object may have only
  303. /// one such data member for holding results, the following code
  304. /// will produce incorrect results:
  305. /// <pre> abcd = group.Add(group.Add(a,b), group.Add(c,d));</pre>
  306. /// But this should be fine:
  307. /// <pre> abcd = group.Add(a, group.Add(b, group.Add(c,d));</pre>
  308. template <class T> class QuotientRing : public AbstractRing<typename T::Element>
  309. {
  310. public:
  311. typedef T EuclideanDomain;
  312. typedef typename T::Element Element;
  313. QuotientRing(const EuclideanDomain &domain, const Element &modulus)
  314. : m_domain(domain), m_modulus(modulus) {}
  315. const EuclideanDomain & GetDomain() const
  316. {return m_domain;}
  317. const Element& GetModulus() const
  318. {return m_modulus;}
  319. bool Equal(const Element &a, const Element &b) const
  320. {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
  321. const Element& Identity() const
  322. {return m_domain.Identity();}
  323. const Element& Add(const Element &a, const Element &b) const
  324. {return m_domain.Add(a, b);}
  325. Element& Accumulate(Element &a, const Element &b) const
  326. {return m_domain.Accumulate(a, b);}
  327. const Element& Inverse(const Element &a) const
  328. {return m_domain.Inverse(a);}
  329. const Element& Subtract(const Element &a, const Element &b) const
  330. {return m_domain.Subtract(a, b);}
  331. Element& Reduce(Element &a, const Element &b) const
  332. {return m_domain.Reduce(a, b);}
  333. const Element& Double(const Element &a) const
  334. {return m_domain.Double(a);}
  335. bool IsUnit(const Element &a) const
  336. {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
  337. const Element& MultiplicativeIdentity() const
  338. {return m_domain.MultiplicativeIdentity();}
  339. const Element& Multiply(const Element &a, const Element &b) const
  340. {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
  341. const Element& Square(const Element &a) const
  342. {return m_domain.Mod(m_domain.Square(a), m_modulus);}
  343. const Element& MultiplicativeInverse(const Element &a) const;
  344. bool operator==(const QuotientRing<T> &rhs) const
  345. {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
  346. protected:
  347. EuclideanDomain m_domain;
  348. Element m_modulus;
  349. };
  350. NAMESPACE_END
  351. #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
  352. #include "algebra.cpp"
  353. #endif
  354. #endif