ug4
vm.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014: G-CSC, Goethe University Frankfurt
3  * Author: Martin Rupp
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef VM_H_
34 #define VM_H_
35 
36 #include "common/log.h"
37 #include <vector>
38 #include "parser_node.h"
39 #include "common/assert.h"
40 #include "parser.hpp"
41 #include "common/error.h"
42 
43 namespace ug{
44 
48 class VMAdd
49 {
50 private:
51  std::vector<char> vmBuf;
52  std::string m_name;
53  std::vector<double> variables;
54  size_t m_nrOut, m_nrIn;
55  std::vector<SmartPtr<VMAdd> > subfunctions;
56 
58  {
62  JMP,
67  OP_CALL
68  };
69 
70 
71 
73  {
74  int i=inst;
75  serializeInt(i);
76  }
77 
78 
79  inline void deserializeVMInstr(size_t &p, VMInstruction &instr)
80  {
81  int i = *((int*)&vmBuf[p]);
82  instr = (VMInstruction) i;
83  p += sizeof(int);
84  }
85 
86  inline void serializeChar(char c)
87  {
88  vmBuf.push_back(c);
89  }
90 
91  inline void serializeInt(int d)
92  {
93  char *tmp = (char*)&d;
94  for(size_t i=0; i<sizeof(d); i++)
95  serializeChar(tmp[i]);
96  }
97 
98  inline void deserializeInt(size_t &p, int &i)
99  {
100  i = *((int*)&vmBuf[p]);
101  p += sizeof(int);
102  }
103 
104  inline void serializeDouble(double d)
105  {
106  char *tmp = (char*)&d;
107  for(size_t i=0; i<sizeof(d); i++)
108  serializeChar(tmp[i]);
109  }
110 
111  inline void deserializeDouble(size_t &p, double &d)
112  {
113  d = *((double*)&vmBuf[p]);
114  p += sizeof(double);
115  }
116 
117 
118  void print_unaryDouble(const char *desc, size_t &i)
119  {
120  double t;
121  deserializeDouble(i, t);
122  UG_LOG(desc << " " << t << "\n");
123  }
124  void print_unaryInt(const char *desc, size_t &i)
125  {
126  int t;
127  deserializeInt(i, t);
128  UG_LOG(desc << " " << t << "\n");
129  }
130 
131  void print_op(size_t &i)
132  {
133  int op;
134  deserializeInt(i, op);
135  switch(op)
136  {
137  case LUAPARSER_MATH_COS: UG_LOG("cos\n"); break;
138  case LUAPARSER_MATH_SIN: UG_LOG("sin\n"); break;
139  case LUAPARSER_MATH_EXP: UG_LOG("exp\n"); break;
140  case LUAPARSER_MATH_ABS: UG_LOG("abs\n"); break;
141  case LUAPARSER_MATH_LOG: UG_LOG("log\n"); break;
142  case LUAPARSER_MATH_LOG10: UG_LOG("log10\n"); break;
143  case LUAPARSER_MATH_SQRT: UG_LOG("sqrt\n"); break;
144  case LUAPARSER_MATH_FLOOR: UG_LOG("floor\n"); break;
145  case LUAPARSER_MATH_CEIL: UG_LOG("ceil\n"); break;
146  case '+': UG_LOG("+\n"); break;
147  case '-': UG_LOG("-\n"); break;
148  case '*': UG_LOG("*\n"); break;
149  case '/': UG_LOG("/\n"); break;
150  case '<': UG_LOG("<\n"); break;
151  case '>': UG_LOG(">\n"); break;
152  case LUAPARSER_GE: UG_LOG("GE >=\n"); break;
153  case LUAPARSER_LE: UG_LOG("LE <=\n"); break;
154  case LUAPARSER_NE: UG_LOG("NE ~=\n"); break;
155  case LUAPARSER_EQ: UG_LOG("EQ ==\n"); break;
156  case LUAPARSER_AND: UG_LOG("AND\n"); break;
157  case LUAPARSER_OR: UG_LOG("OR\n"); break;
158  case LUAPARSER_MATH_POW: UG_LOG("pow\n"); break;
159  case LUAPARSER_MATH_MIN: UG_LOG("min\n"); break;
160  case LUAPARSER_MATH_MAX: UG_LOG("max\n"); break;
161  }
162  }
163 
164 public:
166  {
167  m_name = "unknown";
168  }
169  void set_name(std::string name)
170  {
171  m_name = name;
172  }
173 
174  void push(double constant)
175  {
176 // UG_LOG("POS " << get_pos() << "\n");
177 // UG_LOG("PUSH_CONSTANT " << constant << "\n");
179  serializeDouble(constant);
180  }
181 
182  void push_var(int i)
183  {
184 // UG_LOG("PUSH_VAR " << i << "\n");
186  serializeInt(i);
187 // UG_LOG("POS " << get_pos() << "\n");
188  }
189 
191  {
192 // UG_LOG("JMP_IF_FALSE\n");
193  return jump(JMP_IF_FALSE);
194  }
195 
196  int jmp()
197  {
198 // UG_LOG("JMP\n");
199  return jump(JMP);
200  }
201 
202  int get_pos()
203  {
204  return vmBuf.size();
205  }
206 
207  void unary(int oper)
208  {
209 // UG_LOG("UNARY OP " << oper << "\n");
211  serializeInt(oper);
212 // UG_LOG("POS " << get_pos() << "\n");
213  }
214 
215  void binary(int oper)
216  {
217 // UG_LOG("BINARY OP " << oper << "\n");
219  serializeInt(oper);
220 // UG_LOG("POS " << get_pos() << "\n");
221  }
222 
223  void assign(int v)
224  {
225 // UG_LOG("ASSIGN " << v << "\n");
227  serializeInt(v);
228 // UG_LOG("POS " << get_pos() << "\n");
229  }
230 
231  void call(SmartPtr<VMAdd> subfunction)
232  {
233  size_t i;
234  for(i=0; i<subfunctions.size(); i++)
235  if(subfunctions[i] == subfunction)
236  break;
237  if(i == subfunctions.size())
238  subfunctions.push_back(subfunction);
240  serializeInt(i);
241  }
242 
243  void adjust_jmp_pos(int iPos, int jmpPos)
244  {
245 // UG_LOG("adjusting jmp pos in " << iPos << " to " << jmpPos << "\n");
246  int *p = (int *)&vmBuf[iPos];
247  *p = jmpPos;
248  }
249 
250  void ret()
251  {
253  }
254 
255  void print_short()
256  {
257  UG_LOG("function " << m_name << ", " << m_nrIn << " inputs, " << m_nrOut <<
258  " outputs, "<< variables.size() << " variables, " << subfunctions.size() << " subfunctions");
259  }
260 
261  void print()
262  {
263  print_rec(0);
264  }
265 
266  void print_rec(int level)
267  {
268  if(level > 5) { UG_LOG("\n... aborting recursion (potential infinite loop)\n"); }
269  print_short();
270  UG_LOG("\n");
271  for(size_t i=0; i<vmBuf.size(); )
272  {
273  UG_ASSERT(i<vmBuf.size(), i);
274  UG_LOG(i << " ");
275  VMInstruction instr;
276  deserializeVMInstr(i, instr);
277 
278  switch(instr)
279  {
280  case PUSH_CONSTANT:
281  print_unaryDouble("PUSH_CONSTANT", i);
282  break;
283 
284  case PUSH_VAR:
285  print_unaryInt("PUSH_VAR", i);
286  break;
287 
288  case JMP_IF_FALSE:
289  print_unaryInt("JMP_IF_FALSE", i);
290  break;
291  case JMP:
292  print_unaryInt("JMP", i);
293  break;
294 
295  case OP_UNARY:
296  UG_LOG("OP_UNARY "); print_op(i);
297  break;
298  case OP_BINARY:
299  UG_LOG("OP_BINARY "); print_op(i);
300  break;
301  case ASSIGN:
302  print_unaryInt("ASSIGN", i);
303  break;
304  case OP_RETURN:
305  UG_LOG("RETURN\n");
306  break;
307 
308  case OP_CALL:
309  {
310  int varI;
311  deserializeInt(i, varI);
312 
313  UG_COND_THROW(varI >= (int)subfunctions.size(), i);
314  UG_LOG("CALL to subfunction " << varI << ": ");
315  subfunctions[varI]->print_short();
316  UG_LOG("\n");
317  break;
318  }
319 
320  default:
321  UG_LOG(((int)instr) << "?\n");
322  }
323  }
324  if(subfunctions.size() > 0)
325  {
326  UG_LOG("<< SUBFUNCTIONS OF " << m_name << ":\n");
327  for(size_t i=0; i<subfunctions.size(); i++)
328  {
329  UG_LOG("---- SUBFUNCTION " << i << " of " << m_name << " ----\n");
330  subfunctions[i]->print_rec(level+1);
331  }
332  UG_LOG(" SUBFUNCTIONS OF " << m_name << " >>\n");
333  }
334  }
335 
336  int jump(VMInstruction instr)
337  {
338  serializeVMInstr(instr);
339  int jmpPos = get_pos();
340  serializeInt(jmpPos);
341 // UG_LOG("jump pos is " << jmpPos << "\n");
342  return jmpPos;
343  }
344 
345 
346 
347  void set_in_out(size_t nrIn,size_t nrOut)
348  {
349  m_nrOut = nrOut;
350  m_nrIn = nrIn;
351  }
352  void set_nr_of_variables(size_t nr)
353  {
354  variables.resize(nr);
355  }
356 
357  inline void execute_unary(size_t &i, double &v)
358  {
359  int op;
360 // UG_LOG("unary op " << v << "\n");
361  deserializeInt(i, op);
362  switch(op)
363  {
364  case LUAPARSER_MATH_COS: v = cos(v); break;
365  case LUAPARSER_MATH_SIN: v = sin(v); break;
366  case LUAPARSER_MATH_EXP: v = exp(v); break;
367  case LUAPARSER_MATH_ABS: v = fabs(v); break;
368  case LUAPARSER_MATH_LOG: v = log(v); break;
369  case LUAPARSER_MATH_LOG10: v = log10(v); break;
370  case LUAPARSER_MATH_SQRT: v = sqrt(v); break;
371  case LUAPARSER_MATH_FLOOR: v = floor(v); break;
372  case LUAPARSER_MATH_CEIL: v = ceil(v); break;
373  }
374  }
375 
376  inline void execute_binary(size_t &i, double *stack, int SP)
377  {
378  double &a = stack[SP-2];
379  double &b = stack[SP-1];
380 // UG_LOG("binary op " << a << " op " << b << "\n");
381 
382  int op;
383  deserializeInt(i, op);
384  switch(op)
385  {
386  case '+': a = b+a; break;
387  case '-': a = b-a; break;
388  case '*': a = b*a; break;
389  case '/': a = b/a; break;
390  case '<': a = (b < a) ? 1.0 : 0.0; break;
391  case '>': a = (b > a) ? 1.0 : 0.0; break;
392  case LUAPARSER_GE: a = (b >= a) ? 1.0 : 0.0; break;
393  case LUAPARSER_LE: a = (b <= a) ? 1.0 : 0.0; break;
394  case LUAPARSER_NE: a = (b != a) ? 1.0 : 0.0; break;
395  case LUAPARSER_EQ: a = (b == a) ? 1.0 : 0.0; break;
396  case LUAPARSER_AND: a = (a != 0.0 && b != 0.0) ? 1.0 : 0.0; break;
397  case LUAPARSER_OR: a = (a != 0 || b != 0) ? 1.0 : 0.0; break;
398  case LUAPARSER_MATH_POW: a = pow(b, a); break;
399  case LUAPARSER_MATH_MIN: a = (b < a) ? a : b; break;
400  case LUAPARSER_MATH_MAX: a = (b > a) ? a : b; break;
401  }
402  }
403 
404  double call(double *stack, int &SP)
405  {
406 // for(int j=0; j<variables.size(); j++)
407 // {UG_LOG("var[[" << j << "] = " << variables[j] << "\n");}
408 
409  double varD;
410  int varI;
411  size_t i=0;
412  VMInstruction instr;
413  while(1)
414  {
415 // UG_LOG("IP = " << i << ", SP = " << SP);
416  deserializeVMInstr(i, instr);
417 // UG_LOG("OP = " << (int)instr << "\n");
418 // for(int j=0; j<SP; j++)
419 // {UG_LOG("SP[" << j << "] = " << stack[j] << ", ");}
420 // UG_LOG("\n");
421 
422  switch(instr)
423  {
424  case PUSH_CONSTANT:
425 
426  deserializeDouble(i, varD);
427 // UG_LOG("PUSH CONSTANT " << varD << "\n");
428  stack[SP++] = varD;
429  break;
430 
431  case PUSH_VAR:
432  deserializeInt(i, varI);
433  stack[SP++] = variables[varI-1];
434 // UG_LOG("PUSH VAR " << varI << "\n");
435  break;
436 
437  case JMP_IF_FALSE:
438  deserializeInt(i, varI);
439 // UG_LOG("JMP IF FALSE " << varI << "\n");
440  SP--;
441  if(stack[SP] == 0.0)
442  i = varI;
443  break;
444  case JMP:
445  deserializeInt(i, varI);
446 // UG_LOG("JMP " << varI << "\n");
447  i = varI;
448  break;
449 
450  case OP_UNARY:
451  UG_ASSERT(SP>0, SP);
452  execute_unary(i, stack[SP-1]);
453  break;
454 
455  case OP_BINARY:
456  UG_ASSERT(SP>1, SP);
457  execute_binary(i, stack, SP);
458  SP--;
459  break;
460 
461  case ASSIGN:
462  deserializeInt(i, varI);
463  SP--;
464 // UG_LOG("ASSIGN " << varI << " = " << stack[SP] << "\n");
465  variables[varI-1] = stack[SP];
466  break;
467 
468  case OP_RETURN:
469 // UG_LOG("RETURN\n");
470  UG_ASSERT(SP == (int)m_nrOut, "stack pointer is not nrOut =" << m_nrOut << ", instead " << SP << " ?")
471  return stack[0];
472  break;
473 
474  case OP_CALL:
475  {
476  deserializeInt(i, varI);
477 // UG_LOG("call IP = " << i << ", SP = " << SP << "\n");
478  SmartPtr<VMAdd> sub = subfunctions[varI];
479  sub->call_sub(stack, SP);
480 // UG_LOG("call IP = " << i << ", SP = " << SP << "\n");
481  break;
482  }
483  default:
484  UG_ASSERT(0, "IP: " << i << " op " << ((int)instr) << " ?\n");
485  }
486  }
487  }
488 
489  double call_sub(double *stack, int &SP)
490  {
491  for(size_t i=0; i<m_nrIn; i++)
492  variables[i] = stack[SP+i-1];
493  SP -= m_nrIn;
494  return call(stack, SP);
495  }
496 
497  int execute(double *ret, const double *in)
498  {
499  double stack[255];
500  int SP=0;
501 
502  for(size_t i=0;i<m_nrIn; i++)
503  variables[i] = in[i];
504  call(stack, SP);
505  UG_ASSERT(SP == (int)m_nrOut, SP << " != " << m_nrOut);
506  for(size_t i=0; i<m_nrOut; i++)
507  ret[i] = stack[i];
508 
509  return 1;
510  }
511 
512  double call()
513  {
514  double stack[255];
515  int SP=0;
516  return call(stack, SP);
517  }
518 
519  double call(double a, double b, double c)
520  {
521  UG_ASSERT(m_nrOut == 1, m_nrOut);
522  UG_ASSERT(m_nrIn == 3, m_nrIn);
523  variables[0] = a;
524  variables[1] = b;
525  variables[2] = c;
526  return call();
527  }
528 
529  double call(double a, double b)
530  {
531  UG_ASSERT(m_nrOut == 1, m_nrOut);
532  UG_ASSERT(m_nrIn == 2, m_nrIn);
533  variables[0] = a;
534  variables[1] = b;
535  return call();
536  }
537 
538  double call(double a)
539  {
540  UG_ASSERT(m_nrOut == 1, m_nrOut);
541  UG_ASSERT(m_nrIn == 1, m_nrIn);
542  variables[0] = a;
543  return call();
544  }
545 
546  size_t num_out()
547  {
548  return m_nrOut;
549  }
550  size_t num_in()
551  {
552  return m_nrIn;
553  }
554 };
555 
556 }
557 #endif /* VM_H_ */
parameterString p
location name
Definition: checkpoint_util.lua:128
Definition: smart_pointer.h:108
--> documentation in vm.doxygen <–///
Definition: vm.h:49
std::vector< SmartPtr< VMAdd > > subfunctions
Definition: vm.h:55
int jump(VMInstruction instr)
Definition: vm.h:336
double call(double a, double b, double c)
Definition: vm.h:519
void deserializeDouble(size_t &p, double &d)
Definition: vm.h:111
std::vector< char > vmBuf
Definition: vm.h:51
size_t num_out()
Definition: vm.h:546
double call(double a, double b)
Definition: vm.h:529
void serializeInt(int d)
Definition: vm.h:91
int jmp()
Definition: vm.h:196
std::string m_name
Definition: vm.h:52
double call()
Definition: vm.h:512
void print_op(size_t &i)
Definition: vm.h:131
void print_rec(int level)
Definition: vm.h:266
void deserializeVMInstr(size_t &p, VMInstruction &instr)
Definition: vm.h:79
VMInstruction
Definition: vm.h:58
@ OP_CALL
Definition: vm.h:67
@ JMP_IF_FALSE
Definition: vm.h:61
@ ASSIGN
Definition: vm.h:65
@ PUSH_VAR
Definition: vm.h:60
@ OP_UNARY
Definition: vm.h:63
@ PUSH_CONSTANT
Definition: vm.h:59
@ JMP
Definition: vm.h:62
@ OP_BINARY
Definition: vm.h:64
@ OP_RETURN
Definition: vm.h:66
void serializeDouble(double d)
Definition: vm.h:104
void print_unaryDouble(const char *desc, size_t &i)
Definition: vm.h:118
void push(double constant)
Definition: vm.h:174
void serializeChar(char c)
Definition: vm.h:86
void call(SmartPtr< VMAdd > subfunction)
Definition: vm.h:231
int execute(double *ret, const double *in)
Definition: vm.h:497
void unary(int oper)
Definition: vm.h:207
void binary(int oper)
Definition: vm.h:215
int get_pos()
Definition: vm.h:202
void set_nr_of_variables(size_t nr)
Definition: vm.h:352
void print_short()
Definition: vm.h:255
double call(double a)
Definition: vm.h:538
size_t m_nrOut
Definition: vm.h:54
double call(double *stack, int &SP)
Definition: vm.h:404
int jmp_if_false()
Definition: vm.h:190
size_t num_in()
Definition: vm.h:550
void ret()
Definition: vm.h:250
void execute_binary(size_t &i, double *stack, int SP)
Definition: vm.h:376
void print()
Definition: vm.h:261
void print_unaryInt(const char *desc, size_t &i)
Definition: vm.h:124
void set_name(std::string name)
Definition: vm.h:169
double call_sub(double *stack, int &SP)
Definition: vm.h:489
void adjust_jmp_pos(int iPos, int jmpPos)
Definition: vm.h:243
void serializeVMInstr(VMInstruction inst)
Definition: vm.h:72
size_t m_nrIn
Definition: vm.h:54
void set_in_out(size_t nrIn, size_t nrOut)
Definition: vm.h:347
void push_var(int i)
Definition: vm.h:182
VMAdd()
Definition: vm.h:165
void execute_unary(size_t &i, double &v)
Definition: vm.h:357
void deserializeInt(size_t &p, int &i)
Definition: vm.h:98
std::vector< double > variables
Definition: vm.h:53
void assign(int v)
Definition: vm.h:223
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_LOG(msg)
Definition: log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition: error.h:61
the ug namespace
#define LUAPARSER_MATH_CEIL
Definition: parser.cpp:134
#define LUAPARSER_NE
Definition: parser.cpp:144
#define LUAPARSER_MATH_SQRT
Definition: parser.cpp:132
#define LUAPARSER_MATH_MAX
Definition: parser.cpp:136
#define LUAPARSER_MATH_COS
Definition: parser.cpp:127
#define LUAPARSER_MATH_LOG
Definition: parser.cpp:130
#define LUAPARSER_MATH_FLOOR
Definition: parser.cpp:133
#define LUAPARSER_MATH_EXP
Definition: parser.cpp:128
#define LUAPARSER_MATH_SIN
Definition: parser.cpp:126
#define LUAPARSER_MATH_POW
Definition: parser.cpp:135
#define LUAPARSER_OR
Definition: parser.cpp:142
#define LUAPARSER_EQ
Definition: parser.cpp:145
#define LUAPARSER_AND
Definition: parser.cpp:143
#define LUAPARSER_GE
Definition: parser.cpp:147
#define LUAPARSER_MATH_LOG10
Definition: parser.cpp:131
#define LUAPARSER_MATH_ABS
Definition: parser.cpp:129
#define LUAPARSER_MATH_MIN
Definition: parser.cpp:137
#define LUAPARSER_LE
Definition: parser.cpp:146