Mentions légales du service

Skip to content
Snippets Groups Projects
testing_zgeqrf_qdwh.c 8.38 KiB
Newer Older
/**
 *
 * @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 testing_zgels.c
 *
 *  MORSE testing 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 Bilel Hadri
 * @author Hatem Ltaief
 * @author Mathieu Faverge
 * @author Emmanuel Agullo
 * @author Cedric Castagnede
 * @date 2010-11-15
 * @precisions normal z -> c d s
 *
 **/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <morse.h>
#include <coreblas/include/cblas.h>
#include <coreblas/include/lapacke.h>
#include <coreblas/include/coreblas.h>
#include <coreblas/include/coreblas_z.h>
#include "testing_zauxiliary.h"

#undef REAL
#define COMPLEX

static int check_orthogonality(int, int, const MORSE_Complex64_t*, int, double);
static int check_factorization(int, int, const MORSE_Complex64_t*, int, const MORSE_Complex64_t*, int, MORSE_Complex64_t*, int, double);

int testing_zgeqrf_qdwh(int argc, char **argv)
{
    int hres = 0;

    if ( argc != 4 ) {
        USAGE("GEQRF_QDWH", "optid M NB LDA",
              "   - optid: Take into account the fact that A2 is Id or not\n"
              "   - M    : number of rows of the matrix A1 and A2\n"
              "   - NB   : tile size\n"
              "   - IB   : inner tile size\n");
        return -1;
    }

    int optid = atoi(argv[0]) ? 1: 0;
    int M  = atoi(argv[1]);
    int NB = atoi(argv[2]);
    int IB = atoi(argv[3]);
    int MxM = M * M;
    int LDA = 2*M;
    double eps;
Mathieu Faverge's avatar
Mathieu Faverge committed
    int info_ortho, info_factorization;

    /**
     * Compute A = QR with
     *
     * A = [ A1 ]  and Q = [ Q1 ]
     *     [ A2 ]        = [ Q2 ]
     *
     * and where A1 is the same size as A2
     *
     */
    MORSE_Complex64_t *A1 = (MORSE_Complex64_t *)malloc(M*M*sizeof(MORSE_Complex64_t));
    MORSE_Complex64_t *A2 = (MORSE_Complex64_t *)malloc(M*M*sizeof(MORSE_Complex64_t));
    MORSE_Complex64_t *Q1 = (MORSE_Complex64_t *)malloc(M*M*sizeof(MORSE_Complex64_t));
    MORSE_Complex64_t *Q2 = (MORSE_Complex64_t *)malloc(M*M*sizeof(MORSE_Complex64_t));
    MORSE_Complex64_t *A  = (MORSE_Complex64_t *)malloc(2*M*M*sizeof(MORSE_Complex64_t));
    MORSE_Complex64_t *Q;
    MORSE_desc_t *T1, *T2;

    /* Check if unable to allocate memory */
    if ( (!A) || (!A1) || (!A2) || (!Q1) || (!Q2) ){
        printf("Out of Memory \n ");
        return -2;
    }

    MORSE_Disable(MORSE_AUTOTUNING);
    MORSE_Set(MORSE_TILE_SIZE, NB);
    MORSE_Set(MORSE_INNER_BLOCK_SIZE, IB);

    MORSE_Alloc_Workspace_zgels(M, M, &T1, 1, 1);
    MORSE_Alloc_Workspace_zgels(M, M, &T2, 1, 1);

    eps = LAPACKE_dlamch('e');

    /* Initialize A1, A2, and A */
    LAPACKE_zlarnv_work(IONE, ISEED, MxM, A1);
    LAPACKE_zlaset_work( LAPACK_COL_MAJOR, 'A', M, M, 0., 1., A2, M );

    LAPACKE_zlacpy_work( LAPACK_COL_MAJOR, 'A', M, M, A1, M, A,     LDA );
    LAPACKE_zlacpy_work( LAPACK_COL_MAJOR, 'A', M, M, A2, M, A + M, LDA );

    /* Factorize A */
Mathieu Faverge's avatar
Mathieu Faverge committed
    MORSE_zgeqrf( M, M, A1, M, T1 );
    MORSE_ztpqrt( M, M, optid ? M : 0,
                  A1, M,
                  A2, M, T2 );
Mathieu Faverge's avatar
Mathieu Faverge committed
    MORSE_ztpgqrt( M, M, M, (optid) ? M : 0,
                   A1, M, T1, A2, M, T2, Q1, M, Q2, M );

    /* Copy Q in a single matrix */
    Q = (MORSE_Complex64_t *)malloc(2*M*M*sizeof(MORSE_Complex64_t));
    LAPACKE_zlacpy_work( LAPACK_COL_MAJOR, 'A', M, M, Q1, M, Q,     LDA );
    free(Q1);
    LAPACKE_zlacpy_work( LAPACK_COL_MAJOR, 'A', M, M, Q2, M, Q + M, LDA );
    free(Q2);

    printf("\n");
    printf("------ TESTS FOR CHAMELEON ZGELS ROUTINE -------  \n");
    printf("            Size of the Matrix %d by %d\n", M, M);
    printf("\n");
    printf(" The matrix A is randomly generated for each test.\n");
    printf("============\n");
    printf(" The relative machine precision (eps) is to be %e \n",eps);
    printf(" Computational tests pass if scaled residuals are less than 60.\n");

    /* Check the orthogonality, factorization and the solution */
    info_ortho = check_orthogonality( 2*M, M, Q, LDA, eps );
    info_factorization = check_factorization( 2*M, M, A, LDA, A1, M, Q, LDA, eps );

    if ((info_factorization == 0) & (info_ortho == 0)) {
        printf("***************************************************\n");
        printf(" ---- TESTING ZGELS ...................... PASSED !\n");
        printf("***************************************************\n");
    }
    else {
        printf("************************************************\n");
        printf(" - TESTING ZGELS ... FAILED !\n");    hres++;
        printf("************************************************\n");
    }

    free(A); free(A1); free(A2); free(Q);
    MORSE_Dealloc_Workspace( &T1 );
    MORSE_Dealloc_Workspace( &T2 );

    return hres;
}

