git-svn-id: svn://scm.gforge.inria.fr/svnroot/paradiseo@40 331e1502-861f-0410-8da2-ba01fb791d7f
356 lines
19 KiB
HTML
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 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 Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="namespacemembers.html">Namespace Members</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="pages.html">Related Pages</a> | <span class="search"><u>S</u>earch for <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> / <a class="el" href="dir_000008.html">mathsym</a> / <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 <vector.h></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<double>::const_iterator data_ptr;
|
|
00012 <span class="keyword">typedef</span> vector<data_ptr> 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<Function> 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<func_type, unsigned> entry;
|
|
00058
|
|
00059 <span class="preprocessor">#if USE_TR1</span>
|
|
00060 <span class="preprocessor"></span> <span class="keyword">typedef</span> std::tr1::unordered_map<Sym, entry, HashSym> HashMap;
|
|
00061 <span class="preprocessor">#else</span>
|
|
00062 <span class="preprocessor"></span> <span class="keyword">typedef</span> hash_map<Sym, entry, HashSym> HashMap;
|
|
00063 <span class="preprocessor">#endif </span>
|
|
00064 <span class="preprocessor"></span>
|
|
00065 HashMap map;
|
|
00066
|
|
00067 vector<double> constants;
|
|
00068 vector<unsigned> variables;
|
|
00069 vector< fptr > functions;
|
|
00070 vector< vector<entry> > function_args;
|
|
00071
|
|
00072 <span class="keywordtype">unsigned</span> total_args;
|
|
00073
|
|
00074 vector<entry> 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<entry> vec;
|
|
00102 <span class="keyword">const</span> SymVec& 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 << "Adding + " << vec[0].second << ' ' << vec[1].second << 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 << "Adding * " << vec[0].second << ' ' << vec[1].second << 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 << <span class="stringliteral">"Unknown function "</span> << sym << <span class="stringliteral">" encountered"</span> << 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 << <span class="stringliteral">"Unimplemented token encountered "</span> << sym << endl;
|
|
00168 exit(1);
|
|
00169 }
|
|
00170 }
|
|
00171
|
|
00172 <span class="comment">//cout << "Adding " << print_function(f) << ' ' << vec[0].second << 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->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<unsigned> 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<double> data;
|
|
00210 vector<Function> funcs;
|
|
00211 data_ptrs args;
|
|
00212
|
|
00213 vector<unsigned> 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 < constant_offset + input_idx.size(); ++i) {
|
|
00230 data[i] = x[input_idx[i-constant_offset]];
|
|
00231 }
|
|
00232
|
|
00233 <span class="keywordflow">for</span>(; i < data.size(); ++i) {
|
|
00234 data[i] = funcs[i-var_offset]();
|
|
00235 <span class="comment">//cout << i << " " << data[i] << endl;</span>
|
|
00236 }
|
|
00237
|
|
00238 <span class="keywordflow">for</span> (i = 0; i < 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<double>& x, vector<double>& y) {
|
|
00244 eval(&x[0], &y[0]);
|
|
00245 }
|
|
00246
|
|
00247 <span class="keywordtype">void</span> setup(<span class="keyword">const</span> vector<Sym>& pop) {
|
|
00248
|
|
00249 clear();
|
|
00250 Compiler compiler;
|
|
00251
|
|
00252 <span class="keywordflow">for</span> (<span class="keywordtype">unsigned</span> i = 0; i < 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 < constant_offset; ++i) {
|
|
00268 data[i] = compiler.constants[i];
|
|
00269 <span class="comment">//cout << i << ' ' << data[i] << 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 < var_offset; ++i) {</span>
|
|
00276 <span class="comment">//cout << i << " x" << input_idx[i-constant_offset] << 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 < funcs.size(); ++i) {
|
|
00282
|
|
00283 Function f;
|
|
00284 f.function = compiler.functions[i];
|
|
00285
|
|
00286 <span class="comment">//cout << i+var_offset << ' ' << 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 < 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 << ' ' << idx << "(" << e.second << ")";</span>
|
|
00303 }
|
|
00304
|
|
00305 <span class="comment">//cout << 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 < 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 << "out " << output_idx[i] << endl;</span>
|
|
00322 }
|
|
00323 }
|
|
00324
|
|
00325 };
|
|
00326
|
|
00327
|
|
00328
|
|
00329 MultiFunction::MultiFunction(<span class="keyword">const</span> std::vector<Sym>& pop) : pimpl(new MultiFunctionImpl) {
|
|
00330 pimpl->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<double>& x, std::vector<double>& y) {
|
|
00336 pimpl->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->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
|
|
<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>
|