File:  [CENS] / python / pyGiNaC / wrappers4 / function.cpp
Revision 1.5: download - view: text, annotated - select for diffs - revision graph
Sat Dec 22 14:07:23 2001 UTC (15 years, 11 months ago) by pearu
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/*
  This file is part of the PyGiNaC package.
  http://cens.ioc.ee/projects/pyginac/

  $Revision: 1.5 $
  $Id: function.cpp,v 1.5 2001-12-22 14:07:23 pearu Exp $
 
  Copyright 2001 Pearu Peterson all rights reserved,
  Pearu Peterson <pearu@cens.ioc.ee>
  Permission to use, modify, and distribute this software is given under the
  terms of the LGPL.  See http://www.fsf.org
 
  NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
*/

#ifndef PYGINAC_FUNCTION_CPP
#define PYGINAC_FUNCTION_CPP
/* prototypes */
GiNaC::ex function(unsigned, const GiNaC::exvector &, bool hold);
unsigned build_function(const std::string & name,
			const std::string & texname,
			unsigned nparams,
			PyObject* eval_pyfunc,
			PyObject* evalf_pyfunc,
			PyObject* derivative_pyfunc,
			PyObject* series_pyfunc
			);
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
GiNaC::function & from_python(PyObject* o, py::type<GiNaC::function &>);
const GiNaC::function & from_python(PyObject* o, py::type<const GiNaC::function &>);
BOOST_PYTHON_END_CONVERSION_NAMESPACE
#else
#ifndef PYGINAC_FUNCTION_CPP_1
#define PYGINAC_FUNCTION_CPP_1
/* definitions */
this_module.def(function,"function");
this_module.def(build_function,"build_function");
this_module.def(GiNaC::function::find_function, "function_find");
ex_class.def(&GiNaC::function::get_serial, "function_get_serial");
ex_class.def(&GiNaC::function::get_name, "function_get_name");
#else
/* implementation */
GiNaC::ex function(unsigned ser, const GiNaC::exvector & v, bool hold) {
  if (hold)
    return GiNaC::function(ser,v).hold();
  return GiNaC::function(ser,v);
}
std::map<unsigned, PyObject*> dynfunc_eval_cache;
std::map<unsigned, PyObject*> dynfunc_evalf_cache;
std::map<unsigned, PyObject*> dynfunc_derivative_cache;
std::map<unsigned, PyObject*> dynfunc_series_cache;
#define GET_DYNFUNC(NAME) \
PyObject* get_dynfunc_##NAME(void) { \
  const std::map<unsigned, PyObject*>::const_iterator viter = dynfunc_##NAME##_cache.find(GiNaC::function::current_serial);\
  if (viter==dynfunc_##NAME##_cache.end()) {\
    PyErr_SetString(PyExc_RuntimeError,"get_dynfunc_"#NAME "() failed"); \
    throw py::error_already_set(); \
  } \
  return viter->second; \
}
GET_DYNFUNC(eval);
GET_DYNFUNC(evalf);
GET_DYNFUNC(derivative);
GET_DYNFUNC(series);

