source: git/factory/cfNewtonPolygon.cc @ 102daa

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