来自lapack子程序dgeqrf的QR分解在C中不起作用

时间:2017-11-16 16:22:37

标签: lapack

我想找到使用lapack从A矩阵的QR分解获得的R矩阵的对角元素作为A = QR。我尝试了lapack dgeqrf子程序但它返回相同的矩阵A,即输入和输出矩阵是相同的。如何找到R矩阵及其对角线?我无法弄清楚这段代码出了什么问题。我在C编程。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void dgeqrf_(int *rows, int *cols, double *matA, int *LDA, double *TAU, double *WORK, int *LWORK, int *INFO);
int main()
{
    int rows=3;
    int cols=3;
    double *matA=malloc(sizeof(double)*rows*cols);

    matA[0]=10;
    matA[1]=20;
    matA[2]=10;
    matA[3]=40;
    matA[4]=20;
    matA[5]=50;
    matA[6]=70;
    matA[7]=30;
    matA[8]=20;

    for(int i=0; i<rows*cols; i++)
    {
        printf("%f ",matA[i]);
    }
    printf("\n");
    int LDA=rows;
    int INFO;
    double *WORK=malloc(sizeof(double)*2);
    int LWORK=-1;
    int rowcolmin=rows;
    if(rowcolmin>cols)
    {
        rowcolmin=cols;
    }
    double *TAU=malloc(sizeof(double)*rowcolmin);
    dgeqrf_(&rows, &cols, matA, &LDA, TAU, WORK, &LWORK, &INFO);
    for(int i=0; i<rows*cols; i++)
    {
        printf("%f ",matA[i]);
    }
    printf("\n");
    free(WORK);
    free(TAU);
    free(matA);
    return 0;
}

1 个答案:

答案 0 :(得分:2)

未修改矩阵matA,因为参数LWORK使用值-1调用LAPACK dgeqrf()。这对应于工作区查询:

  

如果LWORK = -1,则假定工作空间查询;例程             只计算WORK数组的最佳大小,返回             此值作为WORK数组的第一个条目,并且没有错误             与LWORK相关的消息由XERBLA发布。

实际上,使用dgeqrf()和LAPACK中的许多其他例程的常用方法是调用它们两次:一次用于工作空间查询,一次用于实际计算结果。 For例如,LAPACK的C接口在lapacke__dgeqrf()中包裹dgeqrf(),由于这个原因,它会调用lapacke__dgeqrf_work()两次。

以下是您的代码的修改方式:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void dgeqrf_(int *rows, int *cols, double *matA, int *LDA, double *TAU, double *WORK, int *LWORK, int *INFO);
int main()
{
    int i;
    int rows=3;
    int cols=3;
    double *matA=malloc(sizeof(double)*rows*cols);

    matA[0]=1;
    matA[1]=2;
    matA[2]=4;
    matA[3]=1;
    matA[4]=3;
    matA[5]=9;
    matA[6]=1;
    matA[7]=4;
    matA[8]=16;

    for(i=0; i<rows*cols; i++)
    {
        printf("%f ",matA[i]);
    }
    printf("\n");
    int LDA=rows;
    int INFO;

    int rowcolmin=rows;
    if(rowcolmin>cols)
    {
        rowcolmin=cols;
    }

    double *TAU=malloc(sizeof(double)*rowcolmin);
    int LWORK=-1;
    // since the value of LWORK is -1, this is a workspace query.
    // it only return the optimum size of work in work[0].
    double lwork2;    
    dgeqrf_(&rows, &cols, matA, &LDA, TAU, &lwork2, &LWORK, &INFO);
    // allocate work using the optimal size
    int lwork3=(int)lwork2;
    double *WORK=malloc(sizeof(double)*lwork3);
    // perform the QR factorization
    dgeqrf_(&rows, &cols, matA, &LDA, TAU, WORK, &lwork3, &INFO);
    if(INFO !=0){fprintf(stderr,"QR factorization failed, error code %d\n",INFO);exit(1);}

    for(i=0; i<rows*cols; i++)
    {
        printf("%f ",matA[i]);
    }
    printf("\n");


    // for instance, the determinant is...
    if(cols==rows){
        // det of R
        double det=1;
        for (i=0;i<cols;i++){
            det*=matA[i*cols+i];
        }
        // det of Q, Householder algorithm
        if(cols%2==0){
            det*=-1;
        }
        printf("det is %g\n",det);
    }
    free(WORK);
    free(TAU);
    free(matA);
    return 0;
}

gcc main.c -o main -llapack -lblas -lm编译。

考虑到你提出的题为compute determinant from LU decomposition in lapack的问题,在代码末尾添加了行列式的计算。矩阵matA现在是Vandermonde matrix,以便轻松检查结果的正确性。