src/glphbm.c
changeset 2 4c8956a7bdf4
equal deleted inserted replaced
-1:000000000000 0:9830d3ae7a85
       
     1 /* glphbm.c */
       
     2 
       
     3 /***********************************************************************
       
     4 *  This code is part of GLPK (GNU Linear Programming Kit).
       
     5 *
       
     6 *  Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
       
     7 *  2009, 2010 Andrew Makhorin, Department for Applied Informatics,
       
     8 *  Moscow Aviation Institute, Moscow, Russia. All rights reserved.
       
     9 *  E-mail: <mao@gnu.org>.
       
    10 *
       
    11 *  GLPK is free software: you can redistribute it and/or modify it
       
    12 *  under the terms of the GNU General Public License as published by
       
    13 *  the Free Software Foundation, either version 3 of the License, or
       
    14 *  (at your option) any later version.
       
    15 *
       
    16 *  GLPK is distributed in the hope that it will be useful, but WITHOUT
       
    17 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    18 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
       
    19 *  License for more details.
       
    20 *
       
    21 *  You should have received a copy of the GNU General Public License
       
    22 *  along with GLPK. If not, see <http://www.gnu.org/licenses/>.
       
    23 ***********************************************************************/
       
    24 
       
    25 #define _GLPSTD_ERRNO
       
    26 #define _GLPSTD_STDIO
       
    27 #include "glphbm.h"
       
    28 #include "glpenv.h"
       
    29 
       
    30 /***********************************************************************
       
    31 *  NAME
       
    32 *
       
    33 *  hbm_read_mat - read sparse matrix in Harwell-Boeing format
       
    34 *
       
    35 *  SYNOPSIS
       
    36 *
       
    37 *  #include "glphbm.h"
       
    38 *  HBM *hbm_read_mat(const char *fname);
       
    39 *
       
    40 *  DESCRIPTION
       
    41 *
       
    42 *  The routine hbm_read_mat reads a sparse matrix in the Harwell-Boeing
       
    43 *  format from a text file whose name is the character string fname.
       
    44 *
       
    45 *  Detailed description of the Harwell-Boeing format recognised by this
       
    46 *  routine is given in the following report:
       
    47 *
       
    48 *  I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing
       
    49 *  Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992.
       
    50 *
       
    51 *  RETURNS
       
    52 *
       
    53 *  If no error occured, the routine hbm_read_mat returns a pointer to
       
    54 *  a data structure containing the matrix. In case of error the routine
       
    55 *  prints an appropriate error message and returns NULL. */
       
    56 
       
    57 struct dsa
       
    58 {     /* working area used by routine hbm_read_mat */
       
    59       const char *fname;
       
    60       /* name of input text file */
       
    61       FILE *fp;
       
    62       /* stream assigned to input text file */
       
    63       int seqn;
       
    64       /* card sequential number */
       
    65       char card[80+1];
       
    66       /* card image buffer */
       
    67       int fmt_p;
       
    68       /* scale factor */
       
    69       int fmt_k;
       
    70       /* iterator */
       
    71       int fmt_f;
       
    72       /* format code */
       
    73       int fmt_w;
       
    74       /* field width */
       
    75       int fmt_d;
       
    76       /* number of decimal places after point */
       
    77 };
       
    78 
       
    79 /***********************************************************************
       
    80 *  read_card - read next data card
       
    81 *
       
    82 *  This routine reads the next 80-column card from the input text file
       
    83 *  and stores its image into the character string card. If the card was
       
    84 *  read successfully, the routine returns zero, otherwise non-zero. */
       
    85 
       
    86 static int read_card(struct dsa *dsa)
       
    87 {     int k, c;
       
    88       dsa->seqn++;
       
    89       memset(dsa->card, ' ', 80), dsa->card[80] = '\0';
       
    90       k = 0;
       
    91       for (;;)
       
    92       {  c = fgetc(dsa->fp);
       
    93          if (ferror(dsa->fp))
       
    94          {  xprintf("%s:%d: read error - %s\n", dsa->fname, dsa->seqn,
       
    95                strerror(errno));
       
    96             return 1;
       
    97          }
       
    98          if (feof(dsa->fp))
       
    99          {  if (k == 0)
       
   100                xprintf("%s:%d: unexpected EOF\n", dsa->fname,
       
   101                   dsa->seqn);
       
   102             else
       
   103                xprintf("%s:%d: missing final LF\n", dsa->fname,
       
   104                   dsa->seqn);
       
   105             return 1;
       
   106          }
       
   107          if (c == '\r') continue;
       
   108          if (c == '\n') break;
       
   109          if (iscntrl(c))
       
   110          {  xprintf("%s:%d: invalid control character 0x%02X\n",
       
   111                dsa->fname, dsa->seqn, c);
       
   112             return 1;
       
   113          }
       
   114          if (k == 80)
       
   115          {  xprintf("%s:%d: card image too long\n", dsa->fname,
       
   116                dsa->seqn);
       
   117             return 1;
       
   118          }
       
   119          dsa->card[k++] = (char)c;
       
   120       }
       
   121       return 0;
       
   122 }
       
   123 
       
   124 /***********************************************************************
       
   125 *  scan_int - scan integer value from the current card
       
   126 *
       
   127 *  This routine scans an integer value from the current card, where fld
       
   128 *  is the name of the field, pos is the position of the field, width is
       
   129 *  the width of the field, val points to a location to which the scanned
       
   130 *  value should be stored. If the value was scanned successfully, the
       
   131 *  routine returns zero, otherwise non-zero. */
       
   132 
       
   133 static int scan_int(struct dsa *dsa, char *fld, int pos, int width,
       
   134       int *val)
       
   135 {     char str[80+1];
       
   136       xassert(1 <= width && width <= 80);
       
   137       memcpy(str, dsa->card + pos, width), str[width] = '\0';
       
   138       if (str2int(strspx(str), val))
       
   139       {  xprintf("%s:%d: field `%s' contains invalid value `%s'\n",
       
   140             dsa->fname, dsa->seqn, fld, str);
       
   141          return 1;
       
   142       }
       
   143       return 0;
       
   144 }
       
   145 
       
   146 /***********************************************************************
       
   147 *  parse_fmt - parse Fortran format specification
       
   148 *
       
   149 *  This routine parses the Fortran format specification represented as
       
   150 *  character string which fmt points to and stores format elements into
       
   151 *  appropriate static locations. Should note that not all valid Fortran
       
   152 *  format specifications may be recognised. If the format specification
       
   153 *  was recognised, the routine returns zero, otherwise non-zero. */
       
   154 
       
   155 static int parse_fmt(struct dsa *dsa, char *fmt)
       
   156 {     int k, s, val;
       
   157       char str[80+1];
       
   158       /* first character should be left parenthesis */
       
   159       if (fmt[0] != '(')
       
   160 fail: {  xprintf("hbm_read_mat: format `%s' not recognised\n", fmt);
       
   161          return 1;
       
   162       }
       
   163       k = 1;
       
   164       /* optional scale factor */
       
   165       dsa->fmt_p = 0;
       
   166       if (isdigit((unsigned char)fmt[k]))
       
   167       {  s = 0;
       
   168          while (isdigit((unsigned char)fmt[k]))
       
   169          {  if (s == 80) goto fail;
       
   170             str[s++] = fmt[k++];
       
   171          }
       
   172          str[s] = '\0';
       
   173          if (str2int(str, &val)) goto fail;
       
   174          if (toupper((unsigned char)fmt[k]) != 'P') goto iter;
       
   175          dsa->fmt_p = val, k++;
       
   176          if (!(0 <= dsa->fmt_p && dsa->fmt_p <= 255)) goto fail;
       
   177          /* optional comma may follow scale factor */
       
   178          if (fmt[k] == ',') k++;
       
   179       }
       
   180       /* optional iterator */
       
   181       dsa->fmt_k = 1;
       
   182       if (isdigit((unsigned char)fmt[k]))
       
   183       {  s = 0;
       
   184          while (isdigit((unsigned char)fmt[k]))
       
   185          {  if (s == 80) goto fail;
       
   186             str[s++] = fmt[k++];
       
   187          }
       
   188          str[s] = '\0';
       
   189          if (str2int(str, &val)) goto fail;
       
   190 iter:    dsa->fmt_k = val;
       
   191          if (!(1 <= dsa->fmt_k && dsa->fmt_k <= 255)) goto fail;
       
   192       }
       
   193       /* format code */
       
   194       dsa->fmt_f = toupper((unsigned char)fmt[k++]);
       
   195       if (!(dsa->fmt_f == 'D' || dsa->fmt_f == 'E' ||
       
   196             dsa->fmt_f == 'F' || dsa->fmt_f == 'G' ||
       
   197             dsa->fmt_f == 'I')) goto fail;
       
   198       /* field width */
       
   199       if (!isdigit((unsigned char)fmt[k])) goto fail;
       
   200       s = 0;
       
   201       while (isdigit((unsigned char)fmt[k]))
       
   202       {  if (s == 80) goto fail;
       
   203          str[s++] = fmt[k++];
       
   204       }
       
   205       str[s] = '\0';
       
   206       if (str2int(str, &dsa->fmt_w)) goto fail;
       
   207       if (!(1 <= dsa->fmt_w && dsa->fmt_w <= 255)) goto fail;
       
   208       /* optional number of decimal places after point */
       
   209       dsa->fmt_d = 0;
       
   210       if (fmt[k] == '.')
       
   211       {  k++;
       
   212          if (!isdigit((unsigned char)fmt[k])) goto fail;
       
   213          s = 0;
       
   214          while (isdigit((unsigned char)fmt[k]))
       
   215          {  if (s == 80) goto fail;
       
   216             str[s++] = fmt[k++];
       
   217          }
       
   218          str[s] = '\0';
       
   219          if (str2int(str, &dsa->fmt_d)) goto fail;
       
   220          if (!(0 <= dsa->fmt_d && dsa->fmt_d <= 255)) goto fail;
       
   221       }
       
   222       /* last character should be right parenthesis */
       
   223       if (!(fmt[k] == ')' && fmt[k+1] == '\0')) goto fail;
       
   224       return 0;
       
   225 }
       
   226 
       
   227 /***********************************************************************
       
   228 *  read_int_array - read array of integer type
       
   229 *
       
   230 *  This routine reads an integer array from the input text file, where
       
   231 *  name is array name, fmt is Fortran format specification that controls
       
   232 *  reading, n is number of array elements, val is array of integer type.
       
   233 *  If the array was read successful, the routine returns zero, otherwise
       
   234 *  non-zero. */
       
   235 
       
   236 static int read_int_array(struct dsa *dsa, char *name, char *fmt,
       
   237       int n, int val[])
       
   238 {     int k, pos;
       
   239       char str[80+1];
       
   240       if (parse_fmt(dsa, fmt)) return 1;
       
   241       if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 &&
       
   242             dsa->fmt_k * dsa->fmt_w <= 80))
       
   243       {  xprintf(
       
   244             "%s:%d: can't read array `%s' - invalid format `%s'\n",
       
   245             dsa->fname, dsa->seqn, name, fmt);
       
   246          return 1;
       
   247       }
       
   248       for (k = 1, pos = INT_MAX; k <= n; k++, pos++)
       
   249       {  if (pos >= dsa->fmt_k)
       
   250          {  if (read_card(dsa)) return 1;
       
   251             pos = 0;
       
   252          }
       
   253          memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w);
       
   254          str[dsa->fmt_w] = '\0';
       
   255          strspx(str);
       
   256          if (str2int(str, &val[k]))
       
   257          {  xprintf(
       
   258                "%s:%d: can't read array `%s' - invalid value `%s'\n",
       
   259                dsa->fname, dsa->seqn, name, str);
       
   260             return 1;
       
   261          }
       
   262       }
       
   263       return 0;
       
   264 }
       
   265 
       
   266 /***********************************************************************
       
   267 *  read_real_array - read array of real type
       
   268 *
       
   269 *  This routine reads a real array from the input text file, where name
       
   270 *  is array name, fmt is Fortran format specification that controls
       
   271 *  reading, n is number of array elements, val is array of real type.
       
   272 *  If the array was read successful, the routine returns zero, otherwise
       
   273 *  non-zero. */
       
   274 
       
   275 static int read_real_array(struct dsa *dsa, char *name, char *fmt,
       
   276       int n, double val[])
       
   277 {     int k, pos;
       
   278       char str[80+1], *ptr;
       
   279       if (parse_fmt(dsa, fmt)) return 1;
       
   280       if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 &&
       
   281             dsa->fmt_k * dsa->fmt_w <= 80))
       
   282       {  xprintf(
       
   283             "%s:%d: can't read array `%s' - invalid format `%s'\n",
       
   284             dsa->fname, dsa->seqn, name, fmt);
       
   285          return 1;
       
   286       }
       
   287       for (k = 1, pos = INT_MAX; k <= n; k++, pos++)
       
   288       {  if (pos >= dsa->fmt_k)
       
   289          {  if (read_card(dsa)) return 1;
       
   290             pos = 0;
       
   291          }
       
   292          memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w);
       
   293          str[dsa->fmt_w] = '\0';
       
   294          strspx(str);
       
   295          if (strchr(str, '.') == NULL && strcmp(str, "0"))
       
   296          {  xprintf("%s(%d): can't read array `%s' - value `%s' has no "
       
   297                "decimal point\n", dsa->fname, dsa->seqn, name, str);
       
   298             return 1;
       
   299          }
       
   300          /* sometimes lower case letters appear */
       
   301          for (ptr = str; *ptr; ptr++)
       
   302             *ptr = (char)toupper((unsigned char)*ptr);
       
   303          ptr = strchr(str, 'D');
       
   304          if (ptr != NULL) *ptr = 'E';
       
   305          /* value may appear with decimal exponent but without letters
       
   306             E or D (for example, -123.456-012), so missing letter should
       
   307             be inserted */
       
   308          ptr = strchr(str+1, '+');
       
   309          if (ptr == NULL) ptr = strchr(str+1, '-');
       
   310          if (ptr != NULL && *(ptr-1) != 'E')
       
   311          {  xassert(strlen(str) < 80);
       
   312             memmove(ptr+1, ptr, strlen(ptr)+1);
       
   313             *ptr = 'E';
       
   314          }
       
   315          if (str2num(str, &val[k]))
       
   316          {  xprintf(
       
   317                "%s:%d: can't read array `%s' - invalid value `%s'\n",
       
   318                dsa->fname, dsa->seqn, name, str);
       
   319             return 1;
       
   320          }
       
   321       }
       
   322       return 0;
       
   323 }
       
   324 
       
   325 HBM *hbm_read_mat(const char *fname)
       
   326 {     struct dsa _dsa, *dsa = &_dsa;
       
   327       HBM *hbm = NULL;
       
   328       dsa->fname = fname;
       
   329       xprintf("hbm_read_mat: reading matrix from `%s'...\n",
       
   330          dsa->fname);
       
   331       dsa->fp = fopen(dsa->fname, "r");
       
   332       if (dsa->fp == NULL)
       
   333       {  xprintf("hbm_read_mat: unable to open `%s' - %s\n",
       
   334             dsa->fname, strerror(errno));
       
   335          goto fail;
       
   336       }
       
   337       dsa->seqn = 0;
       
   338       hbm = xmalloc(sizeof(HBM));
       
   339       memset(hbm, 0, sizeof(HBM));
       
   340       /* read the first heading card */
       
   341       if (read_card(dsa)) goto fail;
       
   342       memcpy(hbm->title, dsa->card, 72), hbm->title[72] = '\0';
       
   343       strtrim(hbm->title);
       
   344       xprintf("%s\n", hbm->title);
       
   345       memcpy(hbm->key, dsa->card+72, 8), hbm->key[8] = '\0';
       
   346       strspx(hbm->key);
       
   347       xprintf("key = %s\n", hbm->key);
       
   348       /* read the second heading card */
       
   349       if (read_card(dsa)) goto fail;
       
   350       if (scan_int(dsa, "totcrd",  0, 14, &hbm->totcrd)) goto fail;
       
   351       if (scan_int(dsa, "ptrcrd", 14, 14, &hbm->ptrcrd)) goto fail;
       
   352       if (scan_int(dsa, "indcrd", 28, 14, &hbm->indcrd)) goto fail;
       
   353       if (scan_int(dsa, "valcrd", 42, 14, &hbm->valcrd)) goto fail;
       
   354       if (scan_int(dsa, "rhscrd", 56, 14, &hbm->rhscrd)) goto fail;
       
   355       xprintf("totcrd = %d; ptrcrd = %d; indcrd = %d; valcrd = %d; rhsc"
       
   356          "rd = %d\n", hbm->totcrd, hbm->ptrcrd, hbm->indcrd,
       
   357          hbm->valcrd, hbm->rhscrd);
       
   358       /* read the third heading card */
       
   359       if (read_card(dsa)) goto fail;
       
   360       memcpy(hbm->mxtype, dsa->card, 3), hbm->mxtype[3] = '\0';
       
   361       if (strchr("RCP",   hbm->mxtype[0]) == NULL ||
       
   362           strchr("SUHZR", hbm->mxtype[1]) == NULL ||
       
   363           strchr("AE",    hbm->mxtype[2]) == NULL)
       
   364       {  xprintf("%s:%d: matrix type `%s' not recognised\n",
       
   365             dsa->fname, dsa->seqn, hbm->mxtype);
       
   366          goto fail;
       
   367       }
       
   368       if (scan_int(dsa, "nrow", 14, 14, &hbm->nrow)) goto fail;
       
   369       if (scan_int(dsa, "ncol", 28, 14, &hbm->ncol)) goto fail;
       
   370       if (scan_int(dsa, "nnzero", 42, 14, &hbm->nnzero)) goto fail;
       
   371       if (scan_int(dsa, "neltvl", 56, 14, &hbm->neltvl)) goto fail;
       
   372       xprintf("mxtype = %s; nrow = %d; ncol = %d; nnzero = %d; neltvl ="
       
   373          " %d\n", hbm->mxtype, hbm->nrow, hbm->ncol, hbm->nnzero,
       
   374          hbm->neltvl);
       
   375       /* read the fourth heading card */
       
   376       if (read_card(dsa)) goto fail;
       
   377       memcpy(hbm->ptrfmt, dsa->card, 16), hbm->ptrfmt[16] = '\0';
       
   378       strspx(hbm->ptrfmt);
       
   379       memcpy(hbm->indfmt, dsa->card+16, 16), hbm->indfmt[16] = '\0';
       
   380       strspx(hbm->indfmt);
       
   381       memcpy(hbm->valfmt, dsa->card+32, 20), hbm->valfmt[20] = '\0';
       
   382       strspx(hbm->valfmt);
       
   383       memcpy(hbm->rhsfmt, dsa->card+52, 20), hbm->rhsfmt[20] = '\0';
       
   384       strspx(hbm->rhsfmt);
       
   385       xprintf("ptrfmt = %s; indfmt = %s; valfmt = %s; rhsfmt = %s\n",
       
   386          hbm->ptrfmt, hbm->indfmt, hbm->valfmt, hbm->rhsfmt);
       
   387       /* read the fifth heading card (optional) */
       
   388       if (hbm->rhscrd <= 0)
       
   389       {  strcpy(hbm->rhstyp, "???");
       
   390          hbm->nrhs = 0;
       
   391          hbm->nrhsix = 0;
       
   392       }
       
   393       else
       
   394       {  if (read_card(dsa)) goto fail;
       
   395          memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0';
       
   396          if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail;
       
   397          if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail;
       
   398          xprintf("rhstyp = `%s'; nrhs = %d; nrhsix = %d\n",
       
   399             hbm->rhstyp, hbm->nrhs, hbm->nrhsix);
       
   400       }
       
   401       /* read matrix structure */
       
   402       hbm->colptr = xcalloc(1+hbm->ncol+1, sizeof(int));
       
   403       if (read_int_array(dsa, "colptr", hbm->ptrfmt, hbm->ncol+1,
       
   404          hbm->colptr)) goto fail;
       
   405       hbm->rowind = xcalloc(1+hbm->nnzero, sizeof(int));
       
   406       if (read_int_array(dsa, "rowind", hbm->indfmt, hbm->nnzero,
       
   407          hbm->rowind)) goto fail;
       
   408       /* read matrix values */
       
   409       if (hbm->valcrd <= 0) goto done;
       
   410       if (hbm->mxtype[2] == 'A')
       
   411       {  /* assembled matrix */
       
   412          hbm->values = xcalloc(1+hbm->nnzero, sizeof(double));
       
   413          if (read_real_array(dsa, "values", hbm->valfmt, hbm->nnzero,
       
   414             hbm->values)) goto fail;
       
   415       }
       
   416       else
       
   417       {  /* elemental (unassembled) matrix */
       
   418          hbm->values = xcalloc(1+hbm->neltvl, sizeof(double));
       
   419          if (read_real_array(dsa, "values", hbm->valfmt, hbm->neltvl,
       
   420             hbm->values)) goto fail;
       
   421       }
       
   422       /* read right-hand sides */
       
   423       if (hbm->nrhs <= 0) goto done;
       
   424       if (hbm->rhstyp[0] == 'F')
       
   425       {  /* dense format */
       
   426          hbm->nrhsvl = hbm->nrow * hbm->nrhs;
       
   427          hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double));
       
   428          if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl,
       
   429             hbm->rhsval)) goto fail;
       
   430       }
       
   431       else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'A')
       
   432       {  /* sparse format */
       
   433          /* read pointers */
       
   434          hbm->rhsptr = xcalloc(1+hbm->nrhs+1, sizeof(int));
       
   435          if (read_int_array(dsa, "rhsptr", hbm->ptrfmt, hbm->nrhs+1,
       
   436             hbm->rhsptr)) goto fail;
       
   437          /* read sparsity pattern */
       
   438          hbm->rhsind = xcalloc(1+hbm->nrhsix, sizeof(int));
       
   439          if (read_int_array(dsa, "rhsind", hbm->indfmt, hbm->nrhsix,
       
   440             hbm->rhsind)) goto fail;
       
   441          /* read values */
       
   442          hbm->rhsval = xcalloc(1+hbm->nrhsix, sizeof(double));
       
   443          if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsix,
       
   444             hbm->rhsval)) goto fail;
       
   445       }
       
   446       else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'E')
       
   447       {  /* elemental format */
       
   448          hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double));
       
   449          if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl,
       
   450             hbm->rhsval)) goto fail;
       
   451       }
       
   452       else
       
   453       {  xprintf("%s:%d: right-hand side type `%c' not recognised\n",
       
   454             dsa->fname, dsa->seqn, hbm->rhstyp[0]);
       
   455          goto fail;
       
   456       }
       
   457       /* read starting guesses */
       
   458       if (hbm->rhstyp[1] == 'G')
       
   459       {  hbm->nguess = hbm->nrow * hbm->nrhs;
       
   460          hbm->sguess = xcalloc(1+hbm->nguess, sizeof(double));
       
   461          if (read_real_array(dsa, "sguess", hbm->rhsfmt, hbm->nguess,
       
   462             hbm->sguess)) goto fail;
       
   463       }
       
   464       /* read solution vectors */
       
   465       if (hbm->rhstyp[2] == 'X')
       
   466       {  hbm->nexact = hbm->nrow * hbm->nrhs;
       
   467          hbm->xexact = xcalloc(1+hbm->nexact, sizeof(double));
       
   468          if (read_real_array(dsa, "xexact", hbm->rhsfmt, hbm->nexact,
       
   469             hbm->xexact)) goto fail;
       
   470       }
       
   471 done: /* reading has been completed */
       
   472       xprintf("hbm_read_mat: %d cards were read\n", dsa->seqn);
       
   473       fclose(dsa->fp);
       
   474       return hbm;
       
   475 fail: /* something wrong in Danish kingdom */
       
   476       if (hbm != NULL)
       
   477       {  if (hbm->colptr != NULL) xfree(hbm->colptr);
       
   478          if (hbm->rowind != NULL) xfree(hbm->rowind);
       
   479          if (hbm->rhsptr != NULL) xfree(hbm->rhsptr);
       
   480          if (hbm->rhsind != NULL) xfree(hbm->rhsind);
       
   481          if (hbm->values != NULL) xfree(hbm->values);
       
   482          if (hbm->rhsval != NULL) xfree(hbm->rhsval);
       
   483          if (hbm->sguess != NULL) xfree(hbm->sguess);
       
   484          if (hbm->xexact != NULL) xfree(hbm->xexact);
       
   485          xfree(hbm);
       
   486       }
       
   487       if (dsa->fp != NULL) fclose(dsa->fp);
       
   488       return NULL;
       
   489 }
       
   490 
       
   491 /***********************************************************************
       
   492 *  NAME
       
   493 *
       
   494 *  hbm_free_mat - free sparse matrix in Harwell-Boeing format
       
   495 *
       
   496 *  SYNOPSIS
       
   497 *
       
   498 *  #include "glphbm.h"
       
   499 *  void hbm_free_mat(HBM *hbm);
       
   500 *
       
   501 *  DESCRIPTION
       
   502 *
       
   503 *  The hbm_free_mat routine frees all the memory allocated to the data
       
   504 *  structure containing a sparse matrix in the Harwell-Boeing format. */
       
   505 
       
   506 void hbm_free_mat(HBM *hbm)
       
   507 {     if (hbm->colptr != NULL) xfree(hbm->colptr);
       
   508       if (hbm->rowind != NULL) xfree(hbm->rowind);
       
   509       if (hbm->rhsptr != NULL) xfree(hbm->rhsptr);
       
   510       if (hbm->rhsind != NULL) xfree(hbm->rhsind);
       
   511       if (hbm->values != NULL) xfree(hbm->values);
       
   512       if (hbm->rhsval != NULL) xfree(hbm->rhsval);
       
   513       if (hbm->sguess != NULL) xfree(hbm->sguess);
       
   514       if (hbm->xexact != NULL) xfree(hbm->xexact);
       
   515       xfree(hbm);
       
   516       return;
       
   517 }
       
   518 
       
   519 /* eof */