/* * CXSPARSE: a Concise Sparse Matrix package - Extended. * Copyright (c) 2006-2009, Timothy A. Davis. * http://www.cise.ufl.edu/research/sparse/CXSparse * * CXSparse is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * CXSparse is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this Module; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "cs.h" /* C = A*B */ cs *cs_multiply (const cs *A, const cs *B) { CS_INT p, j, nz = 0, anz, *Cp, *Ci, *Bp, m, n, bnz, *w, values, *Bi ; CS_ENTRY *x, *Bx, *Cx ; cs *C ; if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */ if (A->n != B->m) return (NULL) ; m = A->m ; anz = A->p [A->n] ; n = B->n ; Bp = B->p ; Bi = B->i ; Bx = B->x ; bnz = Bp [n] ; w = cs_calloc (m, sizeof (CS_INT)) ; /* get workspace */ values = (A->x != NULL) && (Bx != NULL) ; x = values ? cs_malloc (m, sizeof (CS_ENTRY)) : NULL ; /* get workspace */ C = cs_spalloc (m, n, anz + bnz, values, 0) ; /* allocate result */ if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ; Cp = C->p ; for (j = 0 ; j < n ; j++) { if (nz + m > C->nzmax && !cs_sprealloc (C, 2*(C->nzmax)+m)) { return (cs_done (C, w, x, 0)) ; /* out of memory */ } Ci = C->i ; Cx = C->x ; /* C->i and C->x may be reallocated */ Cp [j] = nz ; /* column j of C starts here */ for (p = Bp [j] ; p < Bp [j+1] ; p++) { nz = cs_scatter (A, Bi [p], Bx ? Bx [p] : 1, w, x, j+1, C, nz) ; } if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ; } Cp [n] = nz ; /* finalize the last column of C */ cs_sprealloc (C, 0) ; /* remove extra space from C */ return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */ }