diff --git a/CMakeLists.txt b/CMakeLists.txt
index 167fbf3993ae0a9b20b106c1c5a205df7f586588..0831fd83477efe0f9e9976a00149d555988d68e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,7 +83,7 @@ set(GMSH_API
   Post/PView.h Post/PViewData.h Plugin/PluginManager.h
   Graphics/drawContext.h
   contrib/kbipack/gmp_normal_form.h contrib/kbipack/gmp_matrix.h 
-    contrib/kbipack/gmp_blas.h
+    contrib/kbipack/gmp_blas.h contrib/kbipack/mpz.h
   contrib/DiscreteIntegration/DILevelset.h)
 
 execute_process(COMMAND date "+%Y%m%d" OUTPUT_VARIABLE DATE 
@@ -427,9 +427,11 @@ endif(ENABLE_GMM)
 if(ENABLE_KBIPACK)
   find_library(GMP_LIB NAMES libgmp.a libgmp.dll.a)
   if(GMP_LIB)
-    add_subdirectory(contrib/kbipack)
+    message("-- Found GMP")
     set(HAVE_KBIPACK TRUE)
     list(APPEND CONFIG_OPTIONS "Kbipack")
+    add_subdirectory(contrib/kbipack)
+    set(HAVE_GMP TRUE)
     list(APPEND EXTERNAL_LIBRARIES ${GMP_LIB})
   endif(GMP_LIB)
 endif(ENABLE_KBIPACK)
diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in
index 97c42ba0b6ac0d49c95c38a9528055e6e146bc0b..55b80babe31f3410416433fa32238d4a5ff295f5 100644
--- a/Common/GmshConfig.h.in
+++ b/Common/GmshConfig.h.in
@@ -15,6 +15,7 @@
 #cmakedefine HAVE_FL_TREE
 #cmakedefine HAVE_FOURIER_MODEL
 #cmakedefine HAVE_GMM
+#cmakedefine HAVE_GMP
 #cmakedefine HAVE_KBIPACK
 #cmakedefine HAVE_LAPACK
 #cmakedefine HAVE_LIBCGNS
diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp
index 87a8515e670f9008227eceee1283d44dae7c867e..51a67ebd3c01f6acc130fc0342aa96b3bd102ea0 100644
--- a/Geo/CellComplex.cpp
+++ b/Geo/CellComplex.cpp
@@ -348,7 +348,7 @@ int CellComplex::coreduction(Cell* generator, int omitted){
 
 int CellComplex::reduction(int dim, int omitted){
   if(dim < 1 || dim > 3) return 0;
-  std::map<Cell*, int, Less_Cell > cbd_c;
+
   int count = 0;
   
   bool reduced = true;
@@ -377,90 +377,38 @@ int CellComplex::reduction(int dim, int omitted){
   }
   return count;
 }
-/*
-int CellComplex::reduction(Cell* generator){
-  
-  int coreductions = 0;
 
-  std::queue<Cell*> Q;
-  std::set<Cell*, Less_Cell> Qset;
-  
-  Q.push(generator);
-  Qset.insert(generator);
-  
-  
-  std::list<Cell*> cbd_s;
-  std::list<Cell*> bd_c;
-  Cell* s;
-  int round = 0;
-  while( !Q.empty() ){
-    round++;
-    //printf("%d ", round);
-    
-    s = Q.front();
-    Q.pop();
-    removeCellQset(s, Qset);
-
-    cbd_s = s->getCoboundary();
-    if( cbd_s.size() == 1 && inSameDomain(s, cbd_s.front()) ){
-      removeCell(s);
-      bd_c = bd_s.front()->getBoundary();
-      enqueueCells(cbd_c, Q, Qset);
-      removeCell(cbd_s.front());
-      reductions++;
-    }
-    else if(cbd_s.empty()){
-      bd_c = s->getBoundary();
-      enqueueCells(bd_c, Q, Qset);
-    }
-    
-    
-  }
-  //printf("Coreduction: %d loops with %d coreductions\n", round, coreductions);
-  return reductions;
-}
-*/
-/*
-int CellComplex::reduction(int dim){
+int CellComplex::coreduction(int dim, int omitted){
   if(dim < 1 || dim > 3) return 0;
-  std::list<Cell*> cbd_c;
-  std::list<Cell*> bd_c;
+
   int count = 0;
-  
-  std::queue<Cell*> Q;
-  std::set<Cell*, Less_Cell> Qset;
-  
-  
-  for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){
-    
-    Cell* cell = *cit;
-    Q.push(cell);
-    Qset.insert(cell);
-    
-    while(Q.size() != 0){
-      
-      Cell* s = Q.front();
-      Q.pop();
-      cbd_c = s->getCoboundary();
-      if( cbd_c.size() == 1 && inSameDomain(s, cbd_c.front()) ){
-        
-        removeCell(cbd_c.front());
-        removeCell(s);
+
+  bool reduced = true;
+  bool ignoreCells = true;
+  while (reduced){
+
+    reduced = false;
+    citer cit = firstCell(dim);
+    while(cit != lastCell(dim)){
+      Cell* cell = *cit;
+      if( cell->getBoundarySize() == 1
+          && inSameDomain(cell, cell->firstBoundary()->first)){
+        ++cit;
+	if(dim-1 == 0 && omitted > 0){
+	  _store.at(omitted-1).insert(cell->firstBoundary()->first);
+	}
+        removeCell(cell->firstBoundary()->first);
+        removeCell(cell);
         count++;
-        bd_c = cbd_c.front()->getBoundary();
-        enqueueCells(bd_c, Q, Qset);
-        
-        cit = firstCell(dim-1);
+        reduced = true;
       }
-      
-      removeCellQset(s, Qset);
-      
+
+      if(getSize(dim) == 0 || getSize(dim-1) == 0) break;
+      cit++;
     }
   }
-  
   return count;
 }
-*/
   
 int CellComplex::reduceComplex(){
   
@@ -552,18 +500,21 @@ int CellComplex::coreduceComplex()
 
 void CellComplex::computeBettiNumbers(){
   
+  removeSubdomain();
+
   for(int i = 0; i < 4; i++){
-    _betti[i] = 0;
-    Msg::Debug("Betti number computation process: step %d of 4 \n", i+1);
+    if (getSize(i) != 0) _betti[i] = -1;
+    else _betti[i] = 0;
 
+    Msg::Debug("Betti number computation process: step %d of 4 \n", i+1);
     while (getSize(i) != 0){
       citer cit = firstCell(i);
       Cell* cell = *cit;
-      while(!cell->inSubdomain() && cit != lastCell(i)){
+      /*while(!cell->inSubdomain() && cit != lastCell(i)){
         cell = *cit;
         cit++;
       }
-      if(!cell->inSubdomain()) _betti[i] = _betti[i] + 1;
+      if(!cell->inSubdomain())*/ _betti[i] = _betti[i] + 1;
       removeCell(cell, false);
       coreduction(cell);
     }
@@ -705,86 +656,6 @@ int CellComplex::combine(int dim){
   return count;
 }
 
-/*
-int CellComplex::combine(int dim){ // version of combine that doesn't have a queue
-   double t1 = Cpu();
-  printf("Cell complex before combining: %d volumes, %d faces, %d edges and %d vertices.\n",
-         getSize(3), getSize(2), getSize(1), getSize(0));
-    
-  if(dim < 1 || dim > 3) return 0;
-  
-  std::list< std::pair<int, Cell*> > cbd_c;
-  std::list<Cell*> bd_c;
-  int count = 0;
-  bool combined = true;
-  while(combined){
-    combined = false;
-  for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){
-    Cell* s = *cit;
-    cbd_c = s->getCoboundary();
-        
-    if(s->getCoboundarySize() == 2 && !(*(cbd_c.front().second) == *(cbd_c.back().second)) 
-       && inSameDomain(s, cbd_c.front().second) && inSameDomain(s, cbd_c.back().second)
-       && cbd_c.front().second->getNumVertices() < getSize(dim) // heuristics for mammoth cell birth control
-       && cbd_c.back().second->getNumVertices() < getSize(dim)){
-      int or1 = cbd_c.front().first;
-      int or2 = cbd_c.back().first;
-      Cell* c1 = cbd_c.front().second;
-      Cell* c2 = cbd_c.back().second;
-      
-      removeCell(s);
-      
-      CombinedCell* newCell = new CombinedCell(c1, c2, (or1 != or2) );
-      removeCell(c1);
-      removeCell(c2);
-      std::pair<citer, bool> insertInfo =  _cells[dim].insert(newCell);
-      if(!insertInfo.second) printf("Warning: Combined cell not inserted! \n");
-      cit = firstCell(dim-1);
-      count++;
-      combined = true;
-    }
-  }
-    
-  }
-  
-   double t2 = Cpu();
-  printf("Cell complex after combining: %d volumes, %d faces, %d edges and %d vertices (%g s).\n",
-         getSize(3), getSize(2), getSize(1), getSize(0), t2 - t1);
-  
-  
-  return count;
-}
-*/
-
-/*
-void CellComplex::swapSubdomain(){
-  
-  for(int i = 0; i < 4; i++){
-    for(citer cit = firstCell(i); cit != lastCell(i); cit++){
-      Cell* cell = *cit;
-      if(cell->onDomainBoundary() && cell->inSubdomain()) cell->setInSubdomain(false);
-      else if(cell->onDomainBoundary() && !cell->inSubdomain()) cell->setInSubdomain(true);
-    }
-  }
-  
-  // make subdomain closed
-  for(int i = 0; i < 4; i++){
-    for(citer cit = firstCell(i); cit != lastCell(i); cit++){
-      Cell* cell = *cit;
-      if(cell->inSubdomain()){
-        std::list<Cell*> boundary = cell->getBoundary();
-        for(std::list<Cell*>::iterator it = boundary.begin(); it != boundary.end(); it++){
-          Cell* bdCell = *it;
-          bdCell->setInSubdomain(true);
-        }
-      }
-    }
-  }
-  
-  return;
-}*/
-
-
 void CellComplex::printComplex(int dim){
   for (citer cit = firstCell(dim); cit != lastCell(dim); cit++){
     Cell* cell = *cit;
diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h
index d1a59bbb0eabe35c49dcc53abb8b4525a6970b34..058d85e57a4743fe8877557df8520c4faf8ced4a 100644
--- a/Geo/CellComplex.h
+++ b/Geo/CellComplex.h
@@ -121,11 +121,12 @@ class CellComplex
     return ( (!c1->inSubdomain() && !c2->inSubdomain()) 
 	     || (c1->inSubdomain() && c2->inSubdomain()) ); }
   
-  // reduction of this cell complex
-  // removes reduction pairs of cell of dimension dim and dim-1
+  // (co)reduction of this cell complex
+  // removes (co)reduction pairs of cell of dimension dim and dim-1
   int reduction(int dim, int omitted=0);
-  
-  // useful functions for (co)reduction of cell complex
+  int coreduction(int dim, int omitted=0);  
+
+  // full (co)reduction of this cell complex (all dimensions)
   int reduceComplex();
   int coreduceComplex();
   
diff --git a/Geo/ChainComplex.cpp b/Geo/ChainComplex.cpp
index 9a9d75d6a6173575a36de3dd089592ebadf1196d..0d600737302583c0af45514b3a307ec02c121f20 100644
--- a/Geo/ChainComplex.cpp
+++ b/Geo/ChainComplex.cpp
@@ -68,10 +68,8 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
     }
     
     else{
-     
       mpz_t elem;
       mpz_init(elem);
-      
       _HMatrix[dim] = create_gmp_matrix_zero(rows, cols);
       for( std::set<Cell*, Less_Cell>::iterator cit = 
 	     cellComplex->firstCell(dim);
@@ -106,8 +104,8 @@ ChainComplex::ChainComplex(CellComplex* cellComplex){
             }
           }
         }
-      }     
-      mpz_clear(elem);  
+      } 
+      mpz_clear(elem); 
     }
 
     _kerH[dim] = NULL;
diff --git a/Geo/ChainComplex.h b/Geo/ChainComplex.h
index 5b85d8a1d867c64bbf055297ebaf5d7d88704a10..20546dea01cc3e8c6a2a08eb480fc1503c404f16 100644
--- a/Geo/ChainComplex.h
+++ b/Geo/ChainComplex.h
@@ -25,9 +25,9 @@
 #include "GVertex.h"
 #include "CellComplex.h"
 
-#include "gmp.h"
+#include "mpz.h"
 extern "C" {
-  #include "gmp_normal_form.h" // perhaps make c++ headers instead?
+  #include "gmp_normal_form.h"
 }
 
 // A class representing a chain complex of a cell complex.
diff --git a/Geo/Homology.cpp b/Geo/Homology.cpp
index 1ca2f803e7dbc39e20ad73ab3a7dfec99270ffe7..9d54dffef6eda4e0b87fc01297e6cf516161747f 100644
--- a/Geo/Homology.cpp
+++ b/Geo/Homology.cpp
@@ -199,8 +199,11 @@ void Homology::findDualGenerators(std::string fileName){
   int omitted = _cellComplex->coreduceComplex();
   
   _cellComplex->cocombine(0);
+  _cellComplex->coreduction(1);
   _cellComplex->cocombine(1);
+  _cellComplex->coreduction(2);
   _cellComplex->cocombine(2);
+  _cellComplex->coreduction(3);
   
   _cellComplex->checkCoherence();
   double t2 = Cpu();
diff --git a/contrib/kbipack/CMakeLists.txt b/contrib/kbipack/CMakeLists.txt
index 36e436e5c65a8034446bb6f928974e58b6831ed7..7ac9260016af0013be1e66df62416831ae3f5400 100644
--- a/contrib/kbipack/CMakeLists.txt
+++ b/contrib/kbipack/CMakeLists.txt
@@ -8,6 +8,7 @@ set(SRC
   gmp_matrix_io.c
   gmp_matrix.c
   gmp_blas.c
+  mpz.c
 )
 
 file(GLOB_RECURSE HDR RELATIVE ${CMAKE_SOURCE_DIR}/contrib/kbipack *.h)
diff --git a/contrib/kbipack/gmp_blas.c b/contrib/kbipack/gmp_blas.c
index 501c4eba543f02980b4138c039bbbb8e920913db..6003888d5b67598c71dd23a44d50e5702f2c0feb 100644
--- a/contrib/kbipack/gmp_blas.c
+++ b/contrib/kbipack/gmp_blas.c
@@ -164,7 +164,7 @@ size_t gmp_blas_iamax(size_t n, const mpz_t* x, size_t incx)
   mpz_t  max_so_far;
 
   mpz_init(max_so_far);
-  mpz_set(max_so_far, 0);
+  mpz_set_si(max_so_far, 0);
   ind_so_far = 0;
 
   for(ind = 0; ind < n; ind++)
diff --git a/contrib/kbipack/gmp_blas.h b/contrib/kbipack/gmp_blas.h
index 6c9c88b2f8454539f9ba694239d52232b33e34df..b2800e5c2fa930627c3b74366d25c16d38fbd8a1 100644
--- a/contrib/kbipack/gmp_blas.h
+++ b/contrib/kbipack/gmp_blas.h
@@ -31,7 +31,7 @@
 #define __GMP_BLAS_H__
 
 #include <stdio.h>
-#include <gmp.h>
+#include <mpz.h>
 
 /***********/
 /* Level 1 */
@@ -39,7 +39,7 @@
 
 /* x <-> y */
 void 
-gmp_blas_swap(size_t n,          mpz_t * x, size_t incx, mpz_t * y, size_t incy);
+gmp_blas_swap(size_t n, mpz_t * x, size_t incx, mpz_t * y, size_t incy);
 
 /* x <- ax */
 void 
diff --git a/contrib/kbipack/gmp_matrix.c b/contrib/kbipack/gmp_matrix.c
index 531466abd1372dc38931dd69152b3cb2c7486dca..c690292c6c70a4c07757ea8a974761aae76f4938 100644
--- a/contrib/kbipack/gmp_matrix.c
+++ b/contrib/kbipack/gmp_matrix.c
@@ -132,7 +132,7 @@ create_gmp_matrix_identity(size_t dim)
 
 gmp_matrix * 
 create_gmp_matrix_zero(size_t rows, size_t cols)
-{
+{ 
   gmp_matrix * new_matrix;
   size_t       ind;
 
@@ -156,7 +156,6 @@ create_gmp_matrix_zero(size_t rows, size_t cols)
     {
       mpz_init_set_si (new_matrix -> storage[ind], 0);
     }
-
   return new_matrix;
 }
 
@@ -374,7 +373,6 @@ gmp_matrix_negate_col(size_t col, gmp_matrix * m)
     {
       return EXIT_FAILURE;
     }
-
   mpz_init(minus_one);
   mpz_set_si(minus_one, -1);
   gmp_blas_scal(m -> rows, minus_one, 
diff --git a/contrib/kbipack/gmp_matrix.h b/contrib/kbipack/gmp_matrix.h
index 5d0e7c57dc853238729492548f1da24eb634b837..ea0c9af66b339b88684c3c438442bb554db5c0c1 100644
--- a/contrib/kbipack/gmp_matrix.h
+++ b/contrib/kbipack/gmp_matrix.h
@@ -28,7 +28,7 @@
 #ifndef __GMP_MATRIX_H__
 #define __GMP_MATRIX_H__
 
-#include"gmp_blas.h"
+#include "gmp_blas.h"
 
 typedef struct
 {
diff --git a/contrib/kbipack/mpz.c b/contrib/kbipack/mpz.c
new file mode 100755
index 0000000000000000000000000000000000000000..09c40df9610e6c24c6c802f68adb5833161268e9
--- /dev/null
+++ b/contrib/kbipack/mpz.c
@@ -0,0 +1,238 @@
+/*
+  This is an interface to masquerade ordinary long integers in C
+  language behind an interface mimicing arbitrary precision arithmetic
+  interger (mpz) interface in The GNU MP Bignum library.
+
+  Only the functions needed by Kbipack are available.
+
+  THIS INTERFACE IS NOT BERFORMING ANY ARBITRARY PRECISION ARITHMETIC.
+  You should always use the GMP library (http://gmplib.org/) when possible.
+
+  Some basic techniques to detect integer overflows are implemented.
+  However, they don't interfere the program flow IN ANY WAY, they just write
+  an error message to stdout.
+
+ */
+
+#include "mpz.h"
+
+// disabled for now
+#if 0
+
+#include "limits.h"
+
+void overflow()
+{
+  printf("ERROR: Integer overflow detected! Compile with GMP library to fix this. \n");
+}
+
+long int addcheck(long int a, long int b){
+
+  long int c = a + b;
+  if (b >= 0){
+    if (c < a) overflow();
+  }
+  else if (b < 0){
+    if (c > a) overflow();
+  }
+  return c;
+}
+
+long int multcheck(long int a, long int b){
+  long long int c = (long long int)a*b;
+  if(c > LONG_MAX || c < LONG_MIN) overflow();
+  return c;
+}
+
+void mpz_init(mpz_ptr x)
+{
+  x->z = 0;
+}
+
+void mpz_init_set(mpz_ptr rop, mpz_ptr op)
+{
+  rop->z = op->z;
+}
+
+void mpz_init_set_si(mpz_ptr rop, signed long int op)
+{
+  rop->z = op;
+}
+
+void mpz_set_ui(mpz_ptr rop, unsigned long int op)
+{
+  rop->z = op;
+}
+
+void mpz_set(mpz_ptr rop, mpz_ptr op)
+{
+  rop->z = op->z;
+}
+void mpz_set_si(mpz_ptr rop, signed long int op)
+{
+  rop->z = op;
+}
+
+void mpz_clear(mpz_ptr x)
+{
+
+}
+
+// arithmethic
+void mpz_add(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2)
+{
+  rop->z = addcheck(op1->z, op2->z);
+}
+
+void mpz_mul(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2)
+{
+  rop->z = multcheck(op1->z, op2->z);
+}
+
+void mpz_addmul(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2)
+{
+  rop->z = addcheck(rop->z,multcheck(op1->z,op2->z));
+}
+
+void mpz_neg(mpz_ptr rop, mpz_ptr op)
+{
+  rop->z = -op->z;
+}
+
+
+// division 
+void mpz_divexact(mpz_ptr q, mpz_ptr n, mpz_ptr d)
+{
+  div_t temp;
+  temp = div(n->z, d->z);
+  q->z = temp.quot;
+}
+
+void mpz_cdiv_q(mpz_ptr q, mpz_ptr n, mpz_ptr d)
+{
+  div_t temp;
+  temp = div(n->z, d->z);
+  q->z = temp.quot;
+}
+void mpz_cdiv_qr(mpz_ptr q, mpz_ptr r, mpz_ptr n, mpz_ptr d)
+{
+  div_t temp;
+  temp = div(n->z, d->z);
+  q->z = temp.quot;
+  r->z = temp.rem;
+}
+
+void mpz_tdiv_r(mpz_ptr r, mpz_ptr n, mpz_ptr d)
+{
+  div_t temp;
+  temp = div(n->z, d->z);
+  if(n->z < 0) r->z = -temp.rem;
+  else r->z = temp.rem;
+}
+
+// compare
+int mpz_cmp_si(mpz_ptr op1, signed long int op2)
+{
+  if(op1->z > op2) return 1;
+  else if(op1->z < op2) return -1;
+  else return 0;
+  return 0;
+}
+
+int mpz_cmpabs(mpz_ptr op1, mpz_ptr op2)
+{
+  if(abs(op1->z) > abs(op2->z)) return 1;
+  else if(abs(op1->z) < abs(op2->z)) return -1;
+  else return 0;
+  return 0;
+}
+
+int mpz_sgn(mpz_ptr op)
+{
+  if(op->z > 0) return 1;
+  else if(op->z < 0) return -1;
+  else return 0;
+}
+
+signed long int mpz_get_si(mpz_ptr op)
+{
+  signed long int temp = op->z;
+  return temp;
+}
+
+long int gcd(long int a, long int b)
+{
+  long int temp = 0;
+  long int remainder = 0;
+  if (a < b) {
+    temp = a;
+    a = b;
+    b = temp;
+  }
+  remainder = a % b;
+  if(remainder == 0) return b;
+  else return gcd(b, remainder);
+}
+
+void extended_gcd(long int* g, long int* s, long int* t,
+		  long int a, long int b)
+{
+  long int x = 0;
+  long int lastx = 1;
+  long int y = 1;    
+  long int lasty = 0;
+  while (b != 0){
+    div_t divt = div(a,b);
+    long int quotient = divt.quot;
+        
+    long int temp = b;
+    b = a % b;
+    a = temp;
+        
+    temp = x;
+    x = addcheck(lastx, multcheck(-quotient,x));
+    lastx = temp;
+        
+    temp = y;
+    y = addcheck(lasty, multcheck(-quotient,y));
+    lasty = temp;
+  }
+  *s = lastx;
+  *t = lasty;
+  *g = a;
+}
+
+void mpz_gcdext(mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_ptr a, mpz_ptr b)
+{
+  
+  extended_gcd(&g->z, &s->z, &t->z, a->z, b->z);
+  /*printf("g: %ld, s: %ld, t: %ld, a: %ld, b: %ld. \n", 
+    g->z, s->z, t->z, a->z, b->z); */
+}
+
+size_t mpz_out_str(FILE *stream, int base, mpz_ptr op)
+{
+  return 0;
+}
+
+/*
+main()
+{
+
+  mpz_t a;
+  mpz_t b;
+  mpz_t c;
+  mpz_init(a);
+  mpz_init(b);
+  mpz_init(c);
+
+  mpz_set_si(a, 2147483647);
+  mpz_set_si(b, 2);
+  mpz_mul(c, a, b);
+
+  printf("a: %ld, b: %ld, c: %ld. \n", a->z, b->z, c->z);
+
+  return EXIT_SUCCESS;
+
+  }*/
+#endif
diff --git a/contrib/kbipack/mpz.h b/contrib/kbipack/mpz.h
new file mode 100755
index 0000000000000000000000000000000000000000..d0d508583475802942300ffb6c41b2b533e96c7a
--- /dev/null
+++ b/contrib/kbipack/mpz.h
@@ -0,0 +1,75 @@
+/*
+  This is an interface to masquerade ordinary long integers in C
+  language behind an interface mimicing arbitrary precision arithmetic
+  interger (mpz) interface in The GNU MP Bignum library.
+
+  Only the functions needed by Kbipack are available.
+
+  THIS INTERFACE IS NOT BERFORMING ANY ARBITRARY PRECISION ARITHMETIC.
+  You should always use the GMP library (http://gmplib.org/) when possible.
+
+  Some basic techniques to detect integer overflows are implemented.
+  However, they don't interfere the program flow IN ANY WAY, they just write
+  an error message to stdout.
+
+ */
+
+#ifndef __MPZ_H__
+#define __MPZ_H__
+
+#include "gmp.h"
+
+// disabled for now
+#if 0
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef struct {
+  long int z; 
+} mpz_struct;
+
+typedef mpz_struct mpz_t[1];  
+typedef mpz_struct* mpz_ptr;
+
+// init
+void mpz_init(mpz_ptr x);
+void mpz_init_set(mpz_ptr rop, mpz_ptr op);
+void mpz_init_set_si(mpz_ptr rop, signed long int op);
+
+// set
+void mpz_set(mpz_ptr rop, mpz_ptr op);
+void mpz_set_si(mpz_ptr rop, signed long int op);
+void mpz_set_ui(mpz_ptr rop, unsigned long int op);
+
+// clear
+void mpz_clear(mpz_ptr x);
+
+
+// arithmethic
+void mpz_add(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2);
+void mpz_mul(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2);
+void mpz_addmul(mpz_ptr rop, mpz_ptr op1, mpz_ptr op2);
+void mpz_neg(mpz_ptr rop, mpz_ptr op);
+
+// division 
+void mpz_divexact(mpz_ptr q, mpz_ptr n, mpz_ptr d);
+void mpz_cdiv_q(mpz_ptr q, mpz_ptr n, mpz_ptr d);
+void mpz_cdiv_qr(mpz_ptr q, mpz_ptr r, mpz_ptr n, mpz_ptr d);
+void mpz_tdiv_r(mpz_ptr r, mpz_ptr n, mpz_ptr d);
+
+// compare
+int mpz_cmp_si(mpz_ptr op1, signed long int op2);
+int mpz_cmpabs(mpz_ptr op1, mpz_ptr op2);
+int mpz_sgn(mpz_ptr op);
+
+// extended Euclid's algorithm
+void mpz_gcdext(mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_ptr a, mpz_ptr b);
+
+// conversion
+signed long int mpz_get_si(mpz_ptr op);
+
+// io
+size_t mpz_out_str(FILE *stream, int base, mpz_ptr op);
+#endif
+#endif
+
diff --git a/tutorial/t10.geo b/tutorial/t10.geo
index 6e8606054f0a3495490e4da8ee6056bc0c835745..b80d7b1218e2f8c90a9c2a31336dd98be5fd2d4f 100644
--- a/tutorial/t10.geo
+++ b/tutorial/t10.geo
@@ -129,15 +129,23 @@ Physical Surface(75) = {46, 63, 66, 52, 50, 48, 54, 60, 58, 56};
 // Create a mesh of the model
 Mesh 3;
 
-// Find generators of relative homology spaces of the domain modulo the four terminals.
+// Find generators of relative homology spaces of the domain modulo the 
+// four terminals.
 // Save the generator chains to t10_hom.msh.
 HomGen("t10_hom.msh") = {{69}, {70, 71, 72, 73}};
 
-// Find the corresponding thin cuts.
+// Find the corresponding thin cuts, 
+// generators of relative homology spaces modulo the 
+// non-terminal domain surface.
 // Save the cut chains to t10_hom.msh.
 HomGen("t10_hom.msh") = {{69}, {75}};
 
-// Only find and print the ranks of the relative homology spaces (Betti numbers).
+// Find the corresponding thick cuts.
+// Save the cut chains to t10_hom.msh.
+ HomCut("t10_hom.msh") = {{69}, {70, 71, 72, 73}};
+
+// Only find and print the ranks of the relative homology spaces 
+// (Betti numbers).
 HomRank {{69},{70, 71, 72, 73}};
 
 // More examples (uncomment):