Added mathsym+tcc and boost against all advice
This commit is contained in:
parent
58ae49dd99
commit
90702a435d
136 changed files with 14409 additions and 0 deletions
80
eo/contrib/mathsym/eval/BoundsCheck.cpp
Normal file
80
eo/contrib/mathsym/eval/BoundsCheck.cpp
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
58
eo/contrib/mathsym/eval/BoundsCheck.h
Normal file
58
eo/contrib/mathsym/eval/BoundsCheck.h
Normal 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
|
||||
|
||||
|
||||
115
eo/contrib/mathsym/eval/Interval.h
Normal file
115
eo/contrib/mathsym/eval/Interval.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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
|
||||
using namespace std;
|
||||
using namespace boost::numeric;
|
||||
|
||||
int main() {
|
||||
Interval a(0, 10);
|
||||
Interval b(-1.5, 2);
|
||||
cout << "a = " << a << endl;
|
||||
cout << "b = " << b << endl;
|
||||
cout << "a + b = " << a + b << endl;
|
||||
cout << "a - b = " << a - b << endl;
|
||||
cout << "b - a = " << b - a << endl;
|
||||
cout << "-a = " << -a << endl;
|
||||
cout << "a * b = " << a * b << endl;
|
||||
cout << "b/(a+1) = " << b / (a + 1.0) << endl;
|
||||
cout << "b * a = " << b * a << endl;
|
||||
|
||||
cout << "b / a = " << b/a << endl;
|
||||
|
||||
cout << "cos(a) = " << cos(a) << endl;
|
||||
cout << "cos(b) = " << cos(b) << endl;
|
||||
|
||||
cout << "log(b) = " << log(b) << endl;
|
||||
|
||||
cout << "sqrt(b) = " << sqrt(b) << endl;
|
||||
cout << "sqrt(a) = " << sqrt(a) << endl;
|
||||
cout << "sqr(b) = " << sqr(b) << endl;
|
||||
|
||||
cout << "exp(b*a)= " << exp(b*a) << endl;
|
||||
|
||||
cout << "atan(a) = " << atan(a) << endl;
|
||||
cout << "cosh(b) = " << cosh(b) << endl;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
eo/contrib/mathsym/eval/c_compile.c
Normal file
40
eo/contrib/mathsym/eval/c_compile.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
extern void symc_compile(const char* func_str) {
|
||||
//printf("Compiling %s\n", func_str);
|
||||
tcc_compile_string(s, func_str);
|
||||
}
|
||||
|
||||
extern void symc_link() {
|
||||
tcc_relocate(s);
|
||||
}
|
||||
|
||||
extern void* symc_get_fun(const char* func_name) {
|
||||
unsigned long val;
|
||||
tcc_get_symbol(s, &val, func_name);
|
||||
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);
|
||||
}
|
||||
|
||||
181
eo/contrib/mathsym/eval/sym_compile.cpp
Normal file
181
eo/contrib/mathsym/eval/sym_compile.cpp
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
#if __GNUC__ == 3
|
||||
#include <backward/hash_map.h>
|
||||
#else
|
||||
#include <hash_map.h>
|
||||
using std::hash_map;
|
||||
#endif
|
||||
|
||||
#include "Sym.h"
|
||||
#include "FunDef.h"
|
||||
#include "sym_compile.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern "C" {
|
||||
void symc_init();
|
||||
void symc_compile(const char* func_str);
|
||||
void 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.
|
||||
typedef hash_map<Sym, string, HashSym> HashMap;
|
||||
|
||||
HashMap::iterator find_entry(Sym sym, ostream& os, 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], os, map)->second;
|
||||
}
|
||||
|
||||
unsigned current_entry = map.size(); // current number of variables defined
|
||||
|
||||
// write out the code
|
||||
const FunDef& fun = get_element(sym.token());
|
||||
string code = fun.c_print(argstr, vector<string>());
|
||||
os << "double a" << current_entry << "=" << code << ";\n";
|
||||
|
||||
// insert variable ref in map
|
||||
ostringstream str;
|
||||
str << 'a' << current_entry;
|
||||
|
||||
result = map.insert( make_pair(sym, str.str()) ).first; // only want iterator
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void write_entry(Sym sym, ostream& os, HashMap& map, unsigned out) {
|
||||
HashMap::iterator it = find_entry(sym, os, map);
|
||||
os << "y[" << out << "]=" << it->second << ";\n";
|
||||
}
|
||||
|
||||
multi_function compile(const std::vector<Sym>& syms) {
|
||||
|
||||
ostringstream os;
|
||||
|
||||
os << make_prototypes();
|
||||
|
||||
os << "double func(const double* x, double* y) { \n ";
|
||||
|
||||
HashMap map;
|
||||
|
||||
for (unsigned i = 0; i < syms.size(); ++i) {
|
||||
write_entry(syms[i], os, map, i);
|
||||
}
|
||||
|
||||
os << ";}";
|
||||
string func_str = os.str();
|
||||
|
||||
//cout << "compiling " << func_str << endl;
|
||||
|
||||
return (multi_function) symc_make(func_str.c_str(), "func");
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
ostringstream os;
|
||||
os << make_prototypes();
|
||||
HashMap map;
|
||||
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;
|
||||
}
|
||||
|
||||
#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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
36
eo/contrib/mathsym/eval/sym_compile.h
Normal file
36
eo/contrib/mathsym/eval/sym_compile.h
Normal 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>
|
||||
|
||||
|
||||
typedef double (*single_function)(const double *);
|
||||
typedef void (*multi_function)(const double*, double*); // last argument is output
|
||||
|
||||
/*
|
||||
* 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
|
||||
Reference in a new issue