GiNaC::ex dynfunc_eval_f(const GiNaC::exvector & seq)
{
  PyObject *func = get_dynfunc_eval();
  if (func==NULL)
    throw py::error_already_set();
  PyObject* args = exvector_to_tuple(seq,seq.size());
  if (args==NULL)
    throw py::error_already_set();
  PyObject* ret = PyObject_CallObject(func, args);
  if (ret==NULL)
    throw py::error_already_set();
  return pyobj_get_ex(ret);
}
GiNaC::ex dynfunc_evalf_f(const GiNaC::exvector & seq)
{
  PyObject *func = get_dynfunc_evalf();
  if (func==NULL)
    throw py::error_already_set();
  PyObject* args = exvector_to_tuple(seq,seq.size());
  if (args==NULL)
    throw py::error_already_set();
  PyObject* ret = PyObject_CallObject(func, args);
  if (ret==NULL)
    throw py::error_already_set();
  return pyobj_get_ex(ret);
}
GiNaC::ex dynfunc_derivative_f(const GiNaC::exvector & seq,unsigned diff_param)
{
  PyObject *func = get_dynfunc_derivative();
  if (func==NULL)
    throw py::error_already_set();
  PyObject* args = exvector_to_tuple(seq,seq.size()+1);
  if (args==NULL)
    throw py::error_already_set();
  if(PyTuple_SetItem(args,seq.size(),Py_BuildValue("i",diff_param)))
    throw py::error_already_set();
  PyObject* ret = PyObject_CallObject(func, args);
  if (ret==NULL)
    throw py::error_already_set();
  return pyobj_get_ex(ret);
}
GiNaC::ex dynfunc_series_f(const GiNaC::exvector & seq,const GiNaC::relational& r,int order,unsigned options)
{
  PyObject *func = get_dynfunc_series();
  if (func==NULL)
    throw py::error_already_set();
  PyObject* args = exvector_to_tuple(seq,seq.size()+3);
  if (args==NULL)
    throw py::error_already_set();
  if(PyTuple_SetItem(args,seq.size(),BOOST_PYTHON_CONVERSION::to_python(GiNaC::ex(r)))
     || PyTuple_SetItem(args,seq.size()+1,Py_BuildValue("i",order))
     || PyTuple_SetItem(args,seq.size()+2,Py_BuildValue("i",options)))
    throw py::error_already_set();
  PyObject* ret = PyObject_CallObject(func, args);
  if (ret==NULL)
    throw py::error_already_set();
  return pyobj_get_ex(ret);
}
unsigned build_function(const std::string & name,
			const std::string & texname,
			unsigned nparams,
			PyObject* eval_pyfunc,
			PyObject* evalf_pyfunc,
			PyObject* derivative_pyfunc,
			PyObject* series_pyfunc
			) {
  GiNaC::function_options opts;
  opts = opts.set_name(name,texname).overloaded(-1);
  if (eval_pyfunc!=Py_None) {
    if (PyCallable_Check(eval_pyfunc))
      opts = opts.eval_func(dynfunc_eval_f);
    else {
      PyErr_SetString(PyExc_TypeError,"build_function() eval argument must be callable");
      throw py::error_already_set();
    }
  }
  if (evalf_pyfunc!=Py_None) {
    if (PyCallable_Check(evalf_pyfunc))
      opts = opts.evalf_func(dynfunc_evalf_f);
    else {
      PyErr_SetString(PyExc_TypeError,"build_function() evalf argument must be callable");
      throw py::error_already_set();
    }
  }
  if (derivative_pyfunc!=Py_None) {
    if (PyCallable_Check(derivative_pyfunc))
      opts = opts.derivative_func(dynfunc_derivative_f);
    else {
      PyErr_SetString(PyExc_TypeError,"build_function() derivative argument must be callable");
      throw py::error_already_set();
    }
  }
  if (series_pyfunc!=Py_None) {
    if (PyCallable_Check(series_pyfunc))
      opts = opts.series_func(dynfunc_series_f);
    else {
      PyErr_SetString(PyExc_TypeError,"build_function() series argument must be callable");
      throw py::error_already_set();
    }
  }
  opts.test_and_set_nparams(nparams);
  unsigned serial = GiNaC::function::register_new(opts);
  if (eval_pyfunc!=Py_None) {
    Py_INCREF(eval_pyfunc);
    dynfunc_eval_cache[serial] = eval_pyfunc;
  }
  if (evalf_pyfunc!=Py_None) {
    Py_INCREF(evalf_pyfunc);
    dynfunc_evalf_cache[serial] = evalf_pyfunc;
  }
  if (derivative_pyfunc!=Py_None) {
    Py_INCREF(derivative_pyfunc);
    dynfunc_derivative_cache[serial] = derivative_pyfunc;
  }
  if (series_pyfunc!=Py_None) {
    Py_INCREF(series_pyfunc);
    dynfunc_series_cache[serial] = series_pyfunc;
  }
  return serial;
}
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
GiNaC::function & from_python(PyObject* o, py::type<GiNaC::function &>) {
  if (PYOBJ_IS_EX(o)) {
    GiNaC::ex & e = pyobj_get_ex_nonconst(o);
    if (GiNaC::is_a<GiNaC::function>(e))
      return GiNaC::ex_to_nonconst<GiNaC::function>(e);
  }
  PyErr_SetString(PyExc_TypeError,(std::string("from_python(function) expected function but got ")+PyString_AsString(PyObject_Repr(PyObject_Type(o)))).c_str());
  throw py::error_already_set();
}
const GiNaC::function & from_python(PyObject* o, py::type<const GiNaC::function &>) {
  return from_python(o, py::type<GiNaC::function &>());
}
BOOST_PYTHON_END_CONVERSION_NAMESPACE
#endif
#endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>