Index: factory/facSparseHensel.cc
===================================================================
--- factory/facSparseHensel.cc	(revision 97686ecde8614d72ee9d26e96dc9344df8a7da32)
+++ factory/facSparseHensel.cc	(revision 7b5cb2e2df585c1f09f3b55dd033e016a8aed7b6)
@@ -21,5 +21,5 @@
 #include "facFqFactorize.h"
 
-bool
+int
 LucksWangSparseHeuristic (const CanonicalForm& F, const CFList& factors,
                           int level, const CFList& leadingCoeffs, CFList& result)
@@ -66,6 +66,11 @@
   delete [] monomsLead;
 
-  CFArray termsF= getTerms (F);
-  sort (termsF);
+  CFArray termsF= getBiTerms (F);
+  if (termsF.size() > 450)
+  {
+    delete [] monoms;
+    return 0;
+  }
+  sort (termsF, level);
 
   CFList tmp;
@@ -80,7 +85,6 @@
   CanonicalForm H= prod (tmp);
   CFArray monomsH= getMonoms (H);
-  sort (monomsH);
-
-  groupTogether (termsF, level);
+  sort (monomsH,F.level());
+
   groupTogether (monomsH, F.level());
 
@@ -88,5 +92,5 @@
   {
     delete [] stripped2;
-    return false;
+    return 0;
   }
 
@@ -99,8 +103,9 @@
   {
     delete [] stripped2;
-    return false;
+    return 0;
   }
 
   CFArray A= getEquations (monomsH, termsF);
+  CFArray startingSolution= solution;
   CFArray newSolution= CFArray (solution.size());
   do
@@ -110,22 +115,18 @@
       break;
     if (!simplify (A, newSolution, F.level() + 1))
-    {
-      delete [] stripped2;
-      return false;
-    }
+      break;
     if (isZero (newSolution))
-    {
-      delete [] stripped2;
-      return false;
-    }
+      break;
     if (!merge (solution, newSolution))
-    {
-      delete [] stripped2;
-      return false;
-    }
+      break;
   } while (1);
 
 
   result= CFList();
+  if (isEqual (startingSolution, solution))
+  {
+    delete [] stripped2;
+    return 0;
+  }
   CanonicalForm factor;
   num= 0;
@@ -135,10 +136,16 @@
     factor= 0;
     for (j= 0; j < k; j++, num++)
+    {
+      if (solution [num].isZero())
+        continue;
       factor += solution [num]*stripped2[i][j];
+    }
     result.append (factor);
   }
 
   delete [] stripped2;
-  return true;
+  if (result.length() > 0)
+    return 1;
+  return 0;
 }
 
Index: factory/facSparseHensel.h
===================================================================
--- factory/facSparseHensel.h	(revision 97686ecde8614d72ee9d26e96dc9344df8a7da32)
+++ factory/facSparseHensel.h	(revision 7b5cb2e2df585c1f09f3b55dd033e016a8aed7b6)
@@ -18,4 +18,6 @@
 #include "cf_iter.h"
 #include "templates/ftmpl_functions.h"
+#include "cf_algorithm.h"
+#include "cf_map.h"
 
 /// compare polynomials
@@ -81,5 +83,5 @@
 /// quick sort helper function
 inline
-void quickSort (int lo, int hi, CFArray& A)
+void quickSort (int lo, int hi, CFArray& A, int l)
 {
   int i= lo, j= hi;
@@ -87,6 +89,14 @@
   while (i <= j)
   {
-    while (comp (A [i], tmp) < 0 && i < hi) i++;
-    while (comp (tmp, A[j]) < 0 && j > lo) j--;
+    if (l > 0)
+    {
+      while (comp (A [i], tmp, l) < 0 && i < hi) i++;
+      while (comp (tmp, A[j], l) < 0 && j > lo) j--;
+    }
+    else
+    {
+      while (comp (A [i], tmp) < 0 && i < hi) i++;
+      while (comp (tmp, A[j]) < 0 && j > lo) j--;
+    }
     if (i <= j)
     {
@@ -96,14 +106,15 @@
     }
   }
-  if (lo < j) quickSort (lo, j, A);
-  if (i < hi) quickSort (i, hi, A);
+  if (lo < j) quickSort (lo, j, A, l);
+  if (i < hi) quickSort (i, hi, A, l);
 }
 
 /// quick sort @a A
 inline
-void sort (CFArray& A)
-{
-  quickSort (0, A.size() - 1, A);
-}
+void sort (CFArray& A, int l= 0)
+{
+  quickSort (0, A.size() - 1, A, l);
+}
+
 
 /// find normalizing factors for @a biFactors and build monic univariate factors
@@ -187,4 +198,65 @@
 }
 
+/// helper function for getBiTerms
+inline CFArray
+getBiTerms_helper (const CanonicalForm& F, const CFMap& M)
+{
+  CFArray buf= CFArray (size (F));
+  int k= 0, level= F.level() - 1;
+  Variable x= F.mvar();
+  Variable y= Variable (F.level() - 1);
+  Variable one= Variable (1);
+  Variable two= Variable (2);
+  CFIterator j;
+  for (CFIterator i= F; i.hasTerms(); i++)
+  {
+    if (i.coeff().level() < level)
+    {
+      buf[k]= M (i.coeff())*power (one,i.exp());
+      k++;
+      continue;
+    }
+    j= i.coeff();
+    for (;j.hasTerms(); j++, k++)
+      buf[k]= power (one,i.exp())*power (two,j.exp())*M (j.coeff());
+  }
+  CFArray result= CFArray (k);
+  for (int i= 0; i < k; i++)
+    result[i]= buf[i];
+  return result;
+}
+
+/// get terms of @a F where F is considered a bivariate poly in Variable(1),
+/// Variable (2)
+inline CFArray
+getBiTerms (const CanonicalForm& F)
+{
+  if (F.inCoeffDomain())
+  {
+    CFArray result= CFArray (1);
+    result [0]= F;
+    return result;
+  }
+  if (F.isUnivariate())
+  {
+    CFArray result= CFArray (size(F));
+    int j= 0;
+    for (CFIterator i= F; i.hasTerms(); i++, j++)
+      result[j]= i.coeff()*power (F.mvar(), i.exp());
+    return result;
+  }
+
+  CanonicalForm G= F;
+
+  CFMap M;
+  M.newpair (Variable (1), F.mvar());
+  M.newpair (Variable (2), Variable (F.level() - 1));
+  G= swapvar (F, Variable (1), F.mvar());
+  G= swapvar (G, Variable (2), Variable (F.level() - 1));
+
+  CFArray result= getBiTerms_helper (G, M);
+  return result;
+}
+
 /// build a poly from entries in @a A
 inline CanonicalForm
@@ -197,5 +269,5 @@
 }
 
-/// group together elements in @a A, where entries in @a A are put put together
+/// group together elements in @a A, where entries in @a A are put together
 /// if they coincide up to level @a level
 inline void
@@ -213,4 +285,6 @@
     }
   }
+  if (A[n].isZero())
+    k--;
   CFArray B= CFArray (k);
   n++;
@@ -509,5 +583,5 @@
 ///
 /// @return @a LucksWangSparseHeuristic returns true if it was successful
-bool
+int
 LucksWangSparseHeuristic (const CanonicalForm& F,     ///<[in] polynomial to be
                                                       ///< factored
