diff --git a/ellspmv.c b/ellspmv.c index 66c6e4f..998c650 100644 --- a/ellspmv.c +++ b/ellspmv.c @@ -17,7 +17,7 @@ * . * * Authors: James D. Trotter - * Last modified: 2022-05-13 + * Last modified: 2022-05-27 * * Benchmarking program for sparse matrix-vector multiplication (SpMV) * with matrices in ELLPACK format. @@ -192,6 +192,37 @@ int parse_int( return 0; } +/** + * ‘parse_int64_t()’ parses a string to produce a number that may be + * represented as a signed, 64-bit integer. + * + * The number is parsed using ‘strtoll()’, following the conventions + * documented in the man page for that function. In addition, some + * further error checking is performed to ensure that the number is + * parsed correctly. The parsed number is stored in ‘x’. + * + * If ‘endptr’ is not ‘NULL’, the address stored in ‘endptr’ points to + * the first character beyond the characters that were consumed during + * parsing. + * + * On success, ‘0’ is returned. Otherwise, if the input contained + * invalid characters, ‘EINVAL’ is returned. If the resulting number + * cannot be represented as a signed integer, ‘ERANGE’ is returned. + */ +int parse_int64_t( + int64_t * x, + const char * s, + char ** endptr, + int64_t * bytes_read) +{ + long long int y; + int err = parse_long_long_int(s, endptr, 10, &y, bytes_read); + if (err) return err; + if (y < INT64_MIN || y > INT64_MAX) return ERANGE; + *x = y; + return 0; +} + /** * ‘parse_double()’ parses a string to produce a number that may be * represented as ‘double’. @@ -337,7 +368,7 @@ static int freadline(char * linebuf, size_t line_max, FILE * f) { static int mtxfile_fread_header( int * num_rows, int * num_columns, - int * num_nonzeros, + int64_t * num_nonzeros, FILE * f, int64_t * lines_read, int64_t * bytes_read) @@ -396,7 +427,7 @@ static int mtxfile_fread_header( if (s == t || *t != ' ') { free(linebuf); return EINVAL; } if (bytes_read) (*bytes_read)++; s = t+1; - err = parse_int(num_nonzeros, s, &t, bytes_read); + err = parse_int64_t(num_nonzeros, s, &t, bytes_read); if (err) { free(linebuf); return err; } if (s == t) { free(linebuf); return EINVAL; } free(linebuf); @@ -406,7 +437,7 @@ static int mtxfile_fread_header( static int mtxfile_fread_data( int num_rows, int num_columns, - int num_nonzeros, + int64_t num_nonzeros, int * rowidx, int * colidx, double * a, @@ -417,7 +448,7 @@ static int mtxfile_fread_data( int line_max = sysconf(_SC_LINE_MAX); char * linebuf = malloc(line_max+1); if (!linebuf) return errno; - for (int i = 0; i < num_nonzeros; i++) { + for (int64_t i = 0; i < num_nonzeros; i++) { int err = freadline(linebuf, line_max, f); if (err) { free(linebuf); return err; } char * s = linebuf; @@ -443,18 +474,18 @@ static int mtxfile_fread_data( static int ell_from_coo_size( int num_rows, int num_columns, - int num_nonzeros, + int64_t num_nonzeros, const int * rowidx, const int * colidx, const double * a, - int * rowptr, - int * ellsize, + int64_t * rowptr, + int64_t * ellsize, int * rowsize, int * diagsize) { int rowmax = 0; for (int i = 0; i <= num_rows; i++) rowptr[i] = 0; - for (int k = 0; k < num_nonzeros; k++) { + for (int64_t k = 0; k < num_nonzeros; k++) { if (rowidx[k] != colidx[k]) rowptr[rowidx[k]]++; } @@ -471,19 +502,19 @@ static int ell_from_coo_size( static int ell_from_coo( int num_rows, int num_columns, - int num_nonzeros, + int64_t num_nonzeros, const int * rowidx, const int * colidx, const double * a, - int * rowptr, - int ellsize, + int64_t * rowptr, + int64_t ellsize, int rowsize, int * ellcolidx, double * ella, double * ellad) { for (int i = 0; i <= num_rows; i++) rowptr[i] = 0; - for (int k = 0; k < num_nonzeros; k++) { + for (int64_t k = 0; k < num_nonzeros; k++) { if (rowidx[k] == colidx[k]) { ellad[rowidx[k]-1] += a[k]; } else { @@ -498,7 +529,7 @@ static int ell_from_coo( #endif for (int i = 0; i < num_rows; i++) { int j = i < num_columns ? i : num_columns-1; - for (int l = rowptr[i]; l < rowsize; l++) { + for (int64_t l = rowptr[i]; l < rowsize; l++) { ellcolidx[i*rowsize+l] = j; ella[i*rowsize+l] = 0.0; } @@ -511,7 +542,7 @@ static int ellgemv( double * __restrict y, int num_columns, const double * __restrict x, - int ellsize, + int64_t ellsize, int rowsize, const int * __restrict colidx, const double * __restrict a, @@ -534,7 +565,7 @@ static int ellgemv16( double * __restrict y, int num_columns, const double * __restrict x, - int ellsize, + int64_t ellsize, int rowsize, const int * __restrict colidx, const double * __restrict a, @@ -609,7 +640,7 @@ int main(int argc, char *argv[]) int num_rows; int num_columns; - int num_nonzeros; + int64_t num_nonzeros; int64_t lines_read = 0; int64_t bytes_read = 0; err = mtxfile_fread_header( @@ -677,7 +708,7 @@ int main(int argc, char *argv[]) clock_gettime(CLOCK_MONOTONIC, &t0); } - int * rowptr = malloc((num_rows+1) * sizeof(int)); + int64_t * rowptr = malloc((num_rows+1) * sizeof(int64_t)); if (!rowptr) { if (args.verbose > 0) fprintf(stderr, "\n"); fprintf(stderr, "%s: %s\n", program_invocation_short_name, strerror(errno)); @@ -685,7 +716,7 @@ int main(int argc, char *argv[]) program_options_free(&args); return EXIT_FAILURE; } - int ellsize; + int64_t ellsize; int rowsize; int diagsize; err = ell_from_coo_size( @@ -810,8 +841,8 @@ int main(int argc, char *argv[]) break; } - int num_flops = 2*(ellsize+diagsize); - int num_bytes = num_rows*sizeof(*y) + num_columns*sizeof(*x) + int64_t num_flops = 2*(ellsize+diagsize); + int64_t num_bytes = num_rows*sizeof(*y) + num_columns*sizeof(*x) + ellsize*sizeof(*ellcolidx) + ellsize*sizeof(*ella) + diagsize*sizeof(*ellad); #pragma omp master