2019-07-24 17:19:41 +00:00
|
|
|
#define interpol_splines_linear_c
|
|
|
|
#include "linear_splines.h"
|
|
|
|
#include "../../internal_deque.h"
|
|
|
|
|
|
|
|
double linear_spline_eval_double(
|
|
|
|
double x
|
2019-12-05 07:38:14 +00:00
|
|
|
, interpol_splines_linear_Interpolator * self)
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
|
|
|
unsigned long int i = 0;
|
2019-12-05 07:38:14 +00:00
|
|
|
double * X = PyArray_DATA(self->x);
|
|
|
|
double * Y = PyArray_DATA(self->y);
|
2019-07-24 17:19:41 +00:00
|
|
|
|
|
|
|
// Outside the known data.
|
|
|
|
if(x < X[0])
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2019-12-05 07:38:14 +00:00
|
|
|
if(x > X[self->grid_points - 1])
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while(i < self->grid_points - 1)
|
|
|
|
{
|
|
|
|
if((X[i] <= x) && (x <= X[i + 1]))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
2019-07-24 17:19:41 +00:00
|
|
|
|
|
|
|
return Y[i - 1] + (x - X[i - 1]) / (X[i] - X[i - 1]) * (Y[i] - Y[i - 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_new
|
2019-07-24 17:19:41 +00:00
|
|
|
( PyTypeObject * type
|
|
|
|
, PyObject * args
|
|
|
|
, PyObject * kwds)
|
|
|
|
{
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator * self = (interpol_splines_linear_Interpolator *) type->tp_alloc(type, 0);
|
2019-07-24 17:19:41 +00:00
|
|
|
return (PyObject *) self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_init
|
|
|
|
( interpol_splines_linear_Interpolator * self
|
2019-07-24 17:19:41 +00:00
|
|
|
, PyObject * args)
|
|
|
|
{
|
|
|
|
if(!PyArg_ParseTuple(args, "O!O!"
|
|
|
|
, &PyArray_Type, &(self->x)
|
|
|
|
, &PyArray_Type, &(self->y)))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for proper data types & dimensions first.
|
|
|
|
if(self->x->nd != 1)
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_ValueError, "x has to have 1 dimension");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if(self->y->nd != 1)
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_ValueError, "y has to have 1 dimension");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(PyArray_TYPE(self->x) != PyArray_TYPE(self->y))
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_TypeError, "x and y have to have the same data type");
|
|
|
|
return -1;
|
|
|
|
}
|
2019-12-05 07:38:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
if(PyArray_TYPE(self->x) == NPY_DOUBLE)
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
|
|
|
self->eval = linear_spline_eval_double;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-12-05 07:38:14 +00:00
|
|
|
PyErr_SetString(PyExc_TypeError, "x and y have to be double");
|
2019-07-24 17:19:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(self->x->dimensions[0] != self->y->dimensions[0])
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_ValueError, "x and y must have the same length");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if((PyArray_FLAGS(self->x) & NPY_CARRAY_RO) != NPY_CARRAY_RO)
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_ValueError, "x must be a readable C Array");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if((PyArray_FLAGS(self->y) & NPY_CARRAY_RO) != NPY_CARRAY_RO)
|
|
|
|
{
|
|
|
|
PyErr_SetString(PyExc_ValueError, "y must be a readable C Array");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
self->grid_points = self->x->dimensions[0];
|
|
|
|
Py_INCREF(self->x);
|
|
|
|
Py_INCREF(self->y);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_eval_pyfloat
|
|
|
|
( interpol_splines_linear_Interpolator * self
|
2019-07-24 17:19:41 +00:00
|
|
|
, PyObject * args
|
|
|
|
)
|
|
|
|
{
|
|
|
|
double x;
|
|
|
|
double result;
|
|
|
|
if(!PyArg_ParseTuple(args, "d", &x))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
result = (double) (self->eval)(x, self);
|
|
|
|
return Py_BuildValue("d", result);
|
|
|
|
}
|
2019-12-05 07:38:14 +00:00
|
|
|
PyDoc_STRVAR(interpol_splines_linear_Interpolator_eval_pyfloat_doc
|
2019-07-24 17:19:41 +00:00
|
|
|
, "evaluate the spline at the given point");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_equals_pyfloat_search_double
|
|
|
|
( interpol_splines_linear_Interpolator * self
|
2019-07-24 17:19:41 +00:00
|
|
|
, i_deque_t ** deque
|
|
|
|
, double y)
|
|
|
|
{
|
|
|
|
double * x_data = (double *) PyArray_DATA(self->x),
|
|
|
|
* y_data = (double *) PyArray_DATA(self->y);
|
|
|
|
PyObject * this_result;
|
|
|
|
|
|
|
|
long unsigned int i;
|
|
|
|
for(i = 1; i < self->grid_points; i++)
|
|
|
|
{
|
2019-12-05 07:38:14 +00:00
|
|
|
if(((y_data[i - 1]) <= y && (y <= y_data[i]))
|
|
|
|
|| ((y_data[i - 1] >= y) && (y >= y_data[i])))
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
|
|
|
// just avoid zero division
|
|
|
|
if(y_data[i - 1] == y_data[i])
|
|
|
|
{
|
|
|
|
this_result = PyFloat_FromDouble(x_data[i - 1]);
|
|
|
|
if(!this_result)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*deque = i_deque_t_insert(*deque, this_result);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
this_result = PyFloat_FromDouble(
|
|
|
|
(y - y_data[i - 1]) / (y_data[i] - y_data[i - 1]) * (x_data[i] - x_data[i - 1]) + x_data[i - 1]);
|
|
|
|
if(!this_result)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*deque = i_deque_t_insert(*deque, this_result);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static PyObject *
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_equals_pyfloat
|
|
|
|
( interpol_splines_linear_Interpolator * self
|
2019-07-24 17:19:41 +00:00
|
|
|
, PyObject * args)
|
|
|
|
{
|
|
|
|
double y;
|
|
|
|
if(!PyArg_ParseTuple(args, "d", &y))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
i_deque_t * deque = i_deque_t_start();
|
|
|
|
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_equals_pyfloat_search_double(self, &deque, y);
|
2019-07-24 17:19:41 +00:00
|
|
|
return i_deque_t_to_List(deque);
|
|
|
|
}
|
2019-12-05 07:38:14 +00:00
|
|
|
PyDoc_STRVAR(interpol_splines_linear_Interpolator_equals_pyfloat_doc
|
2019-07-24 17:19:41 +00:00
|
|
|
, "return a deque to all the points where s(x) = y");
|
|
|
|
|
2019-12-05 07:38:14 +00:00
|
|
|
static PyMethodDef interpol_splines_linear_Interpolator_Methods[] =
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
2019-12-05 07:38:14 +00:00
|
|
|
{"eval_float", (PyCFunction) interpol_splines_linear_Interpolator_eval_pyfloat, METH_VARARGS, interpol_splines_linear_Interpolator_eval_pyfloat_doc}
|
|
|
|
, {"equals_float", (PyCFunction) interpol_splines_linear_Interpolator_equals_pyfloat, METH_VARARGS, interpol_splines_linear_Interpolator_equals_pyfloat_doc}
|
2019-07-24 17:19:41 +00:00
|
|
|
, {NULL, NULL, 0, NULL}
|
|
|
|
};
|
|
|
|
|
2019-12-05 07:38:14 +00:00
|
|
|
static PyTypeObject interpol_splines_linear_InterpolatorType =
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
|
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
|
|
"interpol.splines.linear.do.Interpolator",
|
2019-12-05 07:38:14 +00:00
|
|
|
sizeof(interpol_splines_linear_Interpolator),
|
2019-07-24 17:19:41 +00:00
|
|
|
0, /* tp_itemsize */
|
|
|
|
0, /* tp_dealloc */
|
|
|
|
0, /* tp_print */
|
|
|
|
0, /* tp_getattr */
|
|
|
|
0, /* tp_setattr */
|
|
|
|
0, /* tp_reserved */
|
|
|
|
0, /* tp_repr */
|
|
|
|
0, /* tp_as_number */
|
|
|
|
0, /* tp_as_sequence */
|
|
|
|
0, /* tp_as_mapping */
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
0, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT ,/* tp_flags */
|
|
|
|
"The backend for linear splines.",
|
|
|
|
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_Methods, // methods
|
2019-07-24 17:19:41 +00:00
|
|
|
0, // members
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2019-12-05 07:38:14 +00:00
|
|
|
(initproc) interpol_splines_linear_Interpolator_init,
|
2019-07-24 17:19:41 +00:00
|
|
|
0,
|
2019-12-05 07:38:14 +00:00
|
|
|
interpol_splines_linear_Interpolator_new,
|
2019-07-24 17:19:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static PyModuleDef interpol_splines_linear_do_module =
|
|
|
|
{
|
|
|
|
PyModuleDef_HEAD_INIT,
|
|
|
|
"interpol.splines.linear.do",
|
|
|
|
"module containing the backend to linear splines",
|
|
|
|
-1,
|
|
|
|
NULL,NULL,NULL,NULL,NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
PyMODINIT_FUNC PyInit_do(void)
|
|
|
|
{
|
|
|
|
PyObject * module;
|
2019-12-05 07:38:14 +00:00
|
|
|
if(PyType_Ready(&interpol_splines_linear_InterpolatorType) < 0)
|
2019-07-24 17:19:41 +00:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
module = PyModule_Create(&interpol_splines_linear_do_module);
|
|
|
|
if(!module)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-12-05 07:38:14 +00:00
|
|
|
Py_INCREF(&interpol_splines_linear_InterpolatorType);
|
|
|
|
PyModule_AddObject(module, "Interpolator", (PyObject *) &interpol_splines_linear_InterpolatorType);
|
2019-07-24 17:19:41 +00:00
|
|
|
|
|
|
|
import_array();
|
|
|
|
return module;
|
|
|
|
}
|