# HG changeset patch
# User pantxo <pantxo.diribarne@gmail.com>
# Date 1392043198 -3600
#      Mon Feb 10 15:39:58 2014 +0100
# Node ID 9d6af67c1868405c7595a35dbb3cfa5e3fdb2844
# Parent  07ca8b9f8cab4ca5a29c52efaa9249613a943bd3
eigs-base.cc: report aprpack error strings instead of error number

* eigs-base.cc: add new function "std::string arpack_errno2str (const octave_idx_type& errno, const std::string& fcn_name)"
* eigs-base.cc: report error strings after call to xxxupd 

diff -r 07ca8b9f8cab -r 9d6af67c1868 liboctave/numeric/eigs-base.cc
--- a/liboctave/numeric/eigs-base.cc	Mon Feb 03 22:32:12 2014 -0800
+++ b/liboctave/numeric/eigs-base.cc	Mon Feb 10 15:39:58 2014 +0100
@@ -164,6 +164,180 @@
 
 }
 
+// Conversion from error number to strings
+std::string 
+arpack_errno2str (const octave_idx_type& errno, const std::string& fcn_name)
+{
+  std::string msg = "";
+  std::string bug_msg = "\nThis should not happen. Please, see http://www.gnu.org/software/octave/bugs.html, and file a bug report";
+
+  switch (errno)
+    {
+    case -1:
+      {
+        msg = std::string ("N must be positive");
+        break;
+      }
+    case -2:
+      {
+        msg = std::string ("NEV must be positive");
+        break;
+      }
+    case -3:
+      {
+        msg = std::string ("NCV-NEV >= 2 and less than or equal to N");
+        break;
+      }
+    case -4:
+      {
+        msg = std::string ("The maximum number of Arnoldi update iterations allowed must be greater than zero");
+        break;
+      }
+    case -5:
+      {
+        msg = std::string ("WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'");
+        break;
+      }
+    case -6:
+      {
+        msg = std::string ("BMAT must be one of 'I' or 'G'");
+        break;
+      }
+    case -7:
+      {
+        msg = std::string ("Length of private work WORKL array is not sufficient");
+        break;
+      }
+    case -8:
+      {
+        msg = std::string ("Error return from LAPACK eigenvalue calculation");
+        break;
+      }
+    case -9:
+      {
+        if (fcn_name.compare ("zneupd") == 0)
+          msg = std::string ("Error return from calculation of eigenvectors. Informational error from LAPACK routine ztrevc");
+        else if (fcn_name.compare ("dneupd") == 0)
+          msg = std::string ("Error return from calculation of eigenvectors. Informational error from LAPACK routine dtrevc");
+        else
+          msg = std::string ("Starting vector is zero");
+
+        break;
+      }
+    case -10:
+      {
+        if (fcn_name.compare ("dneupd") == 0 | 
+            fcn_name.compare ("dnaupd") == 0)
+          msg = std::string ("IPARAM(7) must be 1,2,3,4");
+        else if (fcn_name.compare ("zneupd") == 0 | 
+                 fcn_name.compare ("znaupd") == 0)
+          msg = std::string ("IPARAM(7) must be 1,2,3");
+        else
+          msg = std::string ("IPARAM(7) must be 1,2,3,4,5");
+
+        break;
+      }
+    case -11:
+      {
+        msg = std::string ("IPARAM(7) = 1 and BMAT = 'G' are incompatible");
+        break;
+      }
+    case -12:
+      {
+        if (fcn_name.compare ("dnaupd") == 0 | 
+            fcn_name.compare ("znaupd") == 0 |
+            fcn_name.compare ("dsaupd") == 0)
+          msg = std::string ("IPARAM(1) must be equal to 0 or 1");
+        else if (fcn_name.compare ("dneupd") == 0 | 
+                 fcn_name.compare ("zneupd") == 0)
+          msg = std::string ("HOWMNY = 'S' not yet implemented");
+        else
+          msg = std::string ("NEV and WHICH = 'BE' are incompatible");
+        
+        break;
+      }
+    case -13:
+      {
+        if (fcn_name.compare ("dneupd") == 0 | 
+            fcn_name.compare ("zneupd") == 0)
+          msg = std::string ("HOWMNY must be one of 'A' or 'P' if RVEC = .true.");
+        else if (fcn_name.compare ("dsaupd") == 0)
+          msg = std::string ("NEV and WHICH = 'BE' are incompatible");
+        
+        break;
+      }
+    case -14:
+      {
+        if (fcn_name.compare ("dneupd") == 0)
+          msg = std::string ("DNAUPD did not find any eigenvalues to sufficient accuracy.");
+        else if (fcn_name.compare ("zneupd") == 0)
+          msg = std::string ("ZNAUPD did not find any eigenvalues to sufficient accuracy.");
+        else if (fcn_name.compare ("dseupd") == 0)
+          msg = std::string ("DSAUPD did not find any eigenvalues to sufficient accuracy.");
+        
+        break;
+      } 
+    case -15:
+      {
+        if (fcn_name.compare ("dseupd") == 0)
+          msg = std::string ("HOWMNY must be one of 'A' or 'S' if RVEC = .true.");
+        
+        break;
+      }
+    case -16:
+      {
+        if (fcn_name.compare ("dseupd") == 0)
+          msg = std::string ("HOWMNY = 'S' not yet implemented");
+        
+        break;
+      }
+    case -9999:
+      {
+        if (fcn_name.compare ("dnaupd") == 0)
+          msg = std::string ("Could not build an Arnoldi factorization. IPARAM(5) returns the size of the current Arnoldi factorization");
+        
+        break;
+      }  
+    case 1:
+      {
+        if (fcn_name.compare ("dneupd") == 0)
+          msg = std::string ("The Schur form computed by LAPACK routine dlahqr could not be reordered by LAPACK routine dtrsen. Re-enter subroutine DNEUPD with IPARAM(5)=NCV and increase the size of the arrays DR and DI to have dimension at least dimension NCV and allocate at least NCV columns for Z. NOTE: Not necessary if Z and V share the same space. Please notify the authors if this error occurs.");
+        else if (fcn_name.compare ("dnaupd") == 0 | 
+                 fcn_name.compare ("znaupd") == 0 |
+                 fcn_name.compare ("dsaupd") == 0)
+          msg = std::string ("Maximum number of iterations taken. All possible eigenvalues of OP has been found. IPARAM(5) returns the number of wanted converged Ritz values");
+        else if (fcn_name.compare ("znaupd") == 0)
+          msg = std::string ("The Schur form computed by LAPACK routine csheqr could not be reordered by LAPACK routine ztrsen. Re-enter subroutine ZNEUPD with IPARAM(5)=NCV and increase the size of the array D to have dimension at least dimension NCV and allocate at least NCV columns for Z. NOTE: Not necessary if Z and V share the same space. Please notify the authors if this error occurs.");
+        
+        break;
+      }
+    case 2:
+      {
+        if (fcn_name.compare ("dnaupd") == 0| 
+            fcn_name.compare ("znaupd") == 0|
+            fcn_name.compare ("dsaupd") == 0)
+          msg = std::string ("No longer an informational error. Deprecated starting with release 2 of ARPACK.");
+        
+        break;
+      }
+    case 3:
+      {
+        if (fcn_name.compare ("dnaupd") == 0| 
+            fcn_name.compare ("znaupd") == 0|
+            fcn_name.compare ("dsaupd") == 0)
+          msg = std::string ("No shifts could be applied during a cycle of the implicitly restarted Arnoldi iteration. One possibility is to increase the size of NCV relative to NEV.");
+        
+        break;
+      }
+    }
+  
+  if ((errno != -9) & (errno != -14) & (errno != -9999))
+    // This is a bug in octave interface to Arpack
+    msg.append (bug_msg);
+
+  return msg;
+}
+
 
 #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
 static octave_idx_type
