FLAME  devel
 All Classes Functions Variables Typedefs Enumerations Pages
glps_ops.cpp
1 #include <cmath>
2 
3 #include <sstream>
4 #include <limits>
5 #include <stdexcept>
6 
7 #include "glps_parser.h"
8 #include "flame/config.h"
9 
10 # define M_PI 3.14159265358979323846
11 
12 using std::isfinite;
13 namespace {
14 // Numeric operations
15 
16 int unary_negate(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
17 {
18  *R = -boost::get<double>(A[0]->value);
19  return 0;
20 }
21 
22 int unary_sin(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
23 {
24  *R = sin(boost::get<double>(A[0]->value));
25  return 0;
26 }
27 int unary_cos(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
28 {
29  *R = cos(boost::get<double>(A[0]->value));
30  return 0;
31 }
32 int unary_tan(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
33 {
34  *R = tan(boost::get<double>(A[0]->value));
35  return 0;
36 }
37 int unary_asin(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
38 {
39  *R = asin(boost::get<double>(A[0]->value));
40  return 0;
41 }
42 int unary_acos(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
43 {
44  *R = acos(boost::get<double>(A[0]->value));
45  return 0;
46 }
47 int unary_atan(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
48 {
49  *R = atan(boost::get<double>(A[0]->value));
50  return 0;
51 }
52 
53 int unary_deg2rad(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
54 {
55  double val = boost::get<double>(A[0]->value);
56  val *= M_PI/180.0;
57  *R = val;
58  return 0;
59 }
60 int unary_rad2deg(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
61 {
62  double val = boost::get<double>(A[0]->value);
63  val *= 180.0/M_PI;
64  *R = val;
65  return 0;
66 }
67 
68 int binary_add(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
69 {
70  *R = boost::get<double>(A[0]->value)+boost::get<double>(A[1]->value);
71  return 0;
72 }
73 int binary_sub(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
74 {
75  *R = boost::get<double>(A[0]->value)-boost::get<double>(A[1]->value);
76  return 0;
77 }
78 int binary_mult(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
79 {
80  *R = boost::get<double>(A[0]->value)*boost::get<double>(A[1]->value);
81  return 0;
82 }
83 int binary_div(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
84 {
85  double result = boost::get<double>(A[0]->value)/boost::get<double>(A[1]->value);
86  if(!isfinite(result)) {
87  ctxt->last_error = "division results in non-finite value";
88  return 1;
89  }
90  *R = result;
91  return 0;
92 }
93 
94 // beamline operations
95 
96 int unary_bl_negate(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
97 {
98  // reverse the order of the beamline
99  const std::vector<std::string>& line = boost::get<std::vector<std::string> >(A[0]->value);
100  std::vector<std::string> ret(line.size());
101  std::copy(line.rbegin(),
102  line.rend(),
103  ret.begin());
104  *R = ret;
105  return 0;
106 }
107 
108 template<int MULT, int LINE>
109 int binary_bl_mult(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
110 {
111  // multiple of scale * beamline repeats the beamline 'scale' times
112  assert(A[MULT]->etype==glps_expr_number);
113  assert(A[LINE]->etype==glps_expr_line);
114 
115  double factor = boost::get<double>(A[MULT]->value);
116 
117  if(factor<0.0 || factor>std::numeric_limits<unsigned>::max()) {
118  ctxt->last_error = "beamline scale by negative value or out of range value";
119  return 1;
120  }
121  unsigned factori = (unsigned)factor;
122 
123  const std::vector<std::string>& line = boost::get<std::vector<std::string> >(A[LINE]->value);
124 
125  std::vector<std::string> ret(line.size()*factori);
126 
127  if(factori>0)
128  {
129  std::vector<std::string>::iterator outi = ret.begin();
130 
131  while(factori--)
132  outi = std::copy(line.begin(),
133  line.end(),
134  outi);
135  }
136  *R = ret;
137  return 0;
138 }
139 
140 int unary_parse(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
141 {
142  using namespace boost::filesystem;
143  assert(A[0]->etype==glps_expr_string);
144  path name(canonical(boost::get<std::string>(A[0]->value), ctxt->cwd));
145 
146  GLPSParser P;
147  P.setPrinter(ctxt->printer);
148 
149  boost::shared_ptr<Config> ret(P.parse_file(name.native().c_str()));
150  *R = ret;
151  return 0;
152 }
153 
154 int unary_file(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
155 {
156  using namespace boost::filesystem;
157  const std::string& inp = boost::get<std::string>(A[0]->value);
158  path ret(canonical(inp, ctxt->cwd));
159 
160  if(!exists(ret)) {
161  std::ostringstream strm;
162  strm<<"\""<<ret<<"\" does not exist";
163  ctxt->last_error = strm.str();
164  return 1;
165  }
166 
167  *R = ret.native();
168  return 0;
169 }
170 
171 #ifdef USE_HDF5
172 int unary_h5file(parse_context* ctxt, expr_value_t *R, const expr_t * const *A)
173 {
174  using namespace boost::filesystem;
175  const std::string& inp = boost::get<std::string>(A[0]->value);
176 
177  /* The provided spec may contain both file path and group(s)
178  * seperated by '/' which is ambigious as the file path
179  * may contain '/' as well...
180  * so do as h5ls does and strip off from the right hand side until
181  * and try to open while '/' remain.
182  */
183  size_t sep = inp.npos;
184 
185  while(true) {
186  sep = inp.find_last_of('/', sep-1);
187 
188  path fname(absolute(inp.substr(0, sep), ctxt->cwd));
189 
190  if(exists(fname)) {
191  *R = canonical(fname).native() + inp.substr(sep);
192  return 0;
193  } else if(sep==inp.npos) {
194  break;
195  }
196  }
197 
198  std::ostringstream strm;
199  strm<<"\""<<inp<<"\" does not exist";
200  ctxt->last_error = strm.str();
201  return 1;
202 }
203 #endif
204 
205 } // namespace
206 
207 parse_context::parse_context(const char *path)
208  :last_line(0), printer(NULL), error_scratch(300), scanner(NULL)
209 {
210  if(path)
211  cwd = boost::filesystem::canonical(path);
212  else
213  cwd = boost::filesystem::current_path();
214  addop("-", &unary_negate, glps_expr_number, 1, glps_expr_number);
215 
216  addop("sin", &unary_sin, glps_expr_number, 1, glps_expr_number);
217  addop("cos", &unary_cos, glps_expr_number, 1, glps_expr_number);
218  addop("tan", &unary_tan, glps_expr_number, 1, glps_expr_number);
219  addop("asin",&unary_asin,glps_expr_number, 1, glps_expr_number);
220  addop("acos",&unary_acos,glps_expr_number, 1, glps_expr_number);
221  addop("atan",&unary_atan,glps_expr_number, 1, glps_expr_number);
222  // aliases to capture legacy behavour :P
223  addop("arcsin",&unary_asin,glps_expr_number, 1, glps_expr_number);
224  addop("arccos",&unary_acos,glps_expr_number, 1, glps_expr_number);
225  addop("arctan",&unary_atan,glps_expr_number, 1, glps_expr_number);
226 
227  addop("deg2rad",&unary_deg2rad,glps_expr_number, 1, glps_expr_number);
228  addop("rad2deg",&unary_rad2deg,glps_expr_number, 1, glps_expr_number);
229 
230  addop("+", &binary_add, glps_expr_number, 2, glps_expr_number, glps_expr_number);
231  addop("-", &binary_sub, glps_expr_number, 2, glps_expr_number, glps_expr_number);
232  addop("*", &binary_mult,glps_expr_number, 2, glps_expr_number, glps_expr_number);
233  addop("/", &binary_div, glps_expr_number, 2, glps_expr_number, glps_expr_number);
234 
235  addop("-", &unary_bl_negate, glps_expr_line, 1, glps_expr_line);
236 
237  addop("*", &binary_bl_mult<0,1>, glps_expr_line, 2, glps_expr_number, glps_expr_line);
238  addop("*", &binary_bl_mult<1,0>, glps_expr_line, 2, glps_expr_line, glps_expr_number);
239 
240  addop("parse", &unary_parse, glps_expr_config, 1, glps_expr_string);
241  addop("file", &unary_file, glps_expr_string, 1, glps_expr_string);
242  addop("dir", &unary_file, glps_expr_string, 1, glps_expr_string);
243 #ifdef USE_HDF5
244  addop("h5file", &unary_h5file, glps_expr_string, 1, glps_expr_string);
245 #endif
246 }
247 
248 parse_context::~parse_context()
249 {
250 }
251 
void setPrinter(std::ostream *)
Set output for lexer/parser error messages.
Definition: config.cpp:358
Interface to lattice file parser.
Definition: config.h:240