source: git/Singular/mpr_base.cc @ 912dfa

spielwiese
Last change on this file since 912dfa was 912dfa, checked in by Hans Schönemann <hannes@…>, 24 years ago
* hannes/obachman: HP-adaptions (Makefile.in mpr_base.cc polys-impl.h) git-svn-id: file:///usr/local/Singular/svn/trunk@3900 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 74.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mpr_base.cc,v 1.15 1999-11-23 17:58:47 Singular Exp $ */
5
6/*
7 * ABSTRACT - multipolynomial resultants - resultant matrices
8 *            ( sparse, dense, u-resultant solver )
9 */
10
11#include <limits.h>
12#include <math.h>
13
14#include "mod2.h"
15
16//-> includes
17#include "structs.h"
18#include "polys.h"
19#include "ideals.h"
20#include "ipid.h"
21#include "ipshell.h"
22#include "febase.h"
23#include "mmemory.h"
24#include "intvec.h"
25#include "matpol.h"
26#include "numbers.h"
27#include "longalg.h"
28#include "tok.h"
29#ifdef HAVE_FACTORY
30#include "clapsing.h"
31#else
32#include "matpol.h"
33#endif
34#include "sparsmat.h"
35
36#include "mpr_global.h"
37#include "mpr_base.h"
38#include "mpr_numeric.h"
39#if HAVE_ASO == 10
40#include "mpr_base.aso"
41#else
42#define AllocSizeOf(X) Alloc(sizeof(X))
43#define FreeSizeOf(X,Y) Free(X,sizeof(Y))
44#endif
45
46//<-
47
48extern void nPrint(number n);  // for debugging output
49
50//%s
51//-----------------------------------------------------------------------------
52//-------------- sparse resultant matrix --------------------------------------
53//-----------------------------------------------------------------------------
54
55//-> definitions
56
57//#define mprTEST
58//#define mprMINKSUM
59
60#define MAXPOINTS      10000
61#define MAXINITELEMS   256
62#define LIFT_COOR      50000   // siRand() % LIFT_COOR gives random lift value
63#define SCALEDOWN      100.0  // lift value scale down for linear program
64#define MINVDIST       0.0
65#define RVMULT         0.0001 // multiplicator for random shift vector
66#define MAXRVVAL       50000
67#define MAXVARS        100
68//<-
69
70//-> sparse resultant matrix
71
72//-> typedefs and structs
73
74/* set of points */
75class pointSet;
76
77/* Linear Program stuff */
78struct linProg
79{
80  mprfloat **LiPM;
81  int *izrov, *iposv;
82  int LiPM_cols,LiPM_rows;
83};
84
85typedef linProg *linProgP;
86
87/* sparse resultant matrix class */
88class resMatrixSparse : virtual public resMatrixBase
89{
90public:
91  resMatrixSparse( const ideal _gls, const int special = SNONE );
92  ~resMatrixSparse();
93
94  // public interface according to base class resMatrixBase
95  const ideal getMatrix();
96
97  /** Fills in resMat[][] with evpoint[] and gets determinant
98   * uRPos[i][1]: row of matrix
99   * uRPos[i][idelem+1]: col of u(0)
100   *  uRPos[i][2..idelem]: col of u(1) .. u(n)
101   *  i= 1 .. numSet0
102   */
103  const number getDetAt( const number* evpoint );
104
105  const poly getUDet( const number* evpoint );
106
107private:
108  resMatrixSparse( const resMatrixSparse & );
109
110  void randomVector( const int dim, mprfloat shift[] );
111
112  /** Row Content Function
113   * Finds the largest i such that F[i] is a point, F[i]= a[ij] in A[i] for some j.
114   * Returns -1 iff the point vert does not lie in a cell
115   */
116  int RC( pointSet **pQ, pointSet *E, int vert, mprfloat shift[] );
117
118  /* Remaps a result of LP to the according point set Qi.
119   * Returns false iff remaping was not possible, otherwise true.
120   */
121  bool remapXiToPoint( const int indx, pointSet **pQ, int *set, int *vtx );
122
123  /** create coeff matrix
124   * uRPos[i][1]: row of matrix
125   * uRPos[i][idelem+1]: col of u(0)
126   *  uRPos[i][2..idelem]: col of u(1) .. u(n)
127   *  i= 1 .. numSet0
128   * Returns the dimension of the matrix or -1 in case of an error
129   */
130  int createMatrix( pointSet *E );
131
132  pointSet * minkSumAll( pointSet **pQ, int numq, int dim );
133  pointSet * minkSumTwo( pointSet *Q1, pointSet *Q2, int dim );
134
135private:
136  ideal gls;
137
138  int n, idelem;     // number of variables, polynoms
139  int numSet0;       // number of elements in S0
140  int msize;         // size of matrix
141
142  intvec *uRPos;
143
144  ideal rmat;        // sparse matrix representation
145
146  linProg LP;
147};
148//<-
149
150
151typedef unsigned int Coord_t;
152
153struct setID
154{
155  int set;
156  int pnt;
157};
158
159struct onePoint
160{
161  Coord_t * point;             // point[0] is unused, maxial dimension is MAXVARS+1
162  setID rc;                    // filled in by Row Content Function
163  struct onePoint * rcPnt;     // filled in by Row Content Function
164};
165
166typedef struct onePoint * onePointP;
167
168/* sparse matrix entry */
169struct _entry
170{
171  number num;
172  int col;
173  struct _entry * next;
174};
175
176typedef struct _entry * entry;
177//<-
178
179//-> class pointSet
180class pointSet
181{
182private:
183  onePointP *points;     // set of onePoint's, index [1..num], supports of monoms
184  bool lifted;
185
186public:
187  int num;               // number of elements in points
188  int max;               // maximal entries in points, i.e. allocated mem
189  int dim;               // dimension, i.e. valid coord entries in point
190  int index;             // should hold unique identifier of point set
191
192  pointSet( const int _dim, const int _index= 0, const int count= MAXINITELEMS );
193   ~pointSet();
194
195  // pointSet.points[i] equals pointSet[i]
196  inline const onePointP operator[] ( const int index );
197
198  /** Adds a point to pointSet, copy vert[0,...,dim] ot point[num+1][0,...,dim].
199   * Returns false, iff additional memory was allocated ( i.e. num >= max )
200   * else returns true
201   */
202  bool addPoint( const onePointP vert );
203
204  /** Adds a point to pointSet, copy vert[0,...,dim] ot point[num+1][0,...,dim].
205   * Returns false, iff additional memory was allocated ( i.e. num >= max )
206   * else returns true
207   */
208  bool addPoint( const Exponent_t * vert );
209
210  /** Adds a point to pointSet, copy vert[0,...,dim] ot point[num+1][0,...,dim].
211   * Returns false, iff additional memory was allocated ( i.e. num >= max )
212   * else returns true
213   */
214  bool addPoint( const Coord_t * vert );
215
216  /* Removes the point at intex indx */
217  bool removePoint( const int indx );
218
219  /** Adds point to pointSet, iff pointSet \cap point = \emptyset.
220   * Returns true, iff added, else false.
221   */
222  bool mergeWithExp( const onePointP vert );
223
224  /** Adds point to pointSet, iff pointSet \cap point = \emptyset.
225   * Returns true, iff added, else false.
226   */
227  bool mergeWithExp( const Exponent_t * vert );
228
229  /* Adds support of poly p to pointSet, iff pointSet \cap point = \emptyset. */
230  void mergeWithPoly( const poly p );
231
232  /* Returns the row polynom multiplicator in vert[] */
233  void getRowMP( const int indx, Exponent_t * vert );
234
235  /* Returns index of supp(LT(p)) in pointSet. */
236  int getExpPos( const poly p );
237
238  /** sort lex
239   */
240  void sort();
241
242  /** Lifts the point set using sufficiently generic linear lifting
243   * homogeneous forms l[1]..l[dim] in Z. Every l[i] is of the form
244   * L1x1+...+Lnxn, for generic L1..Ln in Z.
245   *
246   * Lifting raises dimension by one!
247   */
248  void lift( int *l= NULL );     // !! increments dim by 1
249  void unlift() { dim--; lifted= false; }
250
251private:
252  pointSet( const pointSet & );
253
254  /** points[a] < points[b] ? */
255  inline bool smaller( int, int );
256
257  /** points[a] > points[b] ? */
258  inline bool larger( int, int );
259
260  /** Checks, if more mem is needed ( i.e. num >= max ),
261   * returns false, if more mem was allocated, else true
262   */
263  inline bool checkMem();
264};
265//<-
266
267//-> class convexHull
268/* Compute convex hull of given exponent set */
269class convexHull
270{
271public:
272  convexHull( linProgP _pLP ) : pLP(_pLP) {}
273  ~convexHull() {}
274
275  /** Computes the point sets of the convex hulls of the supports given
276   * by the polynoms in gls.
277   * Returns Q[].
278   */
279   pointSet ** newtonPolytopes( ideal gls );
280
281private:
282  /** Returns true iff the support of poly pointPoly is inside the
283   * convex hull of all points given by the  support of poly p.
284   */
285  bool inHull(poly p, poly pointPoly, int m, int site);
286
287private:
288  pointSet **Q;
289  int n;
290  linProgP pLP;
291};
292//<-
293
294//-> class mayanPyramidAlg
295/* Compute all lattice points in a given convex hull */
296class mayanPyramidAlg
297{
298public:
299  mayanPyramidAlg( linProgP _pLP ) : n(pVariables), pLP(_pLP) {}
300  ~mayanPyramidAlg() {}
301
302  /** Drive Mayan Pyramid Algorithm.
303   * The Alg computes conv(Qi[]+shift[]).
304   */
305  pointSet * getInnerPoints( pointSet **_Qi, mprfloat _shift[] );
306
307private:
308
309  /** Recursive Mayan Pyramid algorithm for directly computing MinkowskiSum
310   * lattice points for (n+1)-fold MinkowskiSum of given point sets Qi[].
311   * Recursively for range of dim: dim in [0..n); acoords[0..var) fixed.
312   * Stores only MinkowskiSum points of udist > 0: done by storeMinkowskiSumPoints.
313   */
314  void runMayanPyramid( int dim );
315
316  /**  Compute v-distance via Linear Programing
317   * Linear Program finds the v-distance of the point in accords[].
318   * The v-distance is the distance along the direction v to boundary of
319   * Minkowski Sum of Qi (here vector v is represented by shift[]).
320   * Returns the v-distance or -1.0 if an error occured.
321   */
322  mprfloat vDistance( Coord_t * acoords, int dim );
323
324  /** LP for finding min/max coord in MinkowskiSum, given previous coors.
325   * Assume MinkowskiSum in non-negative quadrants
326   * coor in [0,n); fixed coords in acoords[0..coor)
327   */
328  void mn_mx_MinkowskiSum( int dim, Coord_t *minR, Coord_t *maxR );
329
330  /**  Stores point in E->points[pt], iff v-distance != 0
331   * Returns true iff point was stored, else flase
332   */
333  bool storeMinkowskiSumPoint();
334
335private:
336  pointSet **Qi;
337  pointSet *E;
338  mprfloat *shift;
339
340  int n,idelem;
341
342  Coord_t acoords[MAXVARS+2];
343
344  linProgP pLP;
345};
346
347poly monomAt( poly p, int i );
348
349#ifndef ASO_GENERATE
350//<-
351
352//-> debug output stuff
353#if defined(mprDEBUG_PROT) || defined(mprDEBUG_ALL)
354void print_mat(mprfloat **a, int maxrow, int maxcol)
355{
356  int i, j;
357
358  for (i = 1; i <= maxrow; i++)
359  {
360    Print("[");
361    for (j = 1; j <= maxcol; j++) Print("% 7.2f, ", a[i][j]);
362    Print("],\n");
363  }
364}
365void print_bmat(mprfloat **a, int nrows, int ncols, int N, int *iposv)
366{
367  int i, j;
368
369  printf("Output matrix from LinProg");
370  for (i = 1; i <= nrows; i++)
371  {
372    printf("\n[ ");
373    if (i == 1) printf("  ");
374    else if (iposv[i-1] <= N) printf("X%d", iposv[i-1]);
375    else printf("Y%d", iposv[i-1]-N+1);
376    for (j = 1; j <= ncols; j++) printf(" %7.2f ",(double)a[i][j]);
377    printf(" ]");
378  } printf("\n");
379  fflush(stdout);
380
381}
382void print_exp( const onePointP vert, int n )
383{
384  int i;
385  for ( i= 1; i <= n; i++ )
386  {
387    Print(" %d",vert->point[i] );
388#ifdef LONG_OUTPUT
389    if ( i < n ) Print(", ");
390#endif
391  }
392}
393void print_matrix( matrix omat )
394{
395  int i,j;
396  int val;
397  Print(" matrix m[%d][%d]=(\n",MATROWS( omat ),MATCOLS( omat ));
398  for ( i= 1; i <= MATROWS( omat ); i++ )
399  {
400    for ( j= 1; j <= MATCOLS( omat ); j++ )
401    {
402      if ( MATELEM( omat, i, j) && pGetCoeff( MATELEM( omat, i, j) ) )
403      {
404        val= nInt(pGetCoeff( MATELEM( omat, i, j) ));
405        if ( i==MATROWS(omat) && j==MATCOLS(omat) )
406        {
407          if ( !val ) Print(" 0 ");
408          else Print("%d ",val);
409        }
410        else
411        {
412          if ( !val ) Print(" 0, ");
413          else Print("%d, ",val);
414        }
415      }
416      else
417      {
418        if ( i==MATROWS(omat) && j==MATCOLS(omat) )
419        {
420          Print("  0");
421        }
422        else
423        {
424          Print("  0, ");
425        }
426      }
427    }
428    Print("\n");
429  }
430  Print(");\n");
431}
432#endif
433//<-
434
435//-> pointSet::*
436pointSet::pointSet( const int _dim, const int _index, const int count )
437  : num(0), max(count), dim(_dim), index(_index)
438{
439  int i;
440  points = (onePointP *)Alloc( (count+1) * sizeof(onePointP) );
441  for ( i= 0; i <= max; i++ )
442  {
443    points[i]= (onePointP)AllocSizeOf( onePoint );
444    points[i]->point= (Coord_t *)Alloc0( (dim+2) * sizeof(Coord_t) );
445  }
446  lifted= false;
447}
448
449pointSet::~pointSet()
450{
451  int i;
452  int fdim= lifted ? dim+1 : dim+2;
453  for ( i= 0; i <= max; i++ )
454  {
455    Free( (ADDRESS) points[i]->point, fdim * sizeof(Coord_t) );
456    FreeSizeOf( (ADDRESS) points[i], onePoint );
457  }
458  Free( (ADDRESS) points, (max+1) * sizeof(onePointP) );
459}
460
461inline const onePointP pointSet::operator[] ( const int index )
462{
463  assume( index > 0 && index <= num );
464  return points[index];
465}
466
467inline bool pointSet::checkMem()
468{
469  if ( num >= max )
470  {
471    int i;
472    int fdim= lifted ? dim+1 : dim+2;
473    points= (onePointP*)ReAlloc( points,
474                                 (max+1) * sizeof(onePointP),
475                                 (2*max + 1) * sizeof(onePointP) );
476    for ( i= max+1; i <= max*2; i++ )
477    {
478      points[i]= (onePointP)AllocSizeOf( onePoint );
479      points[i]->point= (Coord_t *)Alloc0( fdim * sizeof(Coord_t) );
480    }
481    max*= 2;
482    mprSTICKYPROT(ST_SPARSE_MEM);
483    return false;
484  }
485  return true;
486}
487
488bool pointSet::addPoint( const onePointP vert )
489{
490  int i;
491  bool ret;
492  num++;
493  ret= checkMem();
494  points[num]->rcPnt= NULL;
495  for ( i= 1; i <= dim; i++ ) points[num]->point[i]= vert->point[i];
496  return ret;
497}
498
499bool pointSet::addPoint( const Exponent_t * vert )
500{
501  int i;
502  bool ret;
503  num++;
504  ret= checkMem();
505  points[num]->rcPnt= NULL;
506  for ( i= 1; i <= dim; i++ ) points[num]->point[i]= (Coord_t) vert[i];
507  return ret;
508}
509
510bool pointSet::addPoint( const Coord_t * vert )
511{
512  int i;
513  bool ret;
514  num++;
515  ret= checkMem();
516  points[num]->rcPnt= NULL;
517  for ( i= 0; i < dim; i++ ) points[num]->point[i+1]= vert[i];
518  return ret;
519}
520
521bool pointSet::removePoint( const int indx )
522{
523  assume( indx > 0 && indx <= num );
524  if ( indx != num )
525  {
526    onePointP tmp;
527    tmp= points[indx];
528    points[indx]= points[num];
529    points[num]= tmp;
530  }
531  num--;
532
533  return true;
534}
535
536bool pointSet::mergeWithExp( const onePointP vert )
537{
538  int i,j;
539
540  for ( i= 1; i <= num; i++ )
541  {
542    for ( j= 1; j <= dim; j++ )
543      if ( points[i]->point[j] != vert->point[j] ) break;
544    if ( j > dim ) break;
545  }
546
547  if ( i > num )
548  {
549    addPoint( vert );
550    return true;
551  }
552  return false;
553}
554
555bool pointSet::mergeWithExp( const Exponent_t * vert )
556{
557  int i,j;
558
559  for ( i= 1; i <= num; i++ )
560  {
561    for ( j= 1; j <= dim; j++ )
562      if ( points[i]->point[j] != (Coord_t) vert[j] ) break;
563    if ( j > dim ) break;
564  }
565
566  if ( i > num )
567  {
568    addPoint( vert );
569    return true;
570  }
571  return false;
572}
573
574void pointSet::mergeWithPoly( const poly p )
575{
576  int i,j;
577  poly piter= p;
578  Exponent_t * vert;
579  vert= (Exponent_t *)Alloc( (dim+1) * sizeof(Exponent_t) );
580
581  while ( piter )
582  {
583    pGetExpV( piter, vert );
584
585    for ( i= 1; i <= num; i++ )
586    {
587      for ( j= 1; j <= dim; j++ )
588        if ( points[i]->point[j] != (Coord_t) vert[j] ) break;
589      if ( j > dim ) break;
590    }
591
592    if ( i > num )
593    {
594      addPoint( vert );
595    }
596
597    pIter( piter );
598  }
599  Free( (ADDRESS) vert, (dim+1) * sizeof(Exponent_t) );
600}
601
602int pointSet::getExpPos( const poly p )
603{
604  Exponent_t * vert;
605  int i,j;
606
607  // hier unschoen...
608  vert= (Exponent_t *)Alloc( (dim+1) * sizeof(Exponent_t) );
609
610  pGetExpV( p, vert );
611  for ( i= 1; i <= num; i++ )
612  {
613    for ( j= 1; j <= dim; j++ )
614      if ( points[i]->point[j] != (Coord_t) vert[j] ) break;
615    if ( j > dim ) break;
616  }
617  Free( (ADDRESS) vert, (dim+1) * sizeof(Exponent_t) );
618
619  if ( i > num ) return 0;
620  else return i;
621}
622
623void pointSet::getRowMP( const int indx, Exponent_t * vert )
624{
625  assume( indx > 0 && indx <= num && points[indx]->rcPnt );
626  int i;
627
628  vert[0]= 0;
629  for ( i= 1; i <= dim; i++ )
630    vert[i]= (Exponent_t)(points[indx]->point[i] - points[indx]->rcPnt->point[i]);
631}
632
633inline bool pointSet::smaller( int a, int b )
634{
635  int i;
636
637  for ( i= 1; i <= dim; i++ )
638  {
639    if ( points[a]->point[i] > points[b]->point[i] )
640    {
641      return false;
642    }
643    if ( points[a]->point[i] < points[b]->point[i] )
644    {
645      return true;
646    }
647  }
648
649 return false; // they are equal
650}
651
652inline bool pointSet::larger( int a, int b )
653{
654  int i;
655
656  for ( i= 1; i <= dim; i++ )
657  {
658    if ( points[a]->point[i] < points[b]->point[i] )
659    {
660      return false;
661    }
662    if ( points[a]->point[i] > points[b]->point[i] )
663    {
664      return true;
665    }
666  }
667
668 return false; // they are equal
669}
670
671void pointSet::sort()
672{
673  int i,j;
674  bool found= true;;
675  onePointP tmp;
676
677  while ( found )
678  {
679    found= false;
680    for ( i= 1; i < num; i++ )
681    {
682      if ( larger( i, i+1 ) )
683      {
684        tmp= points[i];
685        points[i]= points[i+1];
686        points[i+1]= tmp;
687
688        found= true;
689      }
690    }
691  }
692}
693
694void pointSet::lift( int l[] )
695{
696  bool outerL= true;
697  int i, j;
698  int sum;
699
700  dim++;
701
702  if ( l==NULL )
703  {
704    outerL= false;
705    l= (int *)Alloc( (dim+1) * sizeof(int) ); // [1..dim-1]
706
707    for(i = 1; i < dim; i++)
708    {
709      l[i]= 1 + siRand() % LIFT_COOR;
710    }
711  }
712  for ( j=1; j <= num; j++ )
713  {
714    sum= 0;
715    for ( i=1; i < dim; i++ )
716    {
717      sum += (int)points[j]->point[i] * l[i];
718    }
719    points[j]->point[dim]= sum;
720  }
721
722#ifdef mprDEBUG_PROT
723  Print(" lift vector: ");
724  for ( j=1; j < dim; j++ ) Print(" %d ",l[j] );
725  PrintLn();
726#ifdef mprDEBUG_ALL
727  Print(" lifted points: \n");
728  for ( j=1; j <= num; j++ )
729  {
730    Print("%d: <",j);print_exp(points[j],dim);Print(">\n");
731  }
732  PrintLn();
733#endif
734#endif
735
736  lifted= true;
737
738  if ( !outerL ) Free( (ADDRESS) l, (dim+1) * sizeof(int) );
739}
740//<-
741
742//-> global functions
743// Returns the monom at pos i in poly p
744poly monomAt( poly p, int i )
745{
746  assume( i > 0 );
747  poly iter= p;
748  for ( int j= 1; (j < i) && iter; j++ ) iter= pIter(iter);
749  return iter;
750}
751//<-
752
753//-> convexHull::*
754bool convexHull::inHull(poly p, poly pointPoly, int m, int site)
755{
756  int i, j, col, icase;
757  int numcons;                // num of constraints
758  int numpts;                // num of pts in defining support
759  int numcols;                // tot number of cols
760
761  numcons = n+1;
762  numpts = m-1;
763  numcols = numpts+1;                // this includes col of cts
764
765  pLP->LiPM[1][1] = +0.0;  pLP->LiPM[1][2] = +1.0;        // optimize (arbitrary) var
766  pLP->LiPM[2][1] = +1.0;  pLP->LiPM[2][2] = -1.0;         // lambda vars sum up to 1
767  for ( j=3; j<=numcols; j++)
768  {
769    pLP->LiPM[1][j] = +0.0; pLP->LiPM[2][j] = -1.0;
770  }
771
772  for( i= 1; i <= n; i++) {        // each row constraints one coor
773    pLP->LiPM[i+2][1] = (mprfloat)pGetExp(pointPoly,i);
774    col = 2;
775    for( j= 1; j <= m; j++ )
776    {
777      if( j != site )
778      {
779        pLP->LiPM[i+2][col] = -(mprfloat)pGetExp( monomAt(p,j), i );
780        col++;
781      }
782    }
783  }
784
785#ifdef mprDEBUG_ALL
786  Print("Matrix of Linear Programming\n");
787  print_mat( pLP->LiPM, numcons+1, numcols);
788#endif
789#if 1
790  if ( numcons + 1 > pLP->LiPM_rows )
791    WerrorS("convexHull::inHull: #rows > #pLP->LiPM_rows!");
792  if ( numcols + 1 > pLP->LiPM_cols )
793    WerrorS("convexHull::inHull: #cols > #pLP->LiPM_cols!");
794#endif
795
796  simplx( pLP->LiPM, numcons, numcols-1, 0, 0, numcons, &icase, pLP->izrov, pLP->iposv);
797
798  return (icase == 0);
799}
800
801// mprSTICKYPROT:
802// ST_SPARSE_VADD: new vertex of convex hull added
803// ST_SPARSE_VREJ: point rejected (-> inside hull)
804pointSet ** convexHull::newtonPolytopes( ideal gls )
805{
806  int i, j, k;
807  int m;  // Anzahl der Exponentvektoren im i-ten Polynom (gls->m)[i] des Ideals gls
808  int idelem= IDELEMS(gls);
809  Exponent_t * vert;
810
811  n= pVariables;
812  vert= (Exponent_t *)Alloc( (idelem+1) * sizeof(Exponent_t) );
813
814  Q = (pointSet **)Alloc( idelem * sizeof(pointSet*) );        // support hulls
815  for ( i= 0; i < idelem; i++ )
816    Q[i] = new pointSet( pVariables, i+1, pLength((gls->m)[i])+1 );
817
818  for( i= 0; i < idelem; i++ )
819  {
820    k=1;
821    m = pLength( (gls->m)[i] );
822
823    poly p= (gls->m)[i];
824    for( j= 1; j <= m; j++) {  // für jeden Exponentvektor
825      if( !inHull( (gls->m)[i], p, m, j ) )
826      {
827        pGetExpV( p, vert );
828        Q[i]->addPoint( vert );
829        k++;
830        mprSTICKYPROT(ST_SPARSE_VADD);
831      }
832      else
833      {
834        mprSTICKYPROT(ST_SPARSE_VREJ);
835      }
836      pIter( p );
837    } // j
838    mprSTICKYPROT("\n");
839  } // i
840
841  Free( (ADDRESS) vert, (idelem+1) * sizeof(Exponent_t) );
842
843#ifdef mprDEBUG_PROT
844  PrintLn();
845  for( i= 0; i < idelem; i++ )
846  {
847    Print(" \\Conv(Qi[%d]): #%d\n", i,Q[i]->num );
848    for ( j=1; j <= Q[i]->num; j++ )
849    {
850      Print("%d: <",j);print_exp( (*Q[i])[j] , pVariables );Print(">\n");
851    }
852    PrintLn();
853  }
854#endif
855
856  return Q;
857}
858//<-
859
860//-> mayanPyramidAlg::*
861pointSet * mayanPyramidAlg::getInnerPoints( pointSet **_Qi, mprfloat _shift[] )
862{
863  int i;
864
865  Qi= _Qi;
866  shift= _shift;
867
868  E= new pointSet( Qi[0]->dim ); // E has same dim as Qi[...]
869
870  for ( i= 0; i < MAXVARS+2; i++ ) acoords[i]= 0;
871
872  runMayanPyramid(0);
873
874  mprSTICKYPROT("\n");
875
876  return E;
877}
878
879mprfloat mayanPyramidAlg::vDistance( Coord_t * acoords, int dim )
880{
881  int i, ii, j, k, col, r;
882  int icase, constr, numverts, cols;
883
884  numverts = 0;
885  for( i=0; i<=n; i++)
886  {
887    numverts += Qi[i]->num;
888  }
889  cols = numverts + 2;
890
891  //if( dim < 1 || dim > n )
892  //  WerrorS("mayanPyramidAlg::vDistance: Known coords dim off range");
893
894  pLP->LiPM[1][1] = 0.0;
895  pLP->LiPM[1][2] = 1.0;        // maximize
896  for( j=3; j<=cols; j++) pLP->LiPM[1][j] = 0.0;
897
898  for( i=0; i <= n; i++ ) {
899    pLP->LiPM[i+2][1] = 1.0;
900    pLP->LiPM[i+2][2] = 0.0;
901  }
902  for( i=1; i<=dim; i++) {
903    pLP->LiPM[n+2+i][1] = (mprfloat)(acoords[i-1]);
904    pLP->LiPM[n+2+i][2] = -shift[i];
905  }
906
907  ii = -1;
908  col = 2;
909  for ( i= 0; i <= n; i++ ) {
910    ii++;
911    for( k= 1; k <= Qi[ii]->num; k++ )
912    {
913      col++;
914      for ( r= 0; r <= n; r++ )
915      {
916        if ( r == i ) pLP->LiPM[r+2][col] = -1.0;
917        else pLP->LiPM[r+2][col] = 0.0;
918      }
919      for( r= 1; r <= dim; r++ ) pLP->LiPM[r+n+2][col] = -(mprfloat)((*Qi[ii])[k]->point[r]);
920    }
921  }
922
923  if( col != cols)
924    Werror("mayanPyramidAlg::vDistance:"
925           "setting up matrix for udist: col %d != cols %d",col,cols);
926  constr = n+dim+1;
927
928#ifdef mprDEBUG_ALL
929  Print("vDistance LP, known koords dim=%d, constr %d, cols %d, acoords= ",dim,constr,cols);
930  for( i= 0; i < dim; i++ ) Print(" %d",acoords[i]);
931  PrintLn();
932  print_mat( pLP->LiPM, constr+1, cols);
933#endif
934
935#if 1
936  if ( constr + 1 > pLP->LiPM_rows )
937    WerrorS("mayanPyramidAlg::vDistance: #rows > #pLP->LiPM_rows!");
938  if ( cols + 1 > pLP->LiPM_cols )
939    WerrorS("mayanPyramidAlg::vDistance: #cols > #pLP->LiPM_cols!");
940#endif
941
942  // 3rd arg is #columns excluding column of constants
943  //            M       N       m1  m2  m3,   M= m1+m2+m3
944  simplx( pLP->LiPM, constr, cols-1,  0,  0, constr, &icase, pLP->izrov, pLP->iposv);
945
946#ifdef mprDEBUG_ALL
947  Print("LP returns matrix\n");
948  print_bmat( pLP->LiPM, constr+1, cols+1-constr, cols, pLP->iposv);
949#endif
950
951  if( icase != 0 ) {  // check for errors
952    WerrorS("mayanPyramidAlg::vDistance:");
953    if( icase == 1 )
954      WerrorS(" vDistance: Unbounded v-distance: probably 1st v-coor=0");
955    if( icase == -1 )
956      WerrorS(" vDistance: Infeasible v-distance");
957    return -1.0;
958  }
959
960  return pLP->LiPM[1][1];
961}
962
963void  mayanPyramidAlg::mn_mx_MinkowskiSum( int dim, Coord_t *minR, Coord_t *maxR )
964{
965  int i, j, k, cols, cons;
966  int icase, la_cons_row;
967
968  cons = n+dim+2;
969
970  // first, compute minimum
971  //
972
973  // common part of the matrix
974  pLP->LiPM[1][1] = 0.0;
975  for( i=2; i<=n+2; i++) {
976    pLP->LiPM[i][1] = 1.0;        // 1st col
977    pLP->LiPM[i][2] = 0.0;        // 2nd col
978  }
979
980  la_cons_row = 1;
981  cols = 2;
982  for( i=0; i<=n; i++)
983  {
984    la_cons_row++;
985    for( j=1; j<= Qi[i]->num; j++)
986    {
987      cols++;
988      pLP->LiPM[1][cols] = 0.0;        // set 1st row 0
989      for( k=2; k<=n+2; k++) {  // lambdas sum up to 1
990        if( k != la_cons_row) pLP->LiPM[k][cols] = 0.0;
991        else pLP->LiPM[k][cols] = -1.0;
992      }
993      for( k=1; k<=n; k++) pLP->LiPM[k+n+2][cols] = -(mprfloat)((*Qi[i])[j]->point[k]);
994    } // j
995  } // i
996
997  for( i= 0; i < dim; i++ ) {                // fixed coords
998    pLP->LiPM[i+n+3][1] = acoords[i];
999    pLP->LiPM[i+n+3][2] = 0.0;
1000  }
1001  pLP->LiPM[dim+n+3][1] = 0.0;
1002
1003
1004  pLP->LiPM[1][2] = -1.0;                        // minimize
1005  pLP->LiPM[dim+n+3][2] = 1.0;
1006
1007#ifdef mprDEBUG_ALL
1008  Print("\nThats the matrix for minR, dim= %d, acoords= ",dim);
1009  for( i= 0; i < dim; i++ ) Print(" %d",acoords[i]);
1010  PrintLn();
1011  print_mat( pLP->LiPM, cons+1, cols);
1012#endif
1013
1014#if 1
1015  if ( cons + 1 > pLP->LiPM_rows )
1016    WerrorS(" mn_mx_MinkowskiSum: #rows > #pLP->LiPM_rows!");
1017  if ( cols + 1 > pLP->LiPM_cols )
1018    WerrorS(" mn_mx_MinkowskiSum: #cols > #pLP->LiPM_cols!");
1019#endif
1020
1021  // simplx finds MIN for obj.fnc, puts it in [1,1]
1022  simplx(pLP->LiPM, cons, cols-1, 0, 0, cons, &icase, pLP->izrov, pLP->iposv);
1023
1024  if ( icase != 0 ) { // check for errors
1025    if( icase < 0)
1026      WerrorS(" mn_mx_MinkowskiSum: LinearProgram: minR: infeasible");
1027    else if( icase > 0)
1028      WerrorS(" mn_mx_MinkowskiSum: LinearProgram: minR: unbounded");
1029  }
1030
1031  *minR = (Coord_t)( -pLP->LiPM[1][1] + 1.0 - SIMPLEX_EPS );
1032
1033  // now compute maximum
1034  //
1035
1036  // common part of the matrix again
1037  pLP->LiPM[1][1] = 0.0;
1038  for( i=2; i<=n+2; i++) {
1039    pLP->LiPM[i][1] = 1.0;
1040    pLP->LiPM[i][2] = 0.0;
1041  }
1042  la_cons_row = 1;
1043  cols = 2;
1044  for( i=0; i<=n; i++)
1045  {
1046    la_cons_row++;
1047    for( j=1; j<=Qi[i]->num; j++)
1048    {
1049      cols++;
1050      pLP->LiPM[1][cols] = 0.0;
1051      for( k=2; k<=n+2; k++) {
1052        if( k != la_cons_row) pLP->LiPM[k][cols] = 0.0;
1053        else pLP->LiPM[k][cols] = -1.0;
1054      }
1055      for( k=1; k<=n; k++) pLP->LiPM[k+n+2][cols] = -(mprfloat)((*Qi[i])[j]->point[k]);
1056    } // j
1057  }  // i
1058
1059  for( i= 0; i < dim; i++ ) {                // fixed coords
1060    pLP->LiPM[i+n+3][1] = acoords[i];
1061    pLP->LiPM[i+n+3][2] = 0.0;
1062  }
1063  pLP->LiPM[dim+n+3][1] = 0.0;
1064
1065  pLP->LiPM[1][2] = 1.0;                        // maximize
1066  pLP->LiPM[dim+n+3][2] = 1.0;                // var = sum of pnt coords
1067
1068#ifdef mprDEBUG_ALL
1069  Print("\nThats the matrix for maxR, dim= %d\n",dim);
1070  print_mat( pLP->LiPM, cons+1, cols);
1071#endif
1072
1073#if 1
1074  if ( cons + 1 > pLP->LiPM_rows )
1075    WerrorS(" mn_mx_MinkowskiSum: #rows > #pLP->LiPM_rows!");
1076  if ( cols + 1 > pLP->LiPM_cols )
1077    WerrorS(" mn_mx_MinkowskiSum: #cols > #pLP->LiPM_cols!");
1078#endif
1079
1080  // simplx finds MAX for obj.fnc, puts it in [1,1]
1081  simplx(pLP->LiPM, cons, cols-1, 0, 0, cons, &icase, pLP->izrov, pLP->iposv);
1082
1083  if ( icase != 0 )
1084  {
1085    if( icase < 0)
1086      WerrorS(" mn_mx_MinkowskiSum: LinearProgram: maxR: infeasible");
1087    else if( icase > 0)
1088      WerrorS(" mn_mx_MinkowskiSum: LinearProgram: maxR: unbounded");
1089  }
1090
1091  *maxR = (Coord_t)( pLP->LiPM[1][1] + SIMPLEX_EPS );
1092
1093#ifdef mprDEBUG_ALL
1094  Print("  Range for dim=%d: [%d,%d]\n", dim, *minR, *maxR);
1095#endif
1096}
1097
1098// mprSTICKYPROT:
1099// ST_SPARSE_VREJ: rejected point
1100// ST_SPARSE_VADD: added point to set
1101bool mayanPyramidAlg::storeMinkowskiSumPoint()
1102{
1103  mprfloat dist;
1104
1105  // determine v-distance of point pt
1106  dist= vDistance( &(acoords[0]), n );
1107
1108  // store only points with v-distance > minVdist
1109  if( dist <= MINVDIST + SIMPLEX_EPS )
1110  {
1111    mprSTICKYPROT(ST_SPARSE_VREJ);
1112    return false;
1113  }
1114
1115  E->addPoint( &(acoords[0]) );
1116  mprSTICKYPROT(ST_SPARSE_VADD);
1117
1118  return true;
1119}
1120
1121// mprSTICKYPROT:
1122// ST_SPARSE_MREC1: recurse
1123// ST_SPARSE_MREC2: recurse with extra points
1124// ST_SPARSE_MPEND: end
1125void mayanPyramidAlg::runMayanPyramid( int dim )
1126{
1127  Coord_t minR, maxR;
1128  mprfloat dist;
1129
1130  // step 3
1131  mn_mx_MinkowskiSum( dim, &minR, &maxR );
1132
1133#ifdef mprDEBUG_ALL
1134  int i;
1135  for( i=0; i <= dim; i++) Print("acoords[%d]=%d ",i,(int)acoords[i]);
1136  Print(":: [%d,%d]\n", minR, maxR);
1137#endif
1138
1139  // step 5 -> terminate
1140  if( dim == n-1 ) {
1141    int lastKilled = 0;
1142    // insert points
1143    acoords[dim] = minR;
1144    while( acoords[dim] <= maxR )
1145    {
1146      if( !storeMinkowskiSumPoint() ) lastKilled++;
1147      acoords[dim]++;
1148    }
1149    mprSTICKYPROT(ST_SPARSE_MPEND);
1150    return;
1151  }
1152
1153  // step 4 -> recurse at step 3
1154  acoords[dim] = minR;
1155  while ( acoords[dim] <= maxR )
1156  {
1157    if ( (acoords[dim] > minR) && (acoords[dim] <= maxR) ) {     // acoords[dim] >= minR  ??
1158      mprSTICKYPROT(ST_SPARSE_MREC1);
1159      runMayanPyramid( dim + 1 );         // recurse with higer dimension
1160    } else {
1161      // get v-distance of pt
1162      dist= vDistance( &(acoords[0]), dim + 1 );// dim+1 == known coordinates
1163
1164      if( dist >= SIMPLEX_EPS )
1165      {
1166        mprSTICKYPROT(ST_SPARSE_MREC2);
1167        runMayanPyramid( dim + 1 );       // recurse with higer dimension
1168      }
1169    }
1170    acoords[dim]++;
1171  } // while
1172
1173  return;
1174}
1175//<-
1176
1177//-> resMatrixSparse::*
1178bool resMatrixSparse::remapXiToPoint( const int indx, pointSet **pQ, int *set, int *pnt )
1179{
1180  int i,n= pVariables;
1181  int loffset= 0;
1182  for ( i= 0; i <= n; i++ )
1183  {
1184    if ( (loffset < indx) && (indx <= pQ[i]->num + loffset) )
1185    {
1186      *set= i;
1187      *pnt= indx-loffset;
1188      return true;
1189    }
1190    else loffset+= pQ[i]->num;
1191  }
1192  return false;
1193}
1194
1195// mprSTICKYPROT
1196// ST_SPARSE_RC: point added
1197int resMatrixSparse::RC( pointSet **pQ, pointSet *E, int vert, mprfloat shift[] )
1198{
1199  int i, j, k,c ;
1200  int ncols, size, icase, NumCons;
1201  bool found= true;
1202  mprfloat cd;
1203  int set,pnt,onum;
1204  int bucket[MAXVARS+2];
1205  setID *optSum;
1206
1207  ncols = 1;
1208  NumCons = n + n + 1;   // number of constrains
1209
1210  // fill in LP matrix
1211  for ( i= 0; i <= n; i++ )
1212  {
1213    size= pQ[i]->num;
1214    for ( k= 1; k <= size; k++ )
1215    {
1216      ncols++;
1217
1218      // objective funtion, minimize
1219      LP.LiPM[1][ncols] = - ( (mprfloat) (*pQ[i])[k]->point[pQ[i]->dim] / SCALEDOWN );
1220
1221      // lambdas sum up to 1
1222      for ( j = 0; j <= n; j++ )
1223        if ( i==j )
1224          LP.LiPM[j+2][ncols] = -1.0;
1225        else
1226          LP.LiPM[j+2][ncols] = 0.0;
1227
1228      // the points
1229      for ( j = 1; j <= n; j++ )
1230      {
1231        LP.LiPM[j+n+2][ncols] =  - ( (mprfloat) (*pQ[i])[k]->point[j] );
1232      }
1233    }
1234  }
1235
1236  for ( j = 0; j <= n; j++ ) LP.LiPM[j+2][1] = 1.0;
1237  for ( j= 1; j <= n; j++ )
1238  {
1239    LP.LiPM[j+n+2][1]= (mprfloat)(*E)[vert]->point[j] - shift[j];
1240  }
1241  ncols--;
1242
1243  LP.LiPM[1][1] = 0.0;
1244
1245#ifdef mprDEBUG_ALL
1246  PrintLn();
1247  Print(" n= %d, NumCons=M= %d, ncols=N= %d\n",n,NumCons,ncols);
1248  print_mat(LP.LiPM, NumCons+1, ncols+1);
1249#endif
1250
1251#if 1
1252  if ( NumCons + 1 > LP.LiPM_rows )
1253    WerrorS("resMatrixSparse::RC: #rows > #LP.LiPM_rows!");
1254  if ( ncols + 1 > LP.LiPM_cols )
1255    WerrorS("resMatrixSparse::RC: #cols > #LP.LiPM_cols!");
1256#endif
1257
1258  //           M        N      m1  m2  m3,   M= m1+m2+m3
1259  simplx(LP.LiPM, NumCons, ncols,  0,  0, NumCons, &icase, LP.izrov, LP.iposv);
1260
1261  if (icase < 0)
1262  {
1263    // infeasibility: the point does not lie in a cell -> remove it
1264    return -1;
1265  }
1266
1267  // store result
1268  (*E)[vert]->point[E->dim]= (int)(-LP.LiPM[1][1] * SCALEDOWN);
1269
1270#ifdef mprDEBUG_ALL
1271  Print(" simplx returned %d, Objective value = %f\n", icase, LP.LiPM[1][1]);
1272  //print_bmat(LP.LiPM, NumCons + 1, ncols+1-NumCons, ncols+1, LP.iposv); // ( rows= M+1, cols= N+1-m3 )
1273  //print_mat(LP.LiPM, NumCons+1, ncols);
1274#endif
1275
1276#if 1
1277  // sort LP results
1278  while (found)
1279  {
1280    found=false;
1281    for ( i= 1; i < NumCons; i++ )
1282    {
1283      if ( LP.iposv[i] > LP.iposv[i+1] )
1284      {
1285
1286        c= LP.iposv[i];
1287        LP.iposv[i]=LP.iposv[i+1];
1288        LP.iposv[i+1]=c;
1289
1290        cd=LP.LiPM[i+1][1];
1291        LP.LiPM[i+1][1]=LP.LiPM[i+2][1];
1292        LP.LiPM[i+2][1]=cd;
1293
1294        found= true;
1295      }
1296    }
1297  }
1298#endif
1299
1300#ifdef mprDEBUG_ALL
1301  print_bmat(LP.LiPM, NumCons + 1, ncols+1-NumCons, ncols+1, LP.iposv);
1302  Print(" now split into sets\n");
1303#endif
1304
1305
1306  // init bucket
1307  for ( i= 0; i <= E->dim; i++ ) bucket[i]= 0;
1308  // remap results of LP to sets Qi
1309  c=0;
1310  optSum= (setID*)Alloc( (NumCons) * sizeof(struct setID) );
1311  for ( i= 0; i < NumCons; i++ )
1312  {
1313    //Print("% .15f\n",LP.LiPM[i+2][1]);
1314    if ( LP.LiPM[i+2][1] > 1e-12 )
1315    {
1316      if ( !remapXiToPoint( LP.iposv[i+1], pQ, &(optSum[c].set), &(optSum[c].pnt) ) )
1317      {
1318        Werror(" resMatrixSparse::RC: Found bad solution in LP: %d!",LP.iposv[i+1]);
1319        WerrorS(" resMatrixSparse::RC: remapXiToPoint faild!");
1320        return -1;
1321      }
1322      bucket[optSum[c].set]++;
1323      c++;
1324    }
1325  }
1326
1327  onum= c;
1328  // find last min in bucket[]: maximum i such that Fi is a point
1329  c= 0;
1330  for ( i= 1; i < E->dim; i++ )
1331  {
1332    if ( bucket[c] >= bucket[i] )
1333    {
1334      c= i;
1335    }
1336  }
1337  // find matching point set
1338  for ( i= onum - 1; i >= 0; i-- )
1339  {
1340    if ( optSum[i].set == c )
1341      break;
1342  }
1343  // store
1344  (*E)[vert]->rc.set= c;
1345  (*E)[vert]->rc.pnt= optSum[i].pnt;
1346  (*E)[vert]->rcPnt= (*pQ[c])[optSum[i].pnt];
1347  // count
1348  if ( (*E)[vert]->rc.set == linPolyS ) numSet0++;
1349
1350#ifdef mprDEBUG_ALL
1351  Print("\n Point E[%d] was <",vert);print_exp((*E)[vert],E->dim-1);Print(">, bucket={");
1352  for ( j= 0; j < E->dim; j++ )
1353  {
1354    Print(" %d",bucket[j]);
1355  }
1356  Print(" }\n optimal Sum: Qi ");
1357  for ( j= 0; j < NumCons; j++ )
1358  {
1359    Print(" [ %d, %d ]",optSum[j].set,optSum[j].pnt);
1360  }
1361  Print(" -> i= %d, j = %d\n",(*E)[vert]->rc.set,optSum[i].pnt);
1362#endif
1363
1364  // clean up
1365  Free( (ADDRESS) optSum, (NumCons) * sizeof(struct setID) );
1366
1367  mprSTICKYPROT(ST_SPARSE_RC);
1368
1369  return (int)(-LP.LiPM[1][1] * SCALEDOWN);
1370}
1371
1372// create coeff matrix
1373int resMatrixSparse::createMatrix( pointSet *E )
1374{
1375  // sparse matrix
1376  //    uRPos[i][1]: row of matrix
1377  //    uRPos[i][idelem+1]: col of u(0)
1378  //    uRPos[i][2..idelem]: col of u(1) .. u(n)
1379  //    i= 1 .. numSet0
1380  int i,j,epos;
1381  int rp,cp;
1382  poly rowp,epp;
1383  poly iterp;
1384  Exponent_t *epp_mon, *eexp;
1385
1386  epp_mon= (Exponent_t *)Alloc( (n+2) * sizeof(Exponent_t) );
1387  eexp= (Exponent_t *)Alloc0((pVariables+1)*sizeof(Exponent_t));
1388
1389  totDeg= numSet0;
1390
1391  mprSTICKYPROT2(" size of matrix: %d\n", E->num);
1392  mprSTICKYPROT2("  resultant deg: %d\n", numSet0);
1393
1394  uRPos= NewIntvec3( numSet0, pLength((gls->m)[0])+1, 0 );
1395
1396  // sparse Matrix represented as a module where
1397  // each poly is column vector ( pSetComp(p,k) gives the row )
1398  rmat= idInit( E->num, E->num );    // cols, rank= number of rows
1399  msize= E->num;
1400
1401  rp= 1;
1402  rowp= NULL;
1403  epp= pOne();
1404  for ( i= 1; i <= E->num; i++ ) {       // for every row
1405    E->getRowMP( i, epp_mon );           // compute (p-a[ij]), (i,j) = RC(p)
1406    pSetExpV( epp, epp_mon );
1407
1408    //
1409    rowp= pMult( pCopy(epp), pCopy((gls->m)[(*E)[i]->rc.set]) );  // x^(p-a[ij]) * f(i)
1410    pSetm( rowp );
1411
1412    cp= 2;
1413    // get column for every monomial in rowp and store it
1414    iterp= rowp;
1415    while ( iterp )
1416    {
1417      epos= E->getExpPos( iterp );
1418      if ( epos == 0 )
1419      {
1420        // this can happen, if the shift vektor or the lift funktions
1421        // are not generically choosen.
1422        Werror("resMatrixSparse::createMatrix: Found exponent not in E, id %d, set [%d, %d]!",
1423               i,(*E)[i]->rc.set,(*E)[i]->rc.pnt);
1424        return i;
1425      }
1426      pSetExpV(iterp,eexp);
1427      pSetComp(iterp, epos );
1428      if ( (*E)[i]->rc.set == linPolyS ) { // store coeff positions
1429        IMATELEM(*uRPos,rp,cp)= epos;
1430        cp++;
1431      }
1432      pIter( iterp );
1433    } // while
1434    if ( (*E)[i]->rc.set == linPolyS ) {   // store row
1435      IMATELEM(*uRPos,rp,1)= i-1;
1436      rp++;
1437    }
1438    pSetm(rowp);
1439    (rmat->m)[i-1]= rowp;
1440  } // for
1441
1442  pDelete( &epp );
1443  Free( (ADDRESS) epp_mon, (n+2) * sizeof(Exponent_t) );
1444  Free( (ADDRESS) eexp, (pVariables+1)*sizeof(Exponent_t));
1445
1446#ifdef mprDEBUG_ALL
1447  if ( E->num <= 40 )
1448  {
1449    matrix mout= idModule2Matrix( idCopy(rmat) );
1450    print_matrix(mout);
1451  }
1452  for ( i= 1; i <= numSet0; i++ )
1453  {
1454    Print(" row  %d contains coeffs of f_%d\n",IMATELEM(*uRPos,i,1),linPolyS);
1455  }
1456  Print(" Sparse Matrix done\n");
1457#endif
1458
1459  return E->num;
1460}
1461
1462// find a sufficiently generic and small vector
1463void resMatrixSparse::randomVector( const int dim, mprfloat shift[] )
1464{
1465  int i,j;
1466  i= 1;
1467  /*
1468  shift[1]= (mprfloat) (RVMULT*(siRand()%MAXRVVAL)/(mprfloat)MAXRVVAL);
1469  i++;
1470  while ( i <= dim )
1471  {
1472    shift[i]=shift[1];
1473    i++;
1474  }
1475  */
1476  while ( i <= dim )
1477  {
1478    shift[i]= (mprfloat) (RVMULT*(siRand()%MAXRVVAL)/(mprfloat)MAXRVVAL);
1479    i++;
1480    for ( j= 1; j < i-1; j++ )
1481    {
1482      if ( (shift[j] < shift[i-1] + SIMPLEX_EPS) && (shift[j] > shift[i-1] - SIMPLEX_EPS) )
1483      {
1484        i--;
1485        break;
1486      }
1487    }
1488  }
1489
1490}
1491
1492pointSet * resMatrixSparse::minkSumTwo( pointSet *Q1, pointSet *Q2, int dim )
1493{
1494  pointSet *vs;
1495  onePoint vert;
1496  int j,k,l;
1497
1498  vert.point=(Coord_t*)Alloc( (pVariables+2) * sizeof(Coord_t) );
1499
1500  vs= new pointSet( dim );
1501
1502  for ( j= 1; j <= Q1->num; j++ )
1503  {
1504    for ( k= 1; k <= Q2->num; k++ )
1505    {
1506      for ( l= 1; l <= dim; l++ )
1507      {
1508        vert.point[l]= (*Q1)[j]->point[l] + (*Q2)[k]->point[l];
1509      }
1510      vs->mergeWithExp( &vert );
1511      //vs->addPoint( &vert );
1512    }
1513  }
1514
1515  Free( (ADDRESS) vert.point, (pVariables+2) * sizeof(Coord_t) );
1516
1517  return vs;
1518}
1519
1520pointSet * resMatrixSparse::minkSumAll( pointSet **pQ, int numq, int dim )
1521{
1522  pointSet *vs,*vs_old;
1523  int j;
1524
1525  vs= new pointSet( dim );
1526
1527  for ( j= 1; j <= pQ[0]->num; j++ ) vs->addPoint( (*pQ[0])[j] );
1528
1529  for ( j= 1; j < numq; j++ )
1530  {
1531    vs_old= vs;
1532    vs= minkSumTwo( vs_old, pQ[j], dim );
1533
1534    delete vs_old;
1535  }
1536
1537  return vs;
1538}
1539
1540//----------------------------------------------------------------------------------------
1541
1542resMatrixSparse::resMatrixSparse( const ideal _gls, const int special )
1543  : resMatrixBase(), gls( _gls )
1544{
1545  pointSet **Qi; // vertices sets of Conv(Supp(f_i)), i=0..idelem
1546  pointSet *E;   // all integer lattice points of the minkowski sum of Q0...Qn
1547  int i,j,k;
1548  int pnt;
1549  int totverts;                // total number of exponent vectors in ideal gls
1550  mprfloat shift[MAXVARS+2];   // shiftvector delta, index [1..dim]
1551
1552  if ( pVariables > MAXVARS )
1553  {
1554    WerrorS("resMatrixSparse::resMatrixSparse: To many variables!");
1555    return;
1556  }
1557
1558  rmat= NULL;
1559  numSet0= 0;
1560
1561  if ( special == SNONE ) linPolyS= 0;
1562  else linPolyS= special;
1563
1564  istate= resMatrixBase::ready;
1565
1566  n= pVariables;
1567  idelem= IDELEMS(gls);  // should be n+1
1568
1569  // prepare matrix LP.LiPM for Linear Programming
1570  totverts = 0;
1571  for( i=0; i < idelem; i++) totverts += pLength( (gls->m)[i] );
1572
1573  LP.LiPM_rows= idelem+totverts*2+5;  // very approximal
1574  LP.LiPM_cols= totverts+5;
1575
1576#ifdef mprDEBUG_ALL
1577  Print("LP.LiPM size: %d, %d\n",LP.LiPM_rows,LP.LiPM_cols);
1578#endif
1579
1580  // need AllocAligned since we allocate mem for type double
1581  LP.LiPM = (mprfloat **)Alloc( LP.LiPM_rows * sizeof(mprfloat *) );  // LP matrix
1582  for( i= 0; i < LP.LiPM_rows; i++ )
1583  {
1584    // Mem must be allocated aligned, also for type double!
1585    LP.LiPM[i] = (mprfloat *)AllocAligned0( LP.LiPM_cols * sizeof(mprfloat) );
1586    // LP.LiPM[i] = (mprfloat *)Alloc0( LP.LiPM_cols * sizeof(mprfloat) );
1587  }
1588
1589  LP.iposv = (int *)Alloc0( (idelem * MAXPOINTS) * sizeof(int) );
1590  LP.izrov = (int *)Alloc0( (idelem * MAXPOINTS) * sizeof(int) );
1591
1592  // get shift vector
1593#ifdef mprTEST
1594  shift[0]=0.005; shift[1]=0.003; shift[2]=0.008; shift[3]=0.005; shift[4]=0.002;
1595  shift[5]=0.1; shift[6]=0.3; shift[7]=0.2; shift[8]=0.4; shift[9]=0.2;
1596#else
1597  randomVector( idelem, shift );
1598#endif
1599#ifdef mprDEBUG_PROT
1600  Print(" shift vector: ");
1601  for ( i= 1; i <= idelem; i++ ) Print(" %.12f ",(double)shift[i]);
1602  PrintLn();
1603#endif
1604
1605  // evaluate convex hull for supports of gls
1606  convexHull chnp( &LP );
1607  Qi= chnp.newtonPolytopes( gls );
1608
1609#ifdef mprMINKSUM
1610  E= minkSumAll( Qi, n+1, n);
1611#else
1612  // get inner points
1613  mayanPyramidAlg mpa( &LP );
1614  E= mpa.getInnerPoints( Qi, shift );
1615#endif
1616
1617#ifdef mprDEBUG_ALL
1618#ifdef mprMINKSUM
1619  Print("(MinkSum)");
1620#endif
1621  Print("\n E = (Q_0 + ... + Q_n) \\cap \\N :\n");
1622  for ( pnt= 1; pnt <= E->num; pnt++ )
1623  {
1624    Print("%d: <",pnt);print_exp( (*E)[pnt], E->dim );Print(">\n");
1625  }
1626  PrintLn();
1627#endif
1628
1629#ifdef mprTEST
1630  int lift[5][5];
1631  lift[0][1]=3; lift[0][2]=4; lift[0][3]=8;  lift[0][4]=2;
1632  lift[1][1]=6; lift[1][2]=1; lift[1][3]=7;  lift[1][4]=4;
1633  lift[2][1]=2; lift[2][2]=5; lift[2][3]=9;  lift[2][4]=6;
1634  lift[3][1]=2; lift[3][2]=1; lift[3][3]=9;  lift[3][4]=5;
1635  lift[4][1]=3; lift[4][2]=7; lift[4][3]=1;  lift[4][4]=5;
1636  // now lift everything
1637  for ( i= 0; i <= n; i++ ) Qi[i]->lift( lift[i] );
1638  E->dim++;
1639#else
1640  // now lift everything
1641  for ( i= 0; i <= n; i++ ) Qi[i]->lift();
1642  E->dim++;
1643#endif
1644
1645  // run Row Content Function for every point in E
1646  for ( pnt= 1; pnt <= E->num; pnt++ )
1647  {
1648    RC( Qi, E, pnt, shift );
1649  }
1650
1651  // remove points not in cells
1652  k= E->num;
1653  for ( pnt= k; pnt > 0; pnt-- )
1654  {
1655    if ( (*E)[pnt]->rcPnt == NULL )
1656    {
1657      E->removePoint(pnt);
1658      mprSTICKYPROT(ST_SPARSE_RCRJ);
1659    }
1660  }
1661  mprSTICKYPROT("\n");
1662
1663#ifdef mprDEBUG_PROT
1664  Print(" points which lie in a cell:\n");
1665  for ( pnt= 1; pnt <= E->num; pnt++ )
1666  {
1667    Print("%d: <",pnt);print_exp( (*E)[pnt], E->dim );Print(">\n");
1668  }
1669  PrintLn();
1670#endif
1671
1672  // unlift to old dimension, sort
1673  for ( i= 0; i <= n; i++ ) Qi[i]->unlift();
1674  E->unlift();
1675  E->sort();
1676
1677#ifdef mprDEBUG_ALL
1678  Print(" points with a[ij] (%d):\n",E->num);
1679  for ( pnt= 1; pnt <= E->num; pnt++ )
1680  {
1681    Print("Punkt p \\in E[%d]: <",pnt);print_exp( (*E)[pnt], E->dim );
1682    Print(">, RC(p) = (i:%d, j:%d), a[i,j] = <",(*E)[pnt]->rc.set,(*E)[pnt]->rc.pnt);
1683    //print_exp( (Qi[(*E)[pnt]->rc.set])[(*E)[pnt]->rc.pnt], E->dim );Print("> = <");
1684    print_exp( (*E)[pnt]->rcPnt, E->dim );Print(">\n");
1685  }
1686#endif
1687
1688  // now create matrix
1689  if ( createMatrix( E ) != E->num )
1690  {
1691    // this can happen if the shiftvector shift is to large or not generic
1692    istate= resMatrixBase::fatalError;
1693    WerrorS("resMatrixSparse::resMatrixSparse: Error in resMatrixSparse::createMatrix!");
1694    goto theEnd;
1695    //return;
1696  }
1697
1698 theEnd:
1699  // clean up
1700  for ( i= 0; i < idelem; i++ )
1701  {
1702    delete Qi[i];
1703  }
1704  Free( (ADDRESS) Qi, idelem * sizeof(pointSet*) );
1705
1706  delete E;
1707
1708  for( i= 0; i < LP.LiPM_rows; i++ )
1709  {
1710    FreeAligned( (ADDRESS) LP.LiPM[i], LP.LiPM_cols * sizeof(mprfloat) );
1711    //    Free( (ADDRESS) LP.LiPM[i], LP.LiPM_cols * sizeof(mprfloat) );
1712  }
1713  Free( (ADDRESS) LP.LiPM, LP.LiPM_rows * sizeof(mprfloat *) );
1714
1715  Free( (ADDRESS) LP.iposv, (idelem * MAXPOINTS) * sizeof(int) );
1716  Free( (ADDRESS) LP.izrov, (idelem * MAXPOINTS) * sizeof(int) );
1717}
1718
1719//----------------------------------------------------------------------------------------
1720
1721resMatrixSparse::~resMatrixSparse()
1722{
1723  delete uRPos;
1724  idDelete( &rmat );
1725}
1726
1727const ideal resMatrixSparse::getMatrix()
1728{
1729  int i,j,rp,cp;
1730  poly pp,phelp,piter,pgls;
1731
1732  // copy original sparse res matrix
1733  ideal rmat_out= idCopy(rmat);
1734
1735  // now fill in coeffs of f0
1736  for ( i= 1; i <= numSet0; i++ )
1737  {
1738
1739    pgls= (gls->m)[0]; // f0
1740
1741    // get matrix row and delete it
1742    pp= (rmat_out->m)[IMATELEM(*uRPos,i,1)];
1743    pDelete( &pp );
1744    pp= NULL;
1745    phelp= pp;
1746    piter= NULL;
1747
1748    // u_1,..,u_k
1749    cp=2;
1750    while ( pNext(pgls) )
1751    {
1752      phelp= pOne();
1753      pSetCoeff( phelp, nCopy(pGetCoeff(pgls)) );
1754      pSetComp( phelp, IMATELEM(*uRPos,i,cp) );
1755      if ( piter )
1756      {
1757        pNext(piter)= phelp;
1758        piter= phelp;
1759      }
1760      else
1761      {
1762        pp= phelp;
1763        piter= phelp;
1764      }
1765      cp++;
1766      pIter( pgls );
1767    }
1768    // u0, now pgls points to last monom
1769    phelp= pOne();
1770    pSetCoeff( phelp, nCopy(pGetCoeff(pgls)) );
1771    //pSetComp( phelp, IMATELEM(*uRPos,i,idelem+1) );
1772    pSetComp( phelp, IMATELEM(*uRPos,i,pLength((gls->m)[0])+1) );
1773    pNext(piter)= phelp;
1774    (rmat_out->m)[IMATELEM(*uRPos,i,1)]= pp;
1775  }
1776
1777  return rmat_out;
1778}
1779
1780// Fills in resMat[][] with evpoint[] and gets determinant
1781//    uRPos[i][1]: row of matrix
1782//    uRPos[i][idelem+1]: col of u(0)
1783//    uRPos[i][2..idelem]: col of u(1) .. u(n)
1784//    i= 1 .. numSet0
1785const number resMatrixSparse::getDetAt( const number* evpoint )
1786{
1787  int i,cp,rp;
1788  poly pp,phelp,piter;
1789
1790  mprPROTnl("smCallDet");
1791
1792  for ( i= 1; i <= numSet0; i++ )
1793  {
1794    pp= (rmat->m)[IMATELEM(*uRPos,i,1)];
1795    pDelete( &pp );
1796    pp= NULL;
1797    phelp= pp;
1798    piter= NULL;
1799    // u_1,..,u_n
1800    for ( cp= 2; cp <= idelem; cp++ )
1801    {
1802      if ( !nIsZero(evpoint[cp-1]) )
1803      {
1804        phelp= pOne();
1805        pSetCoeff( phelp, nCopy(evpoint[cp-1]) );
1806        pSetComp( phelp, IMATELEM(*uRPos,i,cp) );
1807        if ( piter )
1808        {
1809          pNext(piter)= phelp;
1810          piter= phelp;
1811        }
1812        else
1813        {
1814          pp= phelp;
1815          piter= phelp;
1816        }
1817      }
1818    }
1819    // u0
1820    phelp= pOne();
1821    pSetCoeff( phelp, nCopy(evpoint[0]) );
1822    pSetComp( phelp, IMATELEM(*uRPos,i,idelem+1) );
1823    pNext(piter)= phelp;
1824    (rmat->m)[IMATELEM(*uRPos,i,1)]= pp;
1825  }
1826
1827  mprSTICKYPROT(ST__DET); // 1
1828
1829  poly pres= smCallDet( rmat );
1830  number numres= nCopy( pGetCoeff( pres ) );
1831  pDelete( &pres );
1832
1833  mprSTICKYPROT(ST__DET); // 2
1834
1835  return ( numres );
1836}
1837
1838// Fills in resMat[][] with evpoint[] and gets determinant
1839//    uRPos[i][1]: row of matrix
1840//    uRPos[i][idelem+1]: col of u(0)
1841//    uRPos[i][2..idelem]: col of u(1) .. u(n)
1842//    i= 1 .. numSet0
1843const poly resMatrixSparse::getUDet( const number* evpoint )
1844{
1845  int i,cp,rp;
1846  poly pp,phelp,piter;
1847
1848  mprPROTnl("smCallDet");
1849
1850  for ( i= 1; i <= numSet0; i++ )
1851  {
1852    pp= (rmat->m)[IMATELEM(*uRPos,i,1)];
1853    pDelete( &pp );
1854    pp= NULL;
1855    phelp= pp;
1856    piter= NULL;
1857    for ( cp= 2; cp <= idelem; cp++ ) { // u1 .. un
1858      if ( !nIsZero(evpoint[cp-1]) )
1859      {
1860        phelp= pOne();
1861        pSetCoeff( phelp, nCopy(evpoint[cp-1]) );
1862        pSetComp( phelp, IMATELEM(*uRPos,i,cp) );
1863        if ( piter )
1864        {
1865          pNext(piter)= phelp;
1866          piter= phelp;
1867        }
1868        else
1869        {
1870          pp= phelp;
1871          piter= phelp;
1872        }
1873      }
1874    }
1875    // u0
1876    phelp= pOne();
1877    pSetExp(phelp,1,1);
1878    pSetComp( phelp, IMATELEM(*uRPos,i,idelem+1) );
1879    pNext(piter)= phelp;
1880    (rmat->m)[IMATELEM(*uRPos,i,1)]= pp;
1881  }
1882
1883  mprSTICKYPROT(ST__DET); // 1
1884
1885  poly pres= smCallDet( rmat );
1886
1887  mprSTICKYPROT(ST__DET); // 2
1888
1889  return ( pres );
1890}
1891//<-
1892
1893//-----------------------------------------------------------------------------
1894//-------------- dense resultant matrix ---------------------------------------
1895//-----------------------------------------------------------------------------
1896
1897//-> dense resultant matrix
1898//
1899class resVector;
1900
1901/* dense resultant matrix */
1902class resMatrixDense : virtual public resMatrixBase
1903{
1904public:
1905  /**
1906   * _gls: system of multivariate polynoms
1907   * special: -1 -> resMatrixDense is a symbolic matrix
1908   *    0,1, ... -> resMatrixDense ist eine u-Resultante, wobei special das
1909   *                        lineare u-Polynom angibt
1910   */
1911  resMatrixDense( const ideal _gls, const int special = SNONE );
1912  ~resMatrixDense();
1913
1914  /** column vector of matrix, index von 0 ... numVectors-1 */
1915  resVector *getMVector( const int i );
1916
1917  /** Returns the matrix M in an usable presentation */
1918  const ideal getMatrix();
1919
1920  /** Returns the submatrix M' of M in an usable presentation */
1921  const ideal getSubMatrix();
1922
1923  /** Evaluate the determinant of the matrix M at the point evpoint
1924   * where the ui's are replaced by the components of evpoint.
1925   * Uses singclap_det from fractory.
1926   */
1927  const number getDetAt( const number* evpoint );
1928
1929  /** Evaluates the determinant of the submatrix M'.
1930   * Since the matrix is numerically, no evaluation point is needed.
1931   * Uses singclap_det from fractory.
1932   */
1933  const number getSubDet();
1934
1935private:
1936  /** deactivated copy constructor */
1937  resMatrixDense( const resMatrixDense & );
1938
1939  /** Generate the "matrix" M. Each column is presented by a resVector
1940   * holding all entries for this column.
1941   */
1942  void generateBaseData();
1943
1944  /** Generates needed set of monoms, split them into sets S0, ... Sn and
1945   * check if reduced/nonreduced and calculate size of submatrix.
1946   */
1947  void generateMonomData( int deg, intvec* polyDegs , intvec* iVO );
1948
1949  /** Recursively generate all homogeneous monoms of
1950   * pVariables variables of degree deg.
1951   */
1952  void generateMonoms( poly m, int var, int deg );
1953
1954  /** Creates quadratic matrix M of size numVectors for later use.
1955   * u0, u1, ...,un are replaced by 0.
1956   * Entries equal to 0 are not initialized ( == NULL)
1957   */
1958  void createMatrix();
1959
1960private:
1961  resVector *resVectorList;
1962
1963  int veclistmax;
1964  int veclistblock;
1965  int numVectors;
1966  int subSize;
1967
1968  matrix m;
1969};
1970//<-
1971
1972//-> struct resVector
1973/* Holds a row vector of the dense resultant matrix */
1974struct resVector
1975{
1976public:
1977  void init()
1978  {
1979    isReduced = FALSE;
1980    elementOfS = SFREE;
1981    mon = NULL;
1982  }
1983  void init( const poly m )
1984  {
1985    isReduced = FALSE;
1986    elementOfS = SFREE;
1987    mon = m;
1988  }
1989
1990  /** index von 0 ... numVectors-1 */
1991  poly getElem( const int i );
1992
1993  /** index von 0 ... numVectors-1 */
1994  number getElemNum( const int i );
1995
1996  // variables
1997  poly mon;
1998  poly dividedBy;
1999  bool isReduced;
2000
2001  /** number of the set S mon is element of */
2002  int elementOfS;
2003
2004  /** holds the index of u0, u1, ..., un, if (elementOfS == linPolyS)
2005   *  the size is given by pVariables
2006   */
2007  int *numColParNr;
2008
2009  /** holds the column vector if (elementOfS != linPolyS) */
2010  number *numColVector;
2011
2012  /** size of numColVector */
2013  int numColVectorSize;
2014
2015  number *numColVecCopy;
2016};
2017//<-
2018
2019//-> resVector::*
2020poly resVector::getElem( const int i ) // inline ???
2021{
2022  assume( 0 < i || i > numColVectorSize );
2023  poly out= pOne();
2024  pSetCoeff( out, numColVector[i] );
2025  pTest( out );
2026  return( out );
2027}
2028
2029number resVector::getElemNum( const int i ) // inline ??
2030{
2031  assume( i >= 0 && i < numColVectorSize );
2032  return( numColVector[i] );
2033}
2034//<-
2035
2036//-> resMatrixDense::*
2037resMatrixDense::resMatrixDense( const ideal _gls, const int special )
2038  : resMatrixBase()
2039{
2040  int i;
2041
2042  sourceRing=currRing;
2043  gls= idCopy( _gls );
2044  linPolyS= special;
2045  m=NULL;
2046
2047  // init all
2048  generateBaseData();
2049
2050  totDeg= 1;
2051  for ( i= 0; i < IDELEMS(gls); i++ )
2052  {
2053    totDeg*=pTotaldegree( (gls->m)[i] );
2054  }
2055
2056  mprSTICKYPROT2("  resultant deg: %d\n",totDeg);
2057
2058  istate= resMatrixBase::ready;
2059}
2060
2061resMatrixDense::~resMatrixDense()
2062{
2063  int i,j;
2064  for (i=0; i < numVectors; i++)
2065  {
2066    pDelete( &resVectorList[i].mon );
2067    pDelete( &resVectorList[i].dividedBy );
2068    for ( j=0; j < resVectorList[i].numColVectorSize; j++ )
2069    {
2070        nDelete( resVectorList[i].numColVector+j );
2071    }
2072    Free( (ADDRESS)resVectorList[i].numColVector, numVectors*sizeof( number ) );
2073    Free( (ADDRESS)resVectorList[i].numColParNr, (pVariables+1) * sizeof(int) );
2074  }
2075
2076  Free( (ADDRESS)resVectorList, veclistmax*sizeof( resVector ) );
2077
2078  // free matrix m
2079  if ( m != NULL )
2080  {
2081    for ( i= 1; i <= numVectors; i++ )
2082      for ( j= 1; j <= numVectors; j++ )
2083        pDelete( &MATELEM(m , i, j) );
2084    Free( (ADDRESS)m->m, numVectors * numVectors * sizeof(poly) );
2085    FreeSizeOf( (ADDRESS)m, ip_smatrix );
2086  }
2087}
2088
2089// mprSTICKYPROT:
2090// ST_DENSE_FR: found row S0
2091// ST_DENSE_NR: normal row
2092void resMatrixDense::createMatrix()
2093{
2094  int k,i,j;
2095  resVector *vecp;
2096
2097  m= mpNew( numVectors, numVectors );
2098
2099  for ( i= 1; i <= MATROWS( m ); i++ )
2100    for ( j= 1; j <= MATCOLS( m ); j++ )
2101    {
2102      MATELEM(m,i,j)= pInit();
2103      pSetCoeff0( MATELEM(m,i,j), nInit(0) );
2104    }
2105
2106
2107  for ( k= 0; k <= numVectors - 1; k++ )
2108  {
2109    if ( linPolyS == getMVector(k)->elementOfS )
2110    {
2111      mprSTICKYPROT(ST_DENSE_FR);
2112      for ( i= 0; i < pVariables; i++ )
2113      {
2114        MATELEM(m,numVectors-k,numVectors-(getMVector(k)->numColParNr)[i])= pInit();
2115      }
2116    }
2117    else
2118    {
2119      mprSTICKYPROT(ST_DENSE_NR);
2120      vecp= getMVector(k);
2121      for ( i= 0; i < numVectors; i++)
2122        if ( !nIsZero( vecp->getElemNum(i) ) )
2123        {
2124          MATELEM(m,numVectors - k,i + 1)= pInit();
2125          pSetCoeff( MATELEM(m,numVectors - k,i + 1), nCopy(vecp->getElemNum(i)) );
2126        }
2127    }
2128  } // for
2129  mprSTICKYPROT("\n");
2130
2131#ifdef mprDEBUG_ALL
2132  for ( k= numVectors - 1; k >= 0; k-- )
2133    if ( linPolyS == getMVector(k)->elementOfS )
2134    {
2135      for ( i=0; i < pVariables; i++ )
2136      {
2137        Print(" %d ",(getMVector(k)->numColParNr)[i]);
2138      }
2139      PrintLn();
2140    }
2141  for (i=1; i <= numVectors; i++)
2142  {
2143    for (j=1; j <= numVectors; j++ )
2144    {
2145      pWrite0(MATELEM(m,i,j));Print("  ");
2146    }
2147    PrintLn();
2148  }
2149#endif
2150}
2151
2152// mprSTICKYPROT:
2153// ST_DENSE_MEM: more mem allocated
2154// ST_DENSE_NMON: new monom added
2155void resMatrixDense::generateMonoms( poly m, int var, int deg )
2156{
2157  if ( !deg ) { // deg == 0
2158    poly mon = pCopy( m );
2159    pSetm( mon );
2160
2161    if ( numVectors == veclistmax )
2162    {
2163      resVectorList= (resVector * )ReAlloc( resVectorList,
2164                                            (veclistmax) * sizeof( resVector ),
2165                                            (veclistmax + veclistblock) * sizeof( resVector ) );
2166      int k;
2167      for ( k= veclistmax; k < (veclistmax + veclistblock); k++ )
2168        resVectorList[k].init();
2169      veclistmax+= veclistblock;
2170      mprSTICKYPROT(ST_DENSE_MEM);
2171
2172    }
2173    resVectorList[numVectors].init( mon );
2174    numVectors++;
2175    mprSTICKYPROT(ST_DENSE_NMON);
2176    return;
2177  }
2178  else
2179  {
2180    if ( var == pVariables+1 ) return;
2181    poly newm = pCopy( m );
2182    while ( deg >= 0 )
2183    {
2184      generateMonoms( newm, var+1, deg );
2185      pIncrExp( newm, var );
2186      pSetm( newm );
2187      deg--;
2188    }
2189    pDelete( & newm );
2190  }
2191
2192  return;
2193}
2194
2195void resMatrixDense::generateMonomData( int deg, intvec* polyDegs , intvec* iVO )
2196{
2197  int i,j,k;
2198
2199  // init monomData
2200  veclistblock= 512;
2201  veclistmax= veclistblock;
2202  resVectorList= (resVector *)Alloc( veclistmax*sizeof( resVector ) );
2203
2204  // Init resVector()s
2205  for ( j= veclistmax - 1; j >= 0; j-- ) resVectorList[j].init();
2206  numVectors= 0;
2207
2208  // Generate all monoms of degree deg
2209  poly start= pOne();
2210  generateMonoms( start, 1, deg );
2211  pDelete( & start );
2212
2213  mprSTICKYPROT("\n");
2214
2215  // Check for reduced monoms
2216  // First generate polyDegs.rows() monoms
2217  //  x(k)^(polyDegs[k]),  0 <= k < polyDegs.rows()
2218  ideal pDegDiv= idInit( polyDegs->rows(), 1 );
2219  for ( k= 0; k < polyDegs->rows(); k++ )
2220  {
2221    poly p= pOne();
2222    pSetExp( p, k + 1, (*polyDegs)[k] );
2223    pSetm( p );
2224    (pDegDiv->m)[k]= p;
2225  }
2226
2227  // Now check each monom if it is reduced.
2228  // A monom monom is called reduced if there exists
2229  // exactly one x(k)^(polyDegs[k]) that divides the monom.
2230  int divCount;
2231  for ( j= numVectors - 1; j >= 0; j-- )
2232  {
2233    divCount= 0;
2234    for ( k= 0; k < IDELEMS(pDegDiv); k++ )
2235      if ( pDivisibleBy2( (pDegDiv->m)[k], resVectorList[j].mon ) )
2236        divCount++;
2237    resVectorList[j].isReduced= (divCount == 1);
2238  }
2239
2240  // create the sets S(k)s
2241  // a monom x(i)^deg, deg given, is element of the set S(i)
2242  // if all x(0)^(polyDegs[0]) ... x(i-1)^(polyDegs[i-1]) DONT divide
2243  // x(i)^deg and only x(i)^(polyDegs[i]) divides x(i)^deg
2244  bool doInsert;
2245  for ( k= 0; k < iVO->rows(); k++)
2246  {
2247    //mprPROTInl(" ------------ var:",(*iVO)[k]);
2248    for ( j= numVectors - 1; j >= 0; j-- )
2249    {
2250      //mprPROTPnl("testing monom",resVectorList[j].mon);
2251      if ( resVectorList[j].elementOfS == SFREE )
2252      {
2253        //mprPROTnl("\tfree");
2254        if ( pDivisibleBy2( (pDegDiv->m)[ (*iVO)[k] ], resVectorList[j].mon ) )
2255        {
2256          //mprPROTPnl("\tdivisible by ",(pDegDiv->m)[ (*iVO)[k] ]);
2257          doInsert=TRUE;
2258          for ( i= 0; i < k; i++ )
2259          {
2260            //mprPROTPnl("\tchecking db ",(pDegDiv->m)[ (*iVO)[i] ]);
2261            if ( pDivisibleBy2( (pDegDiv->m)[ (*iVO)[i] ], resVectorList[j].mon ) )
2262            {
2263              //mprPROTPnl("\t and divisible by",(pDegDiv->m)[ (*iVO)[i] ]);
2264              doInsert=FALSE;
2265              break;
2266            }
2267          }
2268          if ( doInsert )
2269          {
2270            //mprPROTInl("\t------------------> S ",(*iVO)[k]);
2271            resVectorList[j].elementOfS= (*iVO)[k];
2272            resVectorList[j].dividedBy= pCopy( (pDegDiv->m)[ (*iVO)[i] ] );
2273            pSetm( resVectorList[j].dividedBy );
2274          }
2275        }
2276      }
2277    }
2278  }
2279
2280  // size of submatrix M', equal to number of nonreduced monoms
2281  // (size of matrix M is equal to number of monoms=numVectors)
2282  subSize= 0;
2283  int sub;
2284  for ( i= 0; i < polyDegs->rows(); i++ )
2285  {
2286    sub= 1;
2287    for ( k= 0; k < polyDegs->rows(); k++ )
2288      if ( i != k ) sub*= (*polyDegs)[k];
2289    subSize+= sub;
2290  }
2291  subSize= numVectors - subSize;
2292
2293  // pDegDiv wieder freigeben!
2294  idDelete( &pDegDiv );
2295
2296#ifdef mprDEBUG_ALL
2297  // Print a list of monoms and their properties
2298  Print("// \n");
2299  for ( j= numVectors - 1; j >= 0; j-- )
2300  {
2301    Print("// %s, S(%d),  db ",
2302          resVectorList[j].isReduced?"reduced":"nonreduced",
2303          resVectorList[j].elementOfS);
2304    pWrite0(resVectorList[j].dividedBy);
2305    Print("  monom ");
2306    pWrite(resVectorList[j].mon);
2307  }
2308  Print("// size: %d, subSize: %d\n",numVectors,subSize);
2309#endif
2310}
2311
2312void resMatrixDense::generateBaseData()
2313{
2314  int k,j,i;
2315  number matEntry;
2316  poly pmatchPos;
2317  poly pi,factor,pmp;
2318
2319  // holds the degrees of F0, F1, ..., Fn
2320  intvec polyDegs( IDELEMS(gls) );
2321  for ( k= 0; k < IDELEMS(gls); k++ )
2322    polyDegs[k]= pTotaldegree( (gls->m)[k] );
2323
2324  // the internal Variable Ordering
2325  // make sure that the homogenization variable goes last!
2326  intvec iVO( pVariables );
2327  if ( linPolyS != SNONE )
2328  {
2329    iVO[pVariables - 1]= linPolyS;
2330    int p=0;
2331    for ( k= pVariables - 1; k >= 0; k-- )
2332    {
2333      if ( k != linPolyS )
2334      {
2335        iVO[p]= k;
2336        p++;
2337      }
2338    }
2339  }
2340  else
2341  {
2342    linPolyS= 0;
2343    for ( k= 0; k < pVariables; k++ )
2344      iVO[k]= pVariables - k - 1;
2345  }
2346
2347  // the critical degree d= sum( deg(Fi) ) - n
2348  int sumDeg= 0;
2349  for ( k= 0; k < polyDegs.rows(); k++ )
2350    sumDeg+= polyDegs[k];
2351  sumDeg-= polyDegs.rows() - 1;
2352
2353  // generate the base data
2354  generateMonomData( sumDeg, &polyDegs, &iVO );
2355
2356  // generate "matrix"
2357  for ( k= numVectors - 1; k >= 0; k-- )
2358  {
2359    if ( resVectorList[k].elementOfS != linPolyS )
2360    {
2361      // column k is a normal column with numerical or symbolic entries
2362      // init stuff
2363      resVectorList[k].numColParNr= NULL;
2364      resVectorList[k].numColVectorSize= numVectors;
2365      resVectorList[k].numColVector= (number *)Alloc( numVectors*sizeof( number ) );
2366      for ( i= 0; i < numVectors; i++ ) resVectorList[k].numColVector[i]= nInit(0);
2367
2368      // compute row poly
2369      poly pi= pMult( pCopy( (gls->m)[ resVectorList[k].elementOfS ] ) , pCopy( resVectorList[k].mon ) );
2370      pSetm( pi );
2371      pi= pDivideM( pCopy( pi ), pCopy( resVectorList[k].dividedBy ) );
2372      pSetm( pi );
2373
2374      // fill in "matrix"
2375      while ( pi )
2376      {
2377        matEntry= nCopy(pGetCoeff(pi));
2378        pmatchPos= pHead0( pi );
2379        pSetCoeff( pmatchPos, nInit(1) );
2380        pSetm( pmatchPos );
2381
2382        for ( i= 0; i < numVectors; i++)
2383          if ( pEqual( pmatchPos, resVectorList[i].mon ) )
2384            break;
2385
2386        resVectorList[k].numColVector[numVectors - i - 1] = nCopy(matEntry);
2387
2388        pDelete( &pmatchPos );
2389        nDelete( &matEntry );
2390
2391        pIter( pi );
2392      }
2393      pDelete( &pi );
2394    }
2395    else
2396    {
2397      // column is a special column, i.e. is generated by S0 and F0
2398      // safe only the positions of the ui's in the column
2399      //mprPROTInl(" setup of numColParNr ",k);
2400      resVectorList[k].numColVectorSize= 0;
2401      resVectorList[k].numColVector= NULL;
2402      resVectorList[k].numColParNr= (int *)Alloc( (pVariables+1) * sizeof(int) );
2403      for ( i= 0; i < pVariables; i++ ) resVectorList[k].numColParNr[i]= 0;
2404
2405      pi= (gls->m)[ resVectorList[k].elementOfS ];
2406      factor= pDivideM( pCopy( resVectorList[k].mon ), pCopy( resVectorList[k].dividedBy ) );
2407
2408      j=0;
2409      while ( pi ) { // fill in "matrix"
2410        pmp= pMult( pHead( pi ), pCopy( factor ) );
2411        pSetm( pmp );pTest( pi );
2412
2413        for ( i= 0; i < numVectors; i++)
2414          if ( pEqual( pmp, resVectorList[i].mon ) )
2415            break;
2416
2417        resVectorList[k].numColParNr[j]= i;
2418        pDelete( &pmp );
2419        pIter( pi );
2420        j++;
2421      }
2422      pDelete( &pi );
2423      pDelete( &factor );
2424    }
2425  } // for ( k= numVectors - 1; k >= 0; k-- )
2426
2427  mprSTICKYPROT2(" size of matrix:    %d\n",numVectors);
2428  mprSTICKYPROT2(" size of submatrix: %d\n",subSize);
2429
2430  // create the matrix M
2431  createMatrix();
2432}
2433
2434resVector *resMatrixDense::getMVector(int i)
2435{
2436  assume( i >= 0 && i < numVectors );
2437  return &resVectorList[i];
2438}
2439
2440const ideal resMatrixDense::getMatrix()
2441{
2442  int k,i,j;
2443
2444  // copy matrix
2445  matrix resmat= mpNew(numVectors,numVectors);
2446  for (i=1; i <= numVectors; i++)
2447  {
2448    for (j=1; j <= numVectors; j++ )
2449    {
2450      if ( MATELEM(m,i,j) && pGetCoeff(MATELEM(m,i,j)) )
2451      {
2452        MATELEM(resmat,i,j)= pCopy( MATELEM(m,i,j) );
2453      }
2454    }
2455  }
2456  for (i=0; i < numVectors; i++)
2457  {
2458    if ( resVectorList[i].elementOfS == linPolyS )
2459    {
2460      for (j=1; j <= pVariables; j++ )
2461      {
2462        if ( MATELEM(resmat,numVectors-i,numVectors-resVectorList[i].numColParNr[j-1]) )
2463          pDelete( &MATELEM(resmat,numVectors-i,numVectors-resVectorList[i].numColParNr[j-1]) );
2464        MATELEM(resmat,numVectors-i,numVectors-resVectorList[i].numColParNr[j-1])= pOne();
2465        // FIX ME
2466        if ( true )
2467        {
2468          pSetCoeff( MATELEM(resmat,numVectors-i,numVectors-resVectorList[i].numColParNr[j-1]), nPar(j) );
2469        }
2470        else
2471        {
2472          pSetExp( MATELEM(resmat,numVectors-i,numVectors-resVectorList[i].numColParNr[j-1]), j, 1 );
2473        }
2474      }
2475    }
2476  }
2477
2478  // obachman: idMatrix2Module frees resmat !!
2479  ideal resmod= idMatrix2Module(resmat);
2480  return resmod;
2481}
2482
2483const ideal resMatrixDense::getSubMatrix()
2484{
2485  int k,i,j,l;
2486  resVector *vecp;
2487
2488  // generate quadratic matrix resmat of size subSize
2489  matrix resmat= mpNew( subSize, subSize );
2490
2491  j=1;
2492  for ( k= numVectors - 1; k >= 0; k-- )
2493  {
2494    vecp= getMVector(k);
2495    if ( vecp->isReduced ) continue;
2496    l=1;
2497    for ( i= numVectors - 1; i >= 0; i-- )
2498    {
2499      if ( getMVector(i)->isReduced ) continue;
2500      if ( !nIsZero(vecp->getElemNum(numVectors - i - 1)) )
2501      {
2502        MATELEM(resmat,j,l)= pInit();
2503        MATELEM(resmat,j,l)= pCopy( vecp->getElem(numVectors-i-1) );
2504      }
2505      l++;
2506    }
2507    j++;
2508  }
2509
2510  // obachman: idMatrix2Module frees resmat !!
2511  ideal resmod= idMatrix2Module(resmat);
2512  return resmod;
2513}
2514
2515const number resMatrixDense::getDetAt( const number* evpoint )
2516{
2517  int k,i,j;
2518
2519  // copy evaluation point into matrix
2520  // p0, p1, ..., pn replace u0, u1, ..., un
2521  for ( k= numVectors - 1; k >= 0; k-- )
2522  {
2523    if ( linPolyS == getMVector(k)->elementOfS )
2524    {
2525      for ( i= 0; i < pVariables; i++ )
2526      {
2527        pSetCoeff( MATELEM(m,numVectors-k,numVectors-(getMVector(k)->numColParNr)[i]),
2528                   nCopy(evpoint[i]) );
2529      }
2530    }
2531  }
2532
2533  mprSTICKYPROT(ST__DET);
2534
2535  // evaluate determinant of matrix m using factory singclap_det
2536  #ifdef HAVE_FACTORY
2537  poly res= singclap_det( m );
2538  #else
2539  poly res= mpDetBareiss( m );
2540  #endif
2541
2542  // avoid errors for det==0
2543  number numres;
2544  if ( res && pGetCoeff( res ) )
2545  {
2546    numres= nCopy( pGetCoeff( res ) );
2547  }
2548  else
2549  {
2550    numres= nInit(0);
2551    mprPROT("0");
2552  }
2553  pDelete( &res );
2554
2555  mprSTICKYPROT(ST__DET);
2556
2557  return( numres );
2558}
2559
2560const number resMatrixDense::getSubDet()
2561{
2562  int k,i,j,l;
2563  resVector *vecp;
2564
2565  // generate quadratic matrix mat of size subSize
2566  matrix mat= mpNew( subSize, subSize );
2567
2568  for ( i= 1; i <= MATROWS( mat ); i++ )
2569  {
2570    for ( j= 1; j <= MATCOLS( mat ); j++ )
2571    {
2572      MATELEM(mat,i,j)= pInit();
2573      pSetCoeff0( MATELEM(mat,i,j), nInit(0) );
2574    }
2575  }
2576  j=1;
2577  for ( k= numVectors - 1; k >= 0; k-- )
2578  {
2579    vecp= getMVector(k);
2580    if ( vecp->isReduced ) continue;
2581    l=1;
2582    for ( i= numVectors - 1; i >= 0; i-- )
2583    {
2584      if ( getMVector(i)->isReduced ) continue;
2585      if ( vecp->getElemNum(numVectors - i - 1) && !nIsZero(vecp->getElemNum(numVectors - i - 1)) )
2586      {
2587        pSetCoeff(MATELEM(mat, j , l ), nCopy(vecp->getElemNum(numVectors - i - 1)));
2588      }
2589      /* else
2590      {
2591           MATELEM(mat, j , l )= pOne();
2592           pSetCoeff(MATELEM(mat, j , l ), nInit(0) );
2593      }
2594      */
2595      l++;
2596    }
2597    j++;
2598  }
2599
2600  #ifdef HAVE_FACTORY
2601  poly res= singclap_det( mat );
2602  #else
2603  poly res= mpDetBareiss( mat );
2604  #endif
2605
2606  number numres;
2607  if ( res && pGetCoeff( res ) )
2608  {
2609    numres= nCopy(pGetCoeff( res ));
2610    pDelete( &res );
2611  }
2612  else
2613  {
2614    numres= nInit(0);
2615  }
2616  return numres;
2617}
2618//<--
2619
2620//-----------------------------------------------------------------------------
2621//-------------- uResultant ---------------------------------------------------
2622//-----------------------------------------------------------------------------
2623
2624#define MAXEVPOINT 1000000 // 0x7fffffff
2625
2626//-> unsigned long over(unsigned long n,unsigned long d)
2627// Calculates (n+d \over d) using gmp functionality
2628//
2629unsigned long over( const unsigned long n , const unsigned long d )
2630{ // (d+n)! / ( d! n! )
2631  mpz_t res;
2632  mpz_init(res);
2633  mpz_t m,md,mn;
2634  mpz_init(m);mpz_set_ui(m,1);
2635  mpz_init(md);mpz_set_ui(md,1);
2636  mpz_init(mn);mpz_set_ui(mn,1);
2637
2638  mpz_fac_ui(m,n+d);
2639  mpz_fac_ui(md,d);
2640  mpz_fac_ui(mn,n);
2641
2642  mpz_mul(res,md,mn);
2643  mpz_tdiv_q(res,m,res);
2644
2645  mpz_clear(m);mpz_clear(md);mpz_clear(mn);
2646
2647  unsigned long result = mpz_get_ui(res);
2648  mpz_clear(res);
2649
2650  return result;
2651}
2652//<-
2653
2654//-> uResultant::*
2655uResultant::uResultant( const ideal _gls, const resMatType _rmt, BOOLEAN extIdeal )
2656  : rmt( _rmt )
2657{
2658  if ( extIdeal )
2659  {
2660    // extend given ideal by linear poly F0=u0x0 + u1x1 +...+ unxn
2661    gls= extendIdeal( _gls, linearPoly( rmt ), rmt );
2662    n= IDELEMS( gls );
2663  } else
2664    gls= idCopy( _gls );
2665
2666  switch ( rmt )
2667  {
2668  case sparseResMat:
2669    resMat= new resMatrixSparse( gls );
2670    break;
2671  case denseResMat:
2672    resMat= new resMatrixDense( gls );
2673    break;
2674  default:
2675    WerrorS("uResultant::uResultant: Unknown resultant matrix type choosen!");
2676  }
2677}
2678
2679uResultant::~uResultant( )
2680{
2681  delete resMat;
2682}
2683
2684ideal uResultant::extendIdeal( const ideal gls, poly linPoly, const resMatType rmt )
2685{
2686  ideal newGls= idCopy( gls );
2687  newGls->m= (poly *)ReAlloc( newGls->m,
2688                              IDELEMS(gls) * sizeof(poly),
2689                              (IDELEMS(gls) + 1) * sizeof(poly) );
2690  IDELEMS(newGls)++;
2691
2692  switch ( rmt )
2693  {
2694  case sparseResMat:
2695  case denseResMat:
2696    {
2697      int i;
2698      for ( i= IDELEMS(newGls)-1; i > 0; i-- )
2699      {
2700        newGls->m[i]= newGls->m[i-1];
2701      }
2702      newGls->m[0]= linPoly;
2703    }
2704    break;
2705  default:
2706    WerrorS("uResultant::extendIdeal: Unknown resultant matrix type choosen!");
2707  }
2708
2709  return( newGls );
2710}
2711
2712poly uResultant::linearPoly( const resMatType rmt )
2713{
2714  int i,j;
2715
2716  poly newlp= pOne();
2717  poly actlp, rootlp= newlp;
2718
2719  for ( i= 1; i <= pVariables; i++ )
2720  {
2721    actlp= newlp;
2722    pSetExp( actlp, i, 1 );
2723    pSetm( actlp );
2724    newlp= pOne();
2725    actlp->next= newlp;
2726  }
2727  actlp->next= NULL;
2728  pDelete( &newlp );
2729
2730  if ( rmt == sparseResMat )
2731  {
2732    newlp= pOne();
2733    actlp->next= newlp;
2734    newlp->next= NULL;
2735  }
2736  pSetm( rootlp );
2737  return ( rootlp );
2738}
2739
2740poly uResultant::interpolateDense( const number subDetVal )
2741{
2742  int i,j,p;
2743  long tdg;
2744
2745  // D is a Polynom homogeneous in the coeffs of F0 and of degree tdg = d0*d1*...*dn
2746  tdg= resMat->getDetDeg();
2747
2748  // maximum number of terms in polynom D (homogeneous, of degree tdg)
2749  // long mdg= (facul(tdg+n-1) / facul( tdg )) / facul( n - 1 );
2750  long mdg= over( n-1, tdg );
2751
2752  // maxiaml number of terms in a polynom of degree tdg
2753  long l=(long)pow( tdg+1, n );
2754
2755#ifdef mprDEBUG_PROT
2756  Print("// total deg of D: tdg %d\n",tdg);
2757  Print("// maximum number of terms in D: mdg: %d\n",mdg);
2758  Print("// maximum number of terms in polynom of deg tdg: l %d\n",l);
2759#endif
2760
2761  // we need mdg results of D(p0,p1,...,pn)
2762  number *presults;
2763  presults= (number *)Alloc( mdg * sizeof( number ) );
2764  for (i=0; i < mdg; i++) presults[i]= nInit(0);
2765
2766  number *pevpoint= (number *)Alloc( n * sizeof( number ) );
2767  number *pev= (number *)Alloc( n * sizeof( number ) );
2768  for (i=0; i < n; i++) pev[i]= nInit(0);
2769
2770  mprPROTnl("// initial evaluation point: ");
2771  // initial evaluatoin point
2772  p=1;
2773  for (i=0; i < n; i++)
2774  {
2775    // init pevpoint with primes 3,5,7,11, ...
2776    p= nextPrime( p );
2777    pevpoint[i]=nInit( p );
2778    nTest(pevpoint[i]);
2779    mprPROTNnl(" ",pevpoint[i]);
2780  }
2781
2782  // evaluate the determinant in the points pev^0, pev^1, ..., pev^mdg
2783  mprPROTnl("// evaluating:");
2784  for ( i=0; i < mdg; i++ )
2785  {
2786    for (j=0; j < n; j++)
2787    {
2788      nDelete( &pev[j] );
2789      nPower(pevpoint[j],i,&pev[j]);
2790      mprPROTN(" ",pev[j]);
2791    }
2792    mprPROTnl("");
2793
2794    nDelete( &presults[i] );
2795    presults[i]=resMat->getDetAt( pev );
2796
2797    mprSTICKYPROT(ST_BASE_EV);
2798  }
2799  mprSTICKYPROT("\n");
2800
2801  // now interpolate using vandermode interpolation
2802  mprPROTnl("// interpolating:");
2803  number *ncpoly;
2804  {
2805    vandermonde vm( mdg, n, tdg, pevpoint );
2806    ncpoly= vm.interpolateDense( presults );
2807  }
2808
2809  if ( subDetVal != NULL ) {   // divide by common factor
2810      number detdiv;
2811      for ( i= 0; i <= mdg; i++ )
2812      {
2813        detdiv= nDiv( ncpoly[i], subDetVal );
2814        nNormalize( detdiv );
2815        nDelete( &ncpoly[i] );
2816        ncpoly[i]= detdiv;
2817      }
2818    }
2819
2820#ifdef mprDEBUG_ALL
2821  PrintLn();
2822  for ( i=0; i < mdg; i++ )
2823  {
2824    nPrint(ncpoly[i]); Print(" --- ");
2825  }
2826  PrintLn();
2827#endif
2828
2829  // prepare ncpoly for later use
2830  number nn=nInit(0);
2831  for ( i=0; i < mdg; i++ )
2832  {
2833    if ( nEqual(ncpoly[i],nn) )
2834    {
2835      nDelete( &ncpoly[i] );
2836      ncpoly[i]=NULL;
2837    }
2838  }
2839  nDelete( &nn );
2840
2841  // create poly presenting the determinat of the uResultant
2842  intvec exp( n );
2843  for ( i= 0; i < n; i++ ) exp[i]=0;
2844
2845  poly result= NULL;
2846
2847  long sum=0;
2848  long c=0;
2849
2850  for ( i=0; i < l; i++ )
2851  {
2852    if ( sum == tdg )
2853    {
2854      if ( ncpoly[c] )
2855      {
2856        poly p= pOne();
2857        if ( rmt == denseResMat )
2858        {
2859          for ( j= 0; j < n; j++ ) pSetExp( p, j+1, exp[j] );
2860        }
2861        else if ( rmt == sparseResMat )
2862        {
2863          for ( j= 1; j < n; j++ ) pSetExp( p, j, exp[j] );
2864        }
2865        pSetCoeff( p, ncpoly[c] );
2866        pSetm( p );
2867        if (result) result= pAdd( pCopy(result), pCopy(p) );
2868        else result= pCopy( p );
2869        pDelete( &p );
2870      }
2871      c++;
2872    }
2873    sum=0;
2874    exp[0]++;
2875    for ( j= 0; j < n - 1; j++ )
2876    {
2877      if ( exp[j] > tdg )
2878      {
2879        exp[j]= 0;
2880        exp[j + 1]++;
2881      }
2882      sum+=exp[j];
2883    }
2884    sum+=exp[n-1];
2885  }
2886
2887  pSetm( result );
2888  pTest( result );
2889
2890  return result;
2891}
2892
2893rootContainer ** uResultant::interpolateDenseSP( BOOLEAN matchUp, const number subDetVal )
2894{
2895  int i,j,p,uvar;
2896  long tdg;
2897  int loops= (matchUp?n-2:n-1);
2898
2899  mprPROTnl("uResultant::interpolateDenseSP");
2900
2901  tdg= resMat->getDetDeg();
2902
2903  // evaluate D in tdg+1 distinct points, so
2904  // we need tdg+1 results of D(p0,1,0,...,0) =
2905  //              c(0)*u0^tdg + c(1)*u0^tdg-1 + ... + c(tdg-1)*u0 + c(tdg)
2906  number *presults;
2907  presults= (number *)Alloc( (tdg + 1) * sizeof( number ) );
2908  for ( i=0; i <= tdg; i++ ) presults[i]= nInit(0);
2909
2910  rootContainer ** roots;
2911  roots= (rootContainer **) Alloc( loops * sizeof(rootContainer*) );
2912  for ( i=0; i < loops; i++ ) roots[i]= new rootContainer(); // 0..n-2
2913
2914  number *pevpoint= (number *)Alloc( n * sizeof( number ) );
2915  for (i=0; i < n; i++) pevpoint[i]= nInit(0);
2916
2917  number *pev= (number *)Alloc( n * sizeof( number ) );
2918  for (i=0; i < n; i++) pev[i]= nInit(0);
2919
2920  // now we evaluate D(u0,-1,0,...0), D(u0,0,-1,0,...,0), ..., D(u0,0,..,0,-1)
2921  // or D(u0,k1,k2,0,...,0), D(u0,k1,k2,k3,0,...,0), ..., D(u0,k1,k2,k3,...,kn)
2922  // this gives us n-1 evaluations
2923  p=3;
2924  for ( uvar= 0; uvar < loops; uvar++ )
2925  {
2926    // generate initial evaluation point
2927    if ( matchUp )
2928    {
2929      for (i=0; i < n; i++)
2930      {
2931        // prime(random number) between 1 and MAXEVPOINT
2932        nDelete( &pevpoint[i] );
2933        if ( i == 0 )
2934        {
2935          //p= nextPrime( p );
2936          pevpoint[i]= nInit( p );
2937        }
2938        else if ( i <= uvar + 2 )
2939        {
2940          pevpoint[i]=nInit(1+(siRand() % MAXEVPOINT));
2941          //pevpoint[i]=nInit(383);
2942        }
2943        else
2944          pevpoint[i]=nInit(0);
2945        mprPROTNnl(" ",pevpoint[i]);
2946      }
2947    }
2948    else
2949    {
2950      for (i=0; i < n; i++)
2951      {
2952        // init pevpoint with  prime,0,...0,1,0,...,0
2953        nDelete( &pevpoint[i] );
2954        if ( i == 0 )
2955        {
2956          //p=nextPrime( p );
2957          pevpoint[i]=nInit( p );
2958        }
2959        else
2960          if ( i == (uvar + 1) ) pevpoint[i]= nInit(-1);
2961          else pevpoint[i]= nInit(0);
2962        mprPROTNnl(" ",pevpoint[i]);
2963      }
2964    }
2965
2966    // prepare aktual evaluation point
2967    for (i=0; i < n; i++)
2968    {
2969      nDelete( &pev[i] );
2970      pev[i]= nCopy( pevpoint[i] );
2971    }
2972    // evaluate the determinant in the points pev^0, pev^1, ..., pev^tdg
2973    for ( i=0; i <= tdg; i++ )
2974    {
2975      nDelete( &pev[0] );
2976      nPower(pevpoint[0],i,&pev[0]);          // new evpoint
2977
2978      nDelete( &presults[i] );
2979      presults[i]=resMat->getDetAt( pev );   // evaluate det at point evpoint
2980
2981      mprPROTNnl("",presults[i]);
2982
2983      mprSTICKYPROT(ST_BASE_EV);
2984      mprPROTI("",tdg-i);
2985    }
2986    mprSTICKYPROT("\n");
2987
2988    // now interpolate
2989    vandermonde vm( tdg + 1, 1, tdg, pevpoint, FALSE );
2990    number *ncpoly= vm.interpolateDense( presults );
2991
2992    if ( subDetVal != NULL ) {  // divide by common factor
2993      number detdiv;
2994      for ( i= 0; i <= tdg; i++ )
2995      {
2996        detdiv= nDiv( ncpoly[i], subDetVal );
2997        nNormalize( detdiv );
2998        nDelete( &ncpoly[i] );
2999        ncpoly[i]= detdiv;
3000      }
3001    }
3002
3003#ifdef mprDEBUG_ALL
3004    PrintLn();
3005    for ( i=0; i <= tdg; i++ )
3006    {
3007      nPrint(ncpoly[i]); Print(" --- ");
3008    }
3009    PrintLn();
3010#endif
3011
3012    // save results
3013    roots[uvar]->fillContainer( ncpoly, pevpoint, uvar+1, tdg,
3014                                (matchUp?rootContainer::cspecialmu:rootContainer::cspecial),
3015                                loops );
3016  }
3017
3018  // free some stuff: pev, presult
3019  for ( i=0; i < n; i++ ) nDelete( pev + i );
3020  Free( (ADDRESS)pev, n * sizeof( number ) );
3021
3022  for ( i=0; i <= tdg; i++ ) nDelete( presults+i );
3023  Free( (ADDRESS)presults, (tdg + 1) * sizeof( number ) );
3024
3025  return roots;
3026}
3027
3028rootContainer ** uResultant::specializeInU( BOOLEAN matchUp, const number subDetVal )
3029{
3030  int i,j,p,uvar;
3031  long tdg;
3032  poly pures,piter;
3033  int loops=(matchUp?n-2:n-1);
3034
3035  mprPROTnl("uResultant::specializeInU");
3036
3037  tdg= resMat->getDetDeg();
3038
3039  rootContainer ** roots;
3040  roots= (rootContainer **) Alloc( loops * sizeof(rootContainer*) );
3041  for ( i=0; i < loops; i++ ) roots[i]= new rootContainer(); // 0..n-2
3042
3043  number *pevpoint= (number *)Alloc( n * sizeof( number ) );
3044  for (i=0; i < n; i++) pevpoint[i]= nInit(0);
3045
3046  // now we evaluate D(u0,-1,0,...0), D(u0,0,-1,0,...,0), ..., D(u0,0,..,0,-1)
3047  // or D(u0,k1,k2,0,...,0), D(u0,k1,k2,k3,0,...,0), ..., D(u0,k1,k2,k3,...,kn)
3048  p=3;
3049  for ( uvar= 0; uvar < loops; uvar++ )
3050  {
3051    // generate initial evaluation point
3052    if ( matchUp )
3053    {
3054      for (i=0; i < n; i++)
3055      {
3056        // prime(random number) between 1 and MAXEVPOINT
3057        nDelete( &pevpoint[i] );
3058        if ( i <= uvar + 2 )
3059        {
3060          pevpoint[i]=nInit(1+(siRand() % MAXEVPOINT));
3061          //pevpoint[i]=nInit(383);
3062        } else pevpoint[i]=nInit(0);
3063        mprPROTNnl(" ",pevpoint[i]);
3064      }
3065    }
3066    else
3067    {
3068      for (i=0; i < n; i++)
3069      {
3070        // init pevpoint with  prime,0,...0,-1,0,...,0
3071        nDelete( &(pevpoint[i]) );
3072        if ( i == (uvar + 1) ) pevpoint[i]= nInit(-1);
3073        else pevpoint[i]= nInit(0);
3074        mprPROTNnl(" ",pevpoint[i]);
3075      }
3076    }
3077
3078    pures= resMat->getUDet( pevpoint );
3079
3080    number *ncpoly= (number *)Alloc( (tdg+1) * sizeof(number) );
3081
3082#ifdef MPR_TIMING
3083       BOOLEAN masi=true;
3084#endif
3085    piter= pures;
3086    for ( i= tdg; i >= 0; i-- )
3087    {
3088      //if ( piter ) Print("deg %d, pDeg(piter) %d\n",i,pTotaldegree(piter));
3089      if ( piter && pTotaldegree(piter) == i )
3090      {
3091        ncpoly[i]= nCopy( pGetCoeff( piter ) );
3092        pIter( piter );
3093#ifdef MPR_TIMING
3094       masi=false;
3095#endif
3096      }
3097      else
3098      {
3099        ncpoly[i]= nInit(0);
3100      }
3101      mprPROTNnl("", ncpoly[i] );
3102    }
3103
3104#ifdef MPR_TIMING
3105     if ( masi ) Print("MASI MASI MASI\n");
3106#endif
3107
3108    mprSTICKYPROT(ST_BASE_EV); // .
3109
3110    if ( subDetVal != NULL ) {  // divide by common factor
3111      number detdiv;
3112      for ( i= 0; i <= tdg; i++ )
3113      {
3114        detdiv= nDiv( ncpoly[i], subDetVal );
3115        nNormalize( detdiv );
3116        nDelete( &ncpoly[i] );
3117        ncpoly[i]= detdiv;
3118      }
3119    }
3120
3121    pDelete( &pures );
3122
3123    // save results
3124    roots[uvar]->fillContainer( ncpoly, pevpoint, uvar+1, tdg,
3125                                (matchUp?rootContainer::cspecialmu:rootContainer::cspecial),
3126                                loops );
3127  }
3128
3129  mprSTICKYPROT("\n");
3130
3131  // free some stuff: pev, presult
3132  for ( i=0; i < n; i++ ) nDelete( pevpoint + i );
3133  Free( (ADDRESS)pevpoint, n * sizeof( number ) );
3134
3135  return roots;
3136}
3137
3138int uResultant::nextPrime( int i )
3139{
3140  int init=i;
3141  i+=2;
3142  int j= IsPrime( i );
3143  while ( j <= init )
3144  {
3145    i+=2;
3146    j= IsPrime( i );
3147  }
3148  return j;
3149}
3150//<-
3151//%e
3152
3153//-----------------------------------------------------------------------------
3154
3155#endif // ! ASO_GENERATE
3156
3157// local Variables: ***
3158// folded-file: t ***
3159// compile-command-1: "make installg" ***
3160// compile-command-2: "make install" ***
3161// End: ***
3162
3163// in folding: C-c x
3164// leave fold: C-c y
3165//   foldmode: F10
3166
Note: See TracBrowser for help on using the repository browser.