BLAS矩阵向量乘法与向量矩阵乘法。一个有效;另一个失败了

时间:2017-06-13 20:08:39

标签: c linear-algebra lapack blas

在Lapack中使用cgemv BLAS lvl 2函数时,我成功进行了矩阵向量乘法,但是当我尝试转置时,我得到了错误的答案。你可以告诉我我的错误吗? (我实际上使用的是C包装器,而不是FORTRAN。)

我正在尝试

| 4+i    3 |   | 3+2i |          | 4+i    3 |^T   | 3+2i |
| 14+3i  2 | * | 2    |  (AND)   | 14+3i  2 |   * | 2    |

要清楚,第一个成功。第二个输出不正确。

/* config variables */
char normal = 'N';
char transpose = 'T';
integer m = 2;
complex alpha = {r:1,i:0};
complex beta = {r:0,i:0};
integer one = 1;
/* data buffers */
complex a[4] = {(complex){r:4,  i:1},(complex){r:14, i:3},(complex){r:3,  i:0},(complex){r:6,  i:0}};
complex x[2] = {(complex){r:3, i:2},(complex){r:2, i:0}};
complex y[2];
/* execution */
cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);

在第一次cgemv_调用之后,y保留16.0000+11.0000i 48.0000+37.0000i,MATLAB确认这是正确的。

但是在第二次cgemv_调用之后,y保持38.0000+17.0000i 21.0000+6.0000i,而MATLAB则认为它应该是42.0000-1.0000i 21.0000+6.0000i。我不知道会出现什么问题。

1 个答案:

答案 0 :(得分:1)

由于2向量乘以2x2矩阵,因此使用penpaper进行操作并不太复杂。如果使用转置矩阵:

(4 + I)*(3 + 2I)+(14 + 3I)* 2 = 38 + 17I

奇怪的是:

(4-I)*(3 + 2I)+(14-3i)* 2 = 42-i的

因此,MATLAB的输出可能是使用complex conjugate transpose获得的输出。如果cgemv_TRANS参数设置为'C',则BLAS可以生成相同的输出。

以下是基于我们的示例代码,显示了BLAS真正为TRANS的不同值计算的内容。它可以通过gcc main.c -o main -lblas -Wall计算。

#include <stdlib.h>
#include <stdio.h>

#include <complex.h>


extern int cgemv_(char* trans, int * m, int * n, float complex* alpha, float complex* A, int * lda,float complex * x, int* incx, float complex * beta, float complex * y,int* incy);

int main(void) {

    /* config variables */
    char normal = 'N';
    char transpose = 'T';
    char ctranspose = 'C';
    int m = 2;
    float complex alpha = 1.0+0.*I;
    float complex beta = 0.0+0.*I;
    int one = 1;
    /* data buffers */
    float complex a[4]= {4+1.*I,14+3.*I,3.+0.*I,6.+0.*I};
    float complex x[2] = {3.+2.*I,2+0.*I};
    float complex y[2];
    /* execution */

    float complex ye[2];
    ye[0]=a[0]*x[0]+a[2]*x[1];
    ye[1]=a[1]*x[0]+a[3]*x[1];

    cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);

    printf("N\n");
    printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0])); 
    printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1])); 

    //float complex ye[2];
    ye[0]=a[0]*x[0]+a[1]*x[1];
    ye[1]=a[2]*x[0]+a[3]*x[1];

    cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);

    printf("T\n");
    printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0])); 
    printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));  

    ye[0]=conj(a[0])*x[0]+conj(a[1])*x[1];
    ye[1]=conj(a[2])*x[0]+conj(a[3])*x[1];

    cgemv_(&ctranspose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);

    printf("C\n");
    printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0])); 
    printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));  


    return 0;
}