Newer
Older
#ifndef CSR_H
#define CSR_H
typedef int csi;
typedef double csv;
csv zero = 0.0;
#define CS_MAX(a,b) (((a) > (b)) ? (a) : (b))
typedef struct csr_t {
csi m;
csi n;
csi nzmax;
csi nr;
csi* r;
csi* p;
csi* j;
csv* x;
} csr;
/* method declarations {{{*/
csr *csr_spfree(csr *A);
/*}}}*/
/*csr util{{{*/
/* free workspace and return a sparse matrix result */
csr *csr_done(csr *C, void *w, void *x, csi ok) {
return (ok ? C : csr_spfree(C)); /* return result if OK, else free it */
}
/* wrapper for free */
void *cs_free(void *p) {
if (p)
free(p); /* free p if it is not already NULL */
return (NULL); /* return NULL to simplify the use of cs_free */
}
/* wrapper for realloc */
void *csr_realloc(void *p, csi n, size_t size, csi *ok) {
void *pnew = NULL;
pnew = realloc(p, CS_MAX(n, 1) * size); /* realloc the block */
*ok = (pnew != NULL); /* realloc fails if pnew is NULL */
if (pnew == NULL) {
printf("%d:reallocation failed, pnew is NULL\n", __LINE__);
return ((*ok) ? pnew : p); /* return original p if failure */
}
/* wrapper for realloc */
void *cs_realloc(void *p, csi n, size_t size, csi *ok) {
void *pnew = NULL;
pnew = realloc(p, CS_MAX(n, 1) * size); /* realloc the block */
*ok = (pnew != NULL); /* realloc fails if pnew is NULL */
if (pnew == NULL) {
return ((*ok) ? pnew : p); /* return original p if failure */
}
/* change the max # of entries sparse matrix */
csi csr_sprealloc(csr *A, csi nzmax) {
csi ok, oki = 0, okj = 1, okx = 1;
if (!A)
nzmax = A->p[A->m];
A->j = (int*) csr_realloc(A->j, nzmax, sizeof (csi), &oki);
A->x = (csv*) csr_realloc(A->x, nzmax, sizeof (csv), &okx);
}
/* free a sparse matrix */
csr *csr_spfree(csr *A) {
if (!A)
return (NULL); /* do nothing if A already NULL */
cs_free(A->p);
A->p = NULL;
cs_free(A->j);
A->j = NULL;
cs_free(A->x);
A->x = NULL;
cs_free(A->r);
A->r = NULL;
cs_free(A); /* free the cs struct and return NULL */
return NULL;
}
/* allocate a sparse matrix (triplet form or compressed-ROW form) */
csr *csr_spalloc(csi m, csi n, csi nzmax, int values, int triplet, csv f) {
csr* A = (csr*) calloc(1, sizeof (csr)); /* allocate the cs struct */
perror("sparse allocation failed");
return (NULL); /* out of memory */
}
A->m = m; /* define dimensions and nzmax */
A->n = n;
A->nzmax = nzmax = CS_MAX(nzmax, 0);
A->nr = 0; // number of nonzero rows
A->p = (csi*) calloc(m + 2, sizeof (csi));
A->j = (csi*) calloc(CS_MAX(nzmax, 1), sizeof (csi));
A->x = (csv*) calloc(CS_MAX(nzmax, 1), sizeof (csv));
return ((!A->p || !A->j || !A->x) ? csr_spfree(A) : A);
}/*}}}*/
/** Multiply two sparse matrices which are stored in CSR format. MKL is used */
csr *csr_multiply(csi Am, csi An, csi Anzmax, const csi* Ap, const csi* Aj, const csv* Ax, csi Bm, csi Bn, csi Bnzmax, const csi* Bp, const csi* Bj, const csv* Bx, long* nummult, csi* xb, csv* x) { /*{{{*/
csv tf = 0;
csi p, jp, j, kp, k, i, nz = 0, anz, *Cp, *Cj, m, n,
csv *Cx;
csr *C;
if (An != Bm)
if (Anzmax == 0 || Bnzmax == 0) {
C = csr_spalloc(Am, Bn, 0, values, 0, tf);
return C;
}
m = Am;
anz = Ap[Am];
n = Bn;
bnz = Bp[Bm];
for (i = 0; i < n; i++) xb[i] = 0;
for (i = 0; i < n; i++)
xb[i] = 0;
values = (Ax != NULL) && (Bx != NULL);
csi tnz = (anz + bnz) * 2;
C = csr_spalloc(m, n, tnz, values, 0, tf); /* allocate result */
if (!C || !xb || (values && !x))
return (csr_done(C, xb, x, 0));
Cp = C->p;
for (i = 0; i < m; i++) {
if (((nz + n) > C->nzmax)) {
if (!csr_sprealloc(C, (2 * (C->nzmax) + n))) {
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
return (csr_done(C, xb, x, 0)); // out of memory
} else {
}
}
Cj = C->j;
Cx = C->x; /* C->j and C->x may be reallocated */
Cp[i] = nz; /* row i of C starts here */
for (jp = Ap[i]; jp < Ap[i + 1]; jp++) {
j = Aj[jp];
for (kp = Bp[j]; kp < Bp[j + 1]; kp++) {
k = Bj[kp]; /* B(i,j) is nonzero */
if (xb[k] != i + 1) {
xb[k] = i + 1; /* i is new entry in column j */
Cj[nz++] = k; /* add i to pattern of C(:,j) */
if (x) {
x[k] = Ax[jp] * Bx[kp]; /* x(i) = beta*A(i,j) */
(*nummult)++;
}
} else if (x) {
x[k] += (Ax[jp] * Bx[kp]); /* i exists in C(:,j) already */
(*nummult)++;
}
}
}
if (values)
for (p = Cp[i]; p < nz; p++)
Cx[p] = x[Cj[p]];
}
Cp[m] = nz; /* finalize the last row of C */
csr_sprealloc(C, 0); /* remove extra space from C */
xb = NULL;
x = NULL;
return C;
}/*}}}*/
#endif