001/*
002 * $Id: PseudoReductionPar.java 4973 2014-10-22 21:50:34Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.Map;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.gb.ReductionAbstract;
015import edu.jas.poly.PolyUtil;
016import edu.jas.poly.ExpVector;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.structure.RingElem;
019
020
021/**
022 * Polynomial pseudo reduction sequential use algorithm. Coefficients of
023 * polynomials must not be from a field, i.e. the fraction free reduction is
024 * implemented. Implements normalform.
025 * @param <C> coefficient type
026 * @author Heinz Kredel
027 */
028
029public class PseudoReductionPar<C extends RingElem<C>> extends ReductionAbstract<C> implements
030                PseudoReduction<C> {
031
032
033    private static final Logger logger = Logger.getLogger(PseudoReductionPar.class);
034
035
036    private final boolean debug = logger.isDebugEnabled();
037
038
039    /**
040     * Constructor.
041     */
042    public PseudoReductionPar() {
043    }
044
045
046    /**
047     * Normalform.
048     * @param Ap polynomial.
049     * @param Pp polynomial list.
050     * @return nf(Ap) with respect to Pp.
051     */
052    @SuppressWarnings("unchecked")
053    public GenPolynomial<C> normalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
054        if (Pp == null || Pp.isEmpty()) {
055            return Ap;
056        }
057        if (Ap == null || Ap.isZERO()) {
058            return Ap;
059        }
060        GenPolynomial<C>[] P = new GenPolynomial[0];
061        List<GenPolynomial<C>> Ppp;
062        synchronized (Pp) {
063            Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic
064        }
065        P = Ppp.toArray(P);
066        int ll = Ppp.size();
067        GenPolynomial<C> Rz = Ap.ring.getZERO();
068        GenPolynomial<C> R = Rz.copy();
069
070        GenPolynomial<C> S = Ap.copy();
071        while (S.length() > 0) {
072            if (Pp.size() != ll) {
073                //System.out.println("Pp.size() = " + Pp.size() + ", ll = " + ll);
074                //long t = System.currentTimeMillis();
075                synchronized (Pp) {
076                    Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic
077                }
078                P = Ppp.toArray(P);
079                ll = Ppp.size();
080                //ll = P.length; // wrong
081                //t = System.currentTimeMillis()-t;
082                //logger.info("Pp.toArray(): size() = " + l + ", ll = " + ll);
083                S = Ap.copy(); // S.add(R)? // restart reduction ?
084                R = Rz.copy();
085            }
086            boolean mt = false;
087            Map.Entry<ExpVector, C> m = S.leadingMonomial();
088            ExpVector e = m.getKey();
089            C a = m.getValue();
090            ExpVector f = null;
091            int i;
092            for (i = 0; i < ll; i++) {
093                f = P[i].leadingExpVector();
094                mt = e.multipleOf(f);
095                if (mt)
096                    break;
097            }
098            if (!mt) {
099                //System.out.println("m = " + m);
100                //logger.debug("irred");
101                //R = R.sum(a, e);
102                //S = S.subtract(a, e);
103                R.doPutToMap(e, a);
104                S.doRemoveFromMap(e, a);
105                //System.out.println(" S = " + S);
106            } else {
107                e = e.subtract(f);
108                //logger.info("red div = " + e);
109                C c = P[i].leadingBaseCoefficient();
110                if (a.remainder(c).isZERO()) { //c.isUnit() ) {
111                    a = a.divide(c);
112                    S = S.subtractMultiple(a, e, P[i]);
113                } else {
114                    R = R.multiply(c);
115                    //S = S.multiply(c);
116                    S = S.scaleSubtractMultiple(c, a, e, P[i]);
117                }
118                //Q = p[i].multiply(a, e);
119                //S = S.subtract(Q);
120            }
121        }
122        return R;
123    }
124
125
126    /**
127     * Normalform.
128     * @param Pp polynomial list.
129     * @param Ap polynomial.
130     * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor
131     *         for Ap.
132     */
133    @SuppressWarnings("unchecked")
134    public PseudoReductionEntry<C> normalformFactor(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) {
135        if (Ap == null) {
136            return null;
137        }
138        C mfac = Ap.ring.getONECoefficient();
139        PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac);
140        if (Pp == null || Pp.isEmpty()) {
141            return pf;
142        }
143        if (Ap.isZERO()) {
144            return pf;
145        }
146        GenPolynomial<C>[] P = new GenPolynomial[0];
147        List<GenPolynomial<C>> Ppp;
148        synchronized (Pp) {
149            Ppp = new ArrayList<GenPolynomial<C>>(Pp); // sic
150        }
151        P = Ppp.toArray(P);
152        int l = Ppp.size();
153        boolean mt = false;
154        GenPolynomial<C> Rz = Ap.ring.getZERO();
155        GenPolynomial<C> R = Rz.copy();
156        //GenPolynomial<C> T = null;
157        //GenPolynomial<C> Q = null;
158        GenPolynomial<C> S = Ap.copy();
159        while (S.length() > 0) {
160            if (Pp.size() != l) {
161                //long t = System.currentTimeMillis();
162                synchronized (Pp) {
163                    Ppp = new ArrayList<GenPolynomial<C>>(Pp);
164                }
165                P = Ppp.toArray(P);
166                l = Ppp.size();
167                //t = System.currentTimeMillis()-t;
168                //logger.info("Pp.toArray() = " + t + " ms, size() = " + l);
169                S = Ap.copy(); // S.add(R)? // restart reduction ?
170                R = Rz.copy();
171            }
172            Map.Entry<ExpVector, C> m = S.leadingMonomial();
173            ExpVector e = m.getKey();
174            C a = m.getValue();
175            ExpVector f = null;
176            int i;
177            for (i = 0; i < l; i++) {
178                f = P[i].leadingExpVector();
179                mt = e.multipleOf(f);
180                if (mt)
181                    break;
182            }
183            if (!mt) {
184                //logger.debug("irred");
185                //R = R.sum(a, e);
186                //S = S.subtract(a, e);
187                R.doPutToMap(e, a);
188                S.doRemoveFromMap(e, a);
189                //System.out.println(" S = " + S);
190            } else {
191                e = e.subtract(f);
192                //logger.info("red div = " + e);
193                C c = P[i].leadingBaseCoefficient();
194                if (a.remainder(c).isZERO()) { //c.isUnit() ) {
195                    a = a.divide(c);
196                    S = S.subtractMultiple(a, e, P[i]);
197                } else {
198                    mfac = mfac.multiply(c);
199                    R = R.multiply(c);
200                    //S = S.multiply(c);
201                    S = S.scaleSubtractMultiple(c, a, e, P[i]);
202                }
203                //Q = p[i].multiply(a, e);
204                //S = S.subtract(Q);
205            }
206        }
207        if (logger.isInfoEnabled()) {
208            logger.info("multiplicative factor = " + mfac);
209        }
210        pf = new PseudoReductionEntry<C>(R, mfac);
211        return pf;
212    }
213
214
215    /**
216     * Normalform with recording. <b>Note:</b> Only meaningful if all divisions
217     * are exact. Compute first the multiplication factor <code>m</code> with
218     * <code>normalform(Pp,Ap,m)</code>, then call this method with
219     * <code>normalform(row,Pp,m*Ap)</code>.
220     * @param row recording matrix, is modified.
221     * @param Pp a polynomial list for reduction.
222     * @param Ap a polynomial.
223     * @return nf(Pp,Ap), the normal form of Ap wrt. Pp.
224     */
225    @SuppressWarnings("unchecked")
226    public GenPolynomial<C> normalform(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp,
227                    GenPolynomial<C> Ap) {
228        throw new RuntimeException("normalform with recording not implemented");
229    }
230
231
232    /**
233     * Normalform recursive.
234     * @param Ap recursive polynomial.
235     * @param Pp recursive polynomial list.
236     * @return nf(Ap) with respect to Pp.
237     */
238    @SuppressWarnings("unchecked")
239    public GenPolynomial<GenPolynomial<C>> normalformRecursive(List<GenPolynomial<GenPolynomial<C>>> Pp, GenPolynomial<GenPolynomial<C>> Ap) {
240        if (Pp == null || Pp.isEmpty()) {
241            return Ap;
242        }
243        if (Ap == null || Ap.isZERO()) {
244            return Ap;
245        }
246        GenPolynomial<GenPolynomial<C>>[] P = new GenPolynomial[0];
247        List<GenPolynomial<GenPolynomial<C>>> Ppp;
248        synchronized (Pp) {
249            Ppp = new ArrayList<GenPolynomial<GenPolynomial<C>>>(Pp); // sic
250        }
251        P = Ppp.toArray(P);
252        int ll = Ppp.size();
253        GenPolynomial<GenPolynomial<C>> Rz = Ap.ring.getZERO();
254        GenPolynomial<GenPolynomial<C>> R = Rz.copy();
255
256        GenPolynomial<GenPolynomial<C>> S = Ap.copy();
257        while (S.length() > 0) {
258            if (Pp.size() != ll) {
259                //System.out.println("Pp.size() = " + Pp.size() + ", ll = " + ll);
260                //long t = System.currentTimeMillis();
261                synchronized (Pp) {
262                    Ppp = new ArrayList<GenPolynomial<GenPolynomial<C>>>(Pp); // sic
263                }
264                P = Ppp.toArray(P);
265                ll = Ppp.size();
266                //ll = P.length; // wrong
267                //t = System.currentTimeMillis()-t;
268                //logger.info("Pp.toArray(): size() = " + l + ", ll = " + ll);
269                S = Ap.copy(); // S.add(R)? // restart reduction ?
270                R = Rz.copy();
271            }
272            boolean mt = false;
273            Map.Entry<ExpVector, GenPolynomial<C>> m = S.leadingMonomial();
274            ExpVector e = m.getKey();
275            GenPolynomial<C> a = m.getValue();
276            ExpVector f = null;
277            int i;
278            for (i = 0; i < ll; i++) {
279                f = P[i].leadingExpVector();
280                mt = e.multipleOf(f);
281                if (mt)
282                    break;
283            }
284            if (!mt) {
285                //System.out.println("m = " + m);
286                //logger.debug("irred");
287                //R = R.sum(a, e);
288                //S = S.subtract(a, e);
289                R.doPutToMap(e, a);
290                S.doRemoveFromMap(e, a);
291                //System.out.println(" S = " + S);
292            } else {
293                f = e.subtract(f);
294                if (debug) {
295                    logger.info("red div = " + e);
296                }
297                GenPolynomial<C> c = P[i].leadingBaseCoefficient();
298                //if (a.remainder(c).isZERO()) { //c.isUnit() ) {
299                if (PolyUtil.<C> baseSparsePseudoRemainder(a,c).isZERO()) { 
300                    if (debug) {
301                        logger.info("red c = " + c);
302                    }
303                    //a = a.divide(c);
304                    GenPolynomial<C> b = PolyUtil.<C> basePseudoDivide(a,c);
305                    GenPolynomial<GenPolynomial<C>> Sp = S.subtractMultiple(b, f, P[i]);
306                    if (e.equals(Sp.leadingExpVector())) { // TODO: avoid
307                        //throw new RuntimeException("degree not descending");
308                        logger.info("degree not descending: S = " + S + ", Sp = " + Sp);
309                        R = R.multiply(c);
310                        //S = S.multiply(c);
311                        Sp = S.scaleSubtractMultiple(c, a, f, P[i]);
312                    }
313                    S = Sp; 
314                } else {
315                    R = R.multiply(c);
316                    //S = S.multiply(c);
317                    S = S.scaleSubtractMultiple(c, a, f, P[i]);
318                }
319                //Q = p[i].multiply(a, f);
320                //S = S.subtract(Q);
321            }
322        }
323        return R;
324    }
325
326}