1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
/*
Copyright (c) 2012-2023, Intel Corporation
SPDX-License-Identifier: BSD-3-Clause
*/
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
/**************************************************************\
| Includes
\**************************************************************/
#include "matrix.h"
#include "matrix_ispc.h"
extern "C" {
#include "mmio.h"
}
/**************************************************************\
| DenseMatrix methods
\**************************************************************/
void DenseMatrix::multiply(const Vector &v, Vector &r) const {
// Dimensionality check
ASSERT(v.size() == cols());
ASSERT(r.size() == rows());
for (size_t i = 0; i < rows(); i++)
r[i] = v.dot(entries + i * num_cols);
}
const Vector *DenseMatrix::row(size_t row) const { return new Vector(num_cols, entries + row * num_cols, true); }
void DenseMatrix::row(size_t row, Vector &r) {
r.entries = entries + row * cols();
r._size = cols();
}
void DenseMatrix::set_row(size_t row, const Vector &v) {
ASSERT(v.size() == num_cols);
memcpy(entries + row * num_cols, v.entries, num_cols * sizeof(double));
}
/**************************************************************\
| CRSMatrix Methods
\**************************************************************/
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
struct entry {
int row;
int col;
double val;
};
bool compare_entries(struct entry i, struct entry j) {
if (i.row < j.row)
return true;
if (i.row > j.row)
return false;
return i.col < j.col;
}
#define ERR_OUT(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
return nullptr; \
} while(0)
#define ERR_OUT_WITH_CLOSE(file, ...) \
do { \
fclose(file); \
ERR_OUT(__VA_ARGS__); \
} while(0)
CRSMatrix *CRSMatrix::matrix_from_mtf(char *path) {
FILE *f;
MM_typecode matcode;
int m, n, nz;
if ((f = fopen(path, "r")) == nullptr)
ERR_OUT("Error: %s does not name a valid/readable file.\n", path);
if (mm_read_banner(f, &matcode) != 0)
ERR_OUT_WITH_CLOSE(f, "Error: Could not process Matrix Market banner.\n");
if (mm_is_complex(matcode))
ERR_OUT_WITH_CLOSE(f, "Error: Application does not support complex numbers.\n");
if (mm_is_dense(matcode))
ERR_OUT_WITH_CLOSE(f, "Error: supplied matrix is dense (should be sparse.)\n");
if (!mm_is_matrix(matcode))
ERR_OUT_WITH_CLOSE(f, "Error: %s does not encode a matrix.\n", path);
if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0)
ERR_OUT_WITH_CLOSE(f, "Error: could not read matrix size from file.\n");
if (m != n)
ERR_OUT_WITH_CLOSE(f, "Error: Application does not support non-square matrices.");
std::vector<struct entry> entries;
entries.resize(nz);
for (int i = 0; i < nz; i++) {
if (3 != fscanf(f, "%d %d %lg\n", &entries[i].row, &entries[i].col, &entries[i].val)) {
printf("Couldn't read input correctly\n");
exit(-1);
}
// Adjust from 1-based to 0-based
entries[i].row--;
entries[i].col--;
}
sort(entries.begin(), entries.end(), compare_entries);
CRSMatrix *M = new CRSMatrix(m, n, nz);
int cur_row = -1;
for (int i = 0; i < nz; i++) {
while (entries[i].row > cur_row)
M->row_offsets[++cur_row] = i;
M->entries[i] = entries[i].val;
M->columns[i] = entries[i].col;
}
fclose(f);
return M;
}
Vector *Vector::vector_from_mtf(char *path) {
FILE *f;
MM_typecode matcode;
int m, n, nz;
if ((f = fopen(path, "r")) == nullptr)
ERR_OUT("Error: %s does not name a valid/readable file.\n", path);
if (mm_read_banner(f, &matcode) != 0)
ERR_OUT_WITH_CLOSE(f, "Error: Could not process Matrix Market banner.\n");
if (mm_is_complex(matcode))
ERR_OUT_WITH_CLOSE(f, "Error: Application does not support complex numbers.\n");
if (mm_is_dense(matcode)) {
if (mm_read_mtx_array_size(f, &m, &n) != 0)
ERR_OUT_WITH_CLOSE(f, "Error: could not read matrix size from file.\n");
} else {
if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0)
ERR_OUT_WITH_CLOSE(f, "Error: could not read matrix size from file.\n");
}
if (n != 1)
ERR_OUT_WITH_CLOSE(f, "Error: %s does not describe a vector.\n", path);
Vector *x = new Vector(m);
if (mm_is_dense(matcode)) {
double val;
for (int i = 0; i < m; i++) {
if (1 != fscanf(f, "%lg\n", &val)) {
printf("Couldn't read input correctly\n");
exit(-1);
}
(*x)[i] = val;
}
} else {
x->zero();
double val;
int row;
int col;
for (int i = 0; i < nz; i++) {
if (3 != fscanf(f, "%d %d %lg\n", &row, &col, &val)) {
printf("Couldn't read input correctly\n");
exit(-1);
}
(*x)[row - 1] = val;
}
}
fclose(f);
return x;
}
#define ERR(...) \
{ \
fprintf(stderr, __VA_ARGS__); \
exit(-1); \
}
void Vector::to_mtf(char *path) {
FILE *f;
MM_typecode matcode;
mm_initialize_typecode(&matcode);
mm_set_matrix(&matcode);
mm_set_real(&matcode);
mm_set_dense(&matcode);
mm_set_general(&matcode);
if ((f = fopen(path, "w")) == nullptr)
ERR("Error: cannot open/write to %s\n", path);
mm_write_banner(f, matcode);
mm_write_mtx_array_size(f, size(), 1);
for (size_t i = 0; i < size(); i++)
fprintf(f, "%lg\n", entries[i]);
fclose(f);
}
void CRSMatrix::multiply(const Vector &v, Vector &r) const {
ASSERT(v.size() == cols());
ASSERT(r.size() == rows());
for (size_t row = 0; row < rows(); row++) {
int row_offset = row_offsets[row];
int next_offset = ((row + 1 == rows()) ? _nonzeroes : row_offsets[row + 1]);
double sum = 0;
for (int i = row_offset; i < next_offset; i++) {
sum += v[columns[i]] * entries[i];
}
r[row] = sum;
}
}
void CRSMatrix::zero() {
entries.clear();
row_offsets.clear();
columns.clear();
_nonzeroes = 0;
}
|