Fixed compile bug caused by "missing" config.h.
[ginac.git] / ginac / excompiler.cpp
1 /** @file excompiler.cpp
2  *
3  *  Class to facilitate the conversion of a ex to a function pointer suited for
4  *  fast numerical integration. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #include "excompiler.h"
25
26 #include <dlfcn.h>
27 #include <stdexcept>
28 #include <fstream>
29 #include <sstream>
30 #include <string>
31 #include <vector>
32
33 #include "config.h"
34 #include "ex.h"
35 #include "lst.h"
36 #include "operators.h"
37 #include "relational.h"
38 #include "symbol.h"
39
40 namespace GiNaC {
41
42 #ifdef HAVE_LIBDL
43         
44 class excompiler
45 {
46         struct filedesc
47         {
48                 void* module;
49                 std::string name;
50         };
51 public:
52         excompiler() {};
53         ~excompiler()
54         {
55                 for (std::vector<filedesc>::const_iterator it = filelist.begin(); it != filelist.end(); ++it) {
56                         dlclose(it->module);
57                         std::string strremove = "rm " + it->name;
58                         system(strremove.c_str());
59                 }
60         }
61         void add(void* module, std::string name)
62         {
63                 filedesc fd;
64                 fd.module = module;
65                 fd.name = name;
66                 filelist.push_back(fd);
67         }
68         std::vector<filedesc> filelist;
69 };
70
71 excompiler _exc;
72
73 FP_dim1 compile(const ex& expr, const symbol& sym)
74 {
75         symbol argx("argx");
76         ex expr_with_x = expr.subs(lst(sym==argx));
77
78         char filename[] = "/tmp/GiNaCXXXXXX";
79
80         int fno = mkstemp(filename);
81
82         std::ofstream ofs(filename);
83
84         ofs << "#include <stddef.h> " << std::endl;
85         ofs << "#include <stdlib.h> " << std::endl;
86         ofs << "#include <math.h> " << std::endl;
87         ofs << std::endl;
88         ofs << "double compiled_ex(double argx)" << std::endl;
89         ofs << "{" << std::endl;
90         ofs << "double res = ";
91         expr_with_x.print(GiNaC::print_csrc_double(ofs));
92         ofs << ";" << std::endl;
93         ofs << "return(res); " << std::endl;
94         ofs << "}" << std::endl;
95
96         ofs.close();
97
98         std::string strcompile = "ginac-excompiler " + std::string(filename);
99         system(strcompile.c_str());
100
101         std::string strremove = "rm " + std::string(filename) + " " + std::string(filename) + ".o";
102         system(strremove.c_str());
103
104         std::string strsofile = std::string(filename) + ".so";
105         void* module = NULL;
106         module = dlopen(strsofile.c_str(), RTLD_NOW);
107         if (module == NULL)     {
108                 throw std::runtime_error("excompiler: could not open compiled module!");
109         }
110
111         _exc.add(module, strsofile);
112
113         return (FP_dim1) dlsym(module, "compiled_ex");
114 }
115
116 FP_cuba compile(const lst& exprs, const lst& syms)
117 {
118         lst replacements;
119         for (int count=0; count<syms.nops(); ++count) {
120                 std::ostringstream s;
121                 s << "a[" << count << "]";
122                 replacements.append(syms.op(count) == symbol(s.str()));
123         }
124
125         std::vector<ex> expr_with_cname;
126         for (int count=0; count<exprs.nops(); ++count) {
127                 expr_with_cname.push_back(exprs.op(count).subs(replacements));
128         }
129
130         char filename[] = "/tmp/GiNaCXXXXXX";
131
132         int fno = mkstemp(filename);
133
134         std::ofstream ofs(filename);
135
136         ofs << "#include <stddef.h> " << std::endl;
137         ofs << "#include <stdlib.h> " << std::endl;
138         ofs << "#include <math.h> " << std::endl;
139         ofs << std::endl;
140         ofs << "void compiled_ex(const int* an, const double a[], const int* fn, double f[])" << std::endl;
141         ofs << "{" << std::endl;
142         for (int count=0; count<exprs.nops(); ++count) {
143                 ofs << "f[" << count << "] = ";
144                 expr_with_cname[count].print(GiNaC::print_csrc_double(ofs));
145                 ofs << ";" << std::endl;
146         }
147         ofs << "}" << std::endl;
148
149         ofs.close();
150
151         std::string strcompile = "ginac-excompiler " + std::string(filename);
152         system(strcompile.c_str());
153
154         std::string strremove = "rm " + std::string(filename) + " " + std::string(filename) + ".o";
155         system(strremove.c_str());
156
157         std::string strsofile = std::string(filename) + ".so";
158         void* module = NULL;
159         module = dlopen(strsofile.c_str(), RTLD_NOW);
160         if (module == NULL)     {
161                 throw std::runtime_error("excompiler: could not open compiled module!");
162         }
163
164         _exc.add(module, strsofile);
165
166         return (FP_cuba) dlsym(module, "compiled_ex");
167 }
168
169 #elif
170
171 FP_dim1 compile(const ex& expr, const symbol& sym)
172 {
173         throw std::runtime_error("compile has been disabled because of missing libdl!");
174         return NULL;
175 }
176
177 FP_cuba compile(const lst& exprs, const lst& syms)
178 {
179         throw std::runtime_error("compile has been disabled because of missing libdl!");
180         return NULL;
181 }
182
183 #endif
184
185 } // namespace GiNaC