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.

467 lines
17 KiB

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