/** * ResidueSolvableWordPolynomial left and right multiplication. Product with exponent vector. * * @param e exponent. * @param f exponent. * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable multiplication. */ @Override public ResidueSolvableWordPolynomial<C> multiply(ExpVector e, ExpVector f) { if (e == null || e.isZERO()) { return this; } if (f == null || f.isZERO()) { return this; } WordResidue<C> b = ring.getONECoefficient(); return multiply(b, e, b, f); }
/** * ResidueSolvableWordPolynomial multiplication. Left product with exponent vector. * * @param e exponent. * @return x<sup>e</sup> * this, where * denotes solvable multiplication. */ @Override public ResidueSolvableWordPolynomial<C> multiplyLeft(ExpVector e) { if (e == null || e.isZERO()) { return this; } ResidueSolvableWordPolynomial<C> Cp = ring.valueOf(e); return Cp.multiply(this); }
/** * ResidueSolvableWordPolynomial multiplication. Commutative product with exponent vector. * * @param B solvable polynomial. * @param f exponent vector. * @return B*f, where * is commutative multiplication. */ protected ResidueSolvableWordPolynomial<C> shift( ResidueSolvableWordPolynomial<C> B, ExpVector f) { ResidueSolvableWordPolynomial<C> C = ring.getZERO().copy(); if (B == null || B.isZERO()) { return C; } if (f == null || f.isZERO()) { return B; } Map<ExpVector, WordResidue<C>> Cm = C.val; Map<ExpVector, WordResidue<C>> Bm = B.val; for (Map.Entry<ExpVector, WordResidue<C>> y : Bm.entrySet()) { ExpVector e = y.getKey(); WordResidue<C> a = y.getValue(); ExpVector d = e.sum(f); if (!a.isZERO()) { Cm.put(d, a); } } return C; }
// cannot @Override, @NoOverride public ResidueSolvableWordPolynomial<C> multiply(ResidueSolvableWordPolynomial<C> Bp) { if (Bp == null || Bp.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } assert (ring.nvar == Bp.ring.nvar); if (debug) { logger.debug("ring = " + ring); } ExpVector Z = ring.evzero; ResidueSolvableWordPolynomial<C> Dp = ring.getZERO().copy(); ResidueSolvableWordPolynomial<C> zero = ring.getZERO().copy(); WordResidue<C> one = ring.getONECoefficient(); Map<ExpVector, WordResidue<C>> A = val; Map<ExpVector, WordResidue<C>> B = Bp.val; Set<Map.Entry<ExpVector, WordResidue<C>>> Bk = B.entrySet(); for (Map.Entry<ExpVector, WordResidue<C>> y : A.entrySet()) { WordResidue<C> a = y.getValue(); ExpVector e = y.getKey(); if (debug) logger.info("e = " + e + ", a = " + a); for (Map.Entry<ExpVector, WordResidue<C>> x : Bk) { WordResidue<C> b = x.getValue(); ExpVector f = x.getKey(); if (debug) logger.info("f = " + f + ", b = " + b); int[] fp = f.dependencyOnVariables(); int fl1 = 0; if (fp.length > 0) { fl1 = fp[fp.length - 1]; } int fl1s = ring.nvar + 1 - fl1; // polynomial/residue coefficient multiplication ResidueSolvableWordPolynomial<C> Cps = ring.getZERO().copy(); if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric Cps = new ResidueSolvableWordPolynomial<C>(ring, b, e); if (debug) logger.info("symmetric coeff: b = " + b + ", e = " + e); } else { // unsymmetric if (debug) logger.info("unsymmetric coeff: b = " + b + ", e = " + e); // recursive polynomial coefficient multiplication : e * b.val RecSolvableWordPolynomial<C> rsp1 = new RecSolvableWordPolynomial<C>(ring.polCoeff, e); RecSolvableWordPolynomial<C> rsp2 = new RecSolvableWordPolynomial<C>(ring.polCoeff, b.val); RecSolvableWordPolynomial<C> rsp3 = rsp1.multiply(rsp2); Cps = ring.fromPolyCoefficients(rsp3); } if (debug) { logger.info("coeff-poly: Cps = " + Cps); } // polynomial multiplication ResidueSolvableWordPolynomial<C> Dps = ring.getZERO().copy(); ResidueSolvableWordPolynomial<C> Ds = null; ResidueSolvableWordPolynomial<C> D1, D2; if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric if (debug) logger.info("symmetric poly: b = " + b + ", e = " + e); ExpVector g = e.sum(f); if (Cps.isConstant()) { Ds = new ResidueSolvableWordPolynomial<C>( ring, Cps.leadingBaseCoefficient(), g); // symmetric! } else { Ds = shift(Cps, f); // symmetric } } else { // eventually unsymmetric if (debug) logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f); for (Map.Entry<ExpVector, WordResidue<C>> z : Cps.val.entrySet()) { // split g = g1 * g2, f = f1 * f2 WordResidue<C> c = z.getValue(); ExpVector g = z.getKey(); if (debug) logger.info("g = " + g + ", c = " + c); int[] gp = g.dependencyOnVariables(); int gl1 = ring.nvar + 1; if (gp.length > 0) { gl1 = gp[0]; } int gl1s = ring.nvar + 1 - gl1; if (gl1s <= fl1s) { // symmetric ExpVector h = g.sum(f); if (debug) logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h); Ds = (ResidueSolvableWordPolynomial<C>) zero.sum(one, h); // symmetric! } else { ExpVector g1 = g.subst(gl1, 0); ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1 ExpVector g4; ExpVector f1 = f.subst(fl1, 0); ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); if (debug) logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); if (debug) logger.info("poly, g2 = " + g2 + ", f2 = " + f2); TableRelation<WordResidue<C>> rel = ring.table.lookup(g2, f2); if (debug) logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); Ds = new ResidueSolvableWordPolynomial<C>(ring, rel.p); // ring.copy(rel.p); if (rel.f != null) { D2 = new ResidueSolvableWordPolynomial<C>(ring, one, rel.f); Ds = Ds.multiply(D2); if (rel.e == null) { g4 = g2; } else { g4 = g2.subtract(rel.e); } ring.table.update(g4, f2, Ds); } if (rel.e != null) { D1 = new ResidueSolvableWordPolynomial<C>(ring, one, rel.e); Ds = D1.multiply(Ds); ring.table.update(g2, f2, Ds); } if (!f1.isZERO()) { D2 = new ResidueSolvableWordPolynomial<C>(ring, one, f1); Ds = Ds.multiply(D2); // ring.table.update(?,f1,Ds) } if (!g1.isZERO()) { D1 = new ResidueSolvableWordPolynomial<C>(ring, one, g1); Ds = D1.multiply(Ds); // ring.table.update(e1,?,Ds) } } Ds = Ds.multiplyLeft(c); // assume c commutes with Cs Dps = (ResidueSolvableWordPolynomial<C>) Dps.sum(Ds); } // end Dps loop Ds = Dps; } Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric if (debug) logger.debug("Ds = " + Ds); Dp = (ResidueSolvableWordPolynomial<C>) Dp.sum(Ds); } // end B loop } // end A loop return Dp; }