static PyObject* diag(PyObject *self, PyObject *args) { PyObject *F; matrix *d=NULL; cholmod_factor *L; #if PY_MAJOR_VERSION >= 3 const char *descr; #else char *descr; #endif int k, strt, incx=1, incy, nrows, ncols; if (!set_options()) return NULL; if (!PyArg_ParseTuple(args, "O", &F)) return NULL; #if PY_MAJOR_VERSION >= 3 if (!PyCapsule_CheckExact(F) || !(descr = PyCapsule_GetName(F))) err_CO("F"); if (strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); L = (cholmod_factor *) PyCapsule_GetPointer(F, descr); #else if (!PyCObject_Check(F)) err_CO("F"); descr = PyCObject_GetDesc(F); if (!descr || strncmp(descr, "CHOLMOD FACTOR", 14)) PY_ERR_TYPE("F is not a CHOLMOD factor"); L = (cholmod_factor *) PyCObject_AsVoidPtr(F); #endif /* Check factorization */ if (L->xtype == CHOLMOD_PATTERN || L->minor<L->n || !L->is_ll || !L->is_super) PY_ERR(PyExc_ValueError, "F must be a nonsingular supernodal " "Cholesky factor"); if (!(d = Matrix_New(L->n,1,L->xtype == CHOLMOD_REAL ? DOUBLE : COMPLEX))) return PyErr_NoMemory(); strt = 0; for (k=0; k<L->nsuper; k++){ /* x[L->px[k], .... ,L->px[k+1]-1] is a dense lower-triangular * nrowx times ncols matrix. We copy its diagonal to * d[strt, ..., strt+ncols-1] */ ncols = (int)((int_t *) L->super)[k+1] - ((int_t *) L->super)[k]; nrows = (int)((int_t *) L->pi)[k+1] - ((int_t *) L->pi)[k]; incy = nrows+1; if (MAT_ID(d) == DOUBLE) dcopy_(&ncols, ((double *) L->x) + ((int_t *) L->px)[k], &incy, MAT_BUFD(d)+strt, &incx); else zcopy_(&ncols, ((double complex *) L->x) + ((int_t *) L->px)[k], &incy, MAT_BUFZ(d)+strt, &incx); strt += ncols; } return (PyObject *)d; }
static PyObject* linsolve(PyObject *self, PyObject *args, PyObject *kwrds) { spmatrix *A; matrix *B; #if PY_MAJOR_VERSION >= 3 int trans_ = 'N'; #endif char trans='N'; double info[UMFPACK_INFO]; int oB=0, n, nrhs=-1, ldB=0, k; void *symbolic, *numeric, *x; char *kwlist[] = {"A", "B", "trans", "nrhs", "ldB", "offsetB", NULL}; #if PY_MAJOR_VERSION >= 3 if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|Ciii", kwlist, &A, &B, &trans_, &nrhs, &ldB, &oB)) return NULL; trans = (char) trans_; #else if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OO|ciii", kwlist, &A, &B, &trans, &nrhs, &ldB, &oB)) return NULL; #endif if (!SpMatrix_Check(A) || SP_NROWS(A) != SP_NCOLS(A)) PY_ERR_TYPE("A must be a square sparse matrix"); n = SP_NROWS(A); if (!Matrix_Check(B) || MAT_ID(B) != SP_ID(A)) PY_ERR_TYPE("B must a dense matrix of the same numeric type " "as A"); if (nrhs < 0) nrhs = B->ncols; if (n == 0 || nrhs == 0) return Py_BuildValue("i", 0); if (ldB == 0) ldB = MAX(1,B->nrows); if (ldB < MAX(1,n)) err_ld("ldB"); if (oB < 0) err_nn_int("offsetB"); if (oB + (nrhs-1)*ldB + n > MAT_LGT(B)) err_buf_len("B"); if (trans != 'N' && trans != 'T' && trans != 'C') err_char("trans", "'N', 'T', 'C'"); if (SP_ID(A) == DOUBLE) UMFD(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), &symbolic, NULL, info); else UMFZ(symbolic)(n, n, SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, &symbolic, NULL, info); if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (SP_ID(A) == DOUBLE) UMFD(free_symbolic)(&symbolic); else UMFZ(free_symbolic)(&symbolic); if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); return NULL; } } if (SP_ID(A) == DOUBLE) { UMFD(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), symbolic, &numeric, NULL, info); UMFD(free_symbolic)(&symbolic); } else { UMFZ(numeric)(SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, symbolic, &numeric, NULL, info); UMFZ(free_symbolic)(&symbolic); } if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix) PyErr_SetString(PyExc_ArithmeticError, "singular " "matrix"); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); } return NULL; } } if (!(x = malloc(n*E_SIZE[SP_ID(A)]))) { if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); return PyErr_NoMemory(); } for (k=0; k<nrhs; k++){ if (SP_ID(A) == DOUBLE) UMFD(solve)(trans == 'N' ? UMFPACK_A: UMFPACK_Aat, SP_COL(A), SP_ROW(A), SP_VAL(A), x, MAT_BUFD(B) + k*ldB + oB, numeric, NULL, info); else UMFZ(solve)(trans == 'N' ? UMFPACK_A: trans == 'C' ? UMFPACK_At : UMFPACK_Aat, SP_COL(A), SP_ROW(A), SP_VAL(A), NULL, x, NULL, (double *)(MAT_BUFZ(B) + k*ldB + oB), NULL, numeric, NULL, info); if (info[UMFPACK_STATUS] == UMFPACK_OK) memcpy(B->buffer + (k*ldB + oB)*E_SIZE[SP_ID(A)], x, n*E_SIZE[SP_ID(A)]); else break; } free(x); if (SP_ID(A) == DOUBLE) UMFD(free_numeric)(&numeric); else UMFZ(free_numeric)(&numeric); if (info[UMFPACK_STATUS] != UMFPACK_OK){ if (info[UMFPACK_STATUS] == UMFPACK_ERROR_out_of_memory) return PyErr_NoMemory(); else { if (info[UMFPACK_STATUS] == UMFPACK_WARNING_singular_matrix) PyErr_SetString(PyExc_ArithmeticError, "singular " "matrix"); else { snprintf(umfpack_error,20,"%s %i","UMFPACK ERROR", (int) info[UMFPACK_STATUS]); PyErr_SetString(PyExc_ValueError, umfpack_error); } return NULL; } } return Py_BuildValue(""); }