Mercurial > octave
changeset 24289:f52d91f6ef80 stable
Check ARPACK library for buggy behavior in configure (bug #52425)
* configure.ac: Call both OCTAVE_CHECK_LIB_ARPACK_OK_1 and new
OCTAVE_CHECK_LIB_ARPACK_OK_2 to determine if ARPACK library is okay.
* m4/acinclude.m4 (OCTAVE_CHECK_LIB_ARPACK_OK_1): Macro renamed from
OCTAVE_CHECK_LIB_ARPACK_OK. Minor whitespace and punctuation changes.
* m4/acinclude.m4 (OCTAVE_CHECK_LIB_ARPACK_OK_2): New macro with test
Fortran code to check whether ARPACK library is buggy.
author | Rik <rik@octave.org> |
---|---|
date | Tue, 21 Nov 2017 17:49:18 -0800 |
parents | 1ad2297f8ece |
children | 8612ab9fc564 e24bf08dc559 |
files | configure.ac m4/acinclude.m4 |
diffstat | 2 files changed, 156 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.ac Mon Jul 24 16:48:03 2017 +0200 +++ b/configure.ac Tue Nov 21 17:49:18 2017 -0800 @@ -2145,9 +2145,14 @@ [dseupd], [Fortran 77], [don't use the ARPACK library, disable eigs function], [warn_arpack= - OCTAVE_CHECK_LIB_ARPACK_OK( + OCTAVE_CHECK_LIB_ARPACK_OK_1( [AC_DEFINE(HAVE_ARPACK, 1, [Define to 1 if ARPACK is available.])], - [warn_arpack="ARPACK library found, but does not seem to work properly; disabling eigs function"])]) + [warn_arpack="ARPACK library found, but does not seem to work properly; disabling eigs function"]) + if test -z "$warn_arpack"; then + OCTAVE_CHECK_LIB_ARPACK_OK_2([], + [warn_arpack="ARPACK library found, but is buggy; upgrade library (>= v3.3.0) for better results"]) + fi + ]) LIBS="$save_LIBS" ### Check for readline library.
--- a/m4/acinclude.m4 Mon Jul 24 16:48:03 2017 +0200 +++ b/m4/acinclude.m4 Tue Nov 21 17:49:18 2017 -0800 @@ -742,16 +742,16 @@ dnl Check whether ARPACK works (does not crash). dnl dnl Using a pure Fortran program doesn't seem to crash when linked -dnl with the buggy ARPACK library but the C++ program does. Maybe it +dnl with the buggy ARPACK library, but the C++ program does. Maybe it dnl is the memory allocation that exposes the bug and using statically dnl allocated arrays in Fortran does not? dnl dnl FIXME: it would be nice to avoid the duplication of F77 macros dnl and typedefs here and in the f77-fcn.h header file. dnl -AC_DEFUN([OCTAVE_CHECK_LIB_ARPACK_OK], [ +AC_DEFUN([OCTAVE_CHECK_LIB_ARPACK_OK_1], [ AC_CACHE_CHECK([whether the arpack library works], - [octave_cv_lib_arpack_ok], + [octave_cv_lib_arpack_ok_1], [AC_LANG_PUSH(C++) AC_RUN_IFELSE([AC_LANG_PROGRAM([[ @@ -818,13 +818,13 @@ { // Based on function EigsRealNonSymmetricMatrix from liboctave/eigs-base.cc. - // Problem matrix. See bug #31479 + // Problem matrix. See bug #31479. octave_idx_type n = 4; double *m = new double [n * n]; m[0] = 1, m[4] = 0, m[8] = 0, m[12] = -1; - m[1] = 0, m[5] = 1, m[9] = 0, m[13] = 0; - m[2] = 0, m[6] = 0, m[10] = 1, m[14] = 0; - m[3] = 0, m[7] = 0, m[11] = 2, m[15] = 1; + m[1] = 0, m[5] = 1, m[9] = 0, m[13] = 0; + m[2] = 0, m[6] = 0, m[10] = 1, m[14] = 0; + m[3] = 0, m[7] = 0, m[11] = 2, m[15] = 1; double *resid = new double [4]; @@ -883,9 +883,7 @@ else { if (info < 0) - { - return; // Error - } + return; // Error break; } @@ -900,7 +898,7 @@ double *workev = new double [3 * p]; for (octave_idx_type i = 0; i < k + 1; i++) - dr[i] = di[i] = 0.; + dr[i] = di[i] = 0.0; octave_idx_type rvec = 1; @@ -925,13 +923,149 @@ for (int i = 0; i < 10; i++) doit (); + ]])], - octave_cv_lib_arpack_ok=yes, - octave_cv_lib_arpack_ok=no, - octave_cv_lib_arpack_ok=yes) + octave_cv_lib_arpack_ok_1=yes, + octave_cv_lib_arpack_ok_1=no, + octave_cv_lib_arpack_ok_1=yes) AC_LANG_POP(C++) ]) - if test $octave_cv_lib_arpack_ok = yes; then + if test $octave_cv_lib_arpack_ok_1 = yes; then + $1 + : + else + $2 + : + fi +]) +dnl +dnl Check whether ARPACK is buggy (it doesn't crash, but gets wrong answers). +dnl +dnl ARPACK versions < 3.3.0 have a bug which results in different eigenvalues +dnl being calculated depending on whether eigenvectors are also requested. +dnl See bug #52425. +dnl +AC_DEFUN([OCTAVE_CHECK_LIB_ARPACK_OK_2], [ + AC_CACHE_CHECK([whether the arpack library is free of bugs], + [octave_cv_lib_arpack_ok_2], + [AC_LANG_PUSH(Fortran 77) + AC_RUN_IFELSE([[ + program bug_52425 +c + integer maxn, maxnev, maxncv, ldv + parameter (maxn=256, maxnev=10, maxncv=25, + $ ldv=maxn ) +c + Double precision + & v(ldv,maxncv), workl(maxncv*(maxncv+8)), + & workd(3*maxn), d(maxncv,2), resid(maxn), + & ax(maxn) + logical select(maxncv) + integer iparam(11), ipntr(11) +c + character bmat*1, which*2 + integer ido, n, nev, ncv, lworkl, info, ierr, j, + & nx, nconv, maxitr, mode, ishfts + logical rvec + Double precision + & tol, sigma +c + Double precision + & zero + parameter (zero = 0.0D+0) +c + Double precision + & dnrm2 + external dnrm2, daxpy +c + intrinsic abs +c + n = 20 + nev = 4 + ncv = 20 + bmat = 'I' + which = 'BE' +c + lworkl = ncv*(ncv+8) + tol = zero + info = 1 + do j = 1,n + resid (j) = 1.0d0 + end do + ido = 0 +c + ishfts = 1 + maxitr = 300 + mode = 1 +c + iparam(1) = ishfts + iparam(3) = maxitr + iparam(7) = mode +c + 10 continue +c + call dsaupd ( ido, bmat, n, which, nev, tol, resid, + & ncv, v, ldv, iparam, ipntr, workd, workl, + & lworkl, info ) +c + if (ido .eq. -1 .or. ido .eq. 1) then + call av (n, workd(ipntr(1)), workd(ipntr(2))) + go to 10 + end if +c + if ( info .lt. 0 ) then + stop 1 + else + rvec = .false. +c + call dseupd ( rvec, 'All', select, d, v, ldv, sigma, + & bmat, n, which, nev, tol, resid, ncv, v, ldv, + & iparam, ipntr, workd, workl, lworkl, ierr ) +c + if ( ierr .ne. 0) then + stop 1 + else + nconv = iparam(5) + do 20 j=1, nconv + call av(n, v(1,j), ax) + call daxpy(n, -d(j,1), v(1,j), 1, ax, 1) + d(j,2) = dnrm2(n, ax, 1) + d(j,2) = d(j,2) / abs(d(j,1)) +c + 20 continue +c +c | Litmus test: return 1 or 0 based on returned eigenvalue +c + if (abs(d(1,1) - 2.0810) > 1.0d-4) then + stop 1 + else + stop 0 + end if + end if + end if +c + end +c + subroutine av (n, v, w) + integer n, j + Double precision v(n), w(n) +c + w(1) = 4*v(1) + v(3) + w(2) = 4*v(2) + v(4) + do 10 j = 3, n - 2 + w(j) = v(j-2) + 4*v(j) + v(j+2) + 10 continue + w(n-1) = v(n-3) + 4 * v(n-1) + w(n) = v(n-2) + 4 * v(n) + return + end + ]], + octave_cv_lib_arpack_ok_2=yes, + octave_cv_lib_arpack_ok_2=no, + octave_cv_lib_arpack_ok_2=yes) + AC_LANG_POP(Fortran 77) + ]) + if test $octave_cv_lib_arpack_ok_2 = yes; then $1 : else