@@ -768,6 +942,7 @@
   return true;
 }
 
+
 template <class M>
 octave_idx_type
 EigsRealSymmetricMatrix (const M& m, const std::string typ,
@@ -995,7 +1170,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -1081,7 +1257,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dseupd", info2);
+            ("eigs: error in dseupd: %s", 
+             arpack_errno2str (info2, "dseupd").c_str ());
           return -1;
         }
     }
@@ -1332,7 +1509,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -1409,7 +1587,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dseupd", info2);
+            ("eigs: error in dseupd: %s", 
+                 arpack_errno2str (info2, "dseupd").c_str ());
           return -1;
         }
     }
@@ -1590,7 +1769,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -1673,7 +1853,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dseupd", info2);
+            ("eigs: error in dseupd: %s", 
+             arpack_errno2str (info2, "dseupd").c_str ());
           return -1;
         }
     }
@@ -1909,7 +2090,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dnaupd", info);
+                ("eigs: error in dnaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -2042,7 +2224,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dneupd", info2);
+            ("eigs: error in dneupd: %s", 
+             arpack_errno2str (info2, "dneupd").c_str ());
           return -1;
         }
     }
@@ -2295,7 +2478,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -2425,7 +2609,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dneupd", info2);
+            ("eigs: error in dneupd: %s", 
+             arpack_errno2str (info2, "dneupd").c_str ());
           return -1;
         }
     }
@@ -2607,7 +2792,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -2737,7 +2923,8 @@
       else
         {
           (*current_liboctave_error_handler)
-            ("eigs: error %d in dneupd", info2);
+            ("eigs: error in dneupd: %s", 
+             arpack_errno2str (info2, "dneupd").c_str ());
           return -1;
         }
     }
@@ -2920,6 +3107,7 @@
   OCTAVE_LOCAL_BUFFER (double, rwork, p);
   Complex *presid = cresid.fortran_vec ();
 
+  
   do
     {
       F77_FUNC (znaupd, ZNAUPD)
@@ -2977,7 +3165,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in znaupd", info);
+                ("eigs: error in znaupd: %s", 
+                 arpack_errno2str (info, "znaupd").c_str ());
               return -1;
             }
           break;
@@ -3059,7 +3248,8 @@
   else
     {
       (*current_liboctave_error_handler)
-        ("eigs: error %d in zneupd", info2);
+        ("eigs: error in zneupd: %s", 
+         arpack_errno2str (info2, "zneupd").c_str ());
       return -1;
     }
 
@@ -3317,7 +3507,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -3396,7 +3587,8 @@
   else
     {
       (*current_liboctave_error_handler)
-        ("eigs: error %d in zneupd", info2);
+        ("eigs: error in zneupd: %s", 
+         arpack_errno2str (info2, "zneupd").c_str ());
       return -1;
     }
 
@@ -3581,7 +3773,8 @@
           if (info < 0)
             {
               (*current_liboctave_error_handler)
-                ("eigs: error %d in dsaupd", info);
+                ("eigs: error in dsaupd: %s", 
+                 arpack_errno2str (info, "dsaupd").c_str ());
               return -1;
             }
           break;
@@ -3660,7 +3853,8 @@
   else
     {
       (*current_liboctave_error_handler)
-        ("eigs: error %d in zneupd", info2);
+        ("eigs: error in zneupd: %s", 
+         arpack_errno2str (info2, "zneupd").c_str ());
       return -1;
     }
 
