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