diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8faf7143e8abbf9d543019c3231114ed375098e1..e0293612cdf9027ace07b05a24a6bef62874ac98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,7 @@ set(SOURCES
   z_spm_convert_to_ijv.c
   z_spm_dofs2flat.c
   z_spm_expand.c
+  z_spm_dof_extend.c
   z_spm_genrhs.c
   z_spm_integer.c
   z_spm_laplacian.c
@@ -47,7 +48,7 @@ set(spm_sources
   spm.c
   spm_io.c
   spm_integers.c
-  spm_expand.c
+  spm_dofs.c
   spm_read_driver.c
   drivers/skitf.f
   drivers/iohb.c
diff --git a/spm.h b/spm.h
index d46a446dcb800e5c6c169b6c6b05a0b63623501a..c91de942ecb26fcdb04b5f172215bd223e01a682 100644
--- a/spm.h
+++ b/spm.h
@@ -79,12 +79,13 @@ struct pastix_spm_s {
     pastix_int_t      dof;     /**< Number of degrees of freedom per unknown,
                                     if > 0, constant degree of freedom
                                     otherwise, irregular degree of freedom (refer to dofs)      */
-    pastix_int_t     *dofs;    /**< Number of degrees of freedom per unknown (NULL, if dof > 0) */
+    pastix_int_t     *dofs;    /**< Array of the first column of each element in the
+                                    expanded matrix [+baseval]                                  */
     pastix_order_t    layout;  /**< PastixColMajor, or PastixRowMajor                           */
 
-    pastix_int_t     *colptr;  /**< List of indirections to rows for each vertex                */
-    pastix_int_t     *rowptr;  /**< List of edges for each vertex                               */
-    pastix_int_t     *loc2glob;/**< Corresponding numbering from local to global                */
+    pastix_int_t     *colptr;  /**< List of indirections to rows for each vertex [+baseval]     */
+    pastix_int_t     *rowptr;  /**< List of edges for each vertex [+baseval]                    */
+    pastix_int_t     *loc2glob;/**< Corresponding numbering from local to global [+baseval]     */
     void             *values;  /**< Values stored in the matrix                                 */
 };
 
diff --git a/spm_dofs.c b/spm_dofs.c
new file mode 100644
index 0000000000000000000000000000000000000000..1732564327a6717b2c7784883dcf10d5dca71483
--- /dev/null
+++ b/spm_dofs.c
@@ -0,0 +1,147 @@
+/**
+ *
+ * @file spm_dofs.c
+ *
+ *  PaStiX spm routines
+ *  PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest,
+ *  LaBRI, University of Bordeaux 1 and IPB.
+ *
+ * @version 5.1.0
+ * @author Mathieu Faverge
+ * @author Theophile Terraz
+ * @author Alban Bellot
+ * @date 2015-01-01
+ *
+ **/
+#include "common.h"
+#include "spm.h"
+
+#include "z_spm.h"
+#include "c_spm.h"
+#include "d_spm.h"
+#include "s_spm.h"
+#include "p_spm.h"
+
+
+pastix_spm_t *
+spmDofExtend( const int type,
+              const int dof,
+              const pastix_spm_t *spm )
+{
+    pastix_spm_t *newspm;
+
+    /* Quick return */
+    if ( dof == 1 )
+        return (pastix_spm_t *)spm;
+
+    if ( spm->dof != 1 ) {
+        pastix_error_print( "Cannot extend spm including dofs already\n" );
+        return (pastix_spm_t *)spm;
+    }
+
+    newspm = spmCopy( spm );
+
+    /**
+     * Generate constant dof
+     */
+    if (type == 0) {
+        newspm->dof     = dof;
+        newspm->nexp    = spm->n  * dof;
+        newspm->gNexp   = spm->gN * dof;
+        newspm->nnzexp  = spm->nnz  * dof * dof;
+        newspm->gnnzexp = spm->gnnz * dof * dof;
+    }
+    else {
+        pastix_int_t i, j, k, dofi, dofj, baseval;
+        pastix_int_t *dofptr, *colptr, *rowptr;
+
+        baseval = spmFindBase( spm );
+
+        newspm->dof  = -1;
+        newspm->dofs = malloc( (spm->n+1) * sizeof(pastix_int_t) );
+        dofptr = newspm->dofs;
+
+        /**
+         * Initialize the dofs array where the degree of freedom of vertex i is
+         * dof[i+1] - dof[i]
+         */
+        *dofptr = 0;
+        for(i=0; i<spm->n; i++, dofptr++) {
+            dofi = 1 + ( rand() % dof );
+            dofptr[1] = dofptr[0] + dofi;
+        }
+
+        newspm->nexp  = *dofptr;
+        newspm->gNexp = *dofptr;
+
+        /**
+         * Count the number of non zeroes
+         */
+        newspm->nnzexp = 0;
+        colptr = newspm->colptr;
+        rowptr = newspm->rowptr;
+        dofptr = newspm->dofs;
+
+        switch(spm->fmttype)
+        {
+        case PastixCSC:
+            for(j=0; j<newspm->n; j++, colptr++) {
+                dofj = dofptr[j+1] - dofptr[j];
+
+                for(k=colptr[0]; k<colptr[1]; k++, rowptr++) {
+                    i = *rowptr - baseval;
+                    dofi = dofptr[i+1] - dofptr[i];
+
+                    newspm->nnzexp += dofi * dofj;
+                }
+            }
+            break;
+        case PastixCSR:
+            for(i=0; i<newspm->n; i++, rowptr++) {
+                dofi = dofptr[i+1] - dofptr[i];
+
+                for(k=rowptr[0]; k<rowptr[1]; k++, rowptr++) {
+                    j = *colptr - baseval;
+                    dofj = dofptr[j+1] - dofptr[j];
+
+                    newspm->nnzexp += dofi * dofj;
+                }
+            }
+            break;
+        case PastixIJV:
+            for(k=0; k<newspm->nnz; k++, rowptr++, colptr++)
+            {
+                i = *rowptr - baseval;
+                j = *colptr - baseval;
+                dofi = dofptr[i+1] - dofptr[i];
+                dofj = dofptr[j+1] - dofptr[j];
+
+                newspm->nnzexp += dofi * dofj;
+            }
+        }
+        newspm->gnnzexp = newspm->nnzexp;
+    }
+
+    switch (spm->flttype) {
+    case PastixFloat:
+        s_spmDofExtend( newspm );
+        break;
+
+    case PastixDouble:
+        d_spmDofExtend( newspm );
+        break;
+
+    case PastixComplex32:
+        c_spmDofExtend( newspm );
+        break;
+
+    case PastixComplex64:
+        z_spmDofExtend( newspm );
+        break;
+
+    case PastixPattern:
+        ;
+    }
+
+    return newspm;
+}
diff --git a/spm_expand.c b/spm_expand.c
deleted file mode 100644
index 2957feb995540c162e4958092eff76b6fcc495e3..0000000000000000000000000000000000000000
--- a/spm_expand.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- *
- * @file spm_expand.c
- *
- *  PaStiX spm routines
- *  PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest,
- *  LaBRI, University of Bordeaux 1 and IPB.
- *
- * @version 5.1.0
- * @author Mathieu Faverge
- * @author Theophile Terraz
- * @author Alban Bellot
- * @date 2015-01-01
- *
- **/
-#include "common.h"
-#include "spm.h"
-
-#include "z_spm.h"
-#include "c_spm.h"
-#include "d_spm.h"
-#include "s_spm.h"
-#include "p_spm.h"
-
-void print_tab_int(pastix_int_t* tab, pastix_int_t size)
-{
-    int i;
-    for(i=0;i<size;i++)
-        printf("%d ",tab[i]);
-    printf("\n");
-}
-
-void print_tab_cpx(double* tab, pastix_int_t size)
-{
-    int i;
-    for(i=0;i<size;i++)
-        printf("%f ",tab[i]);
-    printf("\n");
-}
-
-
-void init_rand()
-{
-  srand(time(NULL));
-}
-
-int randminmax(pastix_int_t min, pastix_int_t max)
-{
-  return min + rand()%(max-min+1);
-}
-
-pastix_int_t* computeCorrespondIndex(const pastix_int_t *dofs, pastix_int_t n)
-{
-    pastix_int_t* dofs_coef=malloc(sizeof(pastix_int_t)*(n+1));
-    dofs_coef[0]=0;
-    int i;
-    for(i=1;i<n+1;i++)
-    {
-        dofs_coef[i]=dofs_coef[i-1]+dofs[i-1];
-    }
-    return dofs_coef;
-}
-
-void genDof(pastix_int_t step,pastix_int_t* dofs,pastix_int_t size)
-{
-  int i;
-  for(i=0;i<size;i++)
-      dofs[i]=i%step+1;
-}
-
-void genRandDof(pastix_int_t min,pastix_int_t max,pastix_int_t* dofs,pastix_int_t size)
-{
-  int i;
-  for(i=0;i<size;i++)
-    dofs[i]=randminmax(min,max);
-}
-
-pastix_int_t* computeEltPerCol(const pastix_spm_t *spm)
-{
-  pastix_int_t col,row,baseval;
-
-  pastix_int_t* coef=malloc(sizeof(pastix_int_t)*spm->n);
-  int i;
-  for(i=0;i<spm->n;i++)
-      coef[i]=0;
-  baseval=spmFindBase( spm );
-  row=0;
-  for( col=0; col < spm->n; col++ )
-    {
-      for( row=spm->colptr[col]-baseval; row<spm->colptr[col+1]-baseval; row++)
-	{
-            coef[col] += spm->dofs[col] * spm->dofs[spm->rowptr[row]-baseval];
-	}
-    }
-  return coef;
-}
-
-/**
- *******************************************************************************
- *
- * @ingroup spm_internal
- *
- * dofCst - Expand a CSC matrix without dofs into a CSC matrix with constant dofs
- *
- *
- *******************************************************************************
- *
- * @param[in] spm
- *           The spm to expand
- *
- *******************************************************************************/
-void
-dofCst(pastix_spm_t* spm,pastix_int_t dof)
-{
-    int i;
-    pastix_int_t* dofs = malloc((spm->n+1)*sizeof(pastix_int_t));
-
-    spm->dof      = dof;
-    spm->gNexp    = spm->n*dof;
-    spm->nexp     = spm->n*dof;
-    spm->nnzexp   = spm->n*dof*dof;
-    spm->gnnzexp  = spm->n*dof*dof;
-    spm->dofs     = dofs;
-
-    for(i=0;i<spm->n+1;i++)
-        dofs[i]=dof*i;
-
-    spmExpand(spm);
-}
-
-
-/**
- *******************************************************************************
- *
- * @ingroup spm_internal
- *
- * dofVar - Expand a CSC matrix without dofs into a CSC matrix with variable dofs
- *
- *
- *******************************************************************************
- *
- * @param[in] spm
- *           The spm to expand
- *
- *******************************************************************************/
-void
-dofVar(pastix_spm_t* spm)
-{
-    pastix_int_t *dofs=malloc(sizeof(pastix_int_t)*spm->n);
-    pastix_int_t i,nnzexp,nexp;
-
-    spm->gNexp    = spm->gN;
-    spm->nexp     = spm->n;
-    spm->gnnzexp  = spm->gnnz;
-    spm->nnzexp   = spm->nnz;
-    spm->dof      = -1;
-
-    genDof(3,dofs,spm->n); //cyclique, pas de 3
-    //genRandDof(/*min*/1,/*max*/5 ,spm->dofs,spm->n); //random dofs, entre 1 et 5
-
-    spm->dofs = dofs;
-    pastix_int_t *coef = computeEltPerCol(spm); // free coef
-
-    nnzexp = 0;
-    nexp   = 0;
-
-    for(i=0;i<spm->n;i++)
-    {
-        nnzexp += coef[i];
-        nexp   += spm->dofs[i];
-    }
-
-    spm->nnzexp  = nnzexp;
-    spm->gnnzexp = nnzexp;
-    spm->gNexp   = nexp;
-    spm->nexp    = nexp;
-
-    pastix_int_t* tab = computeCorrespondIndex(dofs,spm->n);
-
-    spm->dofs   = tab;
-    spmExpand(spm);
-
-    /*
-    print_tab_int(spm->colptr,spm->n);
-    print_tab_int(spm->rowptr,spm->nnz);
-    print_tab_cpx(spm->values,spm->nnzexp);
-    print_tab_int(spm->dofs,spm->n+1);
-     */
-}
-
-
diff --git a/z_spm.h b/z_spm.h
index c846eeca1380e82be614cdc8ef9a5eeecf8f324d..fc8321ddc6e3cd1e7ddb6adbf2521bf242a7c5f0 100644
--- a/z_spm.h
+++ b/z_spm.h
@@ -66,6 +66,6 @@ void z_spmPrint( const pastix_spm_t *spm );
 
 
 pastix_spm_t *z_spmExpand(const pastix_spm_t *spm);
-void          z_spmDofs2Flat(pastix_spm_t *spm);
+void          z_spmDofExtend(pastix_spm_t *spm);
 
 #endif /* _z_spm_H_ */
diff --git a/z_spm_dof_extend.c b/z_spm_dof_extend.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9e2e0c317bb5ba45d2c48483e3b10f55fc0fdd7
--- /dev/null
+++ b/z_spm_dof_extend.c
@@ -0,0 +1,111 @@
+/**
+ *
+ * @file z_spm_dof_extend.c
+ *
+ *  PaStiX spm routines
+ *  PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest,
+ *  LaBRI, University of Bordeaux 1 and IPB.
+ *
+ * @version 5.1.0
+ * @author Mathieu Faverge
+ * @author Alban Bellot
+ * @date 2015-01-01
+ *
+ * @precisions normal z -> c d s
+ **/
+#include "common.h"
+#include "spm.h"
+#include "z_spm.h"
+
+void
+z_spmDofExtend(pastix_spm_t *spm)
+{
+    pastix_int_t        i, j, k, ii, jj, dofi, dofj, baseval;
+    pastix_int_t       *colptr, *rowptr, *dofs;
+    pastix_complex64_t *newval, *oldval;
+
+    oldval = (pastix_complex64_t*)(spm->values);
+    newval = spm->values = malloc( spm->nnzexp * sizeof(pastix_complex64_t) );
+
+    baseval = spmFindBase( spm );
+    colptr = spm->colptr;
+    rowptr = spm->rowptr;
+    dofs   = spm->dofs;
+
+    switch(spm->fmttype)
+    {
+    case PastixCSC:
+        /**
+         * Loop on col
+         */
+        for(j=0; j<spm->n; j++, colptr++)
+        {
+            dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j];
+
+            /**
+             * Loop on rows
+             */
+            for(k=colptr[0]; k<colptr[1]; k++, rowptr++, oldval++)
+            {
+                i = *rowptr - baseval;
+                dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i];
+
+                for(jj=0; jj<dofj; jj++)
+                {
+                    for(ii=0; ii<dofi; ii++, newval++)
+                    {
+                        *newval = *oldval;
+                    }
+                }
+            }
+        }
+        break;
+    case PastixCSR:
+        /**
+         * Loop on row
+         */
+        for(i=0; i<spm->n; i++, rowptr++)
+        {
+            dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i];
+
+            /**
+             * Loop on cols
+             */
+            for(k=rowptr[0]; k<rowptr[1]; k++, colptr++, oldval++)
+            {
+                j = *colptr - baseval;
+                dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j];
+
+                for(jj=0; jj<dofj; jj++)
+                {
+                    for(ii=0; ii<dofi; ii++, newval++)
+                    {
+                        *newval = *oldval;
+                    }
+                }
+            }
+        }
+        break;
+    case PastixIJV:
+        /**
+         * Loop on coordinates
+         */
+        for(k=0; k<spm->nnz; k++, rowptr++, colptr++, oldval++)
+        {
+            i = *rowptr - baseval;
+            j = *colptr - baseval;
+            dofi = ( spm->dof > 0 ) ? spm->dof : dofs[i+1] - dofs[i];
+            dofj = ( spm->dof > 0 ) ? spm->dof : dofs[j+1] - dofs[j];
+
+            for(jj=0; jj<dofj; jj++)
+            {
+                for(ii=0; ii<dofi; ii++, newval++)
+                {
+                    *newval = *oldval;
+                }
+            }
+        }
+        break;
+    }
+    return;
+}