| File: | /tmp/pyrefcon/scipy/scipy/sparse/linalg/dsolve/_superluobject.c |
| Warning: | line 910, column 5 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* -*-c-*- */ | |||
| 2 | /* | |||
| 3 | * _superlu object | |||
| 4 | * | |||
| 5 | * Python object representing SuperLU factorization + some utility functions. | |||
| 6 | */ | |||
| 7 | ||||
| 8 | #include <Python.h> | |||
| 9 | ||||
| 10 | #define NO_IMPORT_ARRAY | |||
| 11 | #define PY_ARRAY_UNIQUE_SYMBOL_scipy_sparse_superlu_ARRAY_API _scipy_sparse_superlu_ARRAY_API | |||
| 12 | ||||
| 13 | #include "_superluobject.h" | |||
| 14 | #include <ctype.h> | |||
| 15 | ||||
| 16 | ||||
| 17 | /*********************************************************************** | |||
| 18 | * SuperLUObject methods | |||
| 19 | */ | |||
| 20 | ||||
| 21 | static PyObject *SuperLU_solve(SuperLUObject * self, PyObject * args, | |||
| 22 | PyObject * kwds) | |||
| 23 | { | |||
| 24 | volatile PyArrayObject *b, *x = NULL((void*)0); | |||
| 25 | volatile SuperMatrix B = { 0 }; | |||
| 26 | volatile int itrans = 'N'; | |||
| 27 | volatile int info; | |||
| 28 | volatile trans_t trans; | |||
| 29 | volatile SuperLUStat_t stat = { 0 }; | |||
| 30 | static char *kwlist[] = { "rhs", "trans", NULL((void*)0) }; | |||
| 31 | volatile jmp_buf *jmpbuf_ptr; | |||
| 32 | SLU_BEGIN_THREADS_DEFvolatile PyThreadState *_save = ((void*)0); | |||
| 33 | ||||
| 34 | if (!CHECK_SLU_TYPE(self->type)(self->type == NPY_FLOAT || self->type == NPY_DOUBLE || self->type == NPY_CFLOAT || self->type == NPY_CDOUBLE)) { | |||
| 35 | PyErr_SetString(PyExc_ValueError, "unsupported data type"); | |||
| 36 | return NULL((void*)0); | |||
| 37 | } | |||
| 38 | ||||
| 39 | if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|C", kwlist, | |||
| 40 | &PyArray_Type(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[2]), &b, &itrans)) | |||
| 41 | return NULL((void*)0); | |||
| 42 | ||||
| 43 | /* solve transposed system: matrix was passed row-wise instead of | |||
| 44 | * column-wise */ | |||
| 45 | if (itrans == 'n' || itrans == 'N') | |||
| 46 | trans = NOTRANS; | |||
| 47 | else if (itrans == 't' || itrans == 'T') | |||
| 48 | trans = TRANS; | |||
| 49 | else if (itrans == 'h' || itrans == 'H') | |||
| 50 | trans = CONJ; | |||
| 51 | else { | |||
| 52 | PyErr_SetString(PyExc_ValueError, "trans must be N, T, or H"); | |||
| 53 | return NULL((void*)0); | |||
| 54 | } | |||
| 55 | ||||
| 56 | x = (PyArrayObject*)PyArray_FROMANY((*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API[69])((PyObject* )b, (*(PyArray_Descr * (*)(int)) _scipy_sparse_superlu_ARRAY_API [45])(self->type), 1, 2, (((0x0002 | 0x0020) & 0x0020) ? (0x0002 | 0x0020) | ((0x0001 | (0x0100 | 0x0400))) : (0x0002 | 0x0020)), ((void*)0)) | |||
| 57 | (PyObject*)b, self->type, 1, 2,(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API[69])((PyObject* )b, (*(PyArray_Descr * (*)(int)) _scipy_sparse_superlu_ARRAY_API [45])(self->type), 1, 2, (((0x0002 | 0x0020) & 0x0020) ? (0x0002 | 0x0020) | ((0x0001 | (0x0100 | 0x0400))) : (0x0002 | 0x0020)), ((void*)0)) | |||
| 58 | NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ENSURECOPY)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API[69])((PyObject* )b, (*(PyArray_Descr * (*)(int)) _scipy_sparse_superlu_ARRAY_API [45])(self->type), 1, 2, (((0x0002 | 0x0020) & 0x0020) ? (0x0002 | 0x0020) | ((0x0001 | (0x0100 | 0x0400))) : (0x0002 | 0x0020)), ((void*)0)); | |||
| 59 | if (x == NULL((void*)0)) { | |||
| 60 | goto fail; | |||
| 61 | } | |||
| 62 | ||||
| 63 | if (PyArray_DIM((PyArrayObject*)x, 0) != self->n) { | |||
| 64 | PyErr_SetString(PyExc_ValueError, "b is of incompatible size"); | |||
| 65 | goto fail; | |||
| 66 | } | |||
| 67 | ||||
| 68 | if (DenseSuper_from_Numeric((SuperMatrix*)&B, (PyObject *)x)) | |||
| 69 | goto fail; | |||
| 70 | ||||
| 71 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 72 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 73 | goto fail; | |||
| 74 | } | |||
| 75 | ||||
| 76 | StatInit((SuperLUStat_t *)&stat); | |||
| 77 | ||||
| 78 | /* Solve the system, overwriting vector x. */ | |||
| 79 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 80 | SLU_BEGIN_THREADSdo { if (_save == ((void*)0)) _save = PyEval_SaveThread(); } while (0); | |||
| 81 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 82 | SLU_END_THREADSdo { if (_save) { PyEval_RestoreThread((PyThreadState*)_save) ; _save = ((void*)0);} } while (0); | |||
| 83 | goto fail; | |||
| 84 | } | |||
| 85 | gstrs(self->type, | |||
| 86 | trans, &self->L, &self->U, self->perm_c, self->perm_r, | |||
| 87 | (SuperMatrix *)&B, (SuperLUStat_t *)&stat, (int *)&info); | |||
| 88 | SLU_END_THREADSdo { if (_save) { PyEval_RestoreThread((PyThreadState*)_save) ; _save = ((void*)0);} } while (0); | |||
| 89 | ||||
| 90 | if (info) { | |||
| 91 | PyErr_SetString(PyExc_SystemError, | |||
| 92 | "gstrs was called with invalid arguments"); | |||
| 93 | goto fail; | |||
| 94 | } | |||
| 95 | ||||
| 96 | /* free memory */ | |||
| 97 | Destroy_SuperMatrix_Store((SuperMatrix *)&B); | |||
| 98 | StatFree((SuperLUStat_t *)&stat); | |||
| 99 | return (PyObject *) x; | |||
| 100 | ||||
| 101 | fail: | |||
| 102 | XDestroy_SuperMatrix_Store((SuperMatrix *)&B); | |||
| 103 | XStatFree((SuperLUStat_t *)&stat); | |||
| 104 | Py_XDECREF(x)_Py_XDECREF(((PyObject*)(x))); | |||
| 105 | return NULL((void*)0); | |||
| 106 | } | |||
| 107 | ||||
| 108 | /** table of object methods | |||
| 109 | */ | |||
| 110 | PyMethodDef SuperLU_methods[] = { | |||
| 111 | {"solve", (PyCFunction) SuperLU_solve, METH_VARARGS0x0001 | METH_KEYWORDS0x0002, NULL((void*)0)}, | |||
| 112 | {NULL((void*)0), NULL((void*)0)} /* sentinel */ | |||
| 113 | }; | |||
| 114 | ||||
| 115 | ||||
| 116 | /*********************************************************************** | |||
| 117 | * SuperLUType methods | |||
| 118 | */ | |||
| 119 | ||||
| 120 | static void SuperLU_dealloc(SuperLUObject * self) | |||
| 121 | { | |||
| 122 | Py_XDECREF(self->cached_U)_Py_XDECREF(((PyObject*)(self->cached_U))); | |||
| 123 | Py_XDECREF(self->cached_L)_Py_XDECREF(((PyObject*)(self->cached_L))); | |||
| 124 | Py_XDECREF(self->py_csc_construct_func)_Py_XDECREF(((PyObject*)(self->py_csc_construct_func))); | |||
| 125 | self->cached_U = NULL((void*)0); | |||
| 126 | self->cached_L = NULL((void*)0); | |||
| 127 | self->py_csc_construct_func = NULL((void*)0); | |||
| 128 | SUPERLU_FREE(self->perm_r)superlu_python_module_free(self->perm_r); | |||
| 129 | SUPERLU_FREE(self->perm_c)superlu_python_module_free(self->perm_c); | |||
| 130 | self->perm_r = NULL((void*)0); | |||
| 131 | self->perm_c = NULL((void*)0); | |||
| 132 | XDestroy_SuperNode_Matrix(&self->L); | |||
| 133 | XDestroy_CompCol_Matrix(&self->U); | |||
| 134 | PyObject_DelPyObject_Free(self); | |||
| 135 | } | |||
| 136 | ||||
| 137 | static PyObject *SuperLU_getter(PyObject *selfp, void *data) | |||
| 138 | { | |||
| 139 | SuperLUObject *self = (SuperLUObject *)selfp; | |||
| 140 | char *name = (char*)data; | |||
| 141 | ||||
| 142 | if (strcmp(name, "shape") == 0) { | |||
| 143 | return Py_BuildValue("(i,i)", self->m, self->n); | |||
| 144 | } | |||
| 145 | else if (strcmp(name, "nnz") == 0) | |||
| 146 | return Py_BuildValue("i", | |||
| 147 | ((SCformat *) self->L.Store)->nnz + | |||
| 148 | ((SCformat *) self->U.Store)->nnz); | |||
| 149 | else if (strcmp(name, "perm_r") == 0) { | |||
| 150 | PyObject *perm_r; | |||
| 151 | perm_r = PyArray_SimpleNewFromData((*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_r, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)) | |||
| 152 | 1, (npy_intp *) (&self->n), NPY_INT,(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_r, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)) | |||
| 153 | (void *) self->perm_r)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_r, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)); | |||
| 154 | if (perm_r == NULL((void*)0)) { | |||
| 155 | return NULL((void*)0); | |||
| 156 | } | |||
| 157 | ||||
| 158 | /* For ref counting of the memory */ | |||
| 159 | PyArray_SetBaseObject(*(int (*)(PyArrayObject *, PyObject *)) _scipy_sparse_superlu_ARRAY_API [282])((PyArrayObject*)perm_r, (PyObject*)self); | |||
| 160 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 161 | return perm_r; | |||
| 162 | } | |||
| 163 | else if (strcmp(name, "perm_c") == 0) { | |||
| 164 | PyObject *perm_c; | |||
| 165 | ||||
| 166 | perm_c = PyArray_SimpleNewFromData((*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_c, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)) | |||
| 167 | 1, (npy_intp *) (&self->n), NPY_INT,(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_c, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)) | |||
| 168 | (void *) self->perm_c)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) _scipy_sparse_superlu_ARRAY_API [93])(&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API[ 2]), 1, (npy_intp *) (&self->n), NPY_INT, ((void*)0), ( void *) self->perm_c, 0, (0x0001 | (0x0100 | 0x0400)), ((void *)0)); | |||
| 169 | if (perm_c == NULL((void*)0)) { | |||
| 170 | return NULL((void*)0); | |||
| 171 | } | |||
| 172 | ||||
| 173 | /* For ref counting of the memory */ | |||
| 174 | PyArray_SetBaseObject(*(int (*)(PyArrayObject *, PyObject *)) _scipy_sparse_superlu_ARRAY_API [282])((PyArrayObject*)perm_c, (PyObject*)self); | |||
| 175 | Py_INCREF(self)_Py_INCREF(((PyObject*)(self))); | |||
| 176 | return perm_c; | |||
| 177 | } | |||
| 178 | else if (strcmp(name, "U") == 0 || strcmp(name, "L") == 0) { | |||
| 179 | int ok; | |||
| 180 | if (self->cached_U == NULL((void*)0)) { | |||
| 181 | ok = LU_to_csc_matrix(&self->L, &self->U, | |||
| 182 | &self->cached_L, &self->cached_U, | |||
| 183 | self->py_csc_construct_func); | |||
| 184 | if (ok != 0) { | |||
| 185 | return NULL((void*)0); | |||
| 186 | } | |||
| 187 | } | |||
| 188 | if (strcmp(name, "U") == 0) { | |||
| 189 | Py_INCREF(self->cached_U)_Py_INCREF(((PyObject*)(self->cached_U))); | |||
| 190 | return self->cached_U; | |||
| 191 | } | |||
| 192 | else { | |||
| 193 | Py_INCREF(self->cached_L)_Py_INCREF(((PyObject*)(self->cached_L))); | |||
| 194 | return self->cached_L; | |||
| 195 | } | |||
| 196 | } | |||
| 197 | else { | |||
| 198 | PyErr_SetString(PyExc_RuntimeError, | |||
| 199 | "internal error (this is a bug)"); | |||
| 200 | return NULL((void*)0); | |||
| 201 | } | |||
| 202 | } | |||
| 203 | ||||
| 204 | ||||
| 205 | /*********************************************************************** | |||
| 206 | * SuperLUType structure | |||
| 207 | */ | |||
| 208 | ||||
| 209 | PyGetSetDef SuperLU_getset[] = { | |||
| 210 | {"shape", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"shape"}, | |||
| 211 | {"nnz", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"nnz"}, | |||
| 212 | {"perm_r", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"perm_r"}, | |||
| 213 | {"perm_c", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"perm_c"}, | |||
| 214 | {"U", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"U"}, | |||
| 215 | {"L", SuperLU_getter, (setter)NULL((void*)0), (char*)NULL((void*)0), (void*)"L"}, | |||
| 216 | NULL((void*)0) | |||
| 217 | }; | |||
| 218 | ||||
| 219 | ||||
| 220 | PyTypeObject SuperLUType = { | |||
| 221 | PyVarObject_HEAD_INIT(NULL, 0){ { 1, ((void*)0) }, 0 }, | |||
| 222 | "SuperLU", | |||
| 223 | sizeof(SuperLUObject), | |||
| 224 | 0, | |||
| 225 | (destructor) SuperLU_dealloc, /* tp_dealloc */ | |||
| 226 | 0, /* tp_print */ | |||
| 227 | 0, /* tp_getattr */ | |||
| 228 | 0, /* tp_setattr */ | |||
| 229 | 0, /* tp_compare / tp_reserved */ | |||
| 230 | 0, /* tp_repr */ | |||
| 231 | 0, /* tp_as_number */ | |||
| 232 | 0, /* tp_as_sequence */ | |||
| 233 | 0, /* tp_as_mapping */ | |||
| 234 | 0, /* tp_hash */ | |||
| 235 | 0, /* tp_call */ | |||
| 236 | 0, /* tp_str */ | |||
| 237 | 0, /* tp_getattro */ | |||
| 238 | 0, /* tp_setattro */ | |||
| 239 | 0, /* tp_as_buffer */ | |||
| 240 | Py_TPFLAGS_DEFAULT( 0 | (1UL << 18) | 0), /* tp_flags */ | |||
| 241 | NULL((void*)0), /* tp_doc */ | |||
| 242 | 0, /* tp_traverse */ | |||
| 243 | 0, /* tp_clear */ | |||
| 244 | 0, /* tp_richcompare */ | |||
| 245 | 0, /* tp_weaklistoffset */ | |||
| 246 | 0, /* tp_iter */ | |||
| 247 | 0, /* tp_iternext */ | |||
| 248 | SuperLU_methods, /* tp_methods */ | |||
| 249 | 0, /* tp_members */ | |||
| 250 | SuperLU_getset, /* tp_getset */ | |||
| 251 | 0, /* tp_base */ | |||
| 252 | 0, /* tp_dict */ | |||
| 253 | 0, /* tp_descr_get */ | |||
| 254 | 0, /* tp_descr_set */ | |||
| 255 | 0, /* tp_dictoffset */ | |||
| 256 | 0, /* tp_init */ | |||
| 257 | 0, /* tp_alloc */ | |||
| 258 | 0, /* tp_new */ | |||
| 259 | 0, /* tp_free */ | |||
| 260 | 0, /* tp_is_gc */ | |||
| 261 | 0, /* tp_bases */ | |||
| 262 | 0, /* tp_mro */ | |||
| 263 | 0, /* tp_cache */ | |||
| 264 | 0, /* tp_subclasses */ | |||
| 265 | 0, /* tp_weaklist */ | |||
| 266 | 0, /* tp_del */ | |||
| 267 | 0, /* tp_version_tag */ | |||
| 268 | }; | |||
| 269 | ||||
| 270 | ||||
| 271 | int DenseSuper_from_Numeric(SuperMatrix *X, PyObject *PyX) | |||
| 272 | { | |||
| 273 | volatile PyArrayObject *aX; | |||
| 274 | volatile int m, n, ldx, nd; | |||
| 275 | volatile jmp_buf *jmpbuf_ptr; | |||
| 276 | ||||
| 277 | if (!PyArray_Check(PyX)((((PyObject*)(PyX))->ob_type) == (&(*(PyTypeObject *) _scipy_sparse_superlu_ARRAY_API[2])) || PyType_IsSubtype((((PyObject *)(PyX))->ob_type), (&(*(PyTypeObject *)_scipy_sparse_superlu_ARRAY_API [2]))))) { | |||
| 278 | PyErr_SetString(PyExc_TypeError, | |||
| 279 | "argument is not an array."); | |||
| 280 | return -1; | |||
| 281 | } | |||
| 282 | ||||
| 283 | aX = (PyArrayObject*)PyX; | |||
| 284 | ||||
| 285 | if (!CHECK_SLU_TYPE(PyArray_TYPE((PyArrayObject*)aX))(PyArray_TYPE((PyArrayObject*)aX) == NPY_FLOAT || PyArray_TYPE ((PyArrayObject*)aX) == NPY_DOUBLE || PyArray_TYPE((PyArrayObject *)aX) == NPY_CFLOAT || PyArray_TYPE((PyArrayObject*)aX) == NPY_CDOUBLE )) { | |||
| 286 | PyErr_SetString(PyExc_ValueError, "unsupported array data type"); | |||
| 287 | return -1; | |||
| 288 | } | |||
| 289 | ||||
| 290 | if (!(PyArray_FLAGS((PyArrayObject*)aX) & NPY_ARRAY_F_CONTIGUOUS0x0002)) { | |||
| 291 | PyErr_SetString(PyExc_ValueError, "array is not fortran contiguous"); | |||
| 292 | return -1; | |||
| 293 | } | |||
| 294 | ||||
| 295 | nd = PyArray_NDIM((PyArrayObject*)aX); | |||
| 296 | ||||
| 297 | if (nd == 1) { | |||
| 298 | m = PyArray_DIM((PyArrayObject*)aX, 0); | |||
| 299 | n = 1; | |||
| 300 | ldx = m; | |||
| 301 | } | |||
| 302 | else if (nd == 2) { | |||
| 303 | m = PyArray_DIM((PyArrayObject*)aX, 0); | |||
| 304 | n = PyArray_DIM((PyArrayObject*)aX, 1); | |||
| 305 | ldx = m; | |||
| 306 | } | |||
| 307 | else { | |||
| 308 | PyErr_SetString(PyExc_ValueError, "wrong number of dimensions in array"); | |||
| 309 | return -1; | |||
| 310 | } | |||
| 311 | ||||
| 312 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 313 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 314 | return -1; | |||
| 315 | } | |||
| 316 | else { | |||
| 317 | Create_Dense_Matrix(PyArray_TYPE((PyArrayObject*)aX), X, m, n, | |||
| 318 | PyArray_DATA((PyArrayObject*)aX), ldx, SLU_DN, | |||
| 319 | NPY_TYPECODE_TO_SLU(PyArray_TYPE((PyArrayObject*)aX))( ((PyArray_TYPE((PyArrayObject*)aX)) == NPY_FLOAT) ? SLU_S : ((PyArray_TYPE((PyArrayObject*)aX)) == NPY_DOUBLE) ? SLU_D : ((PyArray_TYPE((PyArrayObject*)aX)) == NPY_CFLOAT) ? SLU_C : ((PyArray_TYPE((PyArrayObject*)aX)) == NPY_CDOUBLE) ? SLU_Z : -1), | |||
| 320 | SLU_GE); | |||
| 321 | } | |||
| 322 | return 0; | |||
| 323 | } | |||
| 324 | ||||
| 325 | /* Natively handles Compressed Sparse Row and CSC */ | |||
| 326 | ||||
| 327 | int NRFormat_from_spMatrix(SuperMatrix * A, int m, int n, int nnz, | |||
| 328 | PyArrayObject * nzvals, PyArrayObject * colind, | |||
| 329 | PyArrayObject * rowptr, int typenum) | |||
| 330 | { | |||
| 331 | volatile int ok = 0; | |||
| 332 | volatile jmp_buf *jmpbuf_ptr; | |||
| 333 | ||||
| 334 | ok = (PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(nzvals), typenum) && | |||
| 335 | PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(colind), NPY_INT) && | |||
| 336 | PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(rowptr), NPY_INT) && | |||
| 337 | PyArray_NDIM(nzvals) == 1 && | |||
| 338 | PyArray_NDIM(colind) == 1 && | |||
| 339 | PyArray_NDIM(rowptr) == 1 && | |||
| 340 | PyArray_IS_C_CONTIGUOUS(nzvals)PyArray_CHKFLAGS((nzvals), 0x0001) && | |||
| 341 | PyArray_IS_C_CONTIGUOUS(colind)PyArray_CHKFLAGS((colind), 0x0001) && | |||
| 342 | PyArray_IS_C_CONTIGUOUS(rowptr)PyArray_CHKFLAGS((rowptr), 0x0001) && | |||
| 343 | nnz <= PyArray_DIM(nzvals, 0) && | |||
| 344 | nnz <= PyArray_DIM(colind, 0) && | |||
| 345 | m+1 <= PyArray_DIM(rowptr, 0)); | |||
| 346 | if (!ok) { | |||
| 347 | PyErr_SetString(PyExc_ValueError, | |||
| 348 | "sparse matrix arrays must be 1-D C-contiguous and of proper " | |||
| 349 | "sizes and types"); | |||
| 350 | return -1; | |||
| 351 | } | |||
| 352 | ||||
| 353 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 354 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 355 | return -1; | |||
| 356 | } | |||
| 357 | else { | |||
| 358 | if (!CHECK_SLU_TYPE(PyArray_TYPE(nzvals))(PyArray_TYPE(nzvals) == NPY_FLOAT || PyArray_TYPE(nzvals) == NPY_DOUBLE || PyArray_TYPE(nzvals) == NPY_CFLOAT || PyArray_TYPE (nzvals) == NPY_CDOUBLE)) { | |||
| 359 | PyErr_SetString(PyExc_TypeError, "Invalid type for array."); | |||
| 360 | return -1; | |||
| 361 | } | |||
| 362 | Create_CompRow_Matrix(PyArray_TYPE(nzvals), | |||
| 363 | A, m, n, nnz, PyArray_DATA((PyArrayObject*)nzvals), | |||
| 364 | (int *) PyArray_DATA((PyArrayObject*)colind), | |||
| 365 | (int *) PyArray_DATA((PyArrayObject*)rowptr), | |||
| 366 | SLU_NR, | |||
| 367 | NPY_TYPECODE_TO_SLU(PyArray_TYPE((PyArrayObject*)nzvals))( ((PyArray_TYPE((PyArrayObject*)nzvals)) == NPY_FLOAT) ? SLU_S : ((PyArray_TYPE((PyArrayObject*)nzvals)) == NPY_DOUBLE) ? SLU_D : ((PyArray_TYPE((PyArrayObject*)nzvals)) == NPY_CFLOAT) ? SLU_C : ((PyArray_TYPE((PyArrayObject*)nzvals)) == NPY_CDOUBLE) ? SLU_Z : -1), | |||
| 368 | SLU_GE); | |||
| 369 | } | |||
| 370 | ||||
| 371 | return 0; | |||
| 372 | } | |||
| 373 | ||||
| 374 | int NCFormat_from_spMatrix(SuperMatrix * A, int m, int n, int nnz, | |||
| 375 | PyArrayObject * nzvals, PyArrayObject * rowind, | |||
| 376 | PyArrayObject * colptr, int typenum) | |||
| 377 | { | |||
| 378 | volatile int ok = 0; | |||
| 379 | volatile jmp_buf *jmpbuf_ptr; | |||
| 380 | ||||
| 381 | ok = (PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(nzvals), typenum) && | |||
| 382 | PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(rowind), NPY_INT) && | |||
| 383 | PyArray_EquivTypenums(*(unsigned char (*)(int, int)) _scipy_sparse_superlu_ARRAY_API [191])(PyArray_TYPE(colptr), NPY_INT) && | |||
| 384 | PyArray_NDIM(nzvals) == 1 && | |||
| 385 | PyArray_NDIM(rowind) == 1 && | |||
| 386 | PyArray_NDIM(colptr) == 1 && | |||
| 387 | PyArray_IS_C_CONTIGUOUS(nzvals)PyArray_CHKFLAGS((nzvals), 0x0001) && | |||
| 388 | PyArray_IS_C_CONTIGUOUS(rowind)PyArray_CHKFLAGS((rowind), 0x0001) && | |||
| 389 | PyArray_IS_C_CONTIGUOUS(colptr)PyArray_CHKFLAGS((colptr), 0x0001) && | |||
| 390 | nnz <= PyArray_DIM(nzvals, 0) && | |||
| 391 | nnz <= PyArray_DIM(rowind, 0) && | |||
| 392 | n+1 <= PyArray_DIM(colptr, 0)); | |||
| 393 | if (!ok) { | |||
| 394 | PyErr_SetString(PyExc_ValueError, | |||
| 395 | "sparse matrix arrays must be 1-D C-contiguous and of proper " | |||
| 396 | "sizes and types"); | |||
| 397 | return -1; | |||
| 398 | } | |||
| 399 | ||||
| 400 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 401 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 402 | return -1; | |||
| 403 | } | |||
| 404 | else { | |||
| 405 | if (!CHECK_SLU_TYPE(PyArray_TYPE(nzvals))(PyArray_TYPE(nzvals) == NPY_FLOAT || PyArray_TYPE(nzvals) == NPY_DOUBLE || PyArray_TYPE(nzvals) == NPY_CFLOAT || PyArray_TYPE (nzvals) == NPY_CDOUBLE)) { | |||
| 406 | PyErr_SetString(PyExc_TypeError, "Invalid type for array."); | |||
| 407 | return -1; | |||
| 408 | } | |||
| 409 | Create_CompCol_Matrix(PyArray_TYPE(nzvals), | |||
| 410 | A, m, n, nnz, PyArray_DATA(nzvals), | |||
| 411 | (int *) PyArray_DATA(rowind), (int *) PyArray_DATA(colptr), | |||
| 412 | SLU_NC, | |||
| 413 | NPY_TYPECODE_TO_SLU(PyArray_TYPE(nzvals))( ((PyArray_TYPE(nzvals)) == NPY_FLOAT) ? SLU_S : ((PyArray_TYPE (nzvals)) == NPY_DOUBLE) ? SLU_D : ((PyArray_TYPE(nzvals)) == NPY_CFLOAT) ? SLU_C : ((PyArray_TYPE(nzvals)) == NPY_CDOUBLE ) ? SLU_Z : -1), | |||
| 414 | SLU_GE); | |||
| 415 | } | |||
| 416 | ||||
| 417 | return 0; | |||
| 418 | } | |||
| 419 | ||||
| 420 | ||||
| 421 | /* | |||
| 422 | * Create Scipy sparse matrices out from Superlu LU decomposition. | |||
| 423 | */ | |||
| 424 | ||||
| 425 | static int LU_to_csc(SuperMatrix *L, SuperMatrix *U, | |||
| 426 | int *U_indices, int *U_indptr, char *U_data, | |||
| 427 | int *L_indices, int *L_indptr, char *L_data, | |||
| 428 | Dtype_t dtype); | |||
| 429 | ||||
| 430 | int LU_to_csc_matrix(SuperMatrix *L, SuperMatrix *U, | |||
| 431 | PyObject **L_csc, PyObject **U_csc, | |||
| 432 | PyObject *py_csc_construct_func) | |||
| 433 | { | |||
| 434 | SCformat *Lstore; | |||
| 435 | NCformat *Ustore; | |||
| 436 | PyObject *U_indices = NULL((void*)0), *U_indptr = NULL((void*)0), *U_data = NULL((void*)0); | |||
| 437 | PyObject *L_indices = NULL((void*)0), *L_indptr = NULL((void*)0), *L_data = NULL((void*)0); | |||
| 438 | PyObject *datatuple = NULL((void*)0), *shape = NULL((void*)0); | |||
| 439 | int result = -1, ok; | |||
| 440 | int type; | |||
| 441 | npy_intp dims[1]; | |||
| 442 | ||||
| 443 | *L_csc = NULL((void*)0); | |||
| 444 | *U_csc = NULL((void*)0); | |||
| 445 | ||||
| 446 | if (U->Stype != SLU_NC || L->Stype != SLU_SC || | |||
| 447 | U->Mtype != SLU_TRU || L->Mtype != SLU_TRLU || | |||
| 448 | L->nrow != U->nrow || L->ncol != L->nrow || | |||
| 449 | U->ncol != U->nrow || L->Dtype != U->Dtype) | |||
| 450 | { | |||
| 451 | PyErr_SetString(PyExc_RuntimeError, | |||
| 452 | "internal error: invalid Superlu matrix data"); | |||
| 453 | return -1; | |||
| 454 | } | |||
| 455 | ||||
| 456 | Ustore = (NCformat*)U->Store; | |||
| 457 | Lstore = (SCformat*)L->Store; | |||
| 458 | ||||
| 459 | type = SLU_TYPECODE_TO_NPY(L->Dtype)( ((L->Dtype) == SLU_S) ? NPY_FLOAT : ((L->Dtype) == SLU_D ) ? NPY_DOUBLE : ((L->Dtype) == SLU_C) ? NPY_CFLOAT : ((L-> Dtype) == SLU_Z) ? NPY_CDOUBLE : -1); | |||
| 460 | ||||
| 461 | /* Allocate output */ | |||
| 462 | #define CREATE_1D_ARRAY(name, type, size) \ | |||
| 463 | do { \ | |||
| 464 | dims[0] = size; \ | |||
| 465 | name = PyArray_EMPTY(1, dims, type, 0)(*(PyObject * (*)(int, npy_intp const *, PyArray_Descr *, int )) _scipy_sparse_superlu_ARRAY_API[184])(1, dims, (*(PyArray_Descr * (*)(int)) _scipy_sparse_superlu_ARRAY_API[45])(type), 0); \ | |||
| 466 | if (name == NULL((void*)0)) goto fail; \ | |||
| 467 | } while (0) | |||
| 468 | ||||
| 469 | CREATE_1D_ARRAY(L_indices, NPY_INT, Lstore->nnz); | |||
| 470 | CREATE_1D_ARRAY(L_indptr, NPY_INT, L->ncol + 1); | |||
| 471 | CREATE_1D_ARRAY(L_data, type, Lstore->nnz); | |||
| 472 | ||||
| 473 | CREATE_1D_ARRAY(U_indices, NPY_INT, Ustore->nnz); | |||
| 474 | CREATE_1D_ARRAY(U_indptr, NPY_INT, U->ncol + 1); | |||
| 475 | CREATE_1D_ARRAY(U_data, type, Ustore->nnz); | |||
| 476 | ||||
| 477 | #undef CREATE_1D_ARRAY | |||
| 478 | ||||
| 479 | /* Copy data over */ | |||
| 480 | ok = LU_to_csc( | |||
| 481 | L, U, | |||
| 482 | (int*)PyArray_DATA((PyArrayObject*)L_indices), | |||
| 483 | (int*)PyArray_DATA((PyArrayObject*)L_indptr), | |||
| 484 | (void*)PyArray_DATA((PyArrayObject*)L_data), | |||
| 485 | (int*)PyArray_DATA((PyArrayObject*)U_indices), | |||
| 486 | (int*)PyArray_DATA((PyArrayObject*)U_indptr), | |||
| 487 | (void*)PyArray_DATA((PyArrayObject*)U_data), | |||
| 488 | L->Dtype | |||
| 489 | ); | |||
| 490 | ||||
| 491 | if (ok != 0) { | |||
| 492 | goto fail; | |||
| 493 | } | |||
| 494 | ||||
| 495 | /* Create sparse matrices */ | |||
| 496 | shape = Py_BuildValue("ii", L->nrow, L->ncol); | |||
| 497 | if (shape == NULL((void*)0)) { | |||
| 498 | goto fail; | |||
| 499 | } | |||
| 500 | ||||
| 501 | datatuple = Py_BuildValue("OOO", L_data, L_indices, L_indptr); | |||
| 502 | if (datatuple == NULL((void*)0)) { | |||
| 503 | goto fail; | |||
| 504 | } | |||
| 505 | *L_csc = PyObject_CallFunction(py_csc_construct_func, | |||
| 506 | "OO", datatuple, shape); | |||
| 507 | if (*L_csc == NULL((void*)0)) { | |||
| 508 | goto fail; | |||
| 509 | } | |||
| 510 | ||||
| 511 | Py_DECREF(datatuple)_Py_DECREF(((PyObject*)(datatuple))); | |||
| 512 | datatuple = Py_BuildValue("OOO", U_data, U_indices, U_indptr); | |||
| 513 | if (datatuple == NULL((void*)0)) { | |||
| 514 | Py_DECREF(*L_csc)_Py_DECREF(((PyObject*)(*L_csc))); | |||
| 515 | *L_csc = NULL((void*)0); | |||
| 516 | goto fail; | |||
| 517 | } | |||
| 518 | *U_csc = PyObject_CallFunction(py_csc_construct_func, | |||
| 519 | "OO", datatuple, shape); | |||
| 520 | if (*U_csc == NULL((void*)0)) { | |||
| 521 | Py_DECREF(*L_csc)_Py_DECREF(((PyObject*)(*L_csc))); | |||
| 522 | *L_csc = NULL((void*)0); | |||
| 523 | goto fail; | |||
| 524 | } | |||
| 525 | ||||
| 526 | result = 0; | |||
| 527 | ||||
| 528 | fail: | |||
| 529 | Py_XDECREF(U_indices)_Py_XDECREF(((PyObject*)(U_indices))); | |||
| 530 | Py_XDECREF(U_indptr)_Py_XDECREF(((PyObject*)(U_indptr))); | |||
| 531 | Py_XDECREF(U_data)_Py_XDECREF(((PyObject*)(U_data))); | |||
| 532 | Py_XDECREF(L_indices)_Py_XDECREF(((PyObject*)(L_indices))); | |||
| 533 | Py_XDECREF(L_indptr)_Py_XDECREF(((PyObject*)(L_indptr))); | |||
| 534 | Py_XDECREF(L_data)_Py_XDECREF(((PyObject*)(L_data))); | |||
| 535 | Py_XDECREF(shape)_Py_XDECREF(((PyObject*)(shape))); | |||
| 536 | Py_XDECREF(datatuple)_Py_XDECREF(((PyObject*)(datatuple))); | |||
| 537 | ||||
| 538 | return result; | |||
| 539 | } | |||
| 540 | ||||
| 541 | ||||
| 542 | /* | |||
| 543 | * Convert SuperLU L and U matrices to CSC format. | |||
| 544 | * | |||
| 545 | * The LU decomposition U factor is partly stored in U and partly in the upper | |||
| 546 | * diagonal of L. The L matrix is stored in column-addressable rectangular | |||
| 547 | * superblock format. | |||
| 548 | * | |||
| 549 | * This routine is partly adapted from SuperLU MATLAB wrappers and the | |||
| 550 | * SuperLU Print_SuperNode_Matrix routine. | |||
| 551 | */ | |||
| 552 | static int | |||
| 553 | LU_to_csc(SuperMatrix *L, SuperMatrix *U, | |||
| 554 | int *L_rowind, int *L_colptr, char *L_data, | |||
| 555 | int *U_rowind, int *U_colptr, char *U_data, | |||
| 556 | Dtype_t dtype) | |||
| 557 | { | |||
| 558 | SCformat *Lstore; | |||
| 559 | NCformat *Ustore; | |||
| 560 | npy_intp elsize; | |||
| 561 | int isup, icol, icolstart, icolend, iptr, istart, iend; | |||
| 562 | char *src, *dst; | |||
| 563 | int U_nnz, L_nnz; | |||
| 564 | ||||
| 565 | Ustore = (NCformat*)U->Store; | |||
| 566 | Lstore = (SCformat*)L->Store; | |||
| 567 | ||||
| 568 | switch (dtype) { | |||
| 569 | case SLU_S: elsize = 4; break; | |||
| 570 | case SLU_D: elsize = 8; break; | |||
| 571 | case SLU_C: elsize = 8; break; | |||
| 572 | case SLU_Z: elsize = 16; break; | |||
| 573 | default: | |||
| 574 | /* shouldn't occur */ | |||
| 575 | PyErr_SetString(PyExc_ValueError, "unknown dtype"); | |||
| 576 | return -1; | |||
| 577 | } | |||
| 578 | ||||
| 579 | #define IS_ZERO(p)((dtype == SLU_S) ? (*(float*)(p) == 0) : ((dtype == SLU_D) ? (*(double*)(p) == 0) : ((dtype == SLU_C) ? (*(float*)(p) == 0 && *((float*)(p)+1) == 0) : (*(double*)(p) == 0 && *((double*)(p)+1) == 0)))) \ | |||
| 580 | ((dtype == SLU_S) ? (*(float*)(p) == 0) : \ | |||
| 581 | ((dtype == SLU_D) ? (*(double*)(p) == 0) : \ | |||
| 582 | ((dtype == SLU_C) ? (*(float*)(p) == 0 && *((float*)(p)+1) == 0) : \ | |||
| 583 | (*(double*)(p) == 0 && *((double*)(p)+1) == 0)))) | |||
| 584 | ||||
| 585 | U_colptr[0] = 0; | |||
| 586 | L_colptr[0] = 0; | |||
| 587 | U_nnz = 0; | |||
| 588 | L_nnz = 0; | |||
| 589 | ||||
| 590 | /* For each supernode */ | |||
| 591 | for (isup = 0; isup <= Lstore->nsuper; ++isup) { | |||
| 592 | icolstart = Lstore->sup_to_col[isup]; | |||
| 593 | icolend = Lstore->sup_to_col[isup+1]; | |||
| 594 | istart = Lstore->rowind_colptr[icolstart]; | |||
| 595 | iend = Lstore->rowind_colptr[icolstart+1]; | |||
| 596 | ||||
| 597 | /* For each column in supernode */ | |||
| 598 | for (icol = icolstart; icol < icolend; ++icol) { | |||
| 599 | ||||
| 600 | /* Process data in Ustore */ | |||
| 601 | for (iptr = Ustore->colptr[icol]; iptr < Ustore->colptr[icol+1]; ++iptr) { | |||
| 602 | src = (char*)Ustore->nzval + elsize * iptr; | |||
| 603 | if (!IS_ZERO(src)((dtype == SLU_S) ? (*(float*)(src) == 0) : ((dtype == SLU_D) ? (*(double*)(src) == 0) : ((dtype == SLU_C) ? (*(float*)(src ) == 0 && *((float*)(src)+1) == 0) : (*(double*)(src) == 0 && *((double*)(src)+1) == 0))))) { | |||
| 604 | if (U_nnz >= Ustore->nnz) | |||
| 605 | goto size_error; | |||
| 606 | U_rowind[U_nnz] = Ustore->rowind[iptr]; | |||
| 607 | /* "U_data[U_nnz] = Ustore->nzvals[iptr]" */ | |||
| 608 | dst = U_data + elsize * U_nnz; | |||
| 609 | memcpy(dst, src, elsize); | |||
| 610 | ++U_nnz; | |||
| 611 | } | |||
| 612 | } | |||
| 613 | ||||
| 614 | /* Process data in Lstore */ | |||
| 615 | src = (char*)Lstore->nzval + elsize * Lstore->nzval_colptr[icol]; | |||
| 616 | iptr = istart; | |||
| 617 | ||||
| 618 | /* Upper triangle part */ | |||
| 619 | for (; iptr < iend; ++iptr) { | |||
| 620 | if (Lstore->rowind[iptr] > icol) { | |||
| 621 | break; | |||
| 622 | } | |||
| 623 | if (!IS_ZERO(src)((dtype == SLU_S) ? (*(float*)(src) == 0) : ((dtype == SLU_D) ? (*(double*)(src) == 0) : ((dtype == SLU_C) ? (*(float*)(src ) == 0 && *((float*)(src)+1) == 0) : (*(double*)(src) == 0 && *((double*)(src)+1) == 0))))) { | |||
| 624 | if (U_nnz >= Ustore->nnz) | |||
| 625 | goto size_error; | |||
| 626 | U_rowind[U_nnz] = Lstore->rowind[iptr]; | |||
| 627 | dst = U_data + elsize * U_nnz; | |||
| 628 | memcpy(dst, src, elsize); | |||
| 629 | ++U_nnz; | |||
| 630 | } | |||
| 631 | src += elsize; | |||
| 632 | } | |||
| 633 | ||||
| 634 | /* Add unit diagonal in L */ | |||
| 635 | if (L_nnz >= Lstore->nnz) return -1; | |||
| 636 | dst = L_data + elsize * L_nnz; | |||
| 637 | switch (dtype) { | |||
| 638 | case SLU_S: *(float*)dst = 1.0; break; | |||
| 639 | case SLU_D: *(double*)dst = 1.0; break; | |||
| 640 | case SLU_C: *(float*)dst = 1.0; *((float*)dst+1) = 0.0; break; | |||
| 641 | case SLU_Z: *(double*)dst = 1.0; *((double*)dst+1) = 0.0; break; | |||
| 642 | } | |||
| 643 | L_rowind[L_nnz] = icol; | |||
| 644 | ++L_nnz; | |||
| 645 | ||||
| 646 | /* Lower triangle part */ | |||
| 647 | for (; iptr < iend; ++iptr) { | |||
| 648 | if (!IS_ZERO(src)((dtype == SLU_S) ? (*(float*)(src) == 0) : ((dtype == SLU_D) ? (*(double*)(src) == 0) : ((dtype == SLU_C) ? (*(float*)(src ) == 0 && *((float*)(src)+1) == 0) : (*(double*)(src) == 0 && *((double*)(src)+1) == 0))))) { | |||
| 649 | if (L_nnz >= Lstore->nnz) | |||
| 650 | goto size_error; | |||
| 651 | L_rowind[L_nnz] = Lstore->rowind[iptr]; | |||
| 652 | dst = L_data + elsize * L_nnz; | |||
| 653 | memcpy(dst, src, elsize); | |||
| 654 | ++L_nnz; | |||
| 655 | } | |||
| 656 | src += elsize; | |||
| 657 | } | |||
| 658 | ||||
| 659 | /* Record column pointers */ | |||
| 660 | U_colptr[icol+1] = U_nnz; | |||
| 661 | L_colptr[icol+1] = L_nnz; | |||
| 662 | } | |||
| 663 | } | |||
| 664 | ||||
| 665 | return 0; | |||
| 666 | ||||
| 667 | size_error: | |||
| 668 | PyErr_SetString(PyExc_RuntimeError, | |||
| 669 | "internal error: superlu matrixes have wrong nnz"); | |||
| 670 | return -1; | |||
| 671 | } | |||
| 672 | ||||
| 673 | ||||
| 674 | PyObject *newSuperLUObject(SuperMatrix * A, PyObject * option_dict, | |||
| 675 | int intype, int ilu, PyObject * py_csc_construct_func) | |||
| 676 | { | |||
| 677 | ||||
| 678 | /* A must be in SLU_NC format used by the factorization routine. */ | |||
| 679 | volatile SuperLUObject *self; | |||
| 680 | volatile SuperMatrix AC = { 0 }; /* Matrix postmultiplied by Pc */ | |||
| 681 | volatile int lwork = 0; | |||
| 682 | volatile int *etree = NULL((void*)0); | |||
| 683 | volatile int info; | |||
| 684 | volatile int n; | |||
| 685 | volatile superlu_options_t options; | |||
| 686 | volatile SuperLUStat_t stat = { 0 }; | |||
| 687 | volatile int panel_size, relax; | |||
| 688 | volatile GlobalLU_t Glu; | |||
| 689 | static volatile GlobalLU_t static_Glu; | |||
| 690 | volatile GlobalLU_t *Glu_ptr; | |||
| 691 | volatile jmp_buf *jmpbuf_ptr; | |||
| 692 | SLU_BEGIN_THREADS_DEFvolatile PyThreadState *_save = ((void*)0); | |||
| 693 | ||||
| 694 | n = A->ncol; | |||
| 695 | ||||
| 696 | if (!set_superlu_options_from_dict((superlu_options_t*)&options, ilu, option_dict, | |||
| 697 | (int*)&panel_size, (int*)&relax)) { | |||
| 698 | return NULL((void*)0); | |||
| 699 | } | |||
| 700 | ||||
| 701 | /* Create SLUObject */ | |||
| 702 | self = PyObject_New(SuperLUObject, &SuperLUType)( (SuperLUObject *) _PyObject_New(&SuperLUType) ); | |||
| 703 | if (self == NULL((void*)0)) | |||
| 704 | return PyErr_NoMemory(); | |||
| 705 | self->m = A->nrow; | |||
| 706 | self->n = n; | |||
| 707 | self->perm_r = NULL((void*)0); | |||
| 708 | self->perm_c = NULL((void*)0); | |||
| 709 | self->L.Store = NULL((void*)0); | |||
| 710 | self->U.Store = NULL((void*)0); | |||
| 711 | self->cached_U = NULL((void*)0); | |||
| 712 | self->cached_L = NULL((void*)0); | |||
| 713 | self->py_csc_construct_func = NULL((void*)0); | |||
| 714 | self->type = intype; | |||
| 715 | ||||
| 716 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 717 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 718 | goto fail; | |||
| 719 | } | |||
| 720 | ||||
| 721 | /* Calculate and apply minimum degree ordering */ | |||
| 722 | etree = intMalloc(n); | |||
| 723 | self->perm_r = intMalloc(n); | |||
| 724 | self->perm_c = intMalloc(n); | |||
| 725 | StatInit((SuperLUStat_t *)&stat); | |||
| 726 | ||||
| 727 | /* calc column permutation */ | |||
| 728 | get_perm_c(options.ColPerm, A, self->perm_c); | |||
| 729 | ||||
| 730 | /* apply column permutation */ | |||
| 731 | sp_preorder((superlu_options_t*)&options, A, self->perm_c, (int*)etree, | |||
| 732 | (SuperMatrix*)&AC); | |||
| 733 | ||||
| 734 | /* Perform factorization */ | |||
| 735 | if (!CHECK_SLU_TYPE(SLU_TYPECODE_TO_NPY(A->Dtype))(( ((A->Dtype) == SLU_S) ? NPY_FLOAT : ((A->Dtype) == SLU_D ) ? NPY_DOUBLE : ((A->Dtype) == SLU_C) ? NPY_CFLOAT : ((A-> Dtype) == SLU_Z) ? NPY_CDOUBLE : -1) == NPY_FLOAT || ( ((A-> Dtype) == SLU_S) ? NPY_FLOAT : ((A->Dtype) == SLU_D) ? NPY_DOUBLE : ((A->Dtype) == SLU_C) ? NPY_CFLOAT : ((A->Dtype) == SLU_Z ) ? NPY_CDOUBLE : -1) == NPY_DOUBLE || ( ((A->Dtype) == SLU_S ) ? NPY_FLOAT : ((A->Dtype) == SLU_D) ? NPY_DOUBLE : ((A-> Dtype) == SLU_C) ? NPY_CFLOAT : ((A->Dtype) == SLU_Z) ? NPY_CDOUBLE : -1) == NPY_CFLOAT || ( ((A->Dtype) == SLU_S) ? NPY_FLOAT : ((A->Dtype) == SLU_D) ? NPY_DOUBLE : ((A->Dtype) == SLU_C ) ? NPY_CFLOAT : ((A->Dtype) == SLU_Z) ? NPY_CDOUBLE : -1) == NPY_CDOUBLE)) { | |||
| 736 | PyErr_SetString(PyExc_ValueError, "Invalid type in SuperMatrix."); | |||
| 737 | goto fail; | |||
| 738 | } | |||
| 739 | ||||
| 740 | if (options.Fact == SamePattern || options.Fact == SamePattern_SameRowPerm) { | |||
| 741 | /* XXX: not nice, a better new API should be introduced for this */ | |||
| 742 | Glu_ptr = &static_Glu; | |||
| 743 | } | |||
| 744 | else { | |||
| 745 | Glu_ptr = &Glu; | |||
| 746 | jmpbuf_ptr = (volatile jmp_buf *)superlu_python_jmpbuf(); | |||
| 747 | SLU_BEGIN_THREADSdo { if (_save == ((void*)0)) _save = PyEval_SaveThread(); } while (0); | |||
| 748 | if (setjmp(*(jmp_buf*)jmpbuf_ptr)_setjmp (*(jmp_buf*)jmpbuf_ptr)) { | |||
| 749 | SLU_END_THREADSdo { if (_save) { PyEval_RestoreThread((PyThreadState*)_save) ; _save = ((void*)0);} } while (0); | |||
| 750 | goto fail; | |||
| 751 | } | |||
| 752 | } | |||
| 753 | ||||
| 754 | if (ilu) { | |||
| 755 | gsitrf(SLU_TYPECODE_TO_NPY(A->Dtype)( ((A->Dtype) == SLU_S) ? NPY_FLOAT : ((A->Dtype) == SLU_D ) ? NPY_DOUBLE : ((A->Dtype) == SLU_C) ? NPY_CFLOAT : ((A-> Dtype) == SLU_Z) ? NPY_CDOUBLE : -1), | |||
| 756 | (superlu_options_t*)&options, (SuperMatrix*)&AC, relax, panel_size, | |||
| 757 | (int*)etree, NULL((void*)0), lwork, self->perm_c, self->perm_r, | |||
| 758 | (SuperMatrix*)&self->L, (SuperMatrix*)&self->U, (GlobalLU_t*)Glu_ptr, | |||
| 759 | (SuperLUStat_t*)&stat, (int*)&info); | |||
| 760 | } | |||
| 761 | else { | |||
| 762 | gstrf(SLU_TYPECODE_TO_NPY(A->Dtype)( ((A->Dtype) == SLU_S) ? NPY_FLOAT : ((A->Dtype) == SLU_D ) ? NPY_DOUBLE : ((A->Dtype) == SLU_C) ? NPY_CFLOAT : ((A-> Dtype) == SLU_Z) ? NPY_CDOUBLE : -1), | |||
| 763 | (superlu_options_t*)&options, (SuperMatrix*)&AC, relax, panel_size, | |||
| 764 | (int*)etree, NULL((void*)0), lwork, self->perm_c, self->perm_r, | |||
| 765 | (SuperMatrix*)&self->L, (SuperMatrix*)&self->U, (GlobalLU_t*)Glu_ptr, | |||
| 766 | (SuperLUStat_t*)&stat, (int*)&info); | |||
| 767 | } | |||
| 768 | ||||
| 769 | SLU_END_THREADSdo { if (_save) { PyEval_RestoreThread((PyThreadState*)_save) ; _save = ((void*)0);} } while (0); | |||
| 770 | ||||
| 771 | if (info) { | |||
| 772 | if (info < 0) | |||
| 773 | PyErr_SetString(PyExc_SystemError, | |||
| 774 | "gstrf was called with invalid arguments"); | |||
| 775 | else { | |||
| 776 | if (info <= n) | |||
| 777 | PyErr_SetString(PyExc_RuntimeError, | |||
| 778 | "Factor is exactly singular"); | |||
| 779 | else | |||
| 780 | PyErr_NoMemory(); | |||
| 781 | } | |||
| 782 | goto fail; | |||
| 783 | } | |||
| 784 | ||||
| 785 | Py_INCREF(py_csc_construct_func)_Py_INCREF(((PyObject*)(py_csc_construct_func))); | |||
| 786 | self->py_csc_construct_func = py_csc_construct_func; | |||
| 787 | ||||
| 788 | /* free memory */ | |||
| 789 | SUPERLU_FREE((void*)etree)superlu_python_module_free((void*)etree); | |||
| 790 | Destroy_CompCol_Permuted((SuperMatrix*)&AC); | |||
| 791 | StatFree((SuperLUStat_t*)&stat); | |||
| 792 | ||||
| 793 | return (PyObject *) self; | |||
| 794 | ||||
| 795 | fail: | |||
| 796 | SUPERLU_FREE((void*)etree)superlu_python_module_free((void*)etree); | |||
| 797 | XDestroy_CompCol_Permuted((SuperMatrix*)&AC); | |||
| 798 | XStatFree((SuperLUStat_t*)&stat); | |||
| 799 | Py_DECREF(self)_Py_DECREF(((PyObject*)(self))); | |||
| 800 | return NULL((void*)0); | |||
| 801 | } | |||
| 802 | ||||
| 803 | ||||
| 804 | /*********************************************************************** | |||
| 805 | * Preparing superlu_options_t | |||
| 806 | */ | |||
| 807 | ||||
| 808 | #define ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); } \ | |||
| 809 | long i = -1; \ | |||
| 810 | char *s = ""; \ | |||
| 811 | PyObject *tmpobj = NULL((void*)0); \ | |||
| 812 | if (input == Py_None(&_Py_NoneStruct)) return 1; \ | |||
| 813 | if (PyBytes_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 27))) != 0)) { \ | |||
| 814 | s = PyBytes_AS_STRING(input)(((void) (0)), (((PyBytesObject *)(input))->ob_sval)); \ | |||
| 815 | } \ | |||
| 816 | else if (PyUnicode_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { \ | |||
| 817 | tmpobj = PyUnicode_AsASCIIString(input);\ | |||
| 818 | if (tmpobj == NULL((void*)0)) return 0; \ | |||
| 819 | s = PyBytes_AS_STRING(tmpobj)(((void) (0)), (((PyBytesObject *)(tmpobj))->ob_sval)); \ | |||
| 820 | } \ | |||
| 821 | else if (PyLong_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { \ | |||
| 822 | i = PyLong_AsLong(input); \ | |||
| 823 | } | |||
| 824 | ||||
| 825 | #define ENUM_CHECK_FINISH(message)_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , message); return 0; \ | |||
| 826 | Py_XDECREF(tmpobj)_Py_XDECREF(((PyObject*)(tmpobj))); \ | |||
| 827 | PyErr_SetString(PyExc_ValueError, message); \ | |||
| 828 | return 0; | |||
| 829 | ||||
| 830 | #define ENUM_CHECK_NAME(name, sname)if (my_strxcmp(s, sname) == 0 || i == (long)name) { *value = name ; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; } \ | |||
| 831 | if (my_strxcmp(s, sname) == 0 || i == (long)name) { \ | |||
| 832 | *value = name; \ | |||
| 833 | Py_XDECREF(tmpobj)_Py_XDECREF(((PyObject*)(tmpobj))); \ | |||
| 834 | return 1; \ | |||
| 835 | } | |||
| 836 | ||||
| 837 | #define ENUM_CHECK(name)if (my_strxcmp(s, "name") == 0 || i == (long)name) { *value = name; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; } ENUM_CHECK_NAME(name, #name)if (my_strxcmp(s, #name) == 0 || i == (long)name) { *value = name ; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; } | |||
| 838 | ||||
| 839 | /* | |||
| 840 | * Compare strings ignoring case, underscores and whitespace | |||
| 841 | */ | |||
| 842 | static int my_strxcmp(const char *a, const char *b) | |||
| 843 | { | |||
| 844 | int c; | |||
| 845 | ||||
| 846 | while (*a != '\0' && *b != '\0') { | |||
| 847 | while (*a == '_' || isspace(*a)((*__ctype_b_loc ())[(int) ((*a))] & (unsigned short int) _ISspace)) | |||
| 848 | ++a; | |||
| 849 | while (*b == '_' || isspace(*b)((*__ctype_b_loc ())[(int) ((*b))] & (unsigned short int) _ISspace)) | |||
| 850 | ++b; | |||
| 851 | c = (int) tolower(*a)(__extension__ ({ int __res; if (sizeof (*a) > 1) { if (__builtin_constant_p (*a)) { int __c = (*a); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (*a); } else __res = (*__ctype_tolower_loc ())[(int) (*a)]; __res ; })) - (int) tolower(*b)(__extension__ ({ int __res; if (sizeof (*b) > 1) { if (__builtin_constant_p (*b)) { int __c = (*b); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (*b); } else __res = (*__ctype_tolower_loc ())[(int) (*b)]; __res ; })); | |||
| 852 | if (c != 0) { | |||
| 853 | return c; | |||
| 854 | } | |||
| 855 | ++a; | |||
| 856 | ++b; | |||
| 857 | } | |||
| 858 | return (int) tolower(*a)(__extension__ ({ int __res; if (sizeof (*a) > 1) { if (__builtin_constant_p (*a)) { int __c = (*a); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (*a); } else __res = (*__ctype_tolower_loc ())[(int) (*a)]; __res ; })) - (int) tolower(*b)(__extension__ ({ int __res; if (sizeof (*b) > 1) { if (__builtin_constant_p (*b)) { int __c = (*b); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc ())[__c]; } else __res = tolower (*b); } else __res = (*__ctype_tolower_loc ())[(int) (*b)]; __res ; })); | |||
| 859 | } | |||
| 860 | ||||
| 861 | static int yes_no_cvt(PyObject * input, yes_no_t * value) | |||
| 862 | { | |||
| 863 | if (input == Py_None(&_Py_NoneStruct)) { | |||
| 864 | return 1; | |||
| 865 | } | |||
| 866 | else if (input == Py_True((PyObject *) &_Py_TrueStruct)) { | |||
| 867 | *value = YES; | |||
| 868 | } | |||
| 869 | else if (input == Py_False((PyObject *) &_Py_FalseStruct)) { | |||
| 870 | *value = NO; | |||
| 871 | } | |||
| 872 | else { | |||
| 873 | PyErr_SetString(PyExc_ValueError, "value not a boolean"); | |||
| 874 | return 0; | |||
| 875 | } | |||
| 876 | return 1; | |||
| 877 | } | |||
| 878 | ||||
| 879 | static int fact_cvt(PyObject * input, fact_t * value) | |||
| 880 | { | |||
| 881 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 882 | ENUM_CHECK(DOFACT)if (my_strxcmp(s, "DOFACT") == 0 || i == (long)DOFACT) { *value = DOFACT; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 883 | ENUM_CHECK(SamePattern)if (my_strxcmp(s, "SamePattern") == 0 || i == (long)SamePattern ) { *value = SamePattern; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 884 | ENUM_CHECK(SamePattern_SameRowPerm)if (my_strxcmp(s, "SamePattern_SameRowPerm") == 0 || i == (long )SamePattern_SameRowPerm) { *value = SamePattern_SameRowPerm; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 885 | ENUM_CHECK(FACTORED)if (my_strxcmp(s, "FACTORED") == 0 || i == (long)FACTORED) { * value = FACTORED; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 886 | ENUM_CHECK_FINISH("invalid value for 'Fact' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'Fact' parameter"); return 0;; | |||
| 887 | } | |||
| 888 | ||||
| 889 | static int rowperm_cvt(PyObject * input, rowperm_t * value) | |||
| 890 | { | |||
| 891 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 892 | ENUM_CHECK(NOROWPERM)if (my_strxcmp(s, "NOROWPERM") == 0 || i == (long)NOROWPERM) { *value = NOROWPERM; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 893 | ENUM_CHECK(MY_PERMR)if (my_strxcmp(s, "MY_PERMR") == 0 || i == (long)MY_PERMR) { * value = MY_PERMR; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 894 | ENUM_CHECK_FINISH("invalid value for 'RowPerm' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'RowPerm' parameter"); return 0;; | |||
| 895 | } | |||
| 896 | ||||
| 897 | static int colperm_cvt(PyObject * input, colperm_t * value) | |||
| 898 | { | |||
| 899 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 900 | ENUM_CHECK(NATURAL)if (my_strxcmp(s, "NATURAL") == 0 || i == (long)NATURAL) { *value = NATURAL; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 901 | ENUM_CHECK(MMD_ATA)if (my_strxcmp(s, "MMD_ATA") == 0 || i == (long)MMD_ATA) { *value = MMD_ATA; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 902 | ENUM_CHECK(MMD_AT_PLUS_A)if (my_strxcmp(s, "MMD_AT_PLUS_A") == 0 || i == (long)MMD_AT_PLUS_A ) { *value = MMD_AT_PLUS_A; _Py_XDECREF(((PyObject*)(tmpobj)) ); return 1; }; | |||
| 903 | ENUM_CHECK(COLAMD)if (my_strxcmp(s, "COLAMD") == 0 || i == (long)COLAMD) { *value = COLAMD; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 904 | ENUM_CHECK(MY_PERMC)if (my_strxcmp(s, "MY_PERMC") == 0 || i == (long)MY_PERMC) { * value = MY_PERMC; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 905 | ENUM_CHECK_FINISH("invalid value for 'ColPerm' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'ColPerm' parameter"); return 0;; | |||
| 906 | } | |||
| 907 | ||||
| 908 | static int trans_cvt(PyObject * input, trans_t * value) | |||
| 909 | { | |||
| 910 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| ||||
| ||||
| 911 | ENUM_CHECK(NOTRANS)if (my_strxcmp(s, "NOTRANS") == 0 || i == (long)NOTRANS) { *value = NOTRANS; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 912 | ENUM_CHECK(TRANS)if (my_strxcmp(s, "TRANS") == 0 || i == (long)TRANS) { *value = TRANS; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 913 | ENUM_CHECK(CONJ)if (my_strxcmp(s, "CONJ") == 0 || i == (long)CONJ) { *value = CONJ; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 914 | if (my_strxcmp(s, "N") == 0) { | |||
| 915 | *value = NOTRANS; | |||
| 916 | return 1; | |||
| 917 | } | |||
| 918 | if (my_strxcmp(s, "T") == 0) { | |||
| 919 | *value = TRANS; | |||
| 920 | return 1; | |||
| 921 | } | |||
| 922 | if (my_strxcmp(s, "H") == 0) { | |||
| 923 | *value = CONJ; | |||
| 924 | return 1; | |||
| 925 | } | |||
| 926 | ENUM_CHECK_FINISH("invalid value for 'Trans' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'Trans' parameter"); return 0;; | |||
| 927 | } | |||
| 928 | ||||
| 929 | static int iterrefine_cvt(PyObject * input, IterRefine_t * value) | |||
| 930 | { | |||
| 931 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 932 | ENUM_CHECK(NOREFINE)if (my_strxcmp(s, "NOREFINE") == 0 || i == (long)NOREFINE) { * value = NOREFINE; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 933 | ENUM_CHECK(SLU_SINGLE)if (my_strxcmp(s, "SLU_SINGLE") == 0 || i == (long)SLU_SINGLE ) { *value = SLU_SINGLE; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 934 | ENUM_CHECK_NAME(SLU_SINGLE, "SINGLE")if (my_strxcmp(s, "SINGLE") == 0 || i == (long)SLU_SINGLE) { * value = SLU_SINGLE; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 935 | ENUM_CHECK(SLU_DOUBLE)if (my_strxcmp(s, "SLU_DOUBLE") == 0 || i == (long)SLU_DOUBLE ) { *value = SLU_DOUBLE; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 936 | ENUM_CHECK_NAME(SLU_DOUBLE, "DOUBLE")if (my_strxcmp(s, "DOUBLE") == 0 || i == (long)SLU_DOUBLE) { * value = SLU_DOUBLE; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 937 | ENUM_CHECK(SLU_EXTRA)if (my_strxcmp(s, "SLU_EXTRA") == 0 || i == (long)SLU_EXTRA) { *value = SLU_EXTRA; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 938 | ENUM_CHECK_NAME(SLU_EXTRA, "EXTRA")if (my_strxcmp(s, "EXTRA") == 0 || i == (long)SLU_EXTRA) { *value = SLU_EXTRA; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 939 | ENUM_CHECK_FINISH("invalid value for 'IterRefine' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'IterRefine' parameter"); return 0;; | |||
| 940 | } | |||
| 941 | ||||
| 942 | static int norm_cvt(PyObject * input, norm_t * value) | |||
| 943 | { | |||
| 944 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 945 | ENUM_CHECK(ONE_NORM)if (my_strxcmp(s, "ONE_NORM") == 0 || i == (long)ONE_NORM) { * value = ONE_NORM; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 946 | ENUM_CHECK(TWO_NORM)if (my_strxcmp(s, "TWO_NORM") == 0 || i == (long)TWO_NORM) { * value = TWO_NORM; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 947 | ENUM_CHECK(INF_NORM)if (my_strxcmp(s, "INF_NORM") == 0 || i == (long)INF_NORM) { * value = INF_NORM; _Py_XDECREF(((PyObject*)(tmpobj))); return 1 ; }; | |||
| 948 | ENUM_CHECK_FINISH("invalid value for 'ILU_Norm' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'ILU_Norm' parameter"); return 0;; | |||
| 949 | } | |||
| 950 | ||||
| 951 | static int milu_cvt(PyObject * input, milu_t * value) | |||
| 952 | { | |||
| 953 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 954 | ENUM_CHECK(SILU)if (my_strxcmp(s, "SILU") == 0 || i == (long)SILU) { *value = SILU; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 955 | ENUM_CHECK(SMILU_1)if (my_strxcmp(s, "SMILU_1") == 0 || i == (long)SMILU_1) { *value = SMILU_1; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 956 | ENUM_CHECK(SMILU_2)if (my_strxcmp(s, "SMILU_2") == 0 || i == (long)SMILU_2) { *value = SMILU_2; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 957 | ENUM_CHECK(SMILU_3)if (my_strxcmp(s, "SMILU_3") == 0 || i == (long)SMILU_3) { *value = SMILU_3; _Py_XDECREF(((PyObject*)(tmpobj))); return 1; }; | |||
| 958 | ENUM_CHECK_FINISH("invalid value for 'ILU_MILU' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'ILU_MILU' parameter"); return 0;; | |||
| 959 | } | |||
| 960 | ||||
| 961 | static int droprule_one_cvt(PyObject * input, int *value) | |||
| 962 | { | |||
| 963 | ENUM_CHECK_INITlong i = -1; char *s = ""; PyObject *tmpobj = ((void*)0); if ( input == (&_Py_NoneStruct)) return 1; if (((((((PyObject* )(input))->ob_type))->tp_flags & ((1UL << 27) )) != 0)) { s = (((void) (0)), (((PyBytesObject *)(input))-> ob_sval)); } else if (((((((PyObject*)(input))->ob_type))-> tp_flags & ((1UL << 28))) != 0)) { tmpobj = PyUnicode_AsASCIIString (input); if (tmpobj == ((void*)0)) return 0; s = (((void) (0) ), (((PyBytesObject *)(tmpobj))->ob_sval)); } else if (((( (((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { i = PyLong_AsLong(input); }; | |||
| 964 | if (my_strxcmp(s, "BASIC") == 0) { | |||
| 965 | *value = DROP_BASIC( 0x0001 ); | |||
| 966 | return 1; | |||
| 967 | } | |||
| 968 | if (my_strxcmp(s, "PROWS") == 0) { | |||
| 969 | *value = DROP_PROWS( 0x0002 ); | |||
| 970 | return 1; | |||
| 971 | } | |||
| 972 | if (my_strxcmp(s, "COLUMN") == 0) { | |||
| 973 | *value = DROP_COLUMN( 0x0004 ); | |||
| 974 | return 1; | |||
| 975 | } | |||
| 976 | if (my_strxcmp(s, "AREA") == 0) { | |||
| 977 | *value = DROP_AREA( 0x0008 ); | |||
| 978 | return 1; | |||
| 979 | } | |||
| 980 | if (my_strxcmp(s, "SECONDARY") == 0) { | |||
| 981 | *value = DROP_SECONDARY( 0x000E ); | |||
| 982 | return 1; | |||
| 983 | } | |||
| 984 | if (my_strxcmp(s, "DYNAMIC") == 0) { | |||
| 985 | *value = DROP_DYNAMIC( 0x0010 ); | |||
| 986 | return 1; | |||
| 987 | } | |||
| 988 | if (my_strxcmp(s, "INTERP") == 0) { | |||
| 989 | *value = DROP_INTERP( 0x0100 ); | |||
| 990 | return 1; | |||
| 991 | } | |||
| 992 | ENUM_CHECK_FINISH("invalid value for 'ILU_DropRule' parameter")_Py_XDECREF(((PyObject*)(tmpobj))); PyErr_SetString(PyExc_ValueError , "invalid value for 'ILU_DropRule' parameter"); return 0;; | |||
| 993 | } | |||
| 994 | ||||
| 995 | static int droprule_cvt(PyObject * input, int *value) | |||
| 996 | { | |||
| 997 | PyObject *seq = NULL((void*)0); | |||
| 998 | int i; | |||
| 999 | int rule = 0; | |||
| 1000 | ||||
| 1001 | if (input == Py_None(&_Py_NoneStruct)) { | |||
| 1002 | /* Leave as default */ | |||
| 1003 | return 1; | |||
| 1004 | } | |||
| 1005 | else if (PyLong_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 24))) != 0)) { | |||
| 1006 | *value = PyLong_AsLong(input); | |||
| 1007 | return 1; | |||
| 1008 | } | |||
| 1009 | else if (PyBytes_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 27))) != 0) || PyUnicode_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 28))) != 0)) { | |||
| 1010 | /* Comma-separated string */ | |||
| 1011 | char *fmt = "s"; | |||
| 1012 | if (PyBytes_Check(input)((((((PyObject*)(input))->ob_type))->tp_flags & ((1UL << 27))) != 0)) { | |||
| 1013 | fmt = "y"; | |||
| 1014 | } | |||
| 1015 | seq = PyObject_CallMethod(input, "split", fmt, ","); | |||
| 1016 | if (seq == NULL((void*)0) || !PySequence_Check(seq)) | |||
| 1017 | goto fail; | |||
| 1018 | } | |||
| 1019 | else if (PySequence_Check(input)) { | |||
| 1020 | /* Sequence of strings or integers */ | |||
| 1021 | seq = input; | |||
| 1022 | Py_INCREF(seq)_Py_INCREF(((PyObject*)(seq))); | |||
| 1023 | } | |||
| 1024 | else { | |||
| 1025 | PyErr_SetString(PyExc_ValueError, "invalid value for drop rule"); | |||
| 1026 | goto fail; | |||
| 1027 | } | |||
| 1028 | ||||
| 1029 | /* OR multiple values together */ | |||
| 1030 | for (i = 0; i < PySequence_Size(seq); ++i) { | |||
| 1031 | PyObject *item; | |||
| 1032 | int one_value = 0; | |||
| 1033 | ||||
| 1034 | item = PySequence_ITEM(seq, i)( (((PyObject*)(seq))->ob_type)->tp_as_sequence->sq_item (seq, i) ); | |||
| 1035 | if (item == NULL((void*)0)) { | |||
| 1036 | goto fail; | |||
| 1037 | } | |||
| 1038 | if (!droprule_one_cvt(item, &one_value)) { | |||
| 1039 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
| 1040 | goto fail; | |||
| 1041 | } | |||
| 1042 | Py_DECREF(item)_Py_DECREF(((PyObject*)(item))); | |||
| 1043 | rule |= one_value; | |||
| 1044 | } | |||
| 1045 | Py_DECREF(seq)_Py_DECREF(((PyObject*)(seq))); | |||
| 1046 | ||||
| 1047 | *value = rule; | |||
| 1048 | return 1; | |||
| 1049 | ||||
| 1050 | fail: | |||
| 1051 | Py_XDECREF(seq)_Py_XDECREF(((PyObject*)(seq))); | |||
| 1052 | return 0; | |||
| 1053 | } | |||
| 1054 | ||||
| 1055 | static int double_cvt(PyObject * input, double *value) | |||
| 1056 | { | |||
| 1057 | if (input == Py_None(&_Py_NoneStruct)) | |||
| 1058 | return 1; | |||
| 1059 | *value = PyFloat_AsDouble(input); | |||
| 1060 | if (PyErr_Occurred()) | |||
| 1061 | return 0; | |||
| 1062 | return 1; | |||
| 1063 | } | |||
| 1064 | ||||
| 1065 | static int int_cvt(PyObject * input, int *value) | |||
| 1066 | { | |||
| 1067 | if (input == Py_None(&_Py_NoneStruct)) | |||
| 1068 | return 1; | |||
| 1069 | *value = PyLong_AsLong(input); | |||
| 1070 | if (PyErr_Occurred()) | |||
| 1071 | return 0; | |||
| 1072 | return 1; | |||
| 1073 | } | |||
| 1074 | ||||
| 1075 | int set_superlu_options_from_dict(superlu_options_t * options, | |||
| 1076 | int ilu, PyObject * option_dict, | |||
| 1077 | int *panel_size, int *relax) | |||
| 1078 | { | |||
| 1079 | PyObject *args; | |||
| 1080 | int ret; | |||
| 1081 | int _relax, _panel_size; | |||
| 1082 | ||||
| 1083 | static char *kwlist[] = { | |||
| 1084 | "Fact", "Equil", "ColPerm", "Trans", "IterRefine", | |||
| 1085 | "DiagPivotThresh", "PivotGrowth", "ConditionNumber", | |||
| 1086 | "RowPerm", "SymmetricMode", "PrintStat", "ReplaceTinyPivot", | |||
| 1087 | "SolveInitialized", "RefineInitialized", "ILU_Norm", | |||
| 1088 | "ILU_MILU", "ILU_DropTol", "ILU_FillTol", "ILU_FillFactor", | |||
| 1089 | "ILU_DropRule", "PanelSize", "Relax", NULL((void*)0) | |||
| 1090 | }; | |||
| 1091 | ||||
| 1092 | if (ilu) { | |||
| 1093 | ilu_set_default_options(options); | |||
| 1094 | } | |||
| 1095 | else { | |||
| 1096 | set_default_options(options); | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | _panel_size = sp_ienv(1); | |||
| 1100 | _relax = sp_ienv(2); | |||
| 1101 | ||||
| 1102 | if (option_dict == NULL((void*)0)) { | |||
| 1103 | /* Proceed with default options */ | |||
| 1104 | ret = 1; | |||
| 1105 | } | |||
| 1106 | else { | |||
| 1107 | args = PyTuple_New(0); | |||
| 1108 | ret = PyArg_ParseTupleAndKeywords(args, option_dict, | |||
| 1109 | "|O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&O&", | |||
| 1110 | kwlist, fact_cvt, &options->Fact, | |||
| 1111 | yes_no_cvt, &options->Equil, | |||
| 1112 | colperm_cvt, &options->ColPerm, | |||
| 1113 | trans_cvt, &options->Trans, | |||
| 1114 | iterrefine_cvt, &options->IterRefine, | |||
| 1115 | double_cvt, | |||
| 1116 | &options->DiagPivotThresh, | |||
| 1117 | yes_no_cvt, &options->PivotGrowth, | |||
| 1118 | yes_no_cvt, | |||
| 1119 | &options->ConditionNumber, | |||
| 1120 | rowperm_cvt, &options->RowPerm, | |||
| 1121 | yes_no_cvt, &options->SymmetricMode, | |||
| 1122 | yes_no_cvt, &options->PrintStat, | |||
| 1123 | yes_no_cvt, | |||
| 1124 | &options->ReplaceTinyPivot, | |||
| 1125 | yes_no_cvt, | |||
| 1126 | &options->SolveInitialized, | |||
| 1127 | yes_no_cvt, | |||
| 1128 | &options->RefineInitialized, | |||
| 1129 | norm_cvt, &options->ILU_Norm, | |||
| 1130 | milu_cvt, &options->ILU_MILU, | |||
| 1131 | double_cvt, &options->ILU_DropTol, | |||
| 1132 | double_cvt, &options->ILU_FillTol, | |||
| 1133 | double_cvt, &options->ILU_FillFactor, | |||
| 1134 | droprule_cvt, &options->ILU_DropRule, | |||
| 1135 | int_cvt, &_panel_size, int_cvt, | |||
| 1136 | &_relax); | |||
| 1137 | Py_DECREF(args)_Py_DECREF(((PyObject*)(args))); | |||
| 1138 | } | |||
| 1139 | ||||
| 1140 | if (panel_size != NULL((void*)0)) { | |||
| 1141 | *panel_size = _panel_size; | |||
| 1142 | } | |||
| 1143 | ||||
| 1144 | if (relax != NULL((void*)0)) { | |||
| 1145 | *relax = _relax; | |||
| 1146 | } | |||
| 1147 | ||||
| 1148 | return ret; | |||
| 1149 | } |
| 1 | #ifndef PyUnicode_AsASCIIString |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
| 5 | PyObject* PyUnicode_AsASCIIString(PyObject *unicode) { |
| 6 | return clang_analyzer_PyObject_New_Reference(); |
| 7 | } |
| 8 | #else |
| 9 | #warning "API PyUnicode_AsASCIIString is defined as a macro." |
| 10 | #endif |