1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#ifndef WARPX_PARSER_H_
#define WARPX_PARSER_H_
#include <array>
#include <vector>
#include <string>
#include <set>
#include "wp_parser_c.h"
#include "wp_parser_y.h"
#ifdef _OPENMP
#include <omp.h>
#endif
class GpuParser;
class WarpXParser
{
public:
WarpXParser (std::string const& func_body);
WarpXParser () = default;
~WarpXParser ();
void define (std::string const& func_body);
void setConstant (std::string const& name, double c);
//
// Option 1: Register every variable to an address provided.
// Assign values to external variables.
// Call eval().
void registerVariable (std::string const& name, double& var);
//
inline double eval () const noexcept;
//
// Option 2: Register all variables at once. Parser will create
// variables internally.
// Call eval(...) with variable values.
void registerVariables (std::vector<std::string> const& names);
//
template <typename T, typename... Ts> inline
double eval (T x, Ts... yz) const noexcept;
void print () const;
std::string const& expr () const;
std::set<std::string> symbols () const;
friend class GpuParser;
private:
void clear ();
template <typename T> inline
void unpack (double* p, T x) const noexcept;
template <typename T, typename... Ts> inline
void unpack (double* p, T x, Ts... yz) const noexcept;
std::string m_expression;
#ifdef _OPENMP
std::vector<struct wp_parser*> m_parser;
mutable std::vector<std::array<double,16> > m_variables;
#else
struct wp_parser* m_parser = nullptr;
mutable std::array<double,16> m_variables;
#endif
};
inline
double
WarpXParser::eval () const noexcept
{
#ifdef _OPENMP
return wp_ast_eval(m_parser[omp_get_thread_num()]->ast);
#else
return wp_ast_eval(m_parser->ast);
#endif
}
template <typename T, typename... Ts>
inline
double
WarpXParser::eval (T x, Ts... yz) const noexcept
{
#ifdef _OPENMP
unpack(m_variables[omp_get_thread_num()].data(), x, yz...);
#else
unpack(m_variables.data(), x, yz...);
#endif
return eval();
}
template <typename T>
inline
void
WarpXParser::unpack (double* p, T x) const noexcept
{
*p = x;
}
template <typename T, typename... Ts>
inline
void
WarpXParser::unpack (double* p, T x, Ts... yz) const noexcept
{
*p++ = x;
unpack(p, yz...);
}
#endif
|