source: git/factory/cfNewtonPolygon.cc @ ffae30

spielwiese
Last change on this file since ffae30 was ffae30, checked in by Martin Lee <martinlee84@…>, 11 years ago
chg: long instead of int
  • Property mode set to 100644
File size: 30.9 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file cfNewtonPolygon.cc
5 *
6 * This file provides functions to compute the Newton polygon of a bivariate
7 * polynomial
8 *
9 * @author Martin Lee
10 *
11 **/
12/*****************************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include "config.h"
16#endif /* HAVE_CONFIG_H */
17
18#include "cf_assert.h"
19
20#include <stdlib.h>
21
22#include "canonicalform.h"
23#include "cf_iter.h"
24#include "cf_algorithm.h"
25#include "cf_primes.h"
26#include "cf_reval.h"
27#include "cf_factory.h"
28#include "gfops.h"
29#include "cfNewtonPolygon.h"
30#include "templates/ftmpl_functions.h"
31#include "algext.h"
32
33static
34void translate (int** points, int* point, int sizePoints) //make point to 0
35{
36  for (int i= 0; i < sizePoints; i++)
37  {
38    points[i] [0] -= point [0];
39    points[i] [1] -= point [1];
40  }
41}
42
43static
44int smallestPointIndex (int** points, int sizePoints)
45{
46  int min= 0;
47  for (int i= 1; i < sizePoints; i++)
48  {
49    if (points[i][0] < points[min][0] ||
50        (points[i] [0] == points[min] [0] && points[i] [1] < points[min] [1]))
51      min= i;
52  }
53  return min;
54}
55
56static
57void swap (int** points, int i, int j)
58{
59  int* tmp= points[i];
60  points[i]= points[j];
61  points[j]= tmp;
62}
63
64static
65bool isLess (int* point1, int* point2)
66{
67  long area= point1[0]*point2[1]- point1[1]*point2[0];
68  if (area > 0) return true;
69  if (area == 0)
70  {
71    return (abs (point1[0]) + abs (point1[1]) >
72            abs (point2[0]) + abs (point2[1]));
73  }
74  return false;
75}
76
77static
78void quickSort (int lo, int hi, int** points)
79{
80  int i= lo, j= hi;
81  int* point= new int [2];
82  point [0]= points [(lo+hi)/2] [0];
83  point [1]= points [(lo+hi)/2] [1];
84  while (i <= j)
85  {
86    while (isLess (points [i], point) && i < hi) i++;
87    while (isLess (point, points[j]) && j > lo) j--;
88    if (i <= j)
89    {
90      swap (points, i, j);
91      i++;
92      j--;
93    }
94  }
95  delete [] point;
96  if (lo < j) quickSort (lo, j, points);
97  if (i < hi) quickSort (i, hi, points);
98}
99
100static
101void sort (int** points, int sizePoints)
102{
103  quickSort (1, sizePoints - 1, points);
104}
105
106// check whether p2 is convex
107static
108bool isConvex (int* point1, int* point2, int* point3)
109{
110  long relArea= (point1[0] - point2[0])*(point3[1] - point2[1]) -
111                (point1[1] - point2[1])*(point3[0] - point2[0]);
112  if (relArea < 0)
113    return true;
114  if (relArea == 0)
115  {
116    return !(abs (point1[0] - point3[0]) + abs (point1[1] - point3[1]) >=
117             (abs (point2[0] - point1[0]) + abs (point2[1] - point1[1]) +
118             abs (point2[0] - point3[0]) + abs (point2[1] - point3[1])));
119  }
120  return false;
121}
122
123static
124bool isConvex (int** points, int i)
125{
126  return isConvex (points[i - 1], points [i], points [i + 1]);
127}
128
129int grahamScan (int** points, int sizePoints)
130{
131  swap (points, 0, smallestPointIndex (points, sizePoints));
132  int * minusPoint= new int [2];
133  minusPoint [0]= points[0] [0];
134  minusPoint [1]= points[0] [1];
135  translate (points, minusPoint, sizePoints);
136  sort (points, sizePoints);
137  minusPoint[0]= - minusPoint[0];
138  minusPoint[1]= - minusPoint[1];
139  translate (points, minusPoint, sizePoints); //reverse translation
140  delete [] minusPoint;
141  int i= 3, k= 3;
142  while (k < sizePoints)
143  {
144    swap (points, i, k);
145    while (!isConvex (points, i - 1))
146    {
147      swap (points, i - 1, i);
148      i--;
149    }
150    k++;
151    i++;
152  }
153  if (i + 1 <= sizePoints || i == sizePoints)
154  {
155    long relArea=
156    (points [i-2][0] - points [i-1][0])*(points [0][1] - points [i-1][1])-
157    (points [i-2][1] - points [i-1][1])*(points [0][0] - points [i-1][0]);
158    if (relArea == 0)
159    {
160      if (abs (points [i-2][0] - points [0][0]) +
161          abs (points [i-2][1] - points [0][1]) >=
162          abs (points [i-1][0] - points [i-2][0]) +
163          abs (points [i-1][1] - points [i-2][1]) +
164          abs (points [i-1][0] - points [0][0]) +
165          abs (points [i-1][1] - points [0][1]))
166          i--;
167    }
168  }
169  return i;
170}
171
172//points[i] [0] is x-coordinate, points [i] [1] is y-coordinate
173int polygon (int** points, int sizePoints)
174{
175  if (sizePoints < 3) return sizePoints;
176  return grahamScan (points, sizePoints);
177}
178
179static
180int* getDegrees (const CanonicalForm& F, int& sizeOfOutput)
181{
182  if (F.inCoeffDomain())
183  {
184    int* result= new int [1];
185    result [0]= 0;
186    sizeOfOutput= 1;
187    return result;
188  }
189  sizeOfOutput= size (F);
190  int* result= new int [sizeOfOutput];
191  int j= 0;
192  for (CFIterator i= F; i.hasTerms(); i++, j++)
193    result [j]= i.exp();
194  return result;
195}
196
197//get points in Z^2 whose convex hull is the Newton polygon
198int ** getPoints (const CanonicalForm& F, int& n)
199{
200  n= size (F);
201  int ** points= new int* [n];
202  for (int i= 0; i < n; i++)
203    points [i]= new int [2];
204
205  int j= 0;
206  int * buf;
207  int bufSize;
208  if (F.isUnivariate() && F.level() == 1)
209  {
210    for (CFIterator i= F; i.hasTerms(); i++, j++)
211    {
212      points [j] [0]= i.exp();
213      points [j] [1]= 0;
214    }
215    return points;
216  }
217  for (CFIterator i= F; i.hasTerms(); i++)
218  {
219    buf= getDegrees (i.coeff(), bufSize);
220    for (int k= 0; k < bufSize; k++, j++)
221    {
222      points [j] [0]= i.exp();
223      points [j] [1]= buf [k];
224    }
225    delete [] buf;
226  }
227  return points;
228}
229
230int **
231merge (int ** points1, int sizePoints1, int ** points2, int sizePoints2,
232       int& sizeResult)
233{
234  int i, j;
235  sizeResult= sizePoints1+sizePoints2;
236  for (i= 0; i < sizePoints1; i++)
237  {
238    for (j= 0; j < sizePoints2; j++)
239    {
240      if (points1[i][0] != points2[j][0])
241        continue;
242      else
243      {
244        if (points1[i][1] != points2[j][1])
245          continue;
246        else
247        {
248          points2[j][0]= -1;
249          points2[j][1]= -1;
250          sizeResult--;
251        }
252      }
253    }
254  }
255  if (sizeResult == 0)
256    return points1;
257
258  int ** result= new int *[sizeResult];
259  for (i= 0; i < sizeResult; i++)
260    result [i]= new int [2];
261
262  int k= 0;
263  for (i= 0; i < sizePoints1; i++, k++)
264  {
265    result[k][0]= points1[i][0];
266    result[k][1]= points1[i][1];
267  }
268  for (i= 0; i < sizePoints2; i++)
269  {
270    if (points2[i][0] < 0)
271      continue;
272    else
273    {
274      result[k][0]= points2[i][0];
275      result[k][1]= points2[i][1];
276      k++;
277    }
278  }
279  return result;
280}
281
282// assumes a bivariate poly as input
283int ** newtonPolygon (const CanonicalForm& F, int& sizeOfNewtonPoly)
284{
285  int sizeF= size (F);
286  int ** points= new int* [sizeF];
287  for (int i= 0; i < sizeF; i++)
288    points [i]= new int [2];
289  int j= 0;
290  int * buf;
291  int bufSize;
292  for (CFIterator i= F; i.hasTerms(); i++)
293  {
294    buf= getDegrees (i.coeff(), bufSize);
295    for (int k= 0; k < bufSize; k++, j++)
296    {
297      points [j] [0]= i.exp();
298      points [j] [1]= buf [k];
299    }
300    delete [] buf;
301  }
302
303  int n= polygon (points, sizeF);
304
305  int ** result= new int* [n];
306  for (int i= 0; i < n; i++)
307  {
308    result [i]= new int [2];
309    result [i] [0]= points [i] [0];
310    result [i] [1]= points [i] [1];
311  }
312
313  sizeOfNewtonPoly= n;
314  for (int i= 0; i < sizeF; i++)
315    delete [] points[i];
316  delete [] points;
317
318  return result;
319}
320
321// assumes a bivariate polys as input
322int ** newtonPolygon (const CanonicalForm& F, const CanonicalForm& G,
323                      int& sizeOfNewtonPoly)
324{
325  int sizeF= size (F);
326  int ** pointsF= new int* [sizeF];
327  for (int i= 0; i < sizeF; i++)
328    pointsF [i]= new int [2];
329  int j= 0;
330  int * buf;
331  int bufSize;
332  for (CFIterator i= F; i.hasTerms(); i++)
333  {
334    buf= getDegrees (i.coeff(), bufSize);
335    for (int k= 0; k < bufSize; k++, j++)
336    {
337      pointsF [j] [0]= i.exp();
338      pointsF [j] [1]= buf [k];
339    }
340    delete [] buf;
341  }
342
343  int sizeG= size (G);
344  int ** pointsG= new int* [sizeG];
345  for (int i= 0; i < sizeG; i++)
346    pointsG [i]= new int [2];
347  j= 0;
348  for (CFIterator i= G; i.hasTerms(); i++)
349  {
350    buf= getDegrees (i.coeff(), bufSize);
351    for (int k= 0; k < bufSize; k++, j++)
352    {
353      pointsG [j] [0]= i.exp();
354      pointsG [j] [1]= buf [k];
355    }
356    delete [] buf;
357  }
358
359  int sizePoints;
360  int ** points= merge (pointsF, sizeF, pointsG, sizeG, sizePoints);
361
362  int n= polygon (points, sizePoints);
363
364  int ** result= new int* [n];
365  for (int i= 0; i < n; i++)
366  {
367    result [i]= new int [2];
368    result [i] [0]= points [i] [0];
369    result [i] [1]= points [i] [1];
370  }
371
372  sizeOfNewtonPoly= n;
373  for (int i= 0; i < sizeF; i++)
374    delete [] pointsF[i];
375  delete [] pointsF;
376  for (int i= 0; i < sizeG; i++)
377    delete [] pointsG[i];
378  delete [] pointsG;
379
380  return result;
381}
382
383// assumes first sizePoints entries of points form a Newton polygon
384bool isInPolygon (int ** points, int sizePoints, int* point)
385{
386  int ** buf= new int* [sizePoints + 1];
387  for (int i= 0; i < sizePoints; i++)
388  {
389    buf [i]= new int [2];
390    buf [i] [0]= points [i] [0];
391    buf [i] [1]= points [i] [1];
392  }
393  buf [sizePoints]= new int [2];
394  buf [sizePoints] [0]= point [0];
395  buf [sizePoints] [1]= point [1];
396  int sizeBuf= sizePoints + 1;
397
398  swap (buf, 0, smallestPointIndex (buf, sizeBuf));
399  int * minusPoint= new int [2];
400  minusPoint [0]= buf[0] [0];
401  minusPoint [1]= buf[0] [1];
402  translate (buf, minusPoint, sizeBuf);
403  sort (buf, sizeBuf);
404  minusPoint[0]= - minusPoint[0];
405  minusPoint[1]= - minusPoint[1];
406  translate (buf, minusPoint, sizeBuf); //reverse translation
407  delete [] minusPoint;
408
409  if (buf [0] [0] == point [0] && buf [0] [1] == point [1])
410  {
411    for (int i= 0; i < sizeBuf; i++)
412      delete [] buf[i];
413    delete [] buf;
414    return false;
415  }
416
417  for (int i= 1; i < sizeBuf-1; i++)
418  {
419    if (buf [i] [0] == point [0] && buf [i] [1] == point [1])
420    {
421      bool result= !isConvex (buf, i);
422      for (int i= 0; i < sizeBuf; i++)
423        delete [] buf [i];
424      delete [] buf;
425      return result;
426    }
427  }
428
429  if (buf [sizeBuf - 1] [0] == point [0] && buf [sizeBuf-1] [1] == point [1])
430  {
431    buf [1] [0]= point [0];
432    buf [1] [1]= point [1];
433    buf [2] [0]= buf [0] [0];
434    buf [2] [1]= buf [0] [1];
435    buf [0] [0]= buf [sizeBuf-2] [0];
436    buf [0] [1]= buf [sizeBuf-2] [1];
437    bool result= !isConvex (buf, 1);
438    for (int i= 0; i < sizeBuf; i++)
439      delete [] buf [i];
440    delete [] buf;
441    return result;
442  }
443  for (int i= 0; i < sizeBuf; i++)
444    delete [] buf [i];
445  delete [] buf;
446
447  return false;
448}
449
450void lambda (int** points, int sizePoints)
451{
452  for (int i= 0; i < sizePoints; i++)
453    points [i] [1]= points [i] [1] - points [i] [0];
454}
455
456void lambdaInverse (int** points, int sizePoints)
457{
458  for (int i= 0; i < sizePoints; i++)
459    points [i] [1]= points [i] [1] + points [i] [0];
460}
461
462void tau (int** points, int sizePoints, int k)
463{
464  for (int i= 0; i < sizePoints; i++)
465    points [i] [1]= points [i] [1] + k;
466}
467
468void mu (int** points, int sizePoints)
469{
470  int tmp;
471  for (int i= 0; i < sizePoints; i++)
472  {
473    tmp= points [i] [0];
474    points [i] [0]= points [i] [1];
475    points [i] [1]= tmp;
476  }
477}
478
479void getMaxMin (int** points, int sizePoints, int& minDiff, int& minSum,
480                int& maxDiff, int& maxSum, int& maxX, int& maxY
481               )
482{
483  minDiff= points [0] [1] - points [0] [0];
484  minSum= points [0] [1] + points [0] [0];
485  maxDiff= points [0] [1] - points [0] [0];
486  maxSum= points [0] [1] + points [0] [0];
487  maxX= points [0] [1];
488  maxY= points [0] [0];
489  int diff, sum;
490  for (int i= 1; i < sizePoints; i++)
491  {
492    diff= points [i] [1] - points [i] [0];
493    sum= points [i] [1] + points [i] [0];
494    minDiff= tmin (minDiff, diff);
495    minSum= tmin (minSum, sum);
496    maxDiff= tmax (maxDiff, diff);
497    maxSum= tmax (maxSum, sum);
498    maxX= tmax (maxX, points [i] [1]);
499    maxY= tmax (maxY, points [i] [0]);
500  }
501}
502
503void mpz_mat_mul (const mpz_t* N, mpz_t*& M)
504{
505  mpz_t * tmp= new mpz_t[4];
506
507  mpz_init_set (tmp[0], N[0]);
508  mpz_mul (tmp[0], tmp[0], M[0]);
509  mpz_addmul (tmp[0], N[1], M[2]);
510
511  mpz_init_set (tmp[1], N[0]);
512  mpz_mul (tmp[1], tmp[1], M[1]);
513  mpz_addmul (tmp[1], N[1], M[3]);
514
515  mpz_init_set (tmp[2], N[2]);
516  mpz_mul (tmp[2], tmp[2], M[0]);
517  mpz_addmul (tmp[2], N[3], M[2]);
518
519  mpz_init_set (tmp[3], N[2]);
520  mpz_mul (tmp[3], tmp[3], M[1]);
521  mpz_addmul (tmp[3], N[3], M[3]);
522
523  mpz_set (M[0], tmp[0]);
524  mpz_set (M[1], tmp[1]);
525  mpz_set (M[2], tmp[2]);
526  mpz_set (M[3], tmp[3]);
527
528  mpz_clear (tmp[0]);
529  mpz_clear (tmp[1]);
530  mpz_clear (tmp[2]);
531  mpz_clear (tmp[3]);
532
533  delete [] tmp;
534}
535
536void mpz_mat_inv (mpz_t*& M)
537{
538  mpz_t det;
539  mpz_init_set (det, M[0]);
540  mpz_mul (det, det, M[3]);
541  mpz_submul (det, M[1], M[2]);
542
543  mpz_t tmp;
544  mpz_init_set (tmp, M[0]);
545  mpz_divexact (tmp, tmp, det);
546  mpz_set (M[0], M[3]);
547  mpz_divexact (M[0], M[0], det);
548  mpz_set (M[3], tmp);
549
550  mpz_neg (M[1], M[1]);
551  mpz_divexact (M[1], M[1], det);
552  mpz_neg (M[2], M[2]);
553  mpz_divexact (M[2], M[2], det);
554
555  mpz_clear (det);
556  mpz_clear (tmp);
557}
558
559void convexDense(int** points, int sizePoints, mpz_t*& M, mpz_t*& A)
560{
561  if (sizePoints < 3)
562  {
563    if (sizePoints == 2)
564    {
565      mpz_t u,v,g,maxX,maxY;
566      mpz_init (u);
567      mpz_init (v);
568      mpz_init (g);
569      mpz_init_set_si (maxX,
570                       (points[1][1] < points[0][1])?points[0][1]:points[1][1]);
571      mpz_init_set_si (maxY,
572                       (points[1][0] < points[0][0])?points[0][0]:points[1][0]);
573      mpz_gcdext (g, u, v, maxX, maxY);
574      if (points [0] [1] != points [0] [0] && points [1] [0] != points [1] [1])
575      {
576        mpz_set (A[0], u);
577        mpz_mul (A[0], A[0], maxX);
578        mpz_set (M[2], maxY);
579        mpz_divexact (M[2], M[2], g);
580        mpz_set (A[1], M[2]);
581        mpz_neg (A[1], A[1]);
582        mpz_mul (A[1], A[1], maxX);
583        mpz_neg (u, u);
584        mpz_set (M[0], u);
585        mpz_set (M[1], v);
586        mpz_set (M[3], maxX);
587        mpz_divexact (M[3], M[3], g);
588      }
589      else
590      {
591        mpz_set (M[0], u);
592        mpz_set (M[1], v);
593        mpz_set (M[2], maxY);
594        mpz_divexact (M[2], M[2], g);
595        mpz_neg (M[2], M[2]);
596        mpz_set (M[3], maxX);
597        mpz_divexact (M[3], M[3], g);
598      }
599      mpz_clear (u);
600      mpz_clear (v);
601      mpz_clear (g);
602      mpz_clear (maxX);
603      mpz_clear (maxY);
604    }
605    else if (sizePoints == 1)
606    {
607      mpz_set_si (M[0], 1);
608      mpz_set_si (M[3], 1);
609    }
610    return;
611  }
612  mpz_set_si (M[0], 1);
613  mpz_set_si (M[3], 1);
614
615  mpz_t * Mu= new mpz_t[4];
616  mpz_init_set_si (Mu[1], 1);
617  mpz_init_set_si (Mu[2], 1);
618  mpz_init (Mu[0]);
619  mpz_init (Mu[3]);
620
621  mpz_t * Lambda= new mpz_t[4];
622  mpz_init_set_si (Lambda[0], 1);
623  mpz_init_set_si (Lambda[1], -1);
624  mpz_init_set_si (Lambda[3], 1);
625  mpz_init (Lambda[2]);
626
627  mpz_t * InverseLambda= new mpz_t[4];
628  mpz_init_set_si (InverseLambda[0], 1);
629  mpz_init_set_si (InverseLambda[1], 1);
630  mpz_init_set_si (InverseLambda[3], 1);
631  mpz_init (InverseLambda[2]);
632
633  mpz_t tmp;
634  mpz_init (tmp);
635  int minDiff, minSum, maxDiff, maxSum, maxX, maxY, b, d, f, h;
636  getMaxMin(points, sizePoints, minDiff, minSum, maxDiff, maxSum, maxX, maxY);
637  do
638  {
639    if (maxX < maxY)
640    {
641      mu (points, sizePoints);
642
643      mpz_mat_mul (Mu, M);
644
645      mpz_set (tmp, A[0]);
646      mpz_set (A[0], A[1]);
647      mpz_set (A[1], tmp);
648    }
649    getMaxMin(points, sizePoints, minDiff, minSum, maxDiff, maxSum, maxX, maxY);
650    b= maxX - maxDiff;
651    d= maxX + maxY - maxSum;
652    f= maxY + minDiff;
653    h= minSum;
654    if (b + f > maxY)
655    {
656      lambda (points, sizePoints);
657      tau (points, sizePoints, maxY - f);
658
659      mpz_mat_mul (Lambda, M);
660
661      if (maxY-f > 0)
662        mpz_add_ui (A[0], A[0], maxY-f);
663      else
664        mpz_add_ui (A[0], A[0], f-maxY);
665      maxX= maxX + maxY - b - f;
666    }
667    else if (d + h > maxY)
668    {
669      lambdaInverse (points, sizePoints);
670      tau (points, sizePoints, -h);
671
672      mpz_mat_mul (InverseLambda, M);
673
674      if (h < 0)
675        mpz_add_ui (A[0], A[0], -h);
676      else
677        mpz_sub_ui (A[0], A[0], h);
678      maxX= maxX + maxY - d - h;
679    }
680    else
681    {
682      mpz_clear (tmp);
683      mpz_clear (Mu[0]);
684      mpz_clear (Mu[1]);
685      mpz_clear (Mu[2]);
686      mpz_clear (Mu[3]);
687      delete [] Mu;
688
689      mpz_clear (Lambda[0]);
690      mpz_clear (Lambda[1]);
691      mpz_clear (Lambda[2]);
692      mpz_clear (Lambda[3]);
693      delete [] Lambda;
694
695      mpz_clear (InverseLambda[0]);
696      mpz_clear (InverseLambda[1]);
697      mpz_clear (InverseLambda[2]);
698      mpz_clear (InverseLambda[3]);
699      delete [] InverseLambda;
700
701      return;
702    }
703  } while (1);
704}
705
706CanonicalForm
707compress (const CanonicalForm& F, mpz_t*& M, mpz_t*& A, bool computeMA)
708{
709  int n;
710  int ** newtonPolyg= NULL;
711  if (computeMA)
712  {
713    newtonPolyg= newtonPolygon (F, n);
714    convexDense (newtonPolyg, n, M, A);
715  }
716
717  CanonicalForm result= 0;
718  Variable x= Variable (1);
719  Variable y= Variable (2);
720
721  mpz_t expX, expY, minExpX, minExpY;
722  mpz_init (expX);
723  mpz_init (expY);
724  mpz_init (minExpX);
725  mpz_init (minExpY);
726
727  int k= 0;
728  Variable alpha;
729  for (CFIterator i= F; i.hasTerms(); i++)
730  {
731    if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha))
732    {
733      mpz_set (expX, A[0]);
734      mpz_set (expY, A[1]);
735      mpz_addmul_ui (expX, M[1], i.exp());
736      mpz_addmul_ui (expY, M[3], i.exp());
737
738      if (k == 0)
739      {
740        mpz_set (minExpX, expX);
741        mpz_set (minExpY, expY);
742        k= 1;
743      }
744      else
745      {
746        if (mpz_cmp (minExpY, expY) > 0)
747          mpz_set (minExpY, expY);
748        if (mpz_cmp (minExpX, expX) > 0)
749          mpz_set (minExpX, expX);
750      }
751      result += i.coeff()*power (x, mpz_get_si (expX))*
752                power (y, mpz_get_si (expY));
753      continue;
754    }
755    CFIterator j= i.coeff();
756    if (k == 0)
757    {
758      mpz_set (expX, A[0]);
759      mpz_addmul_ui (expX, M[1], i.exp());
760      mpz_addmul_ui (expX, M[0], j.exp());
761
762      mpz_set (expY, A[1]);
763      mpz_addmul_ui (expY, M[3], i.exp());
764      mpz_addmul_ui (expY, M[2], j.exp());
765
766      mpz_set (minExpX, expX);
767      mpz_set (minExpY, expY);
768      result += j.coeff()*power (x, mpz_get_si (expX))*
769                power (y, mpz_get_si (expY));
770      j++;
771      k= 1;
772    }
773
774    for (; j.hasTerms(); j++)
775    {
776      mpz_set (expX, A[0]);
777      mpz_addmul_ui (expX, M[1], i.exp());
778      mpz_addmul_ui (expX, M[0], j.exp());
779
780      mpz_set (expY, A[1]);
781      mpz_addmul_ui (expY, M[3], i.exp());
782      mpz_addmul_ui (expY, M[2], j.exp());
783
784      result += j.coeff()*power (x, mpz_get_si (expX))*
785                power (y, mpz_get_si (expY));
786      if (mpz_cmp (minExpY, expY) > 0)
787        mpz_set (minExpY, expY);
788      if (mpz_cmp (minExpX, expX) > 0)
789        mpz_set (minExpX, expX);
790    }
791  }
792
793  if (mpz_sgn (minExpX) < 0)
794  {
795    result *= power (x,-mpz_get_si(minExpX));
796    result /= CanonicalForm (x, 0);
797  }
798  else
799    result /= power (x,mpz_get_si(minExpX));
800
801  if (mpz_sgn (minExpY) < 0)
802  {
803    result *= power (y,-mpz_get_si(minExpY));
804    result /= CanonicalForm (y, 0);
805  }
806  else
807    result /= power (y,mpz_get_si(minExpY));
808
809  CanonicalForm tmp= LC (result);
810  if (tmp.inPolyDomain() && degree (tmp) <= 0)
811  {
812    int d= degree (result);
813    Variable x= result.mvar();
814    result -= tmp*power (x, d);
815    result += Lc (tmp)*power (x, d);
816  }
817
818  if (computeMA)
819  {
820    for (int i= 0; i < n; i++)
821      delete [] newtonPolyg [i];
822    delete [] newtonPolyg;
823    mpz_mat_inv (M);
824  }
825
826  mpz_clear (expX);
827  mpz_clear (expY);
828  mpz_clear (minExpX);
829  mpz_clear (minExpY);
830
831  return result;
832}
833
834CanonicalForm
835decompress (const CanonicalForm& F, const mpz_t* inverseM, const mpz_t * A)
836{
837  CanonicalForm result= 0;
838  Variable x= Variable (1);
839  Variable y= Variable (2);
840
841  mpz_t expX, expY, minExpX, minExpY;
842  mpz_init (expX);
843  mpz_init (expY);
844  mpz_init (minExpX);
845  mpz_init (minExpY);
846
847  if (F.isUnivariate() && F.level() == 1)
848  {
849    CFIterator i= F;
850
851    mpz_set_si (expX, i.exp());
852    mpz_sub (expX, expX, A[0]);
853    mpz_mul (expX, expX, inverseM[0]);
854    mpz_submul (expX, inverseM[1], A[1]);
855
856    mpz_set_si (expY, i.exp());
857    mpz_sub (expY, expY, A[0]);
858    mpz_mul (expY, expY, inverseM[2]);
859    mpz_submul (expY, inverseM[3], A[1]);
860
861    mpz_set (minExpX, expX);
862    mpz_set (minExpY, expY);
863    result += i.coeff()*power (x, mpz_get_si (expX))*
864              power (y, mpz_get_si (expY));
865    i++;
866    for (; i.hasTerms(); i++)
867    {
868      mpz_set_si (expX, i.exp());
869      mpz_sub (expX, expX, A[0]);
870      mpz_mul (expX, expX, inverseM[0]);
871      mpz_submul (expX, inverseM[1], A[1]);
872
873      mpz_set_si (expY, i.exp());
874      mpz_sub (expY, expY, A[0]);
875      mpz_mul (expY, expY, inverseM[2]);
876      mpz_submul (expY, inverseM[3], A[1]);
877
878      result += i.coeff()*power (x, mpz_get_si (expX))*
879                power (y, mpz_get_si (expY));
880      if (mpz_cmp (minExpY, expY) > 0)
881        mpz_set (minExpY, expY);
882      if (mpz_cmp (minExpX, expX) > 0)
883        mpz_set (minExpX, expX);
884    }
885
886    if (mpz_sgn (minExpX) < 0)
887    {
888      result *= power (x,-mpz_get_si(minExpX));
889      result /= CanonicalForm (x, 0);
890    }
891    else
892      result /= power (x,mpz_get_si(minExpX));
893
894    if (mpz_sgn (minExpY) < 0)
895    {
896      result *= power (y,-mpz_get_si(minExpY));
897      result /= CanonicalForm (y, 0);
898    }
899    else
900      result /= power (y,mpz_get_si(minExpY));
901
902    mpz_clear (expX);
903    mpz_clear (expY);
904    mpz_clear (minExpX);
905    mpz_clear (minExpY);
906
907    return result/ Lc (result); //normalize
908  }
909
910  mpz_t tmp;
911  mpz_init (tmp);
912  int k= 0;
913  Variable alpha;
914  for (CFIterator i= F; i.hasTerms(); i++)
915  {
916    if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha))
917    {
918      mpz_set_si (expX, i.exp());
919      mpz_sub (expX, expX, A[1]);
920      mpz_mul (expX, expX, inverseM[1]);
921      mpz_submul (expX, A[0], inverseM[0]);
922
923      mpz_set_si (expY, i.exp());
924      mpz_sub (expY, expY, A[1]);
925      mpz_mul (expY, expY, inverseM[3]);
926      mpz_submul (expY, A[0], inverseM[2]);
927
928      if (k == 0)
929      {
930        mpz_set (minExpX, expX);
931        mpz_set (minExpY, expY);
932        k= 1;
933      }
934      else
935      {
936        if (mpz_cmp (minExpY, expY) > 0)
937          mpz_set (minExpY, expY);
938        if (mpz_cmp (minExpX, expX) > 0)
939          mpz_set (minExpX, expX);
940      }
941      result += i.coeff()*power (x, mpz_get_si (expX))*
942                power (y, mpz_get_si (expY));
943      continue;
944    }
945    CFIterator j= i.coeff();
946    if (k == 0)
947    {
948      mpz_set_si (expX, j.exp());
949      mpz_sub (expX, expX, A[0]);
950      mpz_mul (expX, expX, inverseM[0]);
951      mpz_set_si (tmp, i.exp());
952      mpz_sub (tmp, tmp, A[1]);
953      mpz_addmul (expX, tmp, inverseM[1]);
954
955      mpz_set_si (expY, j.exp());
956      mpz_sub (expY, expY, A[0]);
957      mpz_mul (expY, expY, inverseM[2]);
958      mpz_set_si (tmp, i.exp());
959      mpz_sub (tmp, tmp, A[1]);
960      mpz_addmul (expY, tmp, inverseM[3]);
961
962      mpz_set (minExpX, expX);
963      mpz_set (minExpY, expY);
964      result += j.coeff()*power (x, mpz_get_si (expX))*
965                power (y, mpz_get_si (expY));
966      j++;
967      k= 1;
968    }
969
970    for (; j.hasTerms(); j++)
971    {
972      mpz_set_si (expX, j.exp());
973      mpz_sub (expX, expX, A[0]);
974      mpz_mul (expX, expX, inverseM[0]);
975      mpz_set_si (tmp, i.exp());
976      mpz_sub (tmp, tmp, A[1]);
977      mpz_addmul (expX, tmp, inverseM[1]);
978
979      mpz_set_si (expY, j.exp());
980      mpz_sub (expY, expY, A[0]);
981      mpz_mul (expY, expY, inverseM[2]);
982      mpz_set_si (tmp, i.exp());
983      mpz_sub (tmp, tmp, A[1]);
984      mpz_addmul (expY, tmp, inverseM[3]);
985
986      result += j.coeff()*power (x, mpz_get_si (expX))*
987                power (y, mpz_get_si (expY));
988      if (mpz_cmp (minExpY, expY) > 0)
989        mpz_set (minExpY, expY);
990      if (mpz_cmp (minExpX, expX) > 0)
991        mpz_set (minExpX, expX);
992    }
993  }
994
995  if (mpz_sgn (minExpX) < 0)
996  {
997    result *= power (x,-mpz_get_si(minExpX));
998    result /= CanonicalForm (x, 0);
999  }
1000  else
1001    result /= power (x,mpz_get_si(minExpX));
1002
1003  if (mpz_sgn (minExpY) < 0)
1004  {
1005    result *= power (y,-mpz_get_si(minExpY));
1006    result /= CanonicalForm (y, 0);
1007  }
1008  else
1009    result /= power (y,mpz_get_si(minExpY));
1010
1011  mpz_clear (expX);
1012  mpz_clear (expY);
1013  mpz_clear (minExpX);
1014  mpz_clear (minExpY);
1015  mpz_clear (tmp);
1016
1017  return result/Lc (result); //normalize
1018}
1019
1020//assumes the input is a Newton polygon of a bivariate polynomial which is
1021//primitive wrt. x and y, i.e. there is at least one point of the polygon lying
1022//on the x-axis and one lying on the y-axis
1023int* getRightSide (int** polygon, int sizeOfPolygon, int& sizeOfOutput)
1024{
1025  int maxY= polygon [0][0];
1026  int indexY= 0;
1027  for (int i= 1; i < sizeOfPolygon; i++)
1028  {
1029    if (maxY < polygon [i][0])
1030    {
1031      maxY= polygon [i][0];
1032      indexY= i;
1033    }
1034    else if (maxY == polygon [i][0])
1035    {
1036      if (polygon [indexY][1] < polygon[i][1])
1037        indexY= i;
1038    }
1039    if (maxY > polygon [i][0])
1040      break;
1041  }
1042
1043  int count= -1;
1044  for (int i= indexY; i < sizeOfPolygon; i++)
1045  {
1046    if (polygon[i][0] == 0)
1047    {
1048      count= i - indexY;
1049      break;
1050    }
1051  }
1052
1053  int * result;
1054  int index= 0;
1055  if (count < 0)
1056  {
1057    result= new int [sizeOfPolygon - indexY];
1058    sizeOfOutput= sizeOfPolygon - indexY;
1059    count= sizeOfPolygon - indexY - 1;
1060    result [0]= polygon[sizeOfPolygon - 1][0] - polygon [0] [0];
1061    index= 1;
1062  }
1063  else
1064  {
1065    sizeOfOutput= count;
1066    result= new int [count];
1067  }
1068
1069  for (int i= indexY + count; i > indexY; i--, index++)
1070    result [index]= polygon [i - 1] [0] - polygon [i] [0];
1071
1072  return result;
1073}
1074
1075bool irreducibilityTest (const CanonicalForm& F)
1076{
1077  ASSERT (getNumVars (F) == 2, "expected bivariate polynomial");
1078  ASSERT (getCharacteristic() == 0, "expected polynomial over integers or rationals");
1079
1080  int sizeOfNewtonPolygon;
1081  int ** newtonPolyg= newtonPolygon (F, sizeOfNewtonPolygon);
1082  if (sizeOfNewtonPolygon == 3)
1083  {
1084    bool check1=
1085        (newtonPolyg[0][0]==0 || newtonPolyg[1][0]==0 || newtonPolyg[2][0]==0);
1086    if (check1)
1087    {
1088      bool check2=
1089        (newtonPolyg[0][1]==0 || newtonPolyg[1][1]==0 || newtonPolyg[2][0]==0);
1090      if (check2)
1091      {
1092        bool isRat= isOn (SW_RATIONAL);
1093        if (isRat)
1094          Off (SW_RATIONAL);
1095        CanonicalForm tmp= gcd (newtonPolyg[0][0],newtonPolyg[0][1]); // maybe it's better to use plain intgcd
1096        tmp= gcd (tmp, newtonPolyg[1][0]);
1097        tmp= gcd (tmp, newtonPolyg[1][1]);
1098        tmp= gcd (tmp, newtonPolyg[2][0]);
1099        tmp= gcd (tmp, newtonPolyg[2][1]);
1100        if (isRat)
1101          On (SW_RATIONAL);
1102        for (int i= 0; i < sizeOfNewtonPolygon; i++)
1103          delete [] newtonPolyg [i];
1104        delete [] newtonPolyg;
1105        return (tmp==1);
1106      }
1107    }
1108  }
1109  for (int i= 0; i < sizeOfNewtonPolygon; i++)
1110    delete [] newtonPolyg [i];
1111  delete [] newtonPolyg;
1112  return false;
1113}
1114
1115bool absIrredTest (const CanonicalForm& F)
1116{
1117  ASSERT (getNumVars (F) == 2, "expected bivariate polynomial");
1118  ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial");
1119
1120  int sizeOfNewtonPolygon;
1121  int ** newtonPolyg= newtonPolygon (F, sizeOfNewtonPolygon);
1122  bool isRat= isOn (SW_RATIONAL);
1123  if (isRat)
1124    Off (SW_RATIONAL);
1125  int p=getCharacteristic();
1126  int d=1;
1127  char bufGFName='Z';
1128  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
1129  if (GF)
1130  {
1131    d= getGFDegree();
1132    bufGFName=gf_name;
1133  }
1134
1135  setCharacteristic(0);
1136
1137  CanonicalForm g= gcd (newtonPolyg[0][0], newtonPolyg[0][1]); //maybe it's better to use plain intgcd
1138
1139  int i= 1;
1140  while (!g.isOne() && i < sizeOfNewtonPolygon)
1141  {
1142    g= gcd (g, newtonPolyg[i][0]);
1143    g= gcd (g, newtonPolyg[i][1]);
1144    i++;
1145  }
1146
1147  bool result= g.isOne();
1148
1149  if (GF)
1150    setCharacteristic (p, d, bufGFName);
1151  else
1152    setCharacteristic(p);
1153
1154  if (isRat)
1155    On (SW_RATIONAL);
1156
1157  for (int i= 0; i < sizeOfNewtonPolygon; i++)
1158    delete [] newtonPolyg[i];
1159
1160  delete [] newtonPolyg;
1161
1162  return result;
1163}
1164
1165bool modularIrredTest (const CanonicalForm& F)
1166{
1167  ASSERT (getNumVars (F) == 2, "expected bivariate polynomial");
1168  ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial");
1169
1170  bool isRat= isOn (SW_RATIONAL);
1171  if (isRat)
1172    Off (SW_RATIONAL);
1173
1174  if (isRat)
1175  {
1176    ASSERT (bCommonDen (F).isOne(), "poly over Z expected");
1177  }
1178
1179  CanonicalForm Fp, N= maxNorm (F);
1180  int tdeg= totaldegree (F);
1181
1182  int i= 0;
1183  //TODO: maybe it's better to choose the characteristic as large as possible
1184  //      as factorization over large finite field will be faster
1185  //TODO: handle those cases where our factory primes are not enough
1186  //TODO: factorize coefficients corresponding to the vertices of the Newton
1187  //      polygon and only try the obtained factors
1188  if (N < cf_getSmallPrime (cf_getNumSmallPrimes()-1))
1189  {
1190    while (i < cf_getNumSmallPrimes() && N > cf_getSmallPrime(i))
1191    {
1192      setCharacteristic (cf_getSmallPrime (i));
1193      Fp= F.mapinto();
1194      i++;
1195      if (totaldegree (Fp) == tdeg)
1196      {
1197        if (absIrredTest (Fp))
1198        {
1199          CFFList factors= factorize (Fp);
1200          if (factors.length() == 2 && factors.getLast().exp() == 1)
1201          {
1202            if (isRat)
1203              On (SW_RATIONAL);
1204            setCharacteristic (0);
1205            return true;
1206          }
1207        }
1208      }
1209      setCharacteristic (0);
1210    }
1211  }
1212  else
1213  {
1214    while (i < cf_getNumPrimes() && N > cf_getPrime (i))
1215    {
1216      setCharacteristic (cf_getPrime (i));
1217      Fp= F.mapinto();
1218      i++;
1219      if (totaldegree (Fp) == tdeg)
1220      {
1221        if (absIrredTest (Fp))
1222        {
1223          CFFList factors= factorize (Fp);
1224          if (factors.length() == 2 && factors.getLast().exp() == 1)
1225          {
1226            if (isRat)
1227              On (SW_RATIONAL);
1228            setCharacteristic (0);
1229            return true;
1230          }
1231        }
1232      }
1233      setCharacteristic (0);
1234    }
1235  }
1236
1237  if (isRat)
1238    On (SW_RATIONAL);
1239
1240  return false;
1241}
1242
1243bool
1244modularIrredTestWithShift (const CanonicalForm& F)
1245{
1246  ASSERT (getNumVars (F) == 2, "expected bivariate polynomial");
1247  ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial");
1248
1249  bool isRat= isOn (SW_RATIONAL);
1250  if (isRat)
1251    Off (SW_RATIONAL);
1252
1253  if (isRat)
1254  {
1255    ASSERT (bCommonDen (F).isOne(), "poly over Z expected");
1256  }
1257
1258  Variable x= Variable (1);
1259  Variable y= Variable (2);
1260  CanonicalForm Fp;
1261  int tdeg= totaldegree (F);
1262
1263  REvaluation E;
1264
1265  setCharacteristic (2);
1266  Fp= F.mapinto();
1267
1268  E= REvaluation (1,2, FFRandom());
1269
1270  E.nextpoint();
1271
1272  Fp= Fp (x+E[1], x);
1273  Fp= Fp (y+E[2], y);
1274
1275  if (tdeg == totaldegree (Fp))
1276  {
1277    if (absIrredTest (Fp))
1278    {
1279      CFFList factors= factorize (Fp);
1280      if (factors.length() == 2 && factors.getLast().exp() == 1)
1281      {
1282        if (isRat)
1283          On (SW_RATIONAL);
1284        setCharacteristic (0);
1285        return true;
1286      }
1287    }
1288  }
1289
1290  E.nextpoint();
1291
1292  Fp= Fp (x+E[1], x);
1293  Fp= Fp (y+E[2], y);
1294
1295  if (tdeg == totaldegree (Fp))
1296  {
1297    if (absIrredTest (Fp))
1298    {
1299      CFFList factors= factorize (Fp);
1300      if (factors.length() == 2 && factors.getLast().exp() == 1)
1301      {
1302        if (isRat)
1303          On (SW_RATIONAL);
1304        setCharacteristic (0);
1305        return true;
1306      }
1307    }
1308  }
1309
1310  int i= 0;
1311  while (cf_getSmallPrime (i) < 102)
1312  {
1313    setCharacteristic (cf_getSmallPrime (i));
1314    i++;
1315    E= REvaluation (1, 2, FFRandom());
1316
1317    for (int j= 0; j < 3; j++)
1318    {
1319      Fp= F.mapinto();
1320      E.nextpoint();
1321      Fp= Fp (x+E[1], x);
1322      Fp= Fp (y+E[2], y);
1323
1324      if (tdeg == totaldegree (Fp))
1325      {
1326        if (absIrredTest (Fp))
1327        {
1328          CFFList factors= factorize (Fp);
1329          if (factors.length() == 2 && factors.getLast().exp() == 1)
1330          {
1331            if (isRat)
1332              On (SW_RATIONAL);
1333            setCharacteristic (0);
1334            return true;
1335          }
1336        }
1337      }
1338    }
1339  }
1340
1341  setCharacteristic (0);
1342  if (isRat)
1343    On (SW_RATIONAL);
1344
1345  return false;
1346}
1347
1348
Note: See TracBrowser for help on using the repository browser.