int DotPowerPolyByDouble(Polynom* _pPoly, Double* _pDouble, InternalType** _pOut) { if (_pDouble->isEmpty()) { //p .^ [] *_pOut = Double::Empty(); return 0; } int iSize = _pPoly->getSize(); if (_pPoly->isScalar()) { return PowerPolyByDouble(_pPoly, _pDouble, _pOut); } Double** pDblPower = new Double*[iSize]; double* pdblPower = _pDouble->get(); if (_pDouble->isScalar()) { if (pdblPower[0] < 0) { //call overload _pOut = NULL; delete[] pDblPower; return 0; } for (int i = 0; i < iSize; i++) { pDblPower[i] = new Double(pdblPower[0]); } } else if (_pDouble->getSize() == iSize) { for (int i = 0; i < iSize; i++) { if (pdblPower[i] < 0) { //call overload _pOut = NULL; delete[] pDblPower; return 0; } pDblPower[i] = new Double(pdblPower[i]); } } else { delete[] pDblPower; throw ast::InternalError(_W("Invalid exponent.\n")); } InternalType* pITTempOut = NULL; Polynom* pPolyTemp = new Polynom(_pPoly->getVariableName(), 1, 1); Polynom* pPolyOut = new Polynom(_pPoly->getVariableName(), _pPoly->getDims(), _pPoly->getDimsArray()); SinglePoly** pSPOut = pPolyOut->get(); SinglePoly** pSPTemp = pPolyTemp->get(); SinglePoly** pSP = _pPoly->get(); int iResult = 0; for (int i = 0; i < iSize; i++) { // set singlePoly of _pPoly in pPolyTemp without copy pSPTemp[0] = pSP[i]; iResult = PowerPolyByDouble(pPolyTemp, pDblPower[i], &pITTempOut); if (iResult) { break; } // get singlePoly of pITTempOut and set it in pPolyOut without copy SinglePoly** pSPTempOut = pITTempOut->getAs<Polynom>()->get(); pSPOut[i] = pSPTempOut[0]; // increase ref to avoid the delete of pSPTempOut[0] // which are setted in pSPOut without copy. pSPOut[i]->IncreaseRef(); delete pITTempOut; pSPOut[i]->DecreaseRef(); } //delete exp for(int i = 0; i < iSize; i++) { delete pDblPower[i]; } delete[] pDblPower; // delete temporary polynom // do not delete the last SinglePoly of _pPoly setted without copy in pPolyTemp pSPTemp[0]->IncreaseRef(); delete pPolyTemp; pSP[iSize - 1]->DecreaseRef(); switch (iResult) { case 1 : { delete pPolyOut; throw ast::InternalError(_W("Inconsistent row/column dimensions.\n")); } case 2 : { delete pPolyOut; throw ast::InternalError(_W("Invalid exponent.\n")); } default: //OK break; } *_pOut = pPolyOut; return 0; }
//(c) Chernysheva, TEST(Matrix, RightTrian) //------->>>>>>>>>----------------- // приведение матрицы к треугольному виду алгоритмом Коновальцева, // внутри применяется бинарный алгоритм Гаусса // на выходе получаем верхнетреугольную матрицу справа-налево Matrix& Matrix::konovalcevRightTrianBits() { if ((this->getCoding() == ON_LINE)&&(this->getTrianType() == NONE)) { //int r = (log(n)/log(P)) - 3*(log(log(n)/log(P))/log(P)); // длина кортежа int r = 3; uint activeRow = 0, activeCol = this->ColCount - 1;; Polynom *cortege = new Polynom, *nul = new Polynom; while ((activeRow < this->RowCount)&&(activeCol >= 0)) { uint aRow = activeRow, aCol = activeCol, notNulCortegeRow = 0; bool allCortegeNul = false; uint NumNotNulCortege = 0; // работа с кортежами while ((aRow < this->RowCount)&&(!allCortegeNul)) { // ищем первый ненулевой кортеж for (uint i = aRow; i < this->RowCount; i++) { // прохождение по кортежу uint rc = 0; for (uint ri = aCol + 1 - r; ri < aCol + 1; ri++) { bool bit = this->getBit(i, ri); cortege->setBit(rc, bit); rc++; } if (*cortege != *nul) { notNulCortegeRow = i; NumNotNulCortege++; break; } } // все кортежи нулевые if (*cortege == *nul) allCortegeNul = true; else { Polynom *buf = new Polynom, *curCortege = new Polynom; // меняем местами активную строку со строкой с ненулевым кортежем if (notNulCortegeRow != aRow) { *buf = *this->plMatrix[notNulCortegeRow]; *this->plMatrix[notNulCortegeRow] = *this->plMatrix[aRow]; *this->plMatrix[aRow] = *buf; } // удаление одинаковых с активным кортежей for (uint i = aRow + 1; i < this->RowCount; i++) { uint rc = 0; for (uint ri = aCol + 1 - r; ri < aCol + 1; ri++) { bool bit = this->getBit(i, ri); curCortege->setBit(rc, bit); rc++; } uint t = 0; for (uint rc = 0; rc < r; rc++) { bool y = (cortege->getBit(rc) == curCortege->getBit(rc)); if (y) t++; } if (t == r) { *this->plMatrix[i] = *this->plMatrix[i] - *this->plMatrix[aRow]; } } aRow++; } } aRow = activeRow, aCol = activeCol; // метод Гаусса для приведения к треугольному виду while ((aRow < activeRow + NumNotNulCortege)&&(aCol >= 0)) { bool bitActiveRow = this->getBit(aRow, aCol); if (bitActiveRow) { bool bit; for (uint i = aRow + 1; i < this->RowCount; i++) { bit = this->getBit(i, aCol); if (bit) this->plMatrix[i]->Xor(*this->plMatrix[i], *this->plMatrix[aRow]); } aCol--; aRow++; } else { bool bit; // так как мы уже знаем, что бит, находящийся на пересечении // activeRow и activeCol равен 0, то мы можем воспользоваться этим uint firstTrueBit = activeRow; for (uint i = aRow + 1; i < this->RowCount; i++) { bit = this->getBit(i, aCol); if (bit) { firstTrueBit = i; break; } } // не состоит ли весь столбец из нулей if (firstTrueBit != activeRow) this->plMatrix[aRow]->Xor(*this->plMatrix[aRow], *this->plMatrix[firstTrueBit]); else aCol--; } } activeCol -= r; activeRow += r; } this->setTrianType(RIGHT); } return *this; }
int RDividePolyByDouble(Polynom* _pPoly, Double* _pDouble, Polynom** _pPolyOut) { bool bComplex1 = _pPoly->isComplex(); bool bComplex2 = _pDouble->isComplex(); bool bScalar1 = _pPoly->getRows() == 1 && _pPoly->getCols() == 1; bool bScalar2 = _pDouble->getRows() == 1 && _pDouble->getCols() == 1; Polynom *pTemp = NULL; //use only if _pPoly is scalar and _pDouble not. int iRowResult = 0; int iColResult = 0; int *piRank = NULL; /* if(bScalar1 && bScalar2) { iRowResult = 1; iColResult = 1; piRank = new int[1]; piRank[0] = _pPoly->get(0)->getRank(); } else */ if (bScalar1 == false && bScalar2 == false) { // call overload return 0; } if (bScalar2) { double dblDivR = _pDouble->get(0); double dblDivI = _pDouble->getImg(0); (*_pPolyOut) = _pPoly->clone()->getAs<Polynom>(); if (_pDouble->isComplex()) { (*_pPolyOut)->setComplex(true); } for (int i = 0 ; i < _pPoly->getSize() ; i++) { bool bComplex1 = _pPoly->isComplex(); bool bComplex2 = _pDouble->isComplex(); SinglePoly* pC = (*_pPolyOut)->get(i); if (bComplex1 == false && bComplex2 == false) { iRightDivisionRealMatrixByRealMatrix(pC->get(), 1, &dblDivR, 0, pC->get(), 1, pC->getSize()); } else if (bComplex1 == true && bComplex2 == false) { iRightDivisionComplexMatrixByRealMatrix(pC->get(), pC->getImg(), 1, &dblDivR, 0, pC->get(), pC->getImg(), 1, pC->getSize()); } else if (bComplex1 == false && bComplex2 == true) { iRightDivisionRealMatrixByComplexMatrix(pC->get(), 1, &dblDivR, &dblDivI, 0, pC->get(), pC->getImg(), 1, pC->getSize()); } else if (bComplex1 == true && bComplex2 == true) { iRightDivisionComplexMatrixByComplexMatrix(pC->get(), pC->getImg(), 1, &dblDivR, &dblDivI, 0, pC->get(), pC->getImg(), 1, pC->getSize()); } } return 0; } if (bScalar1) { //in this case, we have to create a temporary square polinomial matrix iRowResult = _pDouble->getCols(); iColResult = _pDouble->getRows(); piRank = new int[iRowResult * iRowResult]; int iMaxRank = _pPoly->getMaxRank(); for (int i = 0 ; i < iRowResult * iRowResult ; i++) { piRank[i] = iMaxRank; } pTemp = new Polynom(_pPoly->getVariableName(), iRowResult, iRowResult, piRank); if (bComplex1 || bComplex2) { pTemp->setComplex(true); } SinglePoly *pdblData = _pPoly->get(0); for (int i = 0 ; i < iRowResult ; i++) { pTemp->set(i, i, pdblData); } } (*_pPolyOut) = new Polynom(_pPoly->getVariableName(), iRowResult, iColResult, piRank); delete[] piRank; if (bComplex1 || bComplex2) { (*_pPolyOut)->setComplex(true); } if (bScalar2) { //[p] * cst for (int i = 0 ; i < _pPoly->getSize() ; i++) { SinglePoly *pPolyIn = _pPoly->get(i); double* pRealIn = pPolyIn->get(); double* pImgIn = pPolyIn->getImg(); SinglePoly *pPolyOut = (*_pPolyOut)->get(i); double* pRealOut = pPolyOut->get(); double* pImgOut = pPolyOut->getImg(); if (bComplex1 == false && bComplex2 == false) { iRightDivisionRealMatrixByRealMatrix( pRealIn, 1, _pDouble->getReal(), 0, pRealOut, 1, pPolyOut->getSize()); } else if (bComplex1 == false && bComplex2 == true) { iRightDivisionRealMatrixByComplexMatrix( pRealIn, 1, _pDouble->getReal(), _pDouble->getImg(), 0, pRealOut, pImgOut, 1, pPolyOut->getSize()); } else if (bComplex1 == true && bComplex2 == false) { iRightDivisionComplexMatrixByRealMatrix( pRealIn, pImgIn, 1, _pDouble->getReal(), 0, pRealOut, pImgOut, 1, pPolyOut->getSize()); } else if (bComplex1 == true && bComplex2 == true) { iRightDivisionComplexMatrixByComplexMatrix( pRealIn, pImgIn, 1, _pDouble->getReal(), _pDouble->getImg(), 0, pRealOut, pImgOut, 1, pPolyOut->getSize()); } } } else if (bScalar1) { for (int i = 0 ; i < pTemp->get(0)->getSize() ; i++) { Double *pCoef = pTemp->extractCoef(i); Double *pResultCoef = new Double(iRowResult, iColResult, pCoef->isComplex()); double *pReal = pResultCoef->getReal(); double *pImg = pResultCoef->getImg(); if (bComplex1 == false && bComplex2 == false) { double dblRcond = 0; iRightDivisionOfRealMatrix( pCoef->getReal(), iRowResult, iRowResult, _pDouble->getReal(), _pDouble->getRows(), _pDouble->getCols(), pReal, iRowResult, iColResult, &dblRcond); } else { double dblRcond = 0; iRightDivisionOfComplexMatrix( pCoef->getReal(), pCoef->getImg(), iRowResult, iRowResult, _pDouble->getReal(), _pDouble->getImg(), _pDouble->getRows(), _pDouble->getCols(), pReal, pImg, iRowResult, iColResult, &dblRcond); } (*_pPolyOut)->insertCoef(i, pResultCoef); delete pCoef; delete pResultCoef; } } return 0; }
int PowerPolyByDouble(Polynom* _pPoly, Double* _pDouble, InternalType** _pOut) { bool bComplex1 = _pPoly->isComplex(); bool bScalar1 = _pPoly->isScalar(); double* bImg = _pDouble->getImg(); bool bNumericallyComplex1 = _pDouble->isNumericallyComplex(); if(!bNumericallyComplex1) { return 2; } if (_pDouble->isEmpty()) { //p ** [] *_pOut = Double::Empty(); return 0; } if (bScalar1) { //p ^ x or p ^ X int iRank = 0; int* piRank = new int[_pDouble->getSize()]; _pPoly->getRank(&iRank); for (int i = 0 ; i < _pDouble->getSize() ; i++) { int iInputRank = (int)_pDouble->get(i); if (iInputRank < 0) { //call overload _pOut = NULL; delete[] piRank; return 0; } piRank[i] = iRank * iInputRank; } Polynom* pOut = new Polynom(_pPoly->getVariableName(), _pDouble->getRows(), _pDouble->getCols(), piRank); delete[] piRank; pOut->setComplex(bComplex1); for (int i = 0 ; i < _pDouble->getSize() ; i++) { SinglePoly* pCoeffOut = pOut->get(i); int iCurrentRank = 0; int iLoop = (int)_pDouble->get(i); //initialize Out to 1 pCoeffOut->set(0, 1); //get a copy of p Polynom* pP = _pPoly->clone()->getAs<Polynom>(); pP->setComplex(_pPoly->isComplex()); while (iLoop) { SinglePoly* ps = pP->get()[0]; if (iLoop % 2) { int iRank = pP->getMaxRank(); if (bComplex1) { C2F(wpmul1)(pCoeffOut->get(), pCoeffOut->getImg(), &iCurrentRank, ps->get(), ps->getImg(), &iRank, pCoeffOut->get(), pCoeffOut->getImg()); } else { C2F(dpmul1)(pCoeffOut->get(), &iCurrentRank, ps->get(), &iRank, pCoeffOut->get()); } iCurrentRank += iRank; } iLoop /= 2; if (iLoop) { //p = p * p Polynom* pTemp = NULL; MultiplyPolyByPoly(pP, pP, &pTemp); pP->killMe(); pP = pTemp; } } pP->killMe(); } *_pOut = pOut; } return 0; }
IntervalledPolynom generateIntervalPartition(const unsigned int* const dimensional_upper_bounds, const size_t dimensions) { DEBUG_MSG("Interval Partitioning started"); // vektor<std::pair<vektor<unsigned int>, vektor<unsigned int> > solution; vektor<IB> intervalbounds; intervalbounds.push_back(dimensional_upper_bounds[0]); IntervalledPolynom intervalledPolynom; { Polynom pol(1); pol[0] = 1; intervalledPolynom.push_back(dimensional_upper_bounds[0], pol); } for(size_t k = 1; k < dimensions; ++k) { DEBUG_MSG("k: " << k); assert(dimensional_upper_bounds[k] > 0); vektor<IB> help_intervalbounds; help_intervalbounds.push_back(dimensional_upper_bounds[k] - 1); for(const IB& old_intervalbound : intervalbounds) help_intervalbounds.push_back(old_intervalbound + dimensional_upper_bounds[k]); vektor<IB> tmp_intervalbounds; IntervalledPolynom tmp_intervalledPolynom; for(size_t i = 0, j = 0, witness_left = 0, witness_right = 0, last_upper_bound_index = 0, last_lower_bound_index = 0; j < help_intervalbounds.size();) { const IB intervalbound = i < intervalbounds.size() ? intervalbounds[i] : 0; const IB help_intervalbound = help_intervalbounds[j]; const IB last_upper_bound = last_upper_bound_index == 0 ? 0 : (last_upper_bound_index > intervalbounds.size() ? intervalbounds[last_upper_bound_index-2] : intervalbounds[last_upper_bound_index-1]); const IB last_lower_bound = last_lower_bound_index == 0 ? 0 : (last_lower_bound_index > intervalbounds.size() ? intervalbounds[last_lower_bound_index-2] : intervalbounds[last_lower_bound_index-1]); DEBUG_MSG(""); DEBUG_MSG("k: " << k << ", i: " << i << ", j: " << j); if(i < intervalbounds.size()) { if(intervalbound < help_intervalbound) { tmp_intervalbounds.push_back(intervalbound); if(last_upper_bound < intervalbound) { ++witness_right; ++last_upper_bound_index; } if(intervalbound > last_lower_bound + dimensional_upper_bounds[k] ) //TODO: with else? { ++witness_left; ++last_lower_bound_index; } DEBUG_MSG("Fall 1, addiere " << intervalbound); // jetzt summe mit Anfangsintervall [..., // _old_intervals[j-1]] // und Endintervall [_old_intervals[i-1], ...]auswerten // Ergebnis zu _new_coefficients hinzufuegen ++i; } else if(intervalbound > help_intervalbound) { tmp_intervalbounds.push_back(help_intervalbound); if(last_upper_bound < help_intervalbound) { ++witness_right; ++last_upper_bound_index; } if(help_intervalbound > last_lower_bound + dimensional_upper_bounds[k]) { ++witness_left; ++last_lower_bound_index; } DEBUG_MSG("Fall 2, addiere " << help_intervalbound); // jetzt summe mit Anfangsintervall [..., // _old_intervals[j-1]] // und Endintervall [_old_intervals[i-1], // ...]auswerten // Ergebnis zu _new_coefficients hinzufuegen ++j; } else { tmp_intervalbounds.push_back(intervalbound); if(intervalbound > last_upper_bound) { ++witness_right; ++last_upper_bound_index; } if(intervalbound > last_lower_bound + dimensional_upper_bounds[k]) { ++witness_left; ++last_lower_bound_index; } DEBUG_MSG("Fall 3, addiere " << help_intervalbound); // jetzt summe mit Anfangsintervall [..., // _old_intervals[j-1]] // und Endintervall [_old_intervals[i-1], // ...]auswerten // Ergebnis zu _new_coefficients hinzufuegen ++i; ++j; } } else { tmp_intervalbounds.push_back(help_intervalbound); if(help_intervalbound > last_upper_bound && last_upper_bound_index <= intervalbounds.size()) { ++witness_right; ++last_upper_bound_index; } if(help_intervalbound > last_lower_bound + dimensional_upper_bounds[k]) { ++witness_left; ++last_lower_bound_index; } /* if(help_intervalbound <= static_cast<long>(intervalbounds[intervalbounds.size()-1])) { witness_right = intervalbounds.size(); ++witness_left; } else { if(witness_right == intervalbounds.size()) ++witness_right; else ++witness_left; } */ DEBUG_MSG("Fall 4, addiere " << help_intervalbound); // jetzt summe mit Anfangsintervall [..., // _old_intervals[j-1]] // und Endintervall [_old_intervals[i-1], ...]auswerten // Ergebnis zu _new_coefficients hinzufuegen ++j; } DEBUG_MSG("intervalledPolynom: " << intervalledPolynom); DEBUG_MSG("tmp_intervalledPolynom: " << tmp_intervalledPolynom); DEBUG_MSG("Witness: " << "[" << witness_left << ", " << witness_right << "]"); DEBUG_MSG("tmp_intervalbounds: " << tmp_intervalbounds); DEBUG_MSG("intervalbounds: " << intervalbounds); if(witness_left == witness_right) { if(witness_left <= intervalbounds.size() && witness_left > 0) { const IB& current_intervalbound = intervalbounds[witness_left-1]; //! DEBUG_MSG("Intervalbound: " << current_intervalbound); const Polynom& toSum = intervalledPolynom.at(current_intervalbound); const Polynom& upper = SumFromZeroToUpper::s(toSum); const Polynom lower = sumFromZeroToZMinusGamma(toSum, dimensional_upper_bounds[k]+1); Polynom together(std::max(upper.size(), lower.size())+1); for(size_t l = 0; l < together.size(); ++l) { if(l < upper.size()) together[l] += upper[l]; if(l < lower.size()) together[l] -= lower[l]; } DEBUG_MSG("Together Sum: " << together); tmp_intervalledPolynom.push_back(tmp_intervalbounds.back(), together); } else tmp_intervalledPolynom.push_back(tmp_intervalbounds.back(), Polynom::zero); } else { const Polynom lower_sum = (witness_left < 1 || witness_left-1 >= intervalbounds.size()) ? Polynom::zero : [&] () -> Polynom { const IB& lower_sum_intervalbound = intervalbounds[witness_left-1]; //! DEBUG_MSG("Lower Interval: " << lower_sum_intervalbound); return sumFromZMinusGammaToUpper(intervalledPolynom.at(lower_sum_intervalbound), dimensional_upper_bounds[k], lower_sum_intervalbound); }(); DEBUG_MSG("Lower Sum: " << lower_sum); const Z const_sum = ( (witness_left > 0 || witness_right > 0) && witness_right-witness_left > 1) ? [&] () -> Z { Q const_sumq; for(size_t constinterval = witness_left; constinterval <= witness_right-2; ++constinterval) { if(constinterval >= intervalbounds.size()) break; //! const IB& intervalupper_bound = intervalbounds[constinterval]; //! const Polynom& summedUp = SumFromZeroToUpper::s(intervalledPolynom.at(intervalupper_bound)); const_sumq += summedUp(intervalupper_bound); if(constinterval > 0) { const IB& intervallower_bound = intervalbounds[constinterval-1]; //! const_sumq -= summedUp(intervallower_bound); } } mpq_canonicalize(const_sumq.get_mpq_t()); assert(const_sumq.get_den() == 1); return const_sumq.get_num(); }() : 0; DEBUG_MSG("Constant Sum: " << const_sum); const Polynom upper_sum = (witness_right-1 >= intervalbounds.size()) ? Polynom::zero : [&] () -> Polynom { const IB& upper_sum_intervalupper_bound = intervalbounds[witness_right-1]; //! Polynom upper_sum_pol = SumFromZeroToUpper::s(intervalledPolynom.at(upper_sum_intervalupper_bound)); if(witness_right > 1) { const IB& upper_sum_intervallower_bound = intervalbounds[witness_right-2]; upper_sum_pol[0] -= upper_sum_pol(upper_sum_intervallower_bound); } DEBUG_MSG("Upper Interval: " << upper_sum_intervalupper_bound); return upper_sum_pol; }(); DEBUG_MSG("Upper Sum: " << upper_sum); Polynom together(std::max(upper_sum.size(), lower_sum.size())+1); for(size_t l = 0; l < together.size(); ++l) { if(l < lower_sum.size()) together[l] += lower_sum[l]; if(l < upper_sum.size()) together[l] += upper_sum[l]; } together[0] += const_sum; DEBUG_MSG("Together Sum: " << together); tmp_intervalledPolynom.push_back(tmp_intervalbounds.back(), together); } } intervalbounds.swap(tmp_intervalbounds); intervalledPolynom.swap(tmp_intervalledPolynom); DEBUG_MSG("_old_intervals: " << intervalbounds); } DEBUG_MSG("Resulting Intervalled Polynom: " << intervalledPolynom); return intervalledPolynom; }
void BooleanInvolutiveBasis<MonomType>::ConstructInvolutiveBasis() { typename TSet<MonomType>::Iterator tit(IntermediateBasis.Begin()); Polynom<MonomType>* newNormalForm = 0; Triple<MonomType>* currentTriple = 0; while (!ProlongationsSet.Empty()) { currentTriple = ProlongationsSet.Get(); newNormalForm = NormalForm(currentTriple); /* As far as currentTriple can't be 0 (checked in QSET and TSET), * NormalForm can't return 0. */ std::set<typename MonomType::Integer> currentNmpSet; const Triple<MonomType>* currentAncestor = 0; if (!newNormalForm->IsZero() && newNormalForm->Lm() == currentTriple->GetPolynomLm()) { currentNmpSet = currentTriple->GetNmp(); currentAncestor = currentTriple->GetAncestor(); if (currentAncestor == currentTriple) { currentAncestor = 0; } } delete currentTriple; if (!newNormalForm->IsZero()) { std::list<Triple<MonomType>*> newProlongations; tit = IntermediateBasis.Begin(); while (tit != IntermediateBasis.End()) { if ((**tit).GetPolynomLm().IsTrueDivisibleBy(newNormalForm->Lm())) { ProlongationsSet.DeleteDescendants(*tit); newProlongations.push_back(*tit); tit = IntermediateBasis.Erase(tit); } else { ++tit; } } IntermediateBasis.PushBack(new Triple<MonomType>(newNormalForm, currentAncestor, currentNmpSet, 0, -1)); if (!newNormalForm->Degree()) { return; } IntermediateBasis.CollectNonMultiProlongations(--IntermediateBasis.End(), newProlongations); ProlongationsSet.Insert(newProlongations); } else { delete newNormalForm; } } }
bool Polynom::operator <= (const Polynom& _another) const { return pow() <= _another.pow(); }
bool Polynom::operator > (const Polynom& _another) const { return pow() > _another.pow(); }
Polynom polynomAdd(const Polynom &p1, const Polynom &p2) { Polynom result = p1; for (int i = 0; i < p2.size(); ++i) addToPolynom(result, p2.at(i)); return result; }
static Polynom one() { Polynom res; res.front() = 1; return res; }
Polynom subtract(const Polynom& rhs) const { return add(rhs.negate()); }