Skip to content

Commit

Permalink
Skip unnecessary creation of a temporary object
Browse files Browse the repository at this point in the history
At the cost of making the code more incomprehensible? Maybe not worth,
reroll this if any bugs turn up.
  • Loading branch information
coldfix committed Sep 1, 2021
1 parent c442d53 commit 4ea180e
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/cpymad/clibmadx.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ cdef extern from "madX/mad_gvar.h" nogil:
el_list* base_type_list # list of base types
command_list* defined_commands # with base types, but no user elements
int start_var # start of variables after predefined constants
int_array* deco # temporary buffer for polished expressions


# Function declarations:
Expand All @@ -259,9 +260,12 @@ cdef extern from "madX/mad_str.h" nogil:
void stolower_nq(char*)
int mysplit(char*, char_p_array*)
int supp_lt(char*, int)
char* join(char**, int)

cdef extern from "madX/mad_eval.h" nogil:
void pro_input(char*)
int polish_expr(int, char**)
double polish_value(int_array*, char*)

cdef extern from "madX/mad_expr.h" nogil:
expression* make_expression(int, char**)
Expand Down
25 changes: 10 additions & 15 deletions src/cpymad/libmadx.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -926,12 +926,8 @@ def eval(expression: str) -> float:
invalid input such as '+' can lead to program crashes! If you're looking
for more secure validation, see :func:`cpymad.util.check_expression`.
"""
cdef clib.expression* expr = _make_expr(expression)
if expr == NULL:
raise ValueError("Invalid expression: {!r}".format(expression))
value = clib.expression_value(expr, 2)
clib.delete_expression(expr)
return value
cdef char* string = _polish_expr(expression)
return clib.polish_value(clib.deco, string)


def expression_vars(expression: str) -> set:
Expand All @@ -946,15 +942,12 @@ def expression_vars(expression: str) -> set:
invalid input such as '+' can lead to program crashes! If you're looking
for more secure validation, see :func:`cpymad.util.check_expression`.
"""
cdef clib.expression* expr = _make_expr(expression)
if expr == NULL:
raise ValueError("Invalid expression: {!r}".format(expression))
_polish_expr(expression)
cdef int i
vars = {_str(clib.expr_chunks.names[k % 100000000])
for i in range(expr.polish.curr)
for k in [expr.polish.i[i]]
for i in range(clib.deco.curr)
for k in [clib.deco.i[i]]
if k // 100000000 == 1}
clib.delete_expression(expr)
return vars


Expand All @@ -965,7 +958,7 @@ def expression_vars(expression: str) -> set:
# we want to pass parameters or return values with a pure C type.


cdef clib.expression* _make_expr(str expression):
cdef char* _polish_expr(str expression) except NULL:
# TODO: This function uses global variables as temporaries - which is in
# general an *extremely* bad design choice. Even though MAD-X uses global
# variables internally anyway, this is no excuse for cpymad to copy that
Expand All @@ -986,8 +979,10 @@ cdef clib.expression* _make_expr(str expression):
clib.tmp_p_array.curr,
start, &stop)
if etype == 0 or stop+1 < clib.tmp_p_array.curr:
return NULL
return clib.make_expression(clib.tmp_p_array.curr, clib.tmp_p_array.p)
raise ValueError("Invalid expression: {!r}".format(expression))
if clib.polish_expr(stop + 1, clib.tmp_p_array.p) != 0:
raise ValueError("Invalid expression: {!r}".format(expression))
return clib.join(clib.tmp_p_array.p, stop + 1)


_expr_types = [bool, int, float]
Expand Down

0 comments on commit 4ea180e

Please sign in to comment.