source: git/factory/cfNewtonPolygon.cc @ 08a955

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