source: git/factory/sm_sparsemod.cc @ 38b236

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