diff --git a/compute/CMakeLists.txt b/compute/CMakeLists.txt
index 0fa6dfb80f8ac02d321a1ee1b11aa0ad7e4baeaf..91b17ab5d57bc2d40fd26e56587d311e78802a62 100644
--- a/compute/CMakeLists.txt
+++ b/compute/CMakeLists.txt
@@ -126,6 +126,7 @@ set(ZSRC
     pzunglq.c
     pzunglqrh.c
     pzungqr.c
+    pzungqr_param.c
     pzungqrrh.c
     pzunmlq.c
     pzunmlqrh.c
@@ -169,8 +170,10 @@ set(ZSRC
     ztrtri.c
     zunglq.c
     zungqr.c
+    zungqr_param.c
     zunmlq.c
     zunmqr.c
+    zunmqr_param.c
     ztpgqrt.c
     ztpqrt.c
     ##################
diff --git a/compute/pzgeqrf_param.c b/compute/pzgeqrf_param.c
index e6466a517664fc0baae61e4718c247687e2e98bc..4f880c95cb5bf1e86ffa9bfba49429d016d49e81 100644
--- a/compute/pzgeqrf_param.c
+++ b/compute/pzgeqrf_param.c
@@ -51,7 +51,7 @@ void morse_pzgeqrf_param( const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_de
     size_t ws_host = 0;
     MORSE_desc_t *D = NULL;
 
-    int k, m, n, i, j, p;
+    int k, m, n, i, p;
     int K, M, RD;
     int ldap, ldam, ldaMRD;
     int tempkmin, tempkn, tempMm, tempnn, tempmm, tempMRDm;
@@ -153,8 +153,8 @@ void morse_pzgeqrf_param( const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_de
         /* Setting the order of the tiles */
         libhqr_treewalk(qrtree, k, tiles);
 
-        for (j = k; j < A->mt-1; j++) {
-            m = tiles[j];
+        for (i = k; i < A->mt-1; i++) {
+            m = tiles[i];
             p = qrtree->currpiv(qrtree, k, m);
 
             tempmm = m == A->mt-1 ? A->m-m*A->mb : A->mb;
diff --git a/compute/pzungqr_param.c b/compute/pzungqr_param.c
new file mode 100644
index 0000000000000000000000000000000000000000..d16098dc98e13e2b0efa59b7a62305dc94fa0243
--- /dev/null
+++ b/compute/pzungqr_param.c
@@ -0,0 +1,176 @@
+/**
+ *
+ * @copyright (c) 2009-2014 The University of Tennessee and The University
+ *                          of Tennessee Research Foundation.
+ *                          All rights reserved.
+ * @copyright (c) 2012-2016 Inria. All rights reserved.
+ * @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
+ *
+ **/
+
+/**
+ *
+ * @file pzungqr_param.c
+ *
+ *  MORSE auxiliary routines
+ *  MORSE is a software package provided by Univ. of Tennessee,
+ *  Univ. of California Berkeley and Univ. of Colorado Denver
+ *
+ * @version 2.5.0
+ * @comment This file has been automatically generated
+ *          from Plasma 2.5.0 for MORSE 1.0.0
+ * @author Hatem Ltaief
+ * @author Jakub Kurzak
+ * @author Mathieu Faverge
+ * @author Emmanuel Agullo
+ * @author Cedric Castagnede
+ * @date 2010-11-15
+ * @precisions normal z -> s d c
+ *
+ **/
+#include "control/common.h"
+
+#define A(m,n) A,  m,  n
+#define Q(m,n) Q,  m,  n
+#define T(m,n) T,  m,  n
+#if defined(CHAMELEON_COPY_DIAG)
+#define DIAG(k) DIAG, k, 0
+#else
+#define DIAG(k) A, k, k
+#endif
+
+/**
+ *  Parallel construction of Q using tile V (application to identity) - dynamic scheduling
+ */
+void morse_pzungqr_param(const libhqr_tree_t *qrtree,
+                   MORSE_desc_t *A, MORSE_desc_t *Q, MORSE_desc_t *T,
+                   MORSE_sequence_t *sequence, MORSE_request_t *request)
+{
+    MORSE_context_t *morse;
+    MORSE_option_t options;
+    size_t ws_worker = 0;
+    size_t ws_host = 0;
+    MORSE_desc_t *DIAG = NULL;
+
+    int k, m, n, i, p;
+    int ldak, ldqk, ldam, ldqm;
+    int tempmm, tempnn, tempkmin, tempkm;
+    int tempAkm, tempAkn;
+    int ib, minMT;
+    int *tiles;
+
+    morse = morse_context_self();
+    if (sequence->status != MORSE_SUCCESS)
+        return;
+    RUNTIME_options_init(&options, morse, sequence, request);
+
+    ib = MORSE_IB;
+
+    if (A->m > A->n) {
+        minMT = A->nt;
+    } else {
+        minMT = A->mt;
+    }
+
+    /*
+     * zunmqr = A->nb * ib
+     * ztsmqr = A->nb * ib
+     */
+    ws_worker = A->nb * ib;
+
+    /* Allocation of temporary (scratch) working space */
+#if defined(CHAMELEON_USE_CUDA)
+    /* Worker space
+     *
+     * zunmqr = A->nb * ib
+     * ztsmqr = 2 * A->nb * ib
+     */
+    ws_worker = chameleon_max( ws_worker, ib * A->nb * 2 );
+#endif
+
+    /* Initialisation of tiles */
+
+    tiles = (int*)malloc((qrtree->mt)*sizeof(int));
+    memset( tiles, 0, (qrtree->mt)*sizeof(int) );
+
+    ws_worker *= sizeof(MORSE_Complex64_t);
+    ws_host   *= sizeof(MORSE_Complex64_t);
+
+    RUNTIME_options_ws_alloc( &options, ws_worker, ws_host );
+
+#if defined(CHAMELEON_COPY_DIAG)
+    /* necessary to avoid dependencies between tasks regarding the diag tile */
+    DIAG = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
+    morse_zdesc_alloc_diag(*DIAG, A->mb, A->nb, minMT*A->mb, A->nb, 0, 0, minMT*A->mb, A->nb, A->p, A->q);
+#endif
+
+    for (k = minMT-1; k >= 0; k--) {
+        RUNTIME_iteration_push(morse, k);
+
+        tempAkm  = k == A->mt-1 ? A->m-k*A->mb : A->mb;
+        tempAkn  = k == A->nt-1 ? A->n-k*A->nb : A->nb;
+        tempkmin = chameleon_min( tempAkn, tempAkm );
+        tempkm   = k == Q->mt-1 ? Q->m-k*Q->mb : Q->mb;
+        ldak = BLKLDD(A, k);
+        ldqk = BLKLDD(Q, k);
+
+        /* Setting the order of tiles */
+        libhqr_treewalk(qrtree, k, tiles);
+
+        for (i = Q->mt - 1; i > k; i--) {
+            m = tiles[i];
+            p = qrtree->currpiv(qrtree, k, m);
+
+            tempmm = m == Q->mt-1 ? Q->m-m*Q->mb : Q->mb;
+            ldam = BLKLDD(A, m);
+            ldqm = BLKLDD(Q, m);
+            for (n = k; n < Q->nt; n++) {
+                tempnn = n == Q->nt-1 ? Q->n-n*Q->nb : Q->nb;
+                MORSE_TASK_ztsmqr(
+                    &options,
+                    MorseLeft, MorseNoTrans,
+                    Q->mb, tempnn, tempmm, tempnn, tempAkn, ib, T->nb,
+                    Q(k, n), ldqk,
+                    Q(m, n), ldqm,
+                    A(m, k), ldam,
+                    T(m, k), T->mb);
+            }
+        }
+#if defined(CHAMELEON_COPY_DIAG)
+        MORSE_TASK_zlacpy(
+            &options,
+            MorseLower, tempkm, tempkmin, A->nb,
+            A(k, k), ldak,
+            DIAG(k), ldak );
+#if defined(CHAMELEON_USE_CUDA)
+        MORSE_TASK_zlaset(
+            &options,
+            MorseUpper, tempkm, tempkmin,
+            0., 1.,
+            DIAG(k), ldak );
+#endif
+#endif
+        for (n = k; n < Q->nt; n++) {
+            tempnn = n == Q->nt-1 ? Q->n-n*Q->nb : Q->nb;
+            MORSE_TASK_zunmqr(
+                &options,
+                MorseLeft, MorseNoTrans,
+                tempkm, tempnn, tempkmin, ib, T->nb,
+                DIAG(k), ldak,
+                T(k, k), T->mb,
+                Q(k, n), ldqk);
+        }
+
+        RUNTIME_iteration_pop(morse);
+    }
+    RUNTIME_options_ws_free(&options);
+    RUNTIME_options_finalize(&options, morse);
+    MORSE_TASK_dataflush_all();
+
+#if defined(CHAMELEON_COPY_DIAG)
+    MORSE_Sequence_Wait(sequence);
+    morse_desc_mat_free(DIAG);
+    free(DIAG);
+#endif
+    (void)DIAG;
+}
diff --git a/compute/pzunmqr_param.c b/compute/pzunmqr_param.c
new file mode 100644
index 0000000000000000000000000000000000000000..f18a979a3fafafd4b62564b9c20e3adbea3a6a36
--- /dev/null
+++ b/compute/pzunmqr_param.c
@@ -0,0 +1,356 @@
+/**
+ *
+ * @copyright (c) 2009-2014 The University of Tennessee and The University
+ *                          of Tennessee Research Foundation.
+ *                          All rights reserved.
+ * @copyright (c) 2012-2016 Inria. All rights reserved.
+ * @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
+ *
+ **/
+
+/**
+ *
+ * @file pzunmqr.c
+ *
+ *  MORSE auxiliary routines
+ *  MORSE is a software package provided by Univ. of Tennessee,
+ *  Univ. of California Berkeley and Univ. of Colorado Denver
+ *
+ * @version 2.5.0
+ * @comment This file has been automatically generated
+ *          from Plasma 2.5.0 for MORSE 1.0.0
+ * @author Hatem Ltaief
+ * @author Jakub Kurzak
+ * @author Azzam Haidar
+ * @author Mathieu Faverge
+ * @author Emmanuel Agullo
+ * @author Cedric Castagnede
+ * @date 2010-11-15
+ * @precisions normal z -> s d c
+ *
+ **/
+#include "control/common.h"
+
+#define A(m,n) A,  m,  n
+#define B(m,n) B,  m,  n
+#define T(m,n) T,  m,  n
+#if defined(CHAMELEON_COPY_DIAG)
+#define DIAG(k) DIAG, k, 0
+#else
+#define DIAG(k) A, k, k
+#endif
+
+/**
+ *  Parallel application of Q using tile V - QR factorization - dynamic scheduling
+ */
+void morse_pzunmqr_param(const libhqr_tree_t *qrtree,
+                   MORSE_enum side, MORSE_enum trans,
+                   MORSE_desc_t *A, MORSE_desc_t *B, MORSE_desc_t *T,
+                   MORSE_sequence_t *sequence, MORSE_request_t *request)
+{
+    MORSE_context_t *morse;
+    MORSE_option_t options;
+    size_t ws_worker = 0;
+    size_t ws_host = 0;
+    MORSE_desc_t *DIAG = NULL;
+
+    int k, m, n, i;
+    int ldak, ldbk, ldam, ldan, ldbm;
+    int tempkm, tempnn, tempkmin, tempmm, tempkn;
+    int ib, minMT, minM;
+    int *tiles;
+
+    morse = morse_context_self();
+    if (sequence->status != MORSE_SUCCESS)
+        return;
+    RUNTIME_options_init(&options, morse, sequence, request);
+
+    ib = MORSE_IB;
+
+    if (A->m > A->n) {
+        minM  = A->n;
+        minMT = A->nt;
+    } else {
+        minM  = A->m;
+        minMT = A->mt;
+    }
+
+    /*
+     * zunmqr = A->nb * ib
+     * ztsmqr = A->nb * ib
+     */
+    ws_worker = A->nb * ib;
+
+#if defined(CHAMELEON_USE_CUDA)
+    /* Worker space
+     *
+     * zunmqr = A->nb * ib
+     * ztsmqr = 2 * A->nb * ib
+     */
+    ws_worker = chameleon_max( ws_worker, ib * A->nb * 2 );
+#endif
+
+    /* Initialisation of tiles */
+
+    tiles = (int*)malloc((qrtree->mt)*sizeof(int));
+    memset( tiles, 0, (qrtree->mt)*sizeof(int) );
+
+    ws_worker *= sizeof(MORSE_Complex64_t);
+    ws_host   *= sizeof(MORSE_Complex64_t);
+
+    RUNTIME_options_ws_alloc( &options, ws_worker, ws_host );
+
+    /* necessary to avoid dependencies between tasks regarding the diag tile */
+#if defined(CHAMELEON_COPY_DIAG)
+    DIAG = (MORSE_desc_t*)malloc(sizeof(MORSE_desc_t));
+    morse_zdesc_alloc_diag(*DIAG, A->mb, A->nb, minMT*A->nb, A->nb, 0, 0, minMT*A->nb, A->nb, A->p, A->q);
+#endif
+
+    if (side == MorseLeft ) {
+        if (trans == MorseConjTrans) {
+            /*
+             *  MorseLeft / MorseConjTrans
+             */
+            for (k = 0; k < minMT; k++) {
+                RUNTIME_iteration_push(morse, k);
+
+                tempkm   = k == B->mt-1 ? B->m-k*B->mb : B->mb;
+                tempkmin = k == minMT-1 ? minM-k*A->nb : A->nb;
+                ldak = BLKLDD(A, k);
+                ldbk = BLKLDD(B, k);
+#if defined(CHAMELEON_COPY_DIAG)
+                MORSE_TASK_zlacpy(
+                    &options,
+                    MorseLower, tempkm, tempkmin, A->nb,
+                    A(k, k), ldak,
+                    DIAG(k), ldak );
+#if defined(CHAMELEON_USE_CUDA)
+                MORSE_TASK_zlaset(
+                    &options,
+                    MorseUpper, tempkm, tempkmin,
+                    0., 1.,
+                    DIAG(k), ldak );
+#endif
+#endif
+                for (n = 0; n < B->nt; n++) {
+                    tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                    MORSE_TASK_zunmqr(
+                        &options,
+                        side, trans,
+                        tempkm, tempnn, tempkmin, ib, T->nb,
+                        DIAG(k), ldak,
+                        T(k, k), T->mb,
+                        B(k, n), ldbk);
+                }
+
+                /* Setting the order of the tiles*/
+                libhqr_treewalk(qrtree, k, tiles);
+
+                for (i = k+1; i < B->mt; i++) {
+                    m = tiles[i];
+                    p = qrtree->currpiv(qrtree, k, m);
+
+                    tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                    ldam = BLKLDD(A, m);
+                    ldbm = BLKLDD(B, m);
+                    ldbp = BLKLDD(B, p);
+                    for (n = 0; n < B->nt; n++) {
+                        tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                        MORSE_TASK_ztsmqr(
+                            &options,
+                            side, trans,
+                            B->mb, tempnn, tempmm, tempnn, tempkmin, ib, T->nb,
+                            B(p, n), ldbp,
+                            B(m, n), ldbm,
+                            A(m, k), ldam,
+                            T(m, k), T->mb);
+                    }
+                }
+
+                RUNTIME_iteration_pop(morse);
+            }
+        }
+        /*
+         *  MorseLeft / MorseNoTrans
+         */
+        else {
+            for (k = minMT-1; k >= 0; k--) {
+                RUNTIME_iteration_push(morse, k);
+
+                tempkm = k == B->mt-1 ? B->m-k*B->mb : B->mb;
+                tempkmin = k == minMT-1 ? minM-k*A->nb : A->nb;
+                ldak = BLKLDD(A, k);
+                ldbk = BLKLDD(B, k);
+                for (i = B->mt-1; i > k; i--) {
+                    m = tiles[i];
+                    p = qrtree->currpiv(qrtree, k, m);
+
+                    tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                    ldam = BLKLDD(A, m);
+                    ldbm = BLKLDD(B, m);
+                    ldbp = BLKLDD(B, p);
+                    for (n = 0; n < B->nt; n++) {
+                        tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                        MORSE_TASK_ztsmqr(
+                            &options,
+                            side, trans,
+                            B->mb, tempnn, tempmm, tempnn, tempkmin, ib, T->nb,
+                            B(p, n), ldbp,
+                            B(m, n), ldbm,
+                            A(m, k), ldam,
+                            T(m, k), T->mb);
+                    }
+                }
+#if defined(CHAMELEON_COPY_DIAG)
+                MORSE_TASK_zlacpy(
+                    &options,
+                    MorseLower, tempkm, tempkmin, A->nb,
+                    A(k, k), ldak,
+                    DIAG(k), ldak );
+#if defined(CHAMELEON_USE_CUDA)
+                MORSE_TASK_zlaset(
+                    &options,
+                    MorseUpper, tempkm, tempkmin,
+                    0., 1.,
+                    DIAG(k), ldak );
+#endif
+#endif
+                for (n = 0; n < B->nt; n++) {
+                    tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                    MORSE_TASK_zunmqr(
+                        &options,
+                        side, trans,
+                        tempkm, tempnn, tempkmin, ib, T->nb,
+                        DIAG(k), ldak,
+                        T(k, k), T->mb,
+                        B(k, n), ldbk);
+                }
+
+                RUNTIME_iteration_pop(morse);
+            }
+        }
+    }
+    /*
+     *  MorseRight / MorseConjTrans
+     */
+    else {
+        if (trans == MorseConjTrans) {
+            for (k = minMT-1; k >= 0; k--) {
+                RUNTIME_iteration_push(morse, k);
+
+                tempkn = k == B->nt-1 ? B->n-k*B->nb : B->nb;
+                tempkmin = k == minMT-1 ? minM-k*A->nb : A->nb;
+                ldak = BLKLDD(A, k);
+                ldbk = BLKLDD(B, k);
+                for (n = B->nt-1; n > k; n--) {
+                    tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                    ldan = BLKLDD(A, n);
+                    for (m = 0; m < B->mt; m++) {
+                        tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                        ldbm = BLKLDD(B, m);
+                        MORSE_TASK_ztsmqr(
+                            &options,
+                            side, trans,
+                            tempmm, B->nb, tempmm, tempnn, tempkmin, ib, T->nb,
+                            B(m, k), ldbm,
+                            B(m, n), ldbm,
+                            A(n, k), ldan,
+                            T(n, k), T->mb);
+                    }
+                }
+#if defined(CHAMELEON_COPY_DIAG)
+                MORSE_TASK_zlacpy(
+                    &options,
+                    MorseLower, tempkn, tempkmin, A->nb,
+                    A(k, k), ldak,
+                    DIAG(k), ldak );
+#if defined(CHAMELEON_USE_CUDA)
+                MORSE_TASK_zlaset(
+                    &options,
+                    MorseUpper, tempkn, tempkmin,
+                    0., 1.,
+                    DIAG(k), ldak );
+#endif
+#endif
+                for (m = 0; m < B->mt; m++) {
+                    tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                    ldbm = BLKLDD(B, m);
+                    MORSE_TASK_zunmqr(
+                        &options,
+                        side, trans,
+                        tempmm, tempkn, tempkmin, ib, T->nb,
+                        DIAG(k), ldak,
+                        T(k, k), T->mb,
+                        B(m, k), ldbm);
+                }
+
+                RUNTIME_iteration_pop(morse);
+            }
+        }
+        /*
+         *  MorseRight / MorseNoTrans
+         */
+        else {
+            for (k = 0; k < minMT; k++) {
+                RUNTIME_iteration_push(morse, k);
+
+                tempkn   = k == B->nt-1 ? B->n-k*B->nb : B->nb;
+                tempkmin = k == minMT-1 ? minM-k*A->nb : A->nb;
+                ldak = BLKLDD(A, k);
+#if defined(CHAMELEON_COPY_DIAG)
+                MORSE_TASK_zlacpy(
+                    &options,
+                    MorseLower, tempkn, tempkmin, A->nb,
+                    A(k, k), ldak,
+                    DIAG(k), ldak );
+#if defined(CHAMELEON_USE_CUDA)
+                MORSE_TASK_zlaset(
+                    &options,
+                    MorseUpper, tempkn, tempkmin,
+                    0., 1.,
+                    DIAG(k), ldak );
+#endif
+#endif
+                for (m = 0; m < B->mt; m++) {
+                    tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                    ldbm = BLKLDD(B, m);
+                    MORSE_TASK_zunmqr(
+                        &options,
+                        side, trans,
+                        tempmm, tempkn, tempkmin, ib, T->nb,
+                        DIAG(k), ldak,
+                        T(k, k), T->mb,
+                        B(m, k), ldbm);
+                }
+                for (n = k+1; n < B->nt; n++) {
+                    tempnn = n == B->nt-1 ? B->n-n*B->nb : B->nb;
+                    ldan = BLKLDD(A, n);
+                    for (m = 0; m < B->mt; m++) {
+                        tempmm = m == B->mt-1 ? B->m-m*B->mb : B->mb;
+                        ldbm = BLKLDD(B, m);
+                        MORSE_TASK_ztsmqr(
+                            &options,
+                            side, trans,
+                            tempmm, B->nb, tempmm, tempnn, tempkmin, ib, T->nb,
+                            B(m, k), ldbm,
+                            B(m, n), ldbm,
+                            A(n, k), ldan,
+                            T(n, k), T->mb);
+                    }
+                }
+
+                RUNTIME_iteration_pop(morse);
+            }
+        }
+    }
+    RUNTIME_options_ws_free(&options);
+    RUNTIME_options_finalize(&options, morse);
+    MORSE_TASK_dataflush_all();
+
+#if defined(CHAMELEON_COPY_DIAG)
+    MORSE_Sequence_Wait(sequence);
+    morse_desc_mat_free(DIAG);
+    free(DIAG);
+#endif
+    (void)DIAG;
+}
diff --git a/compute/zgeqrf_param.c b/compute/zgeqrf_param.c
index e47bc3fcaa5c46269806ee9c6fc7a4bc77767e6f..3e3113fb6584d0449e8b1d47e7cba6df1786b467 100644
--- a/compute/zgeqrf_param.c
+++ b/compute/zgeqrf_param.c
@@ -23,6 +23,7 @@
  * @author Mathieu Faverge
  * @author Emmanuel Agullo
  * @author Cedric Castagnede
+ * @author Raphael Boucherie
  * @date 2010-11-15
  * @precisions normal z -> s d c
  *
diff --git a/compute/zungqr_param.c b/compute/zungqr_param.c
new file mode 100644
index 0000000000000000000000000000000000000000..6dddf1cd9382ab9ed7ee75f9033a1c57316b4f47
--- /dev/null
+++ b/compute/zungqr_param.c
@@ -0,0 +1,305 @@
+/**
+ *
+ * @copyright (c) 2009-2014 The University of Tennessee and The University
+ *                          of Tennessee Research Foundation.
+ *                          All rights reserved.
+ * @copyright (c) 2012-2014 Inria. All rights reserved.
+ * @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
+ *
+ **/
+
+/**
+ *
+ * @file zungqr_param.c
+ *
+ *  MORSE computational routines
+ *  MORSE is a software package provided by Univ. of Tennessee,
+ *  Univ. of California Berkeley and Univ. of Colorado Denver
+ *
+ * @version 2.5.0
+ * @comment This file has been automatically generated
+ *          from Plasma 2.5.0 for MORSE 1.0.0
+ * @author Hatem Ltaief
+ * @author Jakub Kurzak
+ * @author Mathieu Faverge
+ * @author Emmanuel Agullo
+ * @author Cedric Castagnede
+ * @date 2010-11-15
+ * @precisions normal z -> s d c
+ *
+ **/
+#include "control/common.h"
+
+/**
+ *******************************************************************************
+ *
+ * @ingroup MORSE_Complex64_t
+ *
+ *  MORSE_zungqr_param - Generates an M-by-N matrix Q with orthonormal columns, which is defined as the
+ *  first N columns of a product of the elementary reflectors returned by MORSE_zgeqrf.
+ *
+ *******************************************************************************
+ *
+ * @param[in] M
+ *          The number of rows of the matrix Q. M >= 0.
+ *
+ * @param[in] N
+ *          The number of columns of the matrix Q. N >= M.
+ *
+ * @param[in] K
+ *          The number of columns of elementary tile reflectors whose product defines the matrix Q.
+ *          M >= K >= 0.
+ *
+ * @param[in] A
+ *          Details of the QR factorization of the original matrix A as returned by MORSE_zgeqrf.
+ *
+ * @param[in] LDA
+ *          The leading dimension of the array A. LDA >= max(1,M).
+ *
+ * @param[in] descT
+ *          Auxiliary factorization data, computed by MORSE_zgeqrf.
+ *
+ * @param[out] Q
+ *          On exit, the M-by-N matrix Q.
+ *
+ * @param[in] LDQ
+ *          The leading dimension of the array Q. LDQ >= max(1,M).
+ *
+ *******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *          \retval <0 if -i, the i-th argument had an illegal value
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zungqr_param_Tile
+ * @sa MORSE_zungqr_param_Tile_Async
+ * @sa MORSE_cungqr
+ * @sa MORSE_dorgqr
+ * @sa MORSE_sorgqr
+ * @sa MORSE_zgeqrf
+ *
+ ******************************************************************************/
+int MORSE_zungqr_param(const libhqr_tree_t *qrtree,
+                       int M, int N, int K,
+                       MORSE_Complex64_t *A, int LDA,
+                       MORSE_desc_t *descT,
+                       MORSE_Complex64_t *Q, int LDQ)
+{
+    int NB;
+    int status;
+    MORSE_context_t *morse;
+    MORSE_sequence_t *sequence = NULL;
+    MORSE_request_t request = MORSE_REQUEST_INITIALIZER;
+    MORSE_desc_t descA, descQ;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zungqr_param", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+
+    /* Check input arguments */
+    if (M < 0) {
+        morse_error("MORSE_zungqr_param", "illegal value of M");
+        return -1;
+    }
+    if (N < 0 || N > M) {
+        morse_error("MORSE_zungqr_param", "illegal value of N");
+        return -2;
+    }
+    if (K < 0 || K > N) {
+        morse_error("MORSE_zungqr_param", "illegal value of K");
+        return -3;
+    }
+    if (LDA < chameleon_max(1, M)) {
+        morse_error("MORSE_zungqr_param", "illegal value of LDA");
+        return -5;
+    }
+    if (LDQ < chameleon_max(1, M)) {
+        morse_error("MORSE_zungqr_param", "illegal value of LDQ");
+        return -8;
+    }
+    if (chameleon_min(M, chameleon_min(N, K)) == 0)
+        return MORSE_SUCCESS;
+
+    /* Tune NB & IB depending on M & N; Set NBNB */
+    status = morse_tune(MORSE_FUNC_ZGELS, M, N, 0);
+    if (status != MORSE_SUCCESS) {
+        morse_error("MORSE_zungqr_param", "morse_tune() failed");
+        return status;
+    }
+
+    /* Set NT */
+    NB = MORSE_NB;
+
+    morse_sequence_create(morse, &sequence);
+
+    /*    if ( MORSE_TRANSLATION == MORSE_OUTOFPLACE ) {*/
+    morse_zooplap2tile( descA, A, NB, NB, LDA, N, 0, 0, M, K, sequence, &request,
+                        morse_desc_mat_free(&(descA)) );
+    morse_zooplap2tile( descQ, Q, NB, NB, LDQ, N, 0, 0, M, N, sequence, &request,
+                        morse_desc_mat_free(&(descA)); morse_desc_mat_free(&(descQ)));
+    /*    } else {*/
+    /*        morse_ziplap2tile( descA, A, NB, NB, LDA, N, 0, 0, M, K,*/
+    /*                            sequence, &request);*/
+    /*        morse_ziplap2tile( descQ, Q, NB, NB, LDQ, N, 0, 0, M, N,*/
+    /*                            sequence, &request);*/
+    /*    }*/
+
+    /* Call the tile interface */
+    MORSE_zungqr_param_Tile_Async(qrtree, &descA, descT, &descQ, sequence, &request);
+
+    /*    if ( MORSE_TRANSLATION == MORSE_OUTOFPLACE ) {*/
+    morse_zooptile2lap(descQ, Q, NB, NB, LDQ, N,  sequence, &request);
+    morse_sequence_wait(morse, sequence);
+    morse_desc_mat_free(&descA);
+    morse_desc_mat_free(&descQ);
+    /*    } else {*/
+    /*        morse_ziptile2lap( descA, A, NB, NB, LDA, K,  sequence, &request);*/
+    /*        morse_ziptile2lap( descQ, Q, NB, NB, LDQ, N,  sequence, &request);*/
+    /*        morse_sequence_wait(morse, sequence);*/
+    /*    }*/
+
+    status = sequence->status;
+    morse_sequence_destroy(morse, sequence);
+    return status;
+}
+
+/***************************************************************************//**
+ *
+ * @ingroup MORSE_Complex64_t_Tile
+ *
+ *  MORSE_zungqr_param_Tile - Generates an M-by-N matrix Q with orthonormal columns, which is defined as the
+ *  first N columns of a product of the elementary reflectors returned by MORSE_zgeqrf.
+ *  All matrices are passed through descriptors. All dimensions are taken from the descriptors.
+ *
+ *******************************************************************************
+ *
+ * @param[in] A
+ *          Details of the QR factorization of the original matrix A as returned by MORSE_zgeqrf.
+ *
+ * @param[in] T
+ *          Auxiliary factorization data, computed by MORSE_zgeqrf.
+ *
+ * @param[out] Q
+ *          On exit, the M-by-N matrix Q.
+ *
+ *******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zungqr_param
+ * @sa MORSE_zungqr_param_Tile_Async
+ * @sa MORSE_cungqr_Tile
+ * @sa MORSE_dorgqr_Tile
+ * @sa MORSE_sorgqr_Tile
+ * @sa MORSE_zgeqrf_Tile
+ *
+ ******************************************************************************/
+int MORSE_zungqr_param_Tile(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *Q)
+{
+    MORSE_context_t *morse;
+    MORSE_sequence_t *sequence = NULL;
+    MORSE_request_t request = MORSE_REQUEST_INITIALIZER;
+    int status;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zungqr_param_Tile", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+    morse_sequence_create(morse, &sequence);
+    MORSE_zungqr_param_Tile_Async(qrtree, A, T, Q, sequence, &request);
+    morse_sequence_wait(morse, sequence);
+    RUNTIME_desc_getoncpu(A);
+    RUNTIME_desc_getoncpu(Q);
+
+    status = sequence->status;
+    morse_sequence_destroy(morse, sequence);
+    return status;
+}
+
+/***************************************************************************//**
+ *
+ * @ingroup MORSE_Complex64_t_Tile_Async
+ *
+ *  Non-blocking equivalent of MORSE_zungqr_param_Tile().
+ *  May return before the computation is finished.
+ *  Allows for pipelining of operations at runtime.
+ *
+ *******************************************************************************
+ *
+ * @param[in] sequence
+ *          Identifies the sequence of function calls that this call belongs to
+ *          (for completion checks and exception handling purposes).
+ *
+ * @param[out] request
+ *          Identifies this function call (for exception handling purposes).
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zungqr_param
+ * @sa MORSE_zungqr_param_Tile
+ * @sa MORSE_cungqr_Tile_Async
+ * @sa MORSE_dorgqr_Tile_Async
+ * @sa MORSE_sorgqr_Tile_Async
+ * @sa MORSE_zgeqrf_Tile_Async
+ *
+ ******************************************************************************/
+int MORSE_zungqr_param_Tile_Async(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *Q,
+                             MORSE_sequence_t *sequence, MORSE_request_t *request)
+{
+    MORSE_context_t *morse;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zungqr_param_Tile", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+    if (sequence == NULL) {
+        morse_fatal_error("MORSE_zungqr_param_Tile", "NULL sequence");
+        return MORSE_ERR_UNALLOCATED;
+    }
+    if (request == NULL) {
+        morse_fatal_error("MORSE_zungqr_param_Tile", "NULL request");
+        return MORSE_ERR_UNALLOCATED;
+    }
+    /* Check sequence status */
+    if (sequence->status == MORSE_SUCCESS)
+        request->status = MORSE_SUCCESS;
+    else
+        return morse_request_fail(sequence, request, MORSE_ERR_SEQUENCE_FLUSHED);
+
+    /* Check descriptors for correctness */
+    if (morse_desc_check(A) != MORSE_SUCCESS) {
+        morse_error("MORSE_zungqr_param_Tile", "invalid first descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if (morse_desc_check(T) != MORSE_SUCCESS) {
+        morse_error("MORSE_zungqr_param_Tile", "invalid second descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if (morse_desc_check(Q) != MORSE_SUCCESS) {
+        morse_error("MORSE_zungqr_param_Tile", "invalid third descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    /* Check input arguments */
+    if (A->nb != A->mb || Q->nb != Q->mb) {
+        morse_error("MORSE_zungqr_param_Tile", "only square tiles supported");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    /* Quick return */
+/*
+    if (N <= 0)
+        return MORSE_SUCCESS;
+*/
+    morse_pzlaset(MorseUpperLower, 0., 1., Q, sequence, request);
+    morse_pzungqr_param(qrtree, A, Q, T, sequence, request);
+
+    return MORSE_SUCCESS;
+}
diff --git a/compute/zunmqr_param.c b/compute/zunmqr_param.c
new file mode 100644
index 0000000000000000000000000000000000000000..b4467c65eaa464940bdc136c70d1779443adc3e5
--- /dev/null
+++ b/compute/zunmqr_param.c
@@ -0,0 +1,374 @@
+/**
+ *
+ * @copyright (c) 2009-2014 The University of Tennessee and The University
+ *                          of Tennessee Research Foundation.
+ *                          All rights reserved.
+ * @copyright (c) 2012-2014 Inria. All rights reserved.
+ * @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved.
+ *
+ **/
+
+/**
+ *
+ * @file zunmqr_param.c
+ *
+ *  MORSE computational routines
+ *  MORSE is a software package provided by Univ. of Tennessee,
+ *  Univ. of California Berkeley and Univ. of Colorado Denver
+ *
+ * @version 2.5.0
+ * @comment This file has been automatically generated
+ *          from Plasma 2.5.0 for MORSE 1.0.0
+ * @author Hatem Ltaief
+ * @author Jakub Kurzak
+ * @author Mathieu Faverge
+ * @author Emmanuel Agullo
+ * @author Cedric Castagnede
+ * @date 2010-11-15
+ * @precisions normal z -> s d c
+ *
+ **/
+#include "control/common.h"
+
+/**
+ *******************************************************************************
+ *
+ * @ingroup MORSE_Complex64_t
+ *
+ *  MORSE_zunmqr_param - Overwrites the general complex M-by-N matrix C with
+ *
+ *                  SIDE = 'L'     SIDE = 'R'
+ *  TRANS = 'N':      Q * C          C * Q
+ *  TRANS = 'C':      Q**H * C       C * Q**H
+ *
+ *  where Q is a complex unitary matrix defined as the product of k
+ *  elementary reflectors
+ *
+ *        Q = H(1) H(2) . . . H(k)
+ *
+ *  as returned by MORSE_zgeqrf. Q is of order M if SIDE = MorseLeft
+ *  and of order N if SIDE = MorseRight.
+ *
+ *******************************************************************************
+ *
+ * @param[in] side
+ *          Intended usage:
+ *          = MorseLeft:  apply Q or Q**H from the left;
+ *          = MorseRight: apply Q or Q**H from the right.
+ *
+ * @param[in] trans
+ *          Intended usage:
+ *          = MorseNoTrans:   no transpose, apply Q;
+ *          = MorseConjTrans: conjugate transpose, apply Q**H.
+ *
+ * @param[in] M
+ *          The number of rows of the matrix C. M >= 0.
+ *
+ * @param[in] N
+ *          The number of columns of the matrix C. N >= 0.
+ *
+ * @param[in] K
+ *          The number of elementary reflectors whose product defines
+ *          the matrix Q.
+ *          If side == MorseLeft,  M >= K >= 0.
+ *          If side == MorseRight, N >= K >= 0.
+ *
+ * @param[in] A
+ *          Details of the QR factorization of the original matrix A as returned by MORSE_zgeqrf.
+ *
+ * @param[in] LDA
+ *          The leading dimension of the array A.
+ *          If side == MorseLeft,  LDA >= max(1,M).
+ *          If side == MorseRight, LDA >= max(1,N).
+ *
+ * @param[in] descT
+ *          Auxiliary factorization data, computed by MORSE_zgeqrf.
+ *
+ * @param[in,out] C
+ *          On entry, the M-by-N matrix C.
+ *          On exit, C is overwritten by Q*C or Q**H*C.
+ *
+ * @param[in] LDC
+ *          The leading dimension of the array C. LDC >= max(1,M).
+ *
+ *******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *          \retval <0 if -i, the i-th argument had an illegal value
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zunmqr_param_Tile
+ * @sa MORSE_zunmqr_param_Tile_Async
+ * @sa MORSE_cunmqr
+ * @sa MORSE_dormqr
+ * @sa MORSE_sormqr
+ * @sa MORSE_zgeqrf
+ *
+ ******************************************************************************/
+int MORSE_zunmqr_param(const libhqr_tree_t *qrtree,
+                       MORSE_enum side, MORSE_enum trans, int M, int N, int K,
+                       MORSE_Complex64_t *A, int LDA,
+                       MORSE_desc_t *descT,
+                       MORSE_Complex64_t *C, int LDC)
+{
+    int NB, Am;
+    int status;
+    MORSE_context_t *morse;
+    MORSE_sequence_t *sequence = NULL;
+    MORSE_request_t request = MORSE_REQUEST_INITIALIZER;
+    MORSE_desc_t descA, descC;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zunmqr_param", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+
+    if ( side == MorseLeft ) {
+        Am = M;
+    } else {
+        Am = N;
+    }
+
+    /* Check input arguments */
+    if ((side != MorseLeft) && (side != MorseRight)) {
+        morse_error("MORSE_zunmqr_param", "illegal value of side");
+        return -1;
+    }
+    if ((trans != MorseConjTrans) && (trans != MorseNoTrans)){
+        morse_error("MORSE_zunmqr_param", "illegal value of trans");
+        return -2;
+    }
+    if (M < 0) {
+        morse_error("MORSE_zunmqr_param", "illegal value of M");
+        return -3;
+    }
+    if (N < 0) {
+        morse_error("MORSE_zunmqr_param", "illegal value of N");
+        return -4;
+    }
+    if ((K < 0) || (K > Am)) {
+        morse_error("MORSE_zunmqr_param", "illegal value of K");
+        return -5;
+    }
+    if (LDA < chameleon_max(1, Am)) {
+        morse_error("MORSE_zunmqr_param", "illegal value of LDA");
+        return -7;
+    }
+    if (LDC < chameleon_max(1, M)) {
+        morse_error("MORSE_zunmqr_param", "illegal value of LDC");
+        return -10;
+    }
+    /* Quick return - currently NOT equivalent to LAPACK's:
+     * CALL DLASET( 'Full', MAX( M, N ), NRHS, ZERO, ZERO, C, LDC ) */
+    if (chameleon_min(M, chameleon_min(N, K)) == 0)
+        return MORSE_SUCCESS;
+
+    /* Tune NB & IB depending on M, K & N; Set NBNB */
+    status = morse_tune(MORSE_FUNC_ZGELS, M, K, N);
+    if (status != MORSE_SUCCESS) {
+        morse_error("MORSE_zunmqr_param", "morse_tune() failed");
+        return status;
+    }
+
+    /* Set MT, NT & NTRHS */
+    NB   = MORSE_NB;
+    morse_sequence_create(morse, &sequence);
+
+/*    if ( MORSE_TRANSLATION == MORSE_OUTOFPLACE ) {*/
+        morse_zooplap2tile( descA, A, NB, NB, LDA, K, 0, 0, Am, K, sequence, &request,
+                             morse_desc_mat_free(&(descA)) );
+        morse_zooplap2tile( descC, C, NB, NB, LDC, N, 0, 0, M,  N, sequence, &request,
+                             morse_desc_mat_free(&(descA)); morse_desc_mat_free(&(descC)));
+/*    } else {*/
+/*        morse_ziplap2tile( descA, A, NB, NB, LDA, K, 0, 0, Am, K,*/
+/*                            sequence, &request);*/
+/*        morse_ziplap2tile( descC, C, NB, NB, LDC, N, 0, 0, M,  N,*/
+/*                            sequence, &request);*/
+/*    }*/
+
+    /* Call the tile interface */
+        MORSE_zunmqr_param_Tile_Async(
+            qrtree, side, trans, &descA, descT, &descC, sequence, &request);
+
+/*    if ( MORSE_TRANSLATION == MORSE_OUTOFPLACE ) {*/
+        morse_zooptile2lap(descC, C, NB, NB, LDC, N,  sequence, &request);
+        morse_sequence_wait(morse, sequence);
+        morse_desc_mat_free(&descA);
+        morse_desc_mat_free(&descC);
+/*    } else {*/
+/*        morse_ziptile2lap( descA, A, NB, NB, LDA, K,  sequence, &request);*/
+/*        morse_ziptile2lap( descC, C, NB, NB, LDC, N,  sequence, &request);*/
+/*        morse_sequence_wait(morse, sequence);*/
+/*    }*/
+
+    status = sequence->status;
+    morse_sequence_destroy(morse, sequence);
+    return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @ingroup MORSE_Complex64_t_Tile
+ *
+ *  MORSE_zunmqr_param_Tile - overwrites the general M-by-N matrix C with Q*C, where Q is an orthogonal
+ *  matrix (unitary in the complex case) defined as the product of elementary reflectors returned
+ *  by MORSE_zgeqrf_Tile Q is of order M.
+ *  All matrices are passed through descriptors. All dimensions are taken from the descriptors.
+ *
+ *******************************************************************************
+ *
+ * @param[in] side
+ *          Intended usage:
+ *          = MorseLeft:  apply Q or Q**H from the left;
+ *          = MorseRight: apply Q or Q**H from the right.
+ *          Currently only MorseLeft is supported.
+ *
+ * @param[in] trans
+ *          Intended usage:
+ *          = MorseNoTrans:   no transpose, apply Q;
+ *          = MorseConjTrans: conjugate transpose, apply Q**H.
+ *          Currently only MorseConjTrans is supported.
+ *
+ * @param[in] A
+ *          Details of the QR factorization of the original matrix A as returned by MORSE_zgeqrf.
+ *
+ * @param[in] T
+ *          Auxiliary factorization data, computed by MORSE_zgeqrf.
+ *          Can be obtained with MORSE_Alloc_Workspace_zgeqrf
+ *
+ * @param[in,out] C
+ *          On entry, the M-by-N matrix C.
+ *          On exit, C is overwritten by Q*C or Q**H*C.
+ *
+ *******************************************************************************
+ *
+ * @return
+ *          \retval MORSE_SUCCESS successful exit
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zunmqr_param
+ * @sa MORSE_zunmqr_param_Tile_Async
+ * @sa MORSE_cunmqr_Tile
+ * @sa MORSE_dormqr_Tile
+ * @sa MORSE_sormqr_Tile
+ * @sa MORSE_zgeqrf_Tile
+ *
+ ******************************************************************************/
+int MORSE_zunmqr_param_Tile(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans,
+                       MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *C)
+{
+    MORSE_context_t *morse;
+    MORSE_sequence_t *sequence = NULL;
+    MORSE_request_t request = MORSE_REQUEST_INITIALIZER;
+    int status;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zunmqr_param_Tile", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+    morse_sequence_create(morse, &sequence);
+    MORSE_zunmqr_param_Tile_Async(qrtree, side, trans, A, T, C, sequence, &request);
+    morse_sequence_wait(morse, sequence);
+    RUNTIME_desc_getoncpu(A);
+        RUNTIME_desc_getoncpu(C);
+
+    status = sequence->status;
+    morse_sequence_destroy(morse, sequence);
+    return status;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @ingroup MORSE_Complex64_t_Tile_Async
+ *
+ *  Non-blocking equivalent of MORSE_zunmqr_param_Tile().
+ *  May return before the computation is finished.
+ *  Allows for pipelining of operations at runtime.
+ *
+ *******************************************************************************
+ *
+ * @param[in] sequence
+ *          Identifies the sequence of function calls that this call belongs to
+ *          (for completion checks and exception handling purposes).
+ *
+ * @param[out] request
+ *          Identifies this function call (for exception handling purposes).
+ *
+ *******************************************************************************
+ *
+ * @sa MORSE_zunmqr_param
+ * @sa MORSE_zunmqr_param_Tile
+ * @sa MORSE_cunmqr_Tile_Async
+ * @sa MORSE_dormqr_Tile_Async
+ * @sa MORSE_sormqr_Tile_Async
+ * @sa MORSE_zgeqrf_Tile_Async
+ *
+ ******************************************************************************/
+int MORSE_zunmqr_param_Tile_Async(const libhqr_tree_t *qrtree,
+                                  MORSE_enum side, MORSE_enum trans,
+                                  MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *C,
+                                  MORSE_sequence_t *sequence, MORSE_request_t *request)
+{
+    MORSE_context_t *morse;
+
+    morse = morse_context_self();
+    if (morse == NULL) {
+        morse_fatal_error("MORSE_zunmqr_param_Tile", "MORSE not initialized");
+        return MORSE_ERR_NOT_INITIALIZED;
+    }
+    if (sequence == NULL) {
+        morse_fatal_error("MORSE_zunmqr_param_Tile", "NULL sequence");
+        return MORSE_ERR_UNALLOCATED;
+    }
+    if (request == NULL) {
+        morse_fatal_error("MORSE_zunmqr_param_Tile", "NULL request");
+        return MORSE_ERR_UNALLOCATED;
+    }
+    /* Check sequence status */
+    if (sequence->status == MORSE_SUCCESS)
+        request->status = MORSE_SUCCESS;
+    else
+        return morse_request_fail(sequence, request, MORSE_ERR_SEQUENCE_FLUSHED);
+
+    /* Check descriptors for correctness */
+    if (morse_desc_check(A) != MORSE_SUCCESS) {
+        morse_error("MORSE_zunmqr_param_Tile", "invalid first descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if (morse_desc_check(T) != MORSE_SUCCESS) {
+        morse_error("MORSE_zunmqr_param_Tile", "invalid second descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if (morse_desc_check(C) != MORSE_SUCCESS) {
+        morse_error("MORSE_zunmqr_param_Tile", "invalid third descriptor");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    /* Check input arguments */
+    if (A->nb != A->mb || C->nb != C->mb) {
+        morse_error("MORSE_zunmqr_param_Tile", "only square tiles supported");
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if ((side != MorseLeft) && (side != MorseRight)) {
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    if ((trans != MorseConjTrans) && (trans != MorseNoTrans)){
+        return morse_request_fail(sequence, request, MORSE_ERR_ILLEGAL_VALUE);
+    }
+    /* Quick return - currently NOT equivalent to LAPACK's:
+     * CALL DLASET( 'Full', MAX( M, N ), NRHS, ZERO, ZERO, C, LDC ) */
+/*
+    if (chameleon_min(M, chameleon_min(N, K)) == 0)
+        return MORSE_SUCCESS;
+*/
+
+    morse_pzunmqr_param(qrtree, side, trans, A, C, T, sequence, request);
+
+    return MORSE_SUCCESS;
+}
diff --git a/control/compute_z.h b/control/compute_z.h
index 6ff705255f00caa570aecfa0225813b25817c40c..9340037118824f0cf0892e7158dd0945f5eb4d26 100644
--- a/control/compute_z.h
+++ b/control/compute_z.h
@@ -156,6 +156,18 @@ void morse_pzunmlqrh(MORSE_enum side, MORSE_enum trans, MORSE_desc_t *A, MORSE_d
 void morse_pzbuild( MORSE_enum uplo, MORSE_desc_t *A, void *user_data, void* user_build_callback, MORSE_sequence_t *sequence, MORSE_request_t *request );
 
 #if defined(CHAMELEON_USE_LIBHQR)
-void morse_pzgeqrf_param( const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *TS, MORSE_desc_t *TT,
-                          MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzgelqf_param(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *TS, MORSE_desc_t *TT,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzgeqrf_param(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *TS, MORSE_desc_t *TT,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzunmlq_param(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans,
+                         MORSE_desc_t *A, MORSE_desc_t *B, MORSE_desc_t *T,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzunmqr_param(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans,
+                         MORSE_desc_t *A, MORSE_desc_t *B, MORSE_desc_t *T,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzunglq_param(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *Q, MORSE_desc_t *T,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
+void morse_pzungqr_param(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *Q, MORSE_desc_t *T,
+                         MORSE_sequence_t *sequence, MORSE_request_t *request);
 #endif /* defined(CHAMELEON_USE_LIBHQR) */
diff --git a/include/morse_z.h b/include/morse_z.h
index 47e0b4c60757919bb0aeae3ddc11fc762b6d6bf6..ac045809a3ecdb95ccfdfafe389be7d2bc88907a 100644
--- a/include/morse_z.h
+++ b/include/morse_z.h
@@ -280,6 +280,12 @@ int MORSE_zunmqr_Tile_Async(MORSE_enum side, MORSE_enum trans, MORSE_desc_t *A,
 int MORSE_zgeqrf_param(const libhqr_tree_t *qrtree, int M, int N, MORSE_Complex64_t *A, int LDA, MORSE_desc_t *descTS, MORSE_desc_t *descTT);
 int MORSE_zgeqrf_param_Tile(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *TS, MORSE_desc_t *TT);
 int MORSE_zgeqrf_param_Tile_Async(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *TS, MORSE_desc_t *TT, MORSE_sequence_t *sequence, MORSE_request_t *request);
+int MORSE_zungqr_param(const libhqr_tree_t *qrtree, int M, int N, int K, MORSE_Complex64_t *A, int LDA, MORSE_desc_t *descT, MORSE_Complex64_t *B, int LDB);
+int MORSE_zungqr_param_Tile(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *B);
+int MORSE_zungqr_param_Tile_Async(const libhqr_tree_t *qrtree, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *B, MORSE_sequence_t *sequence, MORSE_request_t *request);
+int MORSE_zunmqr_param(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans, int M, int N, int K, MORSE_Complex64_t *A, int LDA, MORSE_desc_t *descT, MORSE_Complex64_t *B, int LDB);
+int MORSE_zunmqr_param_Tile(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *B);
+int MORSE_zunmqr_param_Tile_Async(const libhqr_tree_t *qrtree, MORSE_enum side, MORSE_enum trans, MORSE_desc_t *A, MORSE_desc_t *T, MORSE_desc_t *B, MORSE_sequence_t *sequence, MORSE_request_t *request);
 #endif /* defined(CHAMELEON_USE_LIBHQR) */
 /**
  *  Declarations of workspace allocation functions (tile layout) - alphabetical order