paradiseo/trunk/paradiseo-eo/doc/html/_multi_function_8cpp-source.html
legrand c3aec878e5 Paradiseo-eo sources added
git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@40 331e1502-861f-0410-8da2-ba01fb791d7f
2006-12-12 14:49:08 +00:00

356 lines
19 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>EO: MultiFunction.cpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.9.1 -->
<div class="qindex"> <form class="search" action="search.php" method="get">
<a class="qindex" href="main.html">Main&nbsp;Page</a> | <a class="qindex" href="modules.html">Modules</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Class&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="namespacemembers.html">Namespace&nbsp;Members</a> | <a class="qindex" href="functions.html">Class&nbsp;Members</a> | <a class="qindex" href="pages.html">Related&nbsp;Pages</a> | <span class="search"><u>S</u>earch&nbsp;for&nbsp;<input class="search" type="text" name="query" value="" size="20" accesskey="s"/></span></form></div>
<div class="nav">
<a class="el" href="dir_000007.html">contrib</a>&nbsp;/&nbsp;<a class="el" href="dir_000008.html">mathsym</a>&nbsp;/&nbsp;<a class="el" href="dir_000009.html">eval</a></div>
<h1>MultiFunction.cpp</h1><div class="fragment"><pre class="fragment">00001 <span class="preprocessor">#include &lt;vector.h&gt;</span>
00002
00003
00004 <span class="preprocessor">#include "MultiFunction.h"</span>
00005 <span class="preprocessor">#include "Sym.h"</span>
00006 <span class="preprocessor">#include "FunDef.h"</span>
00007
00008 <span class="keyword">using</span> <span class="keyword">namespace </span>std;
00009
00010
00011 <span class="keyword">typedef</span> vector&lt;double&gt;::const_iterator data_ptr;
00012 <span class="keyword">typedef</span> vector&lt;data_ptr&gt; data_ptrs;
00013 <span class="keyword">typedef</span> data_ptrs::const_iterator arg_ptr;
00014
00015 <span class="preprocessor">#include "MultiFuncs.cpp"</span>
00016
00017 <span class="keyword">typedef</span> double (*fptr)( arg_ptr );
00018
00019 string print_function( fptr f) {
00020 <span class="keywordflow">if</span> (f == multi_function::plus) <span class="keywordflow">return</span> <span class="stringliteral">"+"</span>;
00021 <span class="keywordflow">if</span> (f == multi_function::mult) <span class="keywordflow">return</span> <span class="stringliteral">"*"</span>;
00022 <span class="keywordflow">if</span> (f == multi_function::min) <span class="keywordflow">return</span> <span class="stringliteral">"-"</span>;
00023 <span class="keywordflow">if</span> (f == multi_function::inv) <span class="keywordflow">return</span> <span class="stringliteral">"/"</span>;
00024 <span class="keywordflow">if</span> (f == multi_function::exp) <span class="keywordflow">return</span> <span class="stringliteral">"e"</span>;
00025 <span class="keywordflow">return</span> <span class="stringliteral">"unknown"</span>;
00026 }
00027
00028
00029 <span class="keyword">struct </span>Function {
00030
00031 fptr function;
00032 arg_ptr args;
00033
00034 <span class="keywordtype">double</span> operator()()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> function(args); }
00035 };
00036
00037 <span class="keyword">static</span> vector&lt;Function&gt; token_2_function;
00038
00039 Sym make_binary(Sym sym) {
00040 <span class="keywordflow">if</span> (sym.args().size() == 2) <span class="keywordflow">return</span> sym;
00041 SymVec args = sym.args();
00042 Sym an = args.back();
00043 args.pop_back();
00044 Sym nw = make_binary( Sym( sym.token(), args) );
00045 args.resize(2);
00046 args[0] = nw;
00047 args[1] = an;
00048 <span class="keywordflow">return</span> Sym(sym.token(), args);
00049 }
00050
00051 <span class="keyword">class </span>Compiler {
00052
00053 <span class="keyword">public</span>:
00054
00055 <span class="keyword">enum</span> func_type {constant, variable, function};
00056
00057 <span class="keyword">typedef</span> pair&lt;func_type, unsigned&gt; entry;
00058
00059 <span class="preprocessor">#if USE_TR1</span>
00060 <span class="preprocessor"></span> <span class="keyword">typedef</span> std::tr1::unordered_map&lt;Sym, entry, HashSym&gt; HashMap;
00061 <span class="preprocessor">#else</span>
00062 <span class="preprocessor"></span> <span class="keyword">typedef</span> hash_map&lt;Sym, entry, HashSym&gt; HashMap;
00063 <span class="preprocessor">#endif </span>
00064 <span class="preprocessor"></span>
00065 HashMap map;
00066
00067 vector&lt;double&gt; constants;
00068 vector&lt;unsigned&gt; variables;
00069 vector&lt; fptr &gt; functions;
00070 vector&lt; vector&lt;entry&gt; &gt; function_args;
00071
00072 <span class="keywordtype">unsigned</span> total_args;
00073
00074 vector&lt;entry&gt; outputs;
00075
00076 Compiler() : total_args(0) {}
00077
00078 entry do_add(Sym sym) {
00079
00080 HashMap::iterator it = map.find(sym);
00081
00082 <span class="keywordflow">if</span> (it == map.end()) { <span class="comment">// new entry</span>
00083
00084 token_t token = sym.token();
00085
00086 <span class="keywordflow">if</span> (is_constant(token)) {
00087 constants.push_back( get_constant_value(token) ); <span class="comment">// set value</span>
00088 entry e = make_pair(constant, constants.size()-1);
00089 map.insert( make_pair(sym, e) );
00090 <span class="keywordflow">return</span> e;
00091
00092 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (is_variable(token)) {
00093 <span class="keywordtype">unsigned</span> idx = get_variable_index(token);
00094 variables.push_back(idx);
00095 entry e = make_pair(variable, variables.size()-1);
00096 map.insert( make_pair(sym, e) );
00097 <span class="keywordflow">return</span> e;
00098 } <span class="comment">// else </span>
00099
00100 fptr f;
00101 vector&lt;entry&gt; vec;
00102 <span class="keyword">const</span> SymVec&amp; args = sym.args();
00103
00104 <span class="keywordflow">switch</span> (token) {
00105 <span class="keywordflow">case</span> sum_token:
00106 {
00107 <span class="keywordflow">if</span> (args.size() == 0) {
00108 <span class="keywordflow">return</span> do_add( SymConst(0.0));
00109 }
00110 <span class="keywordflow">if</span> (args.size() == 1) {
00111 <span class="keywordflow">return</span> do_add(args[0]);
00112 }
00113 <span class="keywordflow">if</span> (args.size() == 2) {
00114 vec.push_back(do_add(args[0]));
00115 vec.push_back(do_add(args[1]));
00116 f = multi_function::plus;
00117 <span class="comment">//cout &lt;&lt; "Adding + " &lt;&lt; vec[0].second &lt;&lt; ' ' &lt;&lt; vec[1].second &lt;&lt; endl;</span>
00118 <span class="keywordflow">break</span>;
00119
00120 } <span class="keywordflow">else</span> {
00121 <span class="keywordflow">return</span> do_add( make_binary(sym) );
00122 }
00123
00124 }
00125 <span class="keywordflow">case</span> prod_token:
00126 {
00127 <span class="keywordflow">if</span> (args.size() == 0) {
00128 <span class="keywordflow">return</span> do_add( SymConst(1.0));
00129 }
00130 <span class="keywordflow">if</span> (args.size() == 1) {
00131 <span class="keywordflow">return</span> do_add(args[0]);
00132 }
00133 <span class="keywordflow">if</span> (args.size() == 2) {
00134 vec.push_back(do_add(args[0]));
00135 vec.push_back(do_add(args[1]));
00136 f = multi_function::mult;
00137 <span class="comment">//cout &lt;&lt; "Adding * " &lt;&lt; vec[0].second &lt;&lt; ' ' &lt;&lt; vec[1].second &lt;&lt; endl;</span>
00138 <span class="keywordflow">break</span>;
00139
00140
00141 } <span class="keywordflow">else</span> {
00142 <span class="keywordflow">return</span> do_add( make_binary(sym) );
00143 }
00144 }
00145 <span class="keywordflow">case</span> sqr_token:
00146 {
00147 SymVec newargs(2);
00148 newargs[0] = args[0];
00149 newargs[1] = args[0];
00150 <span class="keywordflow">return</span> do_add( Sym(prod_token, newargs));
00151 }
00152 <span class="keywordflow">default</span> :
00153 {
00154 <span class="keywordflow">if</span> (args.size() != 1) {
00155 cerr &lt;&lt; <span class="stringliteral">"Unknown function "</span> &lt;&lt; sym &lt;&lt; <span class="stringliteral">" encountered"</span> &lt;&lt; endl;
00156 exit(1);
00157 }
00158
00159 vec.push_back(do_add(args[0]));
00160
00161 <span class="keywordflow">switch</span> (token) {
00162 <span class="keywordflow">case</span> min_token: f = multi_function::min; <span class="keywordflow">break</span>;
00163 <span class="keywordflow">case</span> inv_token: f = multi_function::inv; <span class="keywordflow">break</span>;
00164 <span class="keywordflow">case</span> exp_token :f = multi_function::exp; <span class="keywordflow">break</span>;
00165 <span class="keywordflow">default</span> :
00166 {
00167 cerr &lt;&lt; <span class="stringliteral">"Unimplemented token encountered "</span> &lt;&lt; sym &lt;&lt; endl;
00168 exit(1);
00169 }
00170 }
00171
00172 <span class="comment">//cout &lt;&lt; "Adding " &lt;&lt; print_function(f) &lt;&lt; ' ' &lt;&lt; vec[0].second &lt;&lt; endl;</span>
00173
00174
00175 }
00176
00177 }
00178
00179 total_args += vec.size();
00180 function_args.push_back(vec);
00181 functions.push_back(f);
00182
00183 entry e = make_pair(function, functions.size()-1);
00184 map.insert( make_pair(sym, e) );
00185 <span class="keywordflow">return</span> e;
00186
00187 }
00188
00189 <span class="keywordflow">return</span> it-&gt;second; <span class="comment">// entry</span>
00190 }
00191
00192 <span class="keywordtype">void</span> add(Sym sym) {
00193 entry e = do_add(sym);
00194 outputs.push_back(e);
00195 }
00196
00197 };
00198
00199 <span class="keyword">class </span>MultiFunctionImpl {
00200 <span class="keyword">public</span>:
00201
00202 <span class="comment">// input mapping</span>
00203 vector&lt;unsigned&gt; input_idx;
00204
00205 <span class="keywordtype">unsigned</span> constant_offset;
00206 <span class="keywordtype">unsigned</span> var_offset;
00207
00208 <span class="comment">// evaluation</span>
00209 vector&lt;double&gt; data;
00210 vector&lt;Function&gt; funcs;
00211 data_ptrs args;
00212
00213 vector&lt;unsigned&gt; output_idx;
00214
00215 MultiFunctionImpl() {}
00216
00217 <span class="keywordtype">void</span> clear() {
00218 input_idx.clear();
00219 data.clear();
00220 funcs.clear();
00221 args.clear();
00222 output_idx.clear();
00223 constant_offset = 0;
00224 }
00225
00226 <span class="keywordtype">void</span> eval(<span class="keyword">const</span> <span class="keywordtype">double</span>* x, <span class="keywordtype">double</span>* y) {
00227 <span class="keywordtype">unsigned</span> i;
00228 <span class="comment">// evaluate variables</span>
00229 <span class="keywordflow">for</span> (i = constant_offset; i &lt; constant_offset + input_idx.size(); ++i) {
00230 data[i] = x[input_idx[i-constant_offset]];
00231 }
00232
00233 <span class="keywordflow">for</span>(; i &lt; data.size(); ++i) {
00234 data[i] = funcs[i-var_offset]();
00235 <span class="comment">//cout &lt;&lt; i &lt;&lt; " " &lt;&lt; data[i] &lt;&lt; endl;</span>
00236 }
00237
00238 <span class="keywordflow">for</span> (i = 0; i &lt; output_idx.size(); ++i) {
00239 y[i] = data[output_idx[i]];
00240 }
00241 }
00242
00243 <span class="keywordtype">void</span> eval(<span class="keyword">const</span> vector&lt;double&gt;&amp; x, vector&lt;double&gt;&amp; y) {
00244 eval(&amp;x[0], &amp;y[0]);
00245 }
00246
00247 <span class="keywordtype">void</span> setup(<span class="keyword">const</span> vector&lt;Sym&gt;&amp; pop) {
00248
00249 clear();
00250 Compiler compiler;
00251
00252 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i &lt; pop.size(); ++i) {
00253 Sym sym = (expand_all(pop[i]));
00254 compiler.add(sym);
00255 }
00256
00257 <span class="comment">// compiler is setup so get the data</span>
00258 constant_offset = compiler.constants.size();
00259 var_offset = constant_offset + compiler.variables.size();
00260 <span class="keywordtype">int</span> n = var_offset + compiler.functions.size();
00261
00262 data.resize(n);
00263 funcs.resize(compiler.functions.size());
00264 args.resize(compiler.total_args);
00265
00266 <span class="comment">// constants</span>
00267 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i &lt; constant_offset; ++i) {
00268 data[i] = compiler.constants[i];
00269 <span class="comment">//cout &lt;&lt; i &lt;&lt; ' ' &lt;&lt; data[i] &lt;&lt; endl;</span>
00270 }
00271
00272 <span class="comment">// variables</span>
00273 input_idx = compiler.variables;
00274
00275 <span class="comment">//for (unsigned i = constant_offset; i &lt; var_offset; ++i) {</span>
00276 <span class="comment">//cout &lt;&lt; i &lt;&lt; " x" &lt;&lt; input_idx[i-constant_offset] &lt;&lt; endl;</span>
00277 <span class="comment">//}</span>
00278
00279 <span class="comment">// functions</span>
00280 <span class="keywordtype">unsigned</span> which_arg = 0;
00281 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i &lt; funcs.size(); ++i) {
00282
00283 Function f;
00284 f.function = compiler.functions[i];
00285
00286 <span class="comment">//cout &lt;&lt; i+var_offset &lt;&lt; ' ' &lt;&lt; print_function(f.function);</span>
00287
00288 <span class="comment">// interpret args</span>
00289 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> j = 0; j &lt; compiler.function_args[i].size(); ++j) {
00290
00291 Compiler::entry e = compiler.function_args[i][j];
00292
00293 <span class="keywordtype">unsigned</span> idx = e.second;
00294
00295 <span class="keywordflow">switch</span> (e.first) {
00296 <span class="keywordflow">case</span> Compiler::function: idx += compiler.variables.size();
00297 <span class="keywordflow">case</span> Compiler::variable: idx += compiler.constants.size();
00298 <span class="keywordflow">case</span> Compiler::constant: {}
00299 }
00300
00301 args[which_arg + j] = data.begin() + idx;
00302 <span class="comment">//cout &lt;&lt; ' ' &lt;&lt; idx &lt;&lt; "(" &lt;&lt; e.second &lt;&lt; ")";</span>
00303 }
00304
00305 <span class="comment">//cout &lt;&lt; endl;</span>
00306
00307 f.args = args.begin() + which_arg;
00308 which_arg += compiler.function_args[i].size();
00309 funcs[i] = f;
00310 }
00311
00312 <span class="comment">// output indices</span>
00313 output_idx.resize(compiler.outputs.size());
00314 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i &lt; output_idx.size(); ++i) {
00315 output_idx[i] = compiler.outputs[i].second;
00316 <span class="keywordflow">switch</span>(compiler.outputs[i].first) {
00317 <span class="keywordflow">case</span> Compiler::function: output_idx[i] += compiler.variables.size();
00318 <span class="keywordflow">case</span> Compiler::variable: output_idx[i] += compiler.constants.size();
00319 <span class="keywordflow">case</span> Compiler::constant: {}
00320 }
00321 <span class="comment">//cout &lt;&lt; "out " &lt;&lt; output_idx[i] &lt;&lt; endl;</span>
00322 }
00323 }
00324
00325 };
00326
00327
00328
00329 MultiFunction::MultiFunction(<span class="keyword">const</span> std::vector&lt;Sym&gt;&amp; pop) : pimpl(new MultiFunctionImpl) {
00330 pimpl-&gt;setup(pop);
00331 }
00332
00333 MultiFunction::~MultiFunction() { <span class="keyword">delete</span> pimpl; }
00334
00335 <span class="keywordtype">void</span> MultiFunction::operator()(<span class="keyword">const</span> std::vector&lt;double&gt;&amp; x, std::vector&lt;double&gt;&amp; y) {
00336 pimpl-&gt;eval(x,y);
00337 }
00338
00339 <span class="keywordtype">void</span> MultiFunction::operator()(<span class="keyword">const</span> <span class="keywordtype">double</span>* x, <span class="keywordtype">double</span>* y) {
00340 pimpl-&gt;eval(x,y);
00341 }
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Oct 19 05:06:41 2006 for EO by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.3.9.1 </small></address>
</body>
</html>