#include "PyROOT.h"
#include "TPyFitFunction.h"
#include "ObjectProxy.h"
#include "MethodProxy.h"
#include "PyBufferFactory.h"
#include <stdexcept>
ClassImp(TPyMultiGenFunction)
ClassImp(TPyMultiGradFunction)
static PyObject* GetOverriddenPyMethod( PyObject* pyself, const char* method )
{
PyObject* pymethod = 0;
if ( pyself && pyself != Py_None ) {
pymethod = PyObject_GetAttrString( (PyObject*)pyself, const_cast< char* >( method ) );
if ( ! PyROOT::MethodProxy_CheckExact( pymethod ) )
return pymethod;
Py_XDECREF( pymethod );
pymethod = 0;
}
return pymethod;
}
static PyObject* DispatchCall( PyObject* pyself, const char* method, PyObject* pymethod = NULL,
PyObject* arg1 = NULL, PyObject* arg2 = NULL, PyObject* arg3 = NULL )
{
PyObject* result = 0;
if ( ! pymethod )
pymethod = GetOverriddenPyMethod( pyself, method );
if ( pymethod ) {
result = PyObject_CallFunctionObjArgs( pymethod, arg1, arg2, arg3, NULL );
} else {
result = 0;
PyErr_Format( PyExc_AttributeError,
"method %s needs implementing in derived class", const_cast< char* >( method ) );
}
Py_XDECREF( pymethod );
return result;
}
TPyMultiGenFunction::TPyMultiGenFunction( PyObject* self ) : fPySelf( 0 )
{
if ( self ) {
fPySelf = self;
} else {
Py_INCREF( Py_None );
fPySelf = Py_None;
}
}
TPyMultiGenFunction::~TPyMultiGenFunction()
{
if ( fPySelf == Py_None ) {
Py_DECREF( fPySelf );
}
}
unsigned int TPyMultiGenFunction::NDim() const
{
PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGenFunction::NDim" );
}
unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
Py_XDECREF( pyresult );
return cppresult;
}
double TPyMultiGenFunction::DoEval( const double* x ) const
{
PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
Py_DECREF( xbuf );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGenFunction::DoEval" );
}
double cppresult = (double)PyFloat_AsDouble( pyresult );
Py_XDECREF( pyresult );
return cppresult;
}
TPyMultiGradFunction::TPyMultiGradFunction( PyObject* self )
{
if ( self ) {
fPySelf = self;
} else {
Py_INCREF( Py_None );
fPySelf = Py_None;
}
}
TPyMultiGradFunction::~TPyMultiGradFunction()
{
if ( fPySelf == Py_None ) {
Py_DECREF( fPySelf );
}
}
unsigned int TPyMultiGradFunction::NDim() const
{
PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGradFunction::NDim" );
}
unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
Py_XDECREF( pyresult );
return cppresult;
}
double TPyMultiGradFunction::DoEval( const double* x ) const
{
PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
Py_DECREF( xbuf );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGradFunction::DoEval" );
}
double cppresult = (double)PyFloat_AsDouble( pyresult );
Py_XDECREF( pyresult );
return cppresult;
}
void TPyMultiGradFunction::Gradient( const double* x, double* grad ) const {
PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "Gradient" );
if ( pymethod ) {
PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
PyObject* gbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)grad );
PyObject* pyresult = DispatchCall( fPySelf, "Gradient", pymethod, xbuf, gbuf );
Py_DECREF( gbuf );
Py_DECREF( xbuf );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGradFunction::Gradient" );
}
Py_DECREF( pyresult );
} else
return ROOT::Math::IMultiGradFunction::Gradient( x, grad );
}
void TPyMultiGradFunction::FdF( const double* x, double& f, double* df ) const
{
PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "FdF" );
if ( pymethod ) {
PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
PyObject* pyf = PyList_New( 1 );
PyList_SetItem( pyf, 0, PyFloat_FromDouble( f ) );
PyObject* dfbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)df );
PyObject* pyresult = DispatchCall( fPySelf, "FdF", pymethod, xbuf, pyf, dfbuf );
f = PyFloat_AsDouble( PyList_GetItem( pyf, 0 ) );
Py_DECREF( dfbuf );
Py_DECREF( pyf );
Py_DECREF( xbuf );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGradFunction::FdF" );
}
Py_DECREF( pyresult );
} else
return ROOT::Math::IMultiGradFunction::FdF( x, f, df );
}
double TPyMultiGradFunction::DoDerivative( const double * x, unsigned int icoord ) const
{
PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
PyObject* pycoord = PyLong_FromLong( icoord );
PyObject* pyresult = DispatchCall( fPySelf, "DoDerivative", NULL, xbuf, pycoord );
Py_DECREF( pycoord );
Py_DECREF( xbuf );
if ( ! pyresult ) {
PyErr_Print();
throw std::runtime_error( "Failure in TPyMultiGradFunction::DoDerivative" );
}
double cppresult = (double)PyFloat_AsDouble( pyresult );
Py_XDECREF( pyresult );
return cppresult;
}