Beispiel #1
0
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;
}
Beispiel #2
0
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("");
}