#if (PYGSL_GSL_MAJOR_VERSION == 1) && (PYGSL_GSL_MINOR_VERSION < 5) #define _PYGSL_HAS_DERIV 0 #else #define _PYGSL_HAS_DERIV 1 #endif #ifdef _PYGSL_HAS_DERIV #include #endif #ifdef PyGSL_DERIV_MODULE #ifndef _PYGSL_HAS_DERIV #error "The deriv module was only introduced by GSL 1.5. You seem to compile against an older verion!" #endif #endif /* PyGSL_DERIV_MODULE */ #include #include #include #include #include #include #include /* * callback functions * - python function passed by user * - actual C callback * - GSL wrapper struct */ /* Used for traceback */ static PyObject *module = NULL; typedef struct{ PyObject * callback; PyObject * args; jmp_buf buffer; }pygsl_diff_args; static double diff_callback(double x, void *p) { double value; int flag; pygsl_diff_args *pargs = NULL; pargs = (pygsl_diff_args *) p; assert(pargs->callback); assert(pargs->args); flag = PyGSL_function_wrap_helper(x, &value, NULL, pargs->callback, pargs->args, (char *)__FUNCTION__); if(GSL_SUCCESS != flag){ longjmp(pargs->buffer, flag); return gsl_nan(); } return value; } /* wrapper function */ typedef int pygsl_deriv_func(const gsl_function *, double, double, double *, double *); typedef int pygsl_diff_func(const gsl_function *, double, double *, double *); static PyObject * PyGSL_diff_generic(PyObject *self, PyObject *args, #ifndef PyGSL_DIFF_MODULE pygsl_deriv_func func #else pygsl_diff_func func #endif ) { PyObject *result=NULL, *myargs=NULL; PyObject *cb=NULL; pygsl_diff_args pargs = {NULL, NULL}; /* Changed to compile using Sun's Compiler */ gsl_function diff_gsl_callback = {NULL, NULL}; double x, value, abserr; int flag; #ifndef PyGSL_DIFF_MODULE double h; if(! PyArg_ParseTuple(args, "Odd|O", &cb, &x, &h, &myargs)){ return NULL; } #else if(! PyArg_ParseTuple(args, "Od|O", &cb, &x, &myargs)){ return NULL; } #endif /* Changed to compile using Sun's Compiler */ diff_gsl_callback.function = diff_callback; diff_gsl_callback.params = (void *) &pargs; if(! PyCallable_Check(cb)) { PyErr_SetString(PyExc_TypeError, "The first parameter must be callable"); return NULL; } Py_INCREF(cb); /* Add a reference to new callback */ pargs.callback = cb; /* Remember new callback */ /* Did I get arguments? If so handle them */ if(NULL == myargs){ Py_INCREF(Py_None); pargs.args= Py_None; }else{ Py_INCREF(myargs); pargs.args= myargs; } if((flag=setjmp(pargs.buffer)) == 0){ /* Jmp buffer set, call the function */ #ifndef PyGSL_DIFF_MODULE flag = func(&diff_gsl_callback, x, h, &value, &abserr); #else flag = func(&diff_gsl_callback, x, &value, &abserr); #endif }else{ DEBUG_MESS(2, "CALLBACK called longjmp!", 0); } /* Arguments no longer used */ Py_DECREF(pargs.args); /* Dispose of callback */ Py_DECREF(pargs.callback); if(flag != GSL_SUCCESS){ PyGSL_ERROR_FLAG(flag); return NULL; } result = Py_BuildValue("(dd)", value, abserr); return result; }