1 #ifndef _UPOLYNOMIAL_H_ 2 #define _UPOLYNOMIAL_H_ 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" 19 template <
class Ring,
class Derived>
28 std::vector< UnivariateTerm<Ring> > terms;
30 inline bool isEqual(
const Derived& b)
const {
31 if (
degree() > 0 && b.degree() > 0 && (name != b.name))
34 int m = b.terms.size();
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)
51 n = terms.size(), m++;
53 for (
int i = 0; i < m; ++i) {
54 if (k < n && terms[k].exp == i) {
71 n = terms.size(), m++;
73 for (
int i = 0; i < m; ++i) {
74 if (k < n && terms[k].exp == i) {
86 inline void pomopo(UnivariateTerm<Ring> t,
const Derived& b) {
87 int ai = 0, m = b.terms.size();
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;
154 if (ai >= terms.size()) {
155 terms.emplace_back(prodCoef, prodExp);
158 aExp = terms[ai].exp;
159 while (aExp < prodExp) {
161 if (ai < terms.size())
162 aExp = terms[ai].exp;
164 terms.emplace_back(prodCoef, prodExp);
169 if (aExp == prodExp) {
170 terms[ai].coef += prodCoef;
171 if (!terms[ai].coef.isZero()) {
174 terms.erase(terms.begin()+ai);
177 else if (aExp > prodExp) {
178 terms.emplace(terms.begin()+ai, prodCoef, prodExp);
186 inline void pomopo(Ring c, UnivariateTerm<Ring> t,
const Derived& b) {
187 int ai = 0, m = b.terms.size();
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;
194 if (ai >= terms.size()) {
195 terms.push_back(product);
199 int e1 = terms[ai].exp, e2 = product.exp;
203 if (ai < terms.size())
206 terms.push_back(product);
213 terms[ai].coef += product.coef;
214 if (terms[ai].coef.isZero())
215 terms.erase(terms.begin()+ai);
219 terms.insert(terms.begin()+ai, product);
224 for (
int i = ai; i < terms.size(); ++i)
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();
235 int a = (int) pow(2, floor(log2(n)));
258 inline Derived DucosSem(Derived& a, Derived& sdm, Derived& se, Ring sd)
const {
261 int e = sdm.degree().get_si();
264 Ring ec = se.leadingCoefficient();
274 Ring dc = a.leadingCoefficient();
281 rTemp = a.coefficient(e);
288 rTemp = se.coefficient(e-1);
290 supTemp.setCoefficient(0,rTemp);
292 supTemp.setCoefficient(1,rTemp);
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);
307 for (
int i = e+1; d > i; ++i)
309 P[e].setVariableName(name);
310 P[e].setCoefficient(e, ec);
313 res.setCoefficient(1, ec);
314 UnivariateTerm<Ring> t (ec, 1);
315 for(
int i = e+1; i < d; ++i) {
317 ec = -P[i-1].coefficient(e-1);
326 P[i].pomopo(t, P[i-1]);
328 res *= P[d.get_si()-1];
331 for (
int i = 0; i < d; ++i) {
332 P[i] *= a.coefficient(i);
335 D /= a.leadingCoefficient();
338 ec = -res.coefficient(e);
343 res.pomopo(mc, t, D);
348 if ((d - e + 1) % 2 == 1) {
355 inline UnivariateTerm<Ring> leadingTerm()
const {
356 int n = terms.size();
357 if (n) {
return terms[n-1]; }
358 else {
return UnivariateTerm<Ring>(); }
362 mpz_class characteristic;
373 characteristic = e.getCharacteristic();
383 characteristic = e.getCharacteristic();
387 UnivariateTerm<Ring> t;
393 UnivariateTerm<Ring> t;
399 UnivariateTerm<Ring> t;
406 UnivariateTerm<Ring> t;
413 for (
int i = 0; i <= b.degree().get_si(); ++i) {
414 Ring e (
Integer(b.coefficient(i)));
416 UnivariateTerm<Ring> t;
426 for (
int i = 0; i <= b.degree().get_si(); ++i) {
429 UnivariateTerm<Ring> t;
466 int n = terms.size();
467 if (n) {
return terms[n-1].exp; }
477 int n = terms.size();
478 if (n) {
return terms[n-1].coef; }
479 else {
return Ring(); }
482 inline Ring trailingCoefficient()
const {
483 int n = terms.size();
485 return terms[0].coef;
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)
514 UnivariateTerm<Ring> b;
519 int k = terms.size() - 1;
520 if ((k < 0 || b.exp > terms[k].exp) && !c.isZero())
523 for (
int i = 0; i <= k; ++i) {
524 int e1 = terms[i].exp, e2 = b.exp;
526 terms[i].coef = b.coef;
527 if (terms[i].coef.isZero())
528 terms.erase(terms.begin()+i);
533 terms.insert(terms.begin()+i, b);
558 inline Derived unitCanonical(Derived* u = NULL, Derived* v = NULL)
const {
561 Ring canon = lead.unitCanonical(&ru, &rv);
562 Derived ret = *
this * ru;
584 characteristic = e.getCharacteristic();
586 return dynamic_cast<Derived&
>(*this);
596 UnivariateTerm<Ring> t;
599 return dynamic_cast<Derived&
>(*this);
609 return !(isEqual(b));
635 return !(terms.size());
653 if (terms.size() == 1 && !terms[0].exp)
654 return terms[0].coef.isOne();
665 UnivariateTerm<Ring> t;
677 if (terms.size() == 1 && !terms[0].exp)
678 return terms[0].coef.isNegativeOne();
689 UnivariateTerm<Ring> t;
690 t.coef.negativeOne();
701 if (terms.size() == 1 && !terms[0].exp)
702 return terms[0].coef.isConstant();
712 if (terms.size() && !terms[0].exp)
713 return terms[0].coef;
728 int n = terms.size();
731 for (
int i = 1; i < n; ++i) {
732 c = c.gcd(terms[i].coef);
741 inline Derived primitivePart()
const {
743 std::cerr <<
"BPAS ERROR: SUP<Ring>::primitivePart NOT YET IMPLEMENTED" << std::endl;
771 if (e % 2) { res *= x; }
792 return dynamic_cast<Derived&
>(*this);
813 for (
int i = 0; i < terms.size(); ++i)
814 terms[i].exp += (
unsigned long int) k;
815 return dynamic_cast<Derived&
>(*this);
839 unsigned long int e = (
unsigned long int) k;
840 while (i < terms.size()) {
841 if (terms[i].exp >= e) {
845 else { terms.erase(terms.begin()); }
847 return dynamic_cast<Derived&
>(*this);
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;
876 for (
int i = 0; i < b.terms.size(); ++i) {
877 UnivariateTerm<Ring> bt = b.terms[i];
878 if (ai >= terms.size()) {
883 int e1 = terms[ai].exp, e2 = bt.exp;
886 if (ai < terms.size())
895 terms[ai].coef += bt.coef;
896 if (terms[ai].coef.isZero())
897 terms.erase(terms.begin()+ai);
901 terms.insert(terms.begin()+ai, bt);
904 return dynamic_cast<Derived&
>(*this);
925 UnivariateTerm<Ring> a = terms[0];
929 terms.insert(terms.begin(), a);
933 if (terms[0].coef.isZero())
934 terms.erase(terms.begin());
938 UnivariateTerm<Ring> a;
944 return dynamic_cast<Derived&
>(*this);
947 inline friend Derived
operator+ (
const Ring& c,
const Derived& p) {
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);
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;
994 for (
int i = 0; i < b.terms.size(); ++i) {
995 UnivariateTerm<Ring> t = b.terms[i];
998 if (ai >= terms.size()) {
1003 int e1 = terms[ai].exp, e2 = t.exp;
1006 if (ai < terms.size())
1015 terms[ai].coef += t.coef;
1016 if (terms[ai].coef.isZero())
1017 terms.erase(terms.begin()+ai);
1021 terms.insert(terms.begin()+ai, t);
1024 return dynamic_cast<Derived&
>(*this);
1045 UnivariateTerm<Ring> t = terms[0];
1049 terms.insert(terms.begin(), t);
1053 if (terms[0].coef.isZero())
1054 terms.erase(terms.begin());
1058 UnivariateTerm<Ring> t;
1064 return dynamic_cast<Derived&
>(*this);
1067 inline friend Derived
operator- (
const Ring& c,
const Derived& p) {
1077 int n = terms.size(), m = b.terms.size();
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;
1090 res.terms.push_back(t);
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);
1107 if (name != b.name) {
1108 std::cout <<
"BPAS: error, trying to multiply between Ring[" << name <<
"] and Ring[" << b.name <<
"]." << std::endl;
1114 for (
int i = 0; i < n; ++i)
1115 res.pomopo(terms[i], b);
1118 for (
int i = 0; i < m; ++i)
1119 res.pomopo(b.terms[i], *
this);
1123 int s = (m > n) ? m : n;
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]);
1131 UnivariateTerm<Ring> t (terms[i].coef, terms[i].exp-s);
1132 f1.terms.push_back(t);
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]);
1141 UnivariateTerm<Ring> t (b.terms[i].coef, b.terms[i].exp-s);
1142 g1.terms.push_back(t);
1146 t0.name = t1.name = name;
1147 n = f0.terms.size(), m = g0.terms.size();
1149 for (
int i = 0; i < n; ++i)
1150 res.pomopo(f0.terms[i], g0);
1153 for (
int i = 0; i < m; ++i)
1154 res.pomopo(g0.terms[i], f0);
1156 n = f1.terms.size(), m = g1.terms.size();
1158 for (
int i = 0; i < n; ++i)
1159 t0.pomopo(f1.terms[i], g1);
1162 for (
int i = 0; i < m; ++i)
1163 t0.pomopo(g1.terms[i], f1);
1166 n = f0.terms.size(), m = g0.terms.size();
1168 for (
int i = 0; i < n; ++i)
1169 t1.pomopo(f0.terms[i], g0);
1172 for (
int i = 0; i < m; ++i)
1173 t1.pomopo(g0.terms[i], f0);
1176 for (
int i = 0; i < t1.terms.size(); ++i)
1177 t1.terms[i].exp += s;
1179 for (
int i = 0; i < t0.terms.size(); ++i)
1180 t0.terms[i].exp += s;
1193 return dynamic_cast<Derived&
>(*this);
1206 inline Derived
operator* (
const sfixn& e)
const {
1218 if (!c.isZero() && !c.isOne()) {
1219 for (
int i = 0; i < terms.size(); ++i)
1222 else if (c.isZero())
1225 return dynamic_cast<Derived&
>(*this);
1228 inline Derived&
operator*= (
const sfixn& e) {
1229 if (e != 0 && e != 1) {
1230 for (
int i = 0; i < terms.size(); ++i)
1233 else if (e == 0) {
zero(); }
1234 return dynamic_cast<Derived&
>(*this);
1237 inline friend Derived
operator* (
const Ring& e,
const Derived& p) {
1241 inline friend Derived
operator* (
const sfixn& e,
const Derived& p) {
1265 std::cout <<
"BPAS: error, dividend is zero from Derived." << std::endl;
1268 if (b.isConstant()) {
return (*
this /= b.terms[0].coef); }
1271 return dynamic_cast<Derived&
>(*this);
1273 if (name != b.name) {
1274 std::cout <<
"BPAS: error, trying to exact divide between Ring[" << name <<
"] and Ring[" << b.name <<
"]." << std::endl;
1282 UnivariateTerm<Ring> bt = b.leadingTerm();
1284 if (db == 1 && bt.coef.
isOne()) {
1285 if (b.terms.size() > 1) {
1288 UnivariateTerm<Ring> t, at = leadingTerm();
1289 if (!terms[0].exp) {
1290 prev = t.coef = terms[0].coef / b.terms[0].coef;
1292 q.terms.push_back(t);
1295 else { prev.zero(); }
1296 for (
int i = 1; i < at.exp; ++i) {
1297 if (k < terms.size() && terms[k].exp == i) {
1302 t.coef = (e - prev) / b.terms[0].coef;
1303 if (!t.coef.isZero()) {
1305 q.terms.push_back(t);
1309 if (prev == at.coef)
1312 std::cout <<
"BPAS: error, not exact division in Derived." << std::endl;
1317 if (!terms[0].exp) {
1318 std::cout <<
"BPAS: error, not exact division in Derived." << std::endl;
1322 for (
int i = 0; i < terms.size(); ++i)
1324 return dynamic_cast<Derived&
>(*this);
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;
1337 q.terms.insert(q.terms.begin(), lc);
1340 std::cout <<
"BPAS: error, not exact division in Derived." << std::endl;
1364 std::cout <<
"BPAS: error, dividend is zero from Derived." << std::endl;
1367 else if (!e.isOne()) {
1369 while (i < terms.size()) {
1371 if (terms[i].coef.isZero())
1372 terms.erase(terms.begin()+i);
1376 return dynamic_cast<Derived&
>(*this);
1379 inline friend Derived
operator/ (
const Ring& e,
const Derived& p) {
1381 std::cout <<
"BPAS: error, dividend is zero from Derived." << std::endl;
1387 if (p.isConstant()) {
1389 return (q /= p.terms[0].coef);
1400 for (
int i = 0; i < terms.size(); ++i)
1401 terms[i].coef = -terms[i].coef;
1413 std::cout <<
"BPAS: error, dividend is zero from Derived." << std::endl;
1416 else if (!b.leadingCoefficient().isOne()) {
1417 std::cout <<
"BPAS: error, leading coefficient is not one in monicDivide() from Derived." << std::endl;
1421 if (b.isConstant()) {
1431 if (name != b.name) {
1432 std::cout <<
"BPAS: error, trying to monic divide between Ring[" << name <<
"] and Ring[" << b.name <<
"]." << std::endl;
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;
1446 quo.terms.insert(quo.terms.begin(), at);
1460 std::cout <<
"*this " << *
this << std::endl;
1461 *rem = *
this; std::cout<<
"salam"<<std::endl;
1462 return rem->monicDivide(b);
1478 if (b.isZero() || db == 0) {
1479 std::cout <<
"BPAS: error, dividend is zero or constant from Derived." << std::endl;
1488 if (name != b.name) {
1489 std::cout <<
"BPAS: error, trying to pseudo divide between Ring[" << name <<
"] and Ring[" << b.name <<
"]." << std::endl;
1501 Ring blc = b.leadingTerm().coef;
1506 UnivariateTerm<Ring> at = leadingTerm();
1507 UnivariateTerm<Ring> nlc;
1508 nlc.coef = -at.coef;
1509 nlc.exp = at.exp - db.get_si();
1513 pomopo(blc, nlc, b);
1515 quo.terms.insert(quo.terms.begin(), at);
1517 for (
int i = e; diff >= i; ++i)
1534 return rem->lazyPseudoDivide(b, c, d);
1565 inline Derived
pseudoDivide (
const Derived& b, Derived* rem, Ring* d)
const {
1580 if (k <= 0) {
return; }
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);
1590 terms.erase(terms.begin());
1627 int i = terms.size()-1;
1629 terms[i].coef /= (terms[i].exp + 1);
1653 int n = terms.size();
1654 if (n && terms[0].exp == 0 && terms[0].coef == Ring(0))
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;
1670 for (
int i = e; i > -1; --i) {
1672 if (i == terms[d].exp && d > -1) {
1673 px += terms[d].coef;
1685 template <
class LargerRing>
1686 inline LargerRing
evaluate(
const LargerRing& x)
const {
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;
1694 for (
int i = e; i > -1; --i) {
1696 if (i == terms[d].exp && d > -1) {
1697 a = (LargerRing)terms[d].coef;
1705 inline void fillChain (std::vector<Derived>& chain)
const {
1708 int fullSize(chain[chain.size()-2].degree().get_ui()+2);
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();
1719 for (
int j=0; j<delta-2; ++j)
1720 chain.insert(chain.begin()+i,
zero);
1723 for (
int j=0; j<delta-1; ++j)
1724 chain.insert(chain.begin()+i,
zero);
1728 if (chain[0].
degree() != 0) {
1729 for (
int j=0; j<chain[0].degree(); ++j)
1730 chain.insert(chain.begin(),
zero);
1743 if (name != q.name) {
1744 std::cout <<
"BPAS: error, trying to compute subresultant chains between Ring[" << name <<
"] and Ring[" << q.name <<
"]." << std::endl;
1748 if (
degree() == 0 || q.degree() == 0){
1749 std::cout <<
"BPAS: error, Input polynomials to subresultantChain must have positive degree." << std::endl;
1753 std::vector< Derived > S;
1755 if (q.degree() >
degree()) {
1764 int k = (a.degree() - b.degree()).get_si();
1767 Derived A = b, B = a, C = -b;
1769 b *= b.leadingCoefficient()^(k-1);
1778 S.insert(S.begin(), B);
1779 delta = A.degree() - B.degree();
1781 C = LazardSe(S[1], S[0], s);
1782 S.insert(S.begin(), C);
1785 if (B.degree() == 0)
1787 B = DucosSem(A, B, C, s);
1789 s = A.leadingCoefficient();
1792 if (S.at(0).degree() > 0) {
1793 S.insert(S.begin(), B);
1796 std::cerr <<
"filling chain..." << std::endl;
1811 for (
int i=s.size()-2; i>0; --i) {
1812 delta = s.at(i).degree() - s.at(i-1).degree();
1814 if (i == 1 && s.at(i-1).isZero())
1818 for (
int j=0; j<n; j++)
1819 s.insert(s.begin()+i-1,sup);
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;
1914 Derived a(*
this), b(q);
1915 if (a.degree() == 0 || b.degree() == 0) {
1938 std::vector< Derived > R = a.subresultantChain(b);
1940 r.setCoefficient(0, ca.gcd(cb));
1946 for (
int i = 0; i < n; ++i) {
1948 cr = R[i].content();
1957 if (a.degree() <= b.degree()) { r *= a; }
1970 std::vector< Derived > sf;
1971 int d = terms.size()-1;
1973 sf.push_back(*
this);
1974 else if (terms[d].exp == 1) {
1979 t = *
this / terms[d].coef;
1983 Derived a (*
this), b(*
this);
1985 Derived g = a.gcd(b);
1993 while (!z.isZero()) {
2007 for (
int i = 0; i < sf.size(); ++i) {
2008 e *= sf[i].leadingCoefficient();
2009 sf[i] /= sf[i].leadingCoefficient();
2014 sf.insert(sf.begin(), t);
2018 f.setRingElement(sf[0]);
2019 for (
int i = 1; i < sf.size(); ++i) {
2020 f.addFactor(sf[i], i);
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())
2039 else if (i && this->terms[i].coef.isConstant() >= 0)
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 <<
"*";
2046 if (this->terms[i].exp > 1)
2047 out <<
"^" << this->terms[i].exp;
2050 if (this->terms[i].coef.isConstant()) { out << this->terms[i].coef; }
2051 else { out <<
"(" << this->terms[i].coef <<
")"; }
2058 std::cerr <<
"BPAS ERROR: SMP<Ring>::convertToExpressionTree NOT YET IMPLEMENTED" << std::endl;
2064 int k = 0, n = terms.size(), d = 0;
2065 if (n) { d = terms[n-1].exp; }
2068 for (
int i = 0; i <= d; ++i) {
2070 if (!terms[k].coef.isConstant()) {
2074 else if (terms[k].exp == i) {
2080 if (!isDense) { res.
zero(); }
2086 int k = 0, n = terms.size(), d = 0;
2087 if (n) { d = terms[n-1].exp; }
2090 for (
int i = 0; i <= d; ++i) {
2092 if (!terms[k].coef.isConstant()) {
2096 else if (terms[k].exp == i) {
2102 if (!isDense) { res.
zero(); }
2122 template <
class Field,
class Derived>
2125 Integer euclideanSize()
const {
2129 Derived euclideanDivision(
2131 Derived* q = NULL)
const 2133 Field lc = b.leadingCoefficient();
2134 Derived monicb = b * lc.inverse();
2141 Derived rem = *
this;
2142 return rem.monicDivide(b);
2147 Derived extendedEuclidean(
2158 Derived quotient(
const Derived& b)
const {
2160 this->euclideanDivision(b, &q);
2164 Derived remainder(
const Derived& b)
const {
2165 return this->euclideanDivision(b);
2168 Derived operator%(
const Derived& b)
const {
2169 Derived ret = *
this;
2174 Derived& operator%=(
const Derived& b) {
2175 *
this = this->remainder(b);
2176 return dynamic_cast<Derived&
>(*this);
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 {
2201 Base::operator=(other);
2206 Base::operator=(other);
2260 rand_mpq_t(coefBound,1,randVal);
2261 mpq_class coef(randVal);
2263 P.setCoefficient(n, coef);
2264 int nTerms = ceil(sparsity*n);
2266 for(
int i = 0; i < nTerms; i++) {
2269 rand_mpq_t(coefBound,1,randVal);
2270 coef = mpq_class(randVal);
2271 P.setCoefficient(index, coef);
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'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'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'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'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