Volker Braun avatar Volker Braun committed 6dca556

implement function::subs() callback into Python

Comments (0)

Files changed (3)

ginac/function.cpp

 	series_f = series_funcp(s);
 	return *this;
 }
+function_options& function_options::subs_func(PyObject* e)
+{
+	python_func |= subs_python_f;
+	subs_f = subs_funcp(e);
+	return *this;
+}
 
 function_options & function_options::set_return_type(unsigned rt, tinfo_t rtt)
 {
 	throw(std::logic_error("function::series(): invalid nparams"));
 }
 
+
+/** Implementation of ex::subs for functions. */
+ex function::subs(const exmap & m, unsigned options) const
+{
+	GINAC_ASSERT(serial<registered_functions().size());
+	const function_options & opt = registered_functions()[serial];
+
+	if (opt.python_func & function_options::subs_python_f) {
+		// convert seq to a PyTuple of Expressions
+		PyObject* args = py_funcs.subs_args_to_PyTuple(m, options, seq);
+		// call opt.subs_f with this list
+		PyObject* pyresult = PyObject_CallMethod(
+				(PyObject*)opt.subs_f,
+				"_subs_", "O", args);
+		Py_DECREF(args);
+		if (!pyresult) { 
+			throw(std::runtime_error("function::subs(): python method (_subs_) raised exception"));
+		}
+		// convert output Expression to an ex
+		ex result = py_funcs.pyExpression_to_ex(pyresult);
+		Py_DECREF(pyresult);
+		if (PyErr_Occurred()) { 
+			throw(std::runtime_error("function::subs(): python function (pyExpression_to_ex) raised exception"));
+		}
+		return result;
+	} else
+		return exprseq::subs(m, options);
+}
+
 /** Implementation of ex::conjugate for functions. */
 ex function::conjugate() const
 {
 typedef ex (* derivative_funcp)();
 typedef ex (* power_funcp)();
 typedef ex (* series_funcp)();
+typedef ex (* subs_funcp)(PyObject* parent);
 typedef void (* print_funcp)();
 
 // the following lines have been generated for max. 14 parameters
 	function_options & derivative_func(PyObject* e);
 	function_options & power_func(PyObject* e);
 	function_options & series_func(PyObject* e);
+	function_options & subs_func(PyObject* e);
 
 	function_options & set_return_type(unsigned rt, tinfo_t rtt=NULL);
 	function_options & do_not_evalf_params();
 		derivative_python_f	= 0x0020,
 		power_python_f		= 0x0040,
 		series_python_f		= 0x0080,
+		subs_python_f           = 0x0100,
 	};
 
 protected:
 	derivative_funcp derivative_f;
 	power_funcp power_f;
 	series_funcp series_f;
+        subs_funcp subs_f;
 	std::vector<print_funcp> print_dispatch_table;
 
 	bool evalf_params_first;
 	ex evalf(int level=0, PyObject* parent=NULL) const;
 	unsigned calchash() const;
 	ex series(const relational & r, int order, unsigned options = 0) const;
+        ex subs(const exmap & m, unsigned options = 0) const;
 	ex thiscontainer(const exvector & v) const;
 	ex thiscontainer(std::auto_ptr<exvector> vp) const;
 	ex conjugate() const;
     PyObject* (*ex_to_pyExpression)(GiNaC::ex e);
     std::string* (*py_print_function)(unsigned id, PyObject* args);
     std::string* (*py_latex_function)(unsigned id, PyObject* args);
+    PyObject* (*subs_args_to_PyTuple)(const GiNaC::exmap & m, unsigned options, const GiNaC::exvector & seq);
     int (*py_get_ginac_serial)();
     PyObject* (*py_get_sfunction_from_serial)(unsigned id);
     unsigned (*py_get_serial_from_sfunction)(PyObject* f);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.