エラーができて実行ができないプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
STR

エラーができて実行ができないプログラム

#1

投稿記事 by STR » 3年前

コード:

// 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: エラーができて実行ができないプログラム

#2

投稿記事 by あんどーなつ » 3年前

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

inemaru
記事: 108
登録日時: 3年前

Re: エラーができて実行ができないプログラム

#3

投稿記事 by inemaru » 3年前

エラーを見る限り58行目で、テンプレート引数を解決できてないだけっぽい
以下のコードで、解決しませんか?

コード:

  // info = zgesv( A, x, b );
  info = zgesv<N>( A, x, b );

STR

Re: エラーができて実行ができないプログラム

#4

投稿記事 by STR » 3年前

回答ありがとうございます。
早速試してみましたが、以下のエラーが発生されました。

エラー 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 件の未解決の外部参照

inemaru
記事: 108
登録日時: 3年前

Re: エラーができて実行ができないプログラム

#5

投稿記事 by inemaru » 3年前

そのエラーは、「関数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 )
  {
        // ここに実装を書く
  }
};

STR

Re: エラーができて実行ができないプログラム

#6

投稿記事 by STR » 3年前

コード:

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;
}

inemaru
記事: 108
登録日時: 3年前

Re: エラーができて実行ができないプログラム

#7

投稿記事 by inemaru » 3年前

後はライブラリリンクだけできればよかったのに、
なぜ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);
};

STR

Re: エラーができて実行ができないプログラム

#8

投稿記事 by STR » 3年前

だいたいエラーの原因わかりました。解決にはもう少しかかりそうですがひとまずは自分で模索してみます。
回答ありがとうございしましま!

STR

Re: エラーができて実行ができないプログラム

#9

投稿記事 by STR » 3年前

だいたいエラーの原因わかりました。解決にはもう少しかかりそうですがひとまずは自分で模索してみます。
回答ありがとうございしましま!

閉鎖

“C言語何でも質問掲示板” へ戻る