void CyclRatFunct::showCoprimeCRF(){ // shows *this also with coprime numerator and denominator // makes only sense if only x[0] appears in the numerator (not checked) if(!verbose_INT) return; cout << "--------------------------------------------" << endl << endl; cout << "Given form" << endl << endl; showCRF(); cout << endl; SparsePolyRing R=owner(num); SparsePolyRing P=NewPolyRing_DMPI(RingQQ(),symbols("t")); vector<RingElem> Im(NumIndets(R),zero(P)); Im[0]=indets(P)[0]; RingHom phi=PolyAlgebraHom(R,P,Im); RingElem f(phi(num)); RingElem g(denom2poly(P,denom)); RingElem h=CoCoA::gcd(f,g); f/=h; g/=h; cout << "Coprime numerator (for denom with remaining factor 1)" << endl <<endl; factorization<RingElem> gf=factor(g); cout << f/gf.myRemainingFactor() << endl << endl << "Factorization of denominator" << endl << endl; size_t nf=gf.myFactors().size(); for(size_t i=0;i<nf;++i) cout << gf.myFactors()[i] << " mult " << gf.myMultiplicities()[i] << endl; cout << "--------------------------------------------" << endl; }
const PolyRing& RingQQt(const MachineInt& NumIndets) { static vector<PolyRing*> QQtTable; if (IsNegative(NumIndets) || IsZero(NumIndets)) CoCoA_ERROR(ERR::NotPositive, "RingQQt"); const long n = AsSignedLong(NumIndets); if (n >= len(QQtTable)) QQtTable.resize(n+1); // will fill with NULL ptrs if (QQtTable[n] == 0/*NULL ptr*/) { vector<symbol> IndetNames; if (n == 1) IndetNames = symbols("t"); else IndetNames = SymbolRange("t",1,n); QQtTable[n] = new SparsePolyRing(NewPolyRing(RingQQ(), IndetNames)); // wasteful copy!! RegisterDtorForGlobal(QQtTable[n], &RingQQtDtor); } return *QQtTable[n]; }
std::vector<RingElem> BM_QQ(const SparsePolyRing& P, const ConstMatrixView& pts_in) { const long NumPts = NumRows(pts_in); const long dim = NumCols(pts_in); matrix pts = NewDenseMat(RingQQ(), NumPts, dim); for (long i=0; i < NumPts; ++i) for (long j=0; j < dim; ++j) { BigRat q; if (!IsRational(q, pts_in(i,j))) throw 999; SetEntry(pts,i,j, q); } // Ensure input pts have integer coords by using // scale factors for each indet. vector<BigInt> ScaleFactor(dim, BigInt(1)); for (long j=0; j < dim; ++j) for (long i=0; i < NumPts; ++i) ScaleFactor[j] = lcm(ScaleFactor[j], ConvertTo<BigInt>(den(pts(i,j)))); mpz_t **points = (mpz_t**)malloc(NumPts*sizeof(mpz_t*)); for (long i=0; i < NumPts; ++i) { points[i] = (mpz_t*)malloc(dim*sizeof(mpz_t)); for (long j=0; j < dim; ++j) mpz_init(points[i][j]); for (long j=0; j < dim; ++j) { mpz_set(points[i][j], mpzref(ConvertTo<BigInt>(ScaleFactor[j]*pts(i,j)))); } } BMGB char0; // these will be "filled in" by BM_affine below BM modp; // pp_cmp_PPM = &PPM(P); // not threadsafe! BM_affine(&char0, &modp, dim, NumPts, points, pp_cmp); // THIS CALL DOES THE REAL WORK!!! pp_cmp_PPM = NULL; for (long i=NumPts-1; i >=0 ; --i) { for (long j=0; j < dim; ++j) mpz_clear(points[i][j]); free(points[i]); } free(points); if (modp == NULL) { if (char0 != NULL) BMGB_dtor(char0); CoCoA_ERROR("Something went wrong", "BM_QQ"); } // Now extract the answer... const int GBsize = char0->GBsize; std::vector<RingElem> GB(GBsize); const long NumVars = dim; vector<long> expv(NumVars); // buffer for creating monomials for (int i=0; i < GBsize; ++i) { BigInt denom(1); // scale factor needed to make GB elem monic. for (int var = 0; var < NumVars; ++var) { expv[var] = modp->pp[modp->GB[i]][var]; denom *= power(ScaleFactor[var], expv[var]); } RingElem GBelem = monomial(P, 1, expv); for (int j=0; j < NumPts; ++j) { if (mpq_sgn(char0->GB[i][j])==0) continue; BigRat c(char0->GB[i][j]); for (int var = 0; var < NumVars; ++var) { expv[var] = modp->pp[modp->sep[j]][var]; c *= power(ScaleFactor[var], expv[var]); } GBelem += monomial(P, c/denom, expv); } GB[i] = GBelem; } BMGB_dtor(char0); BM_dtor(modp); return GB; // ignoring separators for the moment }