Changeset 08daea in git


Ignore:
Timestamp:
Nov 22, 2010, 11:12:46 AM (13 years ago)
Author:
Martin Lee <martinlee84@…>
Branches:
(u'spielwiese', '0d6b7fcd9813a1ca1ed4220cfa2b104b97a0a003')
Children:
fb8ba2756f35787214f1a0b5702e31e4b853de97
Parents:
cde7084dc141670809afd29cafbd9c571bd9fc3a
Message:
new ezgcd, heuristic which gcd to choose and sparse modular gcd all for finite fields


git-svn-id: file:///usr/local/Singular/svn/trunk@13661 2c84dea3-7e68-4137-9b89-c4e89433aadc
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • Singular/tesths.cc

    rcde708 r08daea  
    5555  //On(SW_USE_FF_MOD_GCD);
    5656  //On(SW_USE_fieldGCD);
    57   Off(SW_USE_EZGCD_P);
     57  On(SW_USE_EZGCD_P);
    5858  On(SW_USE_QGCD);
    5959  Off(SW_USE_NTL_SORT); // may be changed by an command line option
  • factory/cf_gcd.cc

    rcde708 r08daea  
    566566    else if (isOn( SW_USE_EZGCD_P ) && (!fc_and_gc_Univariate))
    567567    {
    568       if ( pe == 1 )
     568      /*if ( pe == 1 )
    569569        fc = fin_ezgcd( fc, gc );
    570570      else if ( pe > 0 )// no variable at position 1
     
    580580        gc = swapvar( gc, Variable(pe), Variable(1) );
    581581        fc = swapvar( fin_ezgcd( fc, gc ), Variable(1), Variable(pe) );
    582       }
     582      }*/
     583      fc= EZGCD_P (fc, gc);
    583584    }
    584585    else if (isOn(SW_USE_GCD_P))
  • factory/cf_gcd_smallp.cc

    rcde708 r08daea  
    3030#include "ftmpl_functions.h"
    3131#include "cf_random.h"
     32#include "ffreval.h"
     33#include "facHensel.h"
    3234
    3335// iinline helper functions:
     
    4648TIMING_DEFINE_PRINT(newton_interpolation);
    4749
     50static const double log2exp= 1.442695041;
     51
    4852/// compressing two polynomials F and G, M is used for compressing,
    4953/// N to reverse the compression
    5054static inline
    5155int myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
    52                 CFMap & N, bool& topLevel)
     56                CFMap & N, bool topLevel)
    5357{
    5458  int n= tmax (F.level(), G.level());
     
    205209  return 1;
    206210}
     211
    207212
    208213int
     
    13591364}
    13601365
     1366CFArray
     1367solveVandermonde (const CFArray& M, const CFArray& A)
     1368{
     1369  int r= M.size();
     1370  ASSERT (A.size() == r, "vector does not have right size");
     1371
     1372  if (r == 1)
     1373  {
     1374    CFArray result= CFArray (1);
     1375    result [0]= A [0] / M [0];
     1376    return result;
     1377  }
     1378  // check solvability
     1379  bool notDistinct= false;
     1380  for (int i= 0; i < r - 1; i++)
     1381  {
     1382    for (int j= i + 1; j < r; j++)
     1383    {
     1384      if (M [i] == M [j])
     1385      {
     1386        notDistinct= true;
     1387        break;
     1388      }
     1389    }
     1390  }
     1391  if (notDistinct)
     1392    return CFArray();
     1393
     1394  CanonicalForm master= 1;
     1395  Variable x= Variable (1);
     1396  for (int i= 0; i < r; i++)
     1397    master *= x - M [i];
     1398  CFList Pj;
     1399  CanonicalForm tmp;
     1400  for (int i= 0; i < r; i++)
     1401  {
     1402    tmp= master/(x - M [i]);
     1403    tmp /= tmp (M [i], 1);
     1404    Pj.append (tmp);
     1405  }
     1406  CFArray result= CFArray (r);
     1407
     1408  CFListIterator j= Pj;
     1409  for (int i= 1; i <= r; i++, j++)
     1410  {
     1411    tmp= 0;
     1412    for (int l= 0; l < A.size(); l++)
     1413      tmp += A[l]*j.getItem()[l];
     1414    result[i - 1]= tmp;
     1415  }
     1416  return result;
     1417}
     1418
     1419CFArray
     1420solveGeneralVandermonde (const CFArray& M, const CFArray& A)
     1421{
     1422  int r= M.size();
     1423  ASSERT (c == r, "number of columns and rows not equal");
     1424  ASSERT (A.size() == r, "vector does not have right size");
     1425  if (r == 1)
     1426  {
     1427    CFArray result= CFArray (1);
     1428    result [0]= A[0] / M [0];
     1429    return result;
     1430  }
     1431  // check solvability
     1432  bool notDistinct= false;
     1433  for (int i= 0; i < r - 1; i++)
     1434  {
     1435    for (int j= i + 1; j < r; j++)
     1436    {
     1437      if (M [i] == M [j])
     1438      {
     1439        notDistinct= true;
     1440        break;
     1441      }
     1442    }
     1443  }
     1444  if (notDistinct)
     1445    return CFArray();
     1446
     1447  CanonicalForm master= 1;
     1448  Variable x= Variable (1);
     1449  for (int i= 0; i < r; i++)
     1450    master *= x - M [i];
     1451  master *= x;
     1452  CFList Pj;
     1453  CanonicalForm tmp;
     1454  for (int i= 0; i < r; i++)
     1455  {
     1456    tmp= master/(x - M [i]);
     1457    tmp /= tmp (M [i], 1);
     1458    Pj.append (tmp);
     1459  }
     1460
     1461  CFArray result= CFArray (r);
     1462
     1463  CFListIterator j= Pj;
     1464  for (int i= 1; i <= r; i++, j++)
     1465  {
     1466    tmp= 0;
     1467
     1468    for (int l= 1; l <= A.size(); l++)
     1469      tmp += A[l - 1]*j.getItem()[l];
     1470    result[i - 1]= tmp;
     1471  }
     1472  return result;
     1473}
     1474
     1475/// M in row echolon form, rk rank of M
     1476CFArray
     1477readOffSolution (const CFMatrix& M, const long rk)
     1478{
     1479  CFArray result= CFArray (rk);
     1480  CanonicalForm tmp1, tmp2, tmp3;
     1481  for (int i= rk; i >= 1; i--)
     1482  {
     1483    tmp3= 0;
     1484    tmp1= M (i, M.columns());
     1485    for (int j= M.columns() - 1; j >= 1; j--)
     1486    {
     1487      tmp2= M (i, j);
     1488      if (j == i)
     1489        break;
     1490      else
     1491        tmp3 += tmp2*result[j - 1];
     1492    }
     1493    result[i - 1]= (tmp1 - tmp3)/tmp2;
     1494  }
     1495  return result;
     1496}
     1497
     1498CFArray
     1499readOffSolution (const CFMatrix& M, const CFArray& L, const CFArray& partialSol)
     1500{
     1501  CFArray result= CFArray (M.rows());
     1502  CanonicalForm tmp1, tmp2, tmp3;
     1503  int k;
     1504  for (int i= M.rows(); i >= 1; i--)
     1505  {
     1506    tmp3= 0;
     1507    tmp1= L[i - 1];
     1508    k= 0;
     1509    for (int j= M.columns(); j >= 1; j--, k++)
     1510    {
     1511      tmp2= M (i, j);
     1512      if (j == i)
     1513        break;
     1514      else
     1515      {
     1516        if (k > partialSol.size() - 1)
     1517          tmp3 += tmp2*result[j - 1];
     1518        else
     1519          tmp3 += tmp2*partialSol[partialSol.size() - k - 1];
     1520      }
     1521    }
     1522    result [i - 1]= (tmp1 - tmp3)/tmp2;
     1523  }
     1524  return result;
     1525}
     1526
     1527long
     1528gaussianElimFp (CFMatrix& M, CFArray& L)
     1529{
     1530  ASSERT (L.size() <= M.rows(), "dimension exceeded");
     1531  CFMatrix *N;
     1532  N= new CFMatrix (M.rows(), M.columns() + 1);
     1533
     1534  for (int i= 1; i <= M.rows(); i++)
     1535    for (int j= 1; j <= M.columns(); j++)
     1536      (*N) (i, j)= M (i, j);
     1537
     1538  int j= 1;
     1539  for (int i= 0; i < L.size(); i++, j++)
     1540    (*N) (j, M.columns() + 1)= L[i];
     1541  int p= getCharacteristic ();
     1542  zz_p::init (p);
     1543  mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N);
     1544  long rk= gauss (*NTLN);
     1545
     1546  N= convertNTLmat_zz_p2FacCFMatrix (*NTLN);
     1547
     1548  L= CFArray (M.rows());
     1549  for (int i= 0; i < M.rows(); i++)
     1550    L[i]= (*N) (i + 1, M.columns() + 1);
     1551  M= (*N) (1, M.rows(), 1, M.columns());
     1552  return rk;
     1553}
     1554
     1555long
     1556gaussianElimFq (CFMatrix& M, CFArray& L, const Variable& alpha)
     1557{
     1558  ASSERT (L.size() <= M.rows(), "dimension exceeded");
     1559  CFMatrix *N;
     1560  N= new CFMatrix (M.rows(), M.columns() + 1);
     1561
     1562  for (int i= 1; i <= M.rows(); i++)
     1563    for (int j= 1; j <= M.columns(); j++)
     1564      (*N) (i, j)= M (i, j);
     1565
     1566  int j= 1;
     1567  for (int i= 0; i < L.size(); i++, j++)
     1568    (*N) (j, M.columns() + 1)= L[i];
     1569  int p= getCharacteristic ();
     1570  zz_p::init (p);
     1571  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
     1572  zz_pE::init (NTLMipo);
     1573  mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N);
     1574  long rk= gauss (*NTLN);
     1575
     1576  N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha);
     1577
     1578  M= (*N) (1, M.rows(), 1, M.columns());
     1579  L= CFArray (M.rows());
     1580  for (int i= 0; i < M.rows(); i++)
     1581    L[i]= (*N) (i + 1, M.columns() + 1);
     1582  return rk;
     1583}
     1584
     1585CFArray
     1586solveSystemFp (const CFMatrix& M, const CFArray& L)
     1587{
     1588  ASSERT (L.size() <= M.rows(), "dimension exceeded");
     1589  CFMatrix *N;
     1590  N= new CFMatrix (M.rows(), M.columns() + 1);
     1591
     1592  for (int i= 1; i <= M.rows(); i++)
     1593    for (int j= 1; j <= M.columns(); j++)
     1594      (*N) (i, j)= M (i, j);
     1595
     1596  int j= 1;
     1597  for (int i= 0; i < L.size(); i++, j++)
     1598    (*N) (j, M.columns() + 1)= L[i];
     1599  int p= getCharacteristic ();
     1600  zz_p::init (p);
     1601  mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N);
     1602  long rk= gauss (*NTLN);
     1603  if (rk != M.columns())
     1604    return CFArray();
     1605
     1606  N= convertNTLmat_zz_p2FacCFMatrix (*NTLN);
     1607
     1608  CFArray A= readOffSolution (*N, rk);
     1609
     1610  return A;
     1611}
     1612
     1613CFArray
     1614solveSystemFq (const CFMatrix& M, const CFArray& L, const Variable& alpha)
     1615{
     1616  ASSERT (L.size() <= M.rows(), "dimension exceeded");
     1617  CFMatrix *N;
     1618  N= new CFMatrix (M.rows(), M.columns() + 1);
     1619
     1620  for (int i= 1; i <= M.rows(); i++)
     1621    for (int j= 1; j <= M.columns(); j++)
     1622      (*N) (i, j)= M (i, j);
     1623  int j= 1;
     1624  for (int i= 0; i < L.size(); i++, j++)
     1625    (*N) (j, M.columns() + 1)= L[i];
     1626  int p= getCharacteristic ();
     1627  zz_p::init (p);
     1628  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
     1629  zz_pE::init (NTLMipo);
     1630  mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N);
     1631  long rk= gauss (*NTLN);
     1632  if (rk != M.columns())
     1633    return CFArray();
     1634
     1635  N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha);
     1636
     1637  CFArray A= readOffSolution (*N, rk);
     1638
     1639  return A;
     1640}
     1641
     1642CFArray
     1643getMonoms (const CanonicalForm& F)
     1644{
     1645  if (F.inCoeffDomain())
     1646  {
     1647    CFArray result= CFArray (1);
     1648    result [0]= 1;
     1649    return result;
     1650  }
     1651  if (F.isUnivariate())
     1652  {
     1653    CFArray result= CFArray (size(F));
     1654    int j= 0;
     1655    for (CFIterator i= F; i.hasTerms(); i++, j++)
     1656      result[j]= power (F.mvar(), i.exp());
     1657    return result;
     1658  }
     1659  int numMon= size (F);
     1660  CFArray result= CFArray (numMon);
     1661  int j= 0;
     1662  CFArray recResult;
     1663  Variable x= F.mvar();
     1664  CanonicalForm powX;
     1665  for (CFIterator i= F; i.hasTerms(); i++)
     1666  {
     1667    powX= power (x, i.exp());
     1668    recResult= getMonoms (i.coeff());
     1669    for (int k= 0; k < recResult.size(); k++)
     1670      result[j+k]= powX*recResult[k];
     1671    j += recResult.size();
     1672  }
     1673  return result;
     1674}
     1675
     1676CFArray
     1677evaluateMonom (const CanonicalForm& F, const CFList& evalPoints)
     1678{
     1679  if (F.inCoeffDomain())
     1680  {
     1681    CFArray result= CFArray (1);
     1682    result [0]= F;
     1683    return result;
     1684  }
     1685  if (F.isUnivariate())
     1686  {
     1687    ASSERT (evalPoints.length() == 1,
     1688            "expected an eval point with only one component");
     1689    CFArray result= CFArray (size(F));
     1690    int j= 0;
     1691    CanonicalForm evalPoint= evalPoints.getLast();
     1692    for (CFIterator i= F; i.hasTerms(); i++, j++)
     1693      result[j]= power (evalPoint, i.exp());
     1694    return result;
     1695  }
     1696  int numMon= size (F);
     1697  CFArray result= CFArray (numMon);
     1698  int j= 0;
     1699  CanonicalForm evalPoint= evalPoints.getLast();
     1700  CFList buf= evalPoints;
     1701  buf.removeLast();
     1702  CFArray recResult;
     1703  CanonicalForm powEvalPoint;
     1704  for (CFIterator i= F; i.hasTerms(); i++)
     1705  {
     1706    powEvalPoint= power (evalPoint, i.exp());
     1707    recResult= evaluateMonom (i.coeff(), buf);
     1708    for (int k= 0; k < recResult.size(); k++)
     1709      result[j+k]= powEvalPoint*recResult[k];
     1710    j += recResult.size();
     1711  }
     1712  return result;
     1713}
     1714
     1715CFArray
     1716evaluate (const CFArray& A, const CFList& evalPoints)
     1717{
     1718  CFArray result= A.size();
     1719  CanonicalForm tmp;
     1720  int k;
     1721  for (int i= 0; i < A.size(); i++)
     1722  {
     1723    tmp= A[i];
     1724    k= 1;
     1725    for (CFListIterator j= evalPoints; j.hasItem(); j++, k++)
     1726      tmp= tmp (j.getItem(), k);
     1727    result[i]= tmp;
     1728  }
     1729  return result;
     1730}
     1731
     1732CFList
     1733evaluationPoints (const CanonicalForm& F, const CanonicalForm& G,
     1734                  CanonicalForm& Feval, CanonicalForm& Geval,
     1735                  const CanonicalForm& LCF, const bool& GF,
     1736                  const Variable& alpha, bool& fail, CFList& list
     1737                 )
     1738{
     1739  int k= tmax (F.level(), G.level()) - 1;
     1740  Variable x= Variable (1);
     1741  CFList result;
     1742  FFRandom genFF;
     1743  GFRandom genGF;
     1744  int p= getCharacteristic ();
     1745  int bound;
     1746  if (alpha != Variable (1))
     1747  {
     1748    bound= ipower (p, degree (getMipo(alpha)));
     1749    bound= ipower (bound, k);
     1750  }
     1751  else if (GF)
     1752  {
     1753    bound= ipower (p, getGFDegree());
     1754    bound= ipower (bound, k);
     1755  }
     1756  else
     1757    bound= ipower (p, k);
     1758
     1759  CanonicalForm random;
     1760  int j;
     1761  bool zeroOneOccured= false;
     1762  bool allEqual= false;
     1763  CanonicalForm buf;
     1764  do
     1765  {
     1766    random= 0;
     1767    // possible overflow if list.length() does not fit into a int
     1768    if (list.length() >= bound)
     1769    {
     1770      fail= true;
     1771      break;
     1772    }
     1773    for (int i= 0; i < k; i++)
     1774    {
     1775      if (GF)
     1776      {
     1777        result.append (genGF.generate());
     1778        random += result.getLast()*power (x, i);
     1779      }
     1780      else if (alpha != Variable(1))
     1781      {
     1782        AlgExtRandomF genAlgExt (alpha);
     1783        result.append (genAlgExt.generate());
     1784        random += result.getLast()*power (x, i);
     1785      }
     1786      else
     1787      {
     1788        result.append (genFF.generate());
     1789        random += result.getLast()*power (x, i);
     1790      }
     1791      if (result.getLast().isOne() || result.getLast().isZero())
     1792        zeroOneOccured= true;
     1793    }
     1794    if (find (list, random))
     1795    {
     1796      zeroOneOccured= false;
     1797      allEqual= false;
     1798      result= CFList();
     1799      continue;
     1800    }
     1801    if (zeroOneOccured)
     1802    {
     1803      list.append (random);
     1804      zeroOneOccured= false;
     1805      allEqual= false;
     1806      result= CFList();
     1807      continue;
     1808    }
     1809    // no zero at this point
     1810    if (k > 1)
     1811    {
     1812      allEqual= true;
     1813      CFIterator iter= random;
     1814      buf= iter.coeff();
     1815      iter++;
     1816      for (; iter.hasTerms(); iter++)
     1817        if (buf != iter.coeff())
     1818          allEqual= false;
     1819    }
     1820    if (allEqual)
     1821    {
     1822      list.append (random);
     1823      allEqual= false;
     1824      zeroOneOccured= false;
     1825      result= CFList();
     1826      continue;
     1827    }
     1828
     1829    Feval= F;
     1830    Geval= G;
     1831    CanonicalForm LCeval= LCF;
     1832    j= 1;
     1833    for (CFListIterator i= result; i.hasItem(); i++, j++)
     1834    {
     1835      Feval= Feval (i.getItem(), j);
     1836      Geval= Geval (i.getItem(), j);
     1837      LCeval= LCeval (i.getItem(), j);
     1838    }
     1839
     1840    if (LCeval.isZero())
     1841    {
     1842      if (!find (list, random))
     1843        list.append (random);
     1844      zeroOneOccured= false;
     1845      allEqual= false;
     1846      result= CFList();
     1847      continue;
     1848    }
     1849
     1850    if (list.length() >= bound)
     1851    {
     1852      fail= true;
     1853      break;
     1854    }
     1855  } while (find (list, random));
     1856
     1857  return result;
     1858}
     1859
     1860/// multiply two lists componentwise
     1861void mult (CFList& L1, const CFList& L2)
     1862{
     1863  ASSERT (L1.length() == L2.length(), "lists of the same size expected");
     1864
     1865  CFListIterator j= L2;
     1866  for (CFListIterator i= L1; i.hasItem(); i++, j++)
     1867    i.getItem() *= j.getItem();
     1868}
     1869
     1870void eval (const CanonicalForm& A, const CanonicalForm& B, CanonicalForm& Aeval,
     1871           CanonicalForm& Beval, const CFList& L)
     1872{
     1873  Aeval= A;
     1874  Beval= B;
     1875  int j= 1;
     1876  for (CFListIterator i= L; i.hasItem(); i++, j++)
     1877  {
     1878    Aeval= Aeval (i.getItem(), j);
     1879    Beval= Beval (i.getItem(), j);
     1880  }
     1881}
     1882
     1883CanonicalForm
     1884monicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G,
     1885                     const CanonicalForm& skeleton, const Variable& alpha,
     1886                     bool& fail, CFArray*& coeffMonoms, CFArray& Monoms
     1887                    )
     1888{
     1889  CanonicalForm A= F;
     1890  CanonicalForm B= G;
     1891  if (F.isZero() && degree(G) > 0) return G/Lc(G);
     1892  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
     1893  else if (F.isZero() && G.isZero()) return F.genOne();
     1894  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
     1895  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
     1896  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
     1897  if (F == G) return F/Lc(F);
     1898
     1899  CFMap M,N;
     1900  int best_level= myCompress (A, B, M, N, false);
     1901
     1902  if (best_level == 0)
     1903    return B.genOne();
     1904
     1905  A= M(A);
     1906  B= M(B);
     1907
     1908  Variable x= Variable (1);
     1909  ASSERT (degree (A, y) == 0, "expected degree (F, 1) == 0");
     1910  ASSERT (degree (B, y) == 0, "expected degree (G, 1) == 0");
     1911
     1912  //univariate case
     1913  if (A.isUnivariate() && B.isUnivariate())
     1914    return N (gcd (A, B));
     1915
     1916  CanonicalForm skel= M(skeleton);
     1917  CanonicalForm cA, cB;    // content of A and B
     1918  CanonicalForm ppA, ppB;    // primitive part of A and B
     1919  CanonicalForm gcdcAcB;
     1920  cA = uni_content (A);
     1921  cB = uni_content (B);
     1922  gcdcAcB= gcd (cA, cB);
     1923  ppA= A/cA;
     1924  ppB= B/cB;
     1925
     1926  CanonicalForm lcA, lcB;  // leading coefficients of A and B
     1927  CanonicalForm gcdlcAlcB;
     1928  lcA= uni_lcoeff (ppA);
     1929  lcB= uni_lcoeff (ppB);
     1930
     1931  if (fdivides (lcA, lcB))
     1932  {
     1933    if (fdivides (A, B))
     1934      return F/Lc(F);
     1935  }
     1936  if (fdivides (lcB, lcA))
     1937  {
     1938    if (fdivides (B, A))
     1939      return G/Lc(G);
     1940  }
     1941
     1942  gcdlcAlcB= gcd (lcA, lcB);
     1943  int skelSize= size (skel, skel.mvar());
     1944
     1945  int j= 0;
     1946  int biggestSize= 0;
     1947
     1948  for (CFIterator i= skel; i.hasTerms(); i++, j++)
     1949    biggestSize= tmax (biggestSize, size (i.coeff()));
     1950
     1951  CanonicalForm g, Aeval, Beval;
     1952
     1953  CFList evalPoints;
     1954  bool evalFail= false;
     1955  CFList list;
     1956  bool GF= false;
     1957  CanonicalForm LCA= LC (A);
     1958  CanonicalForm tmp;
     1959  CFArray gcds= CFArray (biggestSize);
     1960  CFList * pEvalPoints= new CFList [biggestSize];
     1961  Variable V_buf= alpha;
     1962  CFList source, dest;
     1963  CanonicalForm prim_elem, im_prim_elem;
     1964  for (int i= 0; i < biggestSize; i++)
     1965  {
     1966    if (i == 0)
     1967      evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail,
     1968                                    list);
     1969    else
     1970    {
     1971      mult (evalPoints, pEvalPoints [0]);
     1972      eval (A, B, Aeval, Beval, evalPoints);
     1973    }
     1974
     1975    if (evalFail)
     1976    {
     1977      if (V_buf != Variable (1))
     1978      {
     1979        do
     1980        {
     1981          int num_vars= tmin (getNumVars(A), getNumVars(B));
     1982          int d= totaldegree (A, Variable(2), Variable (A.level()));
     1983          d= tmin (d, totaldegree (B, Variable(2), Variable (B.level())));
     1984          Variable V_buf2= V_buf;
     1985          choose_extension (d, num_vars, V_buf2);
     1986          source= CFList();
     1987          dest= CFList();
     1988
     1989          bool prim_fail= false;
     1990          Variable V_buf3;
     1991          prim_elem= primitiveElement (V_buf, V_buf3, prim_fail);
     1992
     1993          ASSERT (!prim_fail, "failure in integer factorizer");
     1994          if (prim_fail)
     1995            ; //ERROR
     1996          else
     1997            im_prim_elem= mapPrimElem (prim_elem, V_buf, V_buf2);
     1998
     1999          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf));
     2000          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
     2001
     2002          for (CFListIterator j= list; j.hasItem(); j++)
     2003            j.getItem()= mapUp (j.getItem(), V_buf, V_buf2, prim_elem,
     2004                                im_prim_elem, source, dest);
     2005          for (int k= 0; k < i; k++)
     2006          {
     2007            for (CFListIterator j= pEvalPoints[k]; j.hasItem(); j++)
     2008              j.getItem()= mapUp (j.getItem(), V_buf, V_buf2, prim_elem,
     2009                                  im_prim_elem, source, dest);
     2010            gcds[k]= mapUp (gcds[k], V_buf, V_buf2, prim_elem, im_prim_elem,
     2011                            source, dest);
     2012          }
     2013
     2014          if (alpha != Variable (1))
     2015          {
     2016            A= mapUp (A, V_buf, V_buf2, prim_elem, im_prim_elem, source,dest);
     2017            B= mapUp (B, V_buf, V_buf2, prim_elem, im_prim_elem, source,dest);
     2018          }
     2019          evalFail= false;
     2020          evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
     2021                                        evalFail, list);
     2022        } while (evalFail);
     2023      }
     2024      else
     2025      {
     2026        CanonicalForm mipo;
     2027        int deg= 2;
     2028        do {
     2029          mipo= randomIrredpoly (deg, x);
     2030          V_buf= rootOf (mipo);
     2031          evalFail= false;
     2032          evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
     2033                                        evalFail, list);
     2034          deg++;
     2035        } while (evalFail);
     2036      }
     2037    }
     2038
     2039    g= gcd (Aeval, Beval);
     2040    g /= Lc (g);
     2041
     2042    if (degree (g) != degree (skel) || (skelSize != size (g)))
     2043    {
     2044      delete[] pEvalPoints;
     2045      fail= true;
     2046      return 0;
     2047    }
     2048    CFIterator l= skel;
     2049    for (CFIterator k= g; k.hasTerms(); k++, l++)
     2050    {
     2051      if (k.exp() != l.exp())
     2052      {
     2053        delete[] pEvalPoints;
     2054        fail= true;
     2055        return 0;
     2056      }
     2057    }
     2058    pEvalPoints[i]= evalPoints;
     2059    gcds[i]= g;
     2060
     2061    tmp= 0;
     2062    int j= 0;
     2063    for (CFListIterator k= evalPoints; k.hasItem(); k++, j++)
     2064      tmp += k.getItem()*power (x, j);
     2065    list.append (tmp);
     2066  }
     2067
     2068  if (Monoms.size() == 0)
     2069    Monoms= getMonoms (skel);
     2070  if (coeffMonoms == NULL)
     2071    coeffMonoms= new CFArray [skelSize];
     2072  j= 0;
     2073  for (CFIterator i= skel; i.hasTerms(); i++, j++)
     2074    coeffMonoms[j]= getMonoms (i.coeff());
     2075
     2076  CFArray* pL= new CFArray [skelSize];
     2077  CFArray* pM= new CFArray [skelSize];
     2078  for (int i= 0; i < biggestSize; i++)
     2079  {
     2080    CFIterator l= gcds [i];
     2081    evalPoints= pEvalPoints [i];
     2082    for (int k= 0; k < skelSize; k++, l++)
     2083    {
     2084      if (i == 0)
     2085        pL[k]= CFArray (biggestSize);
     2086      pL[k] [i]= l.coeff();
     2087
     2088      if (i == 0)
     2089        pM[k]= evaluate (coeffMonoms [k], evalPoints);
     2090    }
     2091  }
     2092
     2093  CFArray solution;
     2094  CanonicalForm result= 0;
     2095  int ind= 0;
     2096  CFArray bufArray;
     2097  CFMatrix Mat;
     2098  for (int k= 0; k < skelSize; k++)
     2099  {
     2100    if (biggestSize != coeffMonoms[k].size())
     2101    {
     2102      bufArray= CFArray (coeffMonoms[k].size());
     2103      for (int i= 0; i < coeffMonoms[k].size(); i++)
     2104        bufArray [i]= pL[k] [i];
     2105      solution= solveGeneralVandermonde (pM [k], bufArray);
     2106    }
     2107    else
     2108      solution= solveGeneralVandermonde (pM [k], pL[k]);
     2109
     2110    if (solution.size() == 0)
     2111    {
     2112      delete[] pEvalPoints;
     2113      delete[] pM;
     2114      delete[] pL;
     2115      delete[] coeffMonoms;
     2116      fail= true;
     2117      return 0;
     2118    }
     2119    for (int l= 0; l < solution.size(); l++)
     2120      result += solution[l]*Monoms [ind + l];
     2121    ind += solution.size();
     2122  }
     2123
     2124  delete[] pEvalPoints;
     2125  delete[] pM;
     2126  delete[] pL;
     2127
     2128  if (alpha != Variable (1) && V_buf != alpha)
     2129  {
     2130    CFList u, v;
     2131    result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
     2132  }
     2133
     2134  result= N(result);
     2135  if (fdivides (result, F) && fdivides (result, G))
     2136    return result;
     2137  else
     2138  {
     2139    delete[] coeffMonoms;
     2140    fail= true;
     2141    return 0;
     2142  }
     2143}
     2144
     2145CanonicalForm
     2146nonMonicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G,
     2147                        const CanonicalForm& skeleton, const Variable& alpha,
     2148                        bool& fail, CFArray*& coeffMonoms, CFArray& Monoms
     2149                       )
     2150{
     2151  CanonicalForm A= F;
     2152  CanonicalForm B= G;
     2153  if (F.isZero() && degree(G) > 0) return G/Lc(G);
     2154  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
     2155  else if (F.isZero() && G.isZero()) return F.genOne();
     2156  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
     2157  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
     2158  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
     2159  if (F == G) return F/Lc(F);
     2160
     2161  CFMap M,N;
     2162  int best_level= myCompress (A, B, M, N, false);
     2163
     2164  if (best_level == 0)
     2165    return B.genOne();
     2166
     2167  A= M(A);
     2168  B= M(B);
     2169
     2170  Variable x= Variable (1);
     2171  ASSERT (degree (A, y) == 0, "expected degree (F, 1) == 0");
     2172  ASSERT (degree (B, y) == 0, "expected degree (G, 1) == 0");
     2173
     2174  //univariate case
     2175  if (A.isUnivariate() && B.isUnivariate())
     2176    return N (gcd (A, B));
     2177
     2178  CanonicalForm skel= M(skeleton);
     2179
     2180  CanonicalForm cA, cB;    // content of A and B
     2181  CanonicalForm ppA, ppB;    // primitive part of A and B
     2182  CanonicalForm gcdcAcB;
     2183  cA = uni_content (A);
     2184  cB = uni_content (B);
     2185  gcdcAcB= gcd (cA, cB);
     2186  ppA= A/cA;
     2187  ppB= B/cB;
     2188
     2189  CanonicalForm lcA, lcB;  // leading coefficients of A and B
     2190  CanonicalForm gcdlcAlcB;
     2191  lcA= uni_lcoeff (ppA);
     2192  lcB= uni_lcoeff (ppB);
     2193
     2194  if (fdivides (lcA, lcB))
     2195  {
     2196    if (fdivides (A, B))
     2197      return F/Lc(F);
     2198  }
     2199  if (fdivides (lcB, lcA))
     2200  {
     2201    if (fdivides (B, A))
     2202      return G/Lc(G);
     2203  }
     2204
     2205  gcdlcAlcB= gcd (lcA, lcB);
     2206  int skelSize= size (skel, skel.mvar());
     2207
     2208  int j= 0;
     2209  int biggestSize= 0;
     2210  int bufSize;
     2211  int numberUni= 0;
     2212  for (CFIterator i= skel; i.hasTerms(); i++, j++)
     2213  {
     2214    bufSize= size (i.coeff());
     2215    biggestSize= tmax (biggestSize, bufSize);
     2216    numberUni += bufSize;
     2217  }
     2218  numberUni--;
     2219  numberUni= (int) ceil ( (double) numberUni / (skelSize - 1));
     2220  biggestSize= tmax (biggestSize , numberUni);
     2221
     2222  numberUni= biggestSize + size (LC(skel)) - 1;
     2223  int biggestSize2= tmax (numberUni, biggestSize);
     2224
     2225  CanonicalForm g, Aeval, Beval;
     2226
     2227  CFList evalPoints;
     2228  CFArray coeffEval;
     2229  bool evalFail= false;
     2230  CFList list;
     2231  bool GF= false;
     2232  CanonicalForm LCA= LC (A);
     2233  CanonicalForm tmp;
     2234  CFArray gcds= CFArray (biggestSize);
     2235  CFList * pEvalPoints= new CFList [biggestSize];
     2236  Variable V_buf= alpha;
     2237  CFList source, dest;
     2238  CanonicalForm prim_elem, im_prim_elem;
     2239  for (int i= 0; i < biggestSize; i++)
     2240  {
     2241    if (i == 0)
     2242    {
     2243      if (getCharacteristic() > 3)
     2244        evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
     2245                                    evalFail, list);
     2246      else
     2247        evalFail= true;
     2248
     2249      if (evalFail)
     2250      {
     2251        if (V_buf != Variable (1))
     2252        {
     2253          do
     2254          {
     2255            int num_vars= tmin (getNumVars(A), getNumVars(B));
     2256            int d= totaldegree (A, Variable(2), Variable (A.level()));
     2257            d= tmin (d, totaldegree (B, Variable(2), Variable (B.level())));
     2258            Variable V_buf2= V_buf;
     2259            choose_extension (d, num_vars, V_buf2);
     2260            source= CFList();
     2261            dest= CFList();
     2262
     2263            bool prim_fail= false;
     2264            Variable V_buf3;
     2265            prim_elem= primitiveElement (V_buf, V_buf3, prim_fail);
     2266
     2267            ASSERT (!prim_fail, "failure in integer factorizer");
     2268            if (prim_fail)
     2269              ; //ERROR
     2270            else
     2271              im_prim_elem= mapPrimElem (prim_elem, V_buf, V_buf2);
     2272
     2273            DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf));
     2274            DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
     2275
     2276            for (CFListIterator i= list; i.hasItem(); i++)
     2277              i.getItem()= mapUp (i.getItem(), V_buf, V_buf2, prim_elem,
     2278                                im_prim_elem, source, dest);
     2279            evalFail= false;
     2280            evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
     2281                                          evalFail, list);
     2282          } while (evalFail);
     2283        }
     2284        else
     2285        {
     2286          CanonicalForm mipo;
     2287          int deg= 2;
     2288          do {
     2289            mipo= randomIrredpoly (deg, x);
     2290            V_buf= rootOf (mipo);
     2291            evalFail= false;
     2292            evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
     2293                                          evalFail, list);
     2294            deg++;
     2295          } while (evalFail);
     2296        }
     2297      }
     2298    }
     2299    else
     2300    {
     2301      mult (evalPoints, pEvalPoints[0]);
     2302      eval (A, B, Aeval, Beval, evalPoints);
     2303    }
     2304
     2305    g= gcd (Aeval, Beval);
     2306    g /= Lc (g);
     2307
     2308    if (degree (g) != degree (skel) || (skelSize != size (g)))
     2309    {
     2310      delete[] pEvalPoints;
     2311      fail= true;
     2312      return 0;
     2313    }
     2314    CFIterator l= skel;
     2315    for (CFIterator k= g; k.hasTerms(); k++, l++)
     2316    {
     2317      if (k.exp() != l.exp())
     2318      {
     2319        delete[] pEvalPoints;
     2320        fail= true;
     2321        return 0;
     2322      }
     2323    }
     2324    pEvalPoints[i]= evalPoints;
     2325    gcds[i]= g;
     2326
     2327    tmp= 0;
     2328    int j= 0;
     2329    for (CFListIterator k= evalPoints; k.hasItem(); k++, j++)
     2330      tmp += k.getItem()*power (x, j);
     2331    list.append (tmp);
     2332  }
     2333
     2334  if (Monoms.size() == 0)
     2335    Monoms= getMonoms (skel);
     2336
     2337  if (coeffMonoms == NULL)
     2338    coeffMonoms= new CFArray [skelSize];
     2339
     2340  j= 0;
     2341  for (CFIterator i= skel; i.hasTerms(); i++, j++)
     2342    coeffMonoms[j]= getMonoms (i.coeff());
     2343
     2344  int minimalColumnsIndex;
     2345  if (skelSize > 1)
     2346    minimalColumnsIndex= 1;
     2347  else
     2348    minimalColumnsIndex= 0;
     2349  int minimalColumns;
     2350
     2351  CFArray* pM= new CFArray [skelSize];
     2352  CFMatrix Mat;
     2353  // find the Matrix with minimal number of columns
     2354  for (int i= 0; i < skelSize; i++)
     2355  {
     2356    pM[i]= CFArray (coeffMonoms[i].size());
     2357    if (i == 1)
     2358      minimalColumns= coeffMonoms[i].size();
     2359    if (i > 1)
     2360    {
     2361      if (minimalColumns > coeffMonoms[i].size())
     2362      {
     2363        minimalColumns= coeffMonoms[i].size();
     2364        minimalColumnsIndex= i;
     2365      }
     2366    }
     2367  }
     2368  CFMatrix* pMat= new CFMatrix [2];
     2369  pMat[0]= CFMatrix (biggestSize, coeffMonoms[0].size());
     2370  pMat[1]= CFMatrix (biggestSize, coeffMonoms[minimalColumnsIndex].size());
     2371  CFArray* pL= new CFArray [skelSize];
     2372  for (int i= 0; i < biggestSize; i++)
     2373  {
     2374    CFIterator l= gcds [i];
     2375    evalPoints= pEvalPoints [i];
     2376    for (int k= 0; k < skelSize; k++, l++)
     2377    {
     2378      if (i == 0)
     2379        pL[k]= CFArray (biggestSize);
     2380      pL[k] [i]= l.coeff();
     2381
     2382      if (i == 0 && k != 0 && k != minimalColumnsIndex)
     2383        pM[k]= evaluate (coeffMonoms[k], evalPoints);
     2384      else if (i == 0 && (k == 0 || k == minimalColumnsIndex))
     2385        coeffEval= evaluate (coeffMonoms[k], evalPoints);
     2386      if (i > 0 && (k == 0 || k == minimalColumnsIndex))
     2387        coeffEval= evaluate (coeffMonoms[k], evalPoints);
     2388
     2389      if (k == 0)
     2390      {
     2391        if (pMat[k].rows() >= i + 1)
     2392        {
     2393          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
     2394            pMat[k] (i + 1, ind)= coeffEval[ind - 1];
     2395        }
     2396      }
     2397      if (k == minimalColumnsIndex)
     2398      {
     2399        if (pMat[1].rows() >= i + 1)
     2400        {
     2401          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
     2402            pMat[1] (i + 1, ind)= coeffEval[ind - 1];
     2403        }
     2404      }
     2405    }
     2406  }
     2407
     2408  CFArray solution;
     2409  CanonicalForm result= 0;
     2410  int ind= 1;
     2411  int matRows, matColumns;
     2412  matRows= pMat[1].rows();
     2413  matColumns= pMat[0].columns() - 1;
     2414  matColumns += pMat[1].columns();
     2415
     2416  Mat= CFMatrix (matRows, matColumns);
     2417  for (int i= 1; i <= matRows; i++)
     2418    for (int j= 1; j <= pMat[1].columns(); j++)
     2419      Mat (i, j)= pMat[1] (i, j);
     2420
     2421  for (int j= pMat[1].columns() + 1; j <= matColumns;
     2422       j++, ind++)
     2423  {
     2424    for (int i= 1; i <= matRows; i++)
     2425      Mat (i, j)= (-pMat [0] (i, ind + 1))*pL[minimalColumnsIndex] [i - 1];
     2426  }
     2427
     2428  CFArray firstColumn= CFArray (pMat[0].rows());
     2429  for (int i= 0; i < pMat[0].rows(); i++)
     2430    firstColumn [i]= pMat[0] (i + 1, 1);
     2431
     2432  CFArray bufArray= pL[minimalColumnsIndex];
     2433
     2434  for (int i= 0; i < biggestSize; i++)
     2435    pL[minimalColumnsIndex] [i] *= firstColumn[i];
     2436
     2437  CFMatrix bufMat= pMat[1];
     2438  pMat[1]= Mat;
     2439
     2440  if (V_buf != x)
     2441    solution= solveSystemFq (pMat[1],
     2442                             pL[minimalColumnsIndex], V_buf);
     2443  else
     2444    solution= solveSystemFp (pMat[1],
     2445                             pL[minimalColumnsIndex]);
     2446
     2447  if (solution.size() == 0)
     2448  { //Javadi's method failed, try deKleine, Monagan, Wittkopf instead
     2449    CFMatrix bufMat0= pMat[0];
     2450    delete [] pMat;
     2451    pMat= new CFMatrix [skelSize];
     2452    pL[minimalColumnsIndex]= bufArray;
     2453    CFList* bufpEvalPoints;
     2454    CFArray bufGcds;
     2455    if (biggestSize != biggestSize2)
     2456    {
     2457      bufpEvalPoints= pEvalPoints;
     2458      pEvalPoints= new CFList [biggestSize2];
     2459      bufGcds= gcds;
     2460      gcds= CFArray (biggestSize2);
     2461      for (int i= 0; i < biggestSize; i++)
     2462      {
     2463        pEvalPoints[i]= bufpEvalPoints [i];
     2464        gcds[i]= bufGcds[i];
     2465      }
     2466      for (int i= 0; i < biggestSize2 - biggestSize; i++)
     2467      {
     2468        mult (evalPoints, pEvalPoints[0]);
     2469        eval (A, B, Aeval, Beval, evalPoints);
     2470        g= gcd (Aeval, Beval);
     2471        g /= Lc (g);
     2472        if (degree (g) != degree (skel) || (skelSize != size (g)))
     2473        {
     2474          delete[] pEvalPoints;
     2475          delete[] pMat;
     2476          delete[] pL;
     2477          delete[] coeffMonoms;
     2478          delete[] pM;
     2479          fail= true;
     2480          return 0;
     2481        }
     2482        CFIterator l= skel;
     2483        for (CFIterator k= g; k.hasTerms(); k++, l++)
     2484        {
     2485          if (k.exp() != l.exp())
     2486          {
     2487            delete[] pEvalPoints;
     2488            delete[] pMat;
     2489            delete[] pL;
     2490            delete[] coeffMonoms;
     2491            delete[] pM;
     2492            fail= true;
     2493            return 0;
     2494          }
     2495        }
     2496        pEvalPoints[i + biggestSize]= evalPoints;
     2497        gcds[i + biggestSize]= g;
     2498      }
     2499    }
     2500    for (int i= 0; i < biggestSize; i++)
     2501    {
     2502      CFIterator l= gcds [i];
     2503      evalPoints= pEvalPoints [i];
     2504      for (int k= 1; k < skelSize; k++, l++)
     2505      {
     2506        if (i == 0)
     2507          pMat[k]= CFMatrix (biggestSize2,coeffMonoms[k].size()+biggestSize2-1);
     2508        if (k == minimalColumnsIndex)
     2509          continue;
     2510        coeffEval= evaluate (coeffMonoms[k], evalPoints);
     2511        if (pMat[k].rows() >= i + 1)
     2512        {
     2513          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
     2514            pMat[k] (i + 1, ind)= coeffEval[ind - 1];
     2515        }
     2516      }
     2517    }
     2518    Mat= bufMat0;
     2519    pMat[0]= CFMatrix (biggestSize2, coeffMonoms[0].size() + biggestSize2 - 1);
     2520    for (int j= 1; j <= Mat.rows(); j++)
     2521      for (int k= 1; k <= Mat.columns(); k++)
     2522        pMat [0] (j,k)= Mat (j,k);
     2523    Mat= bufMat;
     2524    for (int j= 1; j <= Mat.rows(); j++)
     2525      for (int k= 1; k <= Mat.columns(); k++)
     2526        pMat [minimalColumnsIndex] (j,k)= Mat (j,k);
     2527    // write old matrix entries into new matrices
     2528    for (int i= 0; i < skelSize; i++)
     2529    {
     2530      bufArray= pL[i];
     2531      pL[i]= CFArray (biggestSize2);
     2532      for (int j= 0; j < bufArray.size(); j++)
     2533        pL[i] [j]= bufArray [j];
     2534    }
     2535    //write old vector entries into new and add new entries to old matrices
     2536    for (int i= 0; i < biggestSize2 - biggestSize; i++)
     2537    {
     2538      CFIterator l= gcds [i + biggestSize];
     2539      evalPoints= pEvalPoints [i + biggestSize];
     2540      for (int k= 0; k < skelSize; k++, l++)
     2541      {
     2542        pL[k] [i + biggestSize]= l.coeff();
     2543        coeffEval= evaluate (coeffMonoms[k], evalPoints);
     2544        if (pMat[k].rows() >= i + biggestSize + 1)
     2545        {
     2546          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
     2547            pMat[k] (i + biggestSize + 1, ind)= coeffEval[ind - 1];
     2548        }
     2549      }
     2550    }
     2551    // begin new
     2552    for (int i= 0; i < skelSize; i++)
     2553    {
     2554      if (pL[i].size() > 1)
     2555      {
     2556        for (int j= 2; j <= pMat[i].rows(); j++)
     2557          pMat[i] (j, coeffMonoms[i].size() + j - 1)=
     2558              -pL[i] [j - 1];
     2559      }
     2560    }
     2561
     2562    long rk;
     2563    matColumns= biggestSize2 - 1;
     2564    matRows= 0;
     2565    for (int i= 0; i < skelSize; i++)
     2566    {
     2567      if (V_buf == x)
     2568        rk= gaussianElimFp (pMat[i], pL[i]);
     2569      else
     2570        rk= gaussianElimFq (pMat[i], pL[i], V_buf);
     2571
     2572      if (pMat[i] (coeffMonoms[i].size(), coeffMonoms[i].size()) == 0)
     2573      {
     2574        delete[] pEvalPoints;
     2575        delete[] pMat;
     2576        delete[] pL;
     2577        delete[] coeffMonoms;
     2578        delete[] pM;
     2579        fail= true;
     2580        return 0;
     2581      }
     2582      matRows += pMat[i].rows() - coeffMonoms[i].size();
     2583    }
     2584
     2585    CFMatrix bufMat;
     2586    Mat= CFMatrix (matRows, matColumns);
     2587    ind= 0;
     2588    bufArray= CFArray (matRows);
     2589    CFArray bufArray2;
     2590    for (int i= 0; i < skelSize; i++)
     2591    {
     2592      bufMat= pMat[i] (coeffMonoms[i].size() + 1, pMat[i].rows(),
     2593                       coeffMonoms[i].size() + 1, pMat[i].columns());
     2594
     2595      for (int j= 1; j <= bufMat.rows(); j++)
     2596        for (int k= 1; k <= bufMat.columns(); k++)
     2597          Mat (j + ind, k)= bufMat(j, k);
     2598      bufArray2= coeffMonoms[i].size();
     2599      for (int j= 1; j <= pMat[i].rows(); j++)
     2600      {
     2601        if (j > coeffMonoms[i].size())
     2602          bufArray [j-coeffMonoms[i].size() + ind - 1]= pL[i] [j - 1];
     2603        else
     2604          bufArray2 [j - 1]= pL[i] [j - 1];
     2605      }
     2606      pL[i]= bufArray2;
     2607      ind += bufMat.rows();
     2608      pMat[i]= pMat[i] (1, coeffMonoms[i].size(), 1, pMat[i].columns());
     2609    }
     2610
     2611    if (V_buf != x)
     2612      solution= solveSystemFq (Mat, bufArray, V_buf);
     2613    else
     2614      solution= solveSystemFp (Mat, bufArray);
     2615
     2616    if (solution.size() == 0)
     2617    {
     2618      delete[] pEvalPoints;
     2619      delete[] pMat;
     2620      delete[] pL;
     2621      delete[] coeffMonoms;
     2622      delete[] pM;
     2623      fail= true;
     2624      return 0;
     2625    }
     2626
     2627    ind= 0;
     2628    result= 0;
     2629    CFArray bufSolution;
     2630    for (int i= 0; i < skelSize; i++)
     2631    {
     2632      bufSolution= readOffSolution (pMat[i], pL[i], solution);
     2633      for (int i= 0; i < bufSolution.size(); i++, ind++)
     2634        result += Monoms [ind]*bufSolution[i];
     2635    }
     2636    if (alpha != Variable (1) && V_buf != alpha)
     2637    {
     2638      CFList u, v;
     2639      result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
     2640    }
     2641    result= N(result);
     2642    if (fdivides (result, F) && fdivides (result, G))
     2643      return result;
     2644    else
     2645    {
     2646      fail= true;
     2647      return 0;
     2648    }
     2649  } // end of deKleine, Monagan & Wittkopf
     2650
     2651  result += Monoms[0];
     2652  int ind2= 0, ind3= 2;
     2653  ind= 0;
     2654  for (int l= 0; l < minimalColumnsIndex; l++)
     2655    ind += coeffMonoms[l].size();
     2656  for (int l= solution.size() - pMat[0].columns() + 1; l < solution.size();
     2657       l++, ind2++, ind3++)
     2658  {
     2659    result += solution[l]*Monoms [1 + ind2];
     2660    for (int i= 0; i < pMat[0].rows(); i++)
     2661      firstColumn[i] += solution[l]*pMat[0] (i + 1, ind3);
     2662  }
     2663  for (int l= 0; l < solution.size() + 1 - pMat[0].columns(); l++)
     2664    result += solution[l]*Monoms [ind + l];
     2665  ind= coeffMonoms[0].size();
     2666  for (int k= 1; k < skelSize; k++)
     2667  {
     2668    if (k == minimalColumnsIndex)
     2669    {
     2670      ind += coeffMonoms[k].size();
     2671      continue;
     2672    }
     2673    if (k != minimalColumnsIndex)
     2674    {
     2675      for (int i= 0; i < biggestSize; i++)
     2676        pL[k] [i] *= firstColumn [i];
     2677    }
     2678
     2679    if (biggestSize != coeffMonoms[k].size() && k != minimalColumnsIndex)
     2680    {
     2681      bufArray= CFArray (coeffMonoms[k].size());
     2682      for (int i= 0; i < bufArray.size(); i++)
     2683        bufArray [i]= pL[k] [i];
     2684      solution= solveGeneralVandermonde (pM[k], bufArray);
     2685    }
     2686    else
     2687      solution= solveGeneralVandermonde (pM[k], pL[k]);
     2688
     2689    if (solution.size() == 0)
     2690    {
     2691      delete[] pEvalPoints;
     2692      delete[] pMat;
     2693      delete[] pL;
     2694      delete[] coeffMonoms;
     2695      delete[] pM;
     2696      fail= true;
     2697      return 0;
     2698    }
     2699    if (k != minimalColumnsIndex)
     2700    {
     2701      for (int l= 0; l < solution.size(); l++)
     2702        result += solution[l]*Monoms [ind + l];
     2703      ind += solution.size();
     2704    }
     2705  }
     2706
     2707  delete[] pEvalPoints;
     2708  delete[] pMat;
     2709  delete[] pL;
     2710  delete[] pM;
     2711
     2712  if (alpha != Variable (1) && V_buf != alpha)
     2713  {
     2714    CFList u, v;
     2715    result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
     2716  }
     2717  result= N(result);
     2718
     2719  if (fdivides (result, F) && fdivides (result, G))
     2720    return result;
     2721  else
     2722  {
     2723    delete[] coeffMonoms;
     2724    fail= true;
     2725    return 0;
     2726  }
     2727}
     2728
     2729CanonicalForm sparseGCDFq (const CanonicalForm& F, const CanonicalForm& G,
     2730                           const Variable & alpha, CFList& l, bool& topLevel)
     2731{
     2732  CanonicalForm A= F;
     2733  CanonicalForm B= G;
     2734  if (F.isZero() && degree(G) > 0) return G/Lc(G);
     2735  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
     2736  else if (F.isZero() && G.isZero()) return F.genOne();
     2737  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
     2738  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
     2739  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
     2740  if (F == G) return F/Lc(F);
     2741
     2742  CFMap M,N;
     2743  int best_level= myCompress (A, B, M, N, topLevel);
     2744
     2745  if (best_level == 0) return B.genOne();
     2746
     2747  A= M(A);
     2748  B= M(B);
     2749
     2750  Variable x= Variable (1);
     2751
     2752  //univariate case
     2753  if (A.isUnivariate() && B.isUnivariate())
     2754    return N (gcd (A, B));
     2755
     2756  int substitute= substituteCheck (A, B);
     2757
     2758  if (substitute > 1)
     2759    subst (A, B, A, B, substitute);
     2760
     2761  CanonicalForm cA, cB;    // content of A and B
     2762  CanonicalForm ppA, ppB;    // primitive part of A and B
     2763  CanonicalForm gcdcAcB;
     2764  if (topLevel)
     2765  {
     2766    if (best_level <= 2)
     2767      gcdcAcB= extractContents (A, B, cA, cB, ppA, ppB, best_level);
     2768    else
     2769      gcdcAcB= extractContents (A, B, cA, cB, ppA, ppB, 2);
     2770  }
     2771  else
     2772  {
     2773    cA = uni_content (A);
     2774    cB = uni_content (B);
     2775    gcdcAcB= gcd (cA, cB);
     2776    ppA= A/cA;
     2777    ppB= B/cB;
     2778  }
     2779
     2780  CanonicalForm lcA, lcB;  // leading coefficients of A and B
     2781  CanonicalForm gcdlcAlcB;
     2782  lcA= uni_lcoeff (ppA);
     2783  lcB= uni_lcoeff (ppB);
     2784
     2785  if (fdivides (lcA, lcB))
     2786  {
     2787    if (fdivides (A, B))
     2788      return F/Lc(F);
     2789  }
     2790  if (fdivides (lcB, lcA))
     2791  {
     2792    if (fdivides (B, A))
     2793      return G/Lc(G);
     2794  }
     2795
     2796  gcdlcAlcB= gcd (lcA, lcB);
     2797
     2798  int d= totaldegree (ppA, Variable (2), Variable (ppA.level()));
     2799  int d0;
     2800
     2801  if (d == 0)
     2802  {
     2803    if (substitute > 1)
     2804      return N(reverseSubst (gcdcAcB, substitute));
     2805    else
     2806      return N(gcdcAcB);
     2807  }
     2808  d0= totaldegree (ppB, Variable (2), Variable (ppB.level()));
     2809
     2810  if (d0 < d)
     2811    d= d0;
     2812
     2813  if (d == 0)
     2814  {
     2815    if (substitute > 1)
     2816      return N(reverseSubst (gcdcAcB, substitute));
     2817    else
     2818      return N(gcdcAcB);
     2819  }
     2820
     2821  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton;
     2822  CanonicalForm newtonPoly= 1;
     2823  m= gcdlcAlcB;
     2824  G_m= 0;
     2825  H= 0;
     2826  bool fail= false;
     2827  topLevel= false;
     2828  bool inextension= false;
     2829  Variable V_buf= alpha;
     2830  CanonicalForm prim_elem, im_prim_elem;
     2831  CFList source, dest;
     2832  do // first do
     2833  {
     2834    random_element= randomElement (m, V_buf, l, fail);
     2835    if (random_element == 0 && !fail)
     2836    {
     2837      if (!find (l, random_element))
     2838        l.append (random_element);
     2839      continue;
     2840    }
     2841    if (fail)
     2842    {
     2843      source= CFList();
     2844      dest= CFList();
     2845      int num_vars= tmin (getNumVars(A), getNumVars(B));
     2846      num_vars--;
     2847
     2848      choose_extension (d, num_vars, V_buf);
     2849      bool prim_fail= false;
     2850      Variable V_buf2;
     2851      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
     2852
     2853      ASSERT (!prim_fail, "failure in integer factorizer");
     2854      if (prim_fail)
     2855        ; //ERROR
     2856      else
     2857        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
     2858
     2859      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
     2860      DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2));
     2861      inextension= true;
     2862      for (CFListIterator i= l; i.hasItem(); i++)
     2863        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
     2864                             im_prim_elem, source, dest);
     2865      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     2866      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     2867      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
     2868                          source, dest);
     2869      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     2870      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     2871      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
     2872                         source, dest);
     2873
     2874      fail= false;
     2875      random_element= randomElement (m, V_buf, l, fail );
     2876      DEBOUTLN (cerr, "fail= " << fail);
     2877      CFList list;
     2878      TIMING_START (gcd_recursion);
     2879      G_random_element=
     2880      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf,
     2881                        list, topLevel);
     2882      TIMING_END_AND_PRINT (gcd_recursion,
     2883                            "time for recursive call: ");
     2884      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     2885    }
     2886    else
     2887    {
     2888      CFList list;
     2889      TIMING_START (gcd_recursion);
     2890      G_random_element=
     2891      sparseGCDFq (ppA(random_element, x), ppB(random_element, x), V_buf,
     2892                        list, topLevel);
     2893      TIMING_END_AND_PRINT (gcd_recursion,
     2894                            "time for recursive call: ");
     2895      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     2896    }
     2897
     2898    d0= totaldegree (G_random_element, Variable(2),
     2899                     Variable (G_random_element.level()));
     2900    if (d0 == 0)
     2901    {
     2902      if (substitute > 1)
     2903        return N(reverseSubst (gcdcAcB, substitute));
     2904      else
     2905        return N(gcdcAcB);
     2906    }
     2907    if (d0 >  d)
     2908    {
     2909      if (!find (l, random_element))
     2910        l.append (random_element);
     2911      continue;
     2912    }
     2913
     2914    G_random_element=
     2915    (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
     2916    * G_random_element;
     2917
     2918    skeleton= G_random_element;
     2919    d0= totaldegree (G_random_element, Variable(2),
     2920                     Variable(G_random_element.level()));
     2921    if (d0 <  d)
     2922    {
     2923      m= gcdlcAlcB;
     2924      newtonPoly= 1;
     2925      G_m= 0;
     2926      d= d0;
     2927    }
     2928
     2929    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
     2930    if (uni_lcoeff (H) == gcdlcAlcB)
     2931    {
     2932      cH= uni_content (H);
     2933      ppH= H/cH;
     2934      if (inextension)
     2935      {
     2936        CFList u, v;
     2937        //maybe it's better to test if ppH is an element of F(\alpha) before
     2938        //mapping down
     2939        DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
     2940        ppH= mapDown (ppH, prim_elem, im_prim_elem, alpha, u, v);
     2941        ppH /= Lc(ppH);
     2942        DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
     2943        if (fdivides (ppH, A) && fdivides (ppH, B))
     2944        {
     2945          if (substitute > 1)
     2946          {
     2947            ppH= reverseSubst (ppH, substitute);
     2948            gcdcAcB= reverseSubst (gcdcAcB, substitute);
     2949          }
     2950          return N(gcdcAcB*ppH);
     2951        }
     2952      }
     2953      else if (fdivides (ppH, A) && fdivides (ppH, B))
     2954      {
     2955        if (substitute > 1)
     2956        {
     2957          ppH= reverseSubst (ppH, substitute);
     2958          gcdcAcB= reverseSubst (gcdcAcB, substitute);
     2959        }
     2960        return N(gcdcAcB*ppH);
     2961      }
     2962    }
     2963    G_m= H;
     2964    newtonPoly= newtonPoly*(x - random_element);
     2965    m= m*(x - random_element);
     2966    if (!find (l, random_element))
     2967      l.append (random_element);
     2968
     2969    if (getCharacteristic () > 3 && size (skeleton) < 100
     2970        || size (skeleton) < 10)
     2971    {
     2972      CFArray Monoms;
     2973      CFArray *coeffMonoms= NULL;
     2974      do //second do
     2975      {
     2976        random_element= randomElement (m, V_buf, l, fail);
     2977        if (random_element == 0 && !fail)
     2978        {
     2979          if (!find (l, random_element))
     2980            l.append (random_element);
     2981          continue;
     2982        }
     2983        if (fail)
     2984        {
     2985          source= CFList();
     2986          dest= CFList();
     2987          int num_vars= tmin (getNumVars(A), getNumVars(B));
     2988          num_vars--;
     2989
     2990          choose_extension (d, num_vars, V_buf);
     2991          bool prim_fail= false;
     2992          Variable V_buf2;
     2993          prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
     2994
     2995          ASSERT (!prim_fail, "failure in integer factorizer");
     2996          if (prim_fail)
     2997            ; //ERROR
     2998          else
     2999            im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
     3000
     3001          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
     3002          DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2));
     3003          inextension= true;
     3004          for (CFListIterator i= l; i.hasItem(); i++)
     3005            i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
     3006                                im_prim_elem, source, dest);
     3007          m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3008          G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3009          newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
     3010                              source, dest);
     3011          ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3012          ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3013
     3014          gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
     3015                            source, dest);
     3016
     3017          fail= false;
     3018          random_element= randomElement (m, V_buf, l, fail);
     3019          DEBOUTLN (cerr, "fail= " << fail);
     3020          CFList list;
     3021          TIMING_START (gcd_recursion);
     3022
     3023          //sparseInterpolation
     3024          bool sparseFail= false;
     3025          if (LC (skeleton).inCoeffDomain())
     3026            G_random_element=
     3027            monicSparseInterpol (ppA (random_element, x), ppB(random_element,x),
     3028                                skeleton,V_buf, sparseFail, coeffMonoms,Monoms);
     3029          else
     3030            G_random_element=
     3031            nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x),
     3032                                    skeleton, V_buf, sparseFail, coeffMonoms,
     3033                                    Monoms);
     3034          if (sparseFail)
     3035            break;
     3036
     3037          TIMING_END_AND_PRINT (gcd_recursion,
     3038                                "time for recursive call: ");
     3039          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3040        }
     3041        else
     3042        {
     3043          CFList list;
     3044          TIMING_START (gcd_recursion);
     3045          bool sparseFail= false;
     3046          if (LC (skeleton).inCoeffDomain())
     3047            G_random_element=
     3048            monicSparseInterpol (ppA (random_element, x),ppB(random_element, x),
     3049                                skeleton,V_buf, sparseFail,coeffMonoms, Monoms);
     3050          else
     3051            G_random_element=
     3052            nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x),
     3053                                    skeleton, V_buf, sparseFail, coeffMonoms,
     3054                                    Monoms);
     3055          if (sparseFail)
     3056            break;
     3057
     3058          TIMING_END_AND_PRINT (gcd_recursion,
     3059                                "time for recursive call: ");
     3060          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3061        }
     3062
     3063        d0= totaldegree (G_random_element, Variable(2),
     3064                        Variable (G_random_element.level()));
     3065        if (d0 == 0)
     3066        {
     3067          if (substitute > 1)
     3068            return N(reverseSubst (gcdcAcB, substitute));
     3069          else
     3070            return N(gcdcAcB);
     3071        }
     3072        if (d0 >  d)
     3073        {
     3074          if (!find (l, random_element))
     3075            l.append (random_element);
     3076          continue;
     3077        }
     3078
     3079        G_random_element=
     3080        (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
     3081        * G_random_element;
     3082
     3083        d0= totaldegree (G_random_element, Variable(2),
     3084                        Variable(G_random_element.level()));
     3085        if (d0 <  d)
     3086        {
     3087          m= gcdlcAlcB;
     3088          newtonPoly= 1;
     3089          G_m= 0;
     3090          d= d0;
     3091        }
     3092
     3093        TIMING_START (newton_interpolation);
     3094        H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
     3095        TIMING_END_AND_PRINT (newton_interpolation,
     3096                              "time for newton interpolation: ");
     3097
     3098        //termination test
     3099        if (uni_lcoeff (H) == gcdlcAlcB)
     3100        {
     3101          cH= uni_content (H);
     3102          ppH= H/cH;
     3103          if (inextension)
     3104          {
     3105            CFList u, v;
     3106            //maybe it's better to test if ppH is an element of F(\alpha) before
     3107            //mapping down
     3108            DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
     3109            ppH= mapDown (ppH, prim_elem, im_prim_elem, alpha, u, v);
     3110            ppH /= Lc(ppH);
     3111            DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
     3112            if (fdivides (ppH, A) && fdivides (ppH, B))
     3113            {
     3114              if (substitute > 1)
     3115              {
     3116                ppH= reverseSubst (ppH, substitute);
     3117                gcdcAcB= reverseSubst (gcdcAcB, substitute);
     3118              }
     3119              return N(gcdcAcB*ppH);
     3120            }
     3121          }
     3122          else if (fdivides (ppH, A) && fdivides (ppH, B))
     3123          {
     3124            if (substitute > 1)
     3125            {
     3126              ppH= reverseSubst (ppH, substitute);
     3127              gcdcAcB= reverseSubst (gcdcAcB, substitute);
     3128            }
     3129            return N(gcdcAcB*ppH);
     3130          }
     3131        }
     3132
     3133        G_m= H;
     3134        newtonPoly= newtonPoly*(x - random_element);
     3135        m= m*(x - random_element);
     3136        if (!find (l, random_element))
     3137          l.append (random_element);
     3138
     3139      } while (1);
     3140    }
     3141  } while (1);
     3142}
     3143
     3144CanonicalForm sparseGCDFp (const CanonicalForm& F, const CanonicalForm& G,
     3145                           bool& topLevel, CFList& l)
     3146{
     3147  CanonicalForm A= F;
     3148  CanonicalForm B= G;
     3149  if (F.isZero() && degree(G) > 0) return G/Lc(G);
     3150  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
     3151  else if (F.isZero() && G.isZero()) return F.genOne();
     3152  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
     3153  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
     3154  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
     3155  if (F == G) return F/Lc(F);
     3156
     3157  CFMap M,N;
     3158  int best_level= myCompress (A, B, M, N, topLevel);
     3159
     3160  if (best_level == 0) return B.genOne();
     3161
     3162  A= M(A);
     3163  B= M(B);
     3164
     3165  Variable x= Variable (1);
     3166
     3167  //univariate case
     3168  if (A.isUnivariate() && B.isUnivariate())
     3169    return N (gcd (A, B));
     3170
     3171  int substitute= substituteCheck (A, B);
     3172
     3173  if (substitute > 1)
     3174    subst (A, B, A, B, substitute);
     3175
     3176  CanonicalForm cA, cB;    // content of A and B
     3177  CanonicalForm ppA, ppB;    // primitive part of A and B
     3178  CanonicalForm gcdcAcB;
     3179  if (topLevel)
     3180  {
     3181    if (best_level <= 2)
     3182      gcdcAcB= extractContents (A, B, cA, cB, ppA, ppB, best_level);
     3183    else
     3184      gcdcAcB= extractContents (A, B, cA, cB, ppA, ppB, 2);
     3185  }
     3186  else
     3187  {
     3188    cA = uni_content (A);
     3189    cB = uni_content (B);
     3190    gcdcAcB= gcd (cA, cB);
     3191    ppA= A/cA;
     3192    ppB= B/cB;
     3193  }
     3194
     3195  CanonicalForm lcA, lcB;  // leading coefficients of A and B
     3196  CanonicalForm gcdlcAlcB;
     3197  lcA= uni_lcoeff (ppA);
     3198  lcB= uni_lcoeff (ppB);
     3199
     3200  if (fdivides (lcA, lcB))
     3201  {
     3202    if (fdivides (A, B))
     3203      return F/Lc(F);
     3204  }
     3205  if (fdivides (lcB, lcA))
     3206  {
     3207    if (fdivides (B, A))
     3208      return G/Lc(G);
     3209  }
     3210
     3211  gcdlcAlcB= gcd (lcA, lcB);
     3212
     3213  int d= totaldegree (ppA, Variable (2), Variable (ppA.level()));
     3214  int d0;
     3215
     3216  if (d == 0)
     3217  {
     3218    if (substitute > 1)
     3219      return N(reverseSubst (gcdcAcB, substitute));
     3220    else
     3221      return N(gcdcAcB);
     3222  }
     3223  d0= totaldegree (ppB, Variable (2), Variable (ppB.level()));
     3224
     3225  if (d0 < d)
     3226    d= d0;
     3227
     3228  if (d == 0)
     3229  {
     3230    if (substitute > 1)
     3231      return N(reverseSubst (gcdcAcB, substitute));
     3232    else
     3233      return N(gcdcAcB);
     3234  }
     3235
     3236  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton;
     3237  CanonicalForm newtonPoly= 1;
     3238  m= gcdlcAlcB;
     3239  G_m= 0;
     3240  H= 0;
     3241  bool fail= false;
     3242  bool topLevel2= topLevel;
     3243  int loops= 0;
     3244  topLevel= false;
     3245  bool inextension= false;
     3246  bool inextensionextension= false;
     3247  Variable V_buf, alpha;
     3248  CanonicalForm prim_elem, im_prim_elem;
     3249  CFList source, dest;
     3250  do //first do
     3251  {
     3252    if (inextension)
     3253      random_element= randomElement (m, alpha, l, fail);
     3254    else
     3255      random_element= FpRandomElement (m, l, fail);
     3256    if (random_element == 0 && !fail)
     3257    {
     3258      if (!find (l, random_element))
     3259        l.append (random_element);
     3260      continue;
     3261    }
     3262
     3263    if (!fail && !inextension)
     3264    {
     3265      CFList list;
     3266      TIMING_START (gcd_recursion);
     3267      G_random_element=
     3268      sparseGCDFp (ppA (random_element,x), ppB (random_element,x), topLevel,
     3269                   list);
     3270      TIMING_END_AND_PRINT (gcd_recursion,
     3271                            "time for recursive call: ");
     3272      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3273    }
     3274    else if (!fail && inextension)
     3275    {
     3276      CFList list;
     3277      TIMING_START (gcd_recursion);
     3278      G_random_element=
     3279      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha,
     3280                        list, topLevel);
     3281      TIMING_END_AND_PRINT (gcd_recursion,
     3282                            "time for recursive call: ");
     3283      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3284    }
     3285    else if (fail && !inextension)
     3286    {
     3287      source= CFList();
     3288      dest= CFList();
     3289      CFList list;
     3290      CanonicalForm mipo;
     3291      int deg= 2;
     3292      do
     3293      {
     3294        mipo= randomIrredpoly (deg, x);
     3295        alpha= rootOf (mipo);
     3296        inextension= true;
     3297        fail= false;
     3298        random_element= randomElement (m, alpha, l, fail);
     3299        deg++;
     3300      } while (fail);
     3301      list= CFList();
     3302      TIMING_START (gcd_recursion);
     3303      G_random_element=
     3304      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha,
     3305                        list, topLevel);
     3306      TIMING_END_AND_PRINT (gcd_recursion,
     3307                            "time for recursive call: ");
     3308      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3309    }
     3310    else if (fail && inextension)
     3311    {
     3312      source= CFList();
     3313      dest= CFList();
     3314      int num_vars= tmin (getNumVars(A), getNumVars(B));
     3315      num_vars--;
     3316      V_buf= alpha;
     3317      choose_extension (d, num_vars, V_buf);
     3318      bool prim_fail= false;
     3319      Variable V_buf2;
     3320      CanonicalForm prim_elem, im_prim_elem;
     3321      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
     3322
     3323      ASSERT (!prim_fail, "failure in integer factorizer");
     3324      if (prim_fail)
     3325        ; //ERROR
     3326      else
     3327        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
     3328
     3329      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
     3330      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
     3331
     3332      inextensionextension= true;
     3333      for (CFListIterator i= l; i.hasItem(); i++)
     3334        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
     3335                             im_prim_elem, source, dest);
     3336      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3337      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3338      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
     3339                          source, dest);
     3340      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3341      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3342      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
     3343                         source, dest);
     3344      fail= false;
     3345      random_element= randomElement (m, V_buf, l, fail );
     3346      DEBOUTLN (cerr, "fail= " << fail);
     3347      CFList list;
     3348      TIMING_START (gcd_recursion);
     3349      G_random_element=
     3350      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf,
     3351                        list, topLevel);
     3352      TIMING_END_AND_PRINT (gcd_recursion,
     3353                            "time for recursive call: ");
     3354      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3355      alpha= V_buf;
     3356    }
     3357
     3358    d0= totaldegree (G_random_element, Variable(2),
     3359                     Variable (G_random_element.level()));
     3360    if (d0 == 0)
     3361    {
     3362      if (substitute > 1)
     3363        return N(reverseSubst (gcdcAcB, substitute));
     3364      else
     3365        return N(gcdcAcB);
     3366    }
     3367    if (d0 >  d)
     3368    {
     3369      if (!find (l, random_element))
     3370        l.append (random_element);
     3371      continue;
     3372    }
     3373
     3374    G_random_element=
     3375    (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
     3376    * G_random_element;
     3377
     3378    skeleton= G_random_element;
     3379
     3380    d0= totaldegree (G_random_element, Variable(2),
     3381                     Variable(G_random_element.level()));
     3382    if (d0 <  d)
     3383    {
     3384      m= gcdlcAlcB;
     3385      newtonPoly= 1;
     3386      G_m= 0;
     3387      d= d0;
     3388    }
     3389
     3390    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
     3391
     3392    if (uni_lcoeff (H) == gcdlcAlcB)
     3393    {
     3394      cH= uni_content (H);
     3395      ppH= H/cH;
     3396      ppH /= Lc (ppH);
     3397      DEBOUTLN (cerr, "ppH= " << ppH);
     3398
     3399      if (fdivides (ppH, A) && fdivides (ppH, B))
     3400      {
     3401        if (substitute > 1)
     3402        {
     3403          ppH= reverseSubst (ppH, substitute);
     3404          gcdcAcB= reverseSubst (gcdcAcB, substitute);
     3405        }
     3406        return N(gcdcAcB*ppH);
     3407      }
     3408    }
     3409    G_m= H;
     3410    newtonPoly= newtonPoly*(x - random_element);
     3411    m= m*(x - random_element);
     3412    if (!find (l, random_element))
     3413      l.append (random_element);
     3414
     3415    if ((getCharacteristic() > 3 && size (skeleton) < 100) ||
     3416         size (skeleton) < 10)
     3417    {
     3418      CFArray Monoms;
     3419      CFArray* coeffMonoms= NULL;
     3420
     3421      do //second do
     3422      {
     3423        if (inextension)
     3424          random_element= randomElement (m, alpha, l, fail);
     3425        else
     3426          random_element= FpRandomElement (m, l, fail);
     3427        if (random_element == 0 && !fail)
     3428        {
     3429          if (!find (l, random_element))
     3430            l.append (random_element);
     3431          continue;
     3432        }
     3433
     3434        bool sparseFail= false;
     3435        if (!fail && !inextension)
     3436        {
     3437          CFList list;
     3438          TIMING_START (gcd_recursion);
     3439          if (LC (skeleton).inCoeffDomain())
     3440            G_random_element=
     3441            monicSparseInterpol(ppA(random_element, x), ppB (random_element, x),
     3442                                skeleton, Variable(1), sparseFail, coeffMonoms,
     3443                                Monoms);
     3444          else
     3445            G_random_element=
     3446            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
     3447                                    skeleton, Variable (1), sparseFail,
     3448                                    coeffMonoms, Monoms);
     3449          TIMING_END_AND_PRINT (gcd_recursion,
     3450                                "time for recursive call: ");
     3451          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3452        }
     3453        else if (!fail && inextension)
     3454        {
     3455          CFList list;
     3456          TIMING_START (gcd_recursion);
     3457          if (LC (skeleton).inCoeffDomain())
     3458            G_random_element=
     3459            monicSparseInterpol(ppA (random_element,x), ppB (random_element, x),
     3460                                skeleton, alpha, sparseFail, coeffMonoms,
     3461                                Monoms);
     3462          else
     3463            G_random_element=
     3464            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
     3465                                   skeleton, alpha, sparseFail, coeffMonoms,
     3466                                   Monoms);
     3467          TIMING_END_AND_PRINT (gcd_recursion,
     3468                                "time for recursive call: ");
     3469          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3470        }
     3471        else if (fail && !inextension)
     3472        {
     3473          source= CFList();
     3474          dest= CFList();
     3475          CFList list;
     3476          CanonicalForm mipo;
     3477          int deg= 2;
     3478          do
     3479          {
     3480            mipo= randomIrredpoly (deg, x);
     3481            alpha= rootOf (mipo);
     3482            inextension= true;
     3483            fail= false;
     3484            random_element= randomElement (m, alpha, l, fail);
     3485            deg++;
     3486          } while (fail);
     3487          list= CFList();
     3488          TIMING_START (gcd_recursion);
     3489          if (LC (skeleton).inCoeffDomain())
     3490            G_random_element=
     3491            monicSparseInterpol (ppA (random_element,x), ppB (random_element,x),
     3492                                skeleton, alpha, sparseFail, coeffMonoms,
     3493                                Monoms);
     3494          else
     3495            G_random_element=
     3496            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
     3497                                   skeleton, alpha, sparseFail, coeffMonoms,
     3498                                   Monoms);
     3499          TIMING_END_AND_PRINT (gcd_recursion,
     3500                                "time for recursive call: ");
     3501          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3502        }
     3503        else if (fail && inextension)
     3504        {
     3505          source= CFList();
     3506          dest= CFList();
     3507          int num_vars= tmin (getNumVars(A), getNumVars(B));
     3508          num_vars--;
     3509          V_buf= alpha;
     3510          choose_extension (d, num_vars, V_buf);
     3511          bool prim_fail= false;
     3512          Variable V_buf2;
     3513          CanonicalForm prim_elem, im_prim_elem;
     3514          prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
     3515
     3516          ASSERT (!prim_fail, "failure in integer factorizer");
     3517          if (prim_fail)
     3518            ; //ERROR
     3519          else
     3520            im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
     3521
     3522          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
     3523          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
     3524
     3525          inextensionextension= true;
     3526          for (CFListIterator i= l; i.hasItem(); i++)
     3527            i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
     3528                                im_prim_elem, source, dest);
     3529          m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3530          G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3531          newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
     3532                              source, dest);
     3533          ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3534          ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
     3535          gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
     3536                            source, dest);
     3537          fail= false;
     3538          random_element= randomElement (m, V_buf, l, fail );
     3539          DEBOUTLN (cerr, "fail= " << fail);
     3540          CFList list;
     3541          TIMING_START (gcd_recursion);
     3542          if (LC (skeleton).inCoeffDomain())
     3543            G_random_element=
     3544            monicSparseInterpol (ppA (random_element, x), ppB (random_element, x),
     3545                                skeleton, V_buf, sparseFail, coeffMonoms,
     3546                                Monoms);
     3547          else
     3548            G_random_element=
     3549            nonMonicSparseInterpol (ppA(random_element,x), ppB(random_element,x),
     3550                                    skeleton, V_buf, sparseFail,
     3551                                    coeffMonoms, Monoms);
     3552          TIMING_END_AND_PRINT (gcd_recursion,
     3553                                "time for recursive call: ");
     3554          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
     3555          alpha= V_buf;
     3556        }
     3557
     3558        if (sparseFail)
     3559          break;
     3560
     3561        d0= totaldegree (G_random_element, Variable(2),
     3562                        Variable (G_random_element.level()));
     3563        if (d0 == 0)
     3564        {
     3565          if (substitute > 1)
     3566            return N(reverseSubst (gcdcAcB, substitute));
     3567          else
     3568            return N(gcdcAcB);
     3569        }
     3570        if (d0 >  d)
     3571        {
     3572          if (!find (l, random_element))
     3573            l.append (random_element);
     3574          continue;
     3575        }
     3576
     3577        G_random_element=
     3578        (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
     3579        * G_random_element;
     3580
     3581        d0= totaldegree (G_random_element, Variable(2),
     3582                        Variable(G_random_element.level()));
     3583        if (d0 <  d)
     3584        {
     3585          m= gcdlcAlcB;
     3586          newtonPoly= 1;
     3587          G_m= 0;
     3588          d= d0;
     3589        }
     3590
     3591        TIMING_START (newton_interpolation);
     3592        H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
     3593        TIMING_END_AND_PRINT (newton_interpolation,
     3594                              "time for newton interpolation: ");
     3595
     3596        //termination test
     3597        if (uni_lcoeff (H) == gcdlcAlcB)
     3598        {
     3599          cH= uni_content (H);
     3600          ppH= H/cH;
     3601          ppH /= Lc (ppH);
     3602          DEBOUTLN (cerr, "ppH= " << ppH);
     3603          if (fdivides (ppH, A) && fdivides (ppH, B))
     3604          {
     3605            if (substitute > 1)
     3606            {
     3607              ppH= reverseSubst (ppH, substitute);
     3608              gcdcAcB= reverseSubst (gcdcAcB, substitute);
     3609            }
     3610            return N(gcdcAcB*ppH);
     3611          }
     3612        }
     3613
     3614        G_m= H;
     3615        newtonPoly= newtonPoly*(x - random_element);
     3616        m= m*(x - random_element);
     3617        if (!find (l, random_element))
     3618          l.append (random_element);
     3619
     3620      } while (1); //end of second do
     3621    }
     3622  } while (1); //end of first do
     3623}
     3624
     3625static inline
     3626int compress4EZGCD (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
     3627                    CFMap & N, int& both_non_zero)
     3628{
     3629  int n= tmax (F.level(), G.level());
     3630  int * degsf= new int [n + 1];
     3631  int * degsg= new int [n + 1];
     3632
     3633  for (int i = 0; i <= n; i++)
     3634    degsf[i]= degsg[i]= 0;
     3635
     3636  degsf= degrees (F, degsf);
     3637  degsg= degrees (G, degsg);
     3638
     3639  both_non_zero= 0;
     3640  int f_zero= 0;
     3641  int g_zero= 0;
     3642  int both_zero= 0;
     3643
     3644  for (int i= 1; i <= n; i++)
     3645  {
     3646    if (degsf[i] != 0 && degsg[i] != 0)
     3647    {
     3648      both_non_zero++;
     3649      continue;
     3650    }
     3651    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
     3652    {
     3653      f_zero++;
     3654      continue;
     3655    }
     3656    if (degsg[i] == 0 && degsf[i] && i <= F.level())
     3657    {
     3658      g_zero++;
     3659      continue;
     3660    }
     3661  }
     3662
     3663  if (both_non_zero == 0) return 0;
     3664
     3665  // map Variables which do not occur in both polynomials to higher levels
     3666  int k= 1;
     3667  int l= 1;
     3668  for (int i= 1; i <= n; i++)
     3669  {
     3670    if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level())
     3671    {
     3672      if (k + both_non_zero != i)
     3673      {
     3674        M.newpair (Variable (i), Variable (k + both_non_zero));
     3675        N.newpair (Variable (k + both_non_zero), Variable (i));
     3676      }
     3677      k++;
     3678    }
     3679    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
     3680    {
     3681      if (l + g_zero + both_non_zero != i)
     3682      {
     3683        M.newpair (Variable (i), Variable (l + g_zero + both_non_zero));
     3684        N.newpair (Variable (l + g_zero + both_non_zero), Variable (i));
     3685      }
     3686      l++;
     3687    }
     3688  }
     3689
     3690  // sort Variables x_{i} in decreasing order of
     3691  // min(deg_{x_{i}}(f),deg_{x_{i}}(g))
     3692  int m= tmin (F.level(), G.level());
     3693  int max_min_deg;
     3694  k= both_non_zero;
     3695  l= 0;
     3696  int i= 1;
     3697  while (k > 0)
     3698  {
     3699    max_min_deg= tmin (degsf[i], degsg[i]);
     3700    while (max_min_deg == 0)
     3701    {
     3702      i++;
     3703      max_min_deg= tmin (degsf[i], degsg[i]);
     3704    }
     3705    for (int j= i + 1; j <= m; j++)
     3706    {
     3707      if ((tmin (degsf[j],degsg[j]) < max_min_deg) &&
     3708          (tmin (degsf[j], degsg[j]) != 0))
     3709      {
     3710        max_min_deg= tmin (degsf[j], degsg[j]);
     3711        l= j;
     3712      }
     3713    }
     3714
     3715    if (l != 0)
     3716    {
     3717      if (l != k)
     3718      {
     3719        M.newpair (Variable (l), Variable(k));
     3720        N.newpair (Variable (k), Variable(l));
     3721        degsf[l]= 0;
     3722        degsg[l]= 0;
     3723        l= 0;
     3724      }
     3725      else
     3726      {
     3727        degsf[l]= 0;
     3728        degsg[l]= 0;
     3729        l= 0;
     3730      }
     3731    }
     3732    else if (l == 0)
     3733    {
     3734      if (i != k)
     3735      {
     3736        M.newpair (Variable (i), Variable (k));
     3737        N.newpair (Variable (k), Variable (i));
     3738        degsf[i]= 0;
     3739        degsg[i]= 0;
     3740      }
     3741      else
     3742      {
     3743        degsf[i]= 0;
     3744        degsg[i]= 0;
     3745      }
     3746      i++;
     3747    }
     3748    k--;
     3749  }
     3750
     3751  delete [] degsf;
     3752  delete [] degsg;
     3753
     3754  return both_non_zero;
     3755}
     3756
     3757static inline
     3758CanonicalForm myShift2Zero (const CanonicalForm& F, CFList& Feval,
     3759                            const CFList& evaluation)
     3760{
     3761  CanonicalForm A= F;
     3762  int k= 2;
     3763  for (CFListIterator i= evaluation; i.hasItem(); i++, k++)
     3764    A= A (Variable (k) + i.getItem(), k);
     3765
     3766  CanonicalForm buf= A;
     3767  Feval= CFList();
     3768  Feval.append (buf);
     3769  for (k= evaluation.length() + 1; k > 2; k--)
     3770  {
     3771    buf= mod (buf, Variable (k));
     3772    Feval.insert (buf);
     3773  }
     3774  return A;
     3775}
     3776
     3777static inline
     3778CanonicalForm myReverseShift (const CanonicalForm& F, const CFList& evaluation)
     3779{
     3780  int l= evaluation.length() + 1;
     3781  CanonicalForm result= F;
     3782  CFListIterator j= evaluation;
     3783  for (int i= 2; i < l + 1; i++, j++)
     3784  {
     3785    if (F.level() < i)
     3786      continue;
     3787    result= result (Variable (i) - j.getItem(), i);
     3788  }
     3789  return result;
     3790}
     3791
     3792static inline
     3793bool Hensel_P (const CanonicalForm & U, CFArray & G, const Evaluation & A,
     3794                const Variable & x, const CFArray& LCs )
     3795{
     3796  CFList factors;
     3797  factors.append (G[1]);
     3798  factors.append (G[2]);
     3799  CFList evaluation;
     3800  for (int i= A.min(); i <= A.max(); i++)
     3801    evaluation.append (A [i]);
     3802  CFList UEval;
     3803  CanonicalForm shiftedU= myShift2Zero (U, UEval, evaluation);
     3804  CFArray shiftedLCs= CFArray (2);
     3805  CFList shiftedLCsEval1, shiftedLCsEval2;
     3806  shiftedLCs[0]= myShift2Zero (LCs[1], shiftedLCsEval1, evaluation);
     3807  shiftedLCs[1]= myShift2Zero (LCs[2], shiftedLCsEval2, evaluation);
     3808  CanonicalForm LcUEval= LC (UEval.getFirst(), x);
     3809  factors.insert (1);
     3810  int liftBound= degree (UEval.getLast(), 2) + 1;
     3811  CFArray Pi;
     3812  CFMatrix M= CFMatrix (liftBound, factors.length() - 1);
     3813  CFList diophant;
     3814  CFArray lcs= CFArray (2);
     3815  lcs [0]= shiftedLCsEval1.getFirst();
     3816  lcs [1]= shiftedLCsEval2.getFirst();
     3817  henselLift122 (UEval.getFirst(), factors, liftBound, Pi, diophant, M,
     3818                 lcs, false);
     3819
     3820  bool noChange= true;
     3821  for (CFListIterator i= factors; i.hasItem(); i++)
     3822  {
     3823    if (degree (i.getItem(), 2) != 0)
     3824      noChange= false;
     3825  }
     3826  if (noChange)
     3827    return !noChange;
     3828  int * liftBounds;
     3829  if (U.level() > 2)
     3830  {
     3831    liftBounds= new int [U.level() - 1];
     3832    liftBounds[0]= liftBound;
     3833    for (int i= 1; i < U.level() - 1; i++)
     3834      liftBounds[i]= degree (shiftedU, Variable (i + 2)) + 1;
     3835    factors= henselLift2 (UEval, factors, liftBounds, U.level() - 1, false,
     3836                          shiftedLCsEval1, shiftedLCsEval2, Pi, diophant);
     3837  }
     3838  G[1]= factors.getFirst();
     3839  G[2]= factors.getLast();
     3840  G[1]= myReverseShift (G[1], evaluation);
     3841  G[2]= myReverseShift (G[2], evaluation);
     3842  return true;
     3843}
     3844
     3845static inline
     3846bool findeval_P (const CanonicalForm & F, const CanonicalForm & G,
     3847                 CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db,
     3848                 FFREvaluation & b, int delta, int degF, int degG, int maxeval,
     3849                 int & count)
     3850{
     3851  if( count == 0 && delta != 0)
     3852  {
     3853    if( count++ > maxeval )
     3854      return false;
     3855  }
     3856  if (count > 0)
     3857  {
     3858    b.nextpoint();
     3859    if (count++ > maxeval)
     3860      return false;
     3861  }
     3862  while( true )
     3863  {
     3864    Fb = b( F );
     3865    if( degree( Fb, 1 ) == degF )
     3866    {
     3867      Gb = b( G );
     3868      if( degree( Gb, 1 ) == degG )
     3869      {
     3870        Db = gcd( Fb, Gb );
     3871        if( delta > 0 )
     3872        {
     3873          if( degree( Db, 1 ) <= delta )
     3874            return true;
     3875        }
     3876        else
     3877          return true;
     3878      }
     3879    }
     3880    b.nextpoint();
     3881    if( count++ > maxeval )
     3882      return false;
     3883  }
     3884}
     3885
     3886// parameters for heuristic
     3887static int maxNumEval= 200;
     3888static int sizePerVars1= 500; //try dense gcd if size/#variables is bigger
     3889static int sizePerVars2= 290; //try psr gcd if size/#variables is less
     3890
     3891/// Extended Zassenhaus GCD for finite fields
     3892CanonicalForm EZGCD_P( const CanonicalForm & FF, const CanonicalForm & GG )
     3893{
     3894  if (FF.isZero() && degree(GG) > 0) return GG/Lc(GG);
     3895  else if (GG.isZero() && degree (FF) > 0) return FF/Lc(FF);
     3896  else if (FF.isZero() && GG.isZero()) return FF.genOne();
     3897  if (FF.inBaseDomain() || GG.inBaseDomain()) return FF.genOne();
     3898  if (FF.isUnivariate() && fdivides(FF, GG)) return FF/Lc(FF);
     3899  if (GG.isUnivariate() && fdivides(GG, FF)) return GG/Lc(GG);
     3900  if (FF == GG) return FF/Lc(FF);
     3901
     3902  CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG,
     3903                lcD;
     3904  CFArray DD( 1, 2 ), lcDD( 1, 2 );
     3905  int degF, degG, delta, count;
     3906  int maxeval;
     3907  maxeval= tmin((getCharacteristic()/
     3908                (int)(ilog2(getCharacteristic())*log2exp))*2, maxNumEval);
     3909  count= 0; // number of eval. used
     3910  FFREvaluation b, bt;
     3911  bool gcdfound = false;
     3912  Variable x = Variable(1);
     3913
     3914  F= FF;
     3915  G= GG;
     3916
     3917  CFMap M,N;
     3918  int smallestDegLev;
     3919  int best_level= compress4EZGCD (F, G, M, N, smallestDegLev);
     3920
     3921  if (best_level == 0) return G.genOne();
     3922
     3923  F= M (F);
     3924  G= M (G);
     3925
     3926  f = content( F, x ); g = content( G, x );
     3927  d = gcd( f, g );
     3928  F /= f; G /= g;
     3929
     3930  if( F.isUnivariate() && G.isUnivariate() )
     3931  {
     3932    if( F.mvar() == G.mvar() )
     3933      d *= gcd( F, G );
     3934    return N (d);
     3935  }
     3936
     3937  int maxNumVars= tmax (getNumVars (F), getNumVars (G));
     3938  Variable a,bv;
     3939  int sizeF= size (F);
     3940  int sizeG= size (G);
     3941
     3942  if (sizeF/maxNumVars > sizePerVars1 && sizeG/maxNumVars > sizePerVars1)
     3943  {
     3944    if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a))
     3945      return N (d*GCD_Fp_extension (F, G, a));
     3946    else if (CFFactory::gettype() == GaloisFieldDomain)
     3947      return N (d*GCD_GF (F, G));
     3948    else
     3949      return N (d*GCD_small_p (F, G));
     3950  }
     3951
     3952  if( gcd_test_one( F, G, false ) )
     3953  {
     3954    return N (d);
     3955  }
     3956
     3957  lcF = LC( F, x ); lcG = LC( G, x );
     3958  lcD = gcd( lcF, lcG );
     3959
     3960  delta = 0;
     3961  degF = degree( F, x ); degG = degree( G, x );
     3962  if(hasFirstAlgVar(F,a))
     3963  {
     3964    if(hasFirstAlgVar(G,bv))
     3965    {
     3966      if(bv.level() > a.level())
     3967        a = bv;
     3968    }
     3969    b = FFREvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) );
     3970  }
     3971  else // F not in extension
     3972  {
     3973    if(hasFirstAlgVar(G,a))
     3974      b = FFREvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) );
     3975    else
     3976    { // both not in extension given by algebraic variable
     3977      if (CFFactory::gettype() != GaloisFieldDomain)
     3978        b = FFREvaluation( 2, tmax(F.level(), G.level()), FFRandom() );
     3979      else
     3980        b = FFREvaluation( 2, tmax(F.level(), G.level()), GFRandom() );
     3981    }
     3982  }
     3983  CanonicalForm cand;
     3984  while( !gcdfound )
     3985  {
     3986    if( !findeval_P( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count ))
     3987    { // too many eval. used --> try another method
     3988      if (sizeF/maxNumVars < sizePerVars2 && sizeG/maxNumVars < sizePerVars2)
     3989      {
     3990        CanonicalForm dummy1, dummy2;
     3991        Variable y= Variable (tmax (F.level(), G.level()));
     3992        Variable z= Variable (smallestDegLev);
     3993        dummy1= swapvar (F, x, y);
     3994        dummy2= swapvar (G, x, y);
     3995        if (size (psr (dummy1, dummy2, y)) <= tmin (size (F), size (G)))
     3996        {
     3997          Off (SW_USE_EZGCD_P);
     3998          CanonicalForm result= swapvar (gcd (dummy1,dummy2), x, y);
     3999          On (SW_USE_EZGCD_P);
     4000          return N (d*result);
     4001        }
     4002      }
     4003      if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a))
     4004        return N (d*sparseGCDFq (F, G, a));
     4005      if (CFFactory::gettype() == GaloisFieldDomain)
     4006        return N (d*GCD_GF (F, G));
     4007      else
     4008        return N (d*sparseGCDFp (F,G));
     4009    }
     4010    delta = degree( Db );
     4011    if( delta == 0 )
     4012      return N (d);
     4013    while( true )
     4014    {
     4015      bt = b;
     4016      if( !findeval_P(F,G,Fbt,Gbt,Dbt, bt, delta, degF, degG, maxeval, count ))
     4017      { // too many eval. used --> try another method
     4018        if (sizeF/maxNumVars < sizePerVars2 && sizeG/maxNumVars < sizePerVars2)
     4019        {
     4020          CanonicalForm dummy1, dummy2;
     4021          Variable y= Variable (tmax (F.level(), G.level()));
     4022          Variable z= Variable (smallestDegLev);
     4023          dummy1= swapvar (F, x, y);
     4024          dummy2= swapvar (G, x, y);
     4025          if (size (psr (dummy1, dummy2, y)) <= tmin (size (F), size (G)))
     4026          {
     4027            Off (SW_USE_EZGCD_P);
     4028            CanonicalForm result= swapvar (gcd (dummy1,dummy2), x, y);
     4029            On (SW_USE_EZGCD_P);
     4030            return N (d*result);
     4031          }
     4032        }
     4033        if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a))
     4034          return N (d*sparseGCDFq (F, G, a));
     4035        if (CFFactory::gettype() == GaloisFieldDomain)
     4036          return N (d*GCD_GF (F, G));
     4037        else
     4038          return N (d*sparseGCDFp (F,G));
     4039      }
     4040      int dd = degree( Dbt );
     4041      if( dd == 0 )
     4042        return N (d);
     4043      if( dd == delta )
     4044        break;
     4045      if( dd < delta )
     4046      {
     4047        delta = dd;
     4048        b = bt;
     4049        Db = Dbt; Fb = Fbt; Gb = Gbt;
     4050      }
     4051    }
     4052    if( degF <= degG && delta == degF && fdivides( F, G ) )
     4053      return N (d*F);
     4054    if( degG < degF && delta == degG && fdivides( G, F ) )
     4055      return N (d*G);
     4056    if( delta != degF && delta != degG )
     4057    {
     4058      bool B_is_F;
     4059      CanonicalForm xxx1, xxx2;
     4060      CanonicalForm buf;
     4061      DD[1] = Fb / Db;
     4062      buf= Gb/Db;
     4063      xxx1 = gcd( DD[1], Db );
     4064      xxx2 = gcd( buf, Db );
     4065      if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
     4066          (size (F) <= size (G)))
     4067          || (xxx1.inCoeffDomain() && !xxx2.inCoeffDomain()))
     4068      {
     4069        B = F;
     4070        DD[2] = Db;
     4071        lcDD[1] = lcF;
     4072        lcDD[2] = lcD;
     4073        B_is_F = true;
     4074      }
     4075      else if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
     4076               (size (G) < size (F)))
     4077               || (!xxx1.inCoeffDomain() && xxx2.inCoeffDomain()))
     4078      {
     4079        DD[1] = buf;
     4080        B = G;
     4081        DD[2] = Db;
     4082        lcDD[1] = lcG;
     4083        lcDD[2] = lcD;
     4084        B_is_F = false;
     4085      }
     4086      else // special case handling
     4087      {
     4088        if (sizeF/maxNumVars < sizePerVars2 && sizeG/maxNumVars < sizePerVars2)
     4089        {
     4090          CanonicalForm dummy1, dummy2;
     4091          Variable y= Variable (tmax (F.level(), G.level()));
     4092          Variable z= Variable (smallestDegLev);
     4093          dummy1= swapvar (F, x, y);
     4094          dummy2= swapvar (G, x, y);
     4095          if (size (psr (dummy1, dummy2, y)) <= tmin (size (F), size (G)))
     4096          {
     4097            Off (SW_USE_EZGCD_P);
     4098            CanonicalForm result= swapvar (gcd (dummy1,dummy2), x, y);
     4099            On (SW_USE_EZGCD_P);
     4100            return N (d*result);
     4101          }
     4102        }
     4103        if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a))
     4104          return N (d*sparseGCDFq (F, G, a));
     4105        if (CFFactory::gettype() == GaloisFieldDomain)
     4106          return N (d*GCD_GF (F, G));
     4107        else
     4108          return N (d*sparseGCDFp (F,G));
     4109      }
     4110      DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) );
     4111      DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) );
     4112
     4113      gcdfound= Hensel_P (B*lcD, DD, b, x, lcDD);
     4114
     4115      if( gcdfound )
     4116      {
     4117        cand = DD[2] / content( DD[2], Variable(1) );
     4118        if( B_is_F )
     4119          gcdfound = fdivides( cand, G );
     4120        else
     4121          gcdfound = fdivides( cand, F );
     4122      }
     4123    }
     4124    delta= 0;
     4125  }
     4126  return N (d*cand);
     4127}
     4128
     4129
    13614130#endif
  • factory/cf_gcd_smallp.h

    rcde708 r08daea  
    6363}
    6464
     65CanonicalForm sparseGCDFp (const CanonicalForm& F, const CanonicalForm& G,
     66                           bool& topLevel, CFList& l);
     67
     68/// Zippel's sparse GCD over Fp
     69static inline
     70CanonicalForm sparseGCDFp (const CanonicalForm& A, const CanonicalForm& B)
     71{
     72  ASSERT (CFFactory::gettype() == GaloisFieldDomain,
     73          "GF as base field expected");
     74  CFList list;
     75  bool topLevel= true;
     76  return sparseGCDFp (A, B, topLevel, list);
     77}
     78
     79/// Zippel's sparse GCD over Fq
     80CanonicalForm
     81sparseGCDFq (const CanonicalForm& F, const CanonicalForm& G,
     82             const Variable& alpha, CFList& l, bool& topLevel);
     83
     84static inline
     85CanonicalForm sparseGCDFq (const CanonicalForm& A, const CanonicalForm& B,
     86                           const Variable& alpha)
     87{
     88  CFList list;
     89  bool topLevel= true;
     90  return sparseGCDFq (A, B, alpha, list, topLevel);
     91}
     92
     93/// extended Zassenhaus GCD
     94CanonicalForm
     95EZGCD_P (const CanonicalForm& A, const CanonicalForm& B);
     96
    6597CanonicalForm
    6698randomIrredpoly (int i, const Variable & x) ;
  • factory/cf_map_ext.cc

    rcde708 r08daea  
    340340      return 0;
    341341  } while (1);
    342   zz_pE::init (NTL_mipo);
    343   zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (mipo, NTL_mipo);
    344   zz_pE root= FindRoot (NTL_alpha_mipo);
     342  zz_pX alpha_mipo= convertFacCF2NTLzzpX (mipo);
     343  zz_pE::init (alpha_mipo);
     344  zz_pEX NTL_beta_mipo= to_zz_pEX (NTL_mipo);
     345  zz_pE root= FindRoot (NTL_beta_mipo);
    345346  return convertNTLzzpE2CF (root, alpha);
    346347}
  • factory/cf_random.cc

    rcde708 r08daea  
    6565CanonicalForm GFRandom::generate () const
    6666{
    67     return CanonicalForm( int2imm_gf( factoryrandom( gf_q ) ) );
     67    int i= factoryrandom( gf_q );
     68    if ( i == gf_q1 ) i++;
     69    return CanonicalForm( int2imm_gf( i ) );
    6870}
    6971
  • factory/facHensel.cc

    rcde708 r08daea  
    2626#include "facHensel.h"
    2727#include "cf_util.h"
     28#include "fac_util.h"
     29#include "cf_algorithm.h"
    2830
    2931#ifdef HAVE_NTL
     
    15531555}
    15541556
     1557void
     1558henselStep122 (const CanonicalForm& F, const CFList& factors,
     1559              CFArray& bufFactors, const CFList& diophant, CFMatrix& M,
     1560              CFArray& Pi, int j, const CFArray& LCs)
     1561{
     1562  Variable x= F.mvar();
     1563  CanonicalForm xToJ= power (x, j);
     1564
     1565  CanonicalForm E;
     1566  // compute the error
     1567  if (degree (Pi [factors.length() - 2], x) > 0)
     1568    E= F[j] - Pi [factors.length() - 2] [j];
     1569  else
     1570    E= F[j];
     1571
     1572  CFArray buf= CFArray (diophant.length());
     1573
     1574  int k= 0;
     1575  CanonicalForm remainder;
     1576  // actual lifting
     1577  for (CFListIterator i= diophant; i.hasItem(); i++, k++)
     1578  {
     1579    if (degree (bufFactors[k], x) > 0)
     1580      remainder= modNTL (E, bufFactors[k] [0]);
     1581    else
     1582      remainder= modNTL (E, bufFactors[k]);
     1583    buf[k]= mulNTL (i.getItem(), remainder);
     1584    if (degree (bufFactors[k], x) > 0)
     1585      buf[k]= modNTL (buf[k], bufFactors[k] [0]);
     1586    else
     1587      buf[k]= modNTL (buf[k], bufFactors[k]);
     1588  }
     1589
     1590  for (k= 0; k < factors.length(); k++)
     1591    bufFactors[k] += xToJ*buf[k];
     1592
     1593  // update Pi [0]
     1594  int degBuf0= degree (bufFactors[0], x);
     1595  int degBuf1= degree (bufFactors[1], x);
     1596  if (degBuf0 > 0 && degBuf1 > 0)
     1597  {
     1598    M (j + 1, 1)= mulNTL (bufFactors[0] [j], bufFactors[1] [j]);
     1599    if (j + 2 <= M.rows())
     1600      M (j + 2, 1)= mulNTL (bufFactors[0] [j + 1], bufFactors[1] [j + 1]);
     1601  }
     1602  CanonicalForm uIZeroJ;
     1603  if (degBuf0 > 0 && degBuf1 > 0)
     1604    uIZeroJ= mulNTL(bufFactors[0][0],buf[1])+mulNTL (bufFactors[1][0], buf[0]);
     1605  else if (degBuf0 > 0)
     1606    uIZeroJ= mulNTL (buf[0], bufFactors[1]);
     1607  else if (degBuf1 > 0)
     1608    uIZeroJ= mulNTL (bufFactors[0], buf [1]);
     1609  else
     1610    uIZeroJ= 0;
     1611  Pi [0] += xToJ*uIZeroJ;
     1612
     1613  CFArray tmp= CFArray (factors.length() - 1);
     1614  for (k= 0; k < factors.length() - 1; k++)
     1615    tmp[k]= 0;
     1616  CFIterator one, two;
     1617  one= bufFactors [0];
     1618  two= bufFactors [1];
     1619  if (degBuf0 > 0 && degBuf1 > 0)
     1620  {
     1621    while (one.exp() > j) one++;
     1622    while (two.exp() > j) two++;
     1623    for (k= 1; k <= (int) ceil (j/2.0); k++)
     1624    {
     1625      if (k != j - k + 1)
     1626      {
     1627        if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
     1628        {
     1629          tmp[0] += mulNTL ((bufFactors[0][k]+one.coeff()),(bufFactors[1][k] +
     1630                      two.coeff())) - M (k + 1, 1) - M (j - k + 2, 1);
     1631          one++;
     1632          two++;
     1633        }
     1634        else if (one.exp() == j - k + 1)
     1635        {
     1636          tmp[0] += mulNTL ((bufFactors[0][k]+one.coeff()), bufFactors[1] [k]) -
     1637                      M (k + 1, 1);
     1638          one++;
     1639        }
     1640        else if (two.exp() == j - k + 1)
     1641        {
     1642          tmp[0] += mulNTL (bufFactors[0][k],(bufFactors[1][k] + two.coeff())) -
     1643                    M (k + 1, 1);
     1644          two++;
     1645        }
     1646      }
     1647      else
     1648        tmp[0] += M (k + 1, 1);
     1649    }
     1650
     1651    if (j + 2 <= M.rows())
     1652    {
     1653      if (degBuf0 >= j + 1 && degBuf1 >= j + 1)
     1654        tmp [0] += mulNTL ((bufFactors [0] [j + 1]+ bufFactors [0] [0]),
     1655                           (bufFactors [1] [j + 1] + bufFactors [1] [0]))
     1656                           - M(1,1) - M (j + 2,1);
     1657      else if (degBuf0 >= j + 1)
     1658        tmp[0] += mulNTL (bufFactors [0] [j+1], bufFactors [1] [0]);
     1659      else if (degBuf1 >= j + 1)
     1660        tmp[0] += mulNTL (bufFactors [0] [0], bufFactors [1] [j + 1]);
     1661    }
     1662  }
     1663  Pi [0] += tmp[0]*xToJ*F.mvar();
     1664
     1665  /*// update Pi [l]
     1666  int degPi, degBuf;
     1667  for (int l= 1; l < factors.length() - 1; l++)
     1668  {
     1669    degPi= degree (Pi [l - 1], x);
     1670    degBuf= degree (bufFactors[l + 1], x);
     1671    if (degPi > 0 && degBuf > 0)
     1672      M (j + 1, l + 1)= mulNTL (Pi [l - 1] [j], bufFactors[l + 1] [j]);
     1673    if (j == 1)
     1674    {
     1675      if (degPi > 0 && degBuf > 0)
     1676        Pi [l] += xToJ*(mulNTL (Pi [l - 1] [0] + Pi [l - 1] [j],
     1677                  bufFactors[l + 1] [0] + buf[l + 1]) - M (j + 1, l +1) -
     1678                  M (1, l + 1));
     1679      else if (degPi > 0)
     1680        Pi [l] += xToJ*(mulNTL (Pi [l - 1] [j], bufFactors[l + 1]));
     1681      else if (degBuf > 0)
     1682        Pi [l] += xToJ*(mulNTL (Pi [l - 1], buf[l + 1]));
     1683    }
     1684    else
     1685    {
     1686      if (degPi > 0 && degBuf > 0)
     1687      {
     1688        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
     1689        uIZeroJ += mulNTL (Pi [l - 1] [0], buf [l + 1]);
     1690      }
     1691      else if (degPi > 0)
     1692        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1]);
     1693      else if (degBuf > 0)
     1694      {
     1695        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
     1696        uIZeroJ += mulNTL (Pi [l - 1], buf[l + 1]);
     1697      }
     1698      Pi[l] += xToJ*uIZeroJ;
     1699    }
     1700    one= bufFactors [l + 1];
     1701    two= Pi [l - 1];
     1702    if (two.exp() == j + 1)
     1703    {
     1704      if (degBuf > 0 && degPi > 0)
     1705      {
     1706          tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1][0]);
     1707          two++;
     1708      }
     1709      else if (degPi > 0)
     1710      {
     1711          tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1]);
     1712          two++;
     1713      }
     1714    }
     1715    if (degBuf > 0 && degPi > 0)
     1716    {
     1717      for (k= 1; k <= (int) ceil (j/2.0); k++)
     1718      {
     1719        if (k != j - k + 1)
     1720        {
     1721          if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
     1722          {
     1723            tmp[l] += mulNTL ((bufFactors[l + 1][k]+one.coeff()),(Pi[l-1] [k] +
     1724                        two.coeff())) - M (k + 1, l + 1) - M (j - k + 2, l + 1);
     1725            one++;
     1726            two++;
     1727          }
     1728          else if (one.exp() == j - k + 1)
     1729          {
     1730            tmp[l] += mulNTL ((bufFactors[l+1][k]+one.coeff()),Pi[l - 1] [k]) -
     1731                        M (k + 1, l + 1);
     1732            one++;
     1733          }
     1734          else if (two.exp() == j - k + 1)
     1735          {
     1736            tmp[l] += mulNTL (bufFactors[l+1][k],(Pi[l-1] [k] + two.coeff())) -
     1737                      M (k + 1, l + 1);
     1738            two++;
     1739          }
     1740        }
     1741        else
     1742          tmp[l] += M (k + 1, l + 1);
     1743      }
     1744    }
     1745    Pi[l] += tmp[l]*xToJ*F.mvar();
     1746  }*/
     1747  return;
     1748}
     1749
     1750void
     1751henselLift122 (const CanonicalForm& F, CFList& factors, int l, CFArray& Pi,
     1752              CFList& diophant, CFMatrix& M, const CFArray& LCs, bool sort)
     1753{
     1754  if (sort)
     1755    sortList (factors, Variable (1));
     1756  Pi= CFArray (factors.length() - 2);
     1757  CFList bufFactors2= factors;
     1758  bufFactors2.removeFirst();
     1759  diophant.removeFirst();
     1760  CFListIterator iter= diophant;
     1761  CanonicalForm s,t;
     1762  extgcd (bufFactors2.getFirst(), bufFactors2.getLast(), s, t);
     1763  diophant= CFList();
     1764  diophant.append (t);
     1765  diophant.append (s);
     1766  DEBOUTLN (cerr, "diophant= " << diophant);
     1767
     1768  CFArray bufFactors= CFArray (bufFactors2.length());
     1769  int i= 0;
     1770  for (CFListIterator k= bufFactors2; k.hasItem(); i++, k++)
     1771    bufFactors[i]= replaceLc (k.getItem(), LCs [i]);
     1772
     1773  Variable x= F.mvar();
     1774  if (degree (bufFactors[0], x) > 0 && degree (bufFactors [1], x) > 0)
     1775  {
     1776    M (1, 1)= mulNTL (bufFactors [0] [0], bufFactors[1] [0]);
     1777    Pi [0]= M (1, 1) + (mulNTL (bufFactors [0] [1], bufFactors[1] [0]) +
     1778                        mulNTL (bufFactors [0] [0], bufFactors [1] [1]))*x;
     1779  }
     1780  else if (degree (bufFactors[0], x) > 0)
     1781  {
     1782    M (1, 1)= mulNTL (bufFactors [0] [0], bufFactors[1]);
     1783    Pi [0]= M (1, 1) +
     1784            mulNTL (bufFactors [0] [1], bufFactors[1])*x;
     1785  }
     1786  else if (degree (bufFactors[1], x) > 0)
     1787  {
     1788    M (1, 1)= mulNTL (bufFactors [0], bufFactors[1] [0]);
     1789    Pi [0]= M (1, 1) +
     1790            mulNTL (bufFactors [0], bufFactors[1] [1])*x;
     1791  }
     1792  else
     1793  {
     1794    M (1, 1)= mulNTL (bufFactors [0], bufFactors[1]);
     1795    Pi [0]= M (1, 1);
     1796  }
     1797
     1798  for (i= 1; i < l; i++)
     1799    henselStep122 (F, bufFactors2, bufFactors, diophant, M, Pi, i, LCs);
     1800
     1801  factors= CFList();
     1802  for (i= 0; i < bufFactors.size(); i++)
     1803    factors.append (bufFactors[i]);
     1804  return;
     1805}
     1806
     1807/// solve \f$ E=sum_{i= 1}^{r}{\sigma_{i}prod_{j=1, j\neq i}^{r}{f_{i}}}\f$
     1808/// mod M, products contains \f$ prod_{j=1, j\neq i}^{r}{f_{i}}} \f$
     1809static inline
     1810CFList
     1811diophantine (const CFList& recResult, const CFList& factors,
     1812             const CFList& products, const CFList& M, const CanonicalForm& E)
     1813{
     1814  if (M.isEmpty())
     1815  {
     1816    CFList result;
     1817    CFListIterator j= factors;
     1818    CanonicalForm buf;
     1819    for (CFListIterator i= recResult; i.hasItem(); i++, j++)
     1820    {
     1821      ASSERT (E.isUnivariate() || E.inCoeffDomain(),
     1822              "constant or univariate poly expected");
     1823      ASSERT (i.getItem().isUnivariate() || i.getItem().inCoeffDomain(),
     1824              "constant or univariate poly expected");
     1825      ASSERT (j.getItem().isUnivariate() || j.getItem().inCoeffDomain(),
     1826              "constant or univariate poly expected");
     1827      buf= mulNTL (E, i.getItem());
     1828      result.append (modNTL (buf, j.getItem()));
     1829    }
     1830    return result;
     1831  }
     1832  Variable y= M.getLast().mvar();
     1833  CFList bufFactors= factors;
     1834  for (CFListIterator i= bufFactors; i.hasItem(); i++)
     1835    i.getItem()= mod (i.getItem(), y);
     1836  CFList bufProducts= products;
     1837  for (CFListIterator i= bufProducts; i.hasItem(); i++)
     1838    i.getItem()= mod (i.getItem(), y);
     1839  CFList buf= M;
     1840  buf.removeLast();
     1841  CanonicalForm bufE= mod (E, y);
     1842  CFList recDiophantine= diophantine (recResult, bufFactors, bufProducts, buf,
     1843                                      bufE);
     1844
     1845  CanonicalForm e= E;
     1846  CFListIterator j= products;
     1847  for (CFListIterator i= recDiophantine; i.hasItem(); i++, j++)
     1848    e -= mulMod (i.getItem(), j.getItem(), M);
     1849
     1850  CFList result= recDiophantine;
     1851  int d= degree (M.getLast());
     1852  CanonicalForm coeffE;
     1853  for (int i= 1; i < d; i++)
     1854  {
     1855    if (degree (e, y) > 0)
     1856      coeffE= e[i];
     1857    else
     1858      coeffE= 0;
     1859    if (!coeffE.isZero())
     1860    {
     1861      CFListIterator k= result;
     1862      recDiophantine= diophantine (recResult, bufFactors, bufProducts, buf,
     1863                                   coeffE);
     1864      CFListIterator l= products;
     1865      for (j= recDiophantine; j.hasItem(); j++, k++, l++)
     1866      {
     1867        k.getItem() += j.getItem()*power (y, i);
     1868        e -= mulMod (j.getItem()*power (y, i), l.getItem(), M);
     1869      }
     1870    }
     1871    if (e.isZero())
     1872      break;
     1873  }
     1874  return result;
     1875}
     1876
     1877// non monic case
     1878static inline
     1879CFList
     1880multiRecDiophantine2 (const CanonicalForm& F, const CFList& factors,
     1881                     const CFList& recResult, const CFList& M, const int d)
     1882{
     1883  Variable y= F.mvar();
     1884  CFList result;
     1885  CFListIterator i;
     1886  CanonicalForm e= 1;
     1887  CFListIterator j= factors;
     1888  CFList p;
     1889  CFArray bufFactors= CFArray (factors.length());
     1890  CanonicalForm yToD= power (y, d);
     1891  int k= 0;
     1892  for (CFListIterator i= factors; i.hasItem(); i++, k++)
     1893    bufFactors [k]= i.getItem();
     1894  CanonicalForm b;
     1895  CFList buf= M;
     1896  buf.removeLast();
     1897  buf.append (yToD);
     1898  for (k= 0; k < factors.length(); k++) //TODO compute b's faster
     1899  {
     1900    b= 1;
     1901    if (fdivides (bufFactors[k], F))
     1902      b= F/bufFactors[k];
     1903    else
     1904    {
     1905      for (int l= 0; l < factors.length(); l++)
     1906      {
     1907        if (l == k)
     1908          continue;
     1909        else
     1910        {
     1911          b= mulMod (b, bufFactors[l], buf);
     1912        }
     1913      }
     1914    }
     1915    p.append (b);
     1916  }
     1917  j= p;
     1918  for (CFListIterator i= recResult; i.hasItem(); i++, j++)
     1919    e -= mulMod (i.getItem(), j.getItem(), M);
     1920  if (e.isZero())
     1921    return recResult;
     1922  CanonicalForm coeffE;
     1923  result= recResult;
     1924  CanonicalForm g;
     1925  buf.removeLast();
     1926  for (int i= 1; i < d; i++)
     1927  {
     1928    if (degree (e, y) > 0)
     1929      coeffE= e[i];
     1930    else
     1931      coeffE= 0;
     1932    if (!coeffE.isZero())
     1933    {
     1934      CFListIterator k= result;
     1935      CFListIterator l= p;
     1936      j= recResult;
     1937      int ii= 0;
     1938      CanonicalForm dummy;
     1939      CFList recDiophantine;
     1940      CFList buf2, buf3;
     1941      buf2= factors;
     1942      buf3= p;
     1943      for (CFListIterator iii= buf2; iii.hasItem(); iii++)
     1944        iii.getItem()= mod (iii.getItem(), y);
     1945      for (CFListIterator iii= buf3; iii.hasItem(); iii++)
     1946        iii.getItem()= mod (iii.getItem(), y);
     1947      recDiophantine= diophantine (recResult, buf2, buf3, buf, coeffE);
     1948      CFListIterator iter= recDiophantine;
     1949      for (; j.hasItem(); j++, k++, l++, ii++, iter++)
     1950      {
     1951        k.getItem() += iter.getItem()*power (y, i);
     1952        e -= mulMod (iter.getItem()*power (y, i), l.getItem(), M);
     1953      }
     1954    }
     1955    if (e.isZero())
     1956      break;
     1957  }
     1958
     1959#ifdef DEBUGOUTPUT
     1960    CanonicalForm test= 0;
     1961    j= p;
     1962    for (CFListIterator i= result; i.hasItem(); i++, j++)
     1963      test += mod (i.getItem()*j.getItem(), power (y, d));
     1964    DEBOUTLN (cerr, "test= " << test);
     1965#endif
     1966  return result;
     1967}
     1968
     1969// so far only tested for two! factor Hensel lifting
     1970static inline
     1971void
     1972henselStep2 (const CanonicalForm& F, const CFList& factors, CFArray& bufFactors,
     1973            const CFList& diophant, CFMatrix& M, CFArray& Pi,
     1974            const CFList& products, int j, const CFList& MOD)
     1975{
     1976  CanonicalForm E;
     1977  CanonicalForm xToJ= power (F.mvar(), j);
     1978  Variable x= F.mvar();
     1979
     1980  // compute the error
     1981#ifdef DEBUGOUTPUT
     1982    CanonicalForm test= 1;
     1983    for (int i= 0; i < factors.length(); i++)
     1984    {
     1985      if (i == 0)
     1986        test *= mod (bufFactors [i], power (x, j));
     1987      else
     1988        test *= bufFactors[i];
     1989    }
     1990    test= mod (test, power (x, j));
     1991    test= mod (test, MOD);
     1992    CanonicalForm test2= mod (F, power (x, j - 1)) - mod (test, power (x, j-1));
     1993    DEBOUTLN (cerr, "test= " << test2);
     1994#endif
     1995
     1996  if (degree (Pi [factors.length() - 2], x) > 0)
     1997    E= F[j] - Pi [factors.length() - 2] [j];
     1998  else
     1999    E= F[j];
     2000
     2001  CFArray buf= CFArray (diophant.length());
     2002
     2003  // actual lifting
     2004  CFList diophantine2= diophantine (diophant, factors, products, MOD, E);
     2005
     2006  int k= 0;
     2007  for (CFListIterator i= diophantine2; k < factors.length(); k++, i++)
     2008  {
     2009    buf[k]= i.getItem();
     2010    bufFactors[k] += xToJ*i.getItem();
     2011  }
     2012
     2013  // update Pi [0]
     2014  int degBuf0= degree (bufFactors[0], x);
     2015  int degBuf1= degree (bufFactors[1], x);
     2016  if (degBuf0 > 0 && degBuf1 > 0)
     2017  {
     2018    M (j + 1, 1)= mulMod (bufFactors[0] [j], bufFactors[1] [j], MOD);
     2019    if (j + 2 <= M.rows())
     2020      M (j + 2, 1)= mulMod (bufFactors[0] [j + 1], bufFactors[1] [j + 1], MOD);
     2021  }
     2022  CanonicalForm uIZeroJ;
     2023
     2024    if (degBuf0 > 0 && degBuf1 > 0)
     2025      uIZeroJ= mulMod (bufFactors[0] [0], buf[1], MOD) +
     2026               mulMod (bufFactors[1] [0], buf[0], MOD);
     2027    else if (degBuf0 > 0)
     2028      uIZeroJ= mulMod (buf[0], bufFactors[1], MOD);
     2029    else if (degBuf1 > 0)
     2030      uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
     2031    else
     2032      uIZeroJ= 0;
     2033    Pi [0] += xToJ*uIZeroJ;
     2034
     2035  CFArray tmp= CFArray (factors.length() - 1);
     2036  for (k= 0; k < factors.length() - 1; k++)
     2037    tmp[k]= 0;
     2038  CFIterator one, two;
     2039  one= bufFactors [0];
     2040  two= bufFactors [1];
     2041  if (degBuf0 > 0 && degBuf1 > 0)
     2042  {
     2043    while (one.exp() > j) one++;
     2044    while (two.exp() > j) two++;
     2045    for (k= 1; k <= (int) ceil (j/2.0); k++)
     2046    {
     2047      if (k != j - k + 1)
     2048      {
     2049        if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
     2050        {
     2051          tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
     2052                    (bufFactors[1] [k] + two.coeff()), MOD) - M (k + 1, 1) -
     2053                    M (j - k + 2, 1);
     2054          one++;
     2055          two++;
     2056        }
     2057        else if (one.exp() == j - k + 1)
     2058        {
     2059          tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
     2060                    bufFactors[1] [k], MOD) - M (k + 1, 1);
     2061          one++;
     2062        }
     2063        else if (two.exp() == j - k + 1)
     2064        {
     2065          tmp[0] += mulMod (bufFactors[0] [k], (bufFactors[1] [k] +
     2066                    two.coeff()), MOD) - M (k + 1, 1);
     2067          two++;
     2068        }
     2069      }
     2070      else
     2071      {
     2072        tmp[0] += M (k + 1, 1);
     2073      }
     2074    }
     2075
     2076    if (j + 2 <= M.rows())
     2077    {
     2078      if (degBuf0 >= j + 1 && degBuf1 >= j + 1)
     2079        tmp [0] += mulMod ((bufFactors [0] [j + 1]+ bufFactors [0] [0]),
     2080                           (bufFactors [1] [j + 1] + bufFactors [1] [0]), MOD)
     2081                   - M(1,1) - M (j + 2,1);
     2082      else if (degBuf0 >= j + 1)
     2083        tmp[0] += mulMod (bufFactors [0] [j+1], bufFactors [1] [0], MOD);
     2084      else if (degBuf1 >= j + 1)
     2085        tmp[0] += mulMod (bufFactors [0] [0], bufFactors [1] [j + 1], MOD);
     2086    }
     2087  }
     2088  Pi [0] += tmp[0]*xToJ*F.mvar();
     2089
     2090  // update Pi [l]
     2091  int degPi, degBuf;
     2092  for (int l= 1; l < factors.length() - 1; l++)
     2093  {
     2094    degPi= degree (Pi [l - 1], x);
     2095    degBuf= degree (bufFactors[l + 1], x);
     2096    if (degPi > 0 && degBuf > 0)
     2097      M (j + 1, l + 1)= mulMod (Pi [l - 1] [j], bufFactors[l + 1] [j], MOD);
     2098    if (j == 1)
     2099    {
     2100      if (degPi > 0 && degBuf > 0)
     2101        Pi [l] += xToJ*(mulMod ((Pi [l - 1] [0] + Pi [l - 1] [j]),
     2102                  (bufFactors[l + 1] [0] + buf[l + 1]), MOD) - M (j + 1, l +1)-
     2103                  M (1, l + 1));
     2104      else if (degPi > 0)
     2105        Pi [l] += xToJ*(mulMod (Pi [l - 1] [j], bufFactors[l + 1], MOD));
     2106      else if (degBuf > 0)
     2107        Pi [l] += xToJ*(mulMod (Pi [l - 1], buf[l + 1], MOD));
     2108    }
     2109    else
     2110    {
     2111      if (degPi > 0 && degBuf > 0)
     2112      {
     2113        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
     2114        uIZeroJ += mulMod (Pi [l - 1] [0], buf [l + 1], MOD);
     2115      }
     2116      else if (degPi > 0)
     2117        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1], MOD);
     2118      else if (degBuf > 0)
     2119      {
     2120        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
     2121        uIZeroJ += mulMod (Pi [l - 1], buf[l + 1], MOD);
     2122      }
     2123      Pi[l] += xToJ*uIZeroJ;
     2124    }
     2125    one= bufFactors [l + 1];
     2126    two= Pi [l - 1];
     2127    if (two.exp() == j + 1)
     2128    {
     2129      if (degBuf > 0 && degPi > 0)
     2130      {
     2131          tmp[l] += mulMod (two.coeff(), bufFactors[l + 1][0], MOD);
     2132          two++;
     2133      }
     2134      else if (degPi > 0)
     2135      {
     2136          tmp[l] += mulMod (two.coeff(), bufFactors[l + 1], MOD);
     2137          two++;
     2138      }
     2139    }
     2140    if (degBuf > 0 && degPi > 0)
     2141    {
     2142      for (k= 1; k <= (int) ceil (j/2.0); k++)
     2143      {
     2144        if (k != j - k + 1)
     2145        {
     2146          if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
     2147          {
     2148            tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
     2149                      (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1) -
     2150                      M (j - k + 2, l + 1);
     2151            one++;
     2152            two++;
     2153          }
     2154          else if (one.exp() == j - k + 1)
     2155          {
     2156            tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
     2157                      Pi[l - 1] [k], MOD) - M (k + 1, l + 1);
     2158            one++;
     2159          }
     2160          else if (two.exp() == j - k + 1)
     2161          {
     2162            tmp[l] += mulMod (bufFactors[l + 1] [k],
     2163                      (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1);
     2164            two++;
     2165          }
     2166        }
     2167        else
     2168          tmp[l] += M (k + 1, l + 1);
     2169      }
     2170    }
     2171    Pi[l] += tmp[l]*xToJ*F.mvar();
     2172  }
     2173
     2174  return;
     2175}
     2176
     2177// wrt. Variable (1)
     2178CanonicalForm replaceLC (const CanonicalForm& F, const CanonicalForm& c)
     2179{
     2180  if (degree (F, 1) <= 0)
     2181   return c;
     2182  else
     2183  {
     2184    CanonicalForm result= swapvar (F, Variable (F.level() + 1), Variable (1));
     2185    result += (swapvar (c, Variable (F.level() + 1), Variable (1))
     2186              - LC (result))*power (result.mvar(), degree (result));
     2187    return swapvar (result, Variable (F.level() + 1), Variable (1));
     2188  }
     2189}
     2190
     2191// so far only for two factor Hensel lifting
     2192CFList
     2193henselLift232 (const CFList& eval, const CFList& factors, int* l, CFList&
     2194              diophant, CFArray& Pi, CFMatrix& M, const CFList& LCs1,
     2195              const CFList& LCs2)
     2196{
     2197  CFList buf= factors;
     2198  int k= 0;
     2199  int liftBoundBivar= l[k];
     2200  CFList bufbuf= factors;
     2201  Variable v= Variable (2);
     2202
     2203  CFList MOD;
     2204  MOD.append (power (Variable (2), liftBoundBivar));
     2205  CFArray bufFactors= CFArray (factors.length());
     2206  k= 0;
     2207  CFListIterator j= eval;
     2208  j++;
     2209  CFListIterator iter1= LCs1;
     2210  CFListIterator iter2= LCs2;
     2211  iter1++;
     2212  iter2++;
     2213  bufFactors[0]= replaceLC (buf.getFirst(), iter1.getItem());
     2214  bufFactors[1]= replaceLC (buf.getLast(), iter2.getItem());
     2215
     2216  CFListIterator i= buf;
     2217  i++;
     2218  Variable y= j.getItem().mvar();
     2219  if (y.level() != 3)
     2220    y= Variable (3);
     2221
     2222  Pi[0]= mod (Pi[0], power (v, liftBoundBivar));
     2223  M (1, 1)= Pi[0];
     2224  if (degree (bufFactors[0], y) > 0 && degree (bufFactors [1], y) > 0)
     2225    Pi [0] += (mulMod (bufFactors [0] [1], bufFactors[1] [0], MOD) +
     2226                        mulMod (bufFactors [0] [0], bufFactors [1] [1], MOD))*y;
     2227  else if (degree (bufFactors[0], y) > 0)
     2228    Pi [0] += mulMod (bufFactors [0] [1], bufFactors[1], MOD)*y;
     2229  else if (degree (bufFactors[1], y) > 0)
     2230    Pi [0] += mulMod (bufFactors [0], bufFactors[1] [1], MOD)*y;
     2231
     2232  CFList products;
     2233  for (int i= 0; i < bufFactors.size(); i++)
     2234  {
     2235    if (degree (bufFactors[i], y) > 0)
     2236      products.append (M (1, 1)/bufFactors[i] [0]);
     2237    else
     2238      products.append (M (1, 1)/bufFactors[i]);
     2239  }
     2240
     2241  for (int d= 1; d < l[1]; d++)
     2242    henselStep2 (j.getItem(), buf, bufFactors, diophant, M, Pi, products, d, MOD);
     2243  CFList result;
     2244  for (k= 0; k < factors.length(); k++)
     2245    result.append (bufFactors[k]);
     2246  return result;
     2247}
     2248
     2249
     2250CFList
     2251henselLift2 (const CFList& F, const CFList& factors, const CFList& MOD, CFList&
     2252            diophant, CFArray& Pi, CFMatrix& M, const int lOld, int&
     2253            lNew, const CFList& LCs1, const CFList& LCs2)
     2254{
     2255  int k= 0;
     2256  CFArray bufFactors= CFArray (factors.length());
     2257  bufFactors[0]= replaceLC (factors.getFirst(), LCs1.getLast());
     2258  bufFactors[1]= replaceLC (factors.getLast(), LCs2.getLast());
     2259  CFList buf= factors;
     2260  Variable y= F.getLast().mvar();
     2261  Variable x= F.getFirst().mvar();
     2262  CanonicalForm xToLOld= power (x, lOld);
     2263  Pi [0]= mod (Pi[0], xToLOld);
     2264  M (1, 1)= Pi [0];
     2265
     2266  if (degree (bufFactors[0], y) > 0 && degree (bufFactors [1], y) > 0)
     2267    Pi [0] += (mulMod (bufFactors [0] [1], bufFactors[1] [0], MOD) +
     2268                        mulMod (bufFactors [0] [0], bufFactors [1] [1], MOD))*y;
     2269  else if (degree (bufFactors[0], y) > 0)
     2270    Pi [0] += mulMod (bufFactors [0] [1], bufFactors[1], MOD)*y;
     2271  else if (degree (bufFactors[1], y) > 0)
     2272    Pi [0] += mulMod (bufFactors [0], bufFactors[1] [1], MOD)*y;
     2273
     2274  CFList products;
     2275  for (int i= 0; i < bufFactors.size(); i++)
     2276  {
     2277    if (degree (bufFactors[i], y) > 0)
     2278    {
     2279      ASSERT (fdivides (bufFactors[i][0], M (1, 1)), "expected exact division");
     2280      products.append (M (1, 1)/bufFactors[i] [0]);
     2281    }
     2282    else
     2283    {
     2284      ASSERT (fdivides (bufFactors[i], M (1, 1)), "expected exact division");
     2285      products.append (M (1, 1)/bufFactors[i]);
     2286    }
     2287  }
     2288
     2289  for (int d= 1; d < lNew; d++)
     2290    henselStep2 (F.getLast(),buf,bufFactors, diophant, M, Pi, products, d, MOD);
     2291
     2292  CFList result;
     2293  for (k= 0; k < factors.length(); k++)
     2294    result.append (bufFactors[k]);
     2295  return result;
     2296}
     2297
     2298// so far only for two! factor Hensel lifting
     2299CFList
     2300henselLift2 (const CFList& eval, const CFList& factors, int* l, const int
     2301             lLength, bool sort, const CFList& LCs1, const CFList& LCs2,
     2302             const CFArray& Pi, const CFList& diophant)
     2303{
     2304  CFList bufDiophant= diophant;
     2305  CFList buf= factors;
     2306  if (sort)
     2307    sortList (buf, Variable (1));
     2308  CFArray bufPi= Pi;
     2309  CFMatrix M= CFMatrix (l[1], factors.length());
     2310  CFList result= henselLift232(eval, buf, l, bufDiophant, bufPi, M, LCs1, LCs2);
     2311  if (eval.length() == 2)
     2312    return result;
     2313  CFList MOD;
     2314  for (int i= 0; i < 2; i++)
     2315    MOD.append (power (Variable (i + 2), l[i]));
     2316  CFListIterator j= eval;
     2317  j++;
     2318  CFList bufEval;
     2319  bufEval.append (j.getItem());
     2320  j++;
     2321  CFListIterator jj= LCs1;
     2322  CFListIterator jjj= LCs2;
     2323  CFList bufLCs1, bufLCs2;
     2324  jj++, jjj++;
     2325  bufLCs1.append (jj.getItem());
     2326  bufLCs2.append (jjj.getItem());
     2327  jj++, jjj++;
     2328
     2329  for (int i= 2; i <= lLength && j.hasItem(); i++, j++, jj++, jjj++)
     2330  {
     2331    bufEval.append (j.getItem());
     2332    bufLCs1.append (jj.getItem());
     2333    bufLCs2.append (jjj.getItem());
     2334    M= CFMatrix (l[i], factors.length());
     2335    result= henselLift2 (bufEval, result, MOD, bufDiophant, bufPi, M, l[i - 1],
     2336                         l[i], bufLCs1, bufLCs2);
     2337    MOD.append (power (Variable (i + 2), l[i]));
     2338    bufEval.removeFirst();
     2339    bufLCs1.removeFirst();
     2340    bufLCs2.removeFirst();
     2341  }
     2342  return result;
     2343}
     2344
    15552345#endif
    15562346/* HAVE_NTL */
  • factory/facHensel.h

    rcde708 r08daea  
    364364           );
    365365
     366/// two factor Hensel lifting from univariate to bivariate, factors need not to
     367/// be monic
     368void
     369henselLift122 (const CanonicalForm& F,///< [in] a bivariate poly
     370               CFList& factors,       ///< [in, out] a list of univariate polys
     371                                      ///< lifted factors
     372               int l,                 ///< [in] lift bound
     373               CFArray& Pi,           ///< [in, out] stores intermediate results
     374               CFList& diophant,      ///< [in, out] result of diophantine
     375               CFMatrix& M,           ///< [in, out] stores intermediate results
     376               const CFArray& LCs,    ///< [in] leading coefficients
     377               bool sort              ///< [in] if true factors are sorted by
     378                                      ///< their degree
     379              );
     380
     381/// two factor Hensel lifting from bivariate to multivariate, factors need not
     382/// to be monic
     383///
     384/// @return @a henselLift122 returns a list of lifted factors
     385CFList
     386henselLift2 (const CFList& eval,   ///< [in] a list of polynomials the last
     387                                   ///< element is a compressed multivariate
     388                                   ///< poly, last but one element equals the
     389                                   ///< last elements modulo its main variable
     390                                   ///< and so on. The first element is a
     391                                   ///< compressed bivariate poly.
     392             const CFList& factors,///< [in] bivariate factors
     393             int* l,               ///< [in] lift bounds
     394             const int lLength,    ///< [in] length of l
     395             bool sort,            ///< [in] if true factors are sorted by
     396                                   ///< their degree in Variable(1)
     397             const CFList& LCs1,   ///< [in] a list of evaluated LC of first
     398                                   ///< factor
     399             const CFList& LCs2,   ///< [in] a list of evaluated LC of second
     400                                   ///< factor
     401             const CFArray& Pi,    ///< [in] intermediate result
     402             const CFList& diophant///< [in] result of diophantine
     403            );
     404
    366405#endif
    367406/* FAC_HENSEL_H */
  • factory/ffreval.cc

    rcde708 r08daea  
    5959}
    6060
    61 /* ------------------------------------------------------------------------ */
    62 /* forward declarations: fin_ezgcd stuff*/
    63 static bool findeval_P( const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db, REvaluation & b, int delta, int degF, int degG, int bound, int & counter );
    64 static void solveF_P ( const CFArray & P, const CFArray & Q, const CFArray & S, const CFArray & T, const CanonicalForm & C, int r, CFArray & a );
    65 static CanonicalForm derivAndEval_P ( const CanonicalForm & f, int n, const Variable & x, const CanonicalForm & a );
    66 //static CanonicalForm checkCombination_P ( const CanonicalForm & W, const Evaluation & a, const IteratedFor & e, int k );
    67 static CFArray findCorrCoeffs_P ( const CFArray & P, const CFArray & Q, const CFArray & P0, const CFArray & Q0, const CFArray & S, const CFArray & T, const CanonicalForm & C, const Evaluation & I, int r, int k, int h, int * n );
    68 static bool liftStep_P ( CFArray & P, int k, int r, int t, const Evaluation & A, const CFArray & lcG, const CanonicalForm & Uk, int * n, int h );
    69 static bool Hensel_P ( const CanonicalForm & U, CFArray & G, const CFArray & lcG, const Evaluation & A, const Variable & x );
    70 static bool hasFirstAlgVar( const CanonicalForm & f, Variable & a );
    71 
    72 CanonicalForm fin_ezgcd( const CanonicalForm & FF, const CanonicalForm & GG )
    73 {
    74   CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG, lcD;
    75   CFArray DD( 1, 2 ), lcDD( 1, 2 );
    76   int degF, degG, delta, count, maxeval;
    77   maxeval = getCharacteristic(); // bound on the number of eval. to use
    78   count = 0; // number of eval. used
    79   REvaluation b, bt;
    80   bool gcdfound = false;
    81   Variable x = Variable(1);
    82   f = content( FF, x ); g = content( GG, x ); d = gcd( f, g );
    83   F = FF / f; G = GG / g;
    84   if( F.isUnivariate() && G.isUnivariate() )
    85   {
    86     if( F.mvar() == G.mvar() )
    87       d *= gcd( F, G );
    88     return d;
    89   }
    90   if( gcd_test_one( F, G, false ) )
    91     return d;
    92 
    93   lcF = LC( F, x ); lcG = LC( G, x );
    94   lcD = gcd( lcF, lcG );
    95   delta = 0;
    96   degF = degree( F, x ); degG = degree( G, x );
    97   Variable a,bv;
    98   if(hasFirstAlgVar(F,a))
    99   {
    100     if(hasFirstAlgVar(G,bv))
    101     {
    102       if(bv.level() > a.level())
    103         a = bv;
    104     }
    105     b = REvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) );
    106   }
    107   else // F not in extension
    108   {
    109     if(hasFirstAlgVar(G,a))
    110       b = REvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) );
    111     else // both not in extension
    112       b = REvaluation( 2, tmax(F.level(), G.level()), FFRandom() );
    113   }
    114   while( !gcdfound )
    115   {
    116     if( !findeval_P( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count ))
    117     { // too many eval. used --> try another method
    118       Off( SW_USE_EZGCD_P );
    119       d *= gcd( F, G );
    120       On( SW_USE_EZGCD_P );
    121       return d;
    122     }
    123     delta = degree( Db );
    124     if( delta == 0 )
    125       return d;
    126     while( true )
    127     {
    128       bt = b;
    129       if( !findeval_P( F, G, Fbt, Gbt, Dbt, bt, delta+1, degF, degG, maxeval, count ))
    130       { // too many eval. used --> try another method
    131         Off( SW_USE_EZGCD_P );
    132         d *= gcd( F, G );
    133         On( SW_USE_EZGCD_P );
    134         return d;
    135       }
    136       int dd = degree( Dbt );
    137       if( dd == 0 )
    138         return d;
    139       if( dd == delta )
    140         break;
    141       if( dd < delta )
    142       {
    143         delta = dd;
    144         b = bt;
    145         Db = Dbt; Fb = Fbt; Gb = Gbt;
    146       }
    147     }
    148     if( degF <= degG && delta == degF && fdivides( F, G ) )
    149       return d*F;
    150     if( degG < degF && delta == degG && fdivides( G, F ) )
    151       return d*G;
    152     if( delta != degF && delta != degG )
    153     {
    154       bool B_is_F;
    155       CanonicalForm xxx;
    156       DD[1] = Fb / Db;
    157       xxx = gcd( DD[1], Db );
    158       if( xxx.inCoeffDomain() )
    159       {
    160         B = F;
    161         DD[2] = Db;
    162         lcDD[1] = lcF;
    163         lcDD[2] = lcF;
    164         B *= lcF;
    165         B_is_F = true;
    166       }
    167       else
    168       {
    169         DD[1] = Gb / Db;
    170         xxx = gcd( DD[1], Db );
    171         if( xxx.inCoeffDomain() )
    172         {
    173           B = G;
    174           DD[2] = Db;
    175           lcDD[1] = lcG;
    176           lcDD[2] = lcG;
    177           B *= lcG;
    178           B_is_F = false;
    179         }
    180         else // special case handling
    181         {
    182           Off( SW_USE_EZGCD_P );
    183           d *= gcd( F, G ); // try another method
    184           On( SW_USE_EZGCD_P );
    185           return d;
    186         }
    187       }
    188       DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) );
    189       DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) );
    190 
    191       gcdfound = Hensel_P( B, DD, lcDD, b, x );
    192 
    193       if( gcdfound )
    194       {
    195         CanonicalForm cand = DD[2] / content( DD[2], Variable(1) );
    196         if( B_is_F )
    197           gcdfound = fdivides( cand, G );
    198         else
    199           gcdfound = fdivides( cand, F );
    200       }
    201     }
    202     delta++;
    203   }
    204   return d * DD[2] / content( DD[2],Variable(1) );
    205 }
    206 
    207 
    208 static bool hasFirstAlgVar( const CanonicalForm & f, Variable & a )
    209 {
    210   if( f.inBaseDomain() ) // f has NO alg. variable
    211     return false;
    212   if( f.level()<0 ) // f has only alg. vars, so take the first one
    213   {
    214     a = f.mvar();
    215     return true;
    216   }
    217   for(CFIterator i=f; i.hasTerms(); i++)
    218     if( hasFirstAlgVar( i.coeff(), a ))
    219       return true; // 'a' is already set
    220   return false;
    221 }
    222 
    223 
    224 static bool findeval_P( const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db, REvaluation & b, int delta, int degF, int degG, int maxeval, int & count )
    225 {
    226   if( delta != 0 )
    227   {
    228     b.nextpoint();
    229     if( count++ > maxeval )
    230       return false; // too many eval. used
    231   }
    232   while( true )
    233   {
    234     Fb = b( F );
    235     if( degree( Fb ) == degF )
    236     {
    237       Gb = b( G );
    238       if( degree( Gb ) == degG )
    239       {
    240         Db = gcd( Fb, Gb );
    241         if( delta > 0 )
    242         {
    243           if( degree( Db ) < delta )
    244             return true;
    245         }
    246         else
    247           return true;
    248       }
    249     }
    250     b.nextpoint();
    251     if( count++ > maxeval ) // too many eval. used
    252       return false;
    253   }
    254 }
    255 
    256 
    257 static void solveF_P ( const CFArray & P, const CFArray & Q, const CFArray & S, const CFArray & T, const CanonicalForm & C, int r, CFArray & a )
    258 {
    259   CanonicalForm bb, b = C;
    260   for ( int j = 1; j < r; j++ )
    261   {
    262     divrem( S[j] * b, Q[j], a[j], bb );
    263     a[j] = T[j] * b + a[j] * P[j];
    264     b = bb;
    265   }
    266   a[r] = b;
    267 }
    268 
    269 
    270 static CanonicalForm derivAndEval_P ( const CanonicalForm & f, int n, const Variable & x, const CanonicalForm & a )
    271 {
    272   if ( n == 0 )
    273     return f( a, x );
    274   if ( f.degree( x ) < n )
    275     return 0;
    276   CFIterator i;
    277   CanonicalForm sum = 0, fact;
    278   int min, j;
    279   Variable v = Variable( f.level() + 1 );
    280   for ( i = swapvar( f, x, v); i.hasTerms() && i.exp() >= n; i++ )
    281   {
    282     fact = 1;
    283     min = i.exp() - n;
    284     for ( j = i.exp(); j > min; j-- )
    285       fact *= j;
    286     sum += fact * i.coeff() * power( v, min );
    287   }
    288   return sum( a, v );
    289 }
    290 
    291 
    292 static CFArray findCorrCoeffs_P ( const CFArray & P, const CFArray & Q, const CFArray & P0, const CFArray & Q0, const CFArray & S, const CFArray & T, const CanonicalForm & C, const Evaluation & I, int r, int k, int h, int * n )
    293 {
    294   bool what;
    295   int i, j, m;
    296   CFArray A(1,r), a(1,r);
    297   CanonicalForm C0, Dm, g, prodcomb;
    298   C0 = I( C, 2, k-1 );
    299   solveF_P( P0, Q0, S, T, 1, r, a );
    300   for ( i = 1; i <= r; i++ )
    301     A[i] = (a[i] * C0) % P0[i];
    302   for ( m = 0; m <= h && ( m == 0 || Dm != 0 ); m++ )
    303   {
    304     Dm = -C;
    305     prodcomb = 1;
    306     for ( i = 1; i <= r; i++ )
    307     {
    308       Dm += prodcomb * A[i] * Q[i];
    309       prodcomb *= P[i];
    310     }
    311     if ( Dm != 0 )
    312     {
    313       if ( k == 2 )
    314       {
    315         solveF_P( P0, Q0, S, T, Dm, r, a );
    316         for ( i = 1; i <= r; i++ )
    317           A[i] -= a[i];
    318       }
    319       else
    320       {
    321         IteratedFor e( 2, k-1, m+1 );
    322         while ( e.iterations_left() )
    323         {
    324           j = 0;
    325           what = true;
    326           for ( i = 2; i < k; i++ )
    327           {
    328             j += e[i];
    329             if ( e[i] > n[i] )
    330             {
    331               what = false;
    332               break;
    333             }
    334           }
    335           if ( what && j == m+1 )
    336           {
    337             g = Dm;
    338             for ( i = k-1; i >= 2 && ! g.isZero(); i-- )
    339               g = derivAndEval_P( g, e[i], Variable( i ), I[i] );
    340             if ( ! g.isZero() )
    341             {
    342               prodcomb = 1;
    343               for ( i = 2; i < k; i++ )
    344                 for ( j = 2; j <= e[i]; j++ )
    345                   prodcomb *= j;
    346               g /= prodcomb;
    347               if( ! (g.mvar() > Variable(1)) )
    348               {
    349                 prodcomb = 1;
    350                 for ( i = k-1; i > 1; i-- )
    351                   prodcomb *= binomialpower( Variable(i), -I[i], e[i] );
    352                 solveF_P( P0, Q0, S, T, g, r, a );
    353                 for ( i = 1; i <= r; i++ )
    354                   A[i] -= a[i] * prodcomb;
    355               }
    356             }
    357           }
    358           e++;
    359         }
    360       }
    361     }
    362   }
    363   return A;
    364 }
    365 
    366 
    367 static bool liftStep_P ( CFArray & P, int k, int r, int t, const Evaluation & A, const CFArray & lcG, const CanonicalForm & Uk, int * n, int h )
    368 {
    369   CFArray K( 1, r ), Q( 1, r ), Q0( 1, r ), P0( 1, r ), S( 1, r ), T( 1, r ), alpha( 1, r );
    370   CanonicalForm Rm, C, D, xa = Variable(k) - A[k];
    371   CanonicalForm xa1 = xa, xa2 = xa*xa;
    372   int i, m;
    373   for ( i = 1; i <= r; i++ )
    374   {
    375     Variable vm = Variable( t + 1 );
    376     Variable v1 = Variable(1);
    377     K[i] = swapvar( replaceLc( swapvar( P[i], v1, vm ), swapvar( A( lcG[i], k+1, t ), v1, vm ) ), v1, vm );
    378     P[i] = A( K[i], k, t );
    379   }
    380   Q[r] = 1;
    381   for ( i = r; i > 1; i-- )
    382   {
    383     Q[i-1] = Q[i] * P[i];
    384     P0[i] = A( P[i], 2, k-1 );
    385     Q0[i] = A( Q[i], 2, k-1 );
    386     (void) extgcd( P0[i], Q0[i], S[i], T[i] );
    387   }
    388   P0[1] = A( P[1], 2, k-1 );
    389   Q0[1] = A( Q[1], 2, k-1 );
    390   (void) extgcd( P0[1], Q0[1], S[1], T[1] );
    391   for ( m = 1; m <= n[k]+1; m++ )
    392   {
    393     Rm = prod( K ) - Uk;
    394     for ( i = 2; i < k; i++ )
    395       Rm.mod( binomialpower( Variable(i), -A[i], n[i]+1 ) );
    396     if ( mod( Rm, xa2 ) != 0 )
    397     {
    398       C = derivAndEval_P( Rm, m, Variable( k ), A[k] );
    399       D = 1;
    400       for ( i = 2; i <= m; i++ )
    401         D *= i;
    402       C /= D;
    403       alpha = findCorrCoeffs_P( P, Q, P0, Q0, S, T, C, A, r, k, h, n );
    404       for ( i = 1; i <= r; i++ )
    405         K[i] -= alpha[i] * xa1;
    406     }
    407     xa1 = xa2;
    408     xa2 *= xa;
    409   }
    410   for ( i = 1; i <= r; i++ )
    411     P[i] = K[i];
    412   return prod( K ) - Uk == 0;
    413 }
    414 
    415 
    416 static bool Hensel_P ( const CanonicalForm & U, CFArray & G, const CFArray & lcG, const Evaluation & A, const Variable & x )
    417 {
    418   int k, i, h, t = A.max();
    419   bool goodeval = true;
    420   CFArray Uk( A.min(), A.max() );
    421   int * n = new int[t+1];
    422   Uk[t] = U;
    423   for ( k = t-1; k > 1; k-- )
    424   {
    425     Uk[k] = Uk[k+1]( A[k+1], Variable( k+1 ) );
    426     n[k] = degree( Uk[k], Variable( k ) );
    427   }
    428   for ( k = A.min(); goodeval && (k <= t); k++ )
    429   {
    430     h = totaldegree( Uk[k], Variable(A.min()), Variable(k-1) );
    431     for ( i = A.min(); i <= k; i++ )
    432       n[i] = degree( Uk[k], Variable(i) );
    433     goodeval = liftStep_P( G, k, G.max(), t, A, lcG, Uk[k], n, h );
    434   }
    435   delete[] n;
    436   return goodeval;
    437 }
  • factory/ffreval.h

    rcde708 r08daea  
    55
    66#include "canonicalform.h"
    7 #include "cf_eval.h"
    8 
     7#include "cf_reval.h"
    98
    109class FFREvaluation : public REvaluation
     
    1716    {
    1817      for( int i=min; i<=max; i++ )
    19         values[i] = start[i] = gen->generate();  //generate random point
     18        values[i] = start[i] = 0; // start with 0
     19
     20      nextpoint();
     21    }
     22    FFREvaluation( int min, int max, const GFRandom & sample ) : REvaluation( min, max, sample ), start( min, max )
     23    {
     24      for( int i=min; i<=max; i++ )
     25        values[i] = start[i] = 0; // start with 0
     26
     27      nextpoint();
     28    }
     29    FFREvaluation( int min, int max, const AlgExtRandomF & sample ) : REvaluation( min, max, sample ), start( min, max )
     30    {
     31      for( int i=min; i<=max; i++ )
     32        values[i] = start[i] = 0; // start with 0
    2033
    2134      nextpoint();
    2235    }
    2336    FFREvaluation& operator= ( const FFREvaluation & e );
     37
    2438    void nextpoint();
    2539    bool hasNext();
    2640};
    2741
    28 CanonicalForm fin_ezgcd ( const CanonicalForm & FF, const CanonicalForm & GG );
    29 
    3042#endif
Note: See TracChangeset for help on using the changeset viewer.