さて、では作ってみよう。
/* * tridmodule.c --- 三重対角行列のLU分解をする Python 用 C モデュール */ /* 三重対角行列の LU 分解 (pivoting なし) */ void trilu(int n, double *al, double *ad, double *au) { int i, nm1 = n - 1; /* 前進消去 (forward elimination) */ for (i = 0; i < nm1; i++) { al[i + 1] /= ad[i]; ad[i + 1] -= au[i] * al[i + 1]; } } /* LU 分解済みの三重対角行列を係数に持つ3項方程式を解く */ void trisol(int n, double *al, double *ad, double *au, double *b) { int i, nm1 = n - 1; /* 前進消去 (forward elimination) */ for (i = 0; i < nm1; i++) b[i + 1] -= b[i] * al[i + 1]; /* 後退代入 (backward substitution) */ b[nm1] /= ad[nm1]; for (i = n - 2; i >= 0; i--) b[i] = (b[i] - au[i] * b[i + 1]) / ad[i]; } #include <Python.h> #include <numpy/arrayobject.h> #include <numpy/arrayscalars.h> #include <stdlib.h> static PyObject *trid_trilu(PyObject *self, PyObject *args) { int n; PyArrayObject *al, *ad, *au; if (!PyArg_ParseTuple(args, "iOOO", &n, &al, &ad, &au)) return NULL; if (al->nd != 1 || al->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg2 types does not much"); return NULL; } if (ad->nd != 1 || ad->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg3 types does not much"); return NULL; } if (au->nd != 1 || au->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg4 types does not much"); return NULL; } trilu(n, (double*)al->data, (double*)ad->data, (double*)au->data); return Py_BuildValue(""); // return Py_RETURN_NONE; もOK? } static PyObject *trid_trisol(PyObject *self, PyObject *args) { int n; PyArrayObject *al, *ad, *au, *b; if (!PyArg_ParseTuple(args, "iOOOO", &n, &al, &ad, &au, &b)) return NULL; if (al->nd != 1 || al->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg2 types does not much"); return NULL; } if (ad->nd != 1 || ad->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg3 types does not much"); return NULL; } if (au->nd != 1 || au->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg4 types does not much"); return NULL; } if (b->nd != 1 || b->descr->type_num != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "arg5 types does not much"); return NULL; } trisol(n, (double*)al->data, (double*)ad->data, (double*)au->data, (double*)b->data); return Py_BuildValue(""); } static PyMethodDef tridMethods[] = { {"trilu", trid_trilu, METH_VARARGS, "LU factorize a tridiagonal matrix"}, {"trisol", trid_trisol, METH_VARARGS, "solve linear equation"}, {NULL,NULL,0,NULL} /* Sentinel */ }; static struct PyModuleDef tridmodule = { PyModuleDef_HEAD_INIT, "trid", /* name of module */ NULL, /* module documentation, may be NULL --- "trid_doc" みたいの */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ tridMethods }; // この辺は Python 2 とは全然違う PyMODINIT_FUNC PyInit_trid(void) { return PyModule_Create(&tridmodule); }