source: git/factory/sm_sparsemod.cc @ 9c9e2a4

spielwiese
Last change on this file since 9c9e2a4 was 9c9e2a4, checked in by Jens Schmidt <schmidt@…>, 26 years ago
^M fix. Was: Thu 27.11.1997 22:30:00 Ruediger Stobbe <rstobbe@de.oracle.com> Factory Win NT Port, see ChangeLog for details git-svn-id: file:///usr/local/Singular/svn/trunk@951 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.4 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: sm_sparsemod.cc,v 1.4 1997-12-08 18:24:45 schmidt Exp $ */
3
4//{{{ docu
5//
6// sm_sparsemod.cc - zippel's sparse modular gcd.
7//
8// Contributed by Marion Bruder <bruder@math.uni-sb.de>.
9//
10// Used by: cf_gcf.cc
11//
12//}}}
13
14#include <config.h>
15
16#include "assert.h"
17#include "debug.h"
18
19#include "canonicalform.h"
20#include "cf_map.h"
21#include "cf_reval.h"
22#include "cf_irred.h"
23#include "cf_iter.h"
24#include "cf_primes.h"
25#include "cf_random.h"
26#include "fac_util.h"
27#include "cf_algorithm.h"
28#include "sm_util.h"
29#include "sm_sparsemod.h"
30#ifdef macintosh
31#include <::templates:ftmpl_array.h>
32#include <::templates:ftmpl_functions.h>
33#else
34#include "templates/ftmpl_array.h"
35#include "templates/ftmpl_functions.h"
36#endif
37
38static CanonicalForm
39smodgcd( const CanonicalForm & u, const CanonicalForm & v, const CanonicalForm & lcggt, const REvaluation & alpha, CFRandom & gen, int CHAR, const Variable & extension )
40{
41  DEBOUTLN( cerr, " ALPHA = " << alpha );
42
43  DEBOUTLN( cerr, " u = " << u );
44  DEBOUTLN( cerr, " v = " << v );
45
46  //    diverse Fallunterscheidungen  //
47
48  if ( u.isZero() )
49    return v;
50  else if ( v.isZero() )
51    return u;
52  else if ( u.inBaseDomain() )
53    if ( v.inBaseDomain() )
54      return gcd( u, v );
55    else
56      return gcd( u, icontent( u ) );
57  else if ( v.inBaseDomain() )
58    return gcd( icontent( u ), v);
59  else if ( u.isUnivariate() )
60    if ( v.isUnivariate() )
61      return gcd( u, v );
62    else
63      return gcd( v, u );
64
65
66
67
68  //   u und v Polynome in levU - Variablen x1, ..., xlevU
69  //   mit den gleichen Variablen, welches in sparsemod gesichert wurde
70
71  int levU = level( u );
72
73
74  CFArray G( 1, levU );
75  Variable x( 1 );
76  CanonicalForm alphau = alpha( u, 2, levU );
77  CanonicalForm alphav = alpha( v, 2, levU );
78
79  G[1] = gcd( alphau, alphav );       // univariater gcd berechnen in x1
80
81  DEBOUTLN( cerr, " G[1] ohne lc = " << G[1] );
82  //  Leitkoeffizienten auf univariaten gcd aufsetzen   //
83
84  if( alpha(lcggt) != 0 && degree(G[1]) != 0 )
85    {
86      //G[1] =( alpha( lcggt ))*( ( 1/lc( G[1] ) ) * G[1] );
87      G[1] =( alpha( lcggt ))*( ( 1/Leitkoeffizient( G[1] ) ) * G[1] );
88
89    }
90
91
92
93  if ( degree( G[1]) < 0 )
94    {
95
96     return 1 ;
97    }
98
99
100  if ( degree( G[1] ) == 0 )
101    {
102      // zwei Auswertungen um sicherzugehen, dass gcd Eins ist!
103
104      return 1;
105    }
106
107
108  CFIterator J = G[ 1 ];
109  CFArray g( 1, degree( G[ 1 ]) + 1 );
110  int * emma = new int[ degree( G[1] ) + 2  ];
111  int s, m, i = 1;
112
113  //  g[i] enthaelt die momentan berechneten Monome bzgl x^emma[i] //
114
115  while ( J.hasTerms() )
116    {
117      g[ i ] = J.coeff() ;
118      emma[ i ] = J.exp();
119      J++;
120      i++;
121    }
122
123
124  m = i-1;           /// Anzahl der Terme bzgl x1
125  int * n = new int[ m+1  ];
126  CFArray U( 2, levU ), V( 2, levU );
127
128  int  N, d   ;
129  int k, j, zip ;
130
131  // fuer jede Variabel interpolieren, um g[s] zu erhalten  //
132
133  DEBOUTLN( cerr, " unigcd mit alpha mit lc = " << G[1] );
134
135  for( s = 2 ;s <= levU ; s++ )
136    {
137      U[ s ] = alpha( u, s+1, levU );  // s Variablen stehen lassen, fuer
138      V[ s ] = alpha( v, s+1, levU );  // den Rest alpha einsetzen
139
140      d = tmin( degree( U[ s ], s ), degree( V[ s ], s ));
141
142      DEBOUTLN( cerr, " U["<< s << "] = " << U[s] );
143      DEBOUTLN( cerr, " V["<< s << "] = " << V[s] );
144      DEBOUTLN( cerr, " d = " << d );
145
146
147
148      for ( i = 1; i <= m ; i++ )
149        {
150          // Anzahl der Monome berechnen pro gi liefert das Skeletonpolynom //
151
152          n[ i ] = countmonome( g[ i ] );
153          //cout << "n["<<i<<"] = "<< n[i] << endl;
154        }
155
156
157
158      for ( i = 1; i <= m    ; i++ )
159        {
160          if ( i ==1 )
161            N = n[i];
162          else
163            {
164              if ( n[i]> N )
165                N = n[i];
166            }
167        }
168
169
170      //      int tau[d+1][m+1][N+1];               /// keine Integers !!!
171      typedef CanonicalForm** CF_ptr_ptr;
172      typedef CanonicalForm* CF_ptr;
173
174      CanonicalForm ***tau = new CF_ptr_ptr[m+1];
175      for ( i = 1; i <= m; i++ ) {
176        tau[i] = new CF_ptr[d+1];
177        for ( j = 1; j <= d; j++ )
178          tau[i][j] = new CanonicalForm[N+1];
179      }
180
181      CFArray beta( 1, d );
182
183      for ( i = 1; i <= d ; i++ )
184        {
185          beta[ i ] =  gen.generate();   // verschiedene Elemente aus Zp
186          //  cout << "  beta["<<i << "] = " << beta[i];
187        }
188
189
190
191
192
193      Array<REvaluation> xi( 1, N );
194      REvaluation a( 2, s-1, gen  );
195
196      for ( i = 1 ; i <= N ; i++ )
197        {
198          a.nextpoint();
199          xi[ i ] = a;//REvaluation( 2, s-1, gen );
200          // cout << "  xi["<<i<<"] = "<< xi[i];
201        }
202
203
204      //CFArray T(1, d*N );
205
206      if ( d == 0 )
207        {
208          ASSERT( 0, "alpha bad point! try some other gcd algorithm" );
209          return gcd(u, v);
210        }
211
212      CFMatrix T( d, N ) ;  // diese Moeglichkeit laeuft!!!
213                    //help = Koeff( T( j, k ), emma[ i ] );
214                    //tau[i][j][k] = help; //.intval();
215
216
217
218      for ( j = 1 ; j <= d ; j++ ) // jedesmal andere REvaluation??
219        for ( k = 1 ; k <= N ; k++ )
220          {
221            CanonicalForm zwischenu, zwischenv, help, nfa ;
222
223            zwischenu = U[ s ]( beta[ j ], s );
224            zwischenv = V[ s ]( beta[ j ], s );
225
226            T( j, k) = gcd ( xi[k]( zwischenu, 2, s-1 ), xi[k]( zwischenv, 2, s-1 ));
227
228
229            nfa = lcggt( beta[j], s );
230            nfa =  alpha( nfa, s+1, levU );
231
232            //T(j, k ) = (xi[k]( nfa, 2, s-1 ))*((1/lc(T( j, k ))) * T( j, k ));
233            T(j, k ) = (xi[k]( nfa, 2, s-1 ))*((1/Leitkoeffizient(T( j, k ))) * T( j, k ));
234
235            //cout <<"T("<<j<<", "<< k <<") = " << T(j, k) << endl;
236
237
238            for ( i = 1 ; i <= m ; i++ )
239              {
240                // diese Moeglichkeit laeuft!!!
241                //help = Koeff( T( j, k ), emma[ i ] );
242                //tau[i][j][k] = help; //.intval();
243                if ( T( j, k).inBaseDomain() )
244                  {
245                    if ( emma[i] == 0 )
246                      tau[i][j][k] = T( j, k );
247                    else
248                      tau[i][j][k] =  0 ;
249                  }
250                else
251                  {
252                    tau[i][j][k] = T(j, k)[emma[i]];
253                  }
254              }
255          }
256
257
258      CFMatrix h( m, d );
259
260
261      for ( i = 1; i <= m ; i++ )
262        {
263          for ( j = 1 ; j <= d ; j++ )
264            {
265              zip = n[i] +1;
266              CanonicalForm * zwischen = new CanonicalForm[ zip ];//n[i]+1 ];
267
268              for ( k = 1 ; k <= n[i] ; k++ )
269                {
270                  zwischen[ k ] = tau[i][j][k];
271                }
272
273              //cout <<" werte fuer sinterpol : " << endl;
274              //cout <<" g["<<i<<"] = " << g[i] << " xi = " << xi << endl;
275              //cout << " zwischen = " << zwischen << " ni = " << n[i]<<endl;
276              h[ i ][ j ] = sinterpol( g[i], xi, zwischen, n[i] );
277              DEBOUTLN( cerr, " Ergebnis von sinterpol h["<<i<<"]["<<j<< "] = " << h[i][j] );
278              delete [] zwischen;
279            }
280        }
281      for ( i = 1 ; i <= m ; i++ )
282        {
283          CFArray zwitscher( 1, d );
284          for ( j = 1 ; j <= d ; j++ )
285            {
286              zwitscher[ j ] = h[ i ][ j ];
287            }
288
289          DEBOUTLN( cerr, "Werte fuer dinterpol : " );
290          DEBOUTLN( cerr, " d = " << d << " g["<<i<<"] = "<< g[i] );
291          DEBOUTLN( cerr, " zwitscher = " << zwitscher );
292          DEBOUTLN( cerr, " alpha["<<s<< "] = "<< alpha[s] << " beta = "<<beta << " n["<<i<<"] = " << n[i] );
293
294          g[ i ] = dinterpol( d, g[i], zwitscher, alpha, s, beta, n[ i ], CHAR );
295          DEBOUTLN( cerr, " Ergebnis von dinterpol g["<<i<<"] = " << g[i] );
296
297        }
298
299
300      for ( i = 1 ; i <= m ; i++ )
301        {
302          G[ s ] += g[ i ] * ( power( x, emma[i] ) );
303        }
304      DEBOUTLN( cerr, "G["<<s<<"] = " << G[s] );
305      for ( i = 1; i <= m; i++ ) {
306        for ( j = 1; j <= d; j++ )
307          delete [] tau[i][j];
308        delete [] tau[i];
309      }
310      delete [] tau;
311    }
312  delete [] emma;
313
314  return G[ levU ];
315}
316
317// In sparsemod testen, ob G[levU] | u und G[levU] | v ///
318static CanonicalForm
319internalSparsemod( const CanonicalForm & F, const CanonicalForm & G )
320{
321  // On(SW_USE_EZGCD );
322  On( SW_SYMMETRIC_FF );
323  //cout << " in sparse " << endl;
324  if( F.inCoeffDomain() &&  G.inCoeffDomain() )
325    {
326      return gcd( F, G );
327    }
328
329  CanonicalForm f, g, ff, gg, ggt, res, fmodp, gmodp ;
330  int i, count = 10;
331
332  //   COMPRESS    ///////////////////
333
334
335  CFArray A(1, 2);
336  A[1] = F;
337  A[2] = G;
338  CFMap M, N;
339  compress(A, M, N);
340  f = M(A[1]);
341  g = M(A[2]);
342
343
344  // POLYNOME PRIMITIV BZGL DER ERSTEN VARIABLE  /////
345
346
347
348  CanonicalForm primif, primig, lcf, lcg, lcggt, lcggtmodp, result ;
349  ff = content( f, Variable(1) );//contentsparse( f, 1  );
350  gg = content( g, Variable(1) );//contentsparse( g, 1  );
351
352
353
354  primif = f/ff;
355  primig = g/gg;
356  ggt = gcd( ff, gg );
357
358  if( primif.inCoeffDomain() &&  primig.inCoeffDomain() )
359    {
360      return N( gcd( primif, primig ) ) * N( ggt );
361    }
362
363
364
365
366  // Variablen, die in beiden Polynomen auftreten /////
367
368  int levis, m, levelprimif, levelprimig;
369  int  ABFRAGE = 1 ;
370
371  levelprimif = level( primif );
372  levelprimig = level( primig );
373
374  if ( levelprimif > levelprimig )
375    levis = levelprimif;
376  else
377    levis = levelprimig;
378
379  if ( levis < 0 )
380    return N( gcd( primif, primig ) );
381
382  int * varf = new int[levis];
383  int * varg = new int[levis];
384  int * schnitt = new int[levis];
385
386  while ( ABFRAGE == 1 )
387    {
388      levelprimif = level(primif);
389      levelprimig = level(primig);
390
391      if ( levelprimif > levelprimig )
392        levis = levelprimif;
393      else
394        levis = levelprimig;
395
396      if ( levis < 0 )
397        return N( gcd(primif, primig ));
398
399
400      for( i = 1; i <= levis ; i++ )
401        {
402          if ( degree( primif, i ) != 0 )
403            varf[i] = 1;
404          else
405            varf[i] = 0;
406          if ( degree( primig, i ) != 0 )
407            varg[i] = 1;
408          else
409            varg[i] = 0;
410          if ( varg[i] == 1 && varf[i] == 1 )
411            schnitt[i] = 1;
412          else
413            schnitt[i] = 0;
414        }
415
416      levelprimif = level(primif);
417      levelprimig = level(primig);
418
419      for ( m  = 1; m <= levis ; m++)
420        {
421          if ( schnitt[m] == 0 )
422            if ( varf[m] == 1)
423              {
424                primif = content( primif, m ); //contentsparse( primif, m  );
425              }
426            else
427              {
428                primig = content( primig, m ); //contentsparse( primig, m  );
429              }
430        }
431
432      if ( level( primif ) == level( primig ) )
433        ABFRAGE = 0 ;
434
435    }
436
437 
438  delete [] varf; delete [] varg; delete [] schnitt;
439
440
441  //  Nochmal compress fuer den Fall, dass eine Variable rausfliegt //
442
443
444  CFArray C(1, 2);
445  C[1] = primif;
446  C[2] = primig;
447  CFMap MM, NN ;
448  compress(C, MM, NN);
449  primif = MM(C[1]);
450  primig = MM(C[2]);
451
452  if ( level( primif) != level( primig ) )
453    ASSERT( 0, "this should n e v e r happen !!!!" );
454
455  //cout << " primif = " << primif << endl;
456  //cout << " primig = " << primig << endl;
457
458  if( primif.inCoeffDomain() &&  primig.inCoeffDomain() )
459    {
460      return N( NN( gcd( primif, primig ) ) ) * N( ggt );
461    }
462
463  // erst hier Leitkoeffizienten updaten  /////////
464
465  //if( primif.inCoeffDomain() || primif.isUnivariate
466
467  lcf = LC(primif, 1 );
468  lcg = LC(primig, 1 );
469  lcggt = gcd ( lcf, lcg );
470
471
472
473  //   BOUND BESTIMMEN fuer Charakteristik Null   /////////
474
475  int CHAR = getCharacteristic(), deg  ;
476  if ( CHAR < 10 )
477    deg = 3; // Default Erweiterung bei kleiner Primzahl;
478  else
479    deg = 1;
480  CanonicalForm B, L, Bound, lcF = Leitkoeffizient( primif); //lc( primif ) ;
481  B =  2 * maxCoeff( primif ) * maxCoeff( g ) ;
482  L = lcF ;
483  Bound = abs( 2 * B * L + 1 );
484  int length = 1;
485
486  CFArray p( 1, 10 ) ;
487
488  if( CHAR == 0 )
489    {
490      p[ 1 ]  = cf_getBigPrime( count );
491      CanonicalForm q = p[ 1 ];
492
493      while ( q < Bound )
494        {
495          count++;
496          length++;
497          p[ length ] = cf_getBigPrime( count );
498          q     *= p[ length ];  //G[levU] = ( 1/lc(G[levU] ))* G[levU];// sinnig?
499    //cout << " lcggt = " << lcggt << endl;
500    //bool ja;
501    //ja = divides( lcggt, lc( G[levU] ) );
502    //cout << " ja = " << ja << endl;
503    //cout << " vor Verlassen " << endl;
504        }
505    }
506  else
507    {
508      //int q  = CHAR;
509      //setCharacteristic( 0 );
510      //CanonicalForm Bound2 = mapinto( Bound ) ;
511      //cout << " Bound2 " << Bound2 << endl;
512      //cout << " CHAR =  " << q << endl;
513
514      // erstmal ohne Erweiterung !!!
515      //deg = 3; // Default Erweiterung
516      //q *= ( q * q ) ;cout << "q = " << q << endl;
517
518      //Bestimme Grad der Koerpererweiterung voellig unnuetz!!!
519      //while ( q < abs( Bound2 ) )
520      //        {
521      //  q *= CHAR;cout << " q = " << q << endl;
522      //deg++;cout << " degchar = " << deg << endl;
523      //cout << " in Graderhoehung? " << endl;
524
525      //}
526      //setCharacteristic( CHAR );
527      //cerr << " JUHU " << endl;
528    }
529
530
531
532
533  //        ENDE BOUNDBESTIMMUNG       /////////////////
534
535
536  FFRandom gen ;
537  levelprimif = level( primif );
538  REvaluation am( 2, levelprimif, FFRandom ( ));
539  int k, help ;
540  CFArray resultat( 1, length );//cout << " nach Resultat " << endl;
541  CanonicalForm zwischen;
542  Variable alpha1( levelprimif + 1 );
543  ABFRAGE = 0;
544
545
546  for ( i = 1 ; i <= 10; i++ )               // 10 Versuche mit sparsemod
547    {
548      if ( CHAR == 0 )
549        {
550          for( k = 1; k <= length ; k++)
551            {
552              help = p[ k ].intval();
553              setCharacteristic( help );
554              FFRandom mache;
555              am = REvaluation( 2, levelprimif, mache  );
556              am.nextpoint();
557              fmodp  = mapinto( primif );
558              gmodp = mapinto( primig );
559              lcggtmodp = mapinto ( lcggt );
560
561              zwischen = smodgcd( fmodp, gmodp, lcggtmodp, am, mache, CHAR, Variable( 1 ));
562              // Variable ( 1 ) Interface fuer endliche Koerper
563
564              // Char auf 0 wegen Chinese Remainder ////////
565
566              setCharacteristic( 0 );
567
568
569              resultat[ k ] = mapinto( zwischen );
570
571            }
572
573
574          ////////////////////////////////////////////////////////////
575          // result[k] mod p[k] via Chinese Remainder zu Resultat //////
576          // ueber Z hochziehen                                //////
577          ////////////////////////////////////////////////////////////
578
579          if( length != 1 )
580            ChinesePoly( length, resultat, p, result );
581          else
582            result = resultat[1];
583
584          CanonicalForm contentresult = content( result, 1 );
585
586          if ( contentresult != 0 )
587            res = result/contentresult;
588          else
589            res = result;
590
591          if ( divides( res, primif ) && divides( res, primig ) )
592            return  N(NN(res))*N(ggt) ;     /// compress rueckgaengig machen!
593          else
594            {
595
596              // Start all over again ///
597
598              count++;
599              for ( k = 1; k <= length ; k++)
600                {
601                  p[k] = cf_getBigPrime( count );
602                  count++;
603                }
604
605            }
606        }
607      else
608        {
609          // Fall Char != 0 ///
610          // in algebraische Erweiterung vom Grad deg gehen //
611          //cout << " IN CHAR != 0 " << endl;
612          //cout << " degree = " << deg << endl;
613          CanonicalForm minimalpoly;
614          //cout << " vor mini " << endl;
615          minimalpoly = find_irreducible( deg, gen, alpha1 );
616          //cout << " nach mini " << endl;
617          Variable alpha2 = rootOf( minimalpoly, 'a' ) ;
618          AlgExtRandomF hallo( alpha2 );
619          //cout << " vor am " << endl;
620          REvaluation am (  2, levelprimif, hallo );
621          //cout << " nach ma " << endl;
622          am.nextpoint();
623          //cout << "vor smodgcd " << endl;
624          result = smodgcd( primif, primig, lcggt, am, hallo, CHAR, alpha2  );
625          if ( result == 1 && ABFRAGE == 0)
626            {
627              // zwei Auswertungen fuer gcd Eins
628              am.nextpoint();
629              ABFRAGE = 1;
630            }
631          //CanonicalForm contentresult = contentsparse(  result, 1 );
632          //zuerst mal auf Nummer sicher gehen ...
633          else
634            {
635              CanonicalForm contentresult = content(  result, 1 );
636              //cout << "RESULT = " << result << endl;
637              if ( contentresult != 0 )
638                res = result/contentresult;
639              else
640                {
641                  res = result;
642                }
643
644
645              if ( ( divides( res, primif )) && ( divides ( res, primig ) ))
646                {
647                  // make monic ////
648                  res = (1/lc(res)) * res;
649                  // eventuell auch hier Leitkoeffizient anstatt lc ?
650
651                  return  N( NN( res ) ) * N( ggt ) ;
652                }
653              else
654                {
655                  // Grad der Erweiterung sukzessive um eins erhoehen
656                  deg++;
657                  //cout << " deg = " << deg << endl;
658                  am.nextpoint();
659                  // nextpoint() unnoetig?
660                }
661            }
662        }
663    }
664
665
666  //Fuer den Fall der unwahrscheinlichen Faelle, dass die Versuche
667  //nicht ausreichen :
668
669  ASSERT( 0, "sparsemod failed! try some other gcd algorithm" );
670  if( CHAR == 0 )
671    setCharacteristic( 0 );
672
673  return 0;
674
675}
676
677CanonicalForm
678sparsemod( const CanonicalForm & F, const CanonicalForm & G )
679{
680    Off( SW_USE_SPARSEMOD );
681    CanonicalForm result = internalSparsemod( F, G );
682    On( SW_USE_SPARSEMOD );
683    return result;
684}
Note: See TracBrowser for help on using the repository browser.