Support verbosity parameter in glp_exact

Patch based on http://lists.gnu.org/archive/html/help-glpk/2011-10/msg00037.html

diff -ru a/doc/glpk02.tex b/doc/glpk02.tex
--- a/doc/glpk02.tex	2017-07-25 09:00:00.000000000 +0200
+++ b/doc/glpk02.tex	2017-08-31 13:28:11.559220389 +0200
@@ -2014,9 +2014,9 @@
 exact in mathematical sense, i.e. free of round-off errors unlike
 floating-point arithmetic.
 
-Note that the routine \verb|glp_exact| uses only two control parameters
-passed in the structure \verb|glp_smcp|, namely, \verb|it_lim| and
-\verb|tm_lim|.
+Note that the routine \verb|glp_exact| uses only three control parameters
+passed in the structure \verb|glp_smcp|, namely, \verb|it_lim|,
+\verb|tm_lim| and \verb|msg\_lev|.
 
 \returns
 
diff -ru a/src/glpapi07.c b/src/glpapi07.c
--- a/src/glpapi07.c	2017-07-25 09:00:00.000000000 +0200
+++ b/src/glpapi07.c	2017-08-31 14:03:54.395718543 +0200
@@ -267,6 +267,13 @@
       if (parm == NULL)
          parm = &_parm, glp_init_smcp((glp_smcp *)parm);
       /* check control parameters */
+      if (!(parm->msg_lev == GLP_MSG_OFF ||
+            parm->msg_lev == GLP_MSG_ERR ||
+            parm->msg_lev == GLP_MSG_ON  ||
+            parm->msg_lev == GLP_MSG_ALL ||
+            parm->msg_lev == GLP_MSG_DBG))
+         xerror("glp_simplex: msg_lev = %d; invalid parameter\n",
+            parm->msg_lev);
       if (parm->it_lim < 0)
          xerror("glp_exact: it_lim = %d; invalid parameter\n",
             parm->it_lim);
@@ -275,7 +282,8 @@
             parm->tm_lim);
       /* the problem must have at least one row and one column */
       if (!(m > 0 && n > 0))
-      {  xprintf("glp_exact: problem has no rows/columns\n");
+      {  if (parm->msg_lev >= GLP_MSG_ERR)
+            xprintf("glp_exact: problem has no rows/columns\n");
          return GLP_EFAIL;
       }
 #if 1
@@ -297,31 +305,35 @@
             ub = lp->col[k-m]->ub;
          }
          if (type == GLP_DB && lb >= ub)
-         {  xprintf("glp_exact: %s %d has invalid bounds\n",
+         {  if (parm->msg_lev >= GLP_MSG_ERR)
+               xprintf("glp_exact: %s %d has invalid bounds\n",
                k <= m ? "row" : "column", k <= m ? k : k-m);
             return GLP_EBOUND;
          }
       }
       /* create the simplex solver workspace */
-      xprintf("glp_exact: %d rows, %d columns, %d non-zeros\n",
+      if (parm->msg_lev >= GLP_MSG_ALL)
+      {  xprintf("glp_exact: %d rows, %d columns, %d non-zeros\n",
          m, n, nnz);
 #ifdef HAVE_GMP
-      xprintf("GNU MP bignum library is being used\n");
+         xprintf("GNU MP bignum library is being used\n");
 #else
-      xprintf("GLPK bignum module is being used\n");
-      xprintf("(Consider installing GNU MP to attain a much better perf"
-         "ormance.)\n");
+         xprintf("GLPK bignum module is being used\n");
+         xprintf("(Consider installing GNU MP to attain a much better performance.)\n");
 #endif
+      }
       ssx = ssx_create(m, n, nnz);
       /* load LP problem data into the workspace */
       load_data(ssx, lp);
       /* load current LP basis into the workspace */
       if (load_basis(ssx, lp))
-      {  xprintf("glp_exact: initial LP basis is invalid\n");
+      {  if (parm->msg_lev >= GLP_MSG_ERR)
+            xprintf("glp_exact: initial LP basis is invalid\n");
          ret = GLP_EBADB;
          goto done;
       }
       /* inherit some control parameters from the LP object */
+      ssx->msg_lev = parm->msg_lev;
 #if 0
       ssx->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM);
       ssx->it_cnt = lpx_get_int_parm(lp, LPX_K_ITCNT);
diff -ru a/src/glpssx02.c b/src/glpssx02.c
--- a/src/glpssx02.c	2017-07-25 09:00:00.000000000 +0200
+++ b/src/glpssx02.c	2017-08-31 13:28:11.559220389 +0200
@@ -132,7 +132,7 @@
       ssx_eval_pi(ssx);
       ssx_eval_cbar(ssx);
       /* display initial progress of the search */
-      show_progress(ssx, 1);
+      if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 1);
       /* main loop starts here */
       for (;;)
       {  /* display current progress of the search */
@@ -141,7 +141,7 @@
 #else
          if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
 #endif
-            show_progress(ssx, 1);
+            if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 1);
          /* we do not need to wait until all artificial variables have
             left the basis */
          if (mpq_sgn(bbar[0]) == 0)
@@ -243,7 +243,7 @@
          ssx->it_cnt++;
       }
       /* display final progress of the search */
