diff --git a/misc/test/CMakeLists.txt b/misc/test/CMakeLists.txt
index 29f447d44a93b3c45b81deda9a59a9e064510f35..995499548a5bbcc75de0f16412b0a3eb2794a0e2 100755
--- a/misc/test/CMakeLists.txt
+++ b/misc/test/CMakeLists.txt
@@ -156,7 +156,7 @@ endif()
 
 if(NOT NOCPPTESTS)
 	foreach(TEST_FPP float double)
-		foreach(FILE faust_mult faust_mult_cplx test_Vect_min test_MatDense_get_row test_MatDense_lower_upper_tri test_MatDense_nonzeros_indices test_Transform_move test_MatDense_min faust_transform_omp_mul faust_pruneout faust_transform_optimize_storage faust_transform_optimize)
+		foreach(FILE faust_mult faust_mult_cplx test_Vect_min test_MatDense_get_row test_MatDense_lower_upper_tri test_MatDense_nonzeros_indices test_Transform_move test_MatDense_min faust_transform_omp_mul faust_pruneout faust_transform_optimize_storage faust_transform_optimize faust_prox_blockdiag)
 			set(TEST_BIN_FILE ${FILE}_${TEST_FPP})
 			set(TEST_FILE_CPP ${TEST_BIN_FILE}.cpp)
 			message(STATUS ${TEST_FILE_CPP})
diff --git a/misc/test/src/C++/unit/faust_prox_blockdiag.cpp.in b/misc/test/src/C++/unit/faust_prox_blockdiag.cpp.in
new file mode 100644
index 0000000000000000000000000000000000000000..ecbceb0a40f3d400095ed0495378bf3c46e9dd3e
--- /dev/null
+++ b/misc/test/src/C++/unit/faust_prox_blockdiag.cpp.in
@@ -0,0 +1,107 @@
+/****************************************************************************/
+/*                              Description:                                */
+/* unitary test for testing multiplication by faust with real  scalar       */
+/*                                                                          */
+/*  For more information on the FAuST Project, please visit the website     */
+/*  of the project : <http://faust.inria.fr>                         */
+/*                                                                          */
+/*                              License:                                    */
+/*  Copyright (2016):   Nicolas Bellot, Adrien Leman, Thomas Gautrais,      */
+/*                      Luc Le Magoarou, Remi Gribonval                     */
+/*                      INRIA Rennes, FRANCE                                */
+/*                      http://www.inria.fr/                                */
+/*                                                                          */
+/*  The FAuST Toolbox is distributed under the terms of the GNU Affero      */
+/*  General Public License.                                                 */
+/*  This program is free software: you can redistribute it and/or modify    */
+/*  it under the terms of the GNU Affero General Public License as          */
+/*  published by the Free Software Foundation.                              */
+/*                                                                          */
+/*  This program is distributed in the hope that it will be useful, but     */
+/*  WITHOUT ANY WARRANTY; without even the implied warranty of              */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                    */
+/*  See the GNU Affero General Public License for more details.             */
+/*                                                                          */
+/*  You should have received a copy of the GNU Affero General Public        */
+/*  License along with this program.                                        */
+/*  If not, see <http://www.gnu.org/licenses/>.                             */
+/*                                                                          */
+/*                             Contacts:                                    */
+/*      Nicolas Bellot  : nicolas.bellot@inria.fr                           */
+/*      Adrien Leman    : adrien.leman@inria.fr                             */
+/*      Thomas Gautrais : thomas.gautrais@inria.fr                          */
+/*      Luc Le Magoarou : luc.le-magoarou@inria.fr                          */
+/*      Remi Gribonval  : remi.gribonval@inria.fr                           */
+/*                                                                          */
+/*                              References:                                 */
+/*  [1] Le Magoarou L. and Gribonval R., "Flexible multi-layer sparse       */
+/*  approximations of matrices and applications", Journal of Selected       */
+/*  Topics in Signal Processing, 2016.                                      */
+/*  <https://hal.archives-ouvertes.fr/hal-01167948v1>                       */
+/****************************************************************************/
+#include "faust_MatSparse.h"
+#include "faust_HierarchicalFact.h"
+#include "faust_Timer.h"
+#include "faust_Transform.h"
+#include <string>
+#include <sstream>
+#include "faust_BlasHandle.h"
+#include "faust_SpBlasHandle.h"
+
+
+#include <iostream>
+#include <iomanip>
+
+/** \brief unitary test for testing multiplication by faust									
+*/
+
+typedef @TEST_FPP@ FPP;
+
+
+//using namespace Faust;
+using namespace std;
+
+int main(int argc, char* argv[])
+{
+	if (typeid(FPP) == typeid(double))
+  	{
+		cout<<"floating point precision == double"<<endl;
+  	}
+
+  	if (typeid(FPP) == typeid(float))
+  	{
+		cout<<"floating point precision == float"<<endl;
+  	}
+
+	int dim1 = 38;
+	int dim2 = 42;
+
+	Faust::MatDense<FPP,Cpu> * M = Faust::MatDense<FPP,Cpu>::randMat(dim1, dim2);
+
+	Faust::MatDense<FPP,Cpu> M_copy = *M;
+
+	std::vector<faust_unsigned_int> m_vec = {5u, 12u, 25u, 38u};
+	std::vector<faust_unsigned_int> n_vec = {9u, 18u, 32u, 42u};
+
+	Faust::prox_blockdiag(M_copy, m_vec, n_vec);
+	cout << "====================== M:" << endl;
+	for(faust_unsigned_int i = 0; i < M->getNbRow(); i++)
+	{
+		for(faust_unsigned_int j = 0; j < M->getNbCol(); j++)
+		{
+			printf("%3.2f ", (*M)(i,j));
+		}
+		printf("\n");
+	}
+	cout << "====================== M_:"<< endl;
+	for(faust_unsigned_int i = 0; i < M->getNbRow(); i++)
+	{
+		for(faust_unsigned_int j = 0; j < M->getNbCol(); j++)
+		{
+			printf("%3.2f ", M_copy(i,j));
+			assert(M_copy(i,j) == 0.0 || M_copy(i,j) == (*M)(i,j));
+		}
+		printf("\n");
+	}
+	return 0;
+}
diff --git a/src/faust_linear_operator/CPU/faust_MatDense.h b/src/faust_linear_operator/CPU/faust_MatDense.h
index 33662da647f7e6c606b57d34d47d5055b4a88287..f153294880eeea81c4df00bb68e5e6d10ef77be7 100644
--- a/src/faust_linear_operator/CPU/faust_MatDense.h
+++ b/src/faust_linear_operator/CPU/faust_MatDense.h
@@ -417,6 +417,10 @@ void spgemm(const Faust::MatSparse<FPP,Cpu> & A,const Faust::MatDense<FPP,Cpu> &
 		Faust::MatDense<FPP,Cpu>* get_rows(faust_unsigned_int start_row_id, faust_unsigned_int num_rows) const;
         Faust::MatDense<FPP,Cpu>* get_rows(faust_unsigned_int* row_ids, faust_unsigned_int n) const;
 
+		Faust::MatDense<FPP,Cpu> get_block(faust_unsigned_int i, faust_unsigned_int j, faust_unsigned_int nrows, faust_unsigned_int ncols);
+
+		void set_block(faust_unsigned_int i, faust_unsigned_int j, Faust::MatDense<FPP,Cpu> & block);
+
 		FPP min_coeff() const;
 		Faust::Vect<FPP,Cpu> rowwise_min() const;
 		Faust::Vect<FPP,Cpu> rowwise_min(int* col_indices) const;
diff --git a/src/faust_linear_operator/CPU/faust_MatDense.hpp b/src/faust_linear_operator/CPU/faust_MatDense.hpp
index cb21c038d5997ca3b7e80b468e2700da84f935e0..dc6d208300e95afed098285ecc1f060fd6d482e5 100644
--- a/src/faust_linear_operator/CPU/faust_MatDense.hpp
+++ b/src/faust_linear_operator/CPU/faust_MatDense.hpp
@@ -1136,6 +1136,23 @@ Faust::MatDense<FPP,Cpu>* Faust::MatDense<FPP,Cpu>::get_rows(faust_unsigned_int*
 	return rows;
 }
 
+template<typename FPP>
+Faust::MatDense<FPP,Cpu> Faust::MatDense<FPP,Cpu>::get_block(faust_unsigned_int i, faust_unsigned_int j, faust_unsigned_int nrows, faust_unsigned_int ncols)
+{
+	Faust::MatDense<FPP,Cpu> block_mat(nrows, ncols);
+	block_mat.mat.block(0,0, nrows, ncols) = mat.block(i, j, nrows, ncols);
+	return block_mat;
+}
+
+template<typename FPP>
+void Faust::MatDense<FPP,Cpu>::set_block(faust_unsigned_int i, faust_unsigned_int j, Faust::MatDense<FPP,Cpu> & block_mat)
+{
+	faust_unsigned_int nrows, ncols;
+	nrows = block_mat.getNbRow();
+	ncols = block_mat.getNbCol();
+	mat.block(i, j, nrows, ncols) = block_mat.mat.block(0, 0, nrows, ncols);
+}
+
 template<typename FPP>
 FPP Faust::MatDense<FPP,Cpu>::min_coeff() const
 {
diff --git a/src/faust_linear_operator/CPU/faust_prox.h b/src/faust_linear_operator/CPU/faust_prox.h
index ef5c96f4987f2de77165f1d511e131f4914591d7..0e6d79169da21d8717b587b14fac79f59745e3d9 100644
--- a/src/faust_linear_operator/CPU/faust_prox.h
+++ b/src/faust_linear_operator/CPU/faust_prox.h
@@ -79,6 +79,9 @@ namespace Faust {
 		void prox_normlin(Faust::MatDense<FPP,Cpu> & M,FPP2 s, const bool normalized=false, const bool pos=false);
 	//    template<typename FPP>
 	//    void prox_blkdiag(Faust::MatDense<FPP,Cpu> & M,faust_unsigned_int k);
+	template<typename FPP>
+		void prox_blockdiag(Faust::MatDense<FPP,Cpu> & M, std::vector<faust_unsigned_int>& m_vec, std::vector<faust_unsigned_int>& n_vec, const bool normalized = false, const bool pos = false);
+
 	template<typename FPP> void pre_prox_pos(MatDense<FPP,Cpu> & M);
 	template<typename FPP> void prox_hankel(Faust::MatDense<FPP, Cpu> & M);
 	template<typename FPP> void prox_toeplitz(Faust::MatDense<FPP, Cpu> & M);
diff --git a/src/faust_linear_operator/CPU/faust_prox.hpp b/src/faust_linear_operator/CPU/faust_prox.hpp
index c15cc9a695e2903f74382a228f3dcee92c1cf481..8b7a59e907a00dc990c5b0205ef26b5391ba1707 100644
--- a/src/faust_linear_operator/CPU/faust_prox.hpp
+++ b/src/faust_linear_operator/CPU/faust_prox.hpp
@@ -240,6 +240,36 @@ void Faust::prox_normlin(Faust::MatDense<FPP,Cpu> & M,FPP2 s, const bool normali
 	M.transpose();
 }
 
+template<typename FPP>
+void Faust::prox_blockdiag(Faust::MatDense<FPP,Cpu> & M, std::vector<faust_unsigned_int> & m_vec, std::vector<faust_unsigned_int>& n_vec, const bool normalized /* default to false */, const bool pos)
+{
+//        if(M.shape != self.shape): raise ValueError('The dimension of the '
+//                                                   'projector and matrix must '
+//                                                   'agree.')
+//        M_ = np.zeros(M.shape)
+//        m_ = 0
+//        n_ = 0
+//        for i,(m,n) in enumerate(zip(self.m_vec, self.n_vec)):
+//            print("i=", i, "m=", m, "n=", n)
+//            M_[m_:m,n_:n] = M[m_:m,n_:n]
+//            m_ = m
+//            n_ = n
+//        return M_
+//
+	Faust::MatDense<FPP,Cpu> M_(M.getNbRow(), M.getNbCol());
+	M_.setZeros();
+	faust_unsigned_int m_ = 0, n_ = 0;
+	for(faust_unsigned_int i=0; i< m_vec.size();i++)
+	{
+		Faust::MatDense<FPP,Cpu> block_mat = M.get_block(m_, n_, m_vec[i]-m_, n_vec[i]-n_);
+		M_.set_block(m_, n_, block_mat);
+		m_ = m_vec[i];
+		n_ = n_vec[i];
+	}
+	M = M_;
+}
+
+
 template<typename FPP>
 void
 Faust::pre_prox_pos(MatDense<FPP,Cpu> & M)