source: PSPA/madxPSPA/src/mad_expr.c @ 430

Last change on this file since 430 was 430, checked in by touze, 11 years ago

import madx-5.01.00

File size: 13.6 KB
Line 
1#include "madx.h"
2
3static int
4is_operand(char c) {
5  return (isalnum(c) || c == '_' || c == '.');
6}
7
8static int
9is_operator(char c) {
10  return strchr("-+*/^", c) != 0;
11}
12
13static int
14is_expr_start(char c) {
15  return strchr("-+(",c) || is_operand(c);
16}
17
18#if 0 // not used...
19/* combine two parameters using compound expression */
20static struct expression*
21comb_param(struct command_parameter* param1, char* op, struct command_parameter* param2)
22{
23  return compound_expr(param1->expr,param1->double_value,op,param2->expr,param2->double_value);
24}
25#endif
26
27static double
28combine_expr_expr(struct expression* exp1, char* oper, 
29                  struct expression* exp2, struct expression** comb_exp)
30{
31  strcpy(c_dum->c, exp1->string);
32  strcat(c_dum->c, oper);
33  strcat(c_dum->c, exp2->string);
34  mysplit(c_dum->c, tmp_p_array);
35  *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p);
36  return expression_value(*comb_exp, 2);
37}
38
39static double
40combine_expr_val(struct expression* exp1, char* oper, double val2, struct expression** comb_exp)
41{
42  strcpy(c_dum->c, exp1->string);
43  sprintf(aux_buff->c, "%.12g", val2);
44  strcat(c_dum->c, oper);
45  strcat(c_dum->c, aux_buff->c);
46  mysplit(c_dum->c, tmp_p_array);
47  *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p);
48  return expression_value(*comb_exp, 2);
49}
50
51static double
52combine_val_expr(double val1, char* oper, struct expression* exp2, struct expression** comb_exp)
53{
54  sprintf(c_dum->c, "%.12g", val1);
55  strcat(c_dum->c, oper);
56  strcat(c_dum->c, exp2->string);
57  mysplit(c_dum->c, tmp_p_array);
58  *comb_exp = make_expression(tmp_p_array->curr, tmp_p_array->p);
59  return expression_value(*comb_exp, 2);
60}
61
62// public interface
63
64struct expression*
65make_expression(int n, char** toks)
66  /* makes an expression from a list of tokens */
67{
68  struct expression* expr = NULL;
69
70  if (polish_expr(n, toks) == 0)
71    expr = new_expression(join_b(toks, n), deco);
72  else warning("Invalid expression starting at:", join_b(toks, n));
73  return expr;
74}
75
76struct expression*
77new_expression(char* in_string, struct int_array* polish)
78{
79  char rout_name[] = "new_expression";
80  int j;
81  struct expression* ex = mycalloc(rout_name,1,sizeof(struct expression));
82  strcpy(ex->name, "expression");
83  ex->stamp = 123456;
84  ex->string = mymalloc(rout_name,strlen(in_string)+1);
85  strcpy(ex->string, in_string);
86  if (watch_flag) fprintf(debug_file, "creating ++> %s\n", ex->name);
87  if (polish != NULL)
88  {
89    ex->polish = new_int_array(polish->curr);
90    ex->polish->curr = polish->curr;
91    for (j = 0; j < polish->curr; j++) ex->polish->i[j] = polish->i[j];
92  }
93  return ex;
94}
95
96struct expr_list*
97new_expr_list(int length)
98{
99  char rout_name[] = "new_expr_list";
100  struct expr_list* ell = mycalloc(rout_name,1, sizeof(struct expr_list));
101  strcpy(ell->name, "expr_list");
102  ell->stamp = 123456;
103  if (watch_flag) fprintf(debug_file, "creating ++> %s\n", ell->name);
104  ell->list  =
105    (struct expression**) mycalloc(rout_name,length, sizeof(struct expression*));
106  ell->max = length;
107  return ell;
108}
109
110double
111expression_value(struct expression* expr, int flag) /* recursive */
112  /* returns the value of an expression if valid, else zero */
113{
114  double val = zero;
115  if (expr->status == 0 || flag == 2)
116  {
117    if (expr->polish != NULL)
118    {
119      val = expr->value = polish_value(expr->polish, expr->string);
120      expr->status = 1;
121    }
122  }
123  else val = expr->value;
124  return val;
125}
126
127struct expression*
128clone_expression(struct expression* p)
129{
130  struct expression* clone;
131  if (p == NULL) return NULL;
132  clone = new_expression(p->string, p->polish);
133  clone->status = p->status;
134  clone->value = p->value;
135  return clone;
136}
137
138struct expr_list*
139clone_expr_list(struct expr_list* p)
140{
141  int i;
142  struct expr_list* clone;
143  if (p == NULL)  return NULL;
144  clone = new_expr_list(p->curr);
145  for (i = 0; i < p->curr; i++) clone->list[i] = clone_expression(p->list[i]);
146  clone->curr = p->curr;
147  return clone;
148}
149
150struct expression*
151delete_expression(struct expression* expr)
152{
153  char rout_name[] = "delete_expression";
154  if (expr == NULL) return NULL;
155  if (stamp_flag && expr->stamp != 123456)
156    fprintf(stamp_file, "d_ex double delete --> %s\n", expr->name);
157  if (watch_flag) fprintf(debug_file, "deleting --> %s\n", expr->name);
158  if (expr->polish != NULL) expr->polish = delete_int_array(expr->polish);
159  if (expr->string != NULL) myfree(rout_name, expr->string);
160  myfree(rout_name, expr);
161  return NULL;
162}
163
164struct expr_list*
165delete_expr_list(struct expr_list* exprl)
166{
167  char rout_name[] = "delete_expr_list";
168  int i;
169  if (exprl == NULL) return NULL;
170  if (stamp_flag && exprl->stamp != 123456)
171    fprintf(stamp_file, "d_ex_l double delete --> %s\n", exprl->name);
172  if (watch_flag) fprintf(debug_file, "deleting --> %s\n", exprl->name);
173  if (exprl->list != NULL)
174  {
175    for (i = 0; i < exprl->curr; i++)
176      if (exprl->list[i] != NULL)  delete_expression(exprl->list[i]);
177    myfree(rout_name, exprl->list);
178  }
179  myfree(rout_name, exprl);
180  return NULL;
181}
182
183void
184grow_expr_list(struct expr_list* p)
185{
186  char rout_name[] = "grow_expr_list";
187  struct expression** e_loc = p->list;
188  int j, new = 2*p->max;
189  p->max = new;
190  p->list = mycalloc(rout_name,new, sizeof(struct expression*));
191  for (j = 0; j < p->curr; j++) p->list[j] = e_loc[j];
192  myfree(rout_name, e_loc);
193}
194
195void
196dump_expression(struct expression* ex)
197{
198  ex->value = expression_value(ex, 2);
199  fprintf(prt_file, v_format("expression: %s :: value: %F\n"),
200          ex->string, ex->value);
201}
202
203double
204expr_combine(struct expression* exp1, double val1, char* oper, 
205             struct expression*  exp2, double val2, 
206             struct expression** exp_comb)
207{
208  double val = 0;
209
210  if (exp1 == NULL && exp2 == NULL)
211  {
212    *exp_comb = NULL;
213    switch(oper[1])
214    {
215      case '+': val = val1 + val2; break;
216      case '-': val = val1 - val2; break;
217    }
218  }
219  else if(exp1 == NULL) val = combine_val_expr (val1, oper, exp2, exp_comb);
220  else if(exp2 == NULL) val = combine_expr_val (exp1, oper, val2, exp_comb);
221  else                  val = combine_expr_expr(exp1, oper, exp2, exp_comb);
222  return val;
223}
224
225void
226update_vector(struct expr_list* ell, struct double_array* da)
227{
228  int i;
229  for (i = 0; i < ell->curr; i++)
230  {
231    if (ell->list[i] != NULL)
232    {
233      while (da->max < i) grow_double_array(da);
234      da->a[i] = expression_value(ell->list[i], 2);
235    }
236  }
237  if (da->curr < ell->curr)  da->curr = ell->curr;
238}
239
240void
241fill_expr_list(char** toks, int s_start, int s_end, struct expr_list* p)
242{
243  int start = s_start, nitem = s_end + 1, end, cnt = 0, nc;
244  while (start < nitem)
245  {
246    if ((nc = next_char(',', toks, start, nitem)) < 0) nc = nitem;
247    if (loc_expr(toks, nc, start, &end))
248    {
249      if (cnt == p->max)  grow_expr_list(p);
250      p->list[cnt++] = make_expression(end + 1 - start, &toks[start]);
251      start = nc + 1;
252    }
253    else break;
254  }
255  p->curr = cnt;
256}
257
258void 
259fill_expr_var_list(struct el_list* ell, struct expression* expr, struct var_list* varl)
260  /* puts all variables an expression depends on, in a list */
261{
262  struct variable* var;
263  struct element* el;
264  char name[2*NAME_L];
265  char* p;
266  int i, k, kc;
267  struct int_array* deco = expr->polish;
268  for (i = 0; i < deco->curr; i++)   /* decoding loop */
269  {
270    if ((k = deco->i[i]) > 4 && (kc = k / 100000000) == 1)
271    {
272      k -= 100000000 * kc;  strcpy(name, expr_chunks->names[k]);
273      if ((p = strstr(name, "->")) != NULL)
274      {
275        *p = '\0';
276        if ((el = find_element(name, element_list)) != NULL)
277          add_to_el_list(&el, 0, ell, 0);
278      }
279      else if ((var = find_variable(name, variable_list)) != NULL)
280      {
281        add_to_var_list(var, varl, 2);
282        if (var->type == 2 && var->expr != NULL)
283          fill_expr_var_list(ell, var->expr, varl);
284      }
285    }
286  }
287}
288
289double
290double_from_expr(char** toks, int s_start, int s_end)
291  /* returns the value of an expression if valid, else INVALID */
292{
293  int end, nitem = s_end + 1;
294  int type = loc_expr(toks, nitem, s_start, &end);
295  if (type == 1) /* simple number */
296    return simple_double(toks, s_start, end);
297  else if (polish_expr(end + 1 - s_start, &toks[s_start]) == 0)
298    return polish_value(deco, join( &toks[s_start],end + 1 - s_start) );
299  else return INVALID;
300}
301
302int
303loc_expr(char** items, int nit, int start, int* end)
304  /* Returns the type and end of an expression, or 0 if illegal */
305{
306  char c;
307  int i, e_type = 1, par_level = 0, ltog = -1;
308  *end = start - 1;
309  if (nit > start && is_expr_start(*items[start]))
310  {
311    c = *items[start];
312    for (i = start; i < nit; i++)
313    {
314      c = *items[i];
315      if (c == '(')  {par_level++; e_type = 2;}
316      else if (c == ')')
317      {
318        if (par_level == 0) return 0;
319        par_level--; ltog = 0;
320      }
321      else if (par_level == 0)
322      {
323        if (ltog < 0)  ltog = is_operator(c) ? 1 : 0;
324        else if ((ltog == 0 && is_operator(c))
325                 || (ltog != 0 && is_operand(c)))  ltog = 1 - ltog;
326        else return 0;
327      }
328      *end = i;
329      if ((*end > start && ltog > 0) || (isalpha(c) || c == '_'))  e_type = 2;
330    }
331    return e_type;
332  }
333  else return 0;
334}
335
336int
337scan_expr(int c_item, char** item)   /* split input */
338
339  /* scans expressions for parameters, elements, numbers, and functions
340
341  categories: 1: variable, 3: floating constant, 4: operator
342  operator types:
343  1 = +, 2 = -, 3 = *, 4 = /, 5 = ^ (power), 6 = function (from functs)
344  */
345
346{
347  int i, lp, lx = -1, l_cat = 0, level = 0, pos, f_level[MAX_ITEM];
348  char c;
349  char* bf;
350
351  for (i = 0; i < c_item; i++)  /* loop over input items */
352  {
353    c = item[i][0];  /* first character of item i */
354    if (c == '(')
355    {
356      f_level[level++] = 0;
357      if (l_cat > 0)
358      {
359        if (cat->i[l_cat-1] < 4)  return 2;  /* error: missing operator */
360        if (cat->i[l_cat-1] == 5)   /* function */
361        {
362          f_level[level-1] = func->i[--l_cat];
363          if (l_cat == func->max)  grow_int_array(func);
364          func->i[l_cat] = 0;
365        }
366      }
367      if (l_cat == cat->max)  grow_int_array(cat);
368      cat->i[l_cat++] = 6;
369    }
370    else if (c == ')')
371    {
372      if (level == 0)  return 1;  /* error: too many right brackets */
373      if (l_cat == cat->max)  grow_int_array(cat);
374      cat->i[l_cat++] = 7;
375      level--;
376      if (f_level[level] != 0)
377      {
378        if (l_cat == oper->max)  grow_int_array(oper);
379        if (l_cat == func->max)  grow_int_array(func);
380        if (l_cat == cat->max)  grow_int_array(cat);
381        oper->i[l_cat] = 6;
382        func->i[l_cat] = f_level[level];
383        cat->i[l_cat++] = 4;
384      }
385    }
386    else if (isalpha(c) || c == '_')  /* start of variable or function */
387    {
388      lp = 0;
389      while (strlen(functs[lp]))
390      {
391        lx = lp;
392        if (strcmp(item[i], functs[lp]) == 0)  break;
393        lp++;
394      }
395      if (lx == lp)    /* function found */
396      {
397        if (l_cat == cat->max)  grow_int_array(cat);
398        if (l_cat == func->max)  grow_int_array(func);
399        cat->i[l_cat] = 5;
400        func->i[l_cat++] = lp;
401        if (strcmp("exist", functs[lp]) == 0  /* special function */
402            && i+3 < c_item && *item[i+1] == '(' && *item[i+3] == ')')
403        {
404          if (find_variable(item[i+2], variable_list) == NULL)
405            strcpy(item[i+2], "0");
406          else strcpy(item[i+2], "1");
407        }
408      }
409      else
410      {
411        if (l_cat == cat->max)  grow_int_array(cat);
412        if (l_cat == d_var->max)  grow_int_array(d_var);
413        cat->i[l_cat] = 1;
414        if ((pos = name_list_pos(item[i], expr_chunks)) < 0)
415        {
416          bf = permbuff(item[i]);
417          d_var->i[l_cat++] = add_to_name_list(bf, 0, expr_chunks);
418        }
419        else d_var->i[l_cat++] = pos;
420      }
421    }
422    else if (isdigit(c) || c == '.')  /* number */
423    {
424      if (l_cat == cat->max)  grow_int_array(cat);
425      if (l_cat == cat_doubles->max) grow_double_array(cat_doubles);
426      cat->i[l_cat] = 3;
427      cat_doubles->a[l_cat++] = atof(item[i]);
428    }
429    else if (is_operator(c))
430    {
431      if (l_cat == cat->max ) grow_int_array(cat);
432      if (l_cat == oper->max) grow_int_array(oper);
433      cat->i[l_cat] = 4;
434      oper->i[l_cat++] = str_pos(op_string, c);
435      /* oper->i[l_cat++] = (int)strchr(op_string, c) -(int)op_string;*/
436    }
437    else return 2;  /* illegal character */
438  }
439  if (level != 0)  return 1;  /* unclosed parentheses */
440  cat->curr = l_cat;
441  return 0;
442}
443
444struct expression*
445compound_expr(struct expression* e1, double v1, char* oper, struct expression* e2, double v2)
446/* make one out of two expressions, using oper to connect them
447 hbu 9/2005 moved from madxn.c to makethin.c as only used here
448 and increased precision   sprintf(tmp, "%e"  ->   sprintf(tmp, "%.14g" */
449{
450  char** toks = tmp_l_array->p;
451  struct expression* expr = NULL;
452  char tmp[30];
453  int n;
454  char lb[] = "(", rb[] = ")";
455  if (e1 != NULL || e2 != NULL)
456  {
457    if (e1 != NULL)
458    {
459      if (e2 != NULL)
460      {
461        toks[0] = lb; toks[1] = e1->string; toks[2] = rb;
462        toks[3] = oper;
463        toks[4] = lb; toks[5] = e2->string; toks[6] = rb;
464      }
465      else
466      {
467        sprintf(tmp, "%.14g", v2); /* hbu */
468        toks[0] = lb; toks[1] = e1->string; toks[2] = rb;
469        toks[3] = oper;
470        toks[4] = lb; toks[5] = tmp; toks[6] = rb;
471      }
472    }
473    else
474    {
475      sprintf(tmp, "%.14g", v1);  /* hbu */
476      toks[0] = lb; toks[1] = tmp; toks[2] = rb;
477      toks[3] = oper;
478      toks[4] = lb; toks[5] = e2->string; toks[6] = rb;
479    }
480    join(toks, 7);
481    pre_split(c_join->c, l_wrk, 0);
482    n = mysplit(l_wrk->c, tmp_l_array);
483    expr = make_expression(n, toks);
484  }
485  return expr;
486}
487
488/* scale an expression by a number - or leave it NULL */
489struct expression*
490scale_expr(struct expression* expr,double scale)
491{
492  if (expr) return compound_expr(expr,0,"*",NULL,scale);
493  return NULL;
494}
495
Note: See TracBrowser for help on using the repository browser.