/*-------------------------------------------------------------------
 * Check the orthogonality of Q
 */

static int
check_orthogonality( int M, int N,
                     const MORSE_Complex64_t *Q, int LDQ,
                     double eps )
{
    MORSE_Complex64_t *Id;
    double alpha, beta;
    double normQ;
    int info_ortho;
    int minMN = min(M, N);

    double *work = (double *)malloc(minMN*sizeof(double));

    alpha = 1.0;
    beta  = -1.0;

    /* Build the idendity matrix */
    Id = (MORSE_Complex64_t *) malloc(minMN*minMN*sizeof(MORSE_Complex64_t));
    LAPACKE_zlaset_work(LAPACK_COL_MAJOR, 'A', minMN, minMN, 0., 1., Id, minMN );

    /* Perform Id - Q'Q */
    if (M >= N)
        cblas_zherk(CblasColMajor, CblasUpper, CblasConjTrans, N, M, beta, Q, LDQ, alpha, Id, N);
    else
        cblas_zherk(CblasColMajor, CblasUpper, CblasNoTrans, M, N, beta, Q, LDQ, alpha, Id, M);

    normQ = LAPACKE_zlansy_work( LAPACK_COL_MAJOR, 'I', 'U', minMN, Id, minMN, work );

    printf("============\n");
    printf("Checking the orthogonality of Q \n");
    printf("||Id-Q'*Q||_oo / (N*eps) = %e \n", normQ/(minMN*eps));

    if ( isnan(normQ / (minMN * eps)) || isinf(normQ / (minMN * eps)) || (normQ / (minMN * eps) > 60.0) ) {
        printf("-- Orthogonality is suspicious ! \n");
        info_ortho=1;
    }
    else {
        printf("-- Orthogonality is CORRECT ! \n");
        info_ortho=0;
    }

    free(work); free(Id);

    return info_ortho;
}

/*------------------------------------------------------------
 *  Check the factorization QR
 */

static int
check_factorization(int M, int N,
                    const MORSE_Complex64_t *A, int LDA,
                    const MORSE_Complex64_t *R, int LDR,
                          MORSE_Complex64_t *Q, int LDQ,
                    double eps )
{
    double Anorm, Rnorm;
Mathieu Faverge's avatar
Mathieu Faverge committed
    MORSE_Complex64_t alpha;
    int info_factorization;
    double *work = (double *)malloc(max(M,N)*sizeof(double));

    alpha = 1.0;

    if (M >= N) {
        /* Perform Q = Q * R */
        cblas_ztrmm( CblasColMajor, CblasRight, CblasUpper, CblasNoTrans, CblasNonUnit, M, N, CBLAS_SADDR(alpha), R, LDR, Q, LDQ);
    }
    else {
        /* Perform Q = L * Q */
        cblas_ztrmm( CblasColMajor, CblasLeft, CblasLower, CblasNoTrans, CblasNonUnit, M, N, CBLAS_SADDR(alpha), R, LDR, Q, LDQ);
    }

    /* Compute the Residual */
    CORE_zgeadd( MorseNoTrans, M, N, -1., A, LDA, 1., Q, LDQ );

    Rnorm = LAPACKE_zlange_work( LAPACK_COL_MAJOR, 'I', M, N, Q, LDQ, work );
    Anorm = LAPACKE_zlange_work( LAPACK_COL_MAJOR, 'I', M, N, A, LDA, work );

    if (M >= N) {
        printf("============\n");
        printf("Checking the QR Factorization \n");
        printf("-- ||A-QR||_oo/(||A||_oo.N.eps) = %e \n",Rnorm/(Anorm*N*eps));
    }
    else {
        printf("============\n");
        printf("Checking the LQ Factorization \n");
        printf("-- ||A-LQ||_oo/(||A||_oo.N.eps) = %e \n",Rnorm/(Anorm*N*eps));
    }

    if (isnan(Rnorm / (Anorm * N *eps)) || isinf(Rnorm / (Anorm * N *eps)) || (Rnorm / (Anorm * N * eps) > 60.0) ) {
        printf("-- Factorization is suspicious ! \n");
        info_factorization = 1;
    }
    else {
        printf("-- Factorization is CORRECT ! \n");
        info_factorization = 0;
    }

    free(work);

    return info_factorization;
}