source: git/numeric/mpr_numeric.cc @ f5d2647

spielwiese
Last change on this file since f5d2647 was ba5e9e, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Changed configure-scripts to generate individual public config files for each package: resources, libpolys, singular (main) fix: sources should include correct corresponding config headers.
  • Property mode set to 100644
File size: 30.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4
5
6/*
7* ABSTRACT - multipolynomial resultants - numeric stuff
8*            ( root finder, vandermonde system solver, simplex )
9*/
10
11#include <math.h>
12
13#ifdef HAVE_CONFIG_H
14#include "singularconfig.h"
15#endif /* HAVE_CONFIG_H */
16#include <kernel/mod2.h>
17
18#include <misc/auxiliary.h>
19#include <omalloc/omalloc.h>
20
21//#ifdef HAVE_MPR
22
23//#define mprDEBUG_ALL
24
25//-> includes
26#include <misc/mylimits.h>
27#include <misc/options.h>
28#include <misc/intvec.h>
29
30#include <coeffs/numbers.h>
31#include <coeffs/mpr_global.h>
32
33#include <polys/matpol.h>
34
35#include <kernel/febase.h>
36#include <kernel/polys.h>
37#include <kernel/ideals.h>
38
39#include <kernel/febase.h>
40#include <kernel/polys.h>
41#include <kernel/ideals.h>
42
43//#include "longrat.h"
44
45#include "mpr_numeric.h"
46
47#include <math.h>
48
49extern size_t gmp_output_digits;
50//<-
51
52extern void nPrint(number n);  // for debugging output
53
54//-----------------------------------------------------------------------------
55//-------------- vandermonde system solver ------------------------------------
56//-----------------------------------------------------------------------------
57
58//-> vandermonde::*
59vandermonde::vandermonde( const long _cn, const long _n, const long _maxdeg,
60                          number *_p, const bool _homog )
61  : n(_n), cn(_cn), maxdeg(_maxdeg), p(_p), homog(_homog)
62{
63  long j;
64  l= (long)pow((double)maxdeg+1,(int)n);
65  x= (number *)omAlloc( cn * sizeof(number) );
66  for ( j= 0; j < cn; j++ ) x[j]= nInit(1);
67  init();
68}
69
70vandermonde::~vandermonde()
71{
72  int j;
73  for ( j= 0; j < cn; j++ ) nDelete( x+j );
74  omFreeSize( (void *)x, cn * sizeof( number ) );
75}
76
77void vandermonde::init()
78{
79  int j;
80  long i,c,sum;
81  number tmp,tmp1;
82
83  c=0;
84  sum=0;
85
86  intvec exp( n );
87  for ( j= 0; j < n; j++ ) exp[j]=0;
88
89  for ( i= 0; i < l; i++ )
90  {
91    if ( !homog || (sum == maxdeg) )
92    {
93      for ( j= 0; j < n; j++ )
94      {
95        nPower( p[j], exp[j], &tmp );
96        tmp1 = nMult( tmp, x[c] );
97        x[c]= tmp1;
98        nDelete( &tmp );
99      }
100      c++;
101    }
102    exp[0]++;
103    sum=0;
104    for ( j= 0; j < n - 1; j++ )
105    {
106      if ( exp[j] > maxdeg )
107      {
108        exp[j]= 0;
109        exp[j + 1]++;
110        }
111      sum+= exp[j];
112    }
113    sum+= exp[n - 1];
114  }
115}
116
117poly vandermonde::numvec2poly( const number * q )
118{
119  int j;
120  long i,/*c,*/sum;
121
122  poly pnew,pit=NULL;
123
124  // c=0;
125  sum=0;
126
127  int *exp= (int *) omAlloc( (n+1) * sizeof(int) );
128
129  for ( j= 0; j < n+1; j++ ) exp[j]=0;
130
131  for ( i= 0; i < l; i++ )
132  {
133    if ( (!homog || (sum == maxdeg)) && q[i] && !nIsZero(q[i]) )
134    {
135      pnew= pOne();
136      pSetCoeff(pnew,q[i]);
137      pSetExpV(pnew,exp);
138      if ( pit )
139      {
140        pNext(pnew)= pit;
141        pit= pnew;
142      }
143      else
144      {
145        pit= pnew;
146        pNext(pnew)= NULL;
147      }
148      pSetm(pit);
149    }
150    exp[1]++;
151    sum=0;
152    for ( j= 1; j < n; j++ )
153    {
154      if ( exp[j] > maxdeg )
155      {
156        exp[j]= 0;
157        exp[j + 1]++;
158        }
159      sum+= exp[j];
160    }
161    sum+= exp[n];
162  }
163
164  omFreeSize( (void *) exp, (n+1) * sizeof(int) );
165
166  pSortAdd(pit);
167  return pit;
168}
169
170number * vandermonde::interpolateDense( const number * q )
171{
172  int i,j,k;
173  number newnum,tmp1;
174  number b,t,xx,s;
175  number *c;
176  number *w;
177
178  b=t=xx=s=tmp1=NULL;
179
180  w= (number *)omAlloc( cn * sizeof(number) );
181  c= (number *)omAlloc( cn * sizeof(number) );
182  for ( j= 0; j < cn; j++ )
183  {
184    w[j]= nInit(0);
185    c[j]= nInit(0);
186  }
187
188  if ( cn == 1 )
189  {
190    nDelete( &w[0] );
191    w[0]= nCopy(q[0]);
192  }
193  else
194  {
195    nDelete( &c[cn-1] );
196    c[cn-1]= nCopy(x[0]);
197    c[cn-1]= nNeg(c[cn-1]);              // c[cn]= -x[1]
198
199    for ( i= 1; i < cn; i++ ) {              // i=2; i <= cn
200      nDelete( &xx );
201      xx= nCopy(x[i]);
202      xx= nNeg(xx);               // xx= -x[i]
203
204      for ( j= (cn-i-1); j <= (cn-2); j++) { // j=(cn+1-i); j <= (cn-1)
205        nDelete( &tmp1 );
206        tmp1= nMult( xx, c[j+1] );           // c[j]= c[j] + (xx * c[j+1])
207        newnum= nAdd( c[j], tmp1 );
208        nDelete( &c[j] );
209        c[j]= newnum;
210      }
211
212      newnum= nAdd( xx, c[cn-1] );           // c[cn-1]= c[cn-1] + xx
213      nDelete( &c[cn-1] );
214      c[cn-1]= newnum;
215    }
216
217    for ( i= 0; i < cn; i++ ) {              // i=1; i <= cn
218      nDelete( &xx );
219      xx= nCopy(x[i]);                     // xx= x[i]
220
221      nDelete( &t );
222      t= nInit( 1 );                         // t= b= 1
223      nDelete( &b );
224      b= nInit( 1 );
225      nDelete( &s );                         // s= q[cn-1]
226      s= nCopy( q[cn-1] );
227
228      for ( k= cn-1; k >= 1; k-- ) {         // k=cn; k >= 2
229        nDelete( &tmp1 );
230        tmp1= nMult( xx, b );                // b= c[k] + (xx * b)
231        nDelete( &b );
232        b= nAdd( c[k], tmp1 );
233
234        nDelete( &tmp1 );
235        tmp1= nMult( q[k-1], b );            // s= s + (q[k-1] * b)
236        newnum= nAdd( s, tmp1 );
237        nDelete( &s );
238        s= newnum;
239
240        nDelete( &tmp1 );
241        tmp1= nMult( xx, t );                // t= (t * xx) + b
242        newnum= nAdd( tmp1, b );
243        nDelete( &t );
244        t= newnum;
245      }
246
247      if (!nIsZero(t))
248      {
249        nDelete( &w[i] );                      // w[i]= s/t
250        w[i]= nDiv( s, t );
251        nNormalize( w[i] );
252      }
253
254      mprSTICKYPROT(ST_VANDER_STEP);
255    }
256  }
257  mprSTICKYPROT("\n");
258
259  // free mem
260  for ( j= 0; j < cn; j++ ) nDelete( c+j );
261  omFreeSize( (void *)c, cn * sizeof( number ) );
262
263  nDelete( &tmp1 );
264  nDelete( &s );
265  nDelete( &t );
266  nDelete( &b );
267  nDelete( &xx );
268
269  // makes quotiens smaller
270  for ( j= 0; j < cn; j++ ) nNormalize( w[j] );
271
272  return w;
273}
274//<-
275
276//-----------------------------------------------------------------------------
277//-------------- rootContainer ------------------------------------------------
278//-----------------------------------------------------------------------------
279
280//-> definitions
281#define MR       8        // never change this value
282#define MT      5
283#define MMOD    (MT*MR)
284#define MAXIT   (5*MMOD)   // max number of iterations in laguer root finder
285
286
287//-> rootContainer::rootContainer()
288rootContainer::rootContainer()
289{
290  rt=none;
291
292  coeffs= NULL;
293  ievpoint= NULL;
294  theroots= NULL;
295
296  found_roots= false;
297}
298//<-
299
300//-> rootContainer::~rootContainer()
301rootContainer::~rootContainer()
302{
303  int i;
304  // free coeffs, ievpoint
305  if ( ievpoint != NULL )
306  {
307    for ( i=0; i < anz+2; i++ ) nDelete( ievpoint + i );
308    omFreeSize( (void *)ievpoint, (anz+2) * sizeof( number ) );
309  }
310
311  for ( i=0; i <= tdg; i++ ) nDelete( coeffs + i );
312  omFreeSize( (void *)coeffs, (tdg+1) * sizeof( number ) );
313
314  // theroots löschen
315  for ( i=0; i < tdg; i++ ) delete theroots[i];
316  omFreeSize( (void *) theroots, (tdg)*sizeof(gmp_complex*) );
317
318  //mprPROTnl("~rootContainer()");
319}
320//<-
321
322//-> void rootContainer::fillContainer( ... )
323void rootContainer::fillContainer( number *_coeffs, number *_ievpoint,
324                                   const int _var, const int _tdg,
325                                   const rootType  _rt, const int _anz )
326{
327  int i;
328  number nn= nInit(0);
329  var=_var;
330  tdg=_tdg;
331  coeffs=_coeffs;
332  rt=_rt;
333  anz=_anz;
334
335  for ( i=0; i <= tdg; i++ )
336  {
337    if ( nEqual(coeffs[i],nn) )
338    {
339      nDelete( &coeffs[i] );
340      coeffs[i]=NULL;
341    }
342  }
343  nDelete( &nn );
344
345  if ( rt == cspecialmu && _ievpoint )  // copy ievpoint
346  {
347    ievpoint= (number *)omAlloc( (anz+2) * sizeof( number ) );
348    for (i=0; i < anz+2; i++) ievpoint[i]= nCopy( _ievpoint[i] );
349  }
350
351  theroots= NULL;
352  found_roots= false;
353}
354//<-
355
356//-> poly rootContainer::getPoly()
357poly rootContainer::getPoly()
358{
359  int i;
360
361  poly result= NULL;
362  poly ppos;
363
364  if ( (rt == cspecial) || ( rt == cspecialmu ) )
365  {
366    for ( i= tdg; i >= 0; i-- )
367    {
368      if ( coeffs[i] )
369      {
370        poly p= pOne();
371        //pSetExp( p, var+1, i);
372        pSetExp( p, 1, i);
373        pSetCoeff( p, nCopy( coeffs[i] ) );
374        pSetm( p );
375        if (result)
376        {
377          ppos->next=p;
378          ppos=ppos->next;
379        }
380        else
381        {
382          result=p;
383          ppos=p;
384        }
385
386      }
387    }
388    if (result!=NULL) pSetm( result );
389  }
390
391  return result;
392}
393//<-
394
395//-> const gmp_complex & rootContainer::opterator[] ( const int i )
396// this is now inline!
397//  gmp_complex & rootContainer::operator[] ( const int i )
398//  {
399//    if ( found_roots && ( i >= 0) && ( i < tdg ) )
400//    {
401//      return *theroots[i];
402//    }
403//    // warning
404//    Warn("rootContainer::getRoot: Wrong index %d, found_roots %s",i,found_roots?"true":"false");
405//    gmp_complex *tmp= new gmp_complex();
406//    return *tmp;
407//  }
408//<-
409
410//-> gmp_complex & rootContainer::evPointCoord( int i )
411gmp_complex & rootContainer::evPointCoord( const int i )
412{
413  if (! ((i >= 0) && (i < anz+2) ) )
414    WarnS("rootContainer::evPointCoord: index out of range");
415  if (ievpoint == NULL)
416    WarnS("rootContainer::evPointCoord: ievpoint == NULL");
417
418  if ( (rt == cspecialmu) && found_roots ) // FIX ME
419  {
420    if ( ievpoint[i] != NULL )
421    {
422      gmp_complex *tmp= new gmp_complex();
423      *tmp= numberToComplex(ievpoint[i], currRing->cf);
424      return *tmp;
425    }
426    else
427    {
428      Warn("rootContainer::evPointCoord: NULL index %d",i);
429    }
430  }
431
432  // warning
433  Warn("rootContainer::evPointCoord: Wrong index %d, found_roots %s",i,found_roots?"true":"false");
434  gmp_complex *tmp= new gmp_complex();
435  return *tmp;
436}
437//<-
438
439//-> bool rootContainer::changeRoots( int from, int to )
440bool rootContainer::swapRoots( const int from, const int to )
441{
442  if ( found_roots && ( from >= 0) && ( from < tdg ) && ( to >= 0) && ( to < tdg ) )
443  {
444    if ( to != from )
445    {
446      gmp_complex tmp( *theroots[from] );
447      *theroots[from]= *theroots[to];
448      *theroots[to]= tmp;
449    }
450    return true;
451  }
452
453  // warning
454  Warn(" rootContainer::changeRoots: Wrong index %d, %d",from,to);
455  return false;
456}
457//<-
458
459//-> void rootContainer::solver()
460bool rootContainer::solver( const int polishmode )
461{
462  int i;
463
464  // there are maximal tdg roots, so *roots ranges form 0 to tdg-1.
465  theroots= (gmp_complex**)omAlloc( tdg*sizeof(gmp_complex*) );
466  for ( i=0; i < tdg; i++ ) theroots[i]= new gmp_complex();
467
468  // copy the coefficients of type number to type gmp_complex
469  gmp_complex **ad= (gmp_complex**)omAlloc( (tdg+1)*sizeof(gmp_complex*) );
470  for ( i=0; i <= tdg; i++ )
471  {
472    ad[i]= new gmp_complex();
473    if ( coeffs[i] ) *ad[i] = numberToComplex( coeffs[i], currRing->cf );
474  }
475
476  // now solve
477  found_roots= laguer_driver( ad, theroots, polishmode != 0 );
478  if (!found_roots)
479    WarnS("rootContainer::solver: No roots found!");
480 
481  // free memory
482  for ( i=0; i <= tdg; i++ ) delete ad[i];
483  omFreeSize( (void *) ad, (tdg+1)*sizeof(gmp_complex*) );
484
485  return found_roots;
486}
487//<-
488
489//-> gmp_complex* rootContainer::laguer_driver( bool polish )
490bool rootContainer::laguer_driver(gmp_complex ** a, gmp_complex ** roots, bool polish )
491{
492  int i,j,k,its;
493  gmp_float zero(0.0);
494  gmp_complex x(0.0),o(1.0);
495  bool ret= true, isf=isfloat(a), type=true;
496
497  gmp_complex ** ad= (gmp_complex**)omAlloc( (tdg+1)*sizeof(gmp_complex*) );
498  for ( i=0; i <= tdg; i++ ) ad[i]= new gmp_complex( *a[i] );
499
500  k = 0;
501  i = tdg;
502  j = i-1;
503  while (i>2)
504  {
505    // run laguer alg
506    x = zero;
507    laguer(ad, i, &x, &its, type);
508    if ( its > MAXIT )
509    {
510      type = !type;
511      x = zero;
512      laguer(ad, i, &x, &its, type);
513    }
514
515    mprSTICKYPROT(ST_ROOTS_LGSTEP);
516    if ( its > MAXIT )
517    {  // error
518      WarnS("Laguerre solver: Too many iterations!");
519      ret= false;
520      goto theend;
521    }
522    if ( polish )
523    {
524      laguer( a, tdg, &x, &its , type);
525      if ( its > MAXIT )
526      {  // error
527        WarnS("Laguerre solver: Too many iterations in polish!");
528        ret= false;
529        goto theend;
530      }
531    }
532    if ((!type)&&(!((x.real()==zero)&&(x.imag()==zero)))) x = o/x;
533    if (x.imag() == zero)
534    {
535      *roots[k] = x;
536      k++;
537      divlin(ad,x,i);
538      i--;
539    }
540    else
541    {
542      if(isf)
543      {
544        *roots[j] = x;
545        *roots[j-1]= gmp_complex(x.real(),-x.imag());
546        j -= 2;
547        divquad(ad,x,i);
548        i -= 2;
549      }
550      else
551      {
552        *roots[j] = x;
553        j--;
554        divlin(ad,x,i);
555        i--;
556      }
557    }
558    type = !type;
559  }
560  solvequad(ad,roots,k,j);
561  sortroots(roots,k,j,isf);
562
563theend:
564  mprSTICKYPROT("\n");
565  for ( i=0; i <= tdg; i++ ) delete ad[i];
566  omFreeSize( (void *) ad, (tdg+1)*sizeof( gmp_complex* ));
567
568  return ret;
569}
570//<-
571
572//-> void rootContainer::laguer(...)
573void rootContainer::laguer(gmp_complex ** a, int m, gmp_complex *x, int *its, bool type)
574{
575  int iter,j;
576  gmp_float zero(0.0),one(1.0),deg(m);
577  gmp_float abx_g, err_g, fabs;
578  gmp_complex dx, x1, b, d, f, g, h, sq, gp, gm, g2;
579  gmp_float frac_g[MR+1] = { 0.0, 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875, 1.0 };
580
581  gmp_float epss(0.1);
582  mpf_pow_ui(*epss._mpfp(),*epss.mpfp(),getGMPFloatDigits());
583
584  for ( iter= 1; iter <= MAXIT; iter++ )
585  {
586    mprSTICKYPROT(ST_ROOTS_LG);
587    *its=iter;
588    if (type)
589      computefx(a,*x,m,b,d,f,abx_g,err_g);
590    else
591      computegx(a,*x,m,b,d,f,abx_g,err_g);
592    err_g *= epss; // EPSS;
593
594    fabs = abs(b);
595    if (fabs <= err_g)
596    {
597      if ((fabs==zero) || (abs(d)==zero)) return;
598      *x -= (b/d); // a last newton-step
599      goto ende;
600    }
601
602    g= d / b;
603    g2 = g * g;
604    h= g2 - (((f+f) / b ));
605    sq= sqrt(( ( h * deg ) - g2 ) * (deg - one));
606    gp= g + sq;
607    gm= g - sq;
608    if (abs(gp)<abs(gm))
609    {
610      dx = deg/gm;
611    }
612    else
613    {
614      if((gp.real()==zero)&&(gp.imag()==zero))
615      {
616        dx.real(cos((mprfloat)iter));
617        dx.imag(sin((mprfloat)iter));
618        dx = dx*(one+abx_g);
619      }
620      else
621      {
622        dx = deg/gp;
623      }
624    }
625    x1= *x - dx;
626
627    if (*x == x1) goto ende;
628
629    j = iter%MMOD;
630    if (j==0) j=MT;
631    if ( j % MT ) *x= x1;
632    else *x -= ( dx * frac_g[ j / MT ] );
633  }
634
635  *its= MAXIT+1;
636ende:
637  checkimag(x,epss);
638}
639
640void rootContainer::checkimag(gmp_complex *x, gmp_float &e)
641{
642  if(abs(x->imag())<abs(x->real())*e)
643  {
644    x->imag(0.0);
645  }
646}
647
648bool rootContainer::isfloat(gmp_complex **a)
649{
650  gmp_float z(0.0);
651  gmp_complex *b;
652  for (int i=tdg; i >= 0; i-- )
653  {
654    b = &(*a[i]);
655    if (!(b->imag()==z))
656      return false;
657  }
658  return true;
659}
660
661void rootContainer::divlin(gmp_complex **a, gmp_complex x, int j)
662{
663  int i;
664  gmp_float o(1.0);
665
666  if (abs(x)<o)
667  {
668    for (i= j-1; i > 0; i-- )
669      *a[i] += (*a[i+1]*x);
670    for (i= 0; i < j; i++ )
671      *a[i] = *a[i+1];
672  }
673  else
674  {
675    gmp_complex y(o/x);
676    for (i= 1; i < j; i++)
677      *a[i] += (*a[i-1]*y);
678  }
679}
680
681void rootContainer::divquad(gmp_complex **a, gmp_complex x, int j)
682{
683  int i;
684  gmp_float o(1.0),p(x.real()+x.real()),
685            q((x.real()*x.real())+(x.imag()*x.imag()));
686
687  if (abs(x)<o)
688  {
689    *a[j-1] += (*a[j]*p);
690    for (i= j-2; i > 1; i-- )
691      *a[i] += ((*a[i+1]*p)-(*a[i+2]*q));
692    for (i= 0; i < j-1; i++ )
693      *a[i] = *a[i+2];
694  }
695  else
696  {
697    p = p/q;
698    q = o/q;
699    *a[1] += (*a[0]*p);
700    for (i= 2; i < j-1; i++)
701      *a[i] += ((*a[i-1]*p)-(*a[i-2]*q));
702  }
703}
704
705void rootContainer::solvequad(gmp_complex **a, gmp_complex **r, int &k, int &j)
706{
707  gmp_float zero(0.0);
708
709  if ((j>k)
710  &&((!(*a[2]).real().isZero())||(!(*a[2]).imag().isZero())))
711  {
712    gmp_complex sq(zero);
713    gmp_complex h1(*a[1]/(*a[2] + *a[2])), h2(*a[0] / *a[2]);
714    gmp_complex disk((h1 * h1) - h2);
715    if (disk.imag().isZero())
716    {
717      if (disk.real()<zero)
718      {
719        sq.real(zero);
720        sq.imag(sqrt(-disk.real()));
721      }
722      else
723        sq = (gmp_complex)sqrt(disk.real());
724    }
725    else
726      sq = sqrt(disk);
727    *r[k+1] = sq - h1;
728    sq += h1;
729    *r[k] = (gmp_complex)0.0-sq;
730    if(sq.imag().isZero())
731    {
732      k = j;
733      j++;
734    }
735    else
736    {
737      j = k;
738      k--;
739    }
740  }
741  else
742  {
743    if (((*a[1]).real().isZero()) && ((*a[1]).imag().isZero()))
744    {
745      WerrorS("precision lost, try again with higher precision");
746    }
747    else
748    {
749      *r[k]= (gmp_complex)0.0-(*a[0] / *a[1]);
750      if(r[k]->imag().isZero())
751        j++;
752      else
753        k--;
754    }
755  }
756}
757
758void rootContainer::sortroots(gmp_complex **ro, int r, int c, bool isf)
759{
760  int j;
761
762  for (j=0; j<r; j++) // the real roots
763    sortre(ro, j, r, 1);
764  if (c>=tdg) return;
765  if (isf)
766  {
767    for (j=c; j+2<tdg; j+=2) // the complex roots for a real poly
768      sortre(ro, j, tdg-1, 2);
769  }
770  else
771  {
772    for (j=c; j+1<tdg; j++) // the complex roots for a general poly
773      sortre(ro, j, tdg-1, 1);
774  }
775}
776
777void rootContainer::sortre(gmp_complex **r, int l, int u, int inc)
778{
779  int pos,i;
780  gmp_complex *x,*y;
781
782  pos = l;
783  x = r[pos];
784  for (i=l+inc; i<=u; i+=inc)
785  {
786    if (r[i]->real()<x->real())
787    {
788      pos = i;
789      x = r[pos];
790    }
791  }
792  if (pos>l)
793  {
794    if (inc==1)
795    {
796      for (i=pos; i>l; i--)
797        r[i] = r[i-1];
798      r[l] = x;
799    }
800    else
801    {
802      y = r[pos+1];
803      for (i=pos+1; i+1>l; i--)
804        r[i] = r[i-2];
805      if (x->imag()>y->imag())
806      {
807        r[l] = x;
808        r[l+1] = y;
809      }
810      else
811      {
812        r[l] = y;
813        r[l+1] = x;
814      }
815    }
816  }
817  else if ((inc==2)&&(x->imag()<r[l+1]->imag()))
818  {
819    r[l] = r[l+1];
820    r[l+1] = x;
821  }
822}
823
824void rootContainer::computefx(gmp_complex **a, gmp_complex x, int m,
825                  gmp_complex &f0, gmp_complex &f1, gmp_complex &f2,
826                  gmp_float &ex, gmp_float &ef)
827{
828  int k;
829
830  f0= *a[m];
831  ef= abs(f0);
832  f1= gmp_complex(0.0);
833  f2= f1;
834  ex= abs(x);
835
836  for ( k= m-1; k >= 0; k-- )
837  {
838    f2 = ( x * f2 ) + f1;
839    f1 = ( x * f1 ) + f0;
840    f0 = ( x * f0 ) + *a[k];
841    ef = abs( f0 ) + ( ex * ef );
842  }
843}
844
845void rootContainer::computegx(gmp_complex **a, gmp_complex x, int m,
846                  gmp_complex &f0, gmp_complex &f1, gmp_complex &f2,
847                  gmp_float &ex, gmp_float &ef)
848{
849  int k;
850
851  f0= *a[0];
852  ef= abs(f0);
853  f1= gmp_complex(0.0);
854  f2= f1;
855  ex= abs(x);
856
857  for ( k= 1; k <= m; k++ )
858  {
859    f2 = ( x * f2 ) + f1;
860    f1 = ( x * f1 ) + f0;
861    f0 = ( x * f0 ) + *a[k];
862    ef = abs( f0 ) + ( ex * ef );
863  }
864}
865
866//-----------------------------------------------------------------------------
867//-------------- rootArranger -------------------------------------------------
868//-----------------------------------------------------------------------------
869
870//-> rootArranger::rootArranger(...)
871rootArranger::rootArranger( rootContainer ** _roots,
872                            rootContainer ** _mu,
873                            const int _howclean )
874  : roots(_roots), mu(_mu), howclean(_howclean)
875{
876  found_roots=false;
877}
878//<-
879
880//-> void rootArranger::solve_all()
881void rootArranger::solve_all()
882{
883  int i;
884  found_roots= true;
885
886  // find roots of polys given by coeffs in roots
887  rc= roots[0]->getAnzElems();
888  for ( i= 0; i < rc; i++ )
889    if ( !roots[i]->solver( howclean ) )
890    {
891      found_roots= false;
892      return;
893    }
894  // find roots of polys given by coeffs in mu
895  mc= mu[0]->getAnzElems();
896  for ( i= 0; i < mc; i++ )
897    if ( ! mu[i]->solver( howclean ) )
898    {
899      found_roots= false;
900      return;
901    }
902}
903//<-
904
905//-> void rootArranger::arrange()
906void rootArranger::arrange()
907{
908  gmp_complex tmp,zwerg;
909  int anzm= mu[0]->getAnzElems();
910  int anzr= roots[0]->getAnzRoots();
911  int xkoord, r, rtest, xk, mtest;
912  bool found;
913  //gmp_complex mprec(1.0/pow(10,gmp_output_digits-5),1.0/pow(10,gmp_output_digits-5));
914
915  for ( xkoord= 0; xkoord < anzm; xkoord++ ) {    // für x1,x2, x1,x2,x3, x1,x2,...,xn
916    gmp_float mprec(1.0/pow(10.0,(int)(gmp_output_digits/3)));
917    for ( r= 0; r < anzr; r++ ) {                 // für jede Nullstelle
918      // (x1-koordinate) * evp[1] + (x2-koordinate) * evp[2] +
919      //                                  ... + (xkoord-koordinate) * evp[xkoord]
920      tmp= gmp_complex();
921      for ( xk =0; xk <= xkoord; xk++ )
922      {
923        tmp -= (*roots[xk])[r] * mu[xkoord]->evPointCoord(xk+1); //xk+1
924      }
925      found= false;
926      do { // while not found
927        for ( rtest= r; rtest < anzr; rtest++ ) {   // für jede Nullstelle
928           zwerg = tmp - (*roots[xk])[rtest] * mu[xkoord]->evPointCoord(xk+1); // xk+1, xkoord+2
929          for ( mtest= 0; mtest < anzr; mtest++ )
930          {
931            //          if ( tmp == (*mu[xkoord])[mtest] )
932            //          {
933            if ( ((zwerg.real() <= (*mu[xkoord])[mtest].real() + mprec) &&
934                  (zwerg.real() >= (*mu[xkoord])[mtest].real() - mprec)) &&
935                 ((zwerg.imag() <= (*mu[xkoord])[mtest].imag() + mprec) &&
936                  (zwerg.imag() >= (*mu[xkoord])[mtest].imag() - mprec)) )
937            {
938              roots[xk]->swapRoots( r, rtest );
939              found= true;
940              break;
941            }
942          }
943        } // rtest
944        if (!found) 
945        {
946          WarnS("rootArranger::arrange: precision lost");
947          mprec*=10;
948        }
949      } while(!found);
950#if 0
951      if ( !found )
952      {
953        Warn("rootArranger::arrange: No match? coord %d, root %d.",xkoord,r);
954//#ifdef mprDEBUG_PROT
955        WarnS("One of these ...");
956        for ( rtest= r; rtest < anzr; rtest++ )
957        {
958          tmp= gmp_complex();
959          for ( xk =0; xk <= xkoord; xk++ )
960          {
961            tmp-= (*roots[xk])[r] * mu[xkoord]->evPointCoord(xk+1);
962          }
963          tmp-= (*roots[xk])[rtest] * mu[xkoord]->evPointCoord(xk+1); // xkoord+2
964          Warn("  %s",complexToStr(tmp,gmp_output_digits+1),rtest);
965        }
966        WarnS(" ... must match to one of these:");
967        for ( mtest= 0; mtest < anzr; mtest++ )
968        {
969          Warn("                  %s",complexToStr((*mu[xkoord])[mtest],gmp_output_digits+1));
970        }
971//#endif
972      }
973#endif     
974    } // r
975  } // xkoord
976}
977//<-
978
979//-----------------------------------------------------------------------------
980//-------------- simplex ----- ------------------------------------------------
981//-----------------------------------------------------------------------------
982
983//  #ifdef mprDEBUG_PROT
984//  #define error(a) a
985//  #else
986//  #define error(a)
987//  #endif
988
989#define error(a) a
990
991#define MAXPOINTS      1000
992
993//-> simplex::*
994//
995simplex::simplex( int rows, int cols )
996   : LiPM_cols(cols), LiPM_rows(rows)
997{
998  int i;
999
1000  LiPM_rows=LiPM_rows+3;
1001  LiPM_cols=LiPM_cols+2;
1002
1003  LiPM = (mprfloat **)omAlloc( LiPM_rows * sizeof(mprfloat *) );  // LP matrix
1004  for( i= 0; i < LiPM_rows; i++ )
1005  {
1006    // Mem must be allocated aligned, also for type double!
1007    LiPM[i] = (mprfloat *)omAlloc0Aligned( LiPM_cols * sizeof(mprfloat) );
1008  }
1009
1010  iposv = (int *)omAlloc0( 2*LiPM_rows*sizeof(int) );
1011  izrov = (int *)omAlloc0( 2*LiPM_rows*sizeof(int) );
1012
1013  m=n=m1=m2=m3=icase=0;
1014
1015#ifdef mprDEBUG_ALL
1016  Print("LiPM size: %d, %d\n",LiPM_rows,LiPM_cols);
1017#endif
1018}
1019
1020simplex::~simplex()
1021{
1022  // clean up
1023  int i;
1024  for( i= 0; i < LiPM_rows; i++ )
1025  {
1026    omFreeSize( (void *) LiPM[i], LiPM_cols * sizeof(mprfloat) );
1027  }
1028  omFreeSize( (void *) LiPM, LiPM_rows * sizeof(mprfloat *) );
1029
1030  omFreeSize( (void *) iposv, 2*LiPM_rows*sizeof(int) );
1031  omFreeSize( (void *) izrov, 2*LiPM_rows*sizeof(int) );
1032}
1033
1034BOOLEAN simplex::mapFromMatrix( matrix mm )
1035{
1036  int i,j;
1037//    if ( MATROWS( m ) > LiPM_rows ||  MATCOLS( m ) > LiPM_cols ) {
1038//      WarnS("");
1039//      return FALSE;
1040//    }
1041
1042  number coef;
1043  for ( i= 1; i <= MATROWS( mm ); i++ )
1044  {
1045     for ( j= 1; j <= MATCOLS( mm ); j++ )
1046     {
1047        if ( MATELEM(mm,i,j) != NULL )
1048        {
1049           coef= pGetCoeff( MATELEM(mm,i,j) );
1050           if ( coef != NULL && !nIsZero(coef) )
1051              LiPM[i][j]= (double)(*(gmp_float*)coef);
1052           //#ifdef mpr_DEBUG_PROT
1053           //Print("%f ",LiPM[i][j]);
1054           //#endif
1055        }
1056     }
1057     //     PrintLn();
1058  }
1059
1060  return TRUE;
1061}
1062
1063matrix simplex::mapToMatrix( matrix mm )
1064{
1065  int i,j;
1066//    if ( MATROWS( mm ) < LiPM_rows-3 ||  MATCOLS( m ) < LiPM_cols-2 ) {
1067//      WarnS("");
1068//      return NULL;
1069//    }
1070
1071//Print(" %d x %d\n",MATROWS( mm ),MATCOLS( mm ));
1072
1073  number coef;
1074  gmp_float * bla;
1075  for ( i= 1; i <= MATROWS( mm ); i++ )
1076  {
1077    for ( j= 1; j <= MATCOLS( mm ); j++ )
1078    {
1079       pDelete( &(MATELEM(mm,i,j)) );
1080       MATELEM(mm,i,j)= NULL;
1081//Print(" %3.0f ",LiPM[i][j]);
1082       if ( LiPM[i][j] != 0.0 )
1083       {
1084          bla= new gmp_float(LiPM[i][j]);
1085          coef= (number)bla;
1086          MATELEM(mm,i,j)= pOne();
1087          pSetCoeff( MATELEM(mm,i,j), coef );
1088       }
1089    }
1090//PrintLn();
1091  }
1092
1093  return mm;
1094}
1095
1096intvec * simplex::posvToIV()
1097{
1098   int i;
1099   intvec * iv = new intvec( m );
1100   for ( i= 1; i <= m; i++ )
1101   {
1102      IMATELEM(*iv,i,1)= iposv[i];
1103   }
1104   return iv;
1105}
1106
1107intvec * simplex::zrovToIV()
1108{
1109   int i;
1110   intvec * iv = new intvec( n );
1111   for ( i= 1; i <= n; i++ )
1112   {
1113      IMATELEM(*iv,i,1)= izrov[i];
1114   }
1115   return iv;
1116}
1117
1118void simplex::compute()
1119{
1120  int i,ip,ir,is,k,kh,kp,m12,nl1,nl2;
1121  int *l1,*l2,*l3;
1122  mprfloat q1, bmax;
1123
1124  if ( m != (m1+m2+m3) )
1125  {
1126    // error: bad input
1127    error(WarnS("simplex::compute: Bad input constraint counts!");)
1128    icase=-2;
1129    return;
1130  }
1131
1132  l1= (int *) omAlloc0( (n+1) * sizeof(int) );
1133  l2= (int *) omAlloc0( (m+1) * sizeof(int) );
1134  l3= (int *) omAlloc0( (m+1) * sizeof(int) );
1135
1136  nl1= n;
1137  for ( k=1; k<=n; k++ ) l1[k]=izrov[k]=k;
1138  nl2=m;
1139  for ( i=1; i<=m; i++ )
1140  {
1141    if ( LiPM[i+1][1] < 0.0 )
1142    {
1143      // error: bad input
1144      error(WarnS("simplex::compute: Bad input tableau!");)
1145      error(Warn("simplex::compute: in input Matrix row %d, column 1, value %f",i+1,LiPM[i+1][1]);)
1146      icase=-2;
1147      // free mem l1,l2,l3;
1148      omFreeSize( (void *) l3, (m+1) * sizeof(int) );
1149      omFreeSize( (void *) l2, (m+1) * sizeof(int) );
1150      omFreeSize( (void *) l1, (n+1) * sizeof(int) );
1151      return;
1152    }
1153    l2[i]= i;
1154    iposv[i]= n+i;
1155  }
1156  for ( i=1; i<=m2; i++) l3[i]= 1;
1157  ir= 0;
1158  if (m2+m3)
1159  {
1160    ir=1;
1161    for ( k=1; k <= (n+1); k++ )
1162    {
1163      q1=0.0;
1164      for ( i=m1+1; i <= m; i++ ) q1+= LiPM[i+1][k];
1165      LiPM[m+2][k]= -q1;
1166    }
1167
1168    do
1169    {
1170      simp1(LiPM,m+1,l1,nl1,0,&kp,&bmax);
1171      if ( bmax <= SIMPLEX_EPS && LiPM[m+2][1] < -SIMPLEX_EPS )
1172      {
1173        icase= -1; // no solution found
1174        // free mem l1,l2,l3;
1175        omFreeSize( (void *) l3, (m+1) * sizeof(int) );
1176        omFreeSize( (void *) l2, (m+1) * sizeof(int) );
1177        omFreeSize( (void *) l1, (n+1) * sizeof(int) );
1178        return;
1179      }
1180      else if ( bmax <= SIMPLEX_EPS && LiPM[m+2][1] <= SIMPLEX_EPS )
1181      {
1182        m12= m1+m2+1;
1183        if ( m12 <= m )
1184        {
1185          for ( ip= m12; ip <= m; ip++ )
1186          {
1187            if ( iposv[ip] == (ip+n) )
1188            {
1189              simp1(LiPM,ip,l1,nl1,1,&kp,&bmax);
1190              if ( fabs(bmax) >= SIMPLEX_EPS)
1191                goto one;
1192            }
1193          }
1194        }
1195        ir= 0;
1196        --m12;
1197        if ( m1+1 <= m12 )
1198          for ( i=m1+1; i <= m12; i++ )
1199            if ( l3[i-m1] == 1 )
1200              for ( k=1; k <= n+1; k++ )
1201                LiPM[i+1][k] = -(LiPM[i+1][k]);
1202        break;
1203      }
1204      //#if DEBUG
1205      //print_bmat( a, m+2, n+3);
1206      //#endif
1207      simp2(LiPM,n,l2,nl2,&ip,kp,&q1);
1208      if ( ip == 0 )
1209      {
1210        icase = -1; // no solution found
1211        // free mem l1,l2,l3;
1212        omFreeSize( (void *) l3, (m+1) * sizeof(int) );
1213        omFreeSize( (void *) l2, (m+1) * sizeof(int) );
1214        omFreeSize( (void *) l1, (n+1) * sizeof(int) );
1215        return;
1216      }
1217    one: simp3(LiPM,m+1,n,ip,kp);
1218      // #if DEBUG
1219      // print_bmat(a,m+2,n+3);
1220      // #endif
1221      if ( iposv[ip] >= (n+m1+m2+1))
1222      {
1223        for ( k= 1; k <= nl1; k++ )
1224          if ( l1[k] == kp ) break;
1225        --nl1;
1226        for ( is=k; is <= nl1; is++ ) l1[is]= l1[is+1];
1227        ++(LiPM[m+2][kp+1]);
1228        for ( i= 1; i <= m+2; i++ ) LiPM[i][kp+1] = -(LiPM[i][kp+1]);
1229      }
1230      else
1231      {
1232        if ( iposv[ip] >= (n+m1+1) )
1233        {
1234          kh= iposv[ip]-m1-n;
1235          if ( l3[kh] )
1236          {
1237            l3[kh]= 0;
1238            ++(LiPM[m+2][kp+1]);
1239            for ( i=1; i<= m+2; i++ )
1240              LiPM[i][kp+1] = -(LiPM[i][kp+1]);
1241          }
1242        }
1243      }
1244      is= izrov[kp];
1245      izrov[kp]= iposv[ip];
1246      iposv[ip]= is;
1247    } while (ir);
1248  }
1249  /* end of phase 1, have feasible sol, now optimize it */
1250  loop
1251  {
1252    // #if DEBUG
1253    // print_bmat( a, m+1, n+5);
1254    // #endif
1255    simp1(LiPM,0,l1,nl1,0,&kp,&bmax);
1256    if (bmax <= /*SIMPLEX_EPS*/0.0)
1257    {
1258      icase=0; // finite solution found
1259      // free mem l1,l2,l3
1260      omFreeSize( (void *) l3, (m+1) * sizeof(int) );
1261      omFreeSize( (void *) l2, (m+1) * sizeof(int) );
1262      omFreeSize( (void *) l1, (n+1) * sizeof(int) );
1263      return;
1264    }
1265    simp2(LiPM,n,l2,nl2,&ip,kp,&q1);
1266    if (ip == 0)
1267    {
1268      //printf("Unbounded:");
1269      // #if DEBUG
1270      //       print_bmat( a, m+1, n+1);
1271      // #endif
1272      icase=1;                /* unbounded */
1273      // free mem
1274      omFreeSize( (void *) l3, (m+1) * sizeof(int) );
1275      omFreeSize( (void *) l2, (m+1) * sizeof(int) );
1276      omFreeSize( (void *) l1, (n+1) * sizeof(int) );
1277      return;
1278    }
1279    simp3(LiPM,m,n,ip,kp);
1280    is= izrov[kp];
1281    izrov[kp]= iposv[ip];
1282    iposv[ip]= is;
1283  }/*for ;;*/
1284}
1285
1286void simplex::simp1( mprfloat **a, int mm, int ll[], int nll, int iabf, int *kp, mprfloat *bmax )
1287{
1288  int k;
1289  mprfloat test;
1290
1291  if( nll <= 0)
1292  {                        /* init'tion: fixed */
1293    *bmax = 0.0;
1294    return;
1295  }
1296  *kp=ll[1];
1297  *bmax=a[mm+1][*kp+1];
1298  for (k=2;k<=nll;k++)
1299  {
1300    if (iabf == 0)
1301    {
1302      test=a[mm+1][ll[k]+1]-(*bmax);
1303      if (test > 0.0)
1304      {
1305        *bmax=a[mm+1][ll[k]+1];
1306        *kp=ll[k];
1307      }
1308    }
1309    else
1310    {                        /* abs values: have fixed it */
1311      test=fabs(a[mm+1][ll[k]+1])-fabs(*bmax);
1312      if (test > 0.0)
1313      {
1314        *bmax=a[mm+1][ll[k]+1];
1315        *kp=ll[k];
1316      }
1317    }
1318  }
1319}
1320
1321void simplex::simp2( mprfloat **a, int nn, int l2[], int nl2, int *ip, int kp, mprfloat *q1 )
1322{
1323  int k,ii,i;
1324  mprfloat qp,q0,q;
1325
1326  *ip= 0;
1327  for ( i=1; i <= nl2; i++ )
1328  {
1329    if ( a[l2[i]+1][kp+1] < -SIMPLEX_EPS )
1330    {
1331      *q1= -a[l2[i]+1][1] / a[l2[i]+1][kp+1];
1332      *ip= l2[i];
1333      for ( i= i+1; i <= nl2; i++ )
1334      {
1335        ii= l2[i];
1336        if (a[ii+1][kp+1] < -SIMPLEX_EPS)
1337        {
1338          q= -a[ii+1][1] / a[ii+1][kp+1];
1339          if (q - *q1 < -SIMPLEX_EPS)
1340          {
1341            *ip=ii;
1342            *q1=q;
1343          }
1344          else if (q - *q1 < SIMPLEX_EPS)
1345          {
1346            for ( k=1; k<= nn; k++ )
1347            {
1348              qp= -a[*ip+1][k+1]/a[*ip+1][kp+1];
1349              q0= -a[ii+1][k+1]/a[ii+1][kp+1];
1350              if ( q0 != qp ) break;
1351            }
1352            if ( q0 < qp ) *ip= ii;
1353          }
1354        }
1355      }
1356    }
1357  }
1358}
1359
1360void simplex::simp3( mprfloat **a, int i1, int k1, int ip, int kp )
1361{
1362  int kk,ii;
1363  mprfloat piv;
1364
1365  piv= 1.0 / a[ip+1][kp+1];
1366  for ( ii=1; ii <= i1+1; ii++ )
1367  {
1368    if ( ii -1 != ip )
1369    {
1370      a[ii][kp+1] *= piv;
1371      for ( kk=1; kk <= k1+1; kk++ )
1372        if ( kk-1 != kp )
1373          a[ii][kk] -= a[ip+1][kk] * a[ii][kp+1];
1374    }
1375  }
1376  for ( kk=1; kk<= k1+1; kk++ )
1377    if ( kk-1 != kp ) a[ip+1][kk] *= -piv;
1378  a[ip+1][kp+1]= piv;
1379}
1380//<-
1381
1382//-----------------------------------------------------------------------------
1383
1384//#endif // HAVE_MPR
1385
1386// local Variables: ***
1387// folded-file: t ***
1388// compile-command-1: "make installg" ***
1389// compile-command-2: "make install" ***
1390// End: ***
1391
Note: See TracBrowser for help on using the repository browser.