File: py_algorithms.hh

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (129 lines) | stat: -rw-r--r-- 4,693 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once

#include <pybind11/pybind11.h>
#include "py_ex.hh"
#include "py_helpers.hh"
#include "py_kernel.hh"
#include "py_progress.hh"

namespace cadabra {
	
	/// \ingroup pythoncore
	///
	/// Generic internal entry point for the Python side to execute a
	/// C++ algorithm. This gets called by the various apply_algo
	/// functions below, which in turn get called by the def_algo
	/// functions.
	template <class Algo>
	Ex_ptr apply_algo_base(Algo& algo, Ex_ptr ex, bool deep, bool repeat, unsigned int depth, bool pre_order=false)
		{
		Ex::iterator it = ex->begin();
		if (ex->is_valid(it)) {
			ProgressMonitor* pm = get_progress_monitor();
			algo.set_progress_monitor(pm);
			if(pre_order)
				ex->update_state(algo.apply_pre_order(repeat));
			else
				ex->update_state(algo.apply_generic(it, deep, repeat, depth));
			call_post_process(*get_kernel_from_scope(), ex);
			}

		return ex;
		}

	template <class Algo>
	Ex_ptr apply_algo(Ex_ptr ex, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex);
		return apply_algo_base(algo, ex, deep, repeat, depth, false);
		}

	template <class Algo, typename Arg1>
	Ex_ptr apply_algo(Ex_ptr ex, Arg1 arg1, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex, arg1);
		return apply_algo_base(algo, ex, deep, repeat, depth, false);
		}

	template <class Algo, typename Arg1, typename Arg2>
	Ex_ptr apply_algo(Ex_ptr ex, Arg1 arg1, Arg2 arg2, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex, arg1, arg2);
		return apply_algo_base(algo, ex, deep, repeat, depth, false);
		}

	template <class Algo, typename Arg1, typename Arg2, typename Arg3>
	Ex_ptr apply_algo(Ex_ptr ex, Arg1 arg1, Arg2 arg2, Arg3 arg3, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex, arg1, arg2, arg3);
		return apply_algo_base(algo, ex, deep, repeat, depth, false);
		}


	/// \ingroup pythoncore
	///
	/// Method to declare a Python function with variable number of
	/// arguments, and make that call a C++ algorithm as specified in
	/// the Algo template parameter.  This will make the algorithm
	/// traverse post-order, that is to say, first on the innermost
	/// child (or leaf) of an expression tree, and then, if that fails,
	/// on parent nodes, and so on.
	template<class Algo, typename... Args, typename... PyArgs>
	void def_algo(pybind11::module& m, const char* name, bool deep, bool repeat, unsigned int depth, PyArgs... pyargs)
		{
		m.def(name,
		      &apply_algo<Algo, Args...>,
		      pybind11::arg("ex"),
		      std::forward<PyArgs>(pyargs)...,
		      pybind11::arg("deep") = deep,
		      pybind11::arg("repeat") = repeat,
		      pybind11::arg("depth") = depth,
		      pybind11::doc(read_manual("algorithms", name).c_str()),
		      pybind11::return_value_policy::reference_internal);
		}

	template <class Algo>
	Ex_ptr apply_algo_preorder(Ex_ptr ex, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex);
		return apply_algo_base(algo, ex, deep, repeat, depth, true);
		}

	template <class Algo, typename Arg1>
	Ex_ptr apply_algo_preorder(Ex_ptr ex, Arg1 arg1, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex, arg1);
		return apply_algo_base(algo, ex, deep, repeat, depth, true);
		}

	template <class Algo, typename Arg1, typename Arg2>
	Ex_ptr apply_algo_preorder(Ex_ptr ex, Arg1 arg1, Arg2 arg2, bool deep, bool repeat, unsigned int depth)
		{
		Algo algo(*get_kernel_from_scope(), *ex, arg1, arg2);
		return apply_algo_base(algo, ex, deep, repeat, depth, true);
		}

	/// \ingroup pythoncore
	///
	/// Method to declare a Python function with variable number of arguments, and
	/// make that call a C++ algorithm as specified in the Algo template parameter.
	/// In contrast to def_algo, this one will apply the algorithm in pre-order
	/// traversal style, that is, it will first attempt to apply on a node itself
	/// before traversing further down the child nodes and attempting there.
	template<class Algo, typename... Args, typename... PyArgs>
	void def_algo_preorder(pybind11::module& m, const char* name, bool deep, bool repeat, unsigned int depth, PyArgs... pyargs)
		{
		m.def(name,
		      &apply_algo_preorder<Algo, Args...>,
		      pybind11::arg("ex"),
		      std::forward<PyArgs>(pyargs)...,
		      pybind11::arg("deep") = deep,
		      pybind11::arg("repeat") = repeat,
		      pybind11::arg("depth") = depth,
		      pybind11::doc(read_manual("algorithms", name).c_str()),
		      pybind11::return_value_policy::reference_internal);
		}


	void init_algorithms(pybind11::module& m);
	}