Mercurial > octave-nkf
comparison m4/acinclude.m4 @ 14147:71e28fda7be9 stable
use C++ program to test ARPACK
* acinclude.m4 (OCTAVE_CHECK_ARPACK_OK): Use C++ instead of Fortran
for the test program.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 05 Jan 2012 00:10:19 -0500 |
parents | 834df9f10963 |
children | 99428221b4e1 |
comparison
equal
deleted
inserted
replaced
14146:2f05228cb959 | 14147:71e28fda7be9 |
---|---|
1015 fi | 1015 fi |
1016 ]) | 1016 ]) |
1017 dnl | 1017 dnl |
1018 dnl Check whether ARPACK works (does not crash) | 1018 dnl Check whether ARPACK works (does not crash) |
1019 dnl | 1019 dnl |
1020 dnl Using a pure Fortran program doesn't seem to crash when linked | |
1021 dnl with the buggy ARPACK library but the C++ program does. Maybe | |
1022 dnl it is the memory allocation that exposes the bug and using statically | |
1023 dnl allocated arrays in Fortran does not? | |
1024 dnl | |
1020 AC_DEFUN([OCTAVE_CHECK_ARPACK_OK], [ | 1025 AC_DEFUN([OCTAVE_CHECK_ARPACK_OK], [ |
1021 AC_LANG_PUSH(Fortran 77) | 1026 AC_LANG_PUSH(C++) |
1022 AC_CACHE_CHECK([whether the arpack library works], | 1027 AC_CACHE_CHECK([whether the arpack library works], |
1023 [octave_cv_lib_arpack_ok], [ | 1028 [octave_cv_lib_arpack_ok], [ |
1024 AC_RUN_IFELSE([AC_LANG_PROGRAM([], [[ | 1029 AC_RUN_IFELSE([AC_LANG_PROGRAM([[ |
1025 * Based on function EigsRealNonSymmetricMatrix from liboctave/eigs-base.cc. | 1030 // External functions from ARPACK library |
1026 * Problem matrix. See bug #31479 | 1031 extern "C" int |
1027 | 1032 F77_FUNC (dnaupd, DNAUPD) (int&, const char *, const int&, const char *, |
1028 integer rvec, ido, info, ii, jj | 1033 int&, const double&, double*, const int&, |
1029 double precision tol, sigmar, sigmai | 1034 double*, const int&, int*, int*, double*, |
1030 | 1035 double*, const int&, int&, long int, long int); |
1031 integer n, k, p, lwork | 1036 |
1032 parameter (n = 4, k = 1, p = 3, lwork = 3*p*(p+2)) | 1037 extern "C" int |
1033 | 1038 F77_FUNC (dneupd, DNEUPD) (const int&, const char *, int*, double*, |
1034 integer ip (11) | 1039 double*, double*, const int&, |
1035 integer ipntr (14) | 1040 const double&, const double&, double*, |
1036 integer sel (p) | 1041 const char*, const int&, const char *, |
1037 | 1042 int&, const double&, double*, const int&, |
1038 double precision m (n, n) | 1043 double*, const int&, int*, int*, double*, |
1039 double precision resid (4) | 1044 double*, const int&, int&, long int, |
1040 double precision v (n*(p+1)); | 1045 long int, long int); |
1041 double precision workl (lwork+1) | 1046 |
1042 double precision workd (3*n+1) | 1047 extern "C" int |
1043 * In Octave, the dimensions of dr and di are k+1, but k+2 avoids segfault | 1048 F77_FUNC (dgemv, DGEMV) (const char *, const int&, const int&, |
1044 double precision dr (k+1) | 1049 const double&, const double*, const int&, |
1045 double precision di (k+1) | 1050 const double*, const int&, const double&, |
1046 double precision workev (3*p) | 1051 double*, const int&, long int); |
1047 * In Octave, this is n*(k+1), but k+2 avoids segfault | 1052 |
1048 double precision z (n*(k+1)) | 1053 #include <cfloat> |
1049 | 1054 |
1050 do 10 ii = 1, 100 | 1055 void |
1051 | 1056 doit (void) |
1052 m(1,1) = 1 | 1057 { |
1053 m(2,1) = 0 | 1058 // Based on function EigsRealNonSymmetricMatrix from liboctave/eigs-base.cc. |
1054 m(3,1) = 0 | 1059 |
1055 m(4,1) = 0 | 1060 // Problem matrix. See bug #31479 |
1056 | 1061 int n = 4; |
1057 m(1,2) = 0 | 1062 double *m = new double [n * n]; |
1058 m(2,2) = 1 | 1063 m[0] = 1, m[4] = 0, m[8] = 0, m[12] = -1; |
1059 m(3,2) = 0 | 1064 m[1] = 0, m[5] = 1, m[9] = 0, m[13] = 0; |
1060 m(4,2) = 0 | 1065 m[2] = 0, m[6] = 0, m[10] = 1, m[14] = 0; |
1061 | 1066 m[3] = 0, m[7] = 0, m[11] = 2, m[15] = 1; |
1062 m(1,3) = 0 | 1067 |
1063 m(2,3) = 0 | 1068 double *resid = new double [4]; |
1064 m(3,3) = 1 | 1069 |
1065 m(4,3) = 2 | 1070 resid[0] = 0.960966; |
1066 | 1071 resid[1] = 0.741195; |
1067 m(1,4) = -1 | 1072 resid[2] = 0.150143; |
1068 m(2,4) = 0 | 1073 resid[3] = 0.868067; |
1069 m(3,4) = 0 | 1074 |
1070 m(4,4) = 1 | 1075 int *ip = new int [11]; |
1071 | 1076 |
1072 resid(1) = 0.960966 | 1077 ip[0] = 1; // ishift |
1073 resid(1) = 0.741195 | 1078 ip[1] = 0; // ip[1] not referenced |
1074 resid(1) = 0.150143 | 1079 ip[2] = 300; // mxiter, maximum number of iterations |
1075 resid(1) = 0.868067 | 1080 ip[3] = 1; // NB blocksize in recurrence |
1076 | 1081 ip[4] = 0; // nconv, number of Ritz values that satisfy convergence |
1077 * ip(1) = ishift | 1082 ip[5] = 0; // ip[5] not referenced |
1078 * ip(2) is not referenced | 1083 ip[6] = 1; // mode |
1079 * ip(3) = maximum number of iterations | 1084 ip[7] = 0; // ip[7] to ip[10] are return values |
1080 * ip(4) = NB blocksize in recurrence | 1085 ip[8] = 0; |
1081 * ip(5) = nconv, number of Ritz values that satisfy convergence | 1086 ip[9] = 0; |
1082 * ip(6) is not referenced | 1087 ip[10] = 0; |
1083 * ip(7) = mode | 1088 |
1084 * ip(8) to ip(11) are return values | 1089 int *ipntr = new int [14]; |
1085 | 1090 |
1086 ip(1) = 1 | 1091 int k = 1; |
1087 ip(2) = 0 | 1092 int p = 3; |
1088 ip(3) = 300 | 1093 int lwork = 3 * p * (p + 2); |
1089 ip(4) = 1 | 1094 |
1090 ip(5) = 0 | 1095 double *v = new double [n * (p + 1)]; |
1091 ip(6) = 0 | 1096 double *workl = new double [lwork + 1]; |
1092 ip(7) = 1 | 1097 double *workd = new double [3 * n + 1]; |
1093 ip(8) = 0 | 1098 |
1094 ip(9) = 0 | 1099 int ido = 0; |
1095 ip(10) = 0 | 1100 int info = 0; |
1096 ip(11) = 0 | 1101 |
1097 | 1102 double tol = DBL_EPSILON; |
1098 ido = 0 | 1103 |
1099 info = 0 | 1104 do |
1100 rvec = 1 | 1105 { |
1101 sigmar = 0 | 1106 F77_FUNC (dnaupd, DNAUPD) (ido, "I", n, "LM", k, tol, resid, p, |
1102 sigmai = 0 | 1107 v, n, ip, ipntr, workd, workl, lwork, |
1103 tol = 2.0d-15 | 1108 info, 1L, 2L); |
1104 | 1109 |
1105 1 continue | 1110 if (ido == -1 || ido == 1 || ido == 2) |
1106 | 1111 { |
1107 call dnaupd (ido, 'I', n, 'LM', k, tol, resid, p, v, n, ip, | 1112 double *x = workd + ipntr[0] - 1; |
1108 $ ipntr, workd, workl, lwork, info) | 1113 double *y = workd + ipntr[1] - 1; |
1109 | 1114 |
1110 if (ido .eq. -1 .or. ido .eq. 1 .or. ido .eq. 2) then | 1115 F77_FUNC (dgemv, DGEMV) ("N", n, n, 1.0, m, n, x, 1, 0.0, |
1111 call dgemv ('N', n, n, 1.0, m, n, workd(ipntr(1)), | 1116 y, 1, 1L); |
1112 $ 1, 0.0, workd(ipntr(2)), 1) | 1117 } |
1113 goto 1 | 1118 else |
1114 else if (info .lt. 0) then | 1119 { |
1115 * error | 1120 if (info < 0) |
1116 goto 9999 | 1121 { |
1117 endif | 1122 return; // Error |
1118 | 1123 } |
1119 do 10 jj = 1, k+1 | 1124 |
1120 dr(jj) = 0 | 1125 break; |
1121 di(jj) = 0 | 1126 } |
1122 10 continue | 1127 } |
1123 | 1128 while (1); |
1124 call dneupd (rvec, "A", sel, dr, di, z, n, sigmar, sigmai, | 1129 |
1125 $ workev,"I", n, "LM", k, tol, resid, p, v, n, ip, ipntr, | 1130 int *sel = new int [p]; |
1126 $ workd,workl, lwork, info) | 1131 |
1127 | 1132 // In Octave, the dimensions of dr and di are k+1, but k+2 avoids segfault |
1128 100 continue | 1133 double *dr = new double [k + 1]; |
1129 | 1134 double *di = new double [k + 1]; |
1130 9999 continue | 1135 double *workev = new double [3 * p]; |
1136 | |
1137 for (int i = 0; i < k + 1; i++) | |
1138 dr[i] = di[i] = 0.; | |
1139 | |
1140 int rvec = 1; | |
1141 | |
1142 double sigmar = 0.0; | |
1143 double sigmai = 0.0; | |
1144 | |
1145 // In Octave, this is n*(k+1), but k+2 avoids segfault | |
1146 double *z = new double [n * (k + 1)]; | |
1147 | |
1148 F77_FUNC (dneupd, DNEUPD) (rvec, "A", sel, dr, di, z, n, sigmar, | |
1149 sigmai, workev, "I", n, "LM", k, tol, | |
1150 resid, p, v, n, ip, ipntr, workd, | |
1151 workl, lwork, info, 1L, 1L, 2L); | |
1152 } | |
1153 ]], [[ | |
1154 for (int i = 0; i < 10; i++) | |
1155 doit (); | |
1131 ]])], | 1156 ]])], |
1132 [octave_cv_lib_arpack_ok=yes], | 1157 [octave_cv_lib_arpack_ok=yes], |
1133 [octave_cv_lib_arpack_ok=no], | 1158 [octave_cv_lib_arpack_ok=no], |
1134 [octave_cv_lib_arpack_ok=yes])]) | 1159 [octave_cv_lib_arpack_ok=yes])]) |
1135 AC_LANG_POP(Fortran 77) | 1160 AC_LANG_POP(C++) |
1136 if test "$octave_cv_lib_arpack_ok" = "yes"; then | 1161 if test "$octave_cv_lib_arpack_ok" = "yes"; then |
1137 $1 | 1162 $1 |
1138 else | 1163 else |
1139 $2 | 1164 $2 |
1140 fi | 1165 fi |