source: git/kernel/gfan.cc @ c17211

spielwiese
Last change on this file since c17211 was c17211, checked in by Martin Monerjan, 14 years ago
bugfixes git-svn-id: file:///usr/local/Singular/svn/trunk@11995 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 67.4 KB
Line 
1/*
2Compute the Groebner fan of an ideal
3$Author: monerjan $
4$Date: 2009-07-21 15:56:28 $
5$Header: /exports/cvsroot-2/cvsroot/kernel/gfan.cc,v 1.79 2009-07-21 15:56:28 monerjan Exp $
6$Id: gfan.cc,v 1.79 2009-07-21 15:56:28 monerjan Exp $
7*/
8
9#include "mod2.h"
10
11#ifdef HAVE_GFAN
12
13#include "kstd1.h"
14#include "kutil.h"
15#include "intvec.h"
16#include "polys.h"
17#include "ideals.h"
18#include "kmatrix.h"
19#include "fast_maps.h"  //Mapping of ideals
20#include "maps.h"
21#include "ring.h"
22#include "prCopy.h"
23#include <iostream>
24#include <bitset>
25#include <fstream>      //read-write cones to files
26#include <gmp.h>
27#include <string>
28#include <sstream>
29//#include <gmpxx.h>
30
31/*DO NOT REMOVE THIS*/
32#ifndef GMPRATIONAL
33#define GMPRATIONAL
34#endif
35
36//Hacks for different working places
37#define ITWM
38
39#ifdef UNI
40#include "/users/urmel/alggeom/monerjan/cddlib/include/setoper.h" //Support for cddlib. Dirty hack
41#include "/users/urmel/alggeom/monerjan/cddlib/include/cdd.h"
42#endif
43
44#ifdef HOME
45#include "/home/momo/studium/diplomarbeit/cddlib/include/setoper.h"
46#include "/home/momo/studium/diplomarbeit/cddlib/include/cdd.h"
47#endif
48
49#ifdef ITWM
50#include "/u/slg/monerjan/cddlib/include/setoper.h"
51#include "/u/slg/monerjan/cddlib/include/cdd.h"
52#include "/u/slg/monerjan/cddlib/include/cddmp.h"
53#endif
54
55#ifndef gfan_DEBUG
56#define gfan_DEBUG
57#endif
58
59//#include gcone.h
60using namespace std;
61
62/**
63*\brief Class facet
64*       Implements the facet structure as a linked list
65*
66*/
67class facet
68{
69        private:
70                /** \brief Inner normal of the facet, describing it uniquely up to isomorphism */
71                intvec *fNormal;
72               
73                /** \brief An interior point of the facet*/
74                intvec *interiorPoint;
75               
76                /** \brief Universal Cone Number
77                * The number of the cone the facet belongs to, Set in getConeNormals()
78                */
79                int UCN;
80               
81                /** \brief The codim of the facet
82                */
83                int codim;
84               
85                /** \brief The Groebner basis on the other side of a shared facet
86                 *
87                 * In order not to have to compute the flipped GB twice we store the basis we already get
88                 * when identifying search facets. Thus in the next step of the reverse search we can
89                 * just copy the old cone and update the facet and the gcBasis.
90                 * facet::flibGB is set via facet::setFlipGB() and printed via facet::printFlipGB
91                 */
92                ideal flipGB;           //The Groebner Basis on the other side, computed via gcone::flip               
93                       
94        public: 
95                /**
96                */     
97                bool isFlippable;       //**flippable facet? */
98                bool isIncoming;        //Is the facet incoming or outgoing in the reverse search?
99                facet *next;            //Pointer to next facet
100                facet *prev;            //Pointer to predecessor. Needed for the SearchList in noRevS
101                facet *codim2Ptr;       //Pointer to (codim-2)-facet. Bit of recursion here ;-)
102                int numCodim2Facets;    //#of (codim-2)-facets of this facet. Set in getCodim2Normals()
103                ring flipRing;          //the ring on the other side of the facet
104                                               
105                /** The default constructor. Do I need a constructor of type facet(intvec)? */
106                facet()                 
107                {
108                        // Pointer to next facet.  */
109                        /* Defaults to NULL. This way there is no need to check explicitly */
110                        this->fNormal=NULL;
111                        this->interiorPoint=NULL;               
112                        this->UCN=0;
113                        this->codim2Ptr=NULL;
114                        this->codim=1;          //default for (codim-1)-facets
115                        this->numCodim2Facets=0;
116                        this->flipGB=NULL;
117                        this->isIncoming=FALSE;
118                        this->next=NULL;
119                        this->prev=NULL;               
120                        this->flipRing=NULL;
121                        this->isFlippable=FALSE;
122                }
123               
124                /** \brief Constructor for facets of codim >= 2
125                */
126                facet(int const &n)
127                {
128                        this->fNormal=NULL;
129                        this->interiorPoint=NULL;                       
130                        this->UCN=0;
131                        this->codim2Ptr=NULL;
132                        if(n>1)
133                        {
134                                this->codim=n;
135                        }//NOTE Handle exception here!                 
136                        this->numCodim2Facets=0;
137                        this->flipGB=NULL;
138                        this->isIncoming=FALSE;
139                        this->next=NULL;
140                        this->prev=NULL;
141                        this->flipRing=NULL;
142                        this->isFlippable=FALSE;
143                }
144               
145                /** The default destructor */
146                ~facet(){;}
147               
148                /** \brief Comparison of facets*/
149                bool areEqual(facet &f, facet &g)
150                {
151                        bool res = TRUE;
152                        intvec *fNormal = new intvec(pVariables);
153                        intvec *gNormal = new intvec(pVariables);
154                        fNormal = f.getFacetNormal();
155                        gNormal = g.getFacetNormal();
156                        if((fNormal == gNormal))//||(gcone::isParallel(fNormal,gNormal)))
157                        {
158                                if(f.numCodim2Facets==g.numCodim2Facets)
159                                {
160                                        facet *f2Act;
161                                        facet *g2Act;
162                                        f2Act = f.codim2Ptr;
163                                        g2Act = g.codim2Ptr;
164                                        intvec *f2N = new intvec(pVariables);
165                                        intvec *g2N = new intvec(pVariables);
166                                        while(f2Act->next!=NULL && g2Act->next!=NULL)
167                                        {
168                                                for(int ii=0;ii<f2N->length();ii++)
169                                                {
170                                                        if(f2Act->getFacetNormal() != g2Act->getFacetNormal())
171                                                        {
172                                                                res=FALSE;                                                             
173                                                        }
174                                                        if (res==FALSE)
175                                                                break;
176                                                }
177                                                if(res==FALSE)
178                                                        break;
179                                               
180                                                f2Act = f2Act->next;
181                                                g2Act = g2Act->next;
182                                        }//while
183                                }//if           
184                        }//if
185                        else
186                        {
187                                res = FALSE;
188                        }
189                        return res;
190                }
191               
192                /** Stores the facet normal \param intvec*/
193                void setFacetNormal(intvec *iv)
194                {
195                        this->fNormal = ivCopy(iv);                     
196                }
197               
198                /** Hopefully returns the facet normal */
199                intvec *getFacetNormal()
200                {                               
201                        return this->fNormal;
202                }
203               
204                /** Method to print the facet normal*/
205                void printNormal()
206                {
207                        fNormal->show();
208                }
209               
210                /** Store the flipped GB*/
211                void setFlipGB(ideal I)
212                {
213                        this->flipGB=idCopy(I);
214                }
215               
216                /** Return the flipped GB*/
217                ideal getFlipGB()
218                {
219                        return this->flipGB;
220                }
221               
222                /** Print the flipped GB*/
223                void printFlipGB()
224                {
225                        idShow(this->flipGB);
226                }
227               
228                /** Set the UCN */
229                void setUCN(int n)
230                {
231                        this->UCN=n;
232                }
233               
234                /** \brief Get the UCN
235                * Returns the UCN iff this != NULL, else -1
236                */
237                int getUCN()
238                {
239                        if(this!=NULL)
240                                return this->UCN;
241                        else
242                                return -1;
243                }
244               
245                /** Store an interior point of the facet */
246                void setInteriorPoint(intvec *iv)
247                {
248                        this->interiorPoint = ivCopy(iv);
249                }
250               
251                intvec *getInteriorPoint()
252                {
253                        return this->interiorPoint;
254                }       
255               
256                /** \brief Debugging function
257                * prints the facet normal an all (codim-2)-facets that belong to it
258                */
259                void fDebugPrint()
260                {                       
261                        facet *codim2Act;                       
262                        codim2Act = this->codim2Ptr;
263                        intvec *fNormal;
264                        fNormal = this->getFacetNormal();
265                        intvec *f2Normal;
266                        cout << "=======================" << endl;
267                        cout << "Facet normal = (";
268                        for(int ii=0;ii<pVariables;ii++)
269                        {
270                                cout << (*fNormal)[ii] << ",";
271                        }
272                        if(this->isFlippable==TRUE)
273                                cout << ")" << endl;
274                        else
275                                cout << ")*" << endl;   //This case should never happen in SLA!
276                        cout << "-----------------------" << endl;
277                        cout << "Codim2 facets:" << endl;
278                        while(codim2Act!=NULL)
279                        {
280                                f2Normal = codim2Act->getFacetNormal();
281                                cout << "(";
282                                for(int jj=0;jj<pVariables;jj++)
283                                {
284                                        cout << (*f2Normal)[jj] << ",";
285                                }
286                                cout << ")" << endl;
287                                codim2Act = codim2Act->next;
288                        }
289                        cout << "=======================" << endl;
290                }
291               
292                /*bool isFlippable(intvec &load)
293                {
294                        bool res=TRUE;                 
295                        int jj;
296                        for (int jj = 0; jj<load.length(); jj++)
297                        {
298                                intvec *ivCanonical = new intvec(load.length());
299                                (*ivCanonical)[jj]=1;                           
300                                if (ivMult(&load,ivCanonical)<0)
301                                {
302                                        res=FALSE;
303                                        break;
304                                }
305                        }
306                        return res;
307                       
308                        /*while (dotProduct(load,ivCanonical)>=0)
309                        {
310                                if (jj!=this->numVars)
311                                {
312                                        intvec *ivCanonical = new intvec(this->numVars);
313                                        (*ivCanonical)[jj]=1;                   
314                                        res=TRUE;
315                                        jj += 1;
316                                }
317                        }
318                        if (jj==this->numVars)
319                        {                       
320                                delete ivCanonical;
321                                return FALSE;
322                        }
323                        else
324                        {
325                                delete ivCanonical;
326                                return TRUE;
327                }*/                                             
328                //}//bool isFlippable(facet &f)
329               
330               
331                friend class gcone;     //Bad style
332};
333
334/**
335*\brief Implements the cone structure
336*
337* A cone is represented by a linked list of facet normals
338* @see facet
339*/
340/*class gcone
341finally this should become s.th. like gconelib.{h,cc} to provide an API
342*/
343class gcone
344{
345        private:               
346                ring rootRing;          //good to know this -> generic walk
347                ideal inputIdeal;       //the original
348                ring baseRing;          //the basering of the cone             
349                /* TODO in order to save memory use pointers to rootRing and inputIdeal instead */
350                intvec *ivIntPt;        //an interior point of the cone
351                int UCN;                //unique number of the cone
352                static int counter;
353               
354        public: 
355                /** \brief Pointer to the first facet */
356                facet *facetPtr;        //Will hold the adress of the first facet; set by gcone::getConeNormals
357               
358                /** # of variables in the ring */
359                int numVars;            //#of variables in the ring
360               
361                /** # of facets of the cone
362                * This value is set by gcone::getConeNormals
363                */
364                int numFacets;          //#of facets of the cone
365               
366                /**
367                * At least as a workaround we store the irredundant facets of a matrix here.
368                * Otherwise, since we throw away non-flippable facets, facets2Matrix will not
369                * yield all the necessary information
370                */
371                dd_MatrixPtr ddFacets;  //Matrix to store irredundant facets of the cone
372               
373                /** Contains the Groebner basis of the cone. Is set by gcone::getGB(ideal I)*/
374                ideal gcBasis;          //GB of the cone, set by gcone::getGB();
375                gcone *next;            //Pointer to *previous* cone in search tree     
376               
377                /** \brief Default constructor.
378                *
379                * Initialises this->next=NULL and this->facetPtr=NULL
380                */
381                gcone()
382                {
383                        this->next=NULL;
384                        this->facetPtr=NULL;    //maybe this->facetPtr = new facet();                   
385                        this->baseRing=currRing;
386                        this->counter++;
387                        this->UCN=this->counter;                       
388                        this->numFacets=0;
389                        this->ivIntPt=NULL;
390                }
391               
392                /** \brief Constructor with ring and ideal
393                *
394                * This constructor takes the root ring and the root ideal as parameters and stores
395                * them in the private members gcone::rootRing and gcone::inputIdeal
396                * Since knowledge of the root ring is only needed when using reverse search,
397                * this constructor is not needed when using the "second" method
398                */
399                gcone(ring r, ideal I)
400                {
401                        this->next=NULL;
402                        this->facetPtr=NULL;                   
403                        this->rootRing=r;
404                        this->inputIdeal=I;
405                        this->baseRing=currRing;
406                        this->counter++;
407                        this->UCN=this->counter;                       
408                        this->numFacets=0;
409                        this->ivIntPt=NULL;
410                }
411               
412                /** \brief Copy constructor
413                *
414                * Copies a cone, sets this->gcBasis to the flipped GB
415                * Call this only after a successful call to gcone::flip which sets facet::flipGB
416                */             
417                gcone(const gcone& gc, const facet &f)
418                {
419                        this->next=NULL;
420                        this->numVars=gc.numVars;                                               
421                        this->counter++;
422                        this->UCN=this->counter;                       
423                        this->facetPtr=NULL;
424                        this->gcBasis=idCopy(f.flipGB);
425                        this->inputIdeal=idCopy(this->gcBasis);
426                        this->baseRing=rCopy(f.flipRing);
427                        this->numFacets=0;
428                        this->ivIntPt=NULL;
429                        //rComplete(this->baseRing);
430                        //rChangeCurrRing(this->baseRing);
431                }
432               
433                /** \brief Default destructor
434                */
435                ~gcone()
436                {
437                        //NOTE SAVE THE FACET STRUCTURE!!!
438                }                       
439               
440                /** \brief Set the interior point of a cone */
441                void setIntPoint(intvec *iv)
442                {
443                        this->ivIntPt=ivCopy(iv);
444                }
445               
446                /** \brief Return the interior point */
447                intvec *getIntPoint()
448                {
449                        return this->ivIntPt;
450                }
451               
452                /** \brief Print the interior point */
453                void showIntPoint()
454                {
455                        ivIntPt->show();
456                }
457               
458                /** \brief Print facets
459                * This is mainly for debugging purposes. Usually called from within gdb
460                */
461                void showFacets(short codim=1)
462                {
463                        facet *f;
464                        switch(codim)
465                        {
466                                case 1:
467                                        f = this->facetPtr;
468                                        break;
469                                case 2:
470                                        f = this->facetPtr->codim2Ptr;
471                                        break;
472                        }                       
473                       
474                        intvec *iv;                     
475                        while(f!=NULL)
476                        {
477                                iv = f->getFacetNormal();
478                                cout << "(";
479                                iv->show(1,0);                         
480                                if(f->isFlippable==FALSE)
481                                        cout << ")* ";
482                                else
483                                        cout << ") ";
484                                f=f->next;
485                        }
486                        cout << endl;
487                }
488               
489                /** For debugging purposes only */
490                void showSLA(facet &f)
491                {
492                        facet *fAct;
493                        fAct = &f;
494                        facet *codim2Act;
495                        codim2Act = fAct->codim2Ptr;
496                        intvec *fNormal;// = new intvec(this->numVars);
497                        intvec *f2Normal;
498                        cout << endl;
499                        while(fAct!=NULL)
500                        {
501                                fNormal=fAct->getFacetNormal();
502                                cout << "(";
503                                fNormal->show(1,0);
504                                if(fAct->isFlippable==TRUE)
505                                        cout << ") ";
506                                else
507                                        cout << ")* ";
508                                codim2Act = fAct->codim2Ptr;
509                                cout << " Codim2: ";
510                                while(codim2Act!=NULL)
511                                {
512                                        f2Normal = codim2Act->getFacetNormal();
513                                        cout << "(";
514                                        f2Normal->show(1,0);
515                                        cout << ") ";
516                                        codim2Act = codim2Act->next;
517                                }
518                                cout << "UCN = " << fAct->getUCN() << endl;                             
519                                fAct = fAct->next;
520                        }
521                }
522               
523                /** \brief Set gcone::numFacets */
524                void setNumFacets()
525                {
526                }
527               
528                /** \brief Get gcone::numFacets */
529                int getNumFacets()
530                {
531                        return this->numFacets;
532                }
533               
534                int getUCN()
535                {
536                        return this->UCN;
537                }
538               
539                /** \brief Compute the normals of the cone
540                *
541                * This method computes a representation of the cone in terms of facet normals. It takes an ideal
542                * as its input. Redundancies are automatically removed using cddlib's dd_MatrixCanonicalize.
543                * Other methods for redundancy checkings might be implemented later. See Anders' diss p.44.
544                * Note that in order to use cddlib a 0-th column has to be added to the matrix since cddlib expects
545                * each row to represent an inequality of type const+x1+...+xn <= 0. While computing the normals we come across
546                * the set \f$ \partial\mathcal{G} \f$ which we might store for later use. C.f p71 of journal
547                * As a result of this procedure the pointer facetPtr points to the first facet of the cone.
548                *
549                * Optionally, if the parameter bool compIntPoint is set to TRUE the method will also compute
550                * an interior point of the cone.
551                */
552                void getConeNormals(ideal const &I, bool compIntPoint=FALSE)
553                {
554#ifdef gfan_DEBUG
555                        std::cout << "*** Computing Inequalities... ***" << std::endl;
556#endif         
557                        //All variables go here - except ineq matrix and *v, see below
558                        int lengthGB=IDELEMS(I);        // # of polys in the groebner basis
559                        int pCompCount;                 // # of terms in a poly
560                        poly aktpoly;
561                        int numvar = pVariables;        // # of variables in a polynomial (or ring?)
562                        int leadexp[numvar];            // dirty hack of exp.vects
563                        int aktexp[numvar];
564                        int cols,rows;                  // will contain the dimensions of the ineq matrix - deprecated by
565                        dd_rowrange ddrows;
566                        dd_colrange ddcols;
567                        dd_rowset ddredrows;            // # of redundant rows in ddineq
568                        dd_rowset ddlinset;             // the opposite
569                        dd_rowindex ddnewpos;             // all to make dd_Canonicalize happy
570                        dd_NumberType ddnumb=dd_Integer; //Number type
571                        dd_ErrorType dderr=dd_NoError;  //
572                        // End of var declaration
573#ifdef gfan_DEBUG
574//                      cout << "The Groebner basis has " << lengthGB << " elements" << endl;
575//                      cout << "The current ring has " << numvar << " variables" << endl;
576#endif
577                        cols = numvar;
578               
579                        //Compute the # inequalities i.e. rows of the matrix
580                        rows=0; //Initialization
581                        for (int ii=0;ii<IDELEMS(I);ii++)
582                        {
583                                aktpoly=(poly)I->m[ii];
584                                rows=rows+pLength(aktpoly)-1;
585                        }
586#ifdef gfan_DEBUG
587//                      cout << "rows=" << rows << endl;
588//                      cout << "Will create a " << rows << " x " << cols << " matrix to store inequalities" << endl;
589#endif
590                        dd_rowrange aktmatrixrow=0;     // needed to store the diffs of the expvects in the rows of ddineq
591                        dd_set_global_constants();
592                        ddrows=rows;
593                        ddcols=cols;
594                        dd_MatrixPtr ddineq;            //Matrix to store the inequalities                     
595                        ddineq=dd_CreateMatrix(ddrows,ddcols+1); //The first col has to be 0 since cddlib checks for additive consts there
596               
597                        // We loop through each g\in GB and compute the resulting inequalities
598                        for (int i=0; i<IDELEMS(I); i++)
599                        {
600                                aktpoly=(poly)I->m[i];          //get aktpoly as i-th component of I
601                                pCompCount=pLength(aktpoly);    //How many terms does aktpoly consist of?
602#ifdef gfan_DEBUG
603//                              cout << "Poly No. " << i << " has " << pCompCount << " components" << endl;
604#endif
605               
606                                int *v=(int *)omAlloc((numvar+1)*sizeof(int));
607                                pGetExpV(aktpoly,v);    //find the exp.vect in v[1],...,v[n], use pNext(p)
608                               
609                                //Store leadexp for aktpoly
610                                for (int kk=0;kk<numvar;kk++)
611                                {
612                                        leadexp[kk]=v[kk+1];
613                                        //Since we need to know the difference of leadexp with the other expvects we do nothing here
614                                        //but compute the diff below
615                                }
616               
617                               
618                                while (pNext(aktpoly)!=NULL) //move to next term until NULL
619                                {
620                                        aktpoly=pNext(aktpoly);
621                                        pSetm(aktpoly);         //doesn't seem to help anything
622                                        pGetExpV(aktpoly,v);
623                                        for (int kk=0;kk<numvar;kk++)
624                                        {
625                                                aktexp[kk]=v[kk+1];
626                                                //ineq[aktmatrixrow][kk]=leadexp[kk]-aktexp[kk];        //dito
627                                                dd_set_si(ddineq->matrix[(dd_rowrange)aktmatrixrow][kk+1],leadexp[kk]-aktexp[kk]); //because of the 1st col being const 0
628                                        }
629                                        aktmatrixrow=aktmatrixrow+1;
630                                }//while
631               
632                        } //for
633               
634                        //Maybe add another row to contain the constraints of the standard simplex?
635
636#ifdef gfan_DEBUG
637//                      cout << "The inequality matrix is" << endl;
638//                      dd_WriteMatrix(stdout, ddineq);
639#endif
640
641                        // The inequalities are now stored in ddineq
642                        // Next we check for superflous rows
643                        ddredrows = dd_RedundantRows(ddineq, &dderr);
644                        if (dderr!=dd_NoError)                  // did an error occur?
645                        {
646                                dd_WriteErrorMessages(stderr,dderr);    //if so tell us
647                        } 
648#ifdef gfan_DEBUG
649                        else
650                        {
651                                cout << "Redundant rows: ";
652                                set_fwrite(stdout, ddredrows);          //otherwise print the redundant rows
653                        }//if dd_Error
654#endif
655                        //Remove reduntant rows here!
656                        dd_MatrixCanonicalize(&ddineq, &ddlinset, &ddredrows, &ddnewpos, &dderr);
657                        ddrows = ddineq->rowsize;       //Size of the matrix with redundancies removed
658                        ddcols = ddineq->colsize;
659                       
660                        //ddCreateMatrix(ddrows,ddcols+1);
661                        ddFacets = dd_CopyMatrix(ddineq);
662#ifdef gfan_DEBUG
663//                      cout << "Having removed redundancies, the normals now read:" << endl;
664//                      dd_WriteMatrix(stdout,ddineq);
665//                      cout << "Rows = " << ddrows << endl;
666//                      cout << "Cols = " << ddcols << endl;
667#endif
668                       
669                        /*Write the normals into class facet*/
670#ifdef gfan_DEBUG
671//                      cout << "Creating list of normals" << endl;
672#endif
673                        /*The pointer *fRoot should be the return value of this function*/
674                        //facet *fRoot = new facet();   //instantiate new facet
675                        //fRoot->setUCN(this->getUCN());
676                        //this->facetPtr = fRoot;               //set variable facetPtr of class gcone to first facet
677                        facet *fAct;                    //pointer to active facet
678                        //fAct = fRoot;                 //Seems to do the trick. fRoot and fAct have to point to the same adress!
679                        //std::cout << "fRoot = " << fRoot << ", fAct = " << fAct << endl;
680                        int numNonFlip=0;
681                        for (int kk = 0; kk<ddrows; kk++)
682                        {
683                                intvec *load = new intvec(this->numVars);       //intvec to store a single facet normal that will then be stored via setFacetNormal
684                                for (int jj = 1; jj <ddcols; jj++)
685                                {
686                                        double foo;
687                                        foo = mpq_get_d(ddineq->matrix[kk][jj]);
688#ifdef gfan_DEBUG
689//                                      std::cout << "fAct is " << foo << " at " << fAct << std::endl;
690#endif
691                                        (*load)[jj-1] = (int)foo;               //store typecasted entry at pos jj-1 of load           
692                                }//for (int jj = 1; jj <ddcols; jj++)
693                               
694                                /*Quick'n'dirty hack for flippability*/ 
695                                bool isFlip=FALSE;
696                                                               
697                                for (int jj = 0; jj<load->length(); jj++)
698                                {
699                                        intvec *ivCanonical = new intvec(load->length());
700                                        (*ivCanonical)[jj]=1;
701//                                      cout << "dotProd=" << dotProduct(*load,*ivCanonical) << endl;
702                                        if (dotProduct(*load,*ivCanonical)<0)   
703                                        //if (ivMult(load,ivCanonical)<0)
704                                        {
705                                                isFlip=TRUE;
706                                                break;  //URGHS
707                                        }
708                                }       
709                                if (isFlip==FALSE)
710                                {
711                                        this->numFacets++;
712                                        numNonFlip++;
713                                        if(this->numFacets==1)
714                                        {
715                                                facet *fRoot = new facet();
716                                                this->facetPtr = fRoot;
717                                                fAct = fRoot;
718                                               
719                                        }
720                                        else
721                                        {
722                                                fAct->next = new facet();
723                                                fAct = fAct->next;
724                                        }
725                                        fAct->isFlippable=FALSE;
726                                        fAct->setFacetNormal(load);
727                                        fAct->setUCN(this->getUCN());
728#ifdef gfan_DEBUG
729                                        cout << "Marking facet (";
730                                        load->show(1,0);
731                                        cout << ") as non flippable" << endl;                           
732#endif
733                                }
734                                else
735                                {       /*Now load should be full and we can call setFacetNormal*/                                     
736                                        this->numFacets++;
737                                        if(this->numFacets==1)
738                                        {
739                                                facet *fRoot = new facet();
740                                                this->facetPtr = fRoot;
741                                                fAct = fRoot;
742                                        }
743                                        else
744                                        {
745                                                fAct->next = new facet();
746                                                fAct = fAct->next;
747                                        }
748                                        fAct->isFlippable=TRUE;
749                                        fAct->setFacetNormal(load);
750                                        fAct->setUCN(this->getUCN());                                   
751                                }//if (isFlippable==FALSE)
752                                //delete load;                         
753                        }//for (int kk = 0; kk<ddrows; kk++)
754                       
755                        //In cases like I=<x-1,y-1> there are only non-flippable facets...
756                        if(numNonFlip==this->numFacets)
757                        {                                       
758                                cerr << "Only non-flippable facets. Terminating..." << endl;
759                        }
760                       
761                        /*
762                        Now we should have a linked list containing the facet normals of those facets that are
763                        -irredundant
764                        -flipable
765                        Adressing is done via *facetPtr
766                        */
767                       
768                        if (compIntPoint==TRUE)
769                        {
770                                intvec *iv = new intvec(this->numVars);
771                                interiorPoint(ddineq, *iv);     //NOTE ddineq contains non-flippable facets
772                                this->setIntPoint(iv);  //stores the interior point in gcone::ivIntPt
773                                //delete iv;
774                        }
775                       
776                        //Compute the number of facets
777                        // wrong because ddineq->rowsize contains only irredundant facets. There can still be
778                        // non-flippable ones!
779                        //this->numFacets=ddineq->rowsize;
780                       
781                        //Clean up but don't delete the return value! (Whatever it will turn out to be)                 
782                        //dd_FreeMatrix(ddineq);
783                        //set_free(ddredrows);
784                        //free(ddnewpos);
785                        //set_free(ddlinset);
786                        //NOTE Commented out. Solved the bug that after facet2Matrix there were facets lost
787                        //THIS SUCKS
788                        //dd_free_global_constants();
789
790                }//method getConeNormals(ideal I)       
791               
792                /** \brief Compute the (codim-2)-facets of a given cone
793                * This method is used during noRevS
794                */
795                void getCodim2Normals(gcone const &gc)
796                {
797                        //this->facetPtr->codim2Ptr = new facet(2);     //instantiate a (codim-2)-facet
798                        facet *fAct;
799                        fAct = this->facetPtr;         
800                        facet *codim2Act;
801                        //codim2Act = this->facetPtr->codim2Ptr;
802                       
803                        dd_set_global_constants();
804                       
805                        dd_MatrixPtr ddineq,P,ddakt;
806                        dd_rowset impl_linset, redset;
807                        dd_ErrorType err;
808                        dd_rowindex newpos;             
809
810                        //ddineq = facets2Matrix(gc);   //get a matrix representation of the cone
811                        ddineq = dd_CopyMatrix(gc.ddFacets);
812                               
813                        /*Now set appropriate linearity*/
814                        dd_PolyhedraPtr ddpolyh;
815                        for (int ii=0; ii<this->numFacets; ii++)                       
816                        {                               
817                                ddakt = dd_CopyMatrix(ddineq);
818                                ddakt->representation=dd_Inequality;
819                                set_addelem(ddakt->linset,ii+1);                               
820                                dd_MatrixCanonicalize(&ddakt, &impl_linset, &redset, &newpos, &err);                   
821                                       
822#ifdef gfan_DEBUG
823//                              cout << "Codim2 matrix"<<endl;
824//                              dd_WriteMatrix(stdout,ddakt);
825#endif
826                                ddpolyh=dd_DDMatrix2Poly(ddakt, &err);
827                                P=dd_CopyGenerators(ddpolyh);                           
828#ifdef gfan_DEBUG
829//                              cout << "Codim2 facet:" << endl;
830//                                      dd_WriteMatrix(stdout,P);
831//                              cout << endl;
832#endif
833                                       
834                                /* We loop through each row of P
835                                * normalize it by making all entries integer ones
836                                * and add the resulting vector to the int matrix facet::codim2Facets
837                                */
838                                for (int jj=1;jj<=P->rowsize;jj++)
839                                {                                       
840                                        fAct->numCodim2Facets++;
841                                        if(fAct->numCodim2Facets==1)                                   
842                                        {                                               
843                                                fAct->codim2Ptr = new facet(2);                                         
844                                                codim2Act = fAct->codim2Ptr;
845                                        }
846                                        else
847                                        {
848                                                codim2Act->next = new facet(2);
849                                                codim2Act = codim2Act->next;
850                                        }
851                                        intvec *n = new intvec(this->numVars);
852                                        makeInt(P,jj,*n);
853                                        codim2Act->setFacetNormal(n);
854                                        delete n;                                       
855                                }               
856                                /*We check whether the facet spanned by the codim-2 facets
857                                * intersects with the positive orthant. Otherwise we define this
858                                * facet to be non-flippable
859                                */
860                                intvec *iv_intPoint = new intvec(this->numVars);
861                                dd_MatrixPtr shiftMatrix;
862                                dd_MatrixPtr intPointMatrix;
863                                shiftMatrix = dd_CreateMatrix(this->numVars,this->numVars+1);
864                                for(int kk=0;kk<this->numVars;kk++)
865                                {
866                                        dd_set_si(shiftMatrix->matrix[kk][0],1);
867                                        dd_set_si(shiftMatrix->matrix[kk][kk+1],1);
868                                }
869                                intPointMatrix=dd_MatrixAppend(ddakt,shiftMatrix);
870                                //dd_WriteMatrix(stdout,intPointMatrix);
871                                interiorPoint(intPointMatrix,*iv_intPoint);
872                                for(int ll=0;ll<this->numVars;ll++)
873                                {
874                                        if( (*iv_intPoint)[ll] < 0 )
875                                        {
876                                                fAct->isFlippable=FALSE;
877                                                break;
878                                        }
879                                }
880                                /*End of check*/                                       
881                                fAct = fAct->next;     
882                                dd_FreeMatrix(ddakt);
883                                dd_FreePolyhedra(ddpolyh);
884                        }//while
885                }
886               
887                /** \brief Compute the Groebner Basis on the other side of a shared facet
888                *
889                * Implements algorithm 4.3.2 from Anders' thesis.
890                * As shown there it is not necessary to compute an interior point. The knowledge of the facet normal
891                * suffices. A term \f$ x^\gamma \f$ of \f$ g \f$ is in \f$  in_\omega(g) \f$ iff \f$ \gamma - leadexp(g)\f$
892                * is parallel to \f$ leadexp(g) \f$
893                * Parallelity is checked using basic linear algebra. See gcone::isParallel.
894                * Other possibilities include computing the rank of the matrix consisting of the vectors in question and
895                * computing an interior point of the facet and taking all terms having the same weight with respect
896                * to this interior point.
897                *\param ideal, facet
898                * Input: a marked,reduced Groebner basis and a facet
899                */
900                void flip(ideal gb, facet *f)           //Compute "the other side"
901                {                       
902                        intvec *fNormal = new intvec(this->numVars);    //facet normal, check for parallelity                   
903                        fNormal = f->getFacetNormal();  //read this->fNormal;
904#ifdef gfan_DEBUG
905                        //std::cout << "===" << std::endl;
906                        std::cout << "running gcone::flip" << std::endl;
907                        std::cout << "flipping UCN " << this->getUCN() << endl;
908                        for(int ii=0;ii<IDELEMS(gb);ii++)
909                        {
910                                pWrite((poly)gb->m[ii]);
911                        }
912                        cout << "over facet (";
913                        fNormal->show(1,0);
914                        cout << ") with UCN " << f->getUCN();
915                        std::cout << std::endl;
916#endif                         
917                        /*1st step: Compute the initial ideal*/
918                        poly initialFormElement[IDELEMS(gb)];   //array of #polys in GB to store initial form
919                        ideal initialForm=idInit(IDELEMS(gb),this->gcBasis->rank);
920                        poly aktpoly;
921                        intvec *check = new intvec(this->numVars);      //array to store the difference of LE and v
922                       
923                        for (int ii=0;ii<IDELEMS(gb);ii++)
924                        {
925                                aktpoly = (poly)gb->m[ii];                                                             
926                                int *v=(int *)omAlloc((this->numVars+1)*sizeof(int));
927                                int *leadExpV=(int *)omAlloc((this->numVars+1)*sizeof(int));
928                                pGetExpV(aktpoly,leadExpV);     //find the leading exponent in leadExpV[1],...,leadExpV[n], use pNext(p)
929                                initialFormElement[ii]=pHead(aktpoly);
930                               
931                                while(pNext(aktpoly)!=NULL)     /*loop trough terms and check for parallelity*/
932                                {
933                                        aktpoly=pNext(aktpoly); //next term
934                                        pSetm(aktpoly);
935                                        pGetExpV(aktpoly,v);           
936                                        /* Convert (int)v into (intvec)check */                 
937                                        for (int jj=0;jj<this->numVars;jj++)
938                                        {
939                                                //cout << "v["<<jj+1<<"]="<<v[jj+1]<<endl;
940                                                //cout << "leadExpV["<<jj+1<<"]="<<leadExpV[jj+1]<<endl;
941                                                (*check)[jj]=v[jj+1]-leadExpV[jj+1];
942                                        }
943#ifdef gfan_DEBUG
944//                                      cout << "check=";                       
945//                                      check->show();
946//                                      cout << endl;
947#endif
948                                        //TODO why not *check, *fNormal????
949                                        if (isParallel(*check,*fNormal)) //pass *check when
950                                        {
951//                                              cout << "Parallel vector found, adding to initialFormElement" << endl;                 
952                                                initialFormElement[ii] = pAdd(pCopy(initialFormElement[ii]),(poly)pHead(aktpoly));
953                                        }                                               
954                                }//while
955#ifdef gfan_DEBUG
956                                cout << "Initial Form=";                               
957                                pWrite(initialFormElement[ii]);
958                                cout << "---" << endl;
959#endif
960                                /*Now initialFormElement must be added to (ideal)initialForm */
961                                initialForm->m[ii]=initialFormElement[ii];
962                        }//for                 
963#ifdef gfan_DEBUG
964/*                      cout << "Initial ideal is: " << endl;
965                        idShow(initialForm);
966                        //f->printFlipGB();*/
967//                      cout << "===" << endl;
968#endif
969                        //delete check;
970                       
971                        /*2nd step: lift initial ideal to a GB of the neighbouring cone using minus alpha as weight*/
972                        /*Substep 2.1
973                        compute $G_{-\alpha}(in_v(I))
974                        see journal p. 66
975                        NOTE Check for different rings. Prolly it will not always be necessary to add a weight, if the
976                        srcRing already has a weighted ordering
977                        */
978                        ring srcRing=currRing;
979                        ring tmpRing;
980                       
981                        if( (srcRing->order[0]!=ringorder_a))
982                        {
983                                tmpRing=rCopyAndAddWeight(srcRing,ivNeg(fNormal));
984                        }
985                        else
986                        {
987                                tmpRing=rCopy0(srcRing);
988                                int length=fNormal->length();
989                                int *A=(int *)omAlloc0(length*sizeof(int));
990                                for(int jj=0;jj<length;jj++)
991                                {
992                                        A[jj]=-(*fNormal)[jj];
993                                }
994                                omFree(tmpRing->wvhdl[0]);
995                                tmpRing->wvhdl[0]=(int*)A;
996                                tmpRing->block1[0]=length;
997                                rComplete(tmpRing);     
998                        }
999                        rChangeCurrRing(tmpRing);
1000                       
1001                        //rWrite(currRing); cout << endl;
1002                       
1003                        ideal ina;                     
1004                        ina=idrCopyR(initialForm,srcRing);                     
1005#ifdef gfan_DEBUG
1006//                      cout << "ina=";
1007//                      idShow(ina); cout << endl;
1008#endif
1009                        ideal H;
1010                        //H=kStd(ina,NULL,isHomog,NULL);        //we know it is homogeneous
1011                        H=kStd(ina,NULL,testHomog,NULL);
1012                        idSkipZeroes(H);
1013#ifdef gfan_DEBUG
1014//                      cout << "H="; idShow(H); cout << endl;
1015#endif
1016                        /*Substep 2.2
1017                        do the lifting and mark according to H
1018                        */
1019                        rChangeCurrRing(srcRing);
1020                        ideal srcRing_H;
1021                        ideal srcRing_HH;                       
1022                        srcRing_H=idrCopyR(H,tmpRing);
1023#ifdef gfan_DEBUG
1024//                      cout << "srcRing_H = ";
1025//                      idShow(srcRing_H); cout << endl;
1026#endif
1027                        srcRing_HH=ffG(srcRing_H,this->gcBasis);               
1028#ifdef gfan_DEBUG
1029//                      cout << "srcRing_HH = ";
1030//                      idShow(srcRing_HH); cout << endl;
1031#endif
1032                        /*Substep 2.2.1
1033                        Mark according to G_-\alpha
1034                        Here we have a minimal basis srcRing_HH. In order to turn this basis into a reduced basis
1035                        we have to compute an interior point of C(srcRing_HH). For this we need to know the cone
1036                        represented by srcRing_HH MARKED ACCORDING TO G_{-\alpha}
1037                        Thus we check whether the leading monomials of srcRing_HH and srcRing_H coincide. If not we
1038                        compute the difference accordingly
1039                        */
1040                        dd_set_global_constants();
1041                        bool markingsAreCorrect=FALSE;
1042                        dd_MatrixPtr intPointMatrix;
1043                        int iPMatrixRows=0;
1044                        dd_rowrange aktrow=0;                   
1045                        for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
1046                        {
1047                                poly aktpoly=(poly)srcRing_HH->m[ii];
1048                                iPMatrixRows = iPMatrixRows+pLength(aktpoly)-1;
1049                        }
1050                        /* additionally one row for the standard-simplex and another for a row that becomes 0 during
1051                        construction of the differences
1052                        */
1053                        intPointMatrix = dd_CreateMatrix(iPMatrixRows+10,this->numVars+1);
1054                        intPointMatrix->numbtype=dd_Integer;    //NOTE: DO NOT REMOVE OR CHANGE TO dd_Rational
1055                       
1056                        for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
1057                        {
1058                                markingsAreCorrect=FALSE;       //crucial to initialise here
1059                                poly aktpoly=srcRing_HH->m[ii];
1060                                /*Comparison of leading monomials is done via exponent vectors*/
1061                                for (int jj=0;jj<IDELEMS(H);jj++)
1062                                {
1063                                        int *src_ExpV = (int *)omAlloc((this->numVars+1)*sizeof(int));
1064                                        int *dst_ExpV = (int *)omAlloc((this->numVars+1)*sizeof(int));
1065                                        pGetExpV(aktpoly,src_ExpV);
1066                                        rChangeCurrRing(tmpRing);       //this ring change is crucial!
1067                                        pGetExpV(pCopy(H->m[ii]),dst_ExpV);
1068                                        rChangeCurrRing(srcRing);
1069                                        bool expVAreEqual=TRUE;
1070                                        for (int kk=1;kk<=this->numVars;kk++)
1071                                        {
1072#ifdef gfan_DEBUG
1073                                                //cout << src_ExpV[kk] << "," << dst_ExpV[kk] << endl;
1074#endif
1075                                                if (src_ExpV[kk]!=dst_ExpV[kk])
1076                                                {
1077                                                        expVAreEqual=FALSE;
1078                                                }
1079                                        }                                       
1080                                        //if (*src_ExpV == *dst_ExpV)
1081                                        if (expVAreEqual==TRUE)
1082                                        {
1083                                                markingsAreCorrect=TRUE; //everything is fine
1084#ifdef gfan_DEBUG
1085//                                              cout << "correct markings" << endl;
1086#endif
1087                                        }//if (pHead(aktpoly)==pHead(H->m[jj])
1088                                        delete src_ExpV;
1089                                        delete dst_ExpV;
1090                                }//for (int jj=0;jj<IDELEMS(H);jj++)
1091                               
1092                                int *v=(int *)omAlloc((this->numVars+1)*sizeof(int));
1093                                int *leadExpV=(int *)omAlloc((this->numVars+1)*sizeof(int));
1094                                if (markingsAreCorrect==TRUE)
1095                                {
1096                                        pGetExpV(aktpoly,leadExpV);
1097                                }
1098                                else
1099                                {
1100                                        rChangeCurrRing(tmpRing);
1101                                        pGetExpV(pHead(H->m[ii]),leadExpV); //We use H->m[ii] as leading monomial
1102                                        rChangeCurrRing(srcRing);
1103                                }
1104                                /*compute differences of the expvects*/                         
1105                                while (pNext(aktpoly)!=NULL)
1106                                {
1107                                        /*The following if-else-block makes sure the first term (i.e. the wrongly marked term)
1108                                        is not omitted when computing the differences*/
1109                                        if(markingsAreCorrect==TRUE)
1110                                        {
1111                                                aktpoly=pNext(aktpoly);
1112                                                pGetExpV(aktpoly,v);
1113                                        }
1114                                        else
1115                                        {
1116                                                pGetExpV(pHead(aktpoly),v);
1117                                                markingsAreCorrect=TRUE;
1118                                        }
1119
1120                                        for (int jj=0;jj<this->numVars;jj++)
1121                                        {                               
1122                                                /*Store into ddMatrix*/                                                         
1123                                                dd_set_si(intPointMatrix->matrix[aktrow][jj+1],leadExpV[jj+1]-v[jj+1]);
1124                                        }
1125                                        aktrow +=1;
1126                                }
1127                                delete v;
1128                                delete leadExpV;
1129                        }//for (int ii=0;ii<IDELEMS(srcRing_HH);ii++)
1130                        /*Now we add the constraint for the standard simplex*/
1131                        /*NOTE:Might actually work without the standard simplex*/
1132                        dd_set_si(intPointMatrix->matrix[aktrow][0],-1);
1133                        for (int jj=1;jj<=this->numVars;jj++)
1134                        {
1135                                dd_set_si(intPointMatrix->matrix[aktrow][jj],1);
1136                        }
1137#ifdef gfan_DEBUG
1138//                      dd_WriteMatrix(stdout,intPointMatrix);
1139#endif
1140                        intvec *iv_weight = new intvec(this->numVars);
1141                        interiorPoint(intPointMatrix, *iv_weight);      //iv_weight now contains the interior point
1142                        dd_FreeMatrix(intPointMatrix);
1143                        dd_free_global_constants();
1144                       
1145                        /*Step 3
1146                        turn the minimal basis into a reduced one
1147                        */
1148                        //ring dstRing=rCopyAndAddWeight(tmpRing,iv_weight);   
1149                       
1150                        // NOTE May assume that at this point srcRing already has 3 blocks of orderins, starting with a
1151                        // Thus:
1152                        //ring dstRing=rCopyAndChangeWeight(srcRing,iv_weight);
1153                        //cout << "PLING" << endl;
1154                        /*ring dstRing=rCopy0(srcRing);
1155                        for (int ii=0;ii<this->numVars;ii++)
1156                        {                               
1157                                dstRing->wvhdl[0][ii]=(*iv_weight)[ii];                         
1158                        }*/
1159                        ring dstRing=rCopy0(tmpRing);
1160                        int length=iv_weight->length();
1161                        int *A=(int *)omAlloc0(length*sizeof(int));
1162                        for(int jj=0;jj<length;jj++)
1163                        {
1164                                A[jj]=(*iv_weight)[jj];
1165                        }
1166                        dstRing->wvhdl[0]=(int*)A;
1167                        rComplete(dstRing);                                     
1168                        rChangeCurrRing(dstRing);
1169                       
1170#ifdef gfan_DEBUG
1171                        rWrite(dstRing); cout << endl;
1172#endif
1173                        ideal dstRing_I;                       
1174                        dstRing_I=idrCopyR(srcRing_HH,srcRing);                 
1175                        //validOpts<1>=TRUE;
1176#ifdef gfan_DEBUG
1177                        //idShow(dstRing_I);
1178#endif                 
1179                        BITSET save=test;
1180                        test|=Sy_bit(OPT_REDSB);
1181                        test|=Sy_bit(6);        //OPT_DEBUG
1182                        ideal tmpI;
1183                        tmpI = idrCopyR(this->inputIdeal,this->baseRing);                               
1184                        dstRing_I=kStd(tmpI,NULL,testHomog,NULL);                                       
1185                        kInterRed(dstRing_I);
1186                        idSkipZeroes(dstRing_I);
1187                        test=save;
1188                        /*End of step 3 - reduction*/
1189                       
1190                        f->setFlipGB(dstRing_I);//store the flipped GB
1191                        f->flipRing=rCopy(dstRing);     //store the ring on the other side
1192//#ifdef gfan_DEBUG
1193                        cout << "Flipped GB is UCN " << counter+1 << ":" << endl;
1194                        f->printFlipGB();
1195                        cout << endl;
1196//#endif                       
1197                        rChangeCurrRing(srcRing);       //return to the ring we started the computation of flipGB in
1198                }//void flip(ideal gb, facet *f)
1199                               
1200                /** \brief Compute the remainder of a polynomial by a given ideal
1201                *
1202                * Compute \f$ f^{\mathcal{G}} \f$
1203                * Algorithm is taken from Cox, Little, O'Shea, IVA 2nd Ed. p 62
1204                * However, since we are only interested in the remainder, there is no need to
1205                * compute the factors \f$ a_i \f$
1206                */
1207                //NOTE: Should be replaced by kNF or kNF2
1208                poly restOfDiv(poly const &f, ideal const &I)
1209                {
1210//                      cout << "Entering restOfDiv" << endl;
1211                        poly p=f;
1212                        //pWrite(p);                   
1213                        poly r=NULL;    //The zero polynomial
1214                        int ii;
1215                        bool divOccured;
1216                       
1217                        while (p!=NULL)
1218                        {
1219                                ii=1;
1220                                divOccured=FALSE;
1221                               
1222                                while( (ii<=IDELEMS(I) && (divOccured==FALSE) ))
1223                                {                                       
1224                                        if (pDivisibleBy(I->m[ii-1],p)) //does LM(I->m[ii]) divide LM(p) ?
1225                                        {                                               
1226                                                poly step1,step2,step3;
1227                                                //cout << "dividing "; pWrite(pHead(p));cout << "by ";pWrite(pHead(I->m[ii-1])); cout << endl;
1228                                                step1 = pDivideM(pHead(p),pHead(I->m[ii-1]));
1229                                                //cout << "LT(p)/LT(f_i)="; pWrite(step1); cout << endl;                               
1230                                                step2 = ppMult_qq(step1, I->m[ii-1]);                                           
1231                                                step3 = pSub(pCopy(p), step2);
1232                                                //p=pSub(p,pMult( pDivide(pHead(p),pHead(I->m[ii])), I->m[ii]));                       
1233                                                //pSetm(p);
1234                                                pSort(step3); //must be here, otherwise strange behaviour with many +o+o+o+o+ terms
1235                                                p=step3;
1236                                                //pWrite(p);                                           
1237                                                divOccured=TRUE;
1238                                        }
1239                                        else
1240                                        {
1241                                                ii += 1;
1242                                        }//if (pLmDivisibleBy(I->m[ii],p,currRing))
1243                                }//while( (ii<IDELEMS(I) && (divOccured==FALSE) ))
1244                                if (divOccured==FALSE)
1245                                {
1246                                        //cout << "TICK 5" << endl;
1247                                        r=pAdd(pCopy(r),pHead(p));
1248                                        pSetm(r);
1249                                        pSort(r);
1250                                        //cout << "r="; pWrite(r); cout << endl;
1251                                       
1252                                        if (pLength(p)!=1)
1253                                        {
1254                                                p=pSub(pCopy(p),pHead(p));      //Here it may occur that p=0 instead of p=NULL
1255                                        }
1256                                        else
1257                                        {
1258                                                p=NULL; //Hack to correct this situation                                               
1259                                        }                                       
1260                                        //cout << "p="; pWrite(p);
1261                                }//if (divOccured==FALSE)
1262                        }//while (p!=0)
1263                        return r;
1264                }//poly restOfDiv(poly const &f, ideal const &I)
1265               
1266                /** \brief Compute \f$ f-f^{\mathcal{G}} \f$
1267                */
1268                //NOTE: use kNF or kNF2 instead of restOfDivision
1269                ideal ffG(ideal const &H, ideal const &G)
1270                {
1271//                      cout << "Entering ffG" << endl;
1272                        int size=IDELEMS(H);
1273                        ideal res=idInit(size,1);
1274                        poly temp1, temp2, temp3;       //polys to temporarily store values for pSub
1275                        for (int ii=0;ii<size;ii++)
1276                        {
1277                                res->m[ii]=restOfDiv(H->m[ii],G);
1278                                //res->m[ii]=kNF(G, NULL,H->m[ii]);
1279                                temp1=H->m[ii];
1280                                temp2=res->m[ii];                               
1281                                temp3=pSub(temp1, temp2);
1282                                res->m[ii]=temp3;
1283                                //res->m[ii]=pSub(temp1,temp2); //buggy
1284                                //pSort(res->m[ii]);
1285                                //pSetm(res->m[ii]);
1286                                //cout << "res->m["<<ii<<"]=";pWrite(res->m[ii]);                                               
1287                        }                       
1288                        return res;
1289                }
1290               
1291                /** \brief Compute a Groebner Basis
1292                *
1293                * Computes the Groebner basis and stores the result in gcone::gcBasis
1294                *\param ideal
1295                *\return void
1296                */
1297                void getGB(ideal const &inputIdeal)
1298                {
1299                        ideal gb;
1300                        gb=kStd(inputIdeal,NULL,testHomog,NULL);
1301                        idSkipZeroes(gb);
1302                        this->gcBasis=gb;       //write the GB into gcBasis
1303                }//void getGB
1304               
1305                /** \brief The Generic Groebner Walk due to FJLT
1306                * Needed for computing the search facet
1307                */
1308                ideal GenGrbWlk(ideal, ideal)
1309                {
1310                }//GGW
1311               
1312                /** \brief Compute the negative of a given intvec
1313                */             
1314                intvec *ivNeg(const intvec *iv)
1315                {
1316                        intvec *res = new intvec(iv->length());
1317                        res=ivCopy(iv);
1318                        *res *= (int)-1;
1319                        //for(int ii=0;ii<this->numVars;ii++)
1320                        //{                     
1321                                //(res)[ii] = (*res[ii])*(int)(-1);
1322                        //}
1323                        //res->show(1,0);                       
1324                        return res;
1325                }
1326
1327
1328                /** \brief Compute the dot product of two intvecs
1329                *
1330                */
1331                int dotProduct(intvec const &iva, intvec const &ivb)                           
1332                {
1333                        //intvec iva=a;
1334                        //intvec ivb=b;
1335                        int res=0;
1336                        for (int i=0;i<this->numVars;i++)
1337                        {
1338                                res = res+(iva[i]*ivb[i]);
1339                        }
1340                        return res;
1341                }//int dotProduct
1342
1343                /** \brief Check whether two intvecs are parallel
1344                *
1345                * \f$ \alpha\parallel\beta\Leftrightarrow\langle\alpha,\beta\rangle^2=\langle\alpha,\alpha\rangle\langle\beta,\beta\rangle \f$
1346                */
1347                bool isParallel(intvec const &a, intvec const &b)
1348                {                       
1349                        int lhs,rhs;
1350                        lhs=dotProduct(a,b)*dotProduct(a,b);
1351                        rhs=dotProduct(a,a)*dotProduct(b,b);
1352                        //cout << "LHS="<<lhs<<", RHS="<<rhs<<endl;
1353                        if (lhs==rhs)
1354                        {
1355                                return TRUE;
1356                        }
1357                        else
1358                        {
1359                                return FALSE;
1360                        }
1361                }//bool isParallel
1362               
1363                /** \brief Compute an interior point of a given cone
1364                * Result will be written into intvec iv.
1365                * Any rational point is automatically converted into an integer.
1366                */
1367                void interiorPoint(dd_MatrixPtr const &M, intvec &iv) //no const &M here since we want to remove redundant rows
1368                {
1369                        dd_LPPtr lp,lpInt;
1370                        dd_ErrorType err=dd_NoError;
1371                        dd_LPSolverType solver=dd_DualSimplex;
1372                        dd_LPSolutionPtr lpSol=NULL;
1373                        dd_rowset ddlinset,ddredrows;   //needed for dd_FindRelativeInterior
1374                        dd_rowindex ddnewpos;
1375                        dd_NumberType numb;     
1376                        //M->representation=dd_Inequality;
1377                        //M->objective-dd_LPMin;  //Not sure whether this is needed
1378                       
1379                        //NOTE: Make this n-dimensional!
1380                        //dd_set_si(M->rowvec[0],1);dd_set_si(M->rowvec[1],1);dd_set_si(M->rowvec[2],1);
1381                                                                       
1382                        //dd_MatrixCanonicalize(&M, &ddlinset, &ddredrows, &ddnewpos, &err);
1383                        //if (err!=dd_NoError){cout << "Error during dd_MatrixCanonicalize" << endl;}
1384                        //cout << "Tick 2" << endl;
1385                        //dd_WriteMatrix(stdout,M);
1386                       
1387                        lp=dd_Matrix2LP(M, &err);
1388                        if (err!=dd_NoError){cout << "Error during dd_Matrix2LP in gcone::interiorPoint" << endl;}                     
1389                        if (lp==NULL){cout << "LP is NULL" << endl;}
1390#ifdef gfan_DEBUG
1391//                      dd_WriteLP(stdout,lp);
1392#endif 
1393                                       
1394                        lpInt=dd_MakeLPforInteriorFinding(lp);
1395                        if (err!=dd_NoError){cout << "Error during dd_MakeLPForInteriorFinding in gcone::interiorPoint" << endl;}
1396#ifdef gfan_DEBUG
1397//                      dd_WriteLP(stdout,lpInt);
1398#endif                 
1399
1400                        dd_FindRelativeInterior(M,&ddlinset,&ddredrows,&lpSol,&err);
1401                        if (err!=dd_NoError)
1402                        {
1403                                cout << "Error during dd_FindRelativeInterior in gcone::interiorPoint" << endl;
1404                                dd_WriteErrorMessages(stdout, err);
1405                        }
1406                       
1407                        //dd_LPSolve(lpInt,solver,&err);        //This will not result in a point from the relative interior
1408                        if (err!=dd_NoError){cout << "Error during dd_LPSolve" << endl;}
1409                                                                       
1410                        //lpSol=dd_CopyLPSolution(lpInt);
1411                        if (err!=dd_NoError){cout << "Error during dd_CopyLPSolution" << endl;}                 
1412#ifdef gfan_DEBUG
1413                        cout << "Interior point: ";
1414                        for (int ii=1; ii<(lpSol->d)-1;ii++)
1415                        {
1416                                dd_WriteNumber(stdout,lpSol->sol[ii]);
1417                        }
1418                        cout << endl;
1419#endif
1420                       
1421                        //NOTE The following strongly resembles parts of makeInt.
1422                        //Maybe merge sometimes
1423                        mpz_t kgV; mpz_init(kgV);
1424                        mpz_set_str(kgV,"1",10);
1425                        mpz_t den; mpz_init(den);
1426                        mpz_t tmp; mpz_init(tmp);
1427                        mpq_get_den(tmp,lpSol->sol[1]);
1428                        for (int ii=1;ii<(lpSol->d)-1;ii++)
1429                        {
1430                                mpq_get_den(den,lpSol->sol[ii+1]);
1431                                mpz_lcm(kgV,tmp,den);
1432                                mpz_set(tmp, kgV);
1433                        }
1434                        mpq_t qkgV;
1435                        mpq_init(qkgV);
1436                        mpq_set_z(qkgV,kgV);
1437                        for (int ii=1;ii<(lpSol->d)-1;ii++)
1438                        {
1439                                mpq_t product;
1440                                mpq_init(product);
1441                                mpq_mul(product,qkgV,lpSol->sol[ii]);
1442                                iv[ii-1]=(int)mpz_get_d(mpq_numref(product));
1443                                mpq_clear(product);
1444                        }
1445#ifdef gfan_DEBUG
1446//                      iv.show();
1447//                      cout << endl;
1448#endif
1449                        mpq_clear(qkgV);
1450                        mpz_clear(tmp);
1451                        mpz_clear(den);
1452                        mpz_clear(kgV);                 
1453                       
1454                        dd_FreeLPSolution(lpSol);
1455                        dd_FreeLPData(lpInt);
1456                        dd_FreeLPData(lp);
1457                        set_free(ddlinset);
1458                        set_free(ddredrows);                   
1459                       
1460                }//void interiorPoint(dd_MatrixPtr const &M)
1461               
1462                /** \brief Copy a ring and add a weighted ordering in first place
1463                *
1464                */
1465                ring rCopyAndAddWeight(ring const &r, intvec const *ivw)                               
1466                {
1467                        ring res=rCopy0(r);
1468                        int jj;
1469                       
1470                        omFree(res->order);
1471                        res->order =(int *)omAlloc0(4*sizeof(int));
1472                        omFree(res->block0);
1473                        res->block0=(int *)omAlloc0(4*sizeof(int));
1474                        omFree(res->block1);
1475                        res->block1=(int *)omAlloc0(4*sizeof(int));
1476                        omfree(res->wvhdl);
1477                        res->wvhdl =(int **)omAlloc0(4*sizeof(int**));
1478                       
1479                        res->order[0]=ringorder_a;
1480                        res->block0[0]=1;
1481                        res->block1[0]=res->N;;
1482                        res->order[1]=ringorder_dp;     //basically useless, since that should never be used                   
1483                        res->block0[1]=1;
1484                        res->block1[1]=res->N;;
1485                        res->order[2]=ringorder_C;
1486
1487                        int length=ivw->length();
1488                        int *A=(int *)omAlloc0(length*sizeof(int));
1489                        for (jj=0;jj<length;jj++)
1490                        {                               
1491                                A[jj]=(*ivw)[jj];                               
1492                        }                       
1493                        res->wvhdl[0]=(int *)A;
1494                        res->block1[0]=length;
1495                       
1496                        rComplete(res);
1497                        return res;
1498                }//rCopyAndAdd
1499               
1500                ring rCopyAndChangeWeight(ring const &r, intvec *ivw)
1501                {
1502                        ring res=rCopy0(currRing);
1503                        rComplete(res);
1504                        rSetWeightVec(res,(int64*)ivw);
1505                        //rChangeCurrRing(rnew);
1506                        return res;
1507                }
1508               
1509                /** \brief Checks whether a given facet is a search facet
1510                * Determines whether a given facet of a cone is the search facet of a neighbouring cone
1511                * This is done in the following way:
1512                * We loop through all facets of the cone and find the "smallest" facet, i.e. the unique facet
1513                * that is first crossed during the generic walk.
1514                * We then check whether the fNormal of this facet is parallel to the fNormal of our testfacet.
1515                * If this is the case, then our facet is indeed a search facet and TRUE is retuned.
1516                */
1517                bool isSearchFacet(gcone &gcTmp, facet *testfacet)
1518                {                               
1519                        ring actRing=currRing;
1520                        facet *facetPtr=(facet*)gcTmp.facetPtr;                 
1521                        facet *fMin=new facet(*facetPtr);       //Pointer to the "minimal" facet
1522                        //facet *fMin = new facet(tmpcone.facetPtr);
1523                        //fMin=tmpcone.facetPtr;                //Initialise to first facet of tmpcone
1524                        facet *fAct;    //Ptr to alpha_i
1525                        facet *fCmp;    //Ptr to alpha_j
1526                        fAct = fMin;
1527                        fCmp = fMin->next;                             
1528                       
1529                        rChangeCurrRing(this->rootRing);        //because we compare the monomials in the rootring                     
1530                        poly p=pInit();
1531                        poly q=pInit();
1532                        intvec *alpha_i = new intvec(this->numVars);                   
1533                        intvec *alpha_j = new intvec(this->numVars);
1534                        intvec *sigma = new intvec(this->numVars);
1535                        sigma=gcTmp.getIntPoint();
1536                       
1537                        int *u=(int *)omAlloc((this->numVars+1)*sizeof(int));
1538                        int *v=(int *)omAlloc((this->numVars+1)*sizeof(int));
1539                        u[0]=0; v[0]=0;
1540                        int weight1,weight2;
1541                        while(fAct->next->next!=NULL)   //NOTE this is ugly. Can it be done without fCmp?
1542                        {
1543                                /* Get alpha_i and alpha_{i+1} */
1544                                alpha_i=fAct->getFacetNormal();
1545                                alpha_j=fCmp->getFacetNormal();
1546#ifdef gfan_DEBUG
1547                                alpha_i->show(); 
1548                                alpha_j->show();
1549#endif
1550                                /*Compute the dot product of sigma and alpha_{i,j}*/
1551                                weight1=dotProduct(sigma,alpha_i);
1552                                weight2=dotProduct(sigma,alpha_j);
1553#ifdef gfan_DEBUG
1554                                cout << "weight1=" << weight1 << " " << "weight2=" << weight2 << endl;
1555#endif
1556                                /*Adjust alpha_i and alpha_i+1 accordingly*/
1557                                for(int ii=1;ii<=this->numVars;ii++)
1558                                {                                       
1559                                        u[ii]=weight1*(*alpha_i)[ii-1];
1560                                        v[ii]=weight2*(*alpha_j)[ii-1];
1561                                }                               
1562                               
1563                                /*Now p_weight and q_weight need to be compared as exponent vectors*/
1564                                pSetCoeff0(p,nInit(1));
1565                                pSetCoeff0(q,nInit(1));
1566                                pSetExpV(p,u); 
1567                                pSetm(p);                       
1568                                pSetExpV(q,v); 
1569                                pSetm(q);
1570#ifdef gfan_DEBUG                               
1571                                pWrite(p);pWrite(q);
1572#endif 
1573                                /*We want to check whether x^p < x^q
1574                                => want to check for return value 1 */
1575                                if (pLmCmp(p,q)==1)     //i.e. x^q is smaller
1576                                {
1577                                        fMin=fCmp;
1578                                        fAct=fMin;
1579                                        fCmp=fCmp->next;
1580                                }
1581                                else
1582                                {
1583                                        //fAct=fAct->next;
1584                                        if(fCmp->next!=NULL)
1585                                        {
1586                                                fCmp=fCmp->next;
1587                                        }
1588                                        else
1589                                        {
1590                                                fAct=fAct->next;
1591                                        }
1592                                }
1593                                //fAct=fAct->next;
1594                        }//while(fAct.facetPtr->next!=NULL)
1595                        delete alpha_i,alpha_j,sigma;
1596                       
1597                        /*If testfacet was minimal then fMin should still point there */
1598                       
1599                        //if(fMin->getFacetNormal()==ivNeg(testfacet.getFacetNormal()))                 
1600#ifdef gfan_DEBUG
1601                        cout << "Checking for parallelity" << endl <<" fMin is";
1602                        fMin->printNormal();
1603                        cout << "testfacet is ";
1604                        testfacet->printNormal();
1605                        cout << endl;
1606#endif
1607                        if (fMin==gcTmp.facetPtr)                       
1608                        //if(areEqual(fMin->getFacetNormal(),ivNeg(testfacet.getFacetNormal())))
1609                        //if (isParallel(fMin->getFacetNormal(),testfacet->getFacetNormal()))
1610                        {                               
1611                                cout << "Parallel" << endl;
1612                                rChangeCurrRing(actRing);
1613                                //delete alpha_min, test;
1614                                return TRUE;
1615                        }
1616                        else 
1617                        {
1618                                cout << "Not parallel" << endl;
1619                                rChangeCurrRing(actRing);
1620                                //delete alpha_min, test;
1621                                return FALSE;
1622                        }
1623                }//bool isSearchFacet
1624               
1625                /** \brief Check for equality of two intvecs
1626                */
1627                bool areEqual(intvec const &a, intvec const &b)
1628                {
1629                        bool res=TRUE;
1630                        for(int ii=0;ii<this->numVars;ii++)
1631                        {
1632                                if(a[ii]!=b[ii])
1633                                {
1634                                        res=FALSE;
1635                                        break;
1636                                }
1637                        }
1638                        return res;
1639                }
1640               
1641                /** \brief The reverse search algorithm
1642                */
1643                void reverseSearch(gcone *gcAct) //no const possible here since we call gcAct->flip
1644                {
1645                        facet *fAct=new facet();
1646                        fAct = gcAct->facetPtr;                 
1647                       
1648                        while(fAct!=NULL) 
1649                        {
1650                                cout << "======================"<< endl;
1651                                gcAct->flip(gcAct->gcBasis,gcAct->facetPtr);
1652                                gcone *gcTmp = new gcone(*gcAct);
1653                                //idShow(gcTmp->gcBasis);
1654                                gcTmp->getConeNormals(gcTmp->gcBasis, TRUE);
1655#ifdef gfan_DEBUG
1656                                facet *f = new facet();
1657                                f=gcTmp->facetPtr;
1658                                while(f!=NULL)
1659                                {
1660                                        f->printNormal();
1661                                        f=f->next;                                     
1662                                }
1663#endif
1664                                gcTmp->showIntPoint();
1665                                /*recursive part goes gere*/
1666                                if (isSearchFacet(*gcTmp,(facet*)gcAct->facetPtr))
1667                                {
1668                                        gcAct->next=gcTmp;
1669                                        cout << "PING"<< endl;
1670                                        reverseSearch(gcTmp);
1671                                }
1672                                else
1673                                {
1674                                        delete gcTmp;
1675                                        /*NOTE remove fAct from linked list. It's no longer needed*/
1676                                }
1677                                /*recursion ends*/
1678                                fAct = fAct->next;             
1679                        }//while(fAct->next!=NULL)
1680                }//reverseSearch
1681               
1682                /** \brief The new method of Markwig and Jensen
1683                * Compute gcBasis and facets for the arbitrary starting cone. Store \f$(codim-1)\f$-facets as normals.
1684                * In order to represent a facet uniquely compute also the \f$(codim-2)\f$-facets and norm by the gcd of the components.
1685                * Keep a list of facets as a linked list containing an intvec and an integer matrix.
1686                * Since a \f$(codim-1)\f$-facet belongs to exactly two full dimensional cones, we remove a facet from the list as
1687                * soon as we compute this facet again. Comparison of facets is done by...
1688                */
1689                void noRevS(gcone &gcRoot, bool usingIntPoint=FALSE)
1690                {       
1691                        facet *SearchListRoot = new facet(); //The list containing ALL facets we come across
1692                        facet *SearchListAct;
1693                        //SearchListAct = SearchListRoot;
1694                       
1695                        gcone *gcAct;
1696                        gcAct = &gcRoot;
1697                        gcone *gcPtr;   //Pointer to end of linked list of cones
1698                        gcPtr = &gcRoot;
1699                        gcone *gcNext;  //Pointer to next cone to be visited
1700                        gcNext = &gcRoot;
1701                        gcone *gcHead;
1702                        gcHead = &gcRoot;
1703                       
1704                        facet *fAct;
1705                        fAct = gcAct->facetPtr;                 
1706                       
1707                        ring rAct;
1708                        rAct = currRing;
1709                                               
1710                        int UCNcounter=gcAct->getUCN();
1711#ifdef gfan_DEBUG
1712                        cout << "NoRevs" << endl;
1713                        cout << "Facets are:" << endl;
1714                        gcAct->showFacets();
1715#endif                 
1716                       
1717                        gcAct->getCodim2Normals(*gcAct);
1718                               
1719                        //Compute unique representation of codim-2-facets
1720                        gcAct->normalize();
1721                       
1722                        /*Make a copy of the facet list of first cone
1723                        Since the operations getCodim2Normals and normalize affect the facets
1724                        we must not memcpy them before these ops!
1725                        */
1726                        intvec *fNormal;// = new intvec(this->numVars);
1727                        intvec *f2Normal;// = new intvec(this->numVars);
1728                        facet *codim2Act; codim2Act = NULL;                     
1729                        facet *sl2Root; //sl2Root = new facet(2);
1730                        facet *sl2Act;  //sl2Act = sl2Root;
1731                       
1732                        for(int ii=0;ii<this->numFacets;ii++)
1733                        {
1734                                //only copy flippable facets!
1735                                if(fAct->isFlippable==TRUE)
1736                                {
1737                                        fNormal = fAct->getFacetNormal();
1738                                        if(ii==0)
1739                                        {                                               
1740                                                SearchListAct = SearchListRoot;
1741                                                //memcpy(SearchListAct,fAct,sizeof(facet));                                     
1742                                        }
1743                                        else
1744                                        {
1745                                                SearchListAct->next = new facet();
1746                                                SearchListAct = SearchListAct->next;
1747                                                //memcpy(SearchListAct,fAct,sizeof(facet));                             
1748                                        }
1749                                        SearchListAct->setFacetNormal(fNormal);
1750                                        SearchListAct->setUCN(this->getUCN());
1751                                        SearchListAct->numCodim2Facets=fAct->numCodim2Facets;
1752                                        SearchListAct->isFlippable=TRUE;
1753                                        //Copy codim2-facets                           
1754                                        codim2Act=fAct->codim2Ptr;
1755                                        SearchListAct->codim2Ptr = new facet(2);
1756                                        sl2Root = SearchListAct->codim2Ptr;
1757                                        sl2Act = sl2Root;
1758                                        //while(codim2Act!=NULL)
1759                                        for(int jj=0;jj<fAct->numCodim2Facets;jj++)
1760                                        {
1761                                                f2Normal = codim2Act->getFacetNormal();
1762                                                if(jj==0)
1763                                                {                                               
1764                                                        sl2Act = sl2Root;
1765                                                        sl2Act->setFacetNormal(f2Normal);
1766                                                }
1767                                                else
1768                                                {
1769                                                        sl2Act->next = new facet(2);
1770                                                        sl2Act = sl2Act->next;
1771                                                        sl2Act->setFacetNormal(f2Normal);
1772                                                }                                       
1773                                                codim2Act = codim2Act->next;
1774                                        }
1775                                        fAct = fAct->next;
1776                                }//if(fAct->isFlippable==TRUE)
1777                                else {fAct = fAct->next;}
1778                        }                               
1779                       
1780                        SearchListAct = SearchListRoot; //Set to beginning of list
1781                        /*Make SearchList doubly linked*/
1782                        while(SearchListAct!=NULL)
1783                        {
1784                                if(SearchListAct->next!=NULL)
1785                                {
1786                                        SearchListAct->next->prev = SearchListAct;
1787                                        //SearchListAct = SearchListAct->next;
1788                                }
1789                                SearchListAct = SearchListAct->next;
1790                        }
1791                        SearchListAct = SearchListRoot; //Set to beginning of List
1792                       
1793                        fAct = gcAct->facetPtr;                 
1794                        //gcAct->writeConeToFile(*gcAct);
1795                       
1796                        /*End of initialisation*/
1797                        fAct = SearchListAct;
1798                        /*2nd step
1799                        Choose a facet from fListPtr, flip it and forget the previous cone
1800                        We always choose the first facet from fListPtr as facet to be flipped
1801                        */
1802                        while(SearchListAct!=NULL)
1803                        {//NOTE See to it that the cone is only changed after ALL facets have been flipped!                             
1804                                fAct = SearchListAct;
1805                                //while( ( (fAct->next!=NULL) && (fAct->getUCN()==fAct->next->getUCN() ) ) )
1806                                //do
1807                                while(fAct!=NULL)
1808                                {       //Since SLA should only contain flippables there should be no need to check for that
1809                                        gcAct->flip(gcAct->gcBasis,fAct);
1810                                        ring rTmp=rCopy(fAct->flipRing);
1811                                        rComplete(rTmp);
1812                                        rChangeCurrRing(rTmp);
1813                                        gcone *gcTmp = new gcone::gcone(*gcAct,*fAct);
1814                                        gcTmp->getConeNormals(gcTmp->gcBasis, FALSE);                                   
1815                                        gcTmp->getCodim2Normals(*gcTmp);                                       
1816                                        gcTmp->normalize();
1817#ifdef gfan_DEBUG
1818                                        gcTmp->showFacets(1);
1819#endif
1820                                        //gcTmp->writeConeToFile(*gcTmp);
1821                                        /*add facets to SLA here*/
1822                                        SearchListRoot=gcTmp->enqueueNewFacets(*SearchListRoot);
1823#ifdef gfan_DEBUG
1824                                        if(SearchListRoot!=NULL)
1825                                                gcTmp->showSLA(*SearchListRoot);
1826#endif
1827                                        rChangeCurrRing(gcAct->baseRing);
1828                                        gcPtr->next=gcTmp;
1829                                        gcPtr=gcPtr->next;
1830                                        if(fAct->getUCN() == fAct->next->getUCN())
1831                                        {
1832                                                fAct=fAct->next;
1833                                        }
1834                                        else
1835                                                break;
1836                                }//while( ( (fAct->next!=NULL) && (fAct->getUCN()==fAct->next->getUCN() ) ) );
1837                                //Search for cone with smallest UCN
1838                                gcNext = gcHead;
1839                                while(gcNext!=NULL)
1840                                {
1841                                        //if( gcNext->getUCN() == UCNcounter+1 )
1842                                        if( gcNext->getUCN() == SearchListRoot->getUCN() )
1843                                        {
1844                                                gcAct = gcNext;
1845                                                rAct=rCopy(gcAct->baseRing);
1846                                                rComplete(rAct);
1847                                                rChangeCurrRing(rAct);                                         
1848                                                break;                                         
1849                                        }
1850                                        gcNext = gcNext->next;
1851                                }
1852                                UCNcounter++;
1853                                //SearchListAct = SearchListAct->next;
1854                                //SearchListAct = fAct->next;
1855                                SearchListAct = SearchListRoot;
1856                        }
1857                        cout << endl << "Found " << counter << " cones - terminating" << endl;
1858               
1859                        //NOTE Hm, comment in and get a crash for free...
1860                        //dd_free_global_constants();                           
1861                        //gc.writeConeToFile(gc);
1862                       
1863                       
1864                        //fAct = fListPtr;
1865                        //gcone *gcTmp = new gcone(gc); //copy
1866                        //gcTmp->flip(gcTmp->gcBasis,fAct);
1867                        //NOTE: gcTmp may be deleted, gcRoot from main proc should probably not!
1868                       
1869                }//void noRevS(gcone &gc)       
1870               
1871               
1872                /** \brief Make a set of rational vectors into integers
1873                *
1874                * We compute the lcm of the denominators and multiply with this to get integer values.         
1875                * \param dd_MatrixPtr,intvec
1876                */
1877                void makeInt(dd_MatrixPtr const &M, int const line, intvec &n)
1878                {                       
1879                        mpz_t denom[this->numVars];
1880                        for(int ii=0;ii<this->numVars;ii++)
1881                        {
1882                                mpz_init_set_str(denom[ii],"0",10);
1883                        }
1884               
1885                        mpz_t kgV,tmp;
1886                        mpz_init(kgV);
1887                        mpz_init(tmp);
1888                       
1889                        for (int ii=0;ii<(M->colsize)-1;ii++)
1890                        {
1891                                mpz_t z;
1892                                mpz_init(z);
1893                                mpq_get_den(z,M->matrix[line-1][ii+1]);
1894                                mpz_set( denom[ii], z);
1895                                mpz_clear(z);                           
1896                        }
1897                       
1898                        //Check whether denom is all ones, in which case we will divide out the gcd of the nominators
1899//                      mpz_t checksum; mpz_t rop;
1900//                      mpz_init(checksum);
1901//                      mpz_init(rop);
1902//                      bool divideOutGcd=FALSE;
1903//                      for(int ii=0;ii<this->numVars;ii++)
1904//                      {
1905//                              mpz_add(rop, checksum, denom[ii]);
1906//                              mpz_set(checksum, rop);
1907//                      }
1908//                      if( (int)mpz_get_ui(checksum)==this->numVars)
1909//                      {
1910//                              divideOutGcd=TRUE;
1911//                      }
1912                       
1913                        /*Compute lcm of the denominators*/
1914                        mpz_set(tmp,denom[0]);
1915                        for (int ii=0;ii<(M->colsize)-1;ii++)
1916                        {
1917                                mpz_lcm(kgV,tmp,denom[ii]);
1918                                mpz_set(tmp,kgV);                               
1919                        }
1920                       
1921                        /*Multiply the nominators by kgV*/
1922                        mpq_t qkgV,res;
1923                        mpq_init(qkgV);
1924                        mpq_set_str(qkgV,"1",10);
1925                        mpq_canonicalize(qkgV);
1926                       
1927                        mpq_init(res);
1928                        mpq_set_str(res,"1",10);
1929                        mpq_canonicalize(res);
1930                       
1931                        mpq_set_num(qkgV,kgV);
1932                       
1933//                      mpq_canonicalize(qkgV);
1934                        for (int ii=0;ii<(M->colsize)-1;ii++)
1935                        {
1936                                mpq_mul(res,qkgV,M->matrix[line-1][ii+1]);
1937                                n[ii]=(int)mpz_get_d(mpq_numref(res));
1938                        }
1939                        //mpz_clear(denom[this->numVars]);
1940                        mpz_clear(kgV);
1941                        mpq_clear(qkgV); mpq_clear(res);                       
1942                       
1943                }
1944                /**
1945                 * For all codim-2-facets we compute the gcd of the components of the facet normal and
1946                 * divide it out. Thus we get a normalized representation of each
1947                 * (codim-2)-facet normal, i.e. a primitive vector
1948                */
1949                void normalize()
1950                {
1951                        int ggT=1;
1952                        facet *fAct;
1953                        facet *codim2Act;
1954                        fAct = this->facetPtr;
1955                        codim2Act = fAct->codim2Ptr;
1956                        intvec *n = new intvec(this->numVars);
1957                       
1958                        //while(codim2Act->next!=NULL)
1959                        while(fAct!=NULL)
1960                        {
1961                                while(codim2Act!=NULL)
1962                                {                               
1963                                        n=codim2Act->getFacetNormal();
1964                                        for(int ii=0;ii<this->numVars;ii++)
1965                                        {
1966                                                ggT = intgcd(ggT,(*n)[ii]);
1967                                        }
1968                                        for(int ii=0;ii<this->numVars;ii++)
1969                                        {
1970                                                (*n)[ii] = ((*n)[ii])/ggT;
1971                                        }
1972                                        codim2Act->setFacetNormal(n);
1973                                        codim2Act = codim2Act->next;                           
1974                                }
1975                                fAct = fAct->next;
1976                        }
1977               
1978                        //delete n;
1979                        /*codim2Act = this->facetPtr->codim2Ptr;        //reset to start of linked list                 
1980                        while(codim2Act!=NULL)
1981                        {                               
1982                                n=codim2Act->getFacetNormal();
1983                                intvec *new_n = new intvec(this->numVars);
1984                                for(int ii=0;ii<this->numVars;ii++)
1985                                {
1986                                        (*new_n)[ii] = (*n)[ii]*ggT;
1987                                }
1988                                codim2Act->setFacetNormal(new_n);
1989                                codim2Act = codim2Act->next;
1990                                //delete n;
1991                                //delete new_n;
1992                        }       */             
1993                }
1994                /**
1995                * Takes ptr to search list root
1996                * Returns a pointer to new first element of Searchlist
1997                */
1998                //void enqueueNewFacets(facet &f)
1999                facet * enqueueNewFacets(facet &f)
2000                {
2001                        facet *slHead;
2002                        slHead = &f;
2003                        facet *slAct;   //called with f=SearchListRoot
2004                        slAct = &f;
2005                        facet *slEnd;   //Pointer to end of SLA
2006                        slEnd = &f;
2007                        facet *slEndStatic;     //marks the end before a new facet is added             
2008                        facet *fAct;
2009                        fAct = this->facetPtr;
2010                        facet *codim2Act;
2011                        codim2Act = this->facetPtr->codim2Ptr;
2012                        facet *sl2Act;
2013                        sl2Act = f.codim2Ptr;
2014                       
2015                        bool doNotAdd=FALSE;
2016                        bool removalOccured=FALSE;
2017                        int ctr=0;      //encountered qualities in SLA
2018                        int notParallelCtr=0;
2019                        int lengthOfSearchList=1;
2020                        while(slEnd->next!=NULL)
2021                        {
2022                                slEnd=slEnd->next;
2023                                lengthOfSearchList++;
2024                        }
2025                        slEndStatic = slEnd;
2026                        /*1st step: compare facetNormals*/
2027                        intvec *fNormal=NULL; //= new intvec(this->numVars);
2028                        intvec *f2Normal=NULL; //= new intvec(this->numVars);
2029                        intvec *slNormal=NULL; //= new intvec(this->numVars);
2030                        intvec *sl2Normal=NULL; //= new intvec(this->numVars);
2031                       
2032                        while(fAct!=NULL)
2033                        {                               
2034                                if(fAct->isFlippable==TRUE)
2035                                {
2036                                        doNotAdd=TRUE;
2037                                        fNormal=fAct->getFacetNormal();
2038                                        slAct = slHead;
2039                                        notParallelCtr=0;
2040                                        while(slAct!=NULL)
2041                                        //while(slAct!=slEndStatic->next)
2042                                        {
2043                                                removalOccured=FALSE;
2044                                                slNormal = slAct->getFacetNormal();
2045#ifdef gfan_DEBUG
2046                                                cout << "Checking facet (";
2047                                                fNormal->show(1,1);
2048                                                cout << ") against (";
2049                                                slNormal->show(1,1);
2050                                                cout << ")" << endl;
2051#endif
2052                                                if(!isParallel(fNormal, slNormal))
2053                                                {
2054                                                        notParallelCtr++;
2055                                                }
2056                                                else
2057                                                {
2058                                                        codim2Act = fAct->codim2Ptr;
2059                                                        ctr=0;
2060                                                        while(codim2Act!=NULL)
2061                                                        {
2062                                                                f2Normal = codim2Act->getFacetNormal();
2063                                                                //sl2Act = f.codim2Ptr;
2064                                                                sl2Act = slAct->codim2Ptr;
2065                                                                while(sl2Act!=NULL)
2066                                                                {
2067                                                                        sl2Normal = sl2Act->getFacetNormal();
2068                                                                        if(areEqual(f2Normal, sl2Normal))
2069                                                                                        ctr++;
2070                                                                        sl2Act = sl2Act->next;
2071                                                                }//while(sl2Act!=NULL)
2072                                                                codim2Act = codim2Act->next;
2073                                                        }//while(codim2Act!=NULL)
2074                                                        if(ctr==fAct->numCodim2Facets)  //facets ARE equal
2075                                                        {
2076#ifdef gfan_DEBUG
2077                                                                cout << "Removing facet (";
2078                                                                slNormal->show(1,0);
2079                                                                cout << ") from SLA:" << endl;
2080                                                                fAct->fDebugPrint();
2081                                                                slAct->fDebugPrint();
2082#endif
2083                                                                removalOccured=TRUE;
2084                                                                slAct->isFlippable=FALSE;
2085                                                                doNotAdd=TRUE;
2086                                                                if(slAct==slHead)       //We want to delete the first element of SearchList
2087                                                                {                                                               
2088                                                                        slHead = slAct->next;
2089                                                                        if(slHead!=NULL)
2090                                                                                slHead->prev = NULL;
2091                                                                        //set a bool flag to mark slAct as to be deleted
2092                                                                }
2093                                                                else if(slAct==slEndStatic)
2094                                                                        {
2095                                                                                if(slEndStatic->next==NULL)
2096                                                                                {
2097                                                                                        slEndStatic = slEndStatic->prev;
2098                                                                                        slEndStatic->next = NULL;
2099                                                                                        slEnd = slEndStatic;
2100                                                                                }
2101                                                                                else    //we already added a facet after slEndStatic
2102                                                                                {
2103                                                                                        slEndStatic->prev->next = slEndStatic->next;
2104                                                                                        slEndStatic = slEndStatic->prev;
2105                                                                                        //slEnd = slEndStatic;
2106                                                                                }
2107                                                                        }                                                               
2108                                                                else
2109                                                                {
2110                                                                        slAct->prev->next = slAct->next;
2111                                                                        slAct->next->prev = slAct->prev;
2112                                                                }
2113                                                                //update lengthOfSearchList                                     
2114                                                                lengthOfSearchList--;
2115                                                                break;
2116                                                        }//if(ctr==fAct->numCodim2Facets)
2117                                                        else    //facets are NOT equal
2118                                                        {
2119                                                                doNotAdd=FALSE;
2120                                                                //break;
2121                                                        }
2122                                                }//if(!isParallel(fNormal, slNormal))
2123                                                slAct = slAct->next;
2124                                                //if slAct was marked as to be deleted, delete it here!
2125                                        }//while(slAct!=NULL)                                                                   
2126                                        if( (notParallelCtr==lengthOfSearchList && removalOccured==FALSE) || (doNotAdd==FALSE) )
2127                                        //if( (notParallelCtr==lengthOfSearchList ) || doNotAdd==FALSE )
2128                                        {
2129#ifdef gfan_DEBUG
2130                                                cout << "Adding facet (";
2131                                                fNormal->show(1,0);
2132                                                cout << ") to SLA " << endl;
2133#endif
2134                                                //Add fAct to SLA
2135                                                facet *marker;
2136                                                marker = slEnd;
2137                                                facet *f2Act;
2138                                                f2Act = fAct->codim2Ptr;
2139                                               
2140                                                slEnd->next = new facet();
2141                                                slEnd = slEnd->next;
2142                                                facet *slEndCodim2Root;
2143                                                facet *slEndCodim2Act;
2144                                                slEndCodim2Root = slEnd->codim2Ptr;
2145                                                slEndCodim2Act = slEndCodim2Root;
2146                                                               
2147                                                slEnd->setUCN(this->getUCN());
2148                                                slEnd->isFlippable = TRUE;
2149                                                slEnd->setFacetNormal(fNormal);
2150                                                slEnd->prev = marker;
2151                                                //Copy codim2-facets
2152                                                intvec *f2Normal;// = new intvec(this->numVars);
2153                                                while(f2Act!=NULL)
2154                                                {
2155                                                        f2Normal=f2Act->getFacetNormal();
2156                                                        if(slEndCodim2Root==NULL)
2157                                                        {
2158                                                                slEndCodim2Root = new facet(2);
2159                                                                slEnd->codim2Ptr = slEndCodim2Root;                     
2160                                                                slEndCodim2Root->setFacetNormal(f2Normal);
2161                                                                slEndCodim2Act = slEndCodim2Root;
2162                                                        }
2163                                                        else                                   
2164                                                        {
2165                                                                slEndCodim2Act->next = new facet(2);
2166                                                                slEndCodim2Act = slEndCodim2Act->next;
2167                                                                slEndCodim2Act->setFacetNormal(f2Normal);
2168                                                        }
2169                                                        f2Act = f2Act->next;
2170                                                }
2171                                                lengthOfSearchList++;
2172                                                //delete f2Normal;                                             
2173                                        }//if( (notParallelCtr==lengthOfSearchList && removalOccured==FALSE) ||
2174                                        //remove facets marked as non-flip
2175//                                      slAct=slHead;
2176//                                      while(slAct!=NULL)
2177//                                      {
2178//                                              if(slAct->isFlippable==FALSE)
2179//                                              {
2180//                                                      if(slAct==slHead)       //We want to delete the first element of SearchList
2181//                                                      {                                                               
2182//                                                              slHead = slAct->next;                                   
2183//                                                              if(slHead!=NULL)
2184//                                                                      slHead->prev = NULL;
2185//                                              //set a bool flag to mark slAct as to be deleted
2186//                                                      }
2187//                                                      else if(slAct==slEndStatic)
2188//                                                      {
2189//                                                              if(slEndStatic->next==NULL)
2190//                                                              {
2191//                                                                      slEndStatic = slEndStatic->prev;
2192//                                                                      slEndStatic->next = NULL;
2193//                                                              }
2194//                                                              else    //we already added a facet after slEndStatic
2195//                                                              {
2196//                                                                      slEndStatic->prev->next = slEndStatic->next;
2197//                                                                      slEndStatic = slEndStatic->prev;
2198//                                                      //slEnd = slEndStatic;
2199//                                                              }
2200//                                                      }
2201//                                                      else
2202//                                                      {
2203//                                                              slAct->prev->next = slAct->next;
2204//                                                      }
2205//                                      //update lengthOfSearchList                                     
2206//                                                      lengthOfSearchList--;
2207//                                              }
2208//                                              slAct=slAct->next;
2209//                                      }
2210                                        fAct = fAct->next;
2211                                }//if(fAct->isFlippable==TRUE)
2212                                else
2213                                {
2214                                        fAct = fAct->next;
2215                                }
2216                        }//while(fAct!=NULL)                                           
2217                        return slHead;
2218//                      delete sl2Normal;
2219//                      delete slNormal;
2220//                      delete f2Normal;
2221//                      delete fNormal;
2222                }//addC2N
2223               
2224                /** \brief Compute the gcd of two ints
2225                */
2226                int intgcd(int a, int b)
2227                {
2228                        int r, p=a, q=b;
2229                        if(p < 0)
2230                                p = -p;
2231                        if(q < 0)
2232                                q = -q;
2233                        while(q != 0)
2234                        {
2235                                r = p % q;
2236                                p = q;
2237                                q = r;
2238                        }
2239                        return p;
2240                }               
2241               
2242                /** \brief Construct a dd_MatrixPtr from a cone's list of facets
2243                *
2244                */
2245                dd_MatrixPtr facets2Matrix(gcone const &gc)
2246                {
2247                        facet *fAct;
2248                        fAct = gc.facetPtr;
2249       
2250                        dd_MatrixPtr M;
2251                        dd_rowrange ddrows;
2252                        dd_colrange ddcols;
2253                        ddcols=(this->numVars)+1;
2254                        ddrows=this->numFacets;
2255                        dd_NumberType numb = dd_Integer;
2256                        M=dd_CreateMatrix(ddrows,ddcols);                       
2257                       
2258                        int jj=0;
2259                        //while(fAct->next!=NULL)
2260                        while(fAct!=NULL)
2261                        {
2262                                intvec *comp;
2263                                comp = fAct->getFacetNormal();
2264                                for(int ii=0;ii<this->numVars;ii++)
2265                                {
2266                                        dd_set_si(M->matrix[jj][ii+1],(*comp)[ii]);
2267                                }
2268                                jj++;
2269                                fAct=fAct->next;                               
2270                        }                       
2271                       
2272                        return M;
2273                }
2274               
2275                /** \brief Write information about a cone into a file on disk
2276                *
2277                * This methods writes the information needed for the "second" method into a file.
2278                * The file's is divided in sections containing information on
2279                * 1) the ring
2280                * 2) the cone's Groebner Basis
2281                * 3) the cone's facets
2282                * Each line contains exactly one date
2283                * Each section starts with its name in CAPITALS
2284                */
2285                void writeConeToFile(gcone const &gc, bool usingIntPoints=FALSE)
2286                {
2287                        int UCN=gc.UCN;
2288                        stringstream ss;
2289                        ss << UCN;
2290                        string UCNstr = ss.str();               
2291                       
2292                        char prefix[]="/tmp/cone";
2293                        char *UCNstring;
2294                        strcpy(UCNstring,UCNstr.c_str());
2295                        char suffix[]=".sg";
2296                        char *filename=strcat(prefix,UCNstring);
2297                        strcat(filename,suffix);
2298                                       
2299                        ofstream gcOutputFile(filename);
2300                        facet *fAct = new facet(); //NOTE Why new?
2301                        fAct = gc.facetPtr;                     
2302                       
2303                        char *ringString = rString(currRing);
2304                       
2305                        if (!gcOutputFile)
2306                        {
2307                                cout << "Error opening file for writing in writeConeToFile" << endl;
2308                        }
2309                        else
2310                        {       gcOutputFile << "UCN" << endl;
2311                                gcOutputFile << this->UCN << endl;
2312                                gcOutputFile << "RING" << endl; 
2313                                gcOutputFile << ringString << endl;                     
2314                                //Write this->gcBasis into file
2315                                gcOutputFile << "GCBASIS" << endl;                             
2316                                for (int ii=0;ii<IDELEMS(gc.gcBasis);ii++)
2317                                {                                       
2318                                        gcOutputFile << p_String((poly)gc.gcBasis->m[ii],gc.baseRing) << endl;
2319                                }                               
2320                               
2321                                gcOutputFile << "FACETS" << endl;                                                               
2322                                //while(fAct->next!=NULL)
2323                                while(fAct!=NULL)
2324                                {       
2325                                        intvec *iv = new intvec(gc.numVars);
2326                                        iv=fAct->getFacetNormal();
2327                                        for (int ii=0;ii<iv->length();ii++)
2328                                        {
2329                                                if (ii<iv->length()-1)
2330                                                {
2331                                                        gcOutputFile << (*iv)[ii] << ",";
2332                                                }
2333                                                else
2334                                                {
2335                                                        gcOutputFile << (*iv)[ii] << endl;
2336                                                }
2337                                        }
2338                                        fAct=fAct->next;
2339                                        //delete iv; iv=NULL;
2340                                }                               
2341                               
2342                                gcOutputFile.close();
2343                                //delete fAct; fAct=NULL;
2344                        }
2345                       
2346                }//writeConeToFile(gcone const &gc)
2347               
2348                /** \brief Reads a cone from a file identified by its number
2349                */
2350                void readConeFromFile(int gcNum)
2351                {
2352                }
2353               
2354        friend class facet;
2355};//class gcone
2356
2357int gcone::counter=0;
2358
2359ideal gfan(ideal inputIdeal)
2360{
2361        int numvar = pVariables; 
2362       
2363        enum searchMethod {
2364                reverseSearch,
2365                noRevS
2366        };
2367       
2368        searchMethod method;
2369        method = noRevS;
2370//      method = reverseSearch;
2371       
2372#ifdef gfan_DEBUG
2373        cout << "Now in subroutine gfan" << endl;
2374#endif
2375        ring inputRing=currRing;        // The ring the user entered
2376        ring rootRing;                  // The ring associated to the target ordering
2377        ideal res;     
2378        facet *fRoot;
2379       
2380        if (method==reverseSearch)
2381        {
2382       
2383        /* Construct a new ring which will serve as our root*/
2384        rootRing=rCopy0(currRing);
2385        rootRing->order[0]=ringorder_lp;
2386       
2387        rComplete(rootRing);
2388        rChangeCurrRing(rootRing);
2389       
2390        /* Fetch the inputIdeal into our rootRing */
2391        map theMap=(map)idMaxIdeal(1);  //evil hack!
2392        theMap->preimage=NULL;  //neccessary?
2393        ideal rootIdeal;
2394        rootIdeal=fast_map(inputIdeal,inputRing,(ideal)theMap, currRing);
2395#ifdef gfan_DEBUG
2396        cout << "Root ideal is " << endl;
2397        idShow(rootIdeal);
2398        cout << "The root ring is " << endl;
2399        rWrite(rootRing);
2400        cout << endl;
2401#endif 
2402       
2403        //gcone *gcRoot = new gcone();  //Instantiate the sink
2404        gcone *gcRoot = new gcone(rootRing,rootIdeal);
2405        gcone *gcAct;
2406        gcAct = gcRoot;
2407        gcAct->numVars=pVariables;
2408        gcAct->getGB(rootIdeal);        //sets gcone::gcBasis
2409        idShow(gcAct->gcBasis);
2410        gcAct->getConeNormals(gcAct->gcBasis);  //hopefully compute the normals
2411        //gcAct->flip(gcAct->gcBasis,gcAct->facetPtr); 
2412        /*Now it is time to compute the search facets, respectively start the reverse search.
2413        But since we are in the root all facets should be search facets. IS THIS TRUE?
2414        NOTE: Check for flippability is not very sophisticated
2415        */     
2416        //gcAct->reverseSearch(gcAct); 
2417        rChangeCurrRing(rootRing);
2418        res=gcRoot->gcBasis;   
2419        }//if method==reverSearch
2420       
2421        if(method==noRevS)
2422        {
2423                gcone *gcRoot = new gcone(currRing,inputIdeal);
2424                gcone *gcAct;
2425                gcAct = gcRoot;
2426                gcAct->numVars=pVariables;
2427                gcAct->getGB(inputIdeal);
2428                cout << "GB of input ideal is:" << endl;
2429                idShow(gcAct->gcBasis);
2430                cout << endl;
2431                gcAct->getConeNormals(gcAct->gcBasis);         
2432                gcAct->noRevS(*gcAct);         
2433                res=gcAct->gcBasis;
2434        }
2435        /*As of now extra.cc expects gfan to return type ideal. Probably this will change in near future.
2436        The return type will then be of type LIST_CMD
2437        Assume gfan has finished, thus we have enumerated all the cones
2438        Create an array of size of #cones. Let each entry in the array contain a pointer to the respective
2439        Groebner Basis and merge this somehow with LIST_CMD
2440        => Count the cones!
2441        */
2442        //rChangeCurrRing(rootRing);
2443        //res=gcAct->gcBasis;
2444        //res=gcRoot->gcBasis; 
2445        return res;
2446        //return GBlist;
2447}
2448/*
2449Since gfan.cc is #included from extra.cc there must not be a int main(){} here
2450*/
2451#endif
Note: See TracBrowser for help on using the repository browser.