【轉,並已經試驗成功,其中記住裏面有個問題,是添加CLAPACK庫文件後,需要將編譯方式更改爲CLAPACK編譯時的編譯方式,否則會報錯“fatal error LNK1169: one or more multiply defined symbols found”】
關於CLAPACK的使用網上的資料並不多。主要就是官方網站上的安裝說明,以及LAPACK官方論壇上的一些資料。然而,國外一般科研使用的平臺都是UNIX或LINUX, 所以對於windows上使用CLAPACK的相關介紹就很少。幸運的是,官方提供了CLAPACK的windows版本,而且還有專門的VisualStudio工程包。所以,對於廣大VS用戶來說可謂非常之方便。
然而,即使如此,很多人在使用的過程中還是出現這樣那樣的問題。其中,多數的情況都是出在編譯的時候。而且上網提問多數都沒人能夠解答。
鑑於此,本人就對如何在VC上編譯和使用CLAPACK庫,作下簡單的說明。
1、什麼是CLAPACK:
CLAPACK是LAPACK的C語言接口。LAPACK的全稱是Linear Algebra PACKage,是非常著名的線性代數庫。原版的LAPACK是用Fortran寫的,爲了方便C/C++程序的使用,就有了LAPACK的C接口CLAPACK。
LAPACK的主頁是 http://www.netlib.org/lapack/
CLAPACK則在 http://www.netlib.org/clapack/。
這兩個庫都是開源的,可以在官方網站免費下載和使用。
2、CLAPACK的安裝:
所謂的安裝其實就是把源代碼編譯成我們可以調用的庫.lib文件。
首先從主頁上下載CLAPACK包。http://www.netlib.org/clapack/ 上有很多版本。我們選擇
http://www.netlib.org/clapack/CLAPACK-3.1.1-VisualStudio.zip
大小: 42MB
版本: 3.1.1
是專門提供給VS用戶的。
(注意:VS的版本不能太低。VC6.0是無法使用的。VS2005及以上都應該沒問題。本人用的是VS2008。測試的時候發現工程文件版本太老,還需要轉換一下呢。當然轉換後運行也很正常。如果你堅持要使用VC++6.0那請下載http://www.netlib.org/clapack/CLAPACK3-Windows.zip 這是CLAPACK3.0版,比我介紹的版本3.1.1版要舊一些)
下載解壓後,我們可以看到如下目錄結構:
/SRC CLAPACK的源代碼
/BLAS BLAS的源代碼
/F2CLIBS F2C的源代碼
/LIB 編譯後的庫文件.lib
/INCLUDE 頭文件
/TESTING 一些使用範例程序
/INSTALL 裏面有UNIX和其他平臺下安裝的文件和方法。lawn81.pdf文件是CLAPACK的使用說明,大家使用的時候可以看看。
這裏我要提醒大家。雖然軟件包裏已經有編譯好的.lib文件,就在/LIB中。但是我建議大家不要直接使用他們,還是自己編譯一下再用才保險。很多人就是因爲直接使用他們而出錯的。這點非常重要!如果你就是直接調用他們失敗的,那不妨先自己編譯一下再試試。
另外,CLAPACK需要F2CLIBS庫,並且使用了blas和tmglib這兩個外部的庫。這幾個庫都已經包含在了CLAPACK的安裝包中。所以,大家無需另外下載。當然,使用前我們還是要重新編譯一下的,原因上面已經說過了。
接下來,我詳細地講講如何編譯他們。
首先雙擊 clapack.vcproj打開工程項目文件。工程中已經包含了所有的子項目。
我們根據個人需要,編譯成debug模式,或者release模式。爲了能在自己的程序調用中方便的進行debug,我這裏就以debug模式爲例說明。我的系統是win32。如果你是64位系統也是支持的,操作方法類似。
首先編譯F2CLIBS,用於將fortran轉換爲c語言。
選擇libf2c子項目。直接生成之。編譯過程中可能會有一些warning,不要理會他們。編譯成功後,輸出文件是libf2cd.lib。這裏的d就是debug模式,如果是release模式就是libf2c.lib。輸出文件默認路徑是/LIB文件夾。注意,/LIB/Win32下已經有一些lib了。大家最好把他們都先刪除了,以免新舊文件混淆。
接着編譯tmglib。這是一個矩陣庫。
這個庫在TESTING/MATGEN裏面。選擇他生成就好了。
輸出文件還是在/LIB裏面。文件名是tmglibd.lib。
然後是編譯blas,選擇項目blas, 編譯之。輸出文件BLASd.lib。
最後是編譯CLAPACK,生成clapackd.lib.
其他模式對應的輸出文件大家可以參看下錶。
這裏需要注意的是,不同模式間不要混合使用。
Win 32
Configuration | F2c | Reference BLAS | CLAPACK | CBLASWRAP | F77BLASWRAP | TMGLIB |
Win32 - Release | ||||||
Win32 - Release no wrap |
|
|
|
|||
Win32 - Debug | ||||||
Win32 - Debug no wrap |
|
|
|
x64
Configuration | F2c | Reference BLAS | CLAPACK | CBLASWRAP | F77BLASWRAP | TMGLIB |
x64 - Release | ||||||
x64 - Release no wrap |
|
|
|
|||
x64 - Debug | ||||||
x64 - Debug no wrap |
|
|
|
3、如何調用CLAPACK:
前面,我們已經生成了CLAPACK的庫文件了。那麼如何在自己的程序中使用他們呢?
其實很簡單。你所需要的只有兩部分:
1)頭文件
頭文件就是.h文件。存放在/INCLUDE中。在自己的工程里加入這個目錄就行了。裏面的文件最好不要作任何修改。程序中主要調用的頭文件是clapack.h和f2c.h。
2)庫文件
庫文件就是我們前面編譯生成的那些lib文件了。
這裏,我就以一個具體的調用實例詳細地說明如何在VC中設置和使用CLAPACK。
首先,VC中項目的設置方式是:
項目的屬性裏。C/C++選項卡中,附加包含目錄裏添加/INCLUDE目錄。
連接器選項卡中。附加庫目錄裏添加/LIB/Win32目錄。然後附加依賴項添加libf2cd.lib BLASd.lib clapackd.lib tmglibd.lib。(根據不同的編譯模式和個人需要以及系統需要選擇庫文件)
另外,如果想在調試時能對庫函數進行源碼級調試。那麼需要在VS的 工具--選項--項目和解決方案--VC++目錄 中添加/SRC的目錄。
本文,我們將調用CLAPACK的一個函數dgesvd_()來學習使用的方法。
注意: 包括此函數在內的所有的CLAPACK函數可以在/SRC下找到源代碼,並在代碼中有函數參數的說明信息。dgesvd_的代碼文件就是dgesvd.c。
dgesvd_的函數聲明:
int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n,
doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,
integer *info)
dgesvd_的功能是對一個實矩陣A進行SVD分解(singular value decomposition)。
即 A = U * SIGMA * transpose(V)
dgesvd.c文件裏有詳細地函數說明和參數說明。
SIGMA is an M-by-N matrix which is zero except for its
min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and
V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA
are the singular values of A; they are real and non-negative, and
are returned in descending order. The first min(m,n) columns of
U and V are the left and right singular vectors of A.
Note that the routine returns V**T, not V.
.........................................
參數的具體說明也請參看這個文件的 Arguments部分
代碼:
#include <stdio.h>
#include <process.h>
//因爲程序是C++,而CLAPACK是f2c程序轉換的C語言版本,所以在此處用extern關鍵字調用
extern"C"
{
#include <f2c.h>
#include <clapack.h>
}
#define SIZE 4
int main()
{
char JOBU;
char JOBVT;
int i;
//數據類型integer是fortran裏的。這裏在C++下可以使用的原因是f2c.h文件中已經作了定義
integer M = SIZE;
integer N = SIZE;
integer LDA = M;
integer LDU = M;
integer LDVT = N;
integer LWORK;
integer INFO;
integer mn = min( M, N );
integer MN = max( M, N );
double a[SIZE*SIZE] = { 16.0, 5.0, 9.0 , 4.0, 2.0, 11.0, 7.0 , 14.0, 3.0, 10.0, 6.0, 15.0, 13.0, 8.0, 12.0, 1.0};
double s[SIZE];
double wk[201];
double uu[SIZE*SIZE];
double vt[SIZE*SIZE];
JOBU = 'A';
JOBVT = 'A';
LWORK = 201;
/* Subroutine int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n,
doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,
integer *info)
*/
dgesvd_( &JOBU, &JOBVT, &M, &N, a, &LDA, s, uu, &LDU, vt, &LDVT, wk, &LWORK, &INFO);
printf("INFO=%d /n", INFO );
for ( i= 0; i< SIZE; i++ ) {
printf("s[ %d ] = %f/n", i, s[ i ] );
}
system("pause");
return 0;
}
運算結果輸出:
INFO=0
s[ 0 ] = 34.000000
s[ 1 ] = 17.888544
s[ 2 ] = 4.472136
s[ 3 ] = 0.000000
注意:這個例子中我們使用的庫是clapackd.lib。
libf2cd.lib BLASd.lib tmglibd.lib都沒有用到。
總之需要什麼庫就用什麼庫。
關鍵點是一定要自己編譯生成這些.lib文件來使用。不要用現成的,以免出錯。