ページ 1 / 1
エラーができて実行ができないプログラム
Posted: 2016年10月25日(火) 17:42
by STR
コード:
// zgesv.cc
// 複素一般行列の線形方程式を解く
#include "stdafx.h"
#include <stdio.h>
#include <complex>
typedef std::complex<double> Complex;
extern "C" {
void zgesv_ ( const int& N, const int& NRHS,
Complex** A, const int& LDA, int* IPIV,
Complex** B, const int& LDB, int& INFO );
};
// 複素一般行列 A の線形方程式 A x = b を解く簡易関数
// Input: A[N][N], b[N] Output: x[N]
//
template <int N> int zgesv( Complex A[N][N], Complex x[N], const Complex b[N] )
{
int i, j, info;
static int ipiv[N];
static Complex U[N][N];
for( i=0; i<N; i++ ){
for( j=0; j<N; j++ ){
U[i][j] = A[j][i];
}
x[i] = b[i];
}
zgesv_( N, 1, (Complex**)U, N, ipiv, (Complex**)x, N, info );
return info;
}
int main(void)
{
const int N = 4;
int i, j, info;
Complex A[N][N];
Complex x[N], b[N];
for( i=0; i<N; i++ ){
for( j=0; j<N; j++ ){
if( i==j ){
A[i][j] = 2.0;
}else{
A[i][j] = 1.0;
}
}
b[i] = 5.0;
}
info = zgesv( A, x, b );
printf("# info=%d.\n", info );
printf("# Solution.\n");
for( j=0; j<N; j++ ){
printf("%+f%+f\n", real(x[j]), imag(x[j]) );
}
printf("# Error.\n");
for( i=0; i<N; i++ ){
Complex sum=0.0;
for( j=0; j<N; j++ ){
sum += A[i][j]*x[j];
}
sum -= b[i];
printf("%+f%+f\n", real(sum), imag(sum) );
}
return 0;
}
以上のプログラムでLAPACKを用いたC++固有値計算をしようと思っていますが、VisualStudio 2012 Expressでは、
エラー 1 error C2784: 'int zgesv(Complex [N][N],Complex [N],const Complex [N])' : テンプレート 引数を 'Complex [N][N]' に対して 'Complex [4][4]' から減少できませんでした
というエラーが出てしまいます;;
以下のサイトの複素一般行列 Aの方程式 A x =b を解く (zgesv)
にあったコードそのものに、 stdafx.hを使っています。
http://www-cms.phys.s.u-tokyo.ac.jp/~na ... RO/LAPACK/
解決策をご存知な方、是非ご助言お願いします
Re: エラーができて実行ができないプログラム
Posted: 2016年10月25日(火) 19:42
by あんどーなつ
LAPACKはさわったことないけど、Visual Studioより先にg++でビルドしてみるのがいいのでないかな。
g++はWindowsではCygwinでインストールできる。
とはいえ、Cygwinも、g++もmakeもbashもすぐすぐできる代物ではない。
g++でちょっとビルドしてみたけど、以下のエラー出ました。
$ make
g++ -O4 dgesv.cc -L/usr/local/lib -llapack -lblas -o dgesv
/usr/lib/gcc/x86_64-pc-cygwin/5.3.0/../../../../x86_64-pc-cygwin/bin/ld: -llapack が見つかりません
/usr/lib/gcc/x86_64-pc-cygwin/5.3.0/../../../../x86_64-pc-cygwin/bin/ld: -lblas が見つかりません
collect2: エラー: ld はステータス 1 で終了しました
Makefile:13: ターゲット 'dgesv' のレシピで失敗しました
make: *** [dgesv] エラー 1
Re: エラーができて実行ができないプログラム
Posted: 2016年10月25日(火) 23:42
by inemaru
エラーを見る限り58行目で、テンプレート引数を解決できてないだけっぽい
以下のコードで、解決しませんか?
コード:
// info = zgesv( A, x, b );
info = zgesv<N>( A, x, b );
Re: エラーができて実行ができないプログラム
Posted: 2016年10月25日(火) 23:57
by STR
回答ありがとうございます。
早速試してみましたが、以下のエラーが発生されました。
エラー 1 error LNK2019: 未解決の外部シンボル _zgesv_ が関数 "int __cdecl zgesv<4>(class std::complex<double> (* const)[4],class std::complex<double> * const,class std::complex<double> const * const)" (??$zgesv@$03@@YAHQAY03V?$complex@N@std@@QAV01@QBV01@@Z) で参照されました。
エラー 2 error LNK1120: 1 件の未解決の外部参照
Re: エラーができて実行ができないプログラム
Posted: 2016年10月26日(水) 00:04
by inemaru
そのエラーは、「関数zgesv_の実体がない」というエラーだと思われますが
Lapackライブラリのリンクが、できていないのでは?
コード:
extern "C" {
// Lapackライブラリの関数呼び出し用の定義
void zgesv_ ( const int& N, const int& NRHS,
Complex** A, const int& LDA, int* IPIV,
Complex** B, const int& LDB, int& INFO );
};
もし自前で実装するのであれば、(本末転倒)
コード:
extern "C" {
void zgesv_ ( const int& N, const int& NRHS,
Complex** A, const int& LDA, int* IPIV,
Complex** B, const int& LDB, int& INFO )
{
// ここに実装を書く
}
};
Re: エラーができて実行ができないプログラム
Posted: 2016年10月26日(水) 00:51
by STR
コード:
extern "C"{
#include "f2c.h"
#include "clapack.h"
}
http://momose-d.cocolog-nifty.com/blog/ ... dio-2.html
以上のページ同様に追加してみたのですが、どうもcomplexをincludeしているのが
原因で、
realがあいまい
Complex から real に変換できません
などの他、
error C2733: 'zgesv_' : オーバーロードされた関数の C リンケージの 2 回以上の宣言は許されません。
というのもありました。
以下コード全文です。
コード:
// zgesv.cc
// 複素一般行列の線形方程式を解く
#include "stdafx.h"
#include< iostream >
#include< complex >
extern "C"{
#include "f2c.h"
#include "clapack.h"
}
using namespace std;
extern "C" {
void zgesv_ ( const int& n, const int& nrhs,
Complex** a, const int& lda, int* ipiv,
Complex** b, const int& ldb, int& info );
};
#pragma comment(lib, "C:\\lapack\\lapack.lib")
#pragma comment(lib, "C:\\lapack\\blas.lib")
#pragma comment(lib, "C:\\lapack\\libf2c.lib")
typedef std::complex<double> Complex;
// 複素一般行列 A の線形方程式 A x = b を解く簡易関数
// Input: A[N][N], b[N] Output: x[N]
//
template <int N> int zgesv( Complex A[N][N], Complex x[N], const Complex b[N] )
{
int i, j, info;
static int ipiv[N];
static Complex U[N][N];
for( i=0; i<N; i++ ){
for( j=0; j<N; j++ ){
U[i][j] = A[j][i];
}
x[i] = b[i];
}
zgesv_( N, 1, (Complex**)U, N, ipiv, (Complex**)x, N, info );
return info;
}
int main(void)
{
const int N = 4;
int i, j, info;
Complex A[N][N];
Complex x[N], b[N];
for( i=0; i<N; i++ ){
for( j=0; j<N; j++ ){
if( i==j ){
A[i][j] = 2.0;
}else{
A[i][j] = 1.0;
}
}
b[i] = 5.0;
}
info = zgesv<N>( A, x, b );
//info = zgesv<N>( A, x, b );
printf("# info=%d.\n", info );
printf("# Solution.\n");
for( j=0; j<N; j++ ){
printf("%+f%+f\n", real(x[j]), imag(x[j]) );
}
printf("# Error.\n");
for( i=0; i<N; i++ ){
Complex sum=0.0;
for( j=0; j<N; j++ ){
sum += A[i][j]*x[j];
}
sum -= b[i];
printf("%+f%+f\n", real(sum), imag(sum) );
}
return 0;
}
Re: エラーができて実行ができないプログラム
Posted: 2016年10月26日(水) 01:33
by inemaru
後はライブラリリンクだけできればよかったのに、
なぜCLAPACKに変更したのでしょうか?
CLAPACKは使用経験がないので、自分では分かりかねます。
とりあえず、エラーについて
予想で答えます。
STR さんが書きました:
error C2733: 'zgesv_' : オーバーロードされた関数の C リンケージの 2 回以上の宣言は許されません。
CLAPACK側に同名(zgesv_)の定義があるため、エラーしていると予想。
STR さんが書きました:
realがあいまい
Complex から real に変換できません
どこかに定義されたreal関数とstd::real関数が名前衝突したと予想。
提示されたコードで怪しいと思った点を修正しました。
コード:
// zgesv.cc
// 複素一般行列の線形方程式を解く
#include "stdafx.h"
#include <iostream>
#include <complex>
#pragma comment(lib, "C:\\lapack\\lapack.lib")
#pragma comment(lib, "C:\\lapack\\blas.lib")
#pragma comment(lib, "C:\\lapack\\libf2c.lib")
extern "C" {
// 以下のどっちかに、zgesv_ 関数の定義が入っている?
// 以下のどっちかに、real 関数の定義が入っている?
#include "f2c.h"
#include "clapack.h"
}
// extern "C" {
// void zgesv_(const int& n, const int& nrhs,
// Complex** a, const int& lda, int* ipiv,
// Complex** b, const int& ldb, int& info);
// };
typedef std::complex<double> Complex;
// 複素一般行列 A の線形方程式 A x = b を解く簡易関数
// Input: A[N][N], b[N] Output: x[N]
//
template <int N> int zgesv(Complex A[N][N], Complex x[N], const Complex b[N])
{
int i, j, info;
static int ipiv[N];
static Complex U[N][N];
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
U[i][j] = A[j][i];
}
x[i] = b[i];
}
// ↓の関数がCLAPACKの定義だと無効 コンパイルエラーすると思う
zgesv_(N, 1, (Complex**)U, N, ipiv, (Complex**)x, N, info);
return info;
}
int main(void)
{
const int N = 4;
int i, j, info;
Complex A[N][N];
Complex x[N], b[N];
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (i == j) {
A[i][j] = 2.0;
}
else {
A[i][j] = 1.0;
}
}
b[i] = 5.0;
}
info = zgesv<N>(A, x, b);
printf("# info=%d.\n", info);
printf("# Solution.\n");
for (j = 0; j < N; j++) {
printf("%+f%+f\n", std::real(x[j]), imag(x[j]));
}
printf("# Error.\n");
for (i = 0; i < N; i++) {
Complex sum = 0.0;
for (j = 0; j < N; j++) {
sum += A[i][j] * x[j];
}
sum -= b[i];
printf("%+f%+f\n", std::real(sum), imag(sum));
}
return 0;
}
先にも書きましたが、CLAPACKは経験がないので、
後は詳しい人に任せます。
オフトピック
もし本家LAPACKのライブラリをリンクできていれば、以下のコードでコンパイルできます。
コード:
// LAPACKのライブラリをリンクする
#pragma comment(lib, "liblapack.lib")
extern "C" {
void zgesv_(const int& N, const int& NRHS,
Complex** A, const int& LDA, int* IPIV,
Complex** B, const int& LDB, int& INFO);
};
Re: エラーができて実行ができないプログラム
Posted: 2016年10月26日(水) 07:48
by STR
だいたいエラーの原因わかりました。解決にはもう少しかかりそうですがひとまずは自分で模索してみます。
回答ありがとうございしましま!
Re: エラーができて実行ができないプログラム
Posted: 2016年10月26日(水) 07:49
by STR
だいたいエラーの原因わかりました。解決にはもう少しかかりそうですがひとまずは自分で模索してみます。
回答ありがとうございしましま!