polynomi.h 17 KB

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