Basic Polynomial Algebra Subprograms (BPAS)  v. 1.791
upolynomial.h
1 #ifndef _UPOLYNOMIAL_H_
2 #define _UPOLYNOMIAL_H_
3 
4 //#include <type_traits>
5 #include "../Polynomial/BPASUnivarPolynomial.hpp"
6 #include "../IntegerPolynomial/uzpolynomial.h"
7 #include "../RationalNumberPolynomial/urpolynomial.h"
8 #include "../Utils/TemplateHelpers.hpp"
9 #include "../Utils/RandomHelpers.hpp"
10 
11 
12 /**
13  * A univariate polynomial over an arbitrary BPASRing represented sparsely.
14  * This is the base for all possible template instantiations.
15  * Users should use SparseUnivariatePolynomial directly and not thing class.
16  *
17  * @see SparseUnivariatePolynomial SparseUnivariateTempFieldPoly
18  */
19 template <class Ring, class Derived>
20 class SparseUnivariateTempPoly : public BPASUnivariatePolynomial<Ring, Derived> {
21 
22  // public std::conditional<std::is_base_of<BPASGCDDomain<Ring>, Ring>::value,
23  // SparseUnivariateDomainPolynomial<Ring, Derived>,
24  // SparseUnivariateTempPolyBase<Ring, Derived> >::type {
25 
26 private:
27  Symbol name;
28  std::vector< UnivariateTerm<Ring> > terms;
29 
30  inline bool isEqual(const Derived& b) const {
31  if (degree() > 0 && b.degree() > 0 && (name != b.name))
32  return 0;
33  int n = terms.size();
34  int m = b.terms.size();
35  if (n != m)
36  return 0;
37  for (int i = 0; i < n; ++i) {
38  UnivariateTerm<Ring> t = b.terms[i];
39  if (terms[i].coef != t.coef || terms[i].exp != t.exp)
40  return 0;
41  }
42  return 1;
43  }
44 
45  inline bool isEqual(const DenseUnivariateRationalPolynomial& b) const {
46  if (name != b.variable())
47  return 0;
48  int n = degree(), m = b.degree();
49  if (n != m)
50  return 0;
51  n = terms.size(), m++;
52  int k = 0;
53  for (int i = 0; i < m; ++i) {
54  if (k < n && terms[k].exp == i) {
55  if (terms[k].coef != b.coefficient(i))
56  return 0;
57  k++;
58  }
59  else if (b.coefficient(i) != 0)
60  return 0;
61  }
62  return 1;
63  }
64 
65  inline bool isEqual(const DenseUnivariateIntegerPolynomial& b) const {
66  if (name != b.variable())
67  return 0;
68  int n = degree().get_si(), m = b.degree().get_si();
69  if (n != m)
70  return 0;
71  n = terms.size(), m++;
72  int k = 0;
73  for (int i = 0; i < m; ++i) {
74  if (k < n && terms[k].exp == i) {
75  if (terms[k].coef != b.coefficient(i))
76  return 0;
77  k++;
78  }
79  else if (b.coefficient(i) != 0)
80  return 0;
81  }
82  return 1;
83  }
84 
85 /* this += t * b */
86  inline void pomopo(UnivariateTerm<Ring> t, const Derived& b) {
87  int ai = 0, m = b.terms.size();
88  int n = terms.size();
89  int i;
90 
91  // //product
92  // std::vector<UnivariateTerm<Ring>> prodTerms;
93  // prodTerms.reserve(m);
94  // Ring coef;
95  // int exp;
96  // for (i = 0; i < m; ++i) {
97  // coef = t.coef + b.terms[i].coef;
98  // exp = t.exp + b.terms[i].exp;
99  // prodTerms.emplace_back(coef, exp);
100  // }
101 
102  // //add
103  // // UnivariateTerm<Ring>* mergeOut = (UnivariateTerm<Ring>*) malloc((terms.size() + m)*sizeof(UnivariateTerm<Ring>));
104  // UnivariateTerm<Ring>* mergeOut = new UnivariateTerm<Ring>[n + m];
105  // UnivariateTerm<Ring>* adata = terms.data(), *proddata = prodTerms.data();
106  // int j, curIdx = 0;
107  // int aExp = 0, bExp = 0;
108  // for (i = 0, j = 0; i < n && j < m; ++curIdx) {
109  // aExp = adata[i].exp;
110  // bExp = proddata[j].exp;
111 
112  // if (aExp == bExp) {
113  // mergeOut[curIdx] = adata[i];
114  // mergeOut[curIdx].coef += proddata[j].coef;
115  // ++i;
116  // ++j;
117  // }
118  // else if (aExp < bExp) {
119  // mergeOut[curIdx] = adata[i];
120  // ++i;
121  // } else {
122  // mergeOut[curIdx] = proddata[j];
123  // ++j;
124  // }
125  // }
126 
127  // for ( ; i < n; ++i, ++curIdx) {
128  // mergeOut[curIdx] = adata[i];
129  // }
130  // for ( ; j < m; ++j, ++curIdx) {
131  // mergeOut[curIdx] = proddata[j];
132  // }
133 
134 
135  // // std::vector<UnivariateTerm<Ring>> newVec;
136  // // newVec.reserve(curIdx);
137  // terms.clear();
138  // terms.reserve(curIdx);
139  // for (i = 0; i < curIdx; ++i) {
140  // terms.push_back(mergeOut[i]);
141  // }
142 
143  // // free(mergeOut);
144  // delete[] mergeOut;
145 
146  // UnivariateTerm<Ring> product;
147  const UnivariateTerm<Ring>* bterms = b.terms.data();
148  Ring prodCoef, tcoef = t.coef;
149  int prodExp, tExp = t.exp, aExp;
150  for (int i = 0; i < m; ++i) {
151  prodCoef = tcoef * bterms[i].coef;
152  prodExp = tExp + bterms[i].exp;
153 
154  if (ai >= terms.size()) {
155  terms.emplace_back(prodCoef, prodExp);
156  ai++;
157  } else {
158  aExp = terms[ai].exp;
159  while (aExp < prodExp) {
160  ++ai;
161  if (ai < terms.size())
162  aExp = terms[ai].exp;
163  else {
164  terms.emplace_back(prodCoef, prodExp);
165  ++ai;
166  break;
167  }
168  }
169  if (aExp == prodExp) {
170  terms[ai].coef += prodCoef;
171  if (!terms[ai].coef.isZero()) {
172  ++ai;
173  } else {
174  terms.erase(terms.begin()+ai);
175  }
176  }
177  else if (aExp > prodExp) {
178  terms.emplace(terms.begin()+ai, prodCoef, prodExp);
179  ++ai;
180  }
181  }
182  }
183  }
184 
185 /* this = c*this + t*b */
186  inline void pomopo(Ring c, UnivariateTerm<Ring> t, const Derived& b) {
187  int ai = 0, m = b.terms.size();
188 
189  for (int i = 0; i < m; ++i) {
190  UnivariateTerm<Ring> product;
191  product.coef = t.coef * b.terms[i].coef;
192  product.exp = t.exp + b.terms[i].exp;
193 
194  if (ai >= terms.size()) {
195  terms.push_back(product);
196  ai++;
197  }
198  else {
199  int e1 = terms[ai].exp, e2 = product.exp;
200  while (e1 < e2) {
201  terms[ai].coef *= c;
202  ai++;
203  if (ai < terms.size())
204  e1 = terms[ai].exp;
205  else {
206  terms.push_back(product);
207  ai++;
208  break;
209  }
210  }
211  if (e1 == e2) {
212  terms[ai].coef *= c;
213  terms[ai].coef += product.coef;
214  if (terms[ai].coef.isZero())
215  terms.erase(terms.begin()+ai);
216  else { ai++; }
217  }
218  else if (e1 > e2) {
219  terms.insert(terms.begin()+ai, product);
220  ai++;
221  }
222  }
223  }
224  for (int i = ai; i < terms.size(); ++i)
225  terms[i].coef *= c;
226  }
227 
228  // For subresultant
229  // y = s;
230  inline Derived LazardSe(Derived& sd, Derived& sdm, Ring& y) const {
231  int n = (sd.degree() - sdm.degree()).get_si() - 1;
232  if (!n) { return sdm; }
233  Ring x = sdm.leadingCoefficient();
234  // Ring y = sd.leadingCoefficient();
235  int a = (int) pow(2, floor(log2(n)));
236  Ring c = x;
237  Derived se = sdm;
238 
239  n -= a;
240  /* int orign = n; */
241  while (a != 1) {
242  a >>= 1;
243  c *= c;
244  c /= y;
245  if (n >= a) {
246  c *= x;
247  c /= y;
248  n -= a;
249  }
250  }
251  se *= c;
252  /* if (orign != 0) { */
253  se /= y;
254  /* } */
255  return se;
256  }
257 
258  inline Derived DucosSem(Derived& a, Derived& sdm, Derived& se, Ring sd) const {
259 
260  Integer d = a.degree();
261  int e = sdm.degree().get_si();
262  Derived res;
263  res.name = name;
264  Ring ec = se.leadingCoefficient();
265 
266  /* std::cout << "Sd := " << a << std::endl; */
267  /* std::cout << "Sdm := " << sdm << std::endl; */
268  /* std::cout << "Se := " << se << std::endl; */
269  /* std::cout << "sd := " << sd << std::endl; */
270  /* std::cout << "se := " << ec << std::endl; */
271 
272  if (d == e){
273  // Streamlined resultant computation for regular case
274  Ring dc = a.leadingCoefficient();
275  Ring rTemp;
276  Derived supTemp;
277  supTemp.name = name;
278  // compute first of two main terms
279  res = a;
280  res *= ec;
281  rTemp = a.coefficient(e);
282  supTemp = se;
283  supTemp *= rTemp;
284  res -= supTemp;
285  res /= dc;
286  res *= ec;
287  // compute second of two main terms
288  rTemp = se.coefficient(e-1);
289  supTemp.zero();
290  supTemp.setCoefficient(0,rTemp);
291  rTemp = -ec;
292  supTemp.setCoefficient(1,rTemp);
293  supTemp *= se;
294  res += supTemp;
295  // divide out dc to obtain resultant
296  res /= dc;
297  return res;
298  }
299  else {
300  // Ducos algorithm for defective case
301  Ring mc = sdm.leadingCoefficient();
302  Derived* P = new Derived[d.get_si()];
303  for (int i = 0; i < e; ++i) {
304  P[i].setVariableName(name);
305  P[i].setCoefficient(i, ec);
306  }
307  for (int i = e+1; d > i; ++i)
308  P[i].setVariableName(name);
309  P[e].setVariableName(name);
310  P[e].setCoefficient(e, ec);
311  P[e] -= se;
312  ec.one();
313  res.setCoefficient(1, ec);
314  UnivariateTerm<Ring> t (ec, 1);
315  for(int i = e+1; i < d; ++i) {
316  if (!P[i-1].coefficient(e-1).isZero()) {
317  ec = -P[i-1].coefficient(e-1);
318  }
319  else {
320  ec.zero(); // prevents poly name error
321  }
322  ec /= mc;
323  P[i] = sdm;
324  P[i] *= ec;
325  //P[i] += res * P[i-1];
326  P[i].pomopo(t, P[i-1]);
327  }
328  res *= P[d.get_si()-1];
329 
330  Derived D;
331  for (int i = 0; i < d; ++i) {
332  P[i] *= a.coefficient(i);
333  D += P[i];
334  }
335  D /= a.leadingCoefficient();
336  delete [] P;
337 
338  ec = -res.coefficient(e);
339  //res += D;
340  //res *= mc;
341  t.coef = mc;
342  t.exp = 0;
343  res.pomopo(mc, t, D);
344  sdm *= ec;
345  res += sdm;
346  res /= sd;
347 
348  if ((d - e + 1) % 2 == 1) {
349  return -res;
350  }
351  return res;
352  }
353  }
354 
355  inline UnivariateTerm<Ring> leadingTerm() const {
356  int n = terms.size();
357  if (n) { return terms[n-1]; }
358  else { return UnivariateTerm<Ring>(); }
359  }
360 
361 public:
362  mpz_class characteristic;
363  // static bool isPrimeField;
364  // static bool isSmallPrimeField;
365  // static bool isComplexField;
366  /**
367  * Construct a polynomial
368  *
369  * @param
370  **/
371  SparseUnivariateTempPoly<Ring, Derived> () : name("%"), terms() {
372  Ring e;
373  characteristic = e.getCharacteristic();
374  }
375 
376  /**
377  * Copy constructor
378  *
379  * @param b: A sparse univariate polynomial
380  **/
382  Ring e;
383  characteristic = e.getCharacteristic();
384  }
385 
387  UnivariateTerm<Ring> t;
388  t.coef = Ring(a);
389  terms.push_back(t);
390  }
391 
393  UnivariateTerm<Ring> t;
394  t.coef = Ring(c);
395  terms.push_back(t);
396  }
397 
399  UnivariateTerm<Ring> t;
400  t.coef = Ring(c);
401  t.exp = 0;
402  terms.push_back(t);
403  }
404 
406  UnivariateTerm<Ring> t;
407  t.coef = Ring(c);
408  terms.push_back(t);
409  }
410 
412  name = b.variable();
413  for (int i = 0; i <= b.degree().get_si(); ++i) {
414  Ring e (Integer(b.coefficient(i)));
415  if (!e.isZero()) {
416  UnivariateTerm<Ring> t;
417  t.coef = e;
418  t.exp = i;
419  terms.push_back(t);
420  }
421  }
422  }
423 
425  name = b.variable();
426  for (int i = 0; i <= b.degree().get_si(); ++i) {
427  Ring e (RationalNumber(b.coefficient(i)));
428  if (!e.isZero()) {
429  UnivariateTerm<Ring> t;
430  t.coef = e;
431  t.exp = i;
432  terms.push_back(t);
433  }
434  }
435  }
436 
437  SparseUnivariateTempPoly<Ring, Derived> (Symbol sym) : name(sym), terms() {
438  this->one();
439  terms[0].exp = 1;
440  }
441 
442  /**
443  * Destroy the polynomial
444  *
445  * @param
446  **/
448  terms.clear();
449  }
450 
451  /**
452  * Get the number of terms
453  *
454  * @param
455  **/
456  inline Integer numberOfTerms() const {
457  return terms.size();
458  }
459 
460  /**
461  * Get the degree of the polynomial
462  *
463  * @param
464  **/
465  inline Integer degree() const {
466  int n = terms.size();
467  if (n) { return terms[n-1].exp; }
468  else { return 0; }
469  }
470 
471  /**
472  * Get the leading coefficient
473  *
474  * @param
475  **/
476  inline Ring leadingCoefficient() const {
477  int n = terms.size();
478  if (n) { return terms[n-1].coef; }
479  else { return Ring(); }
480  }
481 
482  inline Ring trailingCoefficient() const {
483  int n = terms.size();
484  if (n) {
485  return terms[0].coef;
486  } else {
487  return Ring();
488  }
489  }
490 
491  /**
492  * Get a coefficient
493  *
494  * @param k: The exponent
495  **/
496  inline Ring coefficient(int k) const {
497  int n = terms.size();
498  for (int i = 0; i < n; ++i) {
499  if (k == terms[i].exp)
500  return terms[i].coef;
501  else if (k < terms[i].exp)
502  break;
503  }
504  return Ring();
505  }
506 
507  /**
508  * Set a coeffcient with its exponent
509  *
510  * @param e: The exponent
511  * @param c: The coefficient
512  **/
513  inline void setCoefficient(int e, const Ring& c) {
514  UnivariateTerm<Ring> b;
515  b.coef = c;
516  b.exp = e;
517 
518 
519  int k = terms.size() - 1;
520  if ((k < 0 || b.exp > terms[k].exp) && !c.isZero())
521  terms.push_back(b);
522  else {
523  for (int i = 0; i <= k; ++i) {
524  int e1 = terms[i].exp, e2 = b.exp;
525  if (e1 == e2) {
526  terms[i].coef = b.coef;
527  if (terms[i].coef.isZero())
528  terms.erase(terms.begin()+i);
529  break;
530  }
531  else if (e1 > e2) {
532  if (!c.isZero())
533  terms.insert(terms.begin()+i, b);
534  break;
535  }
536  }
537  }
538  }
539 
540  /**
541  * Get the variable name
542  *
543  * @param
544  **/
545  inline Symbol variable() const {
546  return name;
547  }
548 
549  /**
550  * Set the variable name
551  *
552  * @param c: Variable's name
553  **/
554  inline void setVariableName (const Symbol& c) {
555  name = c;
556  }
557 
558  inline Derived unitCanonical(Derived* u = NULL, Derived* v = NULL) const {
559  Ring lead = leadingCoefficient();
560  Ring ru, rv;
561  Ring canon = lead.unitCanonical(&ru, &rv);
562  Derived ret = *this * ru;
563  if (u != NULL) {
564  *u = ru;
565  }
566  if (v != NULL) {
567  *v = rv;
568  }
569 
570  return ret;
571  }
572 
573  /**
574  * Overload operator =
575  *
576  * @param b: A sparse univariate polynomial
577  **/
578  inline Derived& operator= (const Derived& b) {
579  if (this != &b) {
580  terms.clear();
581  name = b.name;
582  terms = b.terms;
583  Ring e;
584  characteristic = e.getCharacteristic();
585  }
586  return dynamic_cast<Derived&>(*this);
587  }
588 
589  /**
590  * Overload operator =
591  *
592  * @param r: A base ring element
593  */
594  inline Derived& operator= (const Ring& r) {
595  terms.clear();
596  UnivariateTerm<Ring> t;
597  t.coef = Ring(r);
598  terms.push_back(t);
599  return dynamic_cast<Derived&>(*this);
600  }
601 
602 
603  /**
604  * Overload operator !=
605  *
606  * @param b: A sparse univariate polynomial
607  **/
608  inline bool operator!= (const Derived& b) const {
609  return !(isEqual(b));
610  }
611 
612  /**
613  * Overload operator ==
614  *
615  * @param b: A sparse univariate polynomial
616  **/
617  inline bool operator== (const Derived& b) const {
618  return isEqual(b);
619  }
620 
621  inline bool operator== (const DenseUnivariateRationalPolynomial& b) const {
622  return isEqual(b);
623  }
624 
625  inline bool operator== (const DenseUnivariateIntegerPolynomial& b) const {
626  return isEqual(b);
627  }
628 
629  /**
630  * Is zero polynomial
631  *
632  * @param
633  **/
634  inline bool isZero() const {
635  return !(terms.size());
636  }
637 
638  /**
639  * Zero polynomial
640  *
641  * @param
642  **/
643  inline void zero() {
644  terms.clear();
645  }
646 
647  /**
648  * Is polynomial a constant 1
649  *
650  * @param
651  **/
652  inline bool isOne() const {
653  if (terms.size() == 1 && !terms[0].exp)
654  return terms[0].coef.isOne();
655  return 0;
656  }
657 
658  /**
659  * Set polynomial to 1
660  *
661  * @param
662  **/
663  inline void one() {
664  terms.clear();
665  UnivariateTerm<Ring> t;
666  t.coef.one();
667  t.exp = 0;
668  terms.push_back(t);
669  }
670 
671  /**
672  * Is polynomial a constant -1
673  *
674  * @param
675  **/
676  inline bool isNegativeOne() const {
677  if (terms.size() == 1 && !terms[0].exp)
678  return terms[0].coef.isNegativeOne();
679  return 0;
680  }
681 
682  /**
683  * Set polynomial to -1
684  *
685  * @param
686  **/
687  inline void negativeOne() {
688  terms.clear();
689  UnivariateTerm<Ring> t;
690  t.coef.negativeOne();
691  t.exp = 0;
692  terms.push_back(t);
693  }
694 
695  /**
696  * Is a constant
697  *
698  * @param
699  **/
700  inline int isConstant() const {
701  if (terms.size() == 1 && !terms[0].exp)
702  return terms[0].coef.isConstant();
703  return 0;
704  }
705 
706  /**
707  * Convert to a constant
708  *
709  * @param
710  **/
711  inline Ring convertToConstant() {
712  if (terms.size() && !terms[0].exp)
713  return terms[0].coef;
714  else {
715  Ring e;
716  e.zero();
717  return e;
718  }
719  }
720 
721  /**
722  * Content of the polynomial
723  *
724  * @param
725  **/
726  inline Ring content() const override {
727  Ring c;
728  int n = terms.size();
729  if (n) {
730  c = terms[0].coef;
731  for (int i = 1; i < n; ++i) {
732  c = c.gcd(terms[i].coef);
733  if (c.isOne())
734  break;
735  }
736  }
737  //else { c.zero(); }
738  return c;
739  }
740 
741  inline Derived primitivePart() const {
742  //TODO
743  std::cerr << "BPAS ERROR: SUP<Ring>::primitivePart NOT YET IMPLEMENTED" << std::endl;
744  return (*this);
745  }
746 
747  /**
748  * Overload operator ^
749  * replace xor operation by exponentiation
750  *
751  * @param e: The exponentiation, e > 0
752  **/
753  inline Derived operator^ (long long int e) const {
754  Derived res;
755  res.name = name;
756  //res.one();
757  //unsigned long int q = e / 2, r = e % 2;
758  //Derived power2 = *this * *this;
759  //for (int i = 0; i < q; ++i)
760  // res *= power2;
761  //if (r) { res *= *this; }
762  if (isZero() || isOne() || e == 1)
763  res = *this;
764  else if (e == 2)
765  res = *this * *this;
766  else if (e > 2) {
767  Derived x (*this);
768  res.one();
769 
770  while (e) {
771  if (e % 2) { res *= x; }
772  x = x * x;
773  e >>= 1;
774  }
775  }
776  else if (!e)
777  res.one();
778  else {
779  res = *this;
780  }
781  return res;
782  }
783 
784  /**
785  * Overload operator ^=
786  * replace xor operation by exponentiation
787  *
788  * @param e: The exponentiation, e > 0
789  **/
790  inline Derived& operator^= (long long int e) {
791  *this = *this ^ e;
792  return dynamic_cast<Derived&>(*this);
793  }
794 
795  /**
796  * Overload operator <<
797  * replace by muplitying x^k
798  *
799  * @param k: The exponent of variable, k > 0
800  **/
801  inline Derived operator<< (int k) const {
802  Derived r (*this);
803  return (r <<= k);
804  }
805 
806  /**
807  * Overload operator <<=
808  * replace by muplitying x^k
809  *
810  * @param k: The exponent of variable, k > 0
811  **/
812  inline Derived& operator<<= (int k) {
813  for (int i = 0; i < terms.size(); ++i)
814  terms[i].exp += (unsigned long int) k;
815  return dynamic_cast<Derived&>(*this);
816  }
817 
818  /**
819  * Overload operator >>
820  * replace by dividing x^k, and
821  * return the quotient
822  *
823  * @param k: The exponent of variable, k > 0
824  **/
825  inline Derived operator>> (int k) const {
826  Derived r (*this);
827  return (r >>= k);
828  }
829 
830  /**
831  * Overload operator >>=
832  * replace by dividing x^k, and
833  * return the quotient
834  *
835  * @param k: The exponent of variable, k > 0
836  **/
837  inline Derived& operator>>= (int k) {
838  int i = 0;
839  unsigned long int e = (unsigned long int) k;
840  while (i < terms.size()) {
841  if (terms[i].exp >= e) {
842  terms[i].exp -= e;
843  i++;
844  }
845  else { terms.erase(terms.begin()); }
846  }
847  return dynamic_cast<Derived&>(*this);
848  }
849 
850  /**
851  * Overload operator +
852  *
853  * @param b: A univariate polynomial
854  **/
855  inline Derived operator+ (const Derived& b) const {
856  Derived res(*this);
857  return (res += b);
858  }
859 
860  /**
861  * Overload operator+=
862  *
863  * @param b: A univariate polynomial
864  **/
865  inline Derived& operator+= (const Derived& b) {
866  if (!terms.size()) { return (*this = b); }
867  if (!b.terms.size()) { return dynamic_cast<Derived&>(*this); }
868  if (isConstant()) { return (*this = b + terms[0].coef); }
869  if (b.isConstant()) { return (*this += b.terms[0].coef); }
870  if (name != b.name) {
871  std::cout << "BPAS: error, trying to add between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
872  exit(1);
873  }
874 
875  int ai = 0;
876  for (int i = 0; i < b.terms.size(); ++i) {
877  UnivariateTerm<Ring> bt = b.terms[i];
878  if (ai >= terms.size()) {
879  terms.push_back(bt);
880  ai++;
881  }
882  else {
883  int e1 = terms[ai].exp, e2 = bt.exp;
884  while (e1 < e2) {
885  ai++;
886  if (ai < terms.size())
887  e1 = terms[ai].exp;
888  else {
889  terms.push_back(bt);
890  ai++;
891  break;
892  }
893  }
894  if (e1 == e2) {
895  terms[ai].coef += bt.coef;
896  if (terms[ai].coef.isZero())
897  terms.erase(terms.begin()+ai);
898  else { ai++; }
899  }
900  else if (e1 > e2)
901  terms.insert(terms.begin()+ai, bt);
902  }
903  }
904  return dynamic_cast<Derived&>(*this);
905  }
906 
907  /**
908  * Overload operator +
909  *
910  * @param e: A coefficient constant
911  **/
912  inline Derived operator+ (const Ring& e) const {
913  Derived r (*this);
914  return (r += e);
915  }
916 
917  /**
918  * Overload operator +=
919  *
920  * @param e: A coefficient constant
921  **/
922  inline Derived& operator+= (const Ring& e) {
923  if (!e.isZero()) {
924  if (terms.size()) {
925  UnivariateTerm<Ring> a = terms[0];
926  if (a.exp) {
927  a.coef = e;
928  a.exp = 0;
929  terms.insert(terms.begin(), a);
930  }
931  else {
932  terms[0].coef += e;
933  if (terms[0].coef.isZero())
934  terms.erase(terms.begin());
935  }
936  }
937  else {
938  UnivariateTerm<Ring> a;
939  a.coef = e;
940  a.exp = 0;
941  terms.push_back(a);
942  }
943  }
944  return dynamic_cast<Derived&>(*this);
945  }
946 
947  inline friend Derived operator+ (const Ring& c, const Derived& p) {
948  return (p + c);
949  }
950 
951  /**
952  * Overload operator -, negate
953  *
954  * @param
955  **/
956  inline Derived operator- () const {
957  Derived res;
958  res.name = name;
959  for (int i = 0; i < terms.size(); ++i) {
960  UnivariateTerm<Ring> t;
961  t.coef = -terms[i].coef;
962  t.exp = terms[i].exp;
963  res.terms.push_back(t);
964  }
965  return res;
966  }
967 
968  /**
969  * Subtract another polynomial
970  *
971  * @param b: A univariate polynomial
972  **/
973  inline Derived operator- (const Derived& b) const {
974  Derived res(*this);
975  return (res -= b);
976  }
977 
978  /**
979  * Overload operator -=
980  *
981  * @param b: A univariate polynomial
982  **/
983  inline Derived& operator-= (const Derived& b) {
984  if (!terms.size()) { return (*this = -b); }
985  if (!b.terms.size()) { return dynamic_cast<Derived&>(*this); }
986  if (isConstant()) { return (*this = -b + terms[0].coef); }
987  if (b.isConstant()) { return (*this -= b.terms[0].coef); }
988  if (name != b.name) {
989  std::cout << "BPAS: error, trying to subtract between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
990  exit(1);
991  }
992 
993  int ai = 0;
994  for (int i = 0; i < b.terms.size(); ++i) {
995  UnivariateTerm<Ring> t = b.terms[i];
996  t.coef = -t.coef;
997 
998  if (ai >= terms.size()) {
999  terms.push_back(t);
1000  ai++;
1001  }
1002  else {
1003  int e1 = terms[ai].exp, e2 = t.exp;
1004  while (e1 < e2) {
1005  ai++;
1006  if (ai < terms.size())
1007  e1 = terms[ai].exp;
1008  else {
1009  terms.push_back(t);
1010  ai++;
1011  break;
1012  }
1013  }
1014  if (e1 == e2) {
1015  terms[ai].coef += t.coef;
1016  if (terms[ai].coef.isZero())
1017  terms.erase(terms.begin()+ai);
1018  else { ai++; }
1019  }
1020  else if (e1 > e2)
1021  terms.insert(terms.begin()+ai, t);
1022  }
1023  }
1024  return dynamic_cast<Derived&>(*this);
1025  }
1026 
1027  /**
1028  * Overload operator -
1029  *
1030  * @param e: A coefficient constant
1031  **/
1032  inline Derived operator- (const Ring& e) const {
1033  Derived r (*this);
1034  return (r -= e);
1035  }
1036 
1037  /**
1038  * Overload operator -=
1039  *
1040  * @param e: A coefficient constant
1041  **/
1042  inline Derived& operator-= (const Ring& e) {
1043  if (!e.isZero()) {
1044  if (terms.size()) {
1045  UnivariateTerm<Ring> t = terms[0];
1046  if (t.exp) {
1047  t.coef = -e;
1048  t.exp = 0;
1049  terms.insert(terms.begin(), t);
1050  }
1051  else {
1052  terms[0].coef -= e;
1053  if (terms[0].coef.isZero())
1054  terms.erase(terms.begin());
1055  }
1056  }
1057  else {
1058  UnivariateTerm<Ring> t;
1059  t.coef = -e;
1060  t.exp = 0;
1061  terms.push_back(t);
1062  }
1063  }
1064  return dynamic_cast<Derived&>(*this);
1065  }
1066 
1067  inline friend Derived operator- (const Ring& c, const Derived& p) {
1068  return (-p + c);
1069  }
1070 
1071  /**
1072  * Multiply another polynomial
1073  *
1074  * @param b: A univariate polynomial
1075  **/
1076  inline Derived operator* (const Derived& b) const {
1077  int n = terms.size(), m = b.terms.size();
1078  if (!n)
1079  return *this;
1080  if (!m)
1081  return b;
1082 
1083  Derived res;
1084  if (degree() == 0) {
1085  for (int i = 0; i < m; ++i) {
1086  UnivariateTerm<Ring> bt = b.terms[i];
1087  UnivariateTerm<Ring> t;
1088  t.coef = terms[0].coef * bt.coef;
1089  t.exp = bt.exp;
1090  res.terms.push_back(t);
1091  }
1092  res.name = b.name;
1093  return res;
1094  }
1095  res.name = name;
1096  if (b.degree() == 0) {
1097  UnivariateTerm<Ring> bt = b.terms[0];
1098  for (int i = 0; i < n; ++i) {
1099  UnivariateTerm<Ring> t;
1100  t.coef = terms[i].coef * bt.coef;
1101  t.exp = terms[i].exp;
1102  res.terms.push_back(t);
1103  }
1104  return res;
1105  }
1106 
1107  if (name != b.name) {
1108  std::cout << "BPAS: error, trying to multiply between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
1109  exit(1);
1110  }
1111 
1112  if (n + m < 64) {
1113  if (n <= m) {
1114  for (int i = 0; i < n; ++i)
1115  res.pomopo(terms[i], b);
1116  }
1117  else {
1118  for (int i = 0; i < m; ++i)
1119  res.pomopo(b.terms[i], *this);
1120  }
1121  }
1122  else {
1123  int s = (m > n) ? m : n;
1124  s >>= 1;
1125  Derived f0, f1;
1126  f0.name = f1.name = name;
1127  for (int i = 0; i < n; ++i) {
1128  if (terms[i].exp < s)
1129  f0.terms.push_back(terms[i]);
1130  else {
1131  UnivariateTerm<Ring> t (terms[i].coef, terms[i].exp-s);
1132  f1.terms.push_back(t);
1133  }
1134  }
1135  Derived g0, g1;
1136  g0.name = g1.name = name;
1137  for (int i = 0; i < m; ++i) {
1138  if (b.terms[i].exp < s)
1139  g0.terms.push_back(b.terms[i]);
1140  else {
1141  UnivariateTerm<Ring> t (b.terms[i].coef, b.terms[i].exp-s);
1142  g1.terms.push_back(t);
1143  }
1144  }
1145  Derived t0, t1;
1146  t0.name = t1.name = name;
1147  n = f0.terms.size(), m = g0.terms.size();
1148  if (n <= m) {
1149  for (int i = 0; i < n; ++i)
1150  res.pomopo(f0.terms[i], g0);
1151  }
1152  else {
1153  for (int i = 0; i < m; ++i)
1154  res.pomopo(g0.terms[i], f0);
1155  }
1156  n = f1.terms.size(), m = g1.terms.size();
1157  if (n <= m) {
1158  for (int i = 0; i < n; ++i)
1159  t0.pomopo(f1.terms[i], g1);
1160  }
1161  else {
1162  for (int i = 0; i < m; ++i)
1163  t0.pomopo(g1.terms[i], f1);
1164  }
1165  f0 += f1, g0 += g1;
1166  n = f0.terms.size(), m = g0.terms.size();
1167  if (n <= m) {
1168  for (int i = 0; i < n; ++i)
1169  t1.pomopo(f0.terms[i], g0);
1170  }
1171  else {
1172  for (int i = 0; i < m; ++i)
1173  t1.pomopo(g0.terms[i], f0);
1174  }
1175  t1 -= res + t0;
1176  for (int i = 0; i < t1.terms.size(); ++i)
1177  t1.terms[i].exp += s;
1178  s <<= 1;
1179  for (int i = 0; i < t0.terms.size(); ++i)
1180  t0.terms[i].exp += s;
1181  res += t0 + t1;
1182  }
1183  return res;
1184  }
1185 
1186  /**
1187  * Overload operator *=
1188  *
1189  * @param b: A univariate polynomial
1190  **/
1191  inline Derived& operator*= (const Derived& b) {
1192  *this = *this * b;
1193  return dynamic_cast<Derived&>(*this);
1194  }
1195 
1196  /**
1197  * Overload operator *
1198  *
1199  * @param c: A coefficient
1200  **/
1201  inline Derived operator* (const Ring& c) const {
1202  Derived r (*this);
1203  return (r *= c);
1204  }
1205 
1206  inline Derived operator* (const sfixn& e) const {
1207  Derived r (*this);
1208  return (r *= e);
1209  }
1210 
1211  /**
1212  * Overload operator *=
1213  *
1214  * @param c: A coefficient
1215  **/
1216  inline Derived& operator*= (const Ring& c) {
1217  if (!isZero()) {
1218  if (!c.isZero() && !c.isOne()) {
1219  for (int i = 0; i < terms.size(); ++i)
1220  terms[i].coef *= c;
1221  }
1222  else if (c.isZero())
1223  terms.clear();
1224  }
1225  return dynamic_cast<Derived&>(*this);
1226  }
1227 
1228  inline Derived& operator*= (const sfixn& e) {
1229  if (e != 0 && e != 1) {
1230  for (int i = 0; i < terms.size(); ++i)
1231  terms[i].coef *= e;
1232  }
1233  else if (e == 0) { zero(); }
1234  return dynamic_cast<Derived&>(*this);
1235  }
1236 
1237  inline friend Derived operator* (const Ring& e, const Derived& p) {
1238  return (p * e);
1239  }
1240 
1241  inline friend Derived operator* (const sfixn& e, const Derived& p) {
1242  return (p * e);
1243  }
1244 
1245  /**
1246  * Overload operator /
1247  * EdeDivision
1248  *
1249  * @param b: A univariate polynomial
1250  **/
1251  inline Derived operator/ (const Derived& b) const {
1252  Derived rem(*this);
1253  rem /= b;
1254  return rem;
1255  }
1256 
1257  /**
1258  * Overload operator /=
1259  * ExactDivision
1260  *
1261  * @param b: A univariate polynomial
1262  **/
1263  inline Derived& operator/= (const Derived& b) {
1264  if (b.isZero()) {
1265  std::cout << "BPAS: error, dividend is zero from Derived." << std::endl;
1266  exit(1);
1267  }
1268  if (b.isConstant()) { return (*this /= b.terms[0].coef); }
1269  if (isConstant()) {
1270  zero();
1271  return dynamic_cast<Derived&>(*this);
1272  }
1273  if (name != b.name) {
1274  std::cout << "BPAS: error, trying to exact divide between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
1275  exit(1);
1276  }
1277 
1278  Derived q;
1279  q.name = name;
1280 
1281  Integer db = b.degree();
1282  UnivariateTerm<Ring> bt = b.leadingTerm();
1283 
1284  if (db == 1 && bt.coef.isOne()) {
1285  if (b.terms.size() > 1) {
1286  int k = 0;
1287  Ring e, prev;
1288  UnivariateTerm<Ring> t, at = leadingTerm();
1289  if (!terms[0].exp) {
1290  prev = t.coef = terms[0].coef / b.terms[0].coef;
1291  t.exp = 0;
1292  q.terms.push_back(t);
1293  k++;
1294  }
1295  else { prev.zero(); }
1296  for (int i = 1; i < at.exp; ++i) {
1297  if (k < terms.size() && terms[k].exp == i) {
1298  e = terms[k].coef;
1299  k++;
1300  }
1301  else { e.zero(); }
1302  t.coef = (e - prev) / b.terms[0].coef;
1303  if (!t.coef.isZero()) {
1304  t.exp = i;
1305  q.terms.push_back(t);
1306  }
1307  prev = t.coef;
1308  }
1309  if (prev == at.coef)
1310  return (*this = q);
1311  else {
1312  std::cout << "BPAS: error, not exact division in Derived." << std::endl;
1313  exit(1);
1314  }
1315  }
1316  else {
1317  if (!terms[0].exp) {
1318  std::cout << "BPAS: error, not exact division in Derived." << std::endl;
1319  exit(1);
1320  }
1321  else {
1322  for (int i = 0; i < terms.size(); ++i)
1323  terms[i].exp--;
1324  return dynamic_cast<Derived&>(*this);
1325  }
1326  }
1327  }
1328 
1329  while (!isZero() && degree() >= db) {
1330  UnivariateTerm<Ring> at = leadingTerm();
1331  UnivariateTerm<Ring> lc, nlc;
1332  lc.coef = at.coef / bt.coef;
1333  lc.exp = at.exp - bt.exp;
1334  nlc.coef = -lc.coef;
1335  nlc.exp = lc.exp;
1336  pomopo(nlc, b);
1337  q.terms.insert(q.terms.begin(), lc);
1338  }
1339  if (!isZero()) {
1340  std::cout << "BPAS: error, not exact division in Derived." << std::endl;
1341  exit(1);
1342  }
1343  return (*this = q);
1344  }
1345 
1346  /**
1347  * Overload operator /
1348  *
1349  * @param e: A coefficient constant
1350  **/
1351  inline Derived operator/ (const Ring& e) const {
1352  Derived r (*this);
1353  r /= e;
1354  return r;
1355  }
1356 
1357  /**
1358  * Overload operator /=
1359  *
1360  * @param e: A coefficient constant
1361  **/
1362  inline Derived& operator/= (const Ring& e) {
1363  if (e.isZero()) {
1364  std::cout << "BPAS: error, dividend is zero from Derived." << std::endl;
1365  exit(1);
1366  }
1367  else if (!e.isOne()) {
1368  int i = 0;
1369  while (i < terms.size()) {
1370  terms[i].coef /= e;
1371  if (terms[i].coef.isZero())
1372  terms.erase(terms.begin()+i);
1373  else { ++i; }
1374  }
1375  }
1376  return dynamic_cast<Derived&>(*this);
1377  }
1378 
1379  inline friend Derived operator/ (const Ring& e, const Derived& p) {
1380  if (p.isZero()) {
1381  std::cout << "BPAS: error, dividend is zero from Derived." << std::endl;
1382  exit(1);
1383  }
1384  Derived q;
1385  q.name = p.name;
1386 
1387  if (p.isConstant()) {
1388  q += e;
1389  return (q /= p.terms[0].coef);
1390  }
1391  else { return q; }
1392  }
1393 
1394  /**
1395  * Negate the polynomial
1396  *
1397  * @param
1398  **/
1399  inline void negate() {
1400  for (int i = 0; i < terms.size(); ++i)
1401  terms[i].coef = -terms[i].coef;
1402  }
1403 
1404  /**
1405  * Monic division
1406  * Assuming the leading coefficient of dividend is 1
1407  * Return quotient and itself becomes remainder
1408  *
1409  * @param b: The dividend polynomial
1410  **/
1411  inline Derived monicDivide(const Derived& b) {
1412  if (b.isZero()) {
1413  std::cout << "BPAS: error, dividend is zero from Derived." << std::endl;
1414  exit(1);
1415  }
1416  else if (!b.leadingCoefficient().isOne()) {
1417  std::cout << "BPAS: error, leading coefficient is not one in monicDivide() from Derived." << std::endl;
1418  exit(1);
1419  }
1420 
1421  if (b.isConstant()) {
1422  Derived r (*this);
1423  zero();
1424  return r;
1425  }
1426  if (isConstant()) {
1427  Derived r;
1428  r.zero();
1429  return r;
1430  }
1431  if (name != b.name) {
1432  std::cout << "BPAS: error, trying to monic divide between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
1433  exit(1);
1434  }
1435 
1436  Derived quo;
1437  quo.name = name;
1438  UnivariateTerm<Ring> bt = b.leadingTerm();
1439  while (degree() >= b.degree()) {
1440  UnivariateTerm<Ring> at = leadingTerm();
1441  UnivariateTerm<Ring> nlc;
1442  nlc.coef = -at.coef;
1443  nlc.exp = at.exp - bt.exp;
1444  pomopo(nlc, b);
1445  at.exp = nlc.exp;
1446  quo.terms.insert(quo.terms.begin(), at);
1447  }
1448  return quo;
1449  }
1450 
1451  /**
1452  * Monic division
1453  * Assuming the leading coefficient of dividend is 1
1454  * Return quotient
1455  *
1456  * @param b: The dividend polynomial
1457  * @param rem: The remainder polynomial
1458  **/
1459  inline Derived monicDivide(const Derived& b, Derived* rem) const {
1460  std::cout << "*this " << *this << std::endl;
1461  *rem = *this; std::cout<< "salam"<<std::endl;
1462  return rem->monicDivide(b);
1463  }
1464 
1465  /**
1466  * Lazy pseudo dividsion
1467  * Return the quotient and itself becomes remainder
1468  * e is the exact number of division steps
1469  *
1470  * @param b: The dividend polynomial
1471  * @param c: The leading coefficient of b to the power e
1472  * @param d: That to the power deg(a) - deg(b) + 1 - e
1473  **/
1474  inline Derived lazyPseudoDivide (const Derived& b, Ring* c, Ring* d=NULL) {
1475  if (d == NULL)
1476  d = new Ring;
1477  Integer da = degree(), db = b.degree();
1478  if (b.isZero() || db == 0) {
1479  std::cout << "BPAS: error, dividend is zero or constant from Derived." << std::endl;
1480  exit(1);
1481  }
1482  c->one(), d->one();
1483  if (isConstant()) {
1484  Derived r;
1485  r.zero();
1486  return r;
1487  }
1488  if (name != b.name) {
1489  std::cout << "BPAS: error, trying to pseudo divide between Ring[" << name << "] and Ring[" << b.name << "]." << std::endl;
1490  exit(1);
1491  }
1492 
1493  if (da < db) {
1494  Derived r;
1495  r.name = name;
1496  return r;
1497  }
1498 
1499  Derived quo;
1500  quo.name = name;
1501  Ring blc = b.leadingTerm().coef;
1502 
1503  int e = 0;
1504  Integer diff = da - db;
1505  while (degree() >= db) {
1506  UnivariateTerm<Ring> at = leadingTerm();
1507  UnivariateTerm<Ring> nlc;
1508  nlc.coef = -at.coef;
1509  nlc.exp = at.exp - db.get_si();
1510 
1511  *c *= blc;
1512  e++;
1513  pomopo(blc, nlc, b);
1514  at.exp = nlc.exp;
1515  quo.terms.insert(quo.terms.begin(), at);
1516  }
1517  for (int i = e; diff >= i; ++i)
1518  *d *= blc;
1519  return quo;
1520  }
1521 
1522  /**
1523  * Lazy pseudo dividsion
1524  * Return the quotient
1525  * e is the exact number of division steps
1526  *
1527  * @param b: The divident polynomial
1528  * @param rem: The remainder polynomial
1529  * @param c: The leading coefficient of b to the power e
1530  * @param d: That to the power deg(a) - deg(b) + 1 - e
1531  **/
1532  inline Derived lazyPseudoDivide (const Derived& b, Derived* rem, Ring* c, Ring* d) const {
1533  *rem = *this;
1534  return rem->lazyPseudoDivide(b, c, d);
1535  }
1536 
1537  /**
1538  * Pseudo dividsion
1539  * Return the quotient and itself becomes remainder
1540  *
1541  * @param b: The divident polynomial
1542  * @param d: The leading coefficient of b
1543  * to the power deg(a) - deg(b) + 1
1544  **/
1545  inline Derived pseudoDivide (const Derived& b, Ring* d=NULL) {
1546  Ring c;
1547  if (d == NULL)
1548  d = new Ring;
1549  Derived quo = lazyPseudoDivide(b, &c, d);
1550  quo *= *d;
1551  *this *= *d;
1552  *d *= c;
1553  return quo;
1554  }
1555 
1556  /**
1557  * Pseudo dividsion
1558  * Return the quotient
1559  *
1560  * @param b: The divident polynomial
1561  * @param rem: The remainder polynomial
1562  * @param d: The leading coefficient of b
1563  * to the power deg(a) - deg(b) + 1
1564  **/
1565  inline Derived pseudoDivide (const Derived& b, Derived* rem, Ring* d) const {
1566  Ring c;
1567  Derived quo = lazyPseudoDivide(b, rem, &c, d);
1568  quo *= *d;
1569  *rem *= *d;
1570  *d *= c;
1571  return quo;
1572  }
1573 
1574  /**
1575  * Compute k-th derivative
1576  *
1577  * @param k: k-th derivative
1578  **/
1579  inline void differentiate(int k) {
1580  if (k <= 0) { return; }
1581  int i = 0;
1582  while (i < terms.size()) {
1583  if (terms[i].exp >= k) {
1584  for (int j = 0; j < k; ++j)
1585  terms[i].coef *= Ring(terms[i].exp - j);
1586  terms[i].exp -= k;
1587  i++;
1588  }
1589  else
1590  terms.erase(terms.begin());
1591  }
1592  }
1593 
1594  /**
1595  * Convert current object to its derivative
1596  *
1597  **/
1598  inline void differentiate() {
1599  this->differentiate(1);
1600  }
1601 
1602  /**
1603  * Return k-th derivative
1604  *
1605  * @param k: k-th derivative, k > 0
1606  **/
1607  inline Derived derivative(int k) const {
1608  Derived a(*this);
1609  a.differentiate(k);
1610  return a;
1611  }
1612 
1613  /**
1614  * Compute derivative
1615  *
1616  **/
1617  inline Derived derivative() const {
1618  return this->derivative(0);
1619  }
1620 
1621  /**
1622  * Compute integral with constant of integration set to 0
1623  *
1624  * @param
1625  **/
1626  inline void integrate() {
1627  int i = terms.size()-1;
1628  while (i > -1) {
1629  terms[i].coef /= (terms[i].exp + 1);
1630  terms[i].exp += 1;
1631  i--;
1632  }
1633  }
1634 
1635  /**
1636  * Compute integral with constant of integration 0
1637  *
1638  **/
1639  inline Derived integral() const {
1640  Derived a(*this);
1641  a.integrate();
1642  return a;
1643  }
1644 
1645  /**
1646  * Is trailing coefficient zero
1647  *
1648  * @param
1649  **/
1650  inline bool isConstantTermZero() const {
1651  if (isZero())
1652  return 1;
1653  int n = terms.size();
1654  if (n && terms[0].exp == 0 && terms[0].coef == Ring(0))
1655  return 1;
1656  return 0;
1657  }
1658 
1659  /**
1660  * Evaluate f(x)
1661  *
1662  * @param x: Evaluation point
1663  **/
1664  inline Ring evaluate(const Ring& x) const {
1665  int d = terms.size() - 1;
1666  if (d < 0) { return Ring(); }
1667  int e = terms[d].exp - 1;
1668  Ring px = terms[d].coef;
1669  d--;
1670  for (int i = e; i > -1; --i) {
1671  px *= x;
1672  if (i == terms[d].exp && d > -1) {
1673  px += terms[d].coef;
1674  d--;
1675  }
1676  }
1677  return px;
1678  }
1679 
1680  /**
1681  * Evaluate f(x)
1682  *
1683  * @param x: Evaluation point in larger ring, i.e. a ring in which the Ring of SUP<Ring> can be embedded
1684  **/
1685  template <class LargerRing>
1686  inline LargerRing evaluate(const LargerRing& x) const {
1687  // we might need a way of checking that this is always possible
1688  int d = terms.size() - 1;
1689  if (d < 0) { return LargerRing(); }
1690  int e = terms[d].exp - 1;
1691  LargerRing px = (LargerRing)terms[d].coef;
1692  LargerRing a;
1693  d--;
1694  for (int i = e; i > -1; --i) {
1695  px *= x;
1696  if (i == terms[d].exp && d > -1) {
1697  a = (LargerRing)terms[d].coef;
1698  px += a;
1699  d--;
1700  }
1701  }
1702  return px;
1703  }
1704 
1705  inline void fillChain (std::vector<Derived>& chain) const {
1706  Derived zero;
1707  zero.zero();
1708  int fullSize(chain[chain.size()-2].degree().get_ui()+2);
1709  int delta;
1710  // std::cerr << "chain.size() = " << chain.size() << std::endl;
1711  // std::cerr << "fullSize = " << fullSize << std::endl;
1712  if (chain.size() < fullSize) {
1713  chain.reserve(fullSize);
1714  for (int i=chain.size()-2; i>0; --i) {
1715  if (chain[i].degree() != chain[i-1].degree()+1) {
1716  delta = chain[i].degree().get_ui() - chain[i-1].degree().get_ui();
1717  if (i > 1) {
1718  i = i-1;
1719  for (int j=0; j<delta-2; ++j)
1720  chain.insert(chain.begin()+i,zero);
1721  }
1722  else {
1723  for (int j=0; j<delta-1; ++j)
1724  chain.insert(chain.begin()+i,zero);
1725  }
1726  }
1727  }
1728  if (chain[0].degree() != 0) {
1729  for (int j=0; j<chain[0].degree(); ++j)
1730  chain.insert(chain.begin(),zero);
1731  }
1732  }
1733  // std::cerr << "chain.size() = " << chain.size() << std::endl;
1734  }
1735 
1736  /**
1737  * Subresultant Chain
1738  * Return the list of subresultants
1739  *
1740  * @param q: The other sparse univariate polynomial
1741  **/
1742  inline std::vector< Derived > subresultantChain (const Derived& q, int filled=0) const {
1743  if (name != q.name) {
1744  std::cout << "BPAS: error, trying to compute subresultant chains between Ring[" << name << "] and Ring[" << q.name << "]." << std::endl;
1745  exit(1);
1746  }
1747 
1748  if (degree() == 0 || q.degree() == 0){
1749  std::cout << "BPAS: error, Input polynomials to subresultantChain must have positive degree." << std::endl;
1750  exit(1);
1751  }
1752 
1753  std::vector< Derived > S;
1754  Derived a, b;
1755  if (q.degree() > degree()) {
1756  a = q;
1757  b = *this;
1758  }
1759  else {
1760  a = *this;
1761  b = q;
1762  }
1763 
1764  int k = (a.degree() - b.degree()).get_si();
1765  Ring s = b.leadingCoefficient() ^ k;
1766 
1767  Derived A = b, B = a, C = -b;
1768  if (k > 1) {
1769  b *= b.leadingCoefficient()^(k-1); // converts b to S_{degree(b)}
1770  }
1771  S.push_back(b);
1772  S.push_back(a);
1773  B.pseudoDivide(C);
1774  Integer delta = 0;
1775  while (true) {
1776  if (B.isZero())
1777  break;
1778  S.insert(S.begin(), B);
1779  delta = A.degree() - B.degree();
1780  if (delta > 1) {
1781  C = LazardSe(S[1], S[0], s);
1782  S.insert(S.begin(), C);
1783  }
1784  else { C = B; }
1785  if (B.degree() == 0)
1786  break;
1787  B = DucosSem(A, B, C, s);
1788  A = C;
1789  s = A.leadingCoefficient();
1790  }
1791  // if resultant is 0, add it to subresultantChain
1792  if (S.at(0).degree() > 0) {
1793  S.insert(S.begin(), B);
1794  }
1795  if (filled) {
1796  std::cerr << "filling chain..." << std::endl;
1797  fillChain(S);
1798  }
1799  return S;
1800  }
1801 
1802  /**
1803  * monomialBasisSubResultantChain
1804  *
1805  * @param q: The other sparse univariate polynomial
1806  **/
1807  inline std::vector<Derived > monomialBasisSubresultantChain(const Derived& q) {
1808  std::vector< Derived > s = this->subresultantChain(q);
1809  Derived sup;
1810  int delta,n;
1811  for (int i=s.size()-2; i>0; --i) {
1812  delta = s.at(i).degree() - s.at(i-1).degree();
1813  if (delta > 1) {
1814  if (i == 1 && s.at(i-1).isZero())
1815  n = delta-1;
1816  else
1817  n = delta-2;
1818  for (int j=0; j<n; j++)
1819  s.insert(s.begin()+i-1,sup);
1820  }
1821  }
1822  return s;
1823  /*int delta;
1824  Derived pp;
1825  std::vector< Derived > src;
1826  if(this->degree()>q.degree()){
1827  src.push_back(*this);
1828  src.push_back(q);
1829  delta = q.degree();
1830  pp = q;
1831  }
1832  else{
1833  src.push_back(q);
1834  src.push_back(*this);
1835  delta = this->degree();
1836  pp = *this;
1837  }
1838 
1839 
1840  int i = s.size()-2;
1841 
1842 
1843 
1844  Derived qq = s[s.size()-1];
1845  src.push_back(qq);
1846  delta= delta - qq.degree();
1847  while(true){
1848 
1849  if(delta>=2){
1850 
1851  for(int j=0;j<delta-2;j++){
1852  Derived poly;
1853  poly.zero();
1854  src.push_back(poly);
1855  }
1856 
1857  }
1858 
1859  if(i==0){
1860  src.push_back(src[0]);
1861  std::reverse(src.begin(),src.end());
1862  return src;
1863 
1864  }
1865  if(i<0){
1866  std::reverse(src.begin(),src.end());
1867  return src;
1868 
1869  }
1870 
1871 
1872  pp= s[i];
1873  src.push_back(pp);
1874 
1875  qq = s[i-1];
1876  src.push_back(qq);
1877 
1878  delta = pp.degree() - qq.degree();
1879  i = i-2;
1880 
1881 
1882 
1883 
1884  }*/
1885 
1886  }
1887 
1888 
1889 
1890 
1891  /**
1892  * Resultant
1893  *
1894  * @param q: The other sparse univariate polynomial
1895  **/
1896  inline Derived resultant (const Derived& q) {
1897  std::vector< Derived > s = subresultantChain(q);
1898  return s[0];
1899  }
1900 
1901  /**
1902  * GCD(p, q)
1903  *
1904  * @param q: The other polynomial
1905  **/
1906  inline Derived gcd (const Derived& q) const {
1907  if (isZero()) { return q; }
1908  if (q.isZero()) { return *this; }
1909  if (name != q.name) {
1910  std::cout << "BPAS: error, trying to compute GCD between Ring[" << name << "] and Ring[" << q.name << "]." << std::endl;
1911  exit(1);
1912  }
1913 
1914  Derived a(*this), b(q);
1915  if (a.degree() == 0 || b.degree() == 0) {
1916  a.one();
1917  return a;
1918  }
1919 
1920  Derived r;
1921  r.name = name;
1922 
1923  //std::cout << "is_same: " << std::is_same<Ring, RationalNumber>::value << std::endl;
1924  Ring rng;
1925  //TODO properly implement the ring properties.
1926  // if (Ring::properties.has(PRIME_FIELD)) {
1927  // DenseUnivariateRationalPolynomial f = a.convertToDUQP();
1928  // DenseUnivariateRationalPolynomial g = b.convertToDUQP();
1929  // DenseUnivariateRationalPolynomial z = f.gcd(g);
1930  // r = Derived (z);
1931  // }
1932  // else {
1933  Ring ca, cb, cr;
1934  ca = a.content();
1935  a /= ca;
1936  cb = b.content();
1937  b /= cb;
1938  std::vector< Derived > R = a.subresultantChain(b);
1939 
1940  r.setCoefficient(0, ca.gcd(cb));
1941  //r *= cb;
1942  int n = R.size();
1943  bool isZero = 0;
1944  if (n) {
1945  isZero = 1;
1946  for (int i = 0; i < n; ++i) {
1947  if (!R[i].isZero()) {
1948  cr = R[i].content();
1949  R[i] /= cr;
1950  r *= R[i];
1951  isZero = 0;
1952  break;
1953  }
1954  }
1955  }
1956  if (isZero) {
1957  if (a.degree() <= b.degree()) { r *= a; }
1958  else { r *= b; }
1959  }
1960  // }
1961  return r;
1962  }
1963 
1964  /**
1965  * Square free
1966  *
1967  * @param
1968  **/
1969  inline Factors<Derived> squareFree() const {
1970  std::vector< Derived > sf;
1971  int d = terms.size()-1;
1972  if (!terms[d].exp)
1973  sf.push_back(*this);
1974  else if (terms[d].exp == 1) {
1975  Derived t;
1976  t.name = name;
1977  t += terms[d].coef;
1978  sf.push_back(t);
1979  t = *this / terms[d].coef;
1980  sf.push_back(t);
1981  }
1982  else {
1983  Derived a (*this), b(*this);
1984  b.differentiate(1);
1985  Derived g = a.gcd(b);
1986  g /= g.content();
1987  Derived x = a / g;
1988  Derived y = b / g;
1989  Derived z = -x;
1990  z.differentiate(1);
1991  z += y;
1992 
1993  while (!z.isZero()) {
1994  g = x.gcd(z);
1995  g /= g.content();
1996  sf.push_back(g);
1997  x /= g;
1998  y = z / g;
1999  z = -x;
2000  z.differentiate(1);
2001  z += y;
2002  }
2003  sf.push_back(x);
2004 
2005  Ring e;
2006  e.one();
2007  for (int i = 0; i < sf.size(); ++i) {
2008  e *= sf[i].leadingCoefficient();
2009  sf[i] /= sf[i].leadingCoefficient();
2010  }
2011  Derived t;
2012  t.name = name;
2013  t += e;
2014  sf.insert(sf.begin(), t);
2015  }
2016 
2017  Factors<Derived> f;
2018  f.setRingElement(sf[0]);
2019  for (int i = 1; i < sf.size(); ++i) {
2020  f.addFactor(sf[i], i);
2021  }
2022 
2023  return f;
2024  }
2025 
2026  /**
2027  * Overload stream operator <<
2028  *
2029  * @param out: Stream object
2030  * @param b: The univariate polynomial
2031  **/
2032  inline void print (std::ostream &out) const {
2033  int n = terms.size();
2034  if (!n) { out << "0"; }
2035  for (int i = 0; i < n; ++i) {
2036  if (this->terms[i].exp) {
2037  if (this->terms[i].coef.isNegativeOne())
2038  out << "-";
2039  else if (i && this->terms[i].coef.isConstant() >= 0)
2040  out << "+";
2041  if (!this->terms[i].coef.isConstant())
2042  out << "(" << this->terms[i].coef << ")*";
2043  else if (!this->terms[i].coef.isOne() && !this->terms[i].coef.isNegativeOne())
2044  out << this->terms[i].coef << "*";
2045  out << this->name;
2046  if (this->terms[i].exp > 1)
2047  out << "^" << this->terms[i].exp;
2048  }
2049  else {
2050  if (this->terms[i].coef.isConstant()) { out << this->terms[i].coef; }
2051  else { out << "(" << this->terms[i].coef << ")"; }
2052  }
2053  }
2054  }
2055 
2056  inline ExpressionTree convertToExpressionTree() const {
2057  //TODO
2058  std::cerr << "BPAS ERROR: SMP<Ring>::convertToExpressionTree NOT YET IMPLEMENTED" << std::endl;
2059  return ExpressionTree();
2060  }
2061 
2062  inline DenseUnivariateRationalPolynomial convertToDUQP() {
2063  bool isDense = 1;
2064  int k = 0, n = terms.size(), d = 0;
2065  if (n) { d = terms[n-1].exp; }
2067  res.setVariableName(name);
2068  for (int i = 0; i <= d; ++i) {
2069  if (k < n) {
2070  if (!terms[k].coef.isConstant()) {
2071  isDense = 0;
2072  break;
2073  }
2074  else if (terms[k].exp == i) {
2075  res.setCoefficient(i, RationalNumber(terms[k].coef));
2076  k++;
2077  }
2078  }
2079  }
2080  if (!isDense) { res.zero(); }
2081  return res;
2082  }
2083 
2084  inline DenseUnivariateIntegerPolynomial convertToDUZP() {
2085  bool isDense = 1;
2086  int k = 0, n = terms.size(), d = 0;
2087  if (n) { d = terms[n-1].exp; }
2089  res.setVariableName(name);
2090  for (int i = 0; i <= d; ++i) {
2091  if (k < n) {
2092  if (!terms[k].coef.isConstant()) {
2093  isDense = 0;
2094  break;
2095  }
2096  else if (terms[k].exp == i) {
2097  res.setCoefficient(i, Integer(terms[k].coef));
2098  k++;
2099  }
2100  }
2101  }
2102  if (!isDense) { res.zero(); }
2103  return res;
2104  }
2105 
2106 
2107 
2108 
2109 
2110 
2111 
2112 };
2113 
2114 /**
2115  * A univariate polynomial over an arbitrary BPASField represented sparsely.
2116  * This is the base for SparseUnivariatePolynomial when the template
2117  * parameter is a field.
2118  * Users should use SparseUnivariatePolynomial directly and not thing class.
2119  *
2120  * @see SparseUnivariatePolynomial SparseUnivariateTempPoly
2121  */
2122 template <class Field, class Derived>
2123 class SparseUnivariateTempFieldPoly : public virtual SparseUnivariateTempPoly<Field, Derived> {
2124 
2125  Integer euclideanSize() const {
2126  return this->degree();
2127  }
2128 
2129  Derived euclideanDivision(
2130  const Derived& b,
2131  Derived* q = NULL) const
2132  {
2133  Field lc = b.leadingCoefficient();
2134  Derived monicb = b * lc.inverse();
2135  if (q != NULL) {
2136  Derived rem;
2137  *q = this->monicDivide(monicb, &rem);
2138  *q *= lc;
2139  return rem;
2140  } else {
2141  Derived rem = *this;
2142  return rem.monicDivide(b);
2143  }
2144 
2145  }
2146 
2147  Derived extendedEuclidean(
2148  const Derived& b,
2149  Derived* s,
2150  Derived* t) const
2151  {
2152  //TODO NOT YET IMPLEMENTED
2153 
2154  return *this;
2155  }
2156 
2157 
2158  Derived quotient(const Derived& b) const {
2159  Derived q;
2160  this->euclideanDivision(b, &q);
2161  return q;
2162  }
2163 
2164  Derived remainder(const Derived& b) const {
2165  return this->euclideanDivision(b);
2166  }
2167 
2168  Derived operator%(const Derived& b) const {
2169  Derived ret = *this;
2170  ret %= b;
2171  return ret;
2172  }
2173 
2174  Derived& operator%=(const Derived& b) {
2175  *this = this->remainder(b);
2176  return dynamic_cast<Derived&>(*this);
2177  }
2178 };
2179 
2180 /**
2181  * A sparsely represented univariate polynomial over an arbitrary ring.
2182  * This class automatically adapts its inheritance structure and
2183  * interface depending on if the template parameter listed is a field or not.
2184  *
2185  * @see SparseUnivariateTempPoly, SparseUnivariateTempFieldPoly
2186  *
2187  *
2188  * Inheritance of proper base class, and exporting of proper functions,
2189  * is automatic when the Ring template parameter is specified at compile time
2190  * by means of std::conditional.
2191  */
2192 template <class Ring>
2193 class SparseUnivariatePolynomial : public std::conditional<std::is_base_of<BPASField<Ring>, Ring>::value, SparseUnivariateTempFieldPoly<Ring, SparseUnivariatePolynomial<Ring>>, SparseUnivariateTempPoly<Ring, SparseUnivariatePolynomial<Ring>> >::type {
2194 
2195 public:
2197 
2198  SparseUnivariatePolynomial<Ring>() : Base() {}
2199 
2201  Base::operator=(other);
2202  return *this;
2203  }
2204 
2206  Base::operator=(other);
2207  return *this;
2208  }
2209 
2211  Base::operator=(r);
2212  return *this;
2213  }
2214 
2217 
2218  SparseUnivariatePolynomial<Ring>(int a) : Base(a) {}
2219 
2220 
2221  SparseUnivariatePolynomial<Ring>(const Integer& a) : Base(a) {}
2222 
2223  SparseUnivariatePolynomial<Ring>(const RationalNumber& a) : Base(a) {}
2224 
2226 
2228 
2230 
2231 
2232  SparseUnivariatePolynomial<Ring> (Symbol sym) : Base(sym) {}
2233 
2234  SparseUnivariatePolynomial<Ring> (const Base& b) : Base(b) {}
2235 
2236  /**
2237  * Destroy the polynomial
2238  *
2239  * @param
2240  **/
2242 
2243 
2244 };
2245 
2246 
2247 
2248 
2249 //TODO: Develop random element generator for all BPASRings so that this can be placed in SUP<Ring>
2250 /**
2251  * Generate random polynomial
2252  *
2253  * @param n: degree of the random polynomial
2254  * @param sparsity: the proportion of non-zero elements
2255  * @param bits: maximum number of bits for each coefficient
2256  **/
2257 static SparseUnivariatePolynomial<RationalNumber> randomSUPQPolynomial(int n, double sparsity, unsigned long int coefBound){
2258  int k;
2259  mpq_t randVal;
2260  rand_mpq_t(coefBound,1,randVal);
2261  mpq_class coef(randVal);
2263  P.setCoefficient(n, coef);
2264  int nTerms = ceil(sparsity*n);
2265  int index;
2266  for(int i = 0; i < nTerms; i++) {
2267  // Set random coefficients with sparsity
2268  index = rand() % n;
2269  rand_mpq_t(coefBound,1,randVal);
2270  coef = mpq_class(randVal);
2271  P.setCoefficient(index, coef);
2272  }
2273 
2274  return P;
2275 }
2276 
2277 
2278 
2279 
2280 
2281 
2282 
2283 
2284 
2285 
2286 
2287 
2288 
2289 
2290 
2291 
2292 
2293 
2294 
2295 
2296 #endif
2297 
2298 
2299 
2300 
2301 
Derived & operator<<=(int k)
Overload operator <<= replace by muplitying x^k.
Definition: upolynomial.h:812
Derived & operator*=(const Derived &b)
Overload operator *=.
Definition: upolynomial.h:1191
Factors< Derived > squareFree() const
Square free.
Definition: upolynomial.h:1969
Derived operator/(const Derived &b) const
Overload operator / EdeDivision.
Definition: upolynomial.h:1251
A sparsely represented univariate polynomial over an arbitrary ring.
Definition: BigPrimeField.hpp:21
Derived operator^(long long int e) const
Overload operator ^ replace xor operation by exponentiation.
Definition: upolynomial.h:753
Derived pseudoDivide(const Derived &b, Derived *rem, Ring *d) const
Pseudo dividsion Return the quotient.
Definition: upolynomial.h:1565
Ring content() const override
Content of the polynomial.
Definition: upolynomial.h:726
Derived lazyPseudoDivide(const Derived &b, Derived *rem, Ring *c, Ring *d) const
Lazy pseudo dividsion Return the quotient e is the exact number of division steps.
Definition: upolynomial.h:1532
std::vector< Derived > monomialBasisSubresultantChain(const Derived &q)
monomialBasisSubResultantChain
Definition: upolynomial.h:1807
void zero()
Zero polynomial.
Definition: urpolynomial.h:313
void negativeOne()
Set polynomial to -1.
Definition: upolynomial.h:687
Derived operator*(const Derived &b) const
Multiply another polynomial.
Definition: upolynomial.h:1076
std::vector< Derived > subresultantChain(const Derived &q, int filled=0) const
Subresultant Chain Return the list of subresultants.
Definition: upolynomial.h:1742
void setVariableName(const Symbol &x)
Set variable&#39;s name.
Definition: urpolynomial.h:240
Derived lazyPseudoDivide(const Derived &b, Ring *c, Ring *d=NULL)
Lazy pseudo dividsion Return the quotient and itself becomes remainder e is the exact number of divis...
Definition: upolynomial.h:1474
An arbitrary-precision complex rational number.
Definition: ComplexRationalNumber.hpp:23
Derived operator-() const
Overload operator -, negate.
Definition: upolynomial.h:956
Symbol variable() const
Get the variable name.
Definition: upolynomial.h:545
RationalNumber coefficient(int k) const
Get a coefficient of the polynomial.
Definition: urpolynomial.h:199
void integrate()
Compute integral with constant of integration set to 0.
Definition: upolynomial.h:1626
An ExpressionTree encompasses various forms of data that can be expressed generically as a binary tre...
Definition: ExpressionTree.hpp:17
Integer numberOfTerms() const
Get the number of terms.
Definition: upolynomial.h:456
Derived & operator>>=(int k)
Overload operator >>= replace by dividing x^k, and return the quotient.
Definition: upolynomial.h:837
bool isNegativeOne() const
Is polynomial a constant -1.
Definition: upolynomial.h:676
Derived monicDivide(const Derived &b)
Monic division Assuming the leading coefficient of dividend is 1 Return quotient and itself becomes r...
Definition: upolynomial.h:1411
A univariate polynomial with Integer coefficients using a dense representation.
Definition: uzpolynomial.h:14
Integer degree() const
Get degree of the polynomial.
Definition: urpolynomial.h:149
Symbol variable() const
Get variable&#39;s name.
Definition: uzpolynomial.h:196
bool isZero() const
Is zero polynomial.
Definition: upolynomial.h:634
int isConstant() const
Is a constant.
Definition: upolynomial.h:700
Ring evaluate(const Ring &x) const
Evaluate f(x)
Definition: upolynomial.h:1664
LargerRing evaluate(const LargerRing &x) const
Evaluate f(x)
Definition: upolynomial.h:1686
A univariate polynomial over an arbitrary BPASRing represented sparsely.
Definition: upolynomial.h:20
Derived monicDivide(const Derived &b, Derived *rem) const
Monic division Assuming the leading coefficient of dividend is 1 Return quotient. ...
Definition: upolynomial.h:1459
void setCoefficient(int k, const mpz_class value)
Set a coefficient of the polynomial.
Definition: uzpolynomial.h:165
void setCoefficient(int e, const Ring &c)
Set a coeffcient with its exponent.
Definition: upolynomial.h:513
Ring coefficient(int k) const
Get a coefficient.
Definition: upolynomial.h:496
Integer leadingCoefficient() const
Get the leading coefficient.
Definition: uzpolynomial.h:114
bool isOne() const
Is polynomial a constant 1.
Definition: upolynomial.h:652
Derived operator>>(int k) const
Overload operator >> replace by dividing x^k, and return the quotient.
Definition: upolynomial.h:825
A univariate polynomial with RationalNumber coefficients represented densely.
Definition: urpolynomial.h:16
void negate()
Negate the polynomial.
Definition: upolynomial.h:1399
Derived & operator/=(const Derived &b)
Overload operator /= ExactDivision.
Definition: upolynomial.h:1263
bool operator==(const Derived &b) const
Overload operator ==.
Definition: upolynomial.h:617
Integer coefficient(int k) const
Get a coefficient of the polynomial.
Definition: uzpolynomial.h:152
A simple data structure for encapsulating a collection of Factor elements.
Definition: Factors.hpp:95
void zero()
Zero polynomial.
Definition: uzpolynomial.h:263
Derived gcd(const Derived &q) const
GCD(p, q)
Definition: upolynomial.h:1906
bool operator!=(const Derived &b) const
Overload operator !=.
Definition: upolynomial.h:608
Derived operator<<(int k) const
Overload operator << replace by muplitying x^k.
Definition: upolynomial.h:801
An arbitrary-precision Integer.
Definition: Integer.hpp:22
An abstract class defining the interface of a univariate polynomial over an arbitrary BPASRing...
Definition: BPASUnivarPolynomial.hpp:22
void setVariableName(const Symbol &c)
Set the variable name.
Definition: upolynomial.h:554
Derived derivative(int k) const
Return k-th derivative.
Definition: upolynomial.h:1607
Derived operator+(const Derived &b) const
Overload operator +.
Definition: upolynomial.h:855
void one()
Set polynomial to 1.
Definition: upolynomial.h:663
Derived & operator+=(const Derived &b)
Overload operator+=.
Definition: upolynomial.h:865
Derived integral() const
Compute integral with constant of integration 0.
Definition: upolynomial.h:1639
Derived & operator=(const Derived &b)
Overload operator =.
Definition: upolynomial.h:578
Ring leadingCoefficient() const
Get the leading coefficient.
Definition: upolynomial.h:476
Derived & operator^=(long long int e)
Overload operator ^= replace xor operation by exponentiation.
Definition: upolynomial.h:790
void differentiate()
Convert current object to its derivative.
Definition: upolynomial.h:1598
void print(std::ostream &out) const
Overload stream operator <<.
Definition: upolynomial.h:2032
void setCoefficient(int k, const RationalNumber &value)
Set a coefficient of the polynomial.
Definition: urpolynomial.h:211
void differentiate(int k)
Compute k-th derivative.
Definition: upolynomial.h:1579
An encapsulation of a mathematical symbol.
Definition: Symbol.hpp:23
An arbitrary-precision rational number.
Definition: RationalNumber.hpp:24
Derived & operator-=(const Derived &b)
Overload operator -=.
Definition: upolynomial.h:983
Ring convertToConstant()
Convert to a constant.
Definition: upolynomial.h:711
bool isConstantTermZero() const
Is trailing coefficient zero.
Definition: upolynomial.h:1650
void zero()
Zero polynomial.
Definition: upolynomial.h:643
Symbol variable() const
Get variable&#39;s name.
Definition: urpolynomial.h:231
bool isOne() const
Is a 1.
Definition: Integer.hpp:179
Derived pseudoDivide(const Derived &b, Ring *d=NULL)
Pseudo dividsion Return the quotient and itself becomes remainder.
Definition: upolynomial.h:1545
A univariate polynomial over an arbitrary BPASField represented sparsely.
Definition: upolynomial.h:2123
Integer degree() const
Get the degree of the polynomial.
Definition: upolynomial.h:465
Integer degree() const
Get degree of the polynomial.
Definition: uzpolynomial.h:105
void setVariableName(const Symbol &x)
Set variable&#39;s name.
Definition: uzpolynomial.h:204
Derived resultant(const Derived &q)
Resultant.
Definition: upolynomial.h:1896
Derived derivative() const
Compute derivative.
Definition: upolynomial.h:1617