move paradiseo/eo to deprecated/ before merge with eodev

This commit is contained in:
Johann Dreo 2012-10-05 15:12:12 +02:00
commit 0c5120f675
717 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <vector>
#include "BoundsCheck.h"
#include <Sym.h>
#include <FunDef.h>
#include <sstream>
using namespace std;
class IntervalBoundsCheckImpl {
public :
vector<Interval> bounds;
};
IntervalBoundsCheck::IntervalBoundsCheck(const vector<double>& mins, const vector<double>& maxes) {
pimpl = new IntervalBoundsCheckImpl;
vector<Interval>& b = pimpl->bounds;
b.resize( mins.size());
for (unsigned i = 0; i < b.size(); ++i) {
b[i] = Interval(mins[i], maxes[i]);
}
}
IntervalBoundsCheck::~IntervalBoundsCheck() { delete pimpl; }
IntervalBoundsCheck::IntervalBoundsCheck(const IntervalBoundsCheck& that) { pimpl = new IntervalBoundsCheckImpl(*that.pimpl); }
IntervalBoundsCheck& IntervalBoundsCheck::operator=(const IntervalBoundsCheck& that) { *pimpl = *that.pimpl; return *this; }
bool IntervalBoundsCheck::in_bounds(const Sym& sym) const {
Interval bounds;
try {
bounds = eval(sym, pimpl->bounds);
if (!valid(bounds)) return false;
} catch (interval_error) {
return false;
}
return true;
}
std::string IntervalBoundsCheck::get_bounds(const Sym& sym) const {
try {
Interval bounds = eval(sym, pimpl->bounds);
if (!valid(bounds)) return "err";
ostringstream os;
os << bounds;
return os.str();
} catch (interval_error) {
return "err";
}
}
std::pair<double, double> IntervalBoundsCheck::calc_bounds(const Sym& sym) const {
Interval bounds = eval(sym, pimpl->bounds);
return make_pair(bounds.lower(), bounds.upper());
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef BOUNDS_CHECK_H_
#define BOUNDS_CHECK_H_
#include <string>
class IntervalBoundsCheckImpl;
class Sym;
class BoundsCheck {
public :
virtual ~BoundsCheck() {};
virtual bool in_bounds(const Sym&) const = 0;
virtual std::string get_bounds(const Sym&) const = 0;
};
// checks if a formula keeps within bounds using interval arithmetic
class IntervalBoundsCheck : public BoundsCheck {
IntervalBoundsCheckImpl* pimpl;
public:
IntervalBoundsCheck(const std::vector<double>& minima, const std::vector<double>& maxima);
~IntervalBoundsCheck();
IntervalBoundsCheck(const IntervalBoundsCheck&);
IntervalBoundsCheck& operator=(const IntervalBoundsCheck&);
bool in_bounds(const Sym&) const;
std::string get_bounds(const Sym&) const;
std::pair<double, double> calc_bounds(const Sym&) const;
};
class NoBoundsCheck : public BoundsCheck {
bool in_bounds(const Sym&) const { return false; }
std::string get_bounds(const Sym&) const { return ""; }
};
#endif

View file

@ -0,0 +1,82 @@
/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef INTERVAL__H__
#define INTERVAL__H__
#include <boost/numeric/interval.hpp>
#include <iostream>
#include <limits>
typedef boost::numeric::interval_lib::rounded_transc_exact<double> RoundingTransc;
typedef boost::numeric::interval_lib::save_state<RoundingTransc> Rounding;
typedef boost::numeric::interval_lib::checking_base<double> Checking;
typedef boost::numeric::interval_lib::policies<Rounding,Checking> Policy;
typedef boost::numeric::interval<double, Policy> Interval;
struct interval_error{};
inline bool valid(const Interval& val) {
if (!finite(val.lower()) || !finite(val.upper())) return false;
return val.lower() > -1e10 && val.upper() < 1e10;
}
inline Interval sqrt(const Interval& val) {
if (val.lower() < 0.0) {
return Interval::whole();
}
return boost::numeric::sqrt(val);
}
inline Interval sqr(const Interval& val) {
return square(val);
}
inline Interval acos(const Interval& val) {
if (val.lower() < 1.0 || val.upper() > 1.0) {
return Interval::whole();
}
return boost::numeric::acos(val);
}
inline Interval asin(const Interval& val) {
if (val.lower() < 1.0 || val.upper() > 1.0) {
return Interval::whole();
}
return boost::numeric::asin(val);
}
inline Interval acosh(const Interval& val) {
if (val.lower() < 1.0) return Interval::whole();
return boost::numeric::acosh(val);
}
inline
std::ostream& operator<<(std::ostream& os, const Interval& val) {
os << '[' << val.lower() << ", " << val.upper() << ']';
return os;
}
#ifdef TEST_INTERVAL
#endif
#endif

View file

@ -0,0 +1,26 @@
namespace multi_function {
double plus(arg_ptr args) {
return *args[0] + *args[1];
}
double mult(arg_ptr args) {
return *args[0] * *args[1];
}
double min(arg_ptr args) {
return -**args;
}
double inv(arg_ptr args) {
return 1 / **args;
}
//template <typename f> class F { public: double operator()(double a) { return f(a); } };
double exp(arg_ptr args) {
return ::exp(**args);
}
} // namespace

View file

@ -0,0 +1,341 @@
#include <vector.h>
#include "MultiFunction.h"
#include "Sym.h"
#include "FunDef.h"
using namespace std;
typedef vector<double>::const_iterator data_ptr;
typedef vector<data_ptr> data_ptrs;
typedef data_ptrs::const_iterator arg_ptr;
#include "MultiFuncs.cpp"
typedef double (*fptr)( arg_ptr );
string print_function( fptr f) {
if (f == multi_function::plus) return "+";
if (f == multi_function::mult) return "*";
if (f == multi_function::min) return "-";
if (f == multi_function::inv) return "/";
if (f == multi_function::exp) return "e";
return "unknown";
}
struct Function {
fptr function;
arg_ptr args;
double operator()() const { return function(args); }
};
static vector<Function> token_2_function;
Sym make_binary(Sym sym) {
if (sym.args().size() == 2) return sym;
SymVec args = sym.args();
Sym an = args.back();
args.pop_back();
Sym nw = make_binary( Sym( sym.token(), args) );
args.resize(2);
args[0] = nw;
args[1] = an;
return Sym(sym.token(), args);
}
class Compiler {
public:
enum func_type {constant, variable, function};
typedef pair<func_type, unsigned> entry;
#if USE_TR1
typedef std::tr1::unordered_map<Sym, entry, HashSym> HashMap;
#else
typedef hash_map<Sym, entry, HashSym> HashMap;
#endif
HashMap map;
vector<double> constants;
vector<unsigned> variables;
vector< fptr > functions;
vector< vector<entry> > function_args;
unsigned total_args;
vector<entry> outputs;
Compiler() : total_args(0) {}
entry do_add(Sym sym) {
HashMap::iterator it = map.find(sym);
if (it == map.end()) { // new entry
token_t token = sym.token();
if (is_constant(token)) {
constants.push_back( get_constant_value(token) ); // set value
entry e = make_pair(constant, constants.size()-1);
map.insert( make_pair(sym, e) );
return e;
} else if (is_variable(token)) {
unsigned idx = get_variable_index(token);
variables.push_back(idx);
entry e = make_pair(variable, variables.size()-1);
map.insert( make_pair(sym, e) );
return e;
} // else
fptr f;
vector<entry> vec;
const SymVec& args = sym.args();
switch (token) {
case sum_token:
{
if (args.size() == 0) {
return do_add( SymConst(0.0));
}
if (args.size() == 1) {
return do_add(args[0]);
}
if (args.size() == 2) {
vec.push_back(do_add(args[0]));
vec.push_back(do_add(args[1]));
f = multi_function::plus;
//cout << "Adding + " << vec[0].second << ' ' << vec[1].second << endl;
break;
} else {
return do_add( make_binary(sym) );
}
}
case prod_token:
{
if (args.size() == 0) {
return do_add( SymConst(1.0));
}
if (args.size() == 1) {
return do_add(args[0]);
}
if (args.size() == 2) {
vec.push_back(do_add(args[0]));
vec.push_back(do_add(args[1]));
f = multi_function::mult;
//cout << "Adding * " << vec[0].second << ' ' << vec[1].second << endl;
break;
} else {
return do_add( make_binary(sym) );
}
}
case sqr_token:
{
SymVec newargs(2);
newargs[0] = args[0];
newargs[1] = args[0];
return do_add( Sym(prod_token, newargs));
}
default :
{
if (args.size() != 1) {
cerr << "Unknown function " << sym << " encountered" << endl;
exit(1);
}
vec.push_back(do_add(args[0]));
switch (token) {
case min_token: f = multi_function::min; break;
case inv_token: f = multi_function::inv; break;
case exp_token :f = multi_function::exp; break;
default :
{
cerr << "Unimplemented token encountered " << sym << endl;
exit(1);
}
}
//cout << "Adding " << print_function(f) << ' ' << vec[0].second << endl;
}
}
total_args += vec.size();
function_args.push_back(vec);
functions.push_back(f);
entry e = make_pair(function, functions.size()-1);
map.insert( make_pair(sym, e) );
return e;
}
return it->second; // entry
}
void add(Sym sym) {
entry e = do_add(sym);
outputs.push_back(e);
}
};
class MultiFunctionImpl {
public:
// input mapping
vector<unsigned> input_idx;
unsigned constant_offset;
unsigned var_offset;
// evaluation
vector<double> data;
vector<Function> funcs;
data_ptrs args;
vector<unsigned> output_idx;
MultiFunctionImpl() {}
void clear() {
input_idx.clear();
data.clear();
funcs.clear();
args.clear();
output_idx.clear();
constant_offset = 0;
}
void eval(const double* x, double* y) {
unsigned i;
// evaluate variables
for (i = constant_offset; i < constant_offset + input_idx.size(); ++i) {
data[i] = x[input_idx[i-constant_offset]];
}
for(; i < data.size(); ++i) {
data[i] = funcs[i-var_offset]();
//cout << i << " " << data[i] << endl;
}
for (i = 0; i < output_idx.size(); ++i) {
y[i] = data[output_idx[i]];
}
}
void eval(const vector<double>& x, vector<double>& y) {
eval(&x[0], &y[0]);
}
void setup(const vector<Sym>& pop) {
clear();
Compiler compiler;
for (unsigned i = 0; i < pop.size(); ++i) {
Sym sym = (expand_all(pop[i]));
compiler.add(sym);
}
// compiler is setup so get the data
constant_offset = compiler.constants.size();
var_offset = constant_offset + compiler.variables.size();
int n = var_offset + compiler.functions.size();
data.resize(n);
funcs.resize(compiler.functions.size());
args.resize(compiler.total_args);
// constants
for (unsigned i = 0; i < constant_offset; ++i) {
data[i] = compiler.constants[i];
//cout << i << ' ' << data[i] << endl;
}
// variables
input_idx = compiler.variables;
//for (unsigned i = constant_offset; i < var_offset; ++i) {
//cout << i << " x" << input_idx[i-constant_offset] << endl;
//}
// functions
unsigned which_arg = 0;
for (unsigned i = 0; i < funcs.size(); ++i) {
Function f;
f.function = compiler.functions[i];
//cout << i+var_offset << ' ' << print_function(f.function);
// interpret args
for (unsigned j = 0; j < compiler.function_args[i].size(); ++j) {
Compiler::entry e = compiler.function_args[i][j];
unsigned idx = e.second;
switch (e.first) {
case Compiler::function: idx += compiler.variables.size();
case Compiler::variable: idx += compiler.constants.size();
case Compiler::constant: {}
}
args[which_arg + j] = data.begin() + idx;
//cout << ' ' << idx << "(" << e.second << ")";
}
//cout << endl;
f.args = args.begin() + which_arg;
which_arg += compiler.function_args[i].size();
funcs[i] = f;
}
// output indices
output_idx.resize(compiler.outputs.size());
for (unsigned i = 0; i < output_idx.size(); ++i) {
output_idx[i] = compiler.outputs[i].second;
switch(compiler.outputs[i].first) {
case Compiler::function: output_idx[i] += compiler.variables.size();
case Compiler::variable: output_idx[i] += compiler.constants.size();
case Compiler::constant: {}
}
//cout << "out " << output_idx[i] << endl;
}
}
};
MultiFunction::MultiFunction(const std::vector<Sym>& pop) : pimpl(new MultiFunctionImpl) {
pimpl->setup(pop);
}
MultiFunction::~MultiFunction() { delete pimpl; }
void MultiFunction::operator()(const std::vector<double>& x, std::vector<double>& y) {
pimpl->eval(x,y);
}
void MultiFunction::operator()(const double* x, double* y) {
pimpl->eval(x,y);
}

View file

@ -0,0 +1,26 @@
#ifndef MULTIFUNCTION_H_
#define MULTIFUNCTION_H_
#include <vector>
class Sym;
class MultiFunctionImpl;
class MultiFunction {
MultiFunction& operator=(const MultiFunction&);
MultiFunction(const MultiFunction&);
MultiFunctionImpl* pimpl;
public:
MultiFunction(const std::vector<Sym>& pop);
~MultiFunction();
void operator()(const std::vector<double>& x, std::vector<double>& y);
void operator()(const double* x, double* y);
};
#endif

View file

@ -0,0 +1,57 @@
#include <stdio.h>
#include <libtcc.h>
#include <math.h>
static TCCState* s = 0;
extern void symc_init() {
if (s != 0) {
tcc_delete(s);
}
s = tcc_new();
if (s == 0) {
fprintf(stderr, "Tiny cc doesn't function properly");
exit(1);
}
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
}
extern int symc_compile(const char* func_str) {
//printf("Compiling %s\n", func_str);
int err = tcc_compile_string(s, func_str);
if (err) {
fprintf(stderr,"Compile failed");
}
return err;
}
extern int symc_link() {
int err = tcc_relocate(s);
if (err) {
fprintf(stderr,"Compile failed");
exit(1);
}
return err;
}
extern void* symc_get_fun(const char* func_name) {
unsigned long val;
tcc_get_symbol(s, &val, func_name);
if (val == 0) {
fprintf(stderr,"getfun failed");
exit(1);
}
return (void*) val;
}
extern void* symc_make(const char* func_str, const char* func_name) {
symc_init();
symc_compile(func_str);
symc_link();
return symc_get_fun(func_name);
}

View file

@ -0,0 +1,219 @@
/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Sym.h"
#include "FunDef.h"
#include "sym_compile.h"
#include <sstream>
using namespace std;
extern "C" {
void symc_init();
int symc_compile(const char* func_str);
int symc_link();
void* symc_get_fun(const char* func_name);
void* symc_make(const char* func_str, const char* func_name);
}
string make_prototypes() {
string prot = get_prototypes();
prot += "double sqr(double x) { return x*x; }";
return prot;
}
// contains variable names, like 'a0', 'a1', etc. or regular code
#if USE_TR1
typedef std::tr1::unordered_map<Sym, string, HashSym> HashMap;
#else
typedef hash_map<Sym, string, HashSym> HashMap;
#endif
// prints 'num' in reverse notation. Does not matter as it's a unique id
string make_var(unsigned num) {
string str = "a";
do {
str += char('0' + (num % 10));
num /= 10;
} while (num);
return str;
}
template <class T>
string to_string(T t) {
ostringstream os;
os << t;
return os.str();
}
HashMap::iterator find_entry(const Sym& sym, string& str, HashMap& map) {
HashMap::iterator result = map.find(sym);
if (result == map.end()) { // new entry
const SymVec& args = sym.args();
vector<string> argstr(args.size());
for (unsigned i = 0; i < args.size(); ++i) {
argstr[i] = find_entry(args[i], str, map)->second;
}
string var = make_var(map.size()); // map.size(): unique id
string code;
// write out the code
const FunDef& fun = get_element(sym.token());
code = fun.c_print(argstr, vector<string>() );
str += "double " + var + "=" + code + ";\n";
result = map.insert( make_pair(sym, var ) ).first; // only want iterator
}
return result;
}
void write_entry(const Sym& sym, string& str, HashMap& map, unsigned out) {
HashMap::iterator it = find_entry(sym, str, map);
str += "y[" + to_string(out) + "]=" + it->second + ";\n";
//cout << "wrote " << out << '\n';
}
#include <fstream>
multi_function compile(const std::vector<Sym>& syms) {
//cout << "Multifunction " << syms.size() << endl;
// static stream to avoid fragmentation of these LARGE strings
static string str;
str.clear();
str += make_prototypes();
str += "extern double func(const double* x, double* y) { \n ";
multi_function result;
HashMap map(Sym::get_dag().size());
for (unsigned i = 0; i < syms.size(); ++i) {
write_entry(syms[i], str, map, i);
}
str += ";}";
/*static int counter = 0;
ostringstream nm;
nm << "cmp/compiled" << (counter++) << ".c";
cout << "Saving as " << nm.str() << endl;
ofstream cmp(nm.str().c_str());
cmp << str;
cmp.close();
//cout << "Multifunction " << syms.size() << endl;
cout << "Size of map " << map.size() << endl;
*/
result = (multi_function) symc_make(str.c_str(), "func");
if (result==0) { // error
cout << "Error in compile " << endl;
}
return result;
}
single_function compile(Sym sym) {
ostringstream os;
os << make_prototypes();
os << "double func(const double* x) { return ";
string code = c_print(sym);
os << code;
os << ";}";
string func_str = os.str();
//cout << "compiling " << func_str << endl;
return (single_function) symc_make(func_str.c_str(), "func");
}
/* finds and inserts the full code in a hashmap */
HashMap::iterator find_code(Sym sym, HashMap& map) {
HashMap::iterator result = map.find(sym);
if (result == map.end()) { // new entry
const SymVec& args = sym.args();
vector<string> argstr(args.size());
for (unsigned i = 0; i < args.size(); ++i) {
argstr[i] = find_code(args[i], map)->second;
}
// write out the code
const FunDef& fun = get_element(sym.token());
string code = fun.c_print(argstr, vector<string>());
result = map.insert( make_pair(sym, code) ).first; // only want iterator
}
return result;
}
string print_code(Sym sym, HashMap& map) {
HashMap::iterator it = find_code(sym, map);
return it->second;
}
void compile(const std::vector<Sym>& syms, std::vector<single_function>& functions) {
symc_init();
static ostringstream os;
os.str("");
os << make_prototypes();
HashMap map(Sym::get_dag().size());
for (unsigned i = 0; i < syms.size(); ++i) {
os << "double func" << i << "(const double* x) { return ";
os << print_code(syms[i], map); //c_print(syms[i]);
os << ";}\n";
//symc_compile(os.str().c_str());
//cout << "compiling " << os.str() << endl;
}
os << ends;
#ifdef INTERVAL_DEBUG
//cout << "Compiling " << os.str() << endl;
#endif
symc_compile(os.str().c_str());
symc_link();
functions.resize(syms.size());
for (unsigned i = 0; i < syms.size(); ++i) {
ostringstream os2;
os2 << "func" << i;
functions[i] = (single_function) symc_get_fun(os2.str().c_str());
}
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2005 Maarten Keijzer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SYMCOMPILE_H_
#define SYMCOMPILE_H_
#include <vector>
#include <sym/Sym.h>
typedef double (*single_function)(const double []);
typedef double (*multi_function)(const double[], double[]);
/*
* Important, after every call of the functions below, the function pointers of the previous
* call are invalidated. Sorry, but that's the way the cookie crumbles (in tcc)
* */
single_function compile(Sym sym);
multi_function compile(const std::vector<Sym>& sym);
void compile(const std::vector<Sym>& sym, std::vector<single_function>& functions);
#endif