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.

459 lines
16 KiB

  1. #ifndef CRYPTOPP_POLYNOMI_H
  2. #define CRYPTOPP_POLYNOMI_H
  3. /*! \file */
  4. #include "cryptlib.h"
  5. #include "misc.h"
  6. #include "algebra.h"
  7. #include <iosfwd>
  8. #include <vector>
  9. NAMESPACE_BEGIN(CryptoPP)
  10. //! represents single-variable polynomials over arbitrary rings
  11. /*! \nosubgrouping */
  12. template <class T> class PolynomialOver
  13. {
  14. public:
  15. //! \name ENUMS, EXCEPTIONS, and TYPEDEFS
  16. //@{
  17. //! division by zero exception
  18. class DivideByZero : public Exception
  19. {
  20. public:
  21. DivideByZero() : Exception(OTHER_ERROR, "PolynomialOver<T>: division by zero") {}
  22. };
  23. //! specify the distribution for randomization functions
  24. class RandomizationParameter
  25. {
  26. public:
  27. RandomizationParameter(unsigned int coefficientCount, const typename T::RandomizationParameter &coefficientParameter )
  28. : m_coefficientCount(coefficientCount), m_coefficientParameter(coefficientParameter) {}
  29. private:
  30. unsigned int m_coefficientCount;
  31. typename T::RandomizationParameter m_coefficientParameter;
  32. friend class PolynomialOver<T>;
  33. };
  34. typedef T Ring;
  35. typedef typename T::Element CoefficientType;
  36. //@}
  37. //! \name CREATORS
  38. //@{
  39. //! creates the zero polynomial
  40. PolynomialOver() {}
  41. //!
  42. PolynomialOver(const Ring &ring, unsigned int count)
  43. : m_coefficients((size_t)count, ring.Identity()) {}
  44. //! copy constructor
  45. PolynomialOver(const PolynomialOver<Ring> &t)
  46. : m_coefficients(t.m_coefficients.size()) {*this = t;}
  47. //! construct constant polynomial
  48. PolynomialOver(const CoefficientType &element)
  49. : m_coefficients(1, element) {}
  50. //! construct polynomial with specified coefficients, starting from coefficient of x^0
  51. template <typename Iterator> PolynomialOver(Iterator begin, Iterator end)
  52. : m_coefficients(begin, end) {}
  53. //! convert from string
  54. PolynomialOver(const char *str, const Ring &ring) {FromStr(str, ring);}
  55. //! convert from big-endian byte array
  56. PolynomialOver(const byte *encodedPolynomialOver, unsigned int byteCount);
  57. //! convert from Basic Encoding Rules encoded byte array
  58. explicit PolynomialOver(const byte *BEREncodedPolynomialOver);
  59. //! convert from BER encoded byte array stored in a BufferedTransformation object
  60. explicit PolynomialOver(BufferedTransformation &bt);
  61. //! create a random PolynomialOver<T>
  62. PolynomialOver(RandomNumberGenerator &rng, const RandomizationParameter &parameter, const Ring &ring)
  63. {Randomize(rng, parameter, ring);}
  64. //@}
  65. //! \name ACCESSORS
  66. //@{
  67. //! the zero polynomial will return a degree of -1
  68. int Degree(const Ring &ring) const {return int(CoefficientCount(ring))-1;}
  69. //!
  70. unsigned int CoefficientCount(const Ring &ring) const;
  71. //! return coefficient for x^i
  72. CoefficientType GetCoefficient(unsigned int i, const Ring &ring) const;
  73. //@}
  74. //! \name MANIPULATORS
  75. //@{
  76. //!
  77. PolynomialOver<Ring>& operator=(const PolynomialOver<Ring>& t);
  78. //!
  79. void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter, const Ring &ring);
  80. //! set the coefficient for x^i to value
  81. void SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring);
  82. //!
  83. void Negate(const Ring &ring);
  84. //!
  85. void swap(PolynomialOver<Ring> &t);
  86. //@}
  87. //! \name BASIC ARITHMETIC ON POLYNOMIALS
  88. //@{
  89. bool Equals(const PolynomialOver<Ring> &t, const Ring &ring) const;
  90. bool IsZero(const Ring &ring) const {return CoefficientCount(ring)==0;}
  91. PolynomialOver<Ring> Plus(const PolynomialOver<Ring>& t, const Ring &ring) const;
  92. PolynomialOver<Ring> Minus(const PolynomialOver<Ring>& t, const Ring &ring) const;
  93. PolynomialOver<Ring> Inverse(const Ring &ring) const;
  94. PolynomialOver<Ring> Times(const PolynomialOver<Ring>& t, const Ring &ring) const;
  95. PolynomialOver<Ring> DividedBy(const PolynomialOver<Ring>& t, const Ring &ring) const;
  96. PolynomialOver<Ring> Modulo(const PolynomialOver<Ring>& t, const Ring &ring) const;
  97. PolynomialOver<Ring> MultiplicativeInverse(const Ring &ring) const;
  98. bool IsUnit(const Ring &ring) const;
  99. PolynomialOver<Ring>& Accumulate(const PolynomialOver<Ring>& t, const Ring &ring);
  100. PolynomialOver<Ring>& Reduce(const PolynomialOver<Ring>& t, const Ring &ring);
  101. //!
  102. PolynomialOver<Ring> Doubled(const Ring &ring) const {return Plus(*this, ring);}
  103. //!
  104. PolynomialOver<Ring> Squared(const Ring &ring) const {return Times(*this, ring);}
  105. CoefficientType EvaluateAt(const CoefficientType &x, const Ring &ring) const;
  106. PolynomialOver<Ring>& ShiftLeft(unsigned int n, const Ring &ring);
  107. PolynomialOver<Ring>& ShiftRight(unsigned int n, const Ring &ring);
  108. //! calculate r and q such that (a == d*q + r) && (0 <= degree of r < degree of d)
  109. static void Divide(PolynomialOver<Ring> &r, PolynomialOver<Ring> &q, const PolynomialOver<Ring> &a, const PolynomialOver<Ring> &d, const Ring &ring);
  110. //@}
  111. //! \name INPUT/OUTPUT
  112. //@{
  113. std::istream& Input(std::istream &in, const Ring &ring);
  114. std::ostream& Output(std::ostream &out, const Ring &ring) const;
  115. //@}
  116. private:
  117. void FromStr(const char *str, const Ring &ring);
  118. std::vector<CoefficientType> m_coefficients;
  119. };
  120. //! Polynomials over a fixed ring
  121. /*! Having a fixed ring allows overloaded operators */
  122. template <class T, int instance> class PolynomialOverFixedRing : private PolynomialOver<T>
  123. {
  124. typedef PolynomialOver<T> B;
  125. typedef PolynomialOverFixedRing<T, instance> ThisType;
  126. public:
  127. typedef T Ring;
  128. typedef typename T::Element CoefficientType;
  129. typedef typename B::DivideByZero DivideByZero;
  130. typedef typename B::RandomizationParameter RandomizationParameter;
  131. //! \name CREATORS
  132. //@{
  133. //! creates the zero polynomial
  134. PolynomialOverFixedRing(unsigned int count = 0) : B(ms_fixedRing, count) {}
  135. //! copy constructor
  136. PolynomialOverFixedRing(const ThisType &t) : B(t) {}
  137. explicit PolynomialOverFixedRing(const B &t) : B(t) {}
  138. //! construct constant polynomial
  139. PolynomialOverFixedRing(const CoefficientType &element) : B(element) {}
  140. //! construct polynomial with specified coefficients, starting from coefficient of x^0
  141. template <typename Iterator> PolynomialOverFixedRing(Iterator first, Iterator last)
  142. : B(first, last) {}
  143. //! convert from string
  144. explicit PolynomialOverFixedRing(const char *str) : B(str, ms_fixedRing) {}
  145. //! convert from big-endian byte array
  146. PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {}
  147. //! convert from Basic Encoding Rules encoded byte array
  148. explicit PolynomialOverFixedRing(const byte *BEREncodedPoly) : B(BEREncodedPoly) {}
  149. //! convert from BER encoded byte array stored in a BufferedTransformation object
  150. explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {}
  151. //! create a random PolynomialOverFixedRing
  152. PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter &parameter) : B(rng, parameter, ms_fixedRing) {}
  153. static const ThisType &Zero();
  154. static const ThisType &One();
  155. //@}
  156. //! \name ACCESSORS
  157. //@{
  158. //! the zero polynomial will return a degree of -1
  159. int Degree() const {return B::Degree(ms_fixedRing);}
  160. //! degree + 1
  161. unsigned int CoefficientCount() const {return B::CoefficientCount(ms_fixedRing);}
  162. //! return coefficient for x^i
  163. CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
  164. //! return coefficient for x^i
  165. CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, ms_fixedRing);}
  166. //@}
  167. //! \name MANIPULATORS
  168. //@{
  169. //!
  170. ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;}
  171. //!
  172. ThisType& operator+=(const ThisType& t) {Accumulate(t, ms_fixedRing); return *this;}
  173. //!
  174. ThisType& operator-=(const ThisType& t) {Reduce(t, ms_fixedRing); return *this;}
  175. //!
  176. ThisType& operator*=(const ThisType& t) {return *this = *this*t;}
  177. //!
  178. ThisType& operator/=(const ThisType& t) {return *this = *this/t;}
  179. //!
  180. ThisType& operator%=(const ThisType& t) {return *this = *this%t;}
  181. //!
  182. ThisType& operator<<=(unsigned int n) {ShiftLeft(n, ms_fixedRing); return *this;}
  183. //!
  184. ThisType& operator>>=(unsigned int n) {ShiftRight(n, ms_fixedRing); return *this;}
  185. //! set the coefficient for x^i to value
  186. void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, ms_fixedRing);}
  187. //!
  188. void Randomize(RandomNumberGenerator &rng, const RandomizationParameter &parameter) {B::Randomize(rng, parameter, ms_fixedRing);}
  189. //!
  190. void Negate() {B::Negate(ms_fixedRing);}
  191. void swap(ThisType &t) {B::swap(t);}
  192. //@}
  193. //! \name UNARY OPERATORS
  194. //@{
  195. //!
  196. bool operator!() const {return CoefficientCount()==0;}
  197. //!
  198. ThisType operator+() const {return *this;}
  199. //!
  200. ThisType operator-() const {return ThisType(Inverse(ms_fixedRing));}
  201. //@}
  202. //! \name BINARY OPERATORS
  203. //@{
  204. //!
  205. friend ThisType operator>>(ThisType a, unsigned int n) {return ThisType(a>>=n);}
  206. //!
  207. friend ThisType operator<<(ThisType a, unsigned int n) {return ThisType(a<<=n);}
  208. //@}
  209. //! \name OTHER ARITHMETIC FUNCTIONS
  210. //@{
  211. //!
  212. ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(ms_fixedRing));}
  213. //!
  214. bool IsUnit() const {return B::IsUnit(ms_fixedRing);}
  215. //!
  216. ThisType Doubled() const {return ThisType(B::Doubled(ms_fixedRing));}
  217. //!
  218. ThisType Squared() const {return ThisType(B::Squared(ms_fixedRing));}
  219. CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, ms_fixedRing);}
  220. //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
  221. static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d)
  222. {B::Divide(r, q, a, d, ms_fixedRing);}
  223. //@}
  224. //! \name INPUT/OUTPUT
  225. //@{
  226. //!
  227. friend std::istream& operator>>(std::istream& in, ThisType &a)
  228. {return a.Input(in, ms_fixedRing);}
  229. //!
  230. friend std::ostream& operator<<(std::ostream& out, const ThisType &a)
  231. {return a.Output(out, ms_fixedRing);}
  232. //@}
  233. private:
  234. struct NewOnePolynomial
  235. {
  236. ThisType * operator()() const
  237. {
  238. return new ThisType(ms_fixedRing.MultiplicativeIdentity());
  239. }
  240. };
  241. static const Ring ms_fixedRing;
  242. };
  243. //! Ring of polynomials over another ring
  244. template <class T> class RingOfPolynomialsOver : public AbstractEuclideanDomain<PolynomialOver<T> >
  245. {
  246. public:
  247. typedef T CoefficientRing;
  248. typedef PolynomialOver<T> Element;
  249. typedef typename Element::CoefficientType CoefficientType;
  250. typedef typename Element::RandomizationParameter RandomizationParameter;
  251. RingOfPolynomialsOver(const CoefficientRing &ring) : m_ring(ring) {}
  252. Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter &parameter)
  253. {return Element(rng, parameter, m_ring);}
  254. bool Equal(const Element &a, const Element &b) const
  255. {return a.Equals(b, m_ring);}
  256. const Element& Identity() const
  257. {return this->result = m_ring.Identity();}
  258. const Element& Add(const Element &a, const Element &b) const
  259. {return this->result = a.Plus(b, m_ring);}
  260. Element& Accumulate(Element &a, const Element &b) const
  261. {a.Accumulate(b, m_ring); return a;}
  262. const Element& Inverse(const Element &a) const
  263. {return this->result = a.Inverse(m_ring);}
  264. const Element& Subtract(const Element &a, const Element &b) const
  265. {return this->result = a.Minus(b, m_ring);}
  266. Element& Reduce(Element &a, const Element &b) const
  267. {return a.Reduce(b, m_ring);}
  268. const Element& Double(const Element &a) const
  269. {return this->result = a.Doubled(m_ring);}
  270. const Element& MultiplicativeIdentity() const
  271. {return this->result = m_ring.MultiplicativeIdentity();}
  272. const Element& Multiply(const Element &a, const Element &b) const
  273. {return this->result = a.Times(b, m_ring);}
  274. const Element& Square(const Element &a) const
  275. {return this->result = a.Squared(m_ring);}
  276. bool IsUnit(const Element &a) const
  277. {return a.IsUnit(m_ring);}
  278. const Element& MultiplicativeInverse(const Element &a) const
  279. {return this->result = a.MultiplicativeInverse(m_ring);}
  280. const Element& Divide(const Element &a, const Element &b) const
  281. {return this->result = a.DividedBy(b, m_ring);}
  282. const Element& Mod(const Element &a, const Element &b) const
  283. {return this->result = a.Modulo(b, m_ring);}
  284. void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
  285. {Element::Divide(r, q, a, d, m_ring);}
  286. class InterpolationFailed : public Exception
  287. {
  288. public:
  289. InterpolationFailed() : Exception(OTHER_ERROR, "RingOfPolynomialsOver<T>: interpolation failed") {}
  290. };
  291. Element Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
  292. // a faster version of Interpolate(x, y, n).EvaluateAt(position)
  293. CoefficientType InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
  294. /*
  295. void PrepareBulkInterpolation(CoefficientType *w, const CoefficientType x[], unsigned int n) const;
  296. void PrepareBulkInterpolationAt(CoefficientType *v, const CoefficientType &position, const CoefficientType x[], const CoefficientType w[], unsigned int n) const;
  297. CoefficientType BulkInterpolateAt(const CoefficientType y[], const CoefficientType v[], unsigned int n) const;
  298. */
  299. protected:
  300. void CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
  301. CoefficientRing m_ring;
  302. };
  303. template <class Ring, class Element>
  304. void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n);
  305. template <class Ring, class Element>
  306. void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n);
  307. template <class Ring, class Element>
  308. Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n);
  309. //!
  310. template <class T, int instance>
  311. inline bool operator==(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  312. {return a.Equals(b, a.ms_fixedRing);}
  313. //!
  314. template <class T, int instance>
  315. inline bool operator!=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  316. {return !(a==b);}
  317. //!
  318. template <class T, int instance>
  319. inline bool operator> (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  320. {return a.Degree() > b.Degree();}
  321. //!
  322. template <class T, int instance>
  323. inline bool operator>=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  324. {return a.Degree() >= b.Degree();}
  325. //!
  326. template <class T, int instance>
  327. inline bool operator< (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  328. {return a.Degree() < b.Degree();}
  329. //!
  330. template <class T, int instance>
  331. inline bool operator<=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  332. {return a.Degree() <= b.Degree();}
  333. //!
  334. template <class T, int instance>
  335. inline CryptoPP::PolynomialOverFixedRing<T, instance> operator+(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  336. {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Plus(b, a.ms_fixedRing));}
  337. //!
  338. template <class T, int instance>
  339. inline CryptoPP::PolynomialOverFixedRing<T, instance> operator-(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  340. {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Minus(b, a.ms_fixedRing));}
  341. //!
  342. template <class T, int instance>
  343. inline CryptoPP::PolynomialOverFixedRing<T, instance> operator*(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  344. {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Times(b, a.ms_fixedRing));}
  345. //!
  346. template <class T, int instance>
  347. inline CryptoPP::PolynomialOverFixedRing<T, instance> operator/(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  348. {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.DividedBy(b, a.ms_fixedRing));}
  349. //!
  350. template <class T, int instance>
  351. inline CryptoPP::PolynomialOverFixedRing<T, instance> operator%(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
  352. {return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Modulo(b, a.ms_fixedRing));}
  353. NAMESPACE_END
  354. NAMESPACE_BEGIN(std)
  355. template<class T> inline void swap(CryptoPP::PolynomialOver<T> &a, CryptoPP::PolynomialOver<T> &b)
  356. {
  357. a.swap(b);
  358. }
  359. template<class T, int i> inline void swap(CryptoPP::PolynomialOverFixedRing<T,i> &a, CryptoPP::PolynomialOverFixedRing<T,i> &b)
  360. {
  361. a.swap(b);
  362. }
  363. NAMESPACE_END
  364. #endif