-      show_progress(ssx, 1);
+      if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 1);
       /* restore components of the original problem, which were changed
          by the routine */
       for (k = 1; k <= m+n; k++)
@@ -282,7 +282,7 @@
 int ssx_phase_II(SSX *ssx)
 {     int ret;
       /* display initial progress of the search */
-      show_progress(ssx, 2);
+      if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 2);
       /* main loop starts here */
       for (;;)
       {  /* display current progress of the search */
@@ -291,7 +291,7 @@
 #else
          if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001)
 #endif
-            show_progress(ssx, 2);
+            if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 2);
          /* check if the iterations limit has been exhausted */
          if (ssx->it_lim == 0)
          {  ret = 2;
@@ -347,7 +347,7 @@
          ssx->it_cnt++;
       }
       /* display final progress of the search */
-      show_progress(ssx, 2);
+      if (ssx->msg_lev >= GLP_MSG_ON) show_progress(ssx, 2);
       /* return to the calling program */
       return ret;
 }
@@ -419,15 +419,15 @@
             ret = 0;
             break;
          case 1:
-            xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n");
             ret = 1;
             break;
          case 2:
-            xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
             ret = 3;
             break;
          case 3:
-            xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
             ret = 5;
             break;
          default:
@@ -446,19 +446,19 @@
       ret = ssx_phase_II(ssx);
       switch (ret)
       {  case 0:
-            xprintf("OPTIMAL SOLUTION FOUND\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("OPTIMAL SOLUTION FOUND\n");
             ret = 0;
             break;
          case 1:
-            xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n");
             ret = 2;
             break;
          case 2:
-            xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) printf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n");
             ret = 4;
             break;
          case 3:
-            xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
+            if (ssx->msg_lev >= GLP_MSG_ALL) xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n");
             ret = 6;
             break;
          default:
diff -ru a/src/glpssx.h b/src/glpssx.h
--- a/src/glpssx.h	2017-07-25 09:00:00.000000000 +0200
+++ b/src/glpssx.h	2017-08-31 13:59:05.577754269 +0200
@@ -25,6 +25,7 @@
 #ifndef GLPSSX_H
 #define GLPSSX_H
 
+#include "glpk.h"
 #include "bfx.h"
 #include "env.h"
 
@@ -337,6 +338,12 @@
 #endif
       /* the most recent time, in seconds, at which the progress of the
          the search was displayed */
+      int msg_lev;
+      /* sets the verbosity of simplex solver
+         GLP_MSG_OFF	no output
+         GLP_MSG_ERR	report errors and warnings
+         GLP_MSG_ON		normal output
+         GLP_MSG_ALL	highest verbosity */
 };
 
 #define ssx_create            _glp_ssx_create
