void F4Reducer::classicReducePolySet( const std::vector< std::unique_ptr<Poly> >& polys, const PolyBasis& basis, std::vector< std::unique_ptr<Poly> >& reducedOut ) { if (polys.size() <= 1) { if (tracingLevel >= 2) std::cerr << "F4Reducer: Using fall-back reducer for " << polys.size() << " polynomials.\n"; mFallback->classicReducePolySet(polys, basis, reducedOut); return; } reducedOut.clear(); MATHICGB_ASSERT(!polys.empty()); if (tracingLevel >= 2) std::cerr << "F4Reducer: Reducing " << polys.size() << " polynomials.\n"; SparseMatrix reduced; QuadMatrix::Monomials monomials; { QuadMatrix qm(ring()); { if (mType == OldType) { F4MatrixBuilder builder(basis, mMemoryQuantum); for (const auto& poly : polys) builder.addPolynomialToMatrix(*poly); builder.buildMatrixAndClear(qm); } else { F4MatrixBuilder2 builder(basis, mMemoryQuantum); for (const auto& poly : polys) builder.addPolynomialToMatrix(*poly); builder.buildMatrixAndClear(qm); } } MATHICGB_LOG_INCREMENT_BY(F4MatrixRows, qm.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixTopRows, qm.topLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixBottomRows, qm.bottomLeft.rowCount()); MATHICGB_LOG_INCREMENT_BY(F4MatrixEntries, qm.entryCount()); saveMatrix(qm); reduced = F4MatrixReducer(basis.ring().charac()). reducedRowEchelonFormBottomRight(qm); monomials = std::move(qm.rightColumnMonomials); for (auto& mono : qm.leftColumnMonomials) monoid().freeRaw(mono.castAwayConst()); } if (tracingLevel >= 2 && false) std::cerr << "F4Reducer: Extracted " << reduced.rowCount() << " non-zero rows\n"; for (SparseMatrix::RowIndex row = 0; row < reduced.rowCount(); ++row) { auto p = make_unique<Poly>(basis.ring()); reduced.rowToPolynomial(row, monomials, *p); reducedOut.push_back(std::move(p)); } for (auto& mono : monomials) monoid().freeRaw(mono.castAwayConst()); }
void SchreyerFrame::show(int len) const { std::cout << "#levels=" << mFrame.mLevels.size() << " currentLevel=" << currentLevel() << std::endl; for (int i=0; i<mFrame.mLevels.size(); i++) { auto& myframe = level(i); auto& myorder = schreyerOrder(i); if (myframe.size() == 0) continue; std::cout << "--- level " << i << " ------" << std::endl; for (int j=0; j<myframe.size(); j++) { std::cout << " " << j << " " << myframe[j].mDegree << " (" << myframe[j].mBegin << "," << myframe[j].mEnd << ") " << std::flush; std::cout << "(size:" << myframe[j].mSyzygy.len << ") ["; monoid().showAlpha(myorder.mTotalMonom[j]); std::cout << " " << myorder.mTieBreaker[j] << "] "; if (len == 0 or myframe[j].mSyzygy.len == 0) monoid().showAlpha(myframe[j].mMonom); else display_poly(stdout, ring(), myframe[j].mSyzygy); std::cout << std::endl; } } showMemoryUsage(); }
void SigPolyBasis::lowBaseDivisorsSlow( std::vector<size_t>& divisors, size_t maxDivisors, size_t newGenerator) const { MATHICGB_ASSERT(newGenerator < size()); divisors.clear(); divisors.reserve(maxDivisors + 1); auto sigNew = signature(newGenerator); for (size_t i = 0; i < newGenerator; ++i) { auto sigi = signature(i); if (monoid().component(sigi) != monoid().component(sigNew)) continue; if (!monoid().divides(sigi, sigNew)) continue; for (size_t j = 0; j <= divisors.size(); ++j) { if (j == divisors.size()) { divisors.push_back(i); break; } if (ratioCompare(i, divisors[j]) == GT) { divisors.insert(divisors.begin() + j, i); break; } } if (divisors.size() > maxDivisors) divisors.pop_back(); MATHICGB_ASSERT(divisors.size() <= maxDivisors); } MATHICGB_ASSERT(divisors.size() <= maxDivisors); }
void SigPolyBasis::displayFancy (std::ostream& out, const Processor& processor) const { mathic::ColumnPrinter pr; auto& indexOut = pr.addColumn(false) << "Index\n"; auto& sigOut = pr.addColumn(false) << "sig\n"; auto& polyOut = pr.addColumn() << "poly\n"; pr.repeatToEndOfLine('-'); auto sig = monoid().alloc(); for (size_t i = 0; i < mBasis.size(); i++) { indexOut << i << '\n'; monoid().copy(*mSignatures[i], *sig); processor.postprocess(sig); if (monoid().isIdentity(*sig)) MathicIO<>().writeComponent(monoid(), *sig, out); else MathicIO<>().writeMonomial(monoid(), true, *sig, out); sigOut << '\n'; MathicIO<>().writePoly(mBasis.poly(i), false, polyOut); polyOut << '\n'; } out << pr; }
// processMonomialProduct // m is a monomial, component is ignored (it determined the possible n's // being used here) // n is a monomial at level 'mThisLevel-1' // compute their product, and return the column index of this product // or -1, if the monomial is not needed. // additionally: the product monomial is inserted into the hash table // and column array (if it is not already there). // caveats: this function is only to be used during construction // of the coeff matrices. It uses mThisLevel. // // If the ring has skew commuting variables, then result_sign_if_skew is set to // 0, 1, or -1. ComponentIndex F4Res::processMonomialProduct(res_const_packed_monomial m, res_const_packed_monomial n, int& result_sign_if_skew) { result_sign_if_skew = 1; auto x = monoid().get_component(n); auto& p = mFrame.level(mThisLevel - 2)[x]; if (p.mBegin == p.mEnd) return -1; int* thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size()); thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as monoid().unchecked_mult(m, n, thisMonom); monoid().set_component(x, thisMonom); if (ring().isSkewCommutative()) { result_sign_if_skew = monoid().skew_mult_sign(ring().skewInfo(), m, n); if (result_sign_if_skew == 0) { mMonomSpace2.popLastAlloc(thisMonom-1); // we did not need this monomial! return -1; } } return processCurrentMonomial(thisMonom); }
void postprocess(MonoRef mono) const { if (needToReverseComponents()) reverseComponent(mono); if (hasSchreyerMultipliers()) { MATHICGB_ASSERT(monoid().divides(moduleAdjustment(mono), mono)); monoid().divideInPlace(moduleAdjustment(mono), mono); } }
SchreyerFrame::PreElement* SchreyerFrame::createQuotientElement(res_packed_monomial m1, res_packed_monomial m) { PreElement* vp = mPreElements.allocate(); vp->vp = mVarpowers.reserve(mMaxVPSize); monoid().quotient_as_vp(m1, m, vp->vp); vp->degree = monoid().degree_of_vp(vp->vp); int len = static_cast<int>(res_varpower_monomials::length(vp->vp)); mVarpowers.intern(len); return vp; }
void SigPolyBasis::display(std::ostream& out) const { for (size_t i = 0; i < mBasis.size(); i++) { out << i << " "; // This is needed for compatibility with old tests. // todo: change the tests so this isn't necessary. if (monoid().isIdentity(*mSignatures[i])) MathicIO<>().writeComponent(monoid(), *mSignatures[i], out); else MathicIO<>().writeMonomial(monoid(), true, *mSignatures[i], out); out << " "; MathicIO<>().writePoly(mBasis.poly(i), false, out); out << '\n'; } }
SigPolyBasis::~SigPolyBasis() { MATHICGB_ASSERT(mBasis.size() == mSignatures.size()); MATHICGB_ASSERT(mBasis.size() == mSigLeadRatio.size()); for (size_t i = 0; i < mBasis.size(); i++) { if (!mSignatures[i].isNull()) monoid().freeRaw(*mSignatures[i]); if (!mSigLeadRatio[i].isNull()) monoid().freeRaw(*mSigLeadRatio[i]); } for (size_t i = 0; i < mSignatureLookup.size(); ++i) delete mSignatureLookup[i]; mBasis.ring().freeMonomial(mTmp); }
ConstMonoRef moduleAdjustment(ConstMonoRef mono) const { MATHICGB_ASSERT(hasSchreyerMultipliers()); const auto component = monoid().component(mono); MATHICGB_ASSERT(component < componentCount()); MATHICGB_ASSERT(mSchreyerMultipliers.size() == componentCount()); return *mSchreyerMultipliers[component]; }
void SchreyerFrame::setSchreyerOrder(int lev) { auto& myframe = level(lev); auto& myorder = schreyerOrder(lev); myorder.mTieBreaker.resize(myframe.size()); if (lev == 0) { for (long i=0; i<myorder.mTieBreaker.size(); i++) myorder.mTieBreaker[i] = i; return; } auto& prevframe = level(lev-1); auto& prevorder = schreyerOrder(lev-1); long* tiebreakers = new long[myframe.size()]; for (long i=0; i<myframe.size(); i++) { long comp = monoid().get_component(myframe[i].mMonom); tiebreakers[i] = i + myframe.size() * prevorder.mTieBreaker[comp]; } std::stable_sort(tiebreakers, tiebreakers + myframe.size()); for (long i=0; i<myframe.size(); i++) { myorder.mTieBreaker[tiebreakers[i] % myframe.size()] = i; } delete [] tiebreakers; }
size_t SigPolyBasis::ratioRank(ConstMonoRef ratio) const { MATHICGB_ASSERT(mUseRatioRank); const size_t index = size(); if (index == 0) return 0; // any value will do as there is nothing to compare to auto& sigLeadRatioNonConst = const_cast<std::vector<MonoPtr>&>(mSigLeadRatio); sigLeadRatioNonConst.push_back(ratio.castAwayConst()); auto pos = mRatioSorted.lower_bound(index); sigLeadRatioNonConst.pop_back(); if (pos == mRatioSorted.end()) { MATHICGB_ASSERT (ratioRank(*mRatioSorted.rbegin()) < std::numeric_limits<Rank>::max()); return std::numeric_limits<Rank>::max(); } else { if (monoid().equal(ratio, sigLeadRatio(*pos))) return ratioRank(*pos); MATHICGB_ASSERT(ratioRank(*pos) > 0); #ifdef MATHICGB_DEBUG if (pos != mRatioSorted.begin()) { auto prev = pos; --prev; MATHICGB_ASSERT(ratioRank(*pos) - 1 > ratioRank(*prev)); } #endif return ratioRank(*pos) - 1; } }
RegExp::RegExp(char* expression) { this->operations.reserve(64); this->transducers.reserve(64); this->expression = expression; for (ui i = 0; i < strlen(expression); i++) { switch(expression[i]) { case '<': { char* input = read_word(i); char* output = read_word(++i); i+=2; ui weight = read_number(i); Monoid monoid(input, output, weight); this->transducers.push_back(new Transducer(monoid)); } break; case '|': this->operations.push_back(UNION); break; case '*': this->operations.push_back(STAR); break; case '.': this->operations.push_back(CONCAT); break; } } }
// new_m is a monomial that we have just created. There are several // things that can happen: // (1) new_m is already in the hash table (as is). // i.e. we have already processed this monomial. // in this case new_m[-1] is the index of the divisor for this monomial // (possibly -1). // (2) new_m is a newly seen monomial in this degree. // insert it into the hash table as a seen monomial // we set the divisor for new_m: either -1 or some index // If there is no divisor, return -1. // If there is: create a row, and push onto the mReducers list. // (2A) ComponentIndex F4Res::processCurrentMonomial(res_packed_monomial thisMonom) { res_packed_monomial new_m; // a pointer to a monomial we are visiting if (mHashTable.find_or_insert(thisMonom, new_m)) { // we did not need the monomial. So pop it. mMonomSpace2.popLastAlloc(thisMonom-1); return static_cast<ComponentIndex>( new_m[-1]); // monom exists, don't save monomial space } // At this point thisMonom has been inserted. We keep it. thisMonom = mMonomSpace2.allocate(1 + monoid().max_monomial_size()); thisMonom++; // so thisMonom[-1] exists, but is not part of the monomial, as far as bool has_divisor = findDivisor(new_m, thisMonom); if (!has_divisor) { mMonomSpace2.popLastAlloc(thisMonom-1); new_m[-1] = -1; // no divisor exists return -1; } ComponentIndex thiscol = static_cast<ComponentIndex>(mColumns.size()); new_m[-1] = thiscol; // this is a HACK: where we keep the divisor mColumns.push_back(new_m); Row row; row.mLeadTerm = thisMonom; mReducers.push_back(row); return thiscol; }
void F4Res::debugOutputReducers() { auto end = mReducers.cend(); for (auto i=mReducers.cbegin(); i != end; ++i) { monoid().showAlpha((*i).mLeadTerm); std::cout << std::endl; } }
void ResPolyRing::memUsage(const poly& f, long& nterms, long& bytes_used, long& bytes_alloc) const { long sz = 0; sz = f.len * sizeof(FieldElement); sz += f.len * monoid().max_monomial_size() * sizeof(monomial_word); nterms += f.len; bytes_used += sz; bytes_alloc += sz; }
void F4Res::debugOutputColumns() { auto end = mColumns.cend(); for (auto i=mColumns.cbegin(); i != end; ++i) { monoid().showAlpha((*i)); std::cout << std::endl; } }
MonomialCounter::MonomialCounter(const ResMonoid& M) : mIgnoreMonomials(new ResMonomialsIgnoringComponent(M)), mAllMonomials(mIgnoreMonomials), mNumAllMonomials(0), mNextMonom(nullptr), mMonoid(M) { // start out mNextMonom mNextMonom = mMonomSpace.reserve(monoid().max_monomial_size()); }
size_t SigPolyBasis::regularReducerSlow( ConstMonoRef sig, ConstMonoRef term ) const { monomial m = ring().allocMonomial(); const size_t stop = size(); for (size_t be = 0; be < stop; ++be) { if (!monoid().divides(leadMono(be), term)) continue; monoid().divide(leadMono(be), term, m); monoid().multiplyInPlace(signature(be), m); if (monoid().lessThan(m, sig)) { ring().freeMonomial(m); return be; } } ring().freeMonomial(m); return static_cast<size_t>(-1); }
void F4Res::resetMatrix(int lev, int degree) { mThisLevel = lev; mThisDegree = degree; mNextReducerToProcess = 0; // mNextMonom[-1] is the reducer corresponding to this monomial mNextMonom = mMonomSpace.reserve(1+monoid().max_monomial_size()); mNextMonom++; }
void F4Res::loadRow(Row& r) { // std::cout << "loadRow: " << std::endl; r.mCoeffs = resGausser().allocateCoefficientVector(); // monoid().showAlpha(r.mLeadTerm); // std::cout << std::endl; int skew_sign; // will be set to 1, unless ring().isSkewCommutative() is // true, then it can be -1,0,1. // however, if it is 0, then "val" below will also be -1. long comp = monoid().get_component(r.mLeadTerm); auto& thiselement = mFrame.level(mThisLevel - 1)[comp]; // std::cout << " comp=" << comp << " mDegree=" << thiselement.mDegree << " // mThisDegree=" << mThisDegree << std::endl; if (thiselement.mDegree == mThisDegree) { // We only need to add in the current monomial // fprintf(stdout, "USING degree 0 monomial\n"); ComponentIndex val = processMonomialProduct(r.mLeadTerm, thiselement.mMonom, skew_sign); if (val < 0) fprintf(stderr, "ERROR: expected monomial to live\n"); r.mComponents.push_back(val); if (skew_sign > 0) mRing.resGausser().pushBackOne(r.mCoeffs); else { // Only happens if we are in a skew commuting ring. ring().resGausser().pushBackMinusOne(r.mCoeffs); } return; } auto& p = thiselement.mSyzygy; auto end = poly_iter(mRing, p, 1); auto i = poly_iter(mRing, p); for (; i != end; ++i) { ComponentIndex val = processMonomialProduct(r.mLeadTerm, i.monomial(), skew_sign); // std::cout << " monom: " << val << " skewsign=" << skew_sign << " // mColumns.size=" << mColumns.size() << std::endl; if (val < 0) continue; r.mComponents.push_back(val); if (skew_sign > 0) mRing.resGausser().pushBackElement( r.mCoeffs, p.coeffs, i.coefficient_index()); else { // Only happens if we are in a skew commuting ring. mRing.resGausser().pushBackNegatedElement( r.mCoeffs, p.coeffs, i.coefficient_index()); } } }
bool SigPolyBasis::isSingularTopReducibleSlow( const Poly& poly, ConstMonoRef sig ) const { if (poly.isZero()) return false; monomial multiplier = ring().allocMonomial(); const size_t genCount = size(); const auto polyLead = poly.leadMono(); for (size_t i = 0; i < genCount; ++i) { if (!monoid().divides(leadMono(i), polyLead)) continue; monoid().divide(leadMono(i), polyLead, multiplier); if (monoid().compare(sig, multiplier, signature(i)) == EQ) return true; } ring().freeMonomial(multiplier); return false; }
// processMonomialProduct // m is a monomial, component is ignored (it determined the possible n's being used here) // n is a monomial at level 'mThisLevel-1' // compute their product, and return the column index of this product // or -1, if the monomial is not needed. // additionally: the product monomial is inserted into the hash table // and column array (if it is not already there). // caveats: this function is only to be used during construction // of the coeff matrices. It uses mThisLevel. // // If the ring has skew commuting variables, then result_sign_if_skew is set to 0, 1, or -1. ComponentIndex F4Res::processMonomialProduct(packed_monomial m, packed_monomial n, int& result_sign_if_skew) { result_sign_if_skew = 1; auto x = monoid().get_component(n); auto& p = mFrame.level(mThisLevel-2)[x]; if (p.mBegin == p.mEnd) return -1; monoid().unchecked_mult(m,n,mNextMonom); // the component is wrong, after this operation, as it adds components // So fix that: monoid().set_component(x, mNextMonom); if (ring().isSkewCommutative()) { result_sign_if_skew = monoid().skew_mult_sign(ring().skewInfo(), m, n); if (result_sign_if_skew == 0) return -1; } return processCurrentMonomial(); }
/// findDivisor // m: monomial at level mThisLevel-1 // result: monomial at level mThisLevel, IF true is returned // returns true if 'm' == inG(result), for some (unique) 'result'. bool F4Res::findDivisor(packed_monomial m, packed_monomial result) { // get component of m // find the range of monomials to check // for each of these, check divisibility in turn // if one works, then return true, and set result. long comp = monoid().get_component(m); // component is an index into level mLevel-2 auto& elem = mFrame.level(mThisLevel-2)[comp]; auto& lev = mFrame.level(mThisLevel-1); for (auto j=elem.mBegin; j<elem.mEnd; ++j) { // Check divisibility of m by this element packed_monomial pj = lev[j].mMonom; if (monoid().divide(m, pj, result)) // this sets the component to be 0 { monoid().set_component(j, result); // this sets component correctly return true; } } return false; }
void SchreyerFrame::insertBasic(int lev, res_packed_monomial monom, int degree) { // if lev >= 2, then level(lev-1)[comp].(mBegin,mEnd) is set separately. auto& myframe = level(lev); long idx = myframe.size(); myframe.emplace_back(FrameElement(monom,degree)); auto& myelem = myframe[idx]; // The rest of this code simply sets the total monomial for the Schreyer order // and should be moved out of here. (MES 3 Feb 2016) auto& myorder = schreyerOrder(lev); auto myTotalMonom = monomialBlock().allocate(monoid().max_monomial_size()); if (lev > 0) { auto& prevlevel = level(lev-1); auto& prevorder = schreyerOrder(lev-1); long comp = monoid().get_component(myelem.mMonom); monoid().unchecked_mult(myelem.mMonom, prevorder.mTotalMonom[comp], myTotalMonom); monoid().set_component(monoid().get_component(prevorder.mTotalMonom[comp]), myTotalMonom); } else { monoid().copy(myelem.mMonom, myTotalMonom); } myorder.mTotalMonom.push_back(myTotalMonom); }
/// Replaces basis element at index with the given new polynomial. The lead /// term of the new polynomial must be the same as the previous one. /// This is useful for auto-tail-reduction. void replaceSameLeadTerm(size_t index, std::unique_ptr<Poly> newValue) { MATHICGB_ASSERT(index < size()); MATHICGB_ASSERT(!retired(index)); MATHICGB_ASSERT(newValue.get() != nullptr); MATHICGB_ASSERT(!newValue->isZero()); MATHICGB_ASSERT (monoid().equal(leadMono(index), newValue->leadMono())); mMonoLookup->remove(leadMono(index)); delete mEntries[index].poly; mEntries[index].poly = newValue.release(); mMonoLookup->insert(leadMono(index), index); MATHICGB_ASSERT(mEntries[index].poly != nullptr); }
void MonomialCounter::accountForMonomial(res_const_packed_monomial mon) { // First copy monomial // Then call find_or_insert // If not there, increment number of monomials // If there: intern monomial monoid().copy(mon, mNextMonom); res_packed_monomial not_used; if (mAllMonomials.find_or_insert(mNextMonom, not_used)) { // true, means that it was already there // nothing needs to be done } else { // false: new monomial mNumAllMonomials++; mMonomSpace.intern(monoid().monomial_size(mNextMonom)); mNextMonom = mMonomSpace.reserve(monoid().max_monomial_size()); } }
void SchreyerFrame::insertLevelZero(res_packed_monomial monom, int degree, int maxdeglevel0) { // return insertBasic(0, monom, degree); auto& myframe = level(0); long idx = myframe.size(); myframe.emplace_back(FrameElement(monom,degree)); auto& myelem = myframe[idx]; auto& myorder = schreyerOrder(0); auto myTotalMonom = monomialBlock().allocate(monoid().max_monomial_size()); // Create the total monomial. It is monom * (firstvar)^(maxdeglevel0-degree) #if 0 long comp; ntuple_monomial exp = new int[monoid().n_vars()]; to_exponent_vector(monom, exp, comp); exp[0] += (maxdeglevel0 - XXXX); from_exponent_vector(exp, comp, monom); // XXXX not correct, I think. #endif monoid().copy(myelem.mMonom, myTotalMonom); myorder.mTotalMonom.push_back(myTotalMonom); }
// new_m is a monomial that we have just created. There are several // things that can happen: // (1) new_m is already in the hash table (as is). // i.e. we have already processed this monomial. // in this case new_m[-1] is the index of the divisor for this monomial // (possibly -1). // (2) new_m is a newly seen monomial in this degree. // insert it into the hash table as a seen monomial // we set the divisor for new_m: either -1 or some index // If there is no divisor, return -1. // If there is: create a row, and push onto the mReducers list. // (2A) ComponentIndex F4Res::processCurrentMonomial() { res_packed_monomial new_m; // a pointer to a monomial we are visiting if (mHashTable.find_or_insert(mNextMonom, new_m)) return static_cast<ComponentIndex>( new_m[-1]); // monom exists, don't save monomial space // intern the monomial just inserted into the hash table mMonomSpace.intern(1 + monoid().monomial_size(mNextMonom)); // leave room for the next monomial. This might be set below. mNextMonom = mMonomSpace.reserve(1 + monoid().max_monomial_size()); mNextMonom++; bool has_divisor = findDivisor(new_m, mNextMonom); if (!has_divisor) { new_m[-1] = -1; // no divisor exists return -1; } mMonomSpace.intern(1 + monoid().monomial_size(mNextMonom)); ComponentIndex thiscol = static_cast<ComponentIndex>(mColumns.size()); new_m[-1] = thiscol; // this is a HACK: where we keep the divisor mColumns.push_back(new_m); Row row; row.mLeadTerm = mNextMonom; mReducers.push_back(row); // Now we increment mNextMonom, for the next time mNextMonom = mMonomSpace.reserve(1 + monoid().max_monomial_size()); mNextMonom++; return thiscol; }
long SchreyerFrame::computeIdealQuotient(int lev, long begin, long elem) { /// std::cout << "computeIdealQuotient(" << lev << "," << begin << "," << elem << ")" << std::endl; // Returns the number of elements added res_packed_monomial m = monomial(lev, elem); std::vector<PreElement*> elements; if (ring().isSkewCommutative()) { auto skewvars = new int[ring().monoid().n_vars()]; int a = ring().monoid().skew_vars(ring().skewInfo(), m, skewvars); // std::cout << "adding " << a << " syz from skew" << std::endl; for (int i=0; i<a; ++i) { PreElement* vp = mPreElements.allocate(); vp->vp = mVarpowers.reserve(mMaxVPSize); monoid().variable_as_vp(skewvars[i], vp->vp); vp->degree = monoid().degree_of_vp(vp->vp); int len = static_cast<int>(res_varpower_monomials::length(vp->vp)); mVarpowers.intern(len); elements.push_back(vp); } delete [] skewvars; } for (long i=begin; i<elem; i++) elements.push_back(createQuotientElement(monomial(lev,i), m)); typedef ResF4MonomialLookupTableT<int32_t> MonomialLookupTable; MonomialLookupTable montab(monoid().n_vars()); #if 0 std::cout << " #pre elements = " << elements.size() << std::endl; for (auto i=elements.begin(); i != elements.end(); ++i) { varpower_monomials::elem_text_out(stdout, (*i)->vp); fprintf(stdout, "\n"); } #endif PreElementSorter C; std::stable_sort(elements.begin(), elements.end(), C); long n_elems = 0; for (auto i = elements.begin(); i != elements.end(); ++i) { int32_t not_used; bool inideal = montab.find_one_divisor_vp(0, (*i)->vp, not_used); if (inideal) continue; // Now we create a res_packed_monomial, and insert it into 'lev+1' montab.insert_minimal_vp(0, (*i)->vp, 0); res_packed_monomial monom = monomialBlock().allocate(monoid().max_monomial_size()); monoid().from_varpower_monomial((*i)->vp, elem, monom); // Now insert it into the frame insertBasic(currentLevel(), monom, (*i)->degree + degree(currentLevel()-1, monoid().get_component(monom))); n_elems++; } //std::cout << " returns " << n_elems << std::endl; return n_elems; }