00001
00002
00003
00004 #include "PyROOT.h"
00005 #include "TPyFitFunction.h"
00006 #include "ObjectProxy.h"
00007 #include "MethodProxy.h"
00008 #include "PyBufferFactory.h"
00009
00010
00011 #include <stdexcept>
00012
00013
00014
00015
00016
00017
00018
00019
00020 ClassImp(TPyMultiGenFunction)
00021 ClassImp(TPyMultiGradFunction)
00022
00023
00024
00025 static PyObject* GetOverriddenPyMethod( PyObject* pyself, const char* method )
00026 {
00027
00028 PyObject* pymethod = 0;
00029
00030 if ( pyself && pyself != Py_None ) {
00031 pymethod = PyObject_GetAttrString( (PyObject*)pyself, const_cast< char* >( method ) );
00032 if ( ! PyROOT::MethodProxy_CheckExact( pymethod ) )
00033 return pymethod;
00034
00035 Py_XDECREF( pymethod );
00036 pymethod = 0;
00037 }
00038
00039 return pymethod;
00040 }
00041
00042 static PyObject* DispatchCall( PyObject* pyself, const char* method, PyObject* pymethod = NULL,
00043 PyObject* arg1 = NULL, PyObject* arg2 = NULL, PyObject* arg3 = NULL )
00044 {
00045
00046 PyObject* result = 0;
00047
00048
00049
00050 if ( ! pymethod )
00051 pymethod = GetOverriddenPyMethod( pyself, method );
00052
00053 if ( pymethod ) {
00054 result = PyObject_CallFunctionObjArgs( pymethod, arg1, arg2, arg3, NULL );
00055 } else {
00056
00057 result = 0;
00058 PyErr_Format( PyExc_AttributeError,
00059 "method %s needs implementing in derived class", const_cast< char* >( method ) );
00060 }
00061
00062 Py_XDECREF( pymethod );
00063
00064 return result;
00065 }
00066
00067
00068
00069 TPyMultiGenFunction::TPyMultiGenFunction( PyObject* self ) : fPySelf( 0 )
00070 {
00071
00072 if ( self ) {
00073
00074 fPySelf = self;
00075 } else {
00076 Py_INCREF( Py_None );
00077 fPySelf = Py_None;
00078 }
00079 }
00080
00081
00082 TPyMultiGenFunction::~TPyMultiGenFunction()
00083 {
00084
00085 if ( fPySelf == Py_None ) {
00086 Py_DECREF( fPySelf );
00087 }
00088 }
00089
00090
00091
00092 unsigned int TPyMultiGenFunction::NDim() const
00093 {
00094
00095 PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
00096
00097 if ( ! pyresult ) {
00098 PyErr_Print();
00099 throw std::runtime_error( "Failure in TPyMultiGenFunction::NDim" );
00100 }
00101
00102 unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
00103 Py_XDECREF( pyresult );
00104
00105 return cppresult;
00106 }
00107
00108
00109 double TPyMultiGenFunction::DoEval( const double* x ) const
00110 {
00111
00112 PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00113 PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
00114 Py_DECREF( xbuf );
00115
00116 if ( ! pyresult ) {
00117 PyErr_Print();
00118 throw std::runtime_error( "Failure in TPyMultiGenFunction::DoEval" );
00119 }
00120
00121 double cppresult = (double)PyFloat_AsDouble( pyresult );
00122 Py_XDECREF( pyresult );
00123
00124 return cppresult;
00125 }
00126
00127
00128
00129
00130 TPyMultiGradFunction::TPyMultiGradFunction( PyObject* self )
00131 {
00132
00133 if ( self ) {
00134
00135 fPySelf = self;
00136 } else {
00137 Py_INCREF( Py_None );
00138 fPySelf = Py_None;
00139 }
00140 }
00141
00142
00143 TPyMultiGradFunction::~TPyMultiGradFunction()
00144 {
00145
00146 if ( fPySelf == Py_None ) {
00147 Py_DECREF( fPySelf );
00148 }
00149 }
00150
00151
00152
00153 unsigned int TPyMultiGradFunction::NDim() const
00154 {
00155
00156 PyObject* pyresult = DispatchCall( fPySelf, "NDim" );
00157
00158 if ( ! pyresult ) {
00159 PyErr_Print();
00160 throw std::runtime_error( "Failure in TPyMultiGradFunction::NDim" );
00161 }
00162
00163 unsigned int cppresult = (unsigned int)PyLong_AsLong( pyresult );
00164 Py_XDECREF( pyresult );
00165
00166 return cppresult;
00167 }
00168
00169
00170 double TPyMultiGradFunction::DoEval( const double* x ) const
00171 {
00172
00173 PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00174 PyObject* pyresult = DispatchCall( fPySelf, "DoEval", NULL, xbuf );
00175 Py_DECREF( xbuf );
00176
00177 if ( ! pyresult ) {
00178 PyErr_Print();
00179 throw std::runtime_error( "Failure in TPyMultiGradFunction::DoEval" );
00180 }
00181
00182 double cppresult = (double)PyFloat_AsDouble( pyresult );
00183 Py_XDECREF( pyresult );
00184
00185 return cppresult;
00186 }
00187
00188
00189 void TPyMultiGradFunction::Gradient( const double* x, double* grad ) const {
00190
00191 PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "Gradient" );
00192
00193 if ( pymethod ) {
00194 PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00195 PyObject* gbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)grad );
00196 PyObject* pyresult = DispatchCall( fPySelf, "Gradient", pymethod, xbuf, gbuf );
00197 Py_DECREF( gbuf );
00198 Py_DECREF( xbuf );
00199
00200 if ( ! pyresult ) {
00201 PyErr_Print();
00202 throw std::runtime_error( "Failure in TPyMultiGradFunction::Gradient" );
00203 }
00204
00205 Py_DECREF( pyresult );
00206
00207 } else
00208 return ROOT::Math::IMultiGradFunction::Gradient( x, grad );
00209 }
00210
00211
00212 void TPyMultiGradFunction::FdF( const double* x, double& f, double* df ) const
00213 {
00214
00215 PyObject* pymethod = GetOverriddenPyMethod( fPySelf, "FdF" );
00216
00217 if ( pymethod ) {
00218 PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00219 PyObject* pyf = PyList_New( 1 );
00220 PyList_SetItem( pyf, 0, PyFloat_FromDouble( f ) );
00221 PyObject* dfbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)df );
00222
00223 PyObject* pyresult = DispatchCall( fPySelf, "FdF", pymethod, xbuf, pyf, dfbuf );
00224 f = PyFloat_AsDouble( PyList_GetItem( pyf, 0 ) );
00225
00226 Py_DECREF( dfbuf );
00227 Py_DECREF( pyf );
00228 Py_DECREF( xbuf );
00229
00230 if ( ! pyresult ) {
00231 PyErr_Print();
00232 throw std::runtime_error( "Failure in TPyMultiGradFunction::FdF" );
00233 }
00234
00235 Py_DECREF( pyresult );
00236
00237 } else
00238 return ROOT::Math::IMultiGradFunction::FdF( x, f, df );
00239 }
00240
00241
00242 double TPyMultiGradFunction::DoDerivative( const double * x, unsigned int icoord ) const
00243 {
00244
00245 PyObject* xbuf = PyROOT::TPyBufferFactory::Instance()->PyBuffer_FromMemory( (Double_t*)x );
00246 PyObject* pycoord = PyLong_FromLong( icoord );
00247
00248 PyObject* pyresult = DispatchCall( fPySelf, "DoDerivative", NULL, xbuf, pycoord );
00249 Py_DECREF( pycoord );
00250 Py_DECREF( xbuf );
00251
00252 if ( ! pyresult ) {
00253 PyErr_Print();
00254 throw std::runtime_error( "Failure in TPyMultiGradFunction::DoDerivative" );
00255 }
00256
00257 double cppresult = (double)PyFloat_AsDouble( pyresult );
00258 Py_XDECREF( pyresult );
00259
00260 return cppresult;
00261 }
00262