Team Fortress 2 Source Code as on 22/4/2020
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.

295 lines
9.0 KiB

  1. // algebra.h - written and placed in the public domain by Wei Dai
  2. //! \file
  3. //! \headerfile algebra.h
  4. //! \brief Classes for performing mathematics over different fields
  5. #ifndef CRYPTOPP_ALGEBRA_H
  6. #define CRYPTOPP_ALGEBRA_H
  7. #include "config.h"
  8. #include "misc.h"
  9. #include "integer.h"
  10. NAMESPACE_BEGIN(CryptoPP)
  11. class Integer;
  12. // "const Element&" returned by member functions are references
  13. // to internal data members. Since each object may have only
  14. // one such data member for holding results, the following code
  15. // will produce incorrect results:
  16. // abcd = group.Add(group.Add(a,b), group.Add(c,d));
  17. // But this should be fine:
  18. // abcd = group.Add(a, group.Add(b, group.Add(c,d));
  19. //! Abstract Group
  20. template <class T> class CRYPTOPP_NO_VTABLE AbstractGroup
  21. {
  22. public:
  23. typedef T Element;
  24. virtual ~AbstractGroup() {}
  25. virtual bool Equal(const Element &a, const Element &b) const =0;
  26. virtual const Element& Identity() const =0;
  27. virtual const Element& Add(const Element &a, const Element &b) const =0;
  28. virtual const Element& Inverse(const Element &a) const =0;
  29. virtual bool InversionIsFast() const {return false;}
  30. virtual const Element& Double(const Element &a) const;
  31. virtual const Element& Subtract(const Element &a, const Element &b) const;
  32. virtual Element& Accumulate(Element &a, const Element &b) const;
  33. virtual Element& Reduce(Element &a, const Element &b) const;
  34. virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
  35. virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
  36. virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
  37. };
  38. //! Abstract Ring
  39. template <class T> class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup<T>
  40. {
  41. public:
  42. typedef T Element;
  43. AbstractRing() {m_mg.m_pRing = this;}
  44. AbstractRing(const AbstractRing &source)
  45. {CRYPTOPP_UNUSED(source); m_mg.m_pRing = this;}
  46. AbstractRing& operator=(const AbstractRing &source)
  47. {CRYPTOPP_UNUSED(source); return *this;}
  48. virtual bool IsUnit(const Element &a) const =0;
  49. virtual const Element& MultiplicativeIdentity() const =0;
  50. virtual const Element& Multiply(const Element &a, const Element &b) const =0;
  51. virtual const Element& MultiplicativeInverse(const Element &a) const =0;
  52. virtual const Element& Square(const Element &a) const;
  53. virtual const Element& Divide(const Element &a, const Element &b) const;
  54. virtual Element Exponentiate(const Element &a, const Integer &e) const;
  55. virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
  56. virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
  57. virtual const AbstractGroup<T>& MultiplicativeGroup() const
  58. {return m_mg;}
  59. private:
  60. class MultiplicativeGroupT : public AbstractGroup<T>
  61. {
  62. public:
  63. const AbstractRing<T>& GetRing() const
  64. {return *m_pRing;}
  65. bool Equal(const Element &a, const Element &b) const
  66. {return GetRing().Equal(a, b);}
  67. const Element& Identity() const
  68. {return GetRing().MultiplicativeIdentity();}
  69. const Element& Add(const Element &a, const Element &b) const
  70. {return GetRing().Multiply(a, b);}
  71. Element& Accumulate(Element &a, const Element &b) const
  72. {return a = GetRing().Multiply(a, b);}
  73. const Element& Inverse(const Element &a) const
  74. {return GetRing().MultiplicativeInverse(a);}
  75. const Element& Subtract(const Element &a, const Element &b) const
  76. {return GetRing().Divide(a, b);}
  77. Element& Reduce(Element &a, const Element &b) const
  78. {return a = GetRing().Divide(a, b);}
  79. const Element& Double(const Element &a) const
  80. {return GetRing().Square(a);}
  81. Element ScalarMultiply(const Element &a, const Integer &e) const
  82. {return GetRing().Exponentiate(a, e);}
  83. Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
  84. {return GetRing().CascadeExponentiate(x, e1, y, e2);}
  85. void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
  86. {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
  87. const AbstractRing<T> *m_pRing;
  88. };
  89. MultiplicativeGroupT m_mg;
  90. };
  91. // ********************************************************
  92. //! Base and Exponent
  93. template <class T, class E = Integer>
  94. struct BaseAndExponent
  95. {
  96. public:
  97. BaseAndExponent() {}
  98. BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
  99. bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
  100. T base;
  101. E exponent;
  102. };
  103. // VC60 workaround: incomplete member template support
  104. template <class Element, class Iterator>
  105. Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
  106. template <class Element, class Iterator>
  107. Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
  108. // ********************************************************
  109. //! Abstract Euclidean Domain
  110. template <class T> class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing<T>
  111. {
  112. public:
  113. typedef T Element;
  114. virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
  115. virtual const Element& Mod(const Element &a, const Element &b) const =0;
  116. virtual const Element& Gcd(const Element &a, const Element &b) const;
  117. protected:
  118. mutable Element result;
  119. };
  120. // ********************************************************
  121. //! EuclideanDomainOf
  122. template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
  123. {
  124. public:
  125. typedef T Element;
  126. EuclideanDomainOf() {}
  127. bool Equal(const Element &a, const Element &b) const
  128. {return a==b;}
  129. const Element& Identity() const
  130. {return Element::Zero();}
  131. const Element& Add(const Element &a, const Element &b) const
  132. {return result = a+b;}
  133. Element& Accumulate(Element &a, const Element &b) const
  134. {return a+=b;}
  135. const Element& Inverse(const Element &a) const
  136. {return result = -a;}
  137. const Element& Subtract(const Element &a, const Element &b) const
  138. {return result = a-b;}
  139. Element& Reduce(Element &a, const Element &b) const
  140. {return a-=b;}
  141. const Element& Double(const Element &a) const
  142. {return result = a.Doubled();}
  143. const Element& MultiplicativeIdentity() const
  144. {return Element::One();}
  145. const Element& Multiply(const Element &a, const Element &b) const
  146. {return result = a*b;}
  147. const Element& Square(const Element &a) const
  148. {return result = a.Squared();}
  149. bool IsUnit(const Element &a) const
  150. {return a.IsUnit();}
  151. const Element& MultiplicativeInverse(const Element &a) const
  152. {return result = a.MultiplicativeInverse();}
  153. const Element& Divide(const Element &a, const Element &b) const
  154. {return result = a/b;}
  155. const Element& Mod(const Element &a, const Element &b) const
  156. {return result = a%b;}
  157. void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
  158. {Element::Divide(r, q, a, d);}
  159. bool operator==(const EuclideanDomainOf<T> &rhs) const
  160. {CRYPTOPP_UNUSED(rhs); return true;}
  161. private:
  162. mutable Element result;
  163. };
  164. //! Quotient Ring
  165. template <class T> class QuotientRing : public AbstractRing<typename T::Element>
  166. {
  167. public:
  168. typedef T EuclideanDomain;
  169. typedef typename T::Element Element;
  170. QuotientRing(const EuclideanDomain &domain, const Element &modulus)
  171. : m_domain(domain), m_modulus(modulus) {}
  172. const EuclideanDomain & GetDomain() const
  173. {return m_domain;}
  174. const Element& GetModulus() const
  175. {return m_modulus;}
  176. bool Equal(const Element &a, const Element &b) const
  177. {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
  178. const Element& Identity() const
  179. {return m_domain.Identity();}
  180. const Element& Add(const Element &a, const Element &b) const
  181. {return m_domain.Add(a, b);}
  182. Element& Accumulate(Element &a, const Element &b) const
  183. {return m_domain.Accumulate(a, b);}
  184. const Element& Inverse(const Element &a) const
  185. {return m_domain.Inverse(a);}
  186. const Element& Subtract(const Element &a, const Element &b) const
  187. {return m_domain.Subtract(a, b);}
  188. Element& Reduce(Element &a, const Element &b) const
  189. {return m_domain.Reduce(a, b);}
  190. const Element& Double(const Element &a) const
  191. {return m_domain.Double(a);}
  192. bool IsUnit(const Element &a) const
  193. {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
  194. const Element& MultiplicativeIdentity() const
  195. {return m_domain.MultiplicativeIdentity();}
  196. const Element& Multiply(const Element &a, const Element &b) const
  197. {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
  198. const Element& Square(const Element &a) const
  199. {return m_domain.Mod(m_domain.Square(a), m_modulus);}
  200. const Element& MultiplicativeInverse(const Element &a) const;
  201. bool operator==(const QuotientRing<T> &rhs) const
  202. {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;}
  203. protected:
  204. EuclideanDomain m_domain;
  205. Element m_modulus;
  206. };
  207. NAMESPACE_END
  208. #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
  209. #include "algebra.cpp"
  210. #endif
  211. #endif