下面是Spencer Nelson上面的示例的工作版本。關於它的一個謎就是輸入矩陣按照行優先順序排列,即使它看起來叫做底層Fortran例程dgetri
。我被引導認爲所有Fortran的例程都需要列主要的順序,但我並不是LAPACK方面的專家,事實上,我正在使用這個例子來幫助我學習它。但是,拋開那個謎團:
示例中的輸入矩陣是單數。 LAPACK試圖告訴你,通過在errorHandler
中返回一個3
。我將該矩陣中的9
更改爲19
,獲得errorHandler
的0
信號成功,並將結果與Mathematica
進行比較。如上所述,該比較也是成功的,並且證實了示例中的矩陣應該按行優先順序排列。
這裏是工作代碼:
#include <stdio.h>
#include <stddef.h>
#include <lapacke.h>
int main() {
int N = 3;
int NN = 9;
double M[3][3] = { {1 , 2 , 3},
{4 , 5 , 6},
{7 , 8 , 9} };
int pivotArray[3]; //since our matrix has three rows
int errorHandler;
double lapackWorkspace[9];
// dgetrf(M,N,A,LDA,IPIV,INFO) means invert LDA columns of an M by N matrix
// called A, sending the pivot indices to IPIV, and spitting error information
// to INFO. also don't forget (like I did) that when you pass a two-dimensional
// array to a function you need to specify the number of "rows"
dgetrf_(&N, &N, M[0], &N, pivotArray, &errorHandler);
printf ("dgetrf eh, %d, should be zero\n", errorHandler);
dgetri_(&N, M[0], &N, pivotArray, lapackWorkspace, &NN, &errorHandler);
printf ("dgetri eh, %d, should be zero\n", errorHandler);
for (size_t row = 0; row < N; ++row)
{ for (size_t col = 0; col < N; ++col)
{ printf ("%g", M[row][col]);
if (N-1 != col)
{ printf (", "); } }
if (N-1 != row)
{ printf ("\n"); } }
return 0; }
我建立並運行它在Mac上,如下所示:
gcc main.c -llapacke -llapack
./a.out
我做的LAPACKE庫中nm
,發現如下:
liblapacke.a(lapacke_dgetri.o):
U _LAPACKE_dge_nancheck
0000000000000000 T _LAPACKE_dgetri
U _LAPACKE_dgetri_work
U _LAPACKE_xerbla
U _free
U _malloc
liblapacke.a(lapacke_dgetri_work.o):
U _LAPACKE_dge_trans
0000000000000000 T _LAPACKE_dgetri_work
U _LAPACKE_xerbla
U _dgetri_
U _free
U _malloc
它看起來像有一個LAPACKE [原文如此]包裝,可能會緩解我們不得不爲了fortran的方便而到處尋址,但我可能不會試着去嘗試它,因爲我有前進的方向。
EDIT
這裏是繞過LAPACKE [原文如此],直接使用LAPACK Fortran例程工作版本。我不明白爲什麼行主要輸入會產生正確的結果,但我在Mathematica中再次證實了它。
#include <stdio.h>
#include <stddef.h>
int main() {
int N = 3;
int NN = 9;
double M[3][3] = { {1 , 2 , 3},
{4 , 5 , 6},
{7 , 8 , 19} };
int pivotArray[3]; //since our matrix has three rows
int errorHandler;
double lapackWorkspace[9];
/* from http://www.netlib.no/netlib/lapack/double/dgetrf.f
SUBROUTINE DGETRF(M, N, A, LDA, IPIV, INFO)
*
* -- LAPACK routine (version 3.1) --
* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
* November 2006
*
* .. Scalar Arguments ..
INTEGER INFO, LDA, M, N
* ..
* .. Array Arguments ..
INTEGER IPIV(*)
DOUBLE PRECISION A(LDA, *)
*/
extern void dgetrf_ (int * m, int * n, double * A, int * LDA, int * IPIV,
int * INFO);
/* from http://www.netlib.no/netlib/lapack/double/dgetri.f
SUBROUTINE DGETRI(N, A, LDA, IPIV, WORK, LWORK, INFO)
*
* -- LAPACK routine (version 3.1) --
* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
* November 2006
*
* .. Scalar Arguments ..
INTEGER INFO, LDA, LWORK, N
* ..
* .. Array Arguments ..
INTEGER IPIV(*)
DOUBLE PRECISION A(LDA, *), WORK(*)
*/
extern void dgetri_ (int * n, double * A, int * LDA, int * IPIV,
double * WORK, int * LWORK, int * INFO);
// dgetrf(M,N,A,LDA,IPIV,INFO) means invert LDA columns of an M by N matrix
// called A, sending the pivot indices to IPIV, and spitting error information
// to INFO. also don't forget (like I did) that when you pass a two-dimensional
// array to a function you need to specify the number of "rows"
dgetrf_(&N, &N, M[0], &N, pivotArray, &errorHandler);
printf ("dgetrf eh, %d, should be zero\n", errorHandler);
dgetri_(&N, M[0], &N, pivotArray, lapackWorkspace, &NN, &errorHandler);
printf ("dgetri eh, %d, should be zero\n", errorHandler);
for (size_t row = 0; row < N; ++row)
{ for (size_t col = 0; col < N; ++col)
{ printf ("%g", M[row][col]);
if (N-1 != col)
{ printf (", "); } }
if (N-1 != row)
{ printf ("\n"); } }
return 0; }
構建並運行這樣的:
$ gcc foo.c -llapack
$ ./a.out
dgetrf eh, 0, should be zero
dgetri eh, 0, should be zero
-1.56667, 0.466667, 0.1
1.13333, 0.0666667, -0.2
0.1, -0.2, 0.1
編輯
謎似乎不再是一個謎。我認爲計算是按照列主要的順序完成的,因爲它們必須這樣做,但我同時輸入和打印這些矩陣,就好像它們是按照主要順序排列的一樣。我有兩個互相抵消的錯誤,所以事情看起來很划算,儘管它們是列式的。
關於1X9或3×3。內存佈局方面確實沒有任何區別。事實上,BLAS/LAPACK例程不需要2d陣列。他們採用一維數組,並假設你如何佈置它。請注意BLAS和LAPACK將假設FORTRAN排序(行更改最快)而不是C排序。 – MRocklin 2012-10-18 18:28:09
您可能需要'LAPACKE_dgetrf'而不是fortran例程'dgetrf_'。同上'dgetri'。否則你必須使用地址來調用所有內容。 – 2016-05-20 02:32:48