32 #ifndef BGEOT_POLY_H__
33 #define BGEOT_POLY_H__
64 std::vector<short_type> v;
70 typedef std::vector<short_type>::iterator iterator;
71 typedef std::vector<short_type>::const_iterator const_iterator;
72 typedef std::vector<short_type>::reverse_iterator reverse_iterator;
73 typedef std::vector<short_type>::const_reverse_iterator const_reverse_iterator;
77 iterator begin() { dirty();
return v.begin(); }
78 const_iterator begin()
const {
return v.begin(); }
79 iterator end() { dirty();
return v.end(); }
80 const_iterator end()
const {
return v.end(); }
82 reverse_iterator rbegin() { dirty();
return v.rbegin(); }
83 const_reverse_iterator rbegin()
const {
return v.rbegin(); }
84 reverse_iterator rend() { dirty();
return v.rend(); }
85 const_reverse_iterator rend()
const {
return v.rend(); }
87 size_type size()
const {
return v.size(); }
179 template<
typename T>
class polynomial :
public std::vector<T> {
186 typedef typename std::vector<T>::iterator iterator;
187 typedef typename std::vector<T>::const_iterator const_iterator;
188 typedef typename std::vector<T>::reverse_iterator reverse_iterator;
189 typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
232 {
polynomial res = *
this; res /= e;
return res; }
244 {
return(this->
real_degree()==0) && (this->size()==0 || (*this)[0]==T(0)); }
245 template <
typename ITER> T horner(power_index &mi,
short_type k,
250 template <
typename ITER> T
eval(
const ITER &it)
const;
254 { n = 0; d = 0; (*this)[0] = 0.0; }
263 : std::vector<T>(
alpha(nn,dd))
264 { n = nn; d = dd; std::fill(this->begin(), this->end(), T(0)); }
268 : std::vector<T>(
alpha(nn,dd)) {
270 std::fill(this->begin(), this->end(), T(0));
276 {
polynomial res = *
this; res *= Q;
return res; }
280 if (dim() != Q.
dim())
return false;
281 const_iterator it1 = this->begin(), ite1 = this->end();
282 const_iterator it2 = Q.begin(), ite2 = Q.end();
283 for ( ; it1 != ite1 && it2 != ite2; ++it1, ++it2)
284 if (*it1 != *it2)
return false;
285 for ( ; it1 != ite1; ++it1)
if (*it1 != T(0))
return false;
286 for ( ; it2 != ite2; ++it2)
if (*it2 != T(0))
return false;
292 {
polynomial res = *
this; res *= e;
return res; }
295 const_reverse_iterator it = this->rbegin(), ite = this->rend();
297 for ( ; it != ite; ++it, --l) {
if (*it != T(0))
break; }
304 this->resize(
alpha(n,dd));
305 if (dd > d) std::fill(this->begin() +
alpha(n,d), this->end(), T(0));
312 GMM_ASSERT2(n == power.size(),
"dimensions mismatch");
313 if (i >= this->size()) { change_degree(power.
degree()); }
314 ((*this)[i]) += coeff;
319 GMM_ASSERT2(Q.
dim() == dim(),
"dimensions mismatch");
322 iterator it = this->begin();
323 const_iterator itq = Q.begin(), ite = Q.end();
324 for ( ; itq != ite; ++itq, ++it) *it += *itq;
330 GMM_ASSERT2(Q.
dim() == dim() && dim() != 0,
"dimensions mismatch");
333 iterator it = this->begin();
334 const_iterator itq = Q.begin(), ite = Q.end();
335 for ( ; itq != ite; ++itq, ++it) *it -= *itq;
342 iterator itq = Q.begin(), ite = Q.end();
343 for ( ; itq != ite; ++itq) *itq = -(*itq);
349 GMM_ASSERT2(Q.
dim() == dim(),
"dimensions mismatch");
352 change_degree(0); (*this)[0] = T(0);
355 if (dim() > 0) miq[dim()-1] = Q.
degree();
356 const_reverse_iterator itq = Q.rbegin(), ite = Q.rend();
357 for ( ; itq != ite; ++itq, --miq) {
359 reverse_iterator ita = aux.rbegin(), itae = aux.rend();
360 std::fill(mia.begin(), mia.end(), 0);
361 if (dim() > 0) mia[dim()-1] = aux.
degree();
362 for ( ; ita != itae; ++ita, --mia)
364 power_index::iterator mita = mia.begin(), mitq = miq.begin();
365 power_index::iterator mit = mitot.begin(), mite = mia.end();
366 for ( ; mita != mite; ++mita, ++mitq, ++mit)
373 add_monomial((*itq) * (*ita), mitot);
385 change_degree(0); n =
short_type(n+Q.
dim()); (*this)[0] = T(0);
389 const_reverse_iterator itq = Q.rbegin(), ite = Q.rend();
390 for ( ; itq != ite; ++itq, --miq)
392 reverse_iterator ita = aux.rbegin(), itae = aux.rend();
393 std::fill(mia.begin(), mia.end(), 0);
395 for ( ; ita != itae; ++ita, --mia)
397 std::copy(mia.begin(), mia.end(), mitot.begin());
398 std::copy(miq.begin(), miq.end(), mitot.begin() + aux.
dim());
399 add_monomial((*itq) * (*ita), mitot);
407 iterator it = this->begin(), ite = this->end();
408 for ( ; it != ite; ++it) (*it) *= e;
414 iterator it = this->begin(), ite = this->end();
415 for ( ; it != ite; ++it) (*it) /= e;
421 GMM_ASSERT2(k < n,
"index out of range");
423 iterator it = this->begin(), ite = this->end();
425 for ( ; it != ite; ++it) {
426 if ((*it) != T(0) && mi[k] > 0)
427 { mi[k]--; (*this)[mi.
global_index()] = (*it) * T(mi[k] + 1); mi[k]++; }
434 template<
typename T>
template<
typename ITER>
440 T v = (*(it+k-1)), res = T(0);
451 template<
typename T>
template<
typename ITER>
454 unsigned deg = degree();
455 const_iterator P = this->begin();
456 if (deg == 0)
return P[0];
459 for (
size_type i=0; i < dim(); ++i) s += it[i]*P[i+1];
466 if (deg == 2)
return P[0] + x*(P[1] + x*(P[2]));
467 if (deg == 3)
return P[0] + x*(P[1] + x*(P[2] + x*(P[3])));
468 if (deg == 4)
return P[0] + x*(P[1] + x*(P[2] + x*(P[3] + x*(P[4]))));
469 if (deg == 5)
return P[0] + x*(P[1] + x*(P[2] + x*(P[3] + x*(P[4] + x*(P[5])))));
470 if (deg == 6)
return P[0] + x*(P[1] + x*(P[2] + x*(P[3] + x*(P[4] + x*(P[5] + x*(P[6]))))));
475 if (deg == 2)
return P[0] + x*(P[1] + x*(P[3])) + y*(P[2] + x*(P[4]) + y*(P[5]));
476 if (deg == 3)
return P[0] + x*(P[1] + x*(P[3] + x*(P[6]))) + y*(P[2] + x*(P[4] + x*(P[7])) + y*(P[5] + x*(P[8]) + y*(P[9])));
477 if (deg == 4)
return P[0] + x*(P[1] + x*(P[3] + x*(P[6] + x*(P[10])))) + y*(P[2] + x*(P[4] + x*(P[7] + x*(P[11]))) + y*(P[5] + x*(P[8] + x*(P[12])) + y*(P[9] + x*(P[13]) + y*(P[14]))));
478 if (deg == 5)
return P[0] + x*(P[1] + x*(P[3] + x*(P[6] + x*(P[10] + x*(P[15]))))) + y*(P[2] + x*(P[4] + x*(P[7] + x*(P[11] + x*(P[16])))) + y*(P[5] + x*(P[8] + x*(P[12] + x*(P[17]))) + y*(P[9] + x*(P[13] + x*(P[18])) + y*(P[14] + x*(P[19]) + y*(P[20])))));
479 if (deg == 6)
return P[0] + x*(P[1] + x*(P[3] + x*(P[6] + x*(P[10] + x*(P[15] + x*(P[21])))))) + y*(P[2] + x*(P[4] + x*(P[7] + x*(P[11] + x*(P[16] + x*(P[22]))))) + y*(P[5] + x*(P[8] + x*(P[12] + x*(P[17] + x*(P[23])))) + y*(P[9] + x*(P[13] + x*(P[18] + x*(P[24]))) + y*(P[14] + x*(P[19] + x*(P[25])) + y*(P[20] + x*(P[26]) + y*(P[27]))))));
485 if (deg == 2)
return P[0] + x*(P[1] + x*(P[4])) + y*(P[2] + x*(P[5]) + y*(P[7])) + z*(P[3] + x*(P[6]) + y*(P[8]) + z*(P[9]));
486 if (deg == 3)
return P[0] + x*(P[1] + x*(P[4] + x*(P[10]))) + y*(P[2] + x*(P[5] + x*(P[11])) + y*(P[7] + x*(P[13]) + y*(P[16]))) + z*(P[3] + x*(P[6] + x*(P[12])) + y*(P[8] + x*(P[14]) + y*(P[17])) + z*(P[9] + x*(P[15]) + y*(P[18]) + z*(P[19])));
487 if (deg == 4)
return P[0] + x*(P[1] + x*(P[4] + x*(P[10] + x*(P[20])))) + y*(P[2] + x*(P[5] + x*(P[11] + x*(P[21]))) + y*(P[7] + x*(P[13] + x*(P[23])) + y*(P[16] + x*(P[26]) + y*(P[30])))) + z*(P[3] + x*(P[6] + x*(P[12] + x*(P[22]))) + y*(P[8] + x*(P[14] + x*(P[24])) + y*(P[17] + x*(P[27]) + y*(P[31]))) + z*(P[9] + x*(P[15] + x*(P[25])) + y*(P[18] + x*(P[28]) + y*(P[32])) + z*(P[19] + x*(P[29]) + y*(P[33]) + z*(P[34]))));
488 if (deg == 5)
return P[0] + x*(P[1] + x*(P[4] + x*(P[10] + x*(P[20] + x*(P[35]))))) + y*(P[2] + x*(P[5] + x*(P[11] + x*(P[21] + x*(P[36])))) + y*(P[7] + x*(P[13] + x*(P[23] + x*(P[38]))) + y*(P[16] + x*(P[26] + x*(P[41])) + y*(P[30] + x*(P[45]) + y*(P[50]))))) + z*(P[3] + x*(P[6] + x*(P[12] + x*(P[22] + x*(P[37])))) + y*(P[8] + x*(P[14] + x*(P[24] + x*(P[39]))) + y*(P[17] + x*(P[27] + x*(P[42])) + y*(P[31] + x*(P[46]) + y*(P[51])))) + z*(P[9] + x*(P[15] + x*(P[25] + x*(P[40]))) + y*(P[18] + x*(P[28] + x*(P[43])) + y*(P[32] + x*(P[47]) + y*(P[52]))) + z*(P[19] + x*(P[29] + x*(P[44])) + y*(P[33] + x*(P[48]) + y*(P[53])) + z*(P[34] + x*(P[49]) + y*(P[54]) + z*(P[55])))));
489 if (deg == 6)
return P[0] + x*(P[1] + x*(P[4] + x*(P[10] + x*(P[20] + x*(P[35] + x*(P[56])))))) + y*(P[2] + x*(P[5] + x*(P[11] + x*(P[21] + x*(P[36] + x*(P[57]))))) + y*(P[7] + x*(P[13] + x*(P[23] + x*(P[38] + x*(P[59])))) + y*(P[16] + x*(P[26] + x*(P[41] + x*(P[62]))) + y*(P[30] + x*(P[45] + x*(P[66])) + y*(P[50] + x*(P[71]) + y*(P[77])))))) + z*(P[3] + x*(P[6] + x*(P[12] + x*(P[22] + x*(P[37] + x*(P[58]))))) + y*(P[8] + x*(P[14] + x*(P[24] + x*(P[39] + x*(P[60])))) + y*(P[17] + x*(P[27] + x*(P[42] + x*(P[63]))) + y*(P[31] + x*(P[46] + x*(P[67])) + y*(P[51] + x*(P[72]) + y*(P[78]))))) + z*(P[9] + x*(P[15] + x*(P[25] + x*(P[40] + x*(P[61])))) + y*(P[18] + x*(P[28] + x*(P[43] + x*(P[64]))) + y*(P[32] + x*(P[47] + x*(P[68])) + y*(P[52] + x*(P[73]) + y*(P[79])))) + z*(P[19] + x*(P[29] + x*(P[44] + x*(P[65]))) + y*(P[33] + x*(P[48] + x*(P[69])) + y*(P[53] + x*(P[74]) + y*(P[80]))) + z*(P[34] + x*(P[49] + x*(P[70])) + y*(P[54] + x*(P[75]) + y*(P[81])) + z*(P[55] + x*(P[76]) + y*(P[82]) + z*(P[83]))))));
533 return horner(mi, dim(), 0, it);
536 template<
typename ITER>
537 typename std::iterator_traits<ITER>::value_type
539 typename std::iterator_traits<ITER>::value_type res
540 =
typename std::iterator_traits<ITER>::value_type(1);
541 power_index::const_iterator mit = mi.begin(), mite = mi.end();
542 for ( ; mit != mite; ++mit, ++it)
553 typename polynomial<T>::const_iterator it = P.begin(), ite = P.end();
555 if (it != ite && *it != T(0))
556 { o << *it; first =
false; ++it; ++n; ++mi; }
557 for ( ; it != ite ; ++it, ++mi ) {
559 bool first_var =
true;
560 if (!first) {
if (*it < T(0)) o <<
" - ";
else o <<
" + "; }
561 else if (*it < T(0)) o <<
"-";
562 if (gmm::abs(*it)!=T(1)) { o << gmm::abs(*it); first_var =
false; }
565 if (!first_var) o <<
"*";
567 if (P.
dim() <= 7) o <<
"xyzwvut"[j];
569 if (mi[j] > 1) o <<
"^" << mi[j];
574 if (n == 0) o <<
"0";
589 GMM_ASSERT2(S.
dim() == 1 && subs_dim < P.
dim(),
590 "wrong arguments for polynomial substitution");
593 std::vector< polynomial<T> > Spow(1);
595 for (
size_type k=0; k < P.size(); ++k, ++pi) {
596 if (P[k] == T(0))
continue;
597 while (pi[subs_dim] >= Spow.size())
598 Spow.push_back(S*Spow.back());
609 template<
typename U,
typename T>
610 polynomial<T> operator *(T c,
const polynomial<T> &p)
611 { polynomial<T> q = p; q *= c;
return q; }
613 typedef polynomial<opt_long_scalar_type> base_poly;
617 inline base_poly null_poly(
short_type n) {
return base_poly(n, 0); }
619 { base_poly res=base_poly(n, 0); res.one();
return res; }
621 {
return base_poly(n, 1, k); }
634 template<
typename T>
class rational_fraction :
public std::vector<T> {
637 polynomial<T> numerator_, denominator_;
641 const polynomial<T> &numerator()
const {
return numerator_; }
642 const polynomial<T> &denominator()
const {
return denominator_; }
644 short_type dim()
const {
return numerator_.dim(); }
647 rational_fraction &operator +=(
const rational_fraction &Q) {
648 numerator_ = numerator_*Q.denominator() + Q.numerator()*denominator_;
649 denominator_ *= Q.denominator();
653 rational_fraction &operator -=(
const rational_fraction &Q) {
654 numerator_ = numerator_*Q.denominator() - Q.numerator()*denominator_;
655 denominator_ *= Q.denominator();
659 rational_fraction
operator +(
const rational_fraction &Q)
const
660 { rational_fraction R = *
this; R += Q;
return R; }
662 rational_fraction
operator -(
const rational_fraction &Q)
const
663 { rational_fraction R = *
this; R -= Q;
return R; }
665 rational_fraction
operator +(
const polynomial<T> &Q)
const
666 { rational_fraction R(numerator_+Q*denominator_, denominator_);
return R; }
668 rational_fraction
operator -(
const polynomial<T> &Q)
const
669 { rational_fraction R(numerator_-Q*denominator_, denominator_);
return R; }
671 { rational_fraction R(-numerator_, denominator_);
return R; }
673 rational_fraction &operator *=(
const rational_fraction &Q)
674 { numerator_*=Q.numerator(); denominator_*=Q.denominator();
return *
this; }
676 rational_fraction &operator /=(
const rational_fraction &Q)
677 { numerator_*=Q.denominator(); denominator_*=Q.numerator();
return *
this; }
679 rational_fraction operator *(
const rational_fraction &Q)
const
680 { rational_fraction R = *
this; R *= Q;
return R; }
682 rational_fraction operator /(
const rational_fraction &Q)
const
683 { rational_fraction R = *
this; R /= Q;
return R; }
685 rational_fraction &operator *=(
const T &e)
686 { numerator_ *= e;
return *
this; }
688 rational_fraction operator *(
const T &e)
const
689 { rational_fraction R = *
this; R *= e;
return R; }
691 rational_fraction &operator /=(
const T &e)
692 { denominator_ *= e;
return *
this; }
694 rational_fraction operator /(
const T &e)
const
695 { rational_fraction res = *
this; res /= e;
return res; }
698 {
return (numerator_==Q.numerator() && denominator_==Q.denominator()); }
700 bool operator !=(
const rational_fraction &Q)
const
704 polynomial<T> der_num = numerator_; der_num.derivative(k);
705 polynomial<T> der_den = denominator_; der_den.derivative(k);
706 if (der_den.is_zero()) {
707 if (der_num.is_zero()) this->
clear();
708 else numerator_ = der_num;
710 numerator_ = der_num * denominator_ - der_den * numerator_;
711 denominator_ = denominator_ * denominator_;
715 void one() { numerator_.one(); denominator_.one(); }
716 void clear() { numerator_.clear(); denominator_.one(); }
717 template <
typename ITER> T eval(
const ITER &it)
const {
718 typedef typename gmm::number_traits<T>::magnitude_type R;
719 T a = numerator_.eval(it), b = denominator_.eval(it);
721 std::vector<T> p(it, it+dim());
724 else gmm::scale(p, R(0.9999999));
725 a = numerator_.eval(p.begin());
726 b = denominator_.eval(p.begin());
728 if (a != T(0)) a /= b;
733 : numerator_(1,0), denominator_(1,0) {
clear(); }
736 : numerator_(dim_,0), denominator_(dim_,0) {
clear(); }
738 rational_fraction(
const polynomial<T> &numer)
739 : numerator_(numer), denominator_(numer.dim(),0) { denominator_.one(); }
741 rational_fraction(
const polynomial<T> &numer,
const polynomial<T> &denom)
742 : numerator_(numer), denominator_(denom)
743 { GMM_ASSERT1(numer.dim() == denom.dim(),
"Dimensions mismatch"); }
749 const rational_fraction<T> &Q) {
750 rational_fraction<T> R(P*Q.denominator()+Q.numerator(), Q.denominator());
756 const rational_fraction<T> &Q) {
757 rational_fraction<T> R(P*Q.denominator()-Q.numerator(), Q.denominator());
761 template<
typename T> std::ostream &
operator <<
762 (std::ostream &o,
const rational_fraction<T>& P) {
763 o <<
"[" << P.numerator() <<
"]/[" << P.denominator() <<
"]";
767 typedef rational_fraction<opt_long_scalar_type> base_rational_fraction;
defines and typedefs for namespace bgeot
This class deals with plain polynomials with several variables.
short_type real_degree() const
gives the degree of the polynomial, considering only non-zero coefficients
polynomial(short_type dim_, short_type degree_, short_type k)
Constructor for the polynomial 'x' (k=0), 'y' (k=1), 'z' (k=2) etc.
polynomial & operator+=(const polynomial &Q)
Add Q to P. P contains the result.
short_type dim() const
Gives the dimension (number of variables)
polynomial & operator-=(const polynomial &Q)
Subtract Q from P. P contains the result.
void add_monomial(const T &coeff, const power_index &power)
Add to the polynomial a monomial of coefficient a and correpsonding to the power index pi.
polynomial operator*(const polynomial &Q) const
Multiply P with Q.
polynomial(short_type dim_, short_type degree_)
Constructor.
T eval(const ITER &it) const
Evaluate the polynomial.
void change_degree(short_type dd)
Change the degree of the polynomial to d.
void derivative(short_type k)
Derivative of P with respect to the variable k. P contains the result.
polynomial operator+(const polynomial &Q) const
Add Q to P.
bool operator!=(const polynomial &Q) const
operator !=.
polynomial & operator*=(const polynomial &Q)
Multiply P with Q. P contains the result.
short_type degree() const
Gives the degree of the polynomial.
polynomial & operator/=(const T &e)
Divide P with the scalar a. P contains the result.
polynomial operator/(const T &e) const
Divide P with the scalar a.
void direct_product(const polynomial &Q)
Product of P and Q considering that variables of Q come after variables of P.
bool operator==(const polynomial &Q) const
operator ==.
Vector of integer (16 bits type) which represent the powers of a monomial.
power_index()
Constructor.
const power_index & operator++()
Gives the next power index.
short_type degree() const
Gives the degree.
size_type global_index() const
Gives the global number of the index (i.e.
const power_index & operator--()
Gives the next previous index.
Stores interdependent getfem objects.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
void fill_random(L &l)
fill a vector or matrix with random value (uniform [-1,1]).
void clear(L &l)
clear (fill with zeros) a vector or matrix.
gmm::uint16_type short_type
used as the common short type integer in the library
base_poly read_base_poly(short_type n, std::istream &f)
read a base_poly on the stream ist.
rational_fraction< T > operator-(const polynomial< T > &P, const rational_fraction< T > &Q)
Subtract Q from P.
polynomial< T > poly_substitute_var(const polynomial< T > &P, const polynomial< T > &S, size_type subs_dim)
polynomial variable substitution
rational_fraction< T > operator+(const polynomial< T > &P, const rational_fraction< T > &Q)
Add Q to P.
std::ostream & operator<<(std::ostream &o, const convex_structure &cv)
Print the details of the convex structure cvs to the output stream o.
bool operator==(const pconvex_structure &p1, const pconvex_structure &p2)
Stored objects must be compared by keys, because there is a possibility that they are duplicated in s...
size_t size_type
used as the common size type in the library
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree .