diff --git a/src/cuMatDs.h b/src/cuMatDs.h
index 7fbc26ecc54b7e0329cb00f0b469c94a648b5202..2ef0b833d9f26e02ea02002c70db8674f3c43fd8 100644
--- a/src/cuMatDs.h
+++ b/src/cuMatDs.h
@@ -50,6 +50,7 @@ struct cuMatDs : Mat
 	static cuMatDs<T>* apply_op(const cuMatDs<T>* in, gm_Op op, cuMatDs<T>* out = nullptr);
 	void transpose();
 	void adjoint();
+	void conjugate();
 	/**
 	 * Normalize the matrix according to its Frobenius norm.
 	 */
diff --git a/src/cuMatDs.hpp b/src/cuMatDs.hpp
index 7e7388833204c9ac0bc2a95e8a5b0179bd52a64c..1f523e2020db1a49d36b9e2466fe3078210b220b 100644
--- a/src/cuMatDs.hpp
+++ b/src/cuMatDs.hpp
@@ -34,6 +34,13 @@ void cuMatDs<T>::adjoint()
 	apply_op(OP_CONJTRANSP);
 }
 
+template<typename T>
+void cuMatDs<T>::conjugate()
+{
+	adjoint();
+	transpose();
+}
+
 template<typename T>
 void cuMatDs<T>::add(cuMatSp<T>& other)
 {
@@ -672,3 +679,9 @@ void cuMatDs<T>::resize(const int32_t nrows, const int32_t ncols)
 		this->data = cu_data;
 	}
 }
+
+template<typename T>
+void cuMatDs<T>::mul(const T& scal)
+{
+	cublasTscal(cuMatDs<T>::handle, ncols*nrows, &scal, data, 1);
+}
diff --git a/src/gm.cpp.in b/src/gm.cpp.in
index 9cb43b5845c633caebb12935f31de256b5567159..7325df5a81d206e6109114ffd88a62663fd59fad 100644
--- a/src/gm.cpp.in
+++ b/src/gm.cpp.in
@@ -24,6 +24,16 @@ extern "C"
 		static_cast<cuMatDs<@GM_SCALAR@>*>(src_mat)->setEyes();
 	}
 
+	__DYNLIB_ATTR__ void gm_DenseMat_transpose_@GM_SCALAR@(gm_DenseMat_t src_mat)
+	{
+		static_cast<cuMatDs<@GM_SCALAR@>*>(src_mat)->transpose();
+	}
+
+	__DYNLIB_ATTR__ void gm_DenseMat_conjugate_@GM_SCALAR@(gm_DenseMat_t src_mat)
+	{
+		static_cast<cuMatDs<@GM_SCALAR@>*>(src_mat)->conjugate();
+	}
+
 	__DYNLIB_ATTR__ void gm_DenseMat_resize_@GM_SCALAR@(gm_DenseMat_t src_mat, const int32_t nrows, const int32_t ncols)
 	{
 		static_cast<cuMatDs<@GM_SCALAR@>*>(src_mat)->resize(nrows, ncols);
@@ -213,6 +223,11 @@ extern "C"
 		return static_cast<cuMatDs<@GM_SCALAR@>*>(a)->mul(*static_cast<cuMatSp<@GM_SCALAR@>*>(b), static_cast<cuMatDs<@GM_SCALAR@>*>(out), op_a, op_b);
 	}
 
+	__DYNLIB_ATTR__ void gm_DenseMat_mul_scalar_@GM_SCALAR@(gm_DenseMat_t a, @GM_SCALAR@* scal)
+	{
+		return static_cast<cuMatDs<@GM_SCALAR@>*>(a)->mul(*scal);
+	}
+
 	__DYNLIB_ATTR__ void gm_MatArray_free_@GM_SCALAR@(gm_MatArray_t array, const bool del_mats)
 	{
 		marr_free<@GM_SCALAR@>(array, del_mats);
diff --git a/src/gm_interf_gen.h.in b/src/gm_interf_gen.h.in
index cf4ff675ffa49cf1ed53ec4ebd4f7655813c9ed5..413a301331a378b7053251641f546f19f2304c2d 100644
--- a/src/gm_interf_gen.h.in
+++ b/src/gm_interf_gen.h.in
@@ -65,6 +65,7 @@ typedef gm_DenseMat_t (*gm_DenseMat_mul_gpu_spm_@GM_SCALAR@_ptr)(gm_DenseMat_t,
  * gm_Op op2: the operation to apply to the second matrix before to multiply.
  */
 typedef gm_DenseMat_t (*gm_DenseMat_mul_gpu_spm_ext_@GM_SCALAR@_ptr)(gm_DenseMat_t, gm_SparseMat_t, gm_DenseMat_t output, gm_Op, gm_Op);
+typedef void (*gm_DenseMat_mul_scalar_@GM_SCALAR@_ptr)(gm_DenseMat_t, const @GM_SCALAR@* scalar);
 /**
  * Performs power_iteration algorithm over the argument dense matrix.
  */
@@ -76,6 +77,9 @@ typedef void (*gm_DenseMat_resize_@GM_SCALAR@_ptr)(gm_DenseMat_t, const int32_t
 typedef void (*gm_DenseMat_setones_@GM_SCALAR@_ptr)(gm_DenseMat_t);
 typedef void (*gm_DenseMat_setzeros_@GM_SCALAR@_ptr)(gm_DenseMat_t);
 typedef void (*gm_DenseMat_seteyes_@GM_SCALAR@_ptr)(gm_DenseMat_t);
+typedef void (*gm_DenseMat_transpose_@GM_SCALAR@_ptr)(gm_DenseMat_t);
+typedef void (*gm_DenseMat_conjugate_@GM_SCALAR@_ptr)(gm_DenseMat_t);
+typedef void (*gm_DenseMat_adjoint_@GM_SCALAR@_ptr)(gm_DenseMat_t);
 
 struct gm_DenseMatFunc_@GM_SCALAR@
 {
@@ -106,6 +110,7 @@ struct gm_DenseMatFunc_@GM_SCALAR@
 	gm_DenseMat_mul_gpu_dsm_tocpu_ext_@GM_SCALAR@_ptr mul_gpu_dsm_tocpu_ext;
 	gm_DenseMat_mul_gpu_spm_@GM_SCALAR@_ptr mul_gpu_spm;
 	gm_DenseMat_mul_gpu_spm_ext_@GM_SCALAR@_ptr mul_gpu_spm_ext;
+	gm_DenseMat_mul_scalar_@GM_SCALAR@_ptr mul_scalar;
 	gm_DenseMat_power_iteration_@GM_SCALAR@_ptr power_iteration;
 	gm_DenseMat_trace_@GM_SCALAR@_ptr trace;
 	gm_DenseMat_max_@GM_SCALAR@_ptr max;
@@ -114,6 +119,8 @@ struct gm_DenseMatFunc_@GM_SCALAR@
 	gm_DenseMat_setones_@GM_SCALAR@_ptr setones;
 	gm_DenseMat_setzeros_@GM_SCALAR@_ptr setzeros;
 	gm_DenseMat_seteyes_@GM_SCALAR@_ptr seteyes;
+	gm_DenseMat_transpose_@GM_SCALAR@_ptr transpose;
+	gm_DenseMat_conjugate_@GM_SCALAR@_ptr conjugate;
 };
 
 /** MatArray function pointers ********************************************************************/
diff --git a/src/gm_interf_gen.hpp.in b/src/gm_interf_gen.hpp.in
index f4974cfcf0fa560b2c8e3b60fb92d7ee59c18de0..45fed1527042e497a93c271c657b647abe44961e 100644
--- a/src/gm_interf_gen.hpp.in
+++ b/src/gm_interf_gen.hpp.in
@@ -37,6 +37,7 @@ void load_dsm_funcs_@GM_SCALAR@(void* gm_handle, gm_DenseMatFunc_@GM_SCALAR@ *ds
 	 dsm_funcs->mul_gpu_dsm_tocpu_ext = (gm_DenseMat_mul_gpu_dsm_tocpu_ext_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle,"gm_DenseMat_mul_gpu_dsm_tocpu_ext_@GM_SCALAR@");
 	 dsm_funcs->mul_gpu_spm = (gm_DenseMat_mul_gpu_spm_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle,"gm_DenseMat_mul_gpu_spm_@GM_SCALAR@");
 	 dsm_funcs->mul_gpu_spm_ext = (gm_DenseMat_mul_gpu_spm_ext_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle,"gm_DenseMat_mul_gpu_spm_ext_@GM_SCALAR@");
+	 dsm_funcs->mul_scalar = (gm_DenseMat_mul_scalar_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_mul_scalar_@GM_SCALAR@");
 	 dsm_funcs->power_iteration = (gm_DenseMat_power_iteration_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle,"gm_DenseMat_power_iteration_@GM_SCALAR@");
 	 dsm_funcs->norm_spectral = (gm_DenseMat_norm_spectral_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle,"gm_DenseMat_norm_spectral_@GM_SCALAR@");
 	 dsm_funcs->trace = (gm_DenseMat_trace_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_trace_@GM_SCALAR@");
@@ -46,6 +47,9 @@ void load_dsm_funcs_@GM_SCALAR@(void* gm_handle, gm_DenseMatFunc_@GM_SCALAR@ *ds
 	 dsm_funcs->setones = (gm_DenseMat_setones_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_setones_@GM_SCALAR@");
 	 dsm_funcs->setzeros = (gm_DenseMat_setzeros_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_setzeros_@GM_SCALAR@");
 	 dsm_funcs->seteyes = (gm_DenseMat_seteyes_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_seteyes_@GM_SCALAR@");
+	 dsm_funcs->transpose = (gm_DenseMat_transpose_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_transpose_@GM_SCALAR@");
+	 dsm_funcs->conjugate = (gm_DenseMat_conjugate_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_conjugate_@GM_SCALAR@");
+	 dsm_funcs->adjoint = (gm_DenseMat_adjoint_@GM_SCALAR@_ptr) gm_load_func_check_err(gm_handle, "gm_DenseMat_adjoint_@GM_SCALAR@");
 }
 
 void load_marr_funcs_@GM_SCALAR@(void* gm_handle, gm_MatArrayFunc_@GM_SCALAR@ *marr_funcs)