001    /*
002     * $Id: SolvableGroebnerBaseSeq.java 3652 2011-06-02 18:17:04Z kredel $
003     */
004    
005    package edu.jas.gb;
006    
007    import java.util.ArrayList;
008    import java.util.List;
009    import java.util.ListIterator;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.structure.RingElem;
014    import edu.jas.poly.ExpVector;
015    import edu.jas.poly.GenPolynomial;
016    import edu.jas.poly.GenSolvablePolynomial;
017    import edu.jas.poly.GenSolvablePolynomialRing;
018    import edu.jas.poly.PolynomialList;
019    
020    
021    /**
022     * Solvable Groebner bases sequential algorithms.
023     * Implements common left, right and twosided Groebner bases 
024     * and left, right and twosided GB tests.
025     * @param <C> coefficient type
026     * @author Heinz Kredel.
027     */
028    
029    public class SolvableGroebnerBaseSeq<C extends RingElem<C>> 
030           extends SolvableGroebnerBaseAbstract<C>  {
031    
032        private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseSeq.class);
033    
034        private final boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Constructor.
039         */
040        public SolvableGroebnerBaseSeq() {
041            super();
042        }
043    
044    
045        /**
046         * Constructor.
047         * @param sred Solvable reduction engine
048         * @param pl pair selection strategy
049         */
050        public SolvableGroebnerBaseSeq(SolvableReduction<C> sred, 
051                                       PairList<C> pl) {
052            super(sred,pl);
053        }
054    
055    
056        /**
057         * Left Groebner base using pairlist class.
058         * @param modv number of module variables.
059         * @param F solvable polynomial list.
060         * @return leftGB(F) a left Groebner base of F.
061         */
062        public List<GenSolvablePolynomial<C>> 
063                   leftGB(int modv, 
064                          List<GenSolvablePolynomial<C>> F) {  
065            List<GenSolvablePolynomial<C>> G 
066               = new ArrayList<GenSolvablePolynomial<C>>();
067            PairList<C> pairlist = null; 
068            int l = F.size();
069            //  ListIterator it = F.listIterator();
070            for ( GenSolvablePolynomial<C> p: F ) { 
071                //  p = (SolvablePolynomial) it.next();
072                if ( p.length() > 0 ) {
073                   p = (GenSolvablePolynomial<C>)p.monic();
074                   if ( p.isONE() ) {
075                      G.clear(); G.add( p );
076                      return G; // since no threads are activated
077                   }
078                   G.add( p );
079                   if ( pairlist == null ) {
080                       //pairlist = new OrderedPairlist<C>( modv, p.ring );
081                       pairlist = strategy.create( modv, p.ring );
082                   }
083                   // putOne not required
084                   pairlist.put( p );
085                } else { 
086                   l--;
087                }
088            }
089            if ( l <= 1 ) {
090               return G; // since no threads are activated
091            }
092    
093            GenSolvablePolynomial<C> pi, pj, S, H;
094            Pair<C> pair;
095            while ( pairlist.hasNext() ) {
096                  pair = pairlist.removeNext();
097                  if ( pair == null ) {
098                     continue; 
099                  }
100                  pi = (GenSolvablePolynomial<C>)pair.pi; 
101                  pj = (GenSolvablePolynomial<C>)pair.pj; 
102                  if ( false && debug ) {
103                     logger.info("pi    = " + pi );
104                     logger.info("pj    = " + pj );
105                  }
106    
107                  S = sred.leftSPolynomial( pi, pj );
108                  if ( S.isZERO() ) {
109                     pair.setZero();
110                     continue;
111                  }
112                  if ( false && debug ) {
113                     logger.info("ht(S) = " + S.leadingExpVector() );
114                  }
115    
116                  H = sred.leftNormalform( G, S );
117                  if ( H.isZERO() ) {
118                     pair.setZero();
119                     continue;
120                  }
121                  if ( false && debug ) {
122                     logger.info("ht(H) = " + H.leadingExpVector() );
123                  }
124    
125                  H = (GenSolvablePolynomial<C>)H.monic();
126                  if ( H.isONE() ) {
127                      G.clear(); G.add( H );
128                      return G; // since no threads are activated
129                  }
130                  if ( debug ) {
131                     logger.info("H = " + H );
132                  }
133                  if ( H.length() > 0 ) {
134                     l++;
135                     G.add( H );
136                     pairlist.put( H );
137                  }
138            }
139            logger.debug("#sequential list = "+G.size());
140            G = leftMinimalGB(G);
141            logger.info("" + pairlist); 
142            return G;
143        }
144    
145    
146        /**
147         * Solvable Extended Groebner base using critical pair class.
148         * @param modv module variable number.
149         * @param F solvable polynomial list.
150         * @return a container for an extended left Groebner base of F.
151         */
152        public SolvableExtendedGB<C> 
153               extLeftGB( int modv, 
154                          List<GenSolvablePolynomial<C>> F ) {
155    
156            List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>();
157            List<List<GenSolvablePolynomial<C>>> F2G = new ArrayList<List<GenSolvablePolynomial<C>>>();
158            List<List<GenSolvablePolynomial<C>>> G2F = new ArrayList<List<GenSolvablePolynomial<C>>>();
159            PairList<C> pairlist = null; 
160            boolean oneInGB = false;
161            int len = F.size();
162    
163            List<GenSolvablePolynomial<C>> row = null;
164            List<GenSolvablePolynomial<C>> rows = null;
165            List<GenSolvablePolynomial<C>> rowh = null;
166            GenSolvablePolynomialRing<C> ring = null;
167            GenSolvablePolynomial<C> H;
168            GenSolvablePolynomial<C> p;
169    
170            int nzlen = 0;
171            for ( GenSolvablePolynomial<C> f : F ) { 
172                if ( f.length() > 0 ) {
173                    nzlen++;
174                }
175                if ( ring == null ) {
176                   ring = f.ring;
177                }
178            }
179            GenSolvablePolynomial<C> mone = ring.getONE(); //.negate();
180            int k = 0;
181            ListIterator<GenSolvablePolynomial<C>> it = F.listIterator();
182            while ( it.hasNext() ) { 
183                p = it.next();
184                if ( p.length() > 0 ) {
185                   row = new ArrayList<GenSolvablePolynomial<C>>( nzlen );
186                   for ( int j = 0; j < nzlen; j++ ) {
187                       row.add(null);
188                   }
189                   //C c = p.leadingBaseCoefficient();
190                   //c = c.inverse();
191                   //p = p.multiply( c );
192                   row.set( k, mone ); //.multiply(c) );
193                   k++;
194                   if ( p.isUnit() ) {
195                      G.clear(); G.add( p );
196                      G2F.clear(); G2F.add( row );
197                      oneInGB = true;
198                      break;
199                   }
200                   G.add( p );
201                   G2F.add( row );
202                   if ( pairlist == null ) {
203                       //pairlist = new CriticalPairList<C>( modv, p.ring );
204                       pairlist = strategy.create( modv, p.ring );
205                   }
206                   // putOne not required
207                   pairlist.put( p );
208                } else { 
209                   len--;
210                }
211            }
212            SolvableExtendedGB<C> exgb;
213            if ( len <= 1 || oneInGB ) {
214               // adjust F2G
215               for ( GenSolvablePolynomial<C> f : F ) {
216                   row = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
217                   for ( int j = 0; j < G.size(); j++ ) {
218                       row.add(null);
219                   }
220                   H = sred.leftNormalform( row, G, f );
221                   if ( ! H.isZERO() ) {
222                      logger.error("nonzero H = " + H );
223                   }
224                   F2G.add( row );
225               }
226               exgb = new SolvableExtendedGB<C>(F,G,F2G,G2F);
227               //System.out.println("exgb 1 = " + exgb);
228               return exgb;
229            }
230    
231            Pair<C> pair;
232            int i, j;
233            GenSolvablePolynomial<C> pi;
234            GenSolvablePolynomial<C> pj;
235            GenSolvablePolynomial<C> S;
236            GenSolvablePolynomial<C> x;
237            GenSolvablePolynomial<C> y;
238            //GenPolynomial<C> z;
239            while ( pairlist.hasNext() && ! oneInGB ) {
240                  pair = pairlist.removeNext();
241                  if ( pair == null ) { 
242                      //pairlist.update(); // ?
243                      continue; 
244                  }
245                  i = pair.i; 
246                  j = pair.j; 
247                  pi = (GenSolvablePolynomial<C>)pair.pi; 
248                  pj = (GenSolvablePolynomial<C>)pair.pj; 
249                  if ( debug ) {
250                     logger.info("i, pi    = " + i + ", " + pi );
251                     logger.info("j, pj    = " + j + ", " + pj );
252                  }
253    
254                  rows = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
255                  for ( int m = 0; m < G.size(); m++ ) {
256                      rows.add(null);
257                  }
258                  S = sred.leftSPolynomial( rows, i, pi, j, pj );
259                  if ( debug ) {
260                     logger.debug("is reduction S = " 
261                                 + sred.isLeftReductionNF( rows, G, ring.getZERO(), S ) );
262                  }
263                  if ( S.isZERO() ) {
264                      pair.setZero();
265                      //pairlist.update( pair, S );
266                      // do not add to G2F
267                      continue;
268                  }
269                  if ( debug ) {
270                     logger.debug("ht(S) = " + S.leadingExpVector() );
271                  }
272    
273                  rowh = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
274                  for ( int m = 0; m < G.size(); m++ ) {
275                      rowh.add(null);
276                  }
277                  H = sred.leftNormalform( rowh, G, S );
278                  if ( debug ) {
279                      //System.out.println("H = " + H);
280                      logger.debug("is reduction H = " 
281                                  + sred.isLeftReductionNF( rowh, G, S, H ) );
282                  }
283                  if ( H.isZERO() ) {
284                      pair.setZero();
285                      //pairlist.update( pair, H );
286                      // do not add to G2F
287                      continue;
288                  }
289                  if ( debug ) {
290                     logger.debug("ht(H) = " + H.leadingExpVector() );
291                  }
292    
293                  row = new ArrayList<GenSolvablePolynomial<C>>( G.size()+1 );
294                  for ( int m = 0; m < G.size(); m++ ) {
295                      x = rows.get(m);
296                      if ( x != null ) {
297                         //System.out.println("ms = " + m + " " + x);
298                         x = (GenSolvablePolynomial<C>)x.negate();
299                      }
300                      y = rowh.get(m);
301                      if ( y != null ) {
302                         y = (GenSolvablePolynomial<C>)y.negate();
303                         //System.out.println("mh = " + m + " " + y);
304                      }
305                      if ( x == null ) {
306                         x = y;
307                      } else {
308                         x = (GenSolvablePolynomial<C>)x.sum( y );
309                      }
310                      //System.out.println("mx = " + m + " " + x);
311                      row.add( x );
312                  }
313                  if ( debug ) {
314                     logger.debug("is reduction 0+sum(row,G) == H : " 
315                                 + sred.isLeftReductionNF( row, G, H, ring.getZERO() ) );
316                  }
317                  row.add( null );
318    
319    
320                  //  H = H.monic();
321                  C c = H.leadingBaseCoefficient();
322                  c = c.inverse();
323                  H = H.multiply( c );
324                  // 1*c*row, leads to wrong method dispatch:
325                  row = PolynomialList.<C>castToSolvableList(blas.scalarProduct(mone.multiply(c),PolynomialList.<C>castToList(row)));
326                  row.set( G.size(), mone );
327                  if ( H.isONE() ) {
328                     // pairlist.record( pair, H );
329                     // G.clear(); 
330                     G.add( H );
331                     G2F.add( row );
332                     oneInGB = true;
333                     break; 
334                  }
335                  if ( debug ) {
336                     logger.debug("H = " + H );
337                  }
338                  G.add( H );
339                  //pairlist.update( pair, H );
340                  pairlist.put(H);
341                  G2F.add( row );
342            }
343            if ( debug ) {
344               exgb = new SolvableExtendedGB<C>(F,G,F2G,G2F);
345               logger.info("exgb unnorm = " + exgb);
346            }
347            G2F = normalizeMatrix( F.size(), G2F );
348            if ( debug ) {
349               exgb = new SolvableExtendedGB<C>(F,G,F2G,G2F);
350               logger.info("exgb nonmin = " + exgb);
351               boolean t2 = isLeftReductionMatrix( exgb );
352               logger.debug("exgb t2 = " + t2);
353            }
354            exgb = minimalSolvableExtendedGB(F.size(),G,G2F);
355            G = exgb.G;
356            G2F = exgb.G2F;
357            logger.debug("#sequential list = " + G.size());
358            logger.info("" + pairlist); 
359            // setup matrices F and F2G
360            for ( GenSolvablePolynomial<C> f : F ) {
361                row = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
362                for ( int m = 0; m < G.size(); m++ ) {
363                    row.add(null);
364                }
365                H = sred.leftNormalform( row, G, f );
366                if ( ! H.isZERO() ) {
367                   logger.error("nonzero H = " + H );
368                }
369                F2G.add( row );
370            }
371            return new SolvableExtendedGB<C>(F,G,F2G,G2F);
372        }
373    
374    
375        /**
376         * Twosided Groebner base using pairlist class.
377         * @param modv number of module variables.
378         * @param Fp solvable polynomial list.
379         * @return tsGB(Fp) a twosided Groebner base of Fp.
380         */
381        public List<GenSolvablePolynomial<C>> 
382                   twosidedGB(int modv, 
383                              List<GenSolvablePolynomial<C>> Fp) {  
384            if ( Fp == null || Fp.size() == 0 ) { // 0 not 1
385                return new ArrayList<GenSolvablePolynomial<C>>( );
386            }
387            GenSolvablePolynomialRing<C> fac = Fp.get(0).ring; // assert != null
388            //List<GenSolvablePolynomial<C>> X = generateUnivar( modv, Fp );
389            List<GenSolvablePolynomial<C>> X = fac.univariateList( modv );
390            //System.out.println("X univ = " + X);
391            List<GenSolvablePolynomial<C>> F 
392                = new ArrayList<GenSolvablePolynomial<C>>( Fp.size() * (1+X.size()) );
393            F.addAll( Fp );
394            GenSolvablePolynomial<C> p, x, q;
395            for ( int i = 0; i < Fp.size(); i++ ) {
396                p = Fp.get(i);
397                for ( int j = 0; j < X.size(); j++ ) {
398                    x = X.get(j);
399                    q = p.multiply( x );
400                    q = sred.leftNormalform( F, q );
401                    if ( !q.isZERO() ) {
402                       F.add( q );
403                    }
404                }
405            }
406            //System.out.println("F generated = " + F);
407            List<GenSolvablePolynomial<C>> G 
408                = new ArrayList<GenSolvablePolynomial<C>>();
409            PairList<C> pairlist = null; 
410            int l = F.size();
411            ListIterator<GenSolvablePolynomial<C>> it = F.listIterator();
412            while ( it.hasNext() ) { 
413                p = it.next();
414                if ( p.length() > 0 ) {
415                   p = (GenSolvablePolynomial<C>)p.monic();
416                   if ( p.isONE() ) {
417                      G.clear(); G.add( p );
418                      return G; // since no threads are activated
419                   }
420                   G.add( p );
421                   if ( pairlist == null ) {
422                       // pairlist = new OrderedPairlist<C>( modv, p.ring );
423                       pairlist = strategy.create( modv, p.ring );
424                   }
425                   // putOne not required
426                   pairlist.put( p );
427                } else { 
428                   l--;
429                }
430            }
431            //System.out.println("G to check = " + G);
432            if ( l <= 1 ) { // 1 ok
433               return G; // since no threads are activated
434            }
435    
436            Pair<C> pair;
437            GenSolvablePolynomial<C> pi, pj, S, H;
438            while ( pairlist.hasNext() ) {
439                  pair = pairlist.removeNext();
440                  if ( pair == null ) {
441                     continue; 
442                  }
443    
444                  pi = (GenSolvablePolynomial<C>)pair.pi; 
445                  pj = (GenSolvablePolynomial<C>)pair.pj; 
446                  if ( false && debug ) {
447                     logger.debug("pi    = " + pi );
448                     logger.debug("pj    = " + pj );
449                  }
450    
451                  S = sred.leftSPolynomial( pi, pj );
452                  if ( S.isZERO() ) {
453                     pair.setZero();
454                     continue;
455                  }
456                  if ( debug ) {
457                     logger.debug("ht(S) = " + S.leadingExpVector() );
458                  }
459    
460                  H = sred.leftNormalform( G, S );
461                  if ( H.isZERO() ) {
462                     pair.setZero();
463                     continue;
464                  }
465                  if ( debug ) {
466                     logger.debug("ht(H) = " + H.leadingExpVector() );
467                  }
468    
469                  H = (GenSolvablePolynomial<C>)H.monic();
470                  if ( H.isONE() ) {
471                      G.clear(); G.add( H );
472                      return G; // since no threads are activated
473                  }
474                  if ( debug ) {
475                     logger.debug("H = " + H );
476                  }
477                  if ( H.length() > 0 ) {
478                     l++;
479                     G.add( H );
480                     pairlist.put( H );
481                     for ( int j = 0; j < X.size(); j++ ) {
482                         l++;
483                         x = X.get(j);
484                         p = H.multiply( x );
485                         p = sred.leftNormalform( G, p );
486                         if ( !p.isZERO() ) {
487                            p = (GenSolvablePolynomial<C>)p.monic();
488                            if ( p.isONE() ) {
489                               G.clear(); G.add( p );
490                               return G; // since no threads are activated
491                            }
492                            G.add( p );
493                            pairlist.put( p );
494                         }
495                     }
496                  }
497            }
498            logger.debug("#sequential list = "+G.size());
499            G = leftMinimalGB(G);
500            logger.info("" + pairlist); 
501            return G;
502        }
503    
504    
505        /**
506         * Normalize M.
507         * Make all rows the same size and make certain column elements zero.
508         * @param M a reduction matrix.
509         * @return normalized M.
510         */
511        public List<List<GenSolvablePolynomial<C>>> 
512               normalizeMatrix(int flen, List<List<GenSolvablePolynomial<C>>> M) {
513            if ( M == null ) {
514                return M;
515            }
516            if ( M.size() == 0 ) {
517                return M;
518            }
519            List<List<GenSolvablePolynomial<C>>> N = new ArrayList<List<GenSolvablePolynomial<C>>>();
520            List<List<GenSolvablePolynomial<C>>> K = new ArrayList<List<GenSolvablePolynomial<C>>>();
521            int len = M.get(  M.size()-1 ).size(); // longest row
522            // pad / extend rows
523            for ( List<GenSolvablePolynomial<C>> row : M ) {
524                List<GenSolvablePolynomial<C>> nrow = new ArrayList<GenSolvablePolynomial<C>>( row );
525                for ( int i = row.size(); i < len; i++ ) {
526                    nrow.add( null );
527                }
528                N.add( nrow );
529            }
530            // System.out.println("norm N fill = " + N);
531            // make zero columns
532            int k = flen;
533            for ( int i = 0; i < N.size(); i++ ) { // 0
534                List<GenSolvablePolynomial<C>> row = N.get( i );
535                if ( debug ) {
536                   logger.info("row = " + row);
537                }
538                K.add( row );
539                if ( i < flen ) { // skip identity part
540                   continue;
541                }
542                List<GenSolvablePolynomial<C>> xrow;
543                GenSolvablePolynomial<C> a;
544                //System.out.println("norm i = " + i);
545                for ( int j = i+1; j < N.size(); j++ ) {
546                    List<GenSolvablePolynomial<C>> nrow = N.get( j );
547                    //System.out.println("nrow j = " +j + ", " + nrow);
548                    if ( k < nrow.size() ) { // always true
549                       a = nrow.get( k );
550                       //System.out.println("k, a = " + k + ", " + a);
551                       if ( a != null && !a.isZERO() ) { // a*row + nrow, leads to wrong method dispatch
552                           List<GenPolynomial<C>> yrow = blas.scalarProduct(a,PolynomialList.<C>castToList(row));
553                           yrow = blas.vectorAdd(yrow,PolynomialList.<C>castToList(nrow));
554                           xrow = PolynomialList.<C>castToSolvableList(yrow);
555                           N.set( j, xrow );
556                       }
557                    }
558                }
559                k++;
560            }
561            //System.out.println("norm K reduc = " + K);
562            // truncate 
563            N.clear();
564            for ( List<GenSolvablePolynomial<C>> row: K ) {
565                List<GenSolvablePolynomial<C>> tr = new ArrayList<GenSolvablePolynomial<C>>();
566                for ( int i = 0; i < flen; i++ ) {
567                    tr.add( row.get(i) );
568                }
569                N.add( tr );
570            }
571            K = N;
572            //System.out.println("norm K trunc = " + K);
573            return K;
574        }
575    
576    
577        /**
578         * Test if M is a left reduction matrix.
579         * @param exgb an SolvableExtendedGB container.
580         * @return true, if exgb contains a left reduction matrix, else false.
581         */
582        @Override
583         public boolean
584               isLeftReductionMatrix(SolvableExtendedGB<C> exgb) {  
585            if ( exgb == null ) {
586                return true;
587            }
588            return isLeftReductionMatrix(exgb.F,exgb.G,exgb.F2G,exgb.G2F);
589        }
590    
591    
592        /**
593         * Minimal solvable extended groebner basis.
594         * @param Gp a left Groebner base.
595         * @param M a left reduction matrix, is modified.
596         * @return a (partially) reduced left Groebner base of Gp in a container.
597         */
598        public SolvableExtendedGB<C> 
599            minimalSolvableExtendedGB(int flen,
600                                      List<GenSolvablePolynomial<C>> Gp,
601                                      List<List<GenSolvablePolynomial<C>>> M) {  
602            if ( Gp == null ) {
603             return null; //new SolvableExtendedGB<C>(null,Gp,null,M);
604            }
605            if ( Gp.size() <= 1 ) {
606               return new SolvableExtendedGB<C>(null,Gp,null,M);
607            }
608            List<GenSolvablePolynomial<C>> G;
609            List<GenSolvablePolynomial<C>> F;
610            G = new ArrayList<GenSolvablePolynomial<C>>( Gp );
611            F = new ArrayList<GenSolvablePolynomial<C>>( Gp.size() );
612    
613            List<List<GenSolvablePolynomial<C>>> Mg;
614            List<List<GenSolvablePolynomial<C>>> Mf;
615            Mg = new ArrayList<List<GenSolvablePolynomial<C>>>( M.size() );
616            Mf = new ArrayList<List<GenSolvablePolynomial<C>>>( M.size() );
617            List<GenSolvablePolynomial<C>> row;
618            for ( List<GenSolvablePolynomial<C>> r : M ) {
619                // must be copied also
620                row = new ArrayList<GenSolvablePolynomial<C>>( r );
621                Mg.add( row );
622            }
623            row = null;
624    
625            GenSolvablePolynomial<C> a;
626            ExpVector e;        
627            ExpVector f;        
628            GenSolvablePolynomial<C> p;
629            boolean mt;
630            ListIterator<GenSolvablePolynomial<C>> it;
631            ArrayList<Integer> ix = new ArrayList<Integer>();
632            ArrayList<Integer> jx = new ArrayList<Integer>();
633            int k = 0;
634            //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() );
635            while ( G.size() > 0 ) {
636                a = G.remove(0);
637                e = a.leadingExpVector();
638    
639                it = G.listIterator();
640                mt = false;
641                while ( it.hasNext() && ! mt ) {
642                   p = it.next();
643                   f = p.leadingExpVector();
644                   mt =  e.multipleOf( f );
645                }
646                it = F.listIterator();
647                while ( it.hasNext() && ! mt ) {
648                   p = it.next();
649                   f = p.leadingExpVector();
650                   mt =  e.multipleOf( f );
651                }
652                //System.out.println("k, mt = " + k + ", " + mt);
653                if ( ! mt ) {
654                   F.add( a );
655                   ix.add( k );
656                } else { // drop polynomial and corresponding row and column
657                   // F.add( a.ring.getZERO() );
658                   jx.add( k );
659                }
660                k++;
661            }
662            if ( debug ) {
663               logger.debug("ix, #M, jx = " + ix + ", " + Mg.size() + ", " + jx);
664            }
665            int fix = -1; // copied polys
666            // copy Mg to Mf as indicated by ix
667            for ( int i = 0; i < ix.size(); i++ ) {
668                int u = ix.get(i); 
669                if ( u >= flen && fix == -1 ) {
670                   fix = Mf.size();
671                }
672                //System.out.println("copy u, fix = " + u + ", " + fix);
673                if ( u >= 0 ) {
674                   row = Mg.get( u );
675                   Mf.add( row );
676                }
677            }
678            if ( F.size() <= 1 || fix == -1 ) {
679               return new SolvableExtendedGB<C>(null,F,null,Mf);
680            }
681            // must return, since extended normalform has not correct order of polys
682            /*
683            G = F;
684            F = new ArrayList<GenSolvablePolynomial<C>>( G.size() );
685            List<GenSolvablePolynomial<C>> temp;
686            k = 0;
687            final int len = G.size();
688            while ( G.size() > 0 ) {
689                a = G.remove(0);
690                if ( k >= fix ) { // dont touch copied polys
691                   row = Mf.get( k );
692                   //System.out.println("doing k = " + k + ", " + a);
693                   // must keep order, but removed polys missing
694                   temp = new ArrayList<GenPolynomial<C>>( len );
695                   temp.addAll( F );
696                   temp.add( a.ring.getZERO() ); // ??
697                   temp.addAll( G );
698                   //System.out.println("row before = " + row);
699                   a = sred.leftNormalform( row, temp, a );
700                   //System.out.println("row after  = " + row);
701                }
702                F.add( a );
703                k++;
704            }
705            // does Mf need renormalization?
706            */
707            return new SolvableExtendedGB<C>(null,F,null,Mf);
708        }
709    
710    }