3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * \brief Selection compilation and optimization.
35 * Better error handling and memory management in error situations.
36 * For example, memory handling in atom-valued method parameters within common
37 * subexpressions may currently result in memory leaks.
38 * Also, the main compilation function leaves the selection collection in
39 * a bad state if an error occurs.
42 * The memory usage could be optimized.
43 * Currently, each selection element allocates a separate block of memory to
44 * hold the evaluated value, but most of this memory is not used
45 * simultaneously. Perhaps the cleanest solution (avoiding constant allocation
46 * and deallocation) would be to have a memory pool whose maximum size is
47 * determined at compilation time and allocate memory from the pool during
51 * \page selcompiler Selection compilation
53 * The compiler takes the selection element tree from the selection parser
54 * (see \ref selparser) as input. The selection parser is quite independent of
55 * selection evaluation details, and the compiler processes the tree to
56 * conform to what the evaluation functions expect.
57 * For better control and optimization possibilities, the compilation is
58 * done on all selections simultaneously.
59 * Hence, all the selections should be parsed before the compiler can be
62 * The compiler initializes all fields in \c t_selelem not initialized by
63 * the parser: \c t_selelem::v (some fields have already been initialized by
64 * the parser), \c t_selelem::evaluate, and \c t_selelem::u (again, some
65 * elements have been initialized in the parser).
66 * The \c t_selelem::cdata field is used during the compilation to store
67 * internal data, but the data is freed when the compiler returns.
69 * In addition to initializing the elements, the compiler reorganizes the tree
70 * to simplify and optimize evaluation. The compiler also evaluates the static
71 * parts of the selection: in the end of the compilation, static parts have
72 * been replaced by the result of the evaluation.
74 * The compiler is called by calling gmx_ana_selcollection_compile().
75 * This functions then does the compilation in several passes over the
77 * -# Subexpressions are extracted: a separate root is created for each
78 * subexpression, and placed before the expression is first used.
79 * Currently, only variables and expressions used to evaluate parameter
80 * values are extracted, but common subexpression could also be detected
82 * -# A second pass with simple reordering and initialization is done:
83 * -# Boolean expressions are combined such that one element can evaluate,
84 * e.g., "A and B and C". The subexpressions in boolean expression are
85 * reordered such that static expressions come first without otherwise
86 * altering the relative order of the expressions.
87 * -# The \c t_selelem::evaluate field is set to the correct evaluation
88 * function from evaluate.h.
89 * -# The compiler data structure is allocated for each element, and
90 * the fields are initialized, with the exception of the contents of
91 * \c gmax and \c gmin fields.
93 * -# The evaluation function of all elements is replaced with the
94 * analyze_static() function to be able to initialize the element before
95 * the actual evaluation function is called.
96 * The evaluation machinery is then called to initialize the whole tree,
97 * while simultaneously evaluating the static expressions.
98 * During the evaluation, track is kept of the smallest and largest
99 * possible selections, and these are stored in the internal compiler
100 * data structure for each element.
101 * To be able to do this for all possible values of dynamical expressions,
102 * special care needs to be taken with boolean expressions because they
103 * are short-circuiting. This is done through the
104 * \c t_compiler_data::bEvalMax flag, which makes dynamic child expressions
105 * of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
106 * of \c BOOL_AND are evaluated to largest possible groups.
107 * Memory is also allocated to store the results of the evaluation.
108 * For each element, analyze_static() calls the actual evaluation function
109 * after the element has been properly initialized.
110 * -# Another evaluation pass is done over subexpressions with more than
111 * one reference to them. These cannot be completely processed during the
112 * first pass, because it is not known whether later references require
113 * additional evaluation of static expressions.
114 * -# Most of the processing is now done, and the next pass simply sets the
115 * evaluation group of root elements to the largest selection as determined
116 * in pass 3. Subexpressions that were evaluated to constants are no
117 * longer referenced at this time, and are removed.
118 * -# The next pass eliminates some unnecessary evaluation calls from
119 * subexpressions that are referenced only once, as well as initializing
120 * the position calculation data for selection method elements that require
121 * it. Compiler data is also freed as it is no longer needed.
122 * -# A final pass initializes the total masses and charges in the
123 * \c gmx_ana_selection_t data structures.
125 * The actual evaluation of the selection is described in the documentation
126 * of the functions in evaluate.h.
129 * Some combinations of method parameter flags are not yet properly treated by
130 * the compiler or the evaluation functions in evaluate.c. All the ones used by
131 * currently implemented methods should work, but new combinations might not.
134 * \section selcompiler_tree Element tree after compilation
136 * After the compilation, the selection element tree is suitable for
137 * gmx_ana_selcollection_evaluate().
138 * Enough memory has been allocated for \ref t_selelem::v
139 * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
140 * selection to be evaluated without allocating any memory.
143 * \subsection selcompiler_tree_root Root elements
145 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
146 * These are used for two purposes:
147 * -# A selection that should be evaluated.
148 * These elements appear in the same order as the selections in the input.
149 * For these elements, \ref t_selelem::v has been set to the maximum
150 * possible group that the selection can evaluate to, and
151 * \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
152 * -# A subexpression that appears in one or more selections.
153 * Each selection that gives a value for a method parameter is a
154 * potential subexpression, as is any variable value.
155 * Only subexpressions that require evaluation for each frame are left
156 * after the selection is compiled.
157 * Each subexpression appears in the chain before any references to it.
158 * For these elements, \c t_selelem::cgrp has been set to the group
159 * that should be used to evaluate the subexpression.
160 * If \c t_selelem::cgrp is empty, the total evaluation group is not known
161 * in advance. If this is the case, \c t_selelem::evaluate is also NULL.
163 * The children of the \ref SEL_ROOT elements can be used to distinguish
164 * the two types of root elements from each other; the rules are the same
165 * as for the parsed tree (see \ref selparser_tree_root).
166 * Subexpressions are treated as if they had been provided through variables.
168 * Selection names are stored as after parsing (see \ref selparser_tree_root).
171 * \subsection selcompiler_tree_const Constant elements
173 * All (sub)selections that do not require particle positions have been
174 * replaced with \ref SEL_CONST elements.
175 * Constant elements from the parser are also retained if present in
176 * dynamic parts of the selections.
177 * Several constant elements with a NULL \c t_selelem::evaluate are left for
178 * debugging purposes; of these, only the ones for \ref BOOL_OR expressions are
179 * used during evaluation.
181 * The value is stored in \c t_selelem::v, and for group values with an
182 * evaluation function set, also in \c t_selelem::cgrp.
183 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
184 * could never be selected) have been removed from the value.
186 * \ref SEL_CONST elements have no children.
189 * \subsection selcompiler_tree_method Method evaluation elements
191 * All selection methods that need to be evaluated dynamically are described
192 * by a \ref SEL_EXPRESSION element. The \c t_selelem::method and
193 * \c t_selelem::mdata fields have already been initialized by the parser,
194 * and the compiler only calls the initialization functions in the method
195 * data structure to do some additional initialization of these fields at
196 * appropriate points. If the \c t_selelem::pc data field has been created by
197 * the parser, the compiler initializes the data structure properly once the
198 * required positions are known. If the \c t_selelem::pc field is NULL after
199 * the parser, but the method provides only sel_updatefunc_pos(), an
200 * appropriate position calculation data structure is created.
201 * If \c t_selelem::pc is not NULL, \c t_selelem::pos is also initialized
202 * to hold the positions calculated.
204 * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
205 * parameter values that need to be evaluated for each frame. See the next
206 * section for more details.
207 * \ref SEL_CONST children can also appear, and stand for parameters that get
208 * their value from a static expression. These elements are present only for
209 * debugging purposes: they always have a NULL evaluation function.
212 * \subsection selcompiler_tree_subexpr Subexpression elements
214 * As described in \ref selcompiler_tree_root, subexpressions are created
215 * for each variable and each expression that gives a value to a selection
216 * method parameter. As the only child of the \ref SEL_ROOT element,
217 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
218 * element has a single child, which evaluates the actual expression.
219 * After compilation, only subexpressions that require particle positions
220 * for evaluation are left.
221 * For non-variable subexpression, automatic names have been generated to
224 * For \ref SEL_SUBEXPR elements, memory has been allocated for
225 * \c t_selelem::cgrp to store the group for which the expression has been
226 * evaluated during the current frame.
228 * \ref SEL_SUBEXPRREF elements are used to describe references to
229 * subexpressions. They have always a single child, which is the
230 * \ref SEL_SUBEXPR element being referenced.
232 * If a subexpression is used only once and can be evaluated statically,
233 * the evaluation has been optimized by setting the child of the
234 * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
235 * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
236 * and \ref SEL_SUBEXPR elements only propagate some status information,
237 * but do not unnecessarily copy the values.
240 * \subsection selcompiler_tree_bool Boolean elements
242 * \ref SEL_BOOLEAN elements have been merged such that one element
243 * may carry out evaluation of more than one operation of the same type.
244 * The static parts of the expressions have been evaluated, and are placed
245 * in the first child. These are followed by the dynamic expressions, in the
246 * order provided by the user.
259 #include <indexutil.h>
261 #include <selection.h>
262 #include <selmethod.h>
264 #include "evaluate.h"
265 #include "keywords.h"
266 #include "selcollection.h"
275 * Whether a subexpression needs to evaluated for all atoms.
277 * This flag is set for \ref SEL_SUBEXPR elements that are used to
278 * evaluate non-atom-valued selection method parameters, as well as
279 * those that are used directly as values of selections.
281 SEL_CDATA_FULLEVAL
= 1,
283 * Whether the whole subexpression should be treated as static.
285 * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
286 * but it is also FALSE for static elements within common subexpressions.
288 SEL_CDATA_STATIC
= 2,
289 /** Whether the subexpression will always be evaluated in the same group. */
290 SEL_CDATA_STATICEVAL
= 4,
291 /** Whether the compiler evaluation routine should return the maximal selection. */
292 SEL_CDATA_EVALMAX
= 8,
293 /** Whether memory has been allocated for \p gmin and \p gmax. */
294 SEL_CDATA_MINMAXALLOC
= 16,
298 * Internal data structure used by the compiler.
300 typedef struct t_compiler_data
302 /** The real evaluation method. */
303 sel_evalfunc evaluate
;
304 /** Flags for specifying how to treat this element during compilation. */
306 /** Smallest selection that can be selected by the subexpression. */
307 gmx_ana_index_t
*gmin
;
308 /** Largest selection that can be selected by the subexpression. */
309 gmx_ana_index_t
*gmax
;
313 /********************************************************************
314 * COMPILER UTILITY FUNCTIONS
315 ********************************************************************/
318 * \param sel Selection to free.
320 * This function only frees the data for the given selection, not its children.
321 * It is safe to call the function when compiler data has not been allocated
322 * or has already been freed; in such a case, nothing is done.
325 _gmx_selelem_free_compiler_data(t_selelem
*sel
)
329 sel
->evaluate
= sel
->cdata
->evaluate
;
330 if (sel
->cdata
->flags
& SEL_CDATA_MINMAXALLOC
)
332 sel
->cdata
->gmin
->name
= NULL
;
333 sel
->cdata
->gmax
->name
= NULL
;
334 gmx_ana_index_deinit(sel
->cdata
->gmin
);
335 gmx_ana_index_deinit(sel
->cdata
->gmax
);
336 sfree(sel
->cdata
->gmin
);
337 sfree(sel
->cdata
->gmax
);
345 * Allocates memory for storing the evaluated value of a selection element.
347 * \param sel Selection element to initialize
348 * \param[in] isize Maximum evaluation group size.
349 * \param[in] bChildEval TRUE if children have already been processed.
350 * \returns TRUE if the memory was allocated, FALSE if children need to
351 * be processed first.
353 * If called more than once, memory is (re)allocated to ensure that the
354 * maximum of the \p isize values can be stored.
357 alloc_selection_data(t_selelem
*sel
, int isize
, bool bChildEval
)
361 /* Find out the number of elements to allocate */
362 if (sel
->flags
& SEL_SINGLEVAL
)
366 else if (sel
->flags
& SEL_ATOMVAL
)
370 else /* sel->flags should contain SEL_VARNUMVAL */
378 child
= (sel
->type
== SEL_SUBEXPRREF
? sel
->child
: sel
);
379 if (child
->type
== SEL_SUBEXPR
)
381 child
= child
->child
;
383 nalloc
= (sel
->v
.type
== POS_VALUE
) ? child
->v
.u
.p
->nr
: child
->v
.nr
;
385 /* For positions, we actually want to allocate just a single structure
386 * for nalloc positions. */
387 if (sel
->v
.type
== POS_VALUE
)
392 /* Allocate memory for sel->v.u if needed */
393 if ((sel
->flags
& SEL_ALLOCVAL
)
394 || (sel
->type
== SEL_SUBEXPRREF
&& sel
->u
.param
395 && (sel
->u
.param
->flags
& (SPAR_VARNUM
| SPAR_ATOMVAL
))))
397 _gmx_selvalue_reserve(&sel
->v
, nalloc
);
399 /* Reserve memory inside group and position structures if
400 * SEL_ALLOCDATA is set. */
401 if (sel
->flags
& SEL_ALLOCDATA
)
403 if (sel
->v
.type
== GROUP_VALUE
)
405 gmx_ana_index_reserve(sel
->v
.u
.g
, isize
);
407 else if (sel
->v
.type
== POS_VALUE
)
409 gmx_ana_pos_reserve(sel
->v
.u
.p
, isize
, 0);
416 * Replace the evaluation function of each element in the subtree.
418 * \param sel Root of the selection subtree to process.
419 * \param[in] eval The new evaluation function.
422 set_evaluation_function(t_selelem
*sel
, sel_evalfunc eval
)
424 sel
->evaluate
= eval
;
425 if (sel
->type
!= SEL_SUBEXPRREF
)
427 t_selelem
*child
= sel
->child
;
430 set_evaluation_function(child
, eval
);
436 /********************************************************************
437 * SUBEXPRESSION EXTRACTION COMPILER PASS
438 ********************************************************************/
441 * Creates a name with a running number for a subexpression.
443 * \param[in,out] sel The subexpression to be named.
444 * \param[in] i Running number for the subexpression.
446 * The name of the selection becomes "SubExpr N", where N is \p i;
447 * Memory is allocated for the name and the name is stored both in
448 * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
449 * is freed by _gmx_selelem_free().
452 create_subexpression_name(t_selelem
*sel
, int i
)
457 len
= 8 + (int)log10(abs(i
)) + 3;
459 /* FIXME: snprintf used to be used here for extra safety, but this
460 * requires extra checking on Windows since it only provides a
461 * non-C99-conforming implementation as _snprintf()... */
462 ret
= sprintf(name
, "SubExpr %d", i
);
463 if (ret
< 0 || ret
> len
)
469 sel
->u
.cgrp
.name
= name
;
473 * Processes and extracts subexpressions from a given selection subtree.
475 * \param sel Root of the subtree to process.
476 * \param[in] gall Index group that contains all the input atoms.
477 * \param subexprn Pointer to a subexpression counter.
478 * \returns Pointer to a chain of subselections, or NULL if none were found.
480 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
481 * the given root element and ensures that their children are within
482 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
483 * that contain the subexpression as their children and returns the first
484 * of these root elements.
487 extract_item_subselections(t_selelem
*sel
, gmx_ana_index_t
*gall
, int *subexprn
)
493 root
= subexpr
= NULL
;
499 root
= subexpr
= extract_item_subselections(child
, gall
, subexprn
);
503 subexpr
->next
= extract_item_subselections(child
, gall
, subexprn
);
505 while (subexpr
&& subexpr
->next
)
507 subexpr
= subexpr
->next
;
509 /* The latter check excludes variable references.
510 * It also excludes subexpression elements that have already been
511 * processed, because they are given a name when they are first
513 * TODO: There should be a more robust mechanism (probably a dedicated
514 * flag) for detecting parser-generated subexpressions than relying on
515 * a NULL name field. */
516 if (child
->type
== SEL_SUBEXPRREF
&& (child
->child
->type
!= SEL_SUBEXPR
517 || child
->child
->name
== NULL
))
519 /* Create the root element for the subexpression */
522 root
= subexpr
= _gmx_selelem_create(SEL_ROOT
);
526 subexpr
->next
= _gmx_selelem_create(SEL_ROOT
);
527 subexpr
= subexpr
->next
;
529 /* Create the subexpression element and/or
530 * move the actual subexpression under the created element. */
531 if (child
->child
->type
!= SEL_SUBEXPR
)
533 subexpr
->child
= _gmx_selelem_create(SEL_SUBEXPR
);
534 _gmx_selelem_set_vtype(subexpr
->child
, child
->v
.type
);
535 subexpr
->child
->child
= child
->child
;
536 child
->child
= subexpr
->child
;
540 subexpr
->child
= child
->child
;
542 create_subexpression_name(subexpr
->child
, ++*subexprn
);
543 subexpr
->child
->refcount
++;
544 /* Set the flags for the created elements */
545 subexpr
->flags
|= (child
->flags
& SEL_VALFLAGMASK
);
546 subexpr
->child
->flags
|= (child
->flags
& SEL_VALFLAGMASK
);
555 * Extracts subexpressions of the selection chain.
557 * \param sel First selection in the whole selection chain.
558 * \param[in] gall Index group that contains all the input atoms.
559 * \returns The new first element for the chain.
561 * Finds all the subexpressions (and their subexpressions) in the
562 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
564 * \ref SEL_ROOT elements are also created for each subexpression
565 * and inserted into the selection chain before the expressions that
569 extract_subexpressions(t_selelem
*sel
, gmx_ana_index_t
*gall
)
571 t_selelem
*root
, *item
, *next
;
579 item
= extract_item_subselections(next
, gall
, &subexprn
);
606 /********************************************************************
607 * BOOLEAN OPERATION REORDERING COMPILER PASS
608 ********************************************************************/
611 * Removes redundant boolean selection elements.
613 * \param sel Root of the selection subtree to optimize.
615 * This function merges similar boolean operations (e.g., (A or B) or C becomes
616 * a single OR operation with three operands).
619 optimize_boolean_expressions(t_selelem
*sel
)
621 t_selelem
*child
, *prev
;
623 /* Do recursively for children */
624 if (sel
->type
!= SEL_SUBEXPRREF
)
630 optimize_boolean_expressions(child
);
631 /* Remove double negations */
632 if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== BOOL_NOT
633 && child
->child
->type
== SEL_BOOLEAN
&& child
->child
->u
.boolt
== BOOL_NOT
)
635 /* Move the doubly negated expression up two levels */
638 sel
->child
= child
->child
->child
;
643 prev
->next
= child
->child
->child
;
646 child
->child
->child
->next
= child
->next
;
647 /* Remove the two negations */
648 child
->child
->child
= NULL
;
650 _gmx_selelem_free(child
);
657 if (sel
->type
!= SEL_BOOLEAN
|| sel
->u
.boolt
== BOOL_NOT
)
661 /* Merge subsequent binary operations */
666 if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== sel
->u
.boolt
)
670 sel
->child
= child
->child
;
675 prev
->next
= child
->child
;
681 prev
->next
= child
->next
;
695 * Reorders children of boolean expressions such that static selections
698 * \param sel Root of the selection subtree to reorder.
700 * The relative order of static expressions does not change.
701 * The same is true for the dynamic expressions.
704 reorder_boolean_static_children(t_selelem
*sel
)
706 t_selelem
*child
, *prev
, *next
;
708 /* Do recursively for children */
709 if (sel
->type
!= SEL_SUBEXPRREF
)
714 reorder_boolean_static_children(child
);
719 /* Reorder boolean expressions such that static selections come first */
720 if (sel
->type
== SEL_BOOLEAN
&& (sel
->flags
& SEL_DYNAMIC
))
724 start
.next
= sel
->child
;
729 /* child is the last handled static expression */
730 /* prev is the last handled non-static expression */
732 while (next
&& (next
->flags
& SEL_DYNAMIC
))
737 /* next is now the first static expression after child */
742 /* Reorder such that next comes after child */
745 prev
->next
= next
->next
;
746 next
->next
= child
->next
;
753 /* Advance child by one */
757 sel
->child
= start
.next
;
761 /********************************************************************
762 * ARITHMETIC EXPRESSION PROCESSING
763 ********************************************************************/
766 * Processes arithmetic expressions to simplify and speed up evaluation.
768 * \param sel Root of the selection subtree to process.
770 * Currently, this function only converts integer constants to reals
771 * within arithmetic expressions.
774 optimize_arithmetic_expressions(t_selelem
*sel
)
779 /* Do recursively for children. */
780 if (sel
->type
!= SEL_SUBEXPRREF
)
785 bOk
= optimize_arithmetic_expressions(child
);
794 if (sel
->type
!= SEL_ARITHMETIC
)
799 /* Convert integer constants to reals. */
803 if (child
->v
.type
== INT_VALUE
)
807 if (child
->type
!= SEL_CONST
)
809 gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
813 r
[0] = child
->v
.u
.i
[0];
816 child
->v
.type
= REAL_VALUE
;
818 else if (child
->v
.type
!= REAL_VALUE
)
820 gmx_bug("Internal error");
828 /********************************************************************
829 * EVALUATION PREPARATION COMPILER PASS
830 ********************************************************************/
833 * Prepares the selection (sub)tree for evaluation.
835 * \param[in,out] sel Root of the selection subtree to prepare.
836 * \returns TRUE on success, FALSE if any subexpression fails.
838 * This function sets the evaluation function (\c t_selelem::evaluate)
839 * for the selection elements.
840 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
841 * structure if required.
844 init_item_evaluation(t_selelem
*sel
)
848 /* Process children */
849 if (sel
->type
!= SEL_SUBEXPRREF
)
854 if (!init_item_evaluation(child
))
862 /* Make sure that the group/position structure is allocated */
863 if (!sel
->v
.u
.ptr
&& (sel
->flags
& SEL_ALLOCVAL
))
865 if (sel
->v
.type
== GROUP_VALUE
|| sel
->v
.type
== POS_VALUE
)
867 _gmx_selvalue_reserve(&sel
->v
, 1);
872 /* Set the evaluation function */
876 if (sel
->v
.type
== GROUP_VALUE
)
878 sel
->evaluate
= &_gmx_sel_evaluate_static
;
883 if (!(sel
->flags
& SEL_DYNAMIC
) && sel
->u
.expr
.method
884 && sel
->u
.expr
.method
->init_frame
)
886 sel
->flags
|= SEL_INITFRAME
;
888 sel
->evaluate
= &_gmx_sel_evaluate_method
;
892 sel
->evaluate
= &_gmx_sel_evaluate_arithmetic
;
896 if (sel
->v
.type
!= NO_VALUE
)
898 sel
->evaluate
= &_gmx_sel_evaluate_modifier
;
903 switch (sel
->u
.boolt
)
905 case BOOL_NOT
: sel
->evaluate
= &_gmx_sel_evaluate_not
; break;
906 case BOOL_AND
: sel
->evaluate
= &_gmx_sel_evaluate_and
; break;
907 case BOOL_OR
: sel
->evaluate
= &_gmx_sel_evaluate_or
; break;
909 gmx_impl("xor expressions not implemented");
915 sel
->evaluate
= &_gmx_sel_evaluate_root
;
919 sel
->evaluate
= &_gmx_sel_evaluate_subexpr
;
923 sel
->name
= sel
->child
->name
;
924 sel
->evaluate
= &_gmx_sel_evaluate_subexprref
;
932 /********************************************************************
933 * COMPILER DATA INITIALIZATION PASS
934 ********************************************************************/
937 * Allocates memory for the compiler data and initializes the structure.
939 * \param sel Root of the selection subtree to process.
942 init_item_compilerdata(t_selelem
*sel
)
946 /* Allocate the compiler data structure */
949 /* Store the real evaluation method because the compiler will replace it */
950 sel
->cdata
->evaluate
= sel
->evaluate
;
952 /* Initialize the flags */
953 sel
->cdata
->flags
= SEL_CDATA_STATICEVAL
;
954 if (!(sel
->flags
& SEL_DYNAMIC
))
956 sel
->cdata
->flags
|= SEL_CDATA_STATIC
;
958 if (sel
->type
== SEL_SUBEXPR
)
960 sel
->cdata
->flags
|= SEL_CDATA_EVALMAX
;
962 /* Set the full evaluation flag for subexpressions that require it;
963 * the subexpression has already been initialized, so we can simply
964 * access its compilation flags.*/
965 if (sel
->type
== SEL_EXPRESSION
|| sel
->type
== SEL_MODIFIER
)
970 if (!(child
->flags
& SEL_ATOMVAL
))
972 child
->child
->cdata
->flags
|= SEL_CDATA_FULLEVAL
;
977 else if (sel
->type
== SEL_ROOT
&& sel
->child
->type
== SEL_SUBEXPRREF
)
979 sel
->child
->child
->cdata
->flags
|= SEL_CDATA_FULLEVAL
;
982 /* Initialize children */
983 if (sel
->type
!= SEL_SUBEXPRREF
)
988 init_item_compilerdata(child
);
993 /* Determine whether we should evaluate the minimum or the maximum
994 * for the children of this element. */
995 if (sel
->type
== SEL_BOOLEAN
)
999 bEvalMax
= (sel
->u
.boolt
== BOOL_AND
);
1005 child
->cdata
->flags
|= SEL_CDATA_EVALMAX
;
1007 else if (child
->type
== SEL_BOOLEAN
&& child
->u
.boolt
== BOOL_NOT
)
1009 child
->child
->cdata
->flags
|= SEL_CDATA_EVALMAX
;
1011 child
= child
->next
;
1014 else if (sel
->type
== SEL_EXPRESSION
|| sel
->type
== SEL_MODIFIER
1015 || sel
->type
== SEL_SUBEXPR
)
1020 child
->cdata
->flags
|= SEL_CDATA_EVALMAX
;
1021 child
= child
->next
;
1025 /* Initialize the minimum and maximum evaluation groups */
1026 if (sel
->type
!= SEL_ROOT
&& sel
->v
.type
!= NO_VALUE
)
1028 if (sel
->type
== SEL_SUBEXPR
)
1030 sel
->cdata
->gmin
= sel
->child
->cdata
->gmin
;
1031 sel
->cdata
->gmax
= sel
->child
->cdata
->gmax
;
1033 else if (sel
->v
.type
== GROUP_VALUE
1034 && (sel
->cdata
->flags
& SEL_CDATA_STATIC
))
1036 sel
->cdata
->gmin
= sel
->v
.u
.g
;
1037 sel
->cdata
->gmax
= sel
->v
.u
.g
;
1041 sel
->cdata
->flags
|= SEL_CDATA_MINMAXALLOC
;
1042 snew(sel
->cdata
->gmin
, 1);
1043 snew(sel
->cdata
->gmax
, 1);
1049 * Initializes the static evaluation flag for a selection subtree.
1051 * \param[in,out] sel Root of the selection subtree to process.
1053 * Sets the \c bStaticEval in the compiler data structure:
1054 * for any element for which the evaluation group may depend on the trajectory
1055 * frame, the flag is cleared.
1057 * reorder_boolean_static_children() should have been called.
1060 init_item_staticeval(t_selelem
*sel
)
1064 /* Subexpressions with full evaluation should always have bStaticEval,
1065 * so don't do anything if a reference to them is encountered. */
1066 if (sel
->type
== SEL_SUBEXPRREF
1067 && (sel
->child
->cdata
->flags
& SEL_CDATA_FULLEVAL
))
1072 /* Propagate the bStaticEval flag to children if it is not set */
1073 if (!(sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
))
1078 if ((sel
->type
!= SEL_EXPRESSION
&& sel
->type
!= SEL_MODIFIER
)
1079 || (child
->flags
& SEL_ATOMVAL
))
1081 if (child
->cdata
->flags
& SEL_CDATA_STATICEVAL
)
1083 child
->cdata
->flags
&= ~SEL_CDATA_STATICEVAL
;
1084 init_item_staticeval(child
);
1087 child
= child
->next
;
1090 else /* bStaticEval is set */
1092 /* For boolean expressions, any expression after the first dynamic
1093 * expression should not have bStaticEval. */
1094 if (sel
->type
== SEL_BOOLEAN
)
1097 while (child
&& !(child
->flags
& SEL_DYNAMIC
))
1099 child
= child
->next
;
1103 child
= child
->next
;
1107 child
->cdata
->flags
&= ~SEL_CDATA_STATICEVAL
;
1108 child
= child
->next
;
1112 /* Process the children */
1116 init_item_staticeval(child
);
1117 child
= child
->next
;
1122 /********************************************************************
1123 * EVALUATION GROUP INITIALIZATION
1124 ********************************************************************/
1127 * Initializes evaluation groups for root items.
1129 * \param[in,out] sc Selection collection data.
1131 * The evaluation group of each \ref SEL_ROOT element corresponding to a
1132 * selection in \p sc is set to \p gall. The same is done for \ref SEL_ROOT
1133 * elements corresponding to subexpressions that need full evaluation.
1136 initialize_evalgrps(gmx_ana_selcollection_t
*sc
)
1144 if (root
->child
->type
!= SEL_SUBEXPR
1145 || (root
->child
->cdata
->flags
& SEL_CDATA_FULLEVAL
))
1147 gmx_ana_index_set(&root
->u
.cgrp
, sc
->gall
.isize
, sc
->gall
.index
,
1148 root
->u
.cgrp
.name
, 0);
1155 /********************************************************************
1156 * STATIC ANALYSIS COMPILER PASS
1157 ********************************************************************/
1160 * Marks a subtree completely dynamic or undoes such a change.
1162 * \param sel Selection subtree to mark.
1163 * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
1164 * selection subtree is cleared. If FALSE, the flag is restored to
1165 * using \ref SEL_DYNAMIC.
1167 * Does not descend into parameters of methods unless the parameters
1168 * are evaluated for each atom.
1171 mark_subexpr_dynamic(t_selelem
*sel
, bool bDynamic
)
1175 if (!bDynamic
&& !(sel
->flags
& SEL_DYNAMIC
))
1177 sel
->cdata
->flags
|= SEL_CDATA_STATIC
;
1181 sel
->cdata
->flags
&= ~SEL_CDATA_STATIC
;
1186 if (sel
->type
!= SEL_EXPRESSION
|| child
->type
!= SEL_SUBEXPRREF
1187 || (child
->u
.param
->flags
& SPAR_ATOMVAL
))
1189 mark_subexpr_dynamic(child
, bDynamic
);
1191 child
= child
->next
;
1196 * Frees memory for subexpressions that are no longer needed.
1198 * \param sel Selection subtree to check.
1200 * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
1201 * elements that are not referred to by anything else except their own root
1202 * element. If such elements are found, all memory allocated for them is freed
1203 * except the actual element. The element is left because otherwise a dangling
1204 * pointer would be left at the root element, which is not traversed by this
1205 * function. Later compilation passes remove the stub elements.
1208 release_subexpr_memory(t_selelem
*sel
)
1215 release_subexpr_memory(child
);
1216 child
= child
->next
;
1219 if (sel
->type
== SEL_SUBEXPR
&& sel
->refcount
== 2)
1221 _gmx_selelem_free_values(sel
);
1222 _gmx_selelem_free_exprdata(sel
);
1223 _gmx_selelem_free_compiler_data(sel
);
1224 _gmx_selelem_free_chain(sel
->child
);
1230 * Makes an evaluated selection element static.
1232 * \param sel Selection element to make static.
1234 * The evaluated value becomes the value of the static element.
1235 * The element type is changed to SEL_CONST and the children are
1239 make_static(t_selelem
*sel
)
1241 /* Free the expression data as it is no longer needed */
1242 _gmx_selelem_free_exprdata(sel
);
1243 /* Make the item static */
1245 sel
->type
= SEL_CONST
;
1246 sel
->evaluate
= NULL
;
1247 sel
->cdata
->evaluate
= NULL
;
1248 /* Free the children */
1249 release_subexpr_memory(sel
);
1250 _gmx_selelem_free_chain(sel
->child
);
1252 /* Set the group value.
1253 * free_exprdata above frees the cgrp group, so we can just override it. */
1254 if (sel
->v
.type
== GROUP_VALUE
)
1256 gmx_ana_index_set(&sel
->u
.cgrp
, sel
->v
.u
.g
->isize
, sel
->v
.u
.g
->index
, NULL
, 0);
1261 * Evaluates a constant expression during analyze_static() and analyze_static2().
1263 * \param[in] data Evaluation data.
1264 * \param[in,out] sel Selection to process.
1265 * \param[in] g The evaluation group.
1266 * \returns 0 on success, a non-zero error code on error.
1269 process_const(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1274 if (sel
->v
.type
== GROUP_VALUE
)
1276 if (sel
->cdata
->evaluate
)
1278 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1281 /* Other constant expressions do not need evaluation */
1286 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1288 * \param[in,out] sel Selection to process.
1290 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1291 * and should receive the value from the compiler
1292 * (most parameter values are handled during parsing).
1293 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1294 * the function does nothing.
1295 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1296 * \ref SPAR_ATOMVAL, the function returns immediately.
1299 store_param_val(t_selelem
*sel
)
1301 /* Return immediately if there is no parameter. */
1302 if (sel
->type
!= SEL_SUBEXPRREF
|| !sel
->u
.param
)
1307 /* Or if the value does not need storing. */
1308 if (!(sel
->u
.param
->flags
& (SPAR_VARNUM
| SPAR_ATOMVAL
)))
1313 if (sel
->v
.type
== INT_VALUE
|| sel
->v
.type
== REAL_VALUE
1314 || sel
->v
.type
== STR_VALUE
)
1316 _gmx_selvalue_setstore(&sel
->u
.param
->val
, sel
->v
.u
.ptr
);
1321 * Handles the initialization of a selection method during analyze_static() pass.
1323 * \param[in,out] sel Selection element to process.
1324 * \param[in] top Topology structure.
1325 * \param[in] isize Size of the evaluation group for the element.
1326 * \returns 0 on success, a non-zero error code on return.
1328 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1330 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1331 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1334 init_method(t_selelem
*sel
, t_topology
*top
, int isize
)
1340 /* Find out whether there are any atom-valued parameters */
1345 if (child
->flags
& SEL_ATOMVAL
)
1349 child
= child
->next
;
1352 /* Initialize the method */
1353 if (sel
->u
.expr
.method
->init
1354 && (bAtomVal
|| !(sel
->flags
& SEL_METHODINIT
)))
1356 sel
->flags
|= SEL_METHODINIT
;
1357 /* The allocation flags are cleared first to not to free anything if
1358 * initialization fails. */
1360 if (sel
->type
== SEL_MODIFIER
&& sel
->v
.type
!= NO_VALUE
)
1362 child
= child
->next
;
1366 child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
1367 child
= child
->next
;
1369 rc
= sel
->u
.expr
.method
->init(top
, sel
->u
.expr
.method
->nparams
,
1370 sel
->u
.expr
.method
->param
, sel
->u
.expr
.mdata
);
1376 if (bAtomVal
|| !(sel
->flags
& SEL_OUTINIT
))
1378 sel
->flags
|= SEL_OUTINIT
;
1379 if (sel
->u
.expr
.method
->outinit
)
1381 rc
= sel
->u
.expr
.method
->outinit(top
, &sel
->v
, sel
->u
.expr
.mdata
);
1386 if (sel
->v
.type
!= POS_VALUE
&& sel
->v
.type
!= GROUP_VALUE
)
1388 alloc_selection_data(sel
, isize
, TRUE
);
1393 alloc_selection_data(sel
, isize
, TRUE
);
1394 if ((sel
->flags
& SEL_DYNAMIC
)
1395 && sel
->v
.type
!= GROUP_VALUE
&& sel
->v
.type
!= POS_VALUE
)
1399 /* If the method is char-valued, pre-allocate the strings. */
1400 if (sel
->u
.expr
.method
->flags
& SMETH_CHARVAL
)
1404 /* A sanity check */
1405 if (sel
->v
.type
!= STR_VALUE
)
1407 gmx_bug("internal error");
1410 sel
->flags
|= SEL_ALLOCDATA
;
1411 for (i
= 0; i
< isize
; ++i
)
1413 if (sel
->v
.u
.s
[i
] == NULL
)
1415 snew(sel
->v
.u
.s
[i
], 2);
1426 * Evaluates the static part of a boolean expression.
1428 * \param[in] data Evaluation data.
1429 * \param[in,out] sel Boolean selection element whose children should be
1431 * \param[in] g The evaluation group.
1432 * \returns 0 on success, a non-zero error code on error.
1434 * reorder_item_static_children() should have been called.
1437 evaluate_boolean_static_part(gmx_sel_evaluate_t
*data
, t_selelem
*sel
,
1440 t_selelem
*child
, *next
;
1443 /* Find the last static subexpression */
1445 while (child
->next
&& (child
->next
->cdata
->flags
& SEL_CDATA_STATIC
))
1447 child
= child
->next
;
1449 if (!(child
->cdata
->flags
& SEL_CDATA_STATIC
))
1454 /* Evalute the static part if there is more than one expression */
1455 if (child
!= sel
->child
)
1459 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1464 /* Replace the subexpressions with the result */
1465 _gmx_selelem_free_chain(sel
->child
);
1467 child
->type
= SEL_CONST
;
1468 child
->flags
= SEL_FLAGSSET
| SEL_SINGLEVAL
| SEL_ALLOCVAL
| SEL_ALLOCDATA
;
1469 _gmx_selelem_set_vtype(child
, GROUP_VALUE
);
1470 child
->evaluate
= NULL
;
1471 _gmx_selvalue_reserve(&child
->v
, 1);
1472 gmx_ana_index_copy(child
->v
.u
.g
, sel
->v
.u
.g
, TRUE
);
1473 init_item_compilerdata(child
);
1474 child
->cdata
->flags
&= ~SEL_CDATA_STATICEVAL
;
1475 child
->cdata
->flags
|= sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
;
1479 else if (child
->evaluate
)
1481 rc
= child
->evaluate(data
, child
, g
);
1487 /* Set the evaluation function for the constant element.
1488 * We never need to evaluate the element again during compilation,
1489 * but we may need to evaluate the static part again if the
1490 * expression is not an OR with a static evaluation group.
1491 * If we reach here with a NOT expression, the NOT expression
1492 * is also static, and will be made a constant later, so don't waste
1493 * time copying the group. */
1494 child
->evaluate
= NULL
;
1495 if (sel
->u
.boolt
== BOOL_NOT
1496 || ((sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
)
1497 && sel
->u
.boolt
== BOOL_OR
))
1499 child
->cdata
->evaluate
= NULL
;
1503 child
->cdata
->evaluate
= &_gmx_sel_evaluate_static
;
1504 /* The cgrp has only been allocated if it originated from an
1505 * external index group. In that case, we need special handling
1506 * to preserve the name of the group and to not leak memory.
1507 * If cgrp has been set in make_static(), it is not allocated,
1508 * and hence we can overwrite it safely. */
1509 if (child
->u
.cgrp
.nalloc_index
> 0)
1511 char *name
= child
->u
.cgrp
.name
;
1512 gmx_ana_index_copy(&child
->u
.cgrp
, child
->v
.u
.g
, FALSE
);
1513 gmx_ana_index_squeeze(&child
->u
.cgrp
);
1514 child
->u
.cgrp
.name
= name
;
1518 gmx_ana_index_copy(&child
->u
.cgrp
, child
->v
.u
.g
, TRUE
);
1525 * Evaluates the minimum and maximum groups for a boolean expression.
1527 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
1528 * \param[in] g Group for which \p sel has been evaluated.
1529 * \param[out] gmin Largest subset of the possible values of \p sel.
1530 * \param[out] gmax Smallest superset of the possible values of \p sel.
1532 * This is a helper function for analyze_static() that is called for
1533 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
1534 * It uses the minimum and maximum groups of the children to calculate
1535 * the minimum and maximum groups for \p sel, and also updates the static
1536 * part of \p sel (which is in the first child) if the children give
1539 * This function may allocate some extra memory for \p gmin and \p gmax,
1540 * but as these groups are freed at the end of analyze_static() (which is
1541 * reached shortly after this function returns), this should not be a major
1545 evaluate_boolean_minmax_grps(t_selelem
*sel
, gmx_ana_index_t
*g
,
1546 gmx_ana_index_t
*gmin
, gmx_ana_index_t
*gmax
)
1550 switch (sel
->u
.boolt
)
1553 gmx_ana_index_reserve(gmin
, g
->isize
);
1554 gmx_ana_index_reserve(gmax
, g
->isize
);
1555 gmx_ana_index_difference(gmax
, g
, sel
->child
->cdata
->gmin
);
1556 gmx_ana_index_difference(gmin
, g
, sel
->child
->cdata
->gmax
);
1560 gmx_ana_index_copy(gmin
, sel
->child
->cdata
->gmin
, TRUE
);
1561 gmx_ana_index_copy(gmax
, sel
->child
->cdata
->gmax
, TRUE
);
1562 child
= sel
->child
->next
;
1563 while (child
&& gmax
->isize
> 0)
1565 gmx_ana_index_intersection(gmin
, gmin
, child
->cdata
->gmin
);
1566 gmx_ana_index_intersection(gmax
, gmax
, child
->cdata
->gmax
);
1567 child
= child
->next
;
1569 /* Update the static part if other expressions limit it */
1570 if ((sel
->child
->cdata
->flags
& SEL_CDATA_STATIC
)
1571 && sel
->child
->v
.u
.g
->isize
> gmax
->isize
)
1573 gmx_ana_index_copy(sel
->child
->v
.u
.g
, gmax
, FALSE
);
1574 gmx_ana_index_squeeze(sel
->child
->v
.u
.g
);
1575 if (sel
->child
->u
.cgrp
.isize
> 0)
1577 gmx_ana_index_copy(&sel
->child
->u
.cgrp
, gmax
, FALSE
);
1578 gmx_ana_index_squeeze(&sel
->child
->u
.cgrp
);
1584 /* We can assume here that the gmin of children do not overlap
1585 * because of the way _gmx_sel_evaluate_or() works. */
1586 gmx_ana_index_reserve(gmin
, g
->isize
);
1587 gmx_ana_index_reserve(gmax
, g
->isize
);
1588 gmx_ana_index_copy(gmin
, sel
->child
->cdata
->gmin
, FALSE
);
1589 gmx_ana_index_copy(gmax
, sel
->child
->cdata
->gmax
, FALSE
);
1590 child
= sel
->child
->next
;
1591 while (child
&& gmin
->isize
< g
->isize
)
1593 gmx_ana_index_merge(gmin
, gmin
, child
->cdata
->gmin
);
1594 gmx_ana_index_union(gmax
, gmax
, child
->cdata
->gmax
);
1595 child
= child
->next
;
1597 /* Update the static part if other expressions have static parts
1598 * that are not included. */
1599 if ((sel
->child
->cdata
->flags
& SEL_CDATA_STATIC
)
1600 && sel
->child
->v
.u
.g
->isize
< gmin
->isize
)
1602 gmx_ana_index_reserve(sel
->child
->v
.u
.g
, gmin
->isize
);
1603 gmx_ana_index_copy(sel
->child
->v
.u
.g
, gmin
, FALSE
);
1604 if (sel
->child
->u
.cgrp
.isize
> 0)
1606 gmx_ana_index_reserve(&sel
->child
->u
.cgrp
, gmin
->isize
);
1607 gmx_ana_index_copy(&sel
->child
->u
.cgrp
, gmin
, FALSE
);
1612 case BOOL_XOR
: /* Should not be reached */
1613 gmx_impl("xor expressions not implemented");
1619 * Evaluates the static parts of \p sel and analyzes the structure.
1621 * \param[in] data Evaluation data.
1622 * \param[in,out] sel Selection currently being evaluated.
1623 * \param[in] g Group for which \p sel should be evaluated.
1624 * \returns 0 on success, a non-zero error code on error.
1626 * This function is used as the replacement for the \c t_selelem::evaluate
1628 * It does the single most complex task in the compiler: after all elements
1629 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
1630 * have been properly initialized, enough memory has been allocated for
1631 * storing the value of each expression, and the static parts of the
1632 * expressions have been evaluated.
1633 * The above is exactly true only for elements other than subexpressions:
1634 * another pass is required for subexpressions that are referred to more than
1635 * once to evaluate the static parts.
1636 * This second pass is performed by analyze_static2().
1638 * \see analyze_static2()
1641 analyze_static(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1643 t_selelem
*child
, *next
;
1644 gmx_ana_index_t gmin
, gmax
;
1648 gmx_ana_index_clear(&gmin
);
1649 gmx_ana_index_clear(&gmax
);
1650 bDelayAlloc
= FALSE
;
1652 if (sel
->type
!= SEL_ROOT
&& g
)
1654 bDelayAlloc
= !alloc_selection_data(sel
, g
->isize
, FALSE
);
1657 /* TODO: This switch is awfully long... */
1662 rc
= process_const(data
, sel
, g
);
1665 case SEL_EXPRESSION
:
1667 rc
= _gmx_sel_evaluate_method_params(data
, sel
, g
);
1672 rc
= init_method(sel
, data
->top
, g
->isize
);
1677 if (!(sel
->flags
& SEL_DYNAMIC
))
1679 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1680 if (rc
== 0 && (sel
->cdata
->flags
& SEL_CDATA_STATIC
))
1687 /* Modifiers need to be evaluated even though they process
1688 * positions to get the modified output groups from the
1689 * maximum possible selections. */
1690 if (sel
->type
== SEL_MODIFIER
)
1692 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1694 gmx_ana_index_copy(&gmax
, g
, TRUE
);
1699 if (!(sel
->flags
& SEL_DYNAMIC
))
1701 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1702 if (rc
== 0 && (sel
->cdata
->flags
& SEL_CDATA_STATIC
))
1709 /* Evalute the static part if there is more than one expression */
1710 rc
= evaluate_boolean_static_part(data
, sel
, g
);
1716 /* Evaluate the selection.
1717 * If the type is boolean, we must explicitly handle the
1718 * static part evaluated in evaluate_boolean_static_part()
1719 * here because g may be larger. */
1720 if (sel
->u
.boolt
== BOOL_AND
&& sel
->child
->type
== SEL_CONST
)
1722 rc
= sel
->cdata
->evaluate(data
, sel
, sel
->child
->v
.u
.g
);
1726 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1733 /* Evaluate minimal and maximal selections */
1734 evaluate_boolean_minmax_grps(sel
, g
, &gmin
, &gmax
);
1738 case SEL_ARITHMETIC
:
1739 if (!(sel
->flags
& SEL_DYNAMIC
))
1741 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1742 if (rc
== 0 && (sel
->cdata
->flags
& SEL_CDATA_STATIC
))
1749 rc
= _gmx_sel_evaluate_children(data
, sel
, g
);
1754 gmx_ana_index_copy(&gmax
, g
, TRUE
);
1759 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1763 if (sel
->u
.cgrp
.isize
== 0)
1765 gmx_ana_index_reserve(&sel
->u
.cgrp
, g
->isize
);
1768 /* We need to evaluate the child before we can allocate the
1770 rc
= sel
->child
->evaluate(data
, sel
->child
, g
);
1775 alloc_selection_data(sel
, g
->isize
, TRUE
);
1776 /* Do not evaluate the child again */
1777 sel
->child
->evaluate
= NULL
;
1778 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1779 sel
->child
->evaluate
= &analyze_static
;
1783 alloc_selection_data(sel
->child
, g
->isize
, FALSE
);
1784 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1789 int isize
= gmx_ana_index_difference_size(g
, &sel
->u
.cgrp
);
1792 isize
+= sel
->u
.cgrp
.isize
;
1793 gmx_ana_index_reserve(&sel
->u
.cgrp
, isize
);
1794 if (sel
->v
.type
== GROUP_VALUE
|| (sel
->flags
& SEL_ATOMVAL
))
1796 alloc_selection_data(sel
->child
, isize
, FALSE
);
1797 alloc_selection_data(sel
, isize
, FALSE
);
1799 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1803 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1808 case SEL_SUBEXPRREF
:
1809 /* The subexpression should have been evaluated if g is NULL
1810 * (i.e., this is a method parameter or a direct value of a
1814 alloc_selection_data(sel
, sel
->child
->cdata
->gmax
->isize
, TRUE
);
1816 /* TODO: This is not general enough if/when position references
1817 * can be evaluated more than once (that is, if there are position
1818 * methods that do not have SMETH_SINGLEVAL or SMETH_VARNUMVAL). */
1819 if (sel
->v
.type
== POS_VALUE
&& !(sel
->flags
& SEL_OUTINIT
))
1821 gmx_ana_pos_copy(sel
->v
.u
.p
, sel
->child
->child
->v
.u
.p
, TRUE
);
1822 sel
->flags
|= SEL_OUTINIT
;
1824 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1829 /* Store the parameter value if required */
1830 store_param_val(sel
);
1831 if (!(sel
->flags
& SEL_DYNAMIC
))
1833 if (sel
->cdata
->flags
& SEL_CDATA_STATIC
)
1840 if (sel
->child
->refcount
<= 2 || !g
)
1842 gmx_ana_index_copy(&gmin
, sel
->child
->cdata
->gmin
, TRUE
);
1843 gmx_ana_index_copy(&gmax
, sel
->child
->cdata
->gmax
, TRUE
);
1847 gmx_ana_index_reserve(&gmin
, min(g
->isize
, sel
->child
->cdata
->gmin
->isize
));
1848 gmx_ana_index_reserve(&gmax
, min(g
->isize
, sel
->child
->cdata
->gmax
->isize
));
1849 gmx_ana_index_intersection(&gmin
, sel
->child
->cdata
->gmin
, g
);
1850 gmx_ana_index_intersection(&gmax
, sel
->child
->cdata
->gmax
, g
);
1855 /* Exit if there was some problem */
1861 /* Update the minimal and maximal evaluation groups */
1862 if (sel
->cdata
->flags
& SEL_CDATA_MINMAXALLOC
)
1864 gmx_ana_index_reserve(sel
->cdata
->gmin
, sel
->cdata
->gmin
->isize
+ gmin
.isize
);
1865 gmx_ana_index_reserve(sel
->cdata
->gmax
, sel
->cdata
->gmax
->isize
+ gmax
.isize
);
1866 gmx_ana_index_merge(sel
->cdata
->gmin
, sel
->cdata
->gmin
, &gmin
);
1867 gmx_ana_index_merge(sel
->cdata
->gmax
, sel
->cdata
->gmax
, &gmax
);
1869 /* Replace the result of the evaluation */
1870 /* This is not necessary for subexpressions or for boolean negations
1871 * because the evaluation function already has done it properly. */
1872 if (sel
->v
.type
== GROUP_VALUE
&& (sel
->flags
& SEL_DYNAMIC
)
1873 && sel
->type
!= SEL_SUBEXPR
1874 && !(sel
->type
== SEL_BOOLEAN
&& sel
->u
.boolt
== BOOL_NOT
))
1876 if (sel
->cdata
->flags
& SEL_CDATA_EVALMAX
)
1878 gmx_ana_index_copy(sel
->v
.u
.g
, &gmax
, FALSE
);
1882 gmx_ana_index_copy(sel
->v
.u
.g
, &gmin
, FALSE
);
1885 gmx_ana_index_deinit(&gmin
);
1886 gmx_ana_index_deinit(&gmax
);
1888 /* Make sure that enough data storage has been allocated */
1889 /* TODO: Constant expressions could be handled here more intelligently */
1890 if (sel
->type
!= SEL_ROOT
&& (sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
))
1892 alloc_selection_data(sel
, sel
->cdata
->gmax
->isize
, TRUE
);
1893 /* Make sure that the new value pointer is stored if required */
1894 store_param_val(sel
);
1901 * Evaluates the static parts of \p sel and analyzes the structure.
1903 * \param[in] data Evaluation data.
1904 * \param[in,out] sel Selection currently being evaluated.
1905 * \param[in] g Group for which \p sel should be evaluated.
1906 * \returns 0 on success, a non-zero error code on error.
1908 * This function is a simpler version of analyze_static() that is used
1909 * during a second evaluation round, and can thus use information calculated
1910 * by analyze_static().
1911 * It is also used as the replacement for the \c t_selelem::evaluate
1913 * It is used to evaluate the static parts of subexpressions that could not
1914 * be evaluated during the analyze_static() pass.
1916 * \see analyze_static()
1919 analyze_static2(gmx_sel_evaluate_t
*data
, t_selelem
*sel
, gmx_ana_index_t
*g
)
1927 rc
= process_const(data
, sel
, g
);
1930 case SEL_EXPRESSION
:
1932 case SEL_SUBEXPRREF
:
1933 case SEL_ARITHMETIC
:
1934 if (sel
->cdata
->flags
& SEL_CDATA_STATIC
)
1936 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1942 else if (sel
->type
== SEL_BOOLEAN
)
1944 rc
= evaluate_boolean_static_part(data
, sel
, g
);
1947 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1952 case SEL_ROOT
: /* Roots should not be present here */
1953 case SEL_MODIFIER
: /* Modifiers should not be present here */
1955 rc
= sel
->cdata
->evaluate(data
, sel
, g
);
1958 /* Exit if there was some problem */
1964 /* Replace the result of the evaluation */
1965 /* This is not necessary for subexpressions or for boolean negations
1966 * because the evaluation function already has done it properly. */
1967 if (sel
->v
.type
== GROUP_VALUE
&& !(sel
->cdata
->flags
& SEL_CDATA_STATIC
)
1968 && sel
->type
!= SEL_SUBEXPR
1969 && !(sel
->type
== SEL_BOOLEAN
&& sel
->u
.boolt
== BOOL_NOT
))
1971 if (sel
->cdata
->flags
& SEL_CDATA_EVALMAX
)
1973 gmx_ana_index_copy(sel
->v
.u
.g
, sel
->cdata
->gmax
, FALSE
);
1977 gmx_ana_index_copy(sel
->v
.u
.g
, sel
->cdata
->gmin
, FALSE
);
1985 /********************************************************************
1986 * ROOT ITEM INITIALIZATION COMPILER PASS
1987 ********************************************************************/
1990 * Initializes a \ref SEL_ROOT element.
1992 * \param root Root element to initialize.
1993 * \param[in] gall Group of all atoms.
1994 * \returns Pointer to the selection element that should replace \p root.
1995 * Can be \p root itself or NULL if the selection should be removed.
1997 * Checks whether it is necessary to evaluate anything through the root
1998 * element, and either clears the evaluation function or initializes the
2001 * If the function returns NULL, the memory allocated for \p root is
2002 * automatically freed.
2005 init_root_item(t_selelem
*root
, gmx_ana_index_t
*gall
)
2010 /* Process subexpressions */
2011 if (root
->child
->type
== SEL_SUBEXPR
)
2013 if (root
->child
->refcount
== 1)
2015 /* Free subexpressions that are no longer used */
2016 _gmx_selelem_free(root
);
2019 else if (root
->child
->v
.type
== POS_VALUE
)
2021 /* Position values only need to be evaluated once, by the root */
2023 else if (!(root
->child
->cdata
->flags
& SEL_CDATA_STATICEVAL
))
2025 /* Subexpressions with non-static evaluation group should not be
2026 * evaluated by the root. */
2027 root
->evaluate
= NULL
;
2030 root
->cdata
->evaluate
= NULL
;
2035 /* Set the evaluation group */
2036 name
= root
->u
.cgrp
.name
;
2040 /* Non-atom-valued non-group expressions don't care about the group, so
2041 * don't allocate any memory for it. */
2042 if ((expr
->flags
& SEL_VARNUMVAL
)
2043 || ((expr
->flags
& SEL_SINGLEVAL
) && expr
->type
!= GROUP_VALUE
))
2045 gmx_ana_index_set(&root
->u
.cgrp
, -1, NULL
, NULL
, 0);
2047 else if (expr
->cdata
->gmax
->isize
== gall
->isize
)
2049 /* Save some memory by only referring to the global group. */
2050 gmx_ana_index_set(&root
->u
.cgrp
, gall
->isize
, gall
->index
, NULL
, 0);
2054 gmx_ana_index_copy(&root
->u
.cgrp
, expr
->cdata
->gmax
, TRUE
);
2056 /* For selections, store the maximum group for
2057 * gmx_ana_selcollection_evaluate_fin() as the value of the root
2058 * element (unused otherwise). */
2059 if (expr
->type
!= SEL_SUBEXPR
&& expr
->v
.u
.p
->g
)
2061 _gmx_selelem_set_vtype(root
, GROUP_VALUE
);
2062 root
->flags
|= (SEL_ALLOCVAL
| SEL_ALLOCDATA
);
2063 _gmx_selvalue_reserve(&root
->v
, 1);
2064 gmx_ana_index_copy(root
->v
.u
.g
, expr
->v
.u
.p
->g
, TRUE
);
2069 gmx_ana_index_clear(&root
->u
.cgrp
);
2071 root
->u
.cgrp
.name
= name
;
2076 * Reverses the chain of selection elements starting at \p root.
2078 * \param root First selection in the whole selection chain.
2079 * \returns The new first element for the chain.
2082 reverse_selelem_chain(t_selelem
*root
)
2101 * Initializes the evaluation groups for \ref SEL_ROOT items.
2103 * \param root First selection in the whole selection chain.
2104 * \param[in] gall Group of all atoms.
2105 * \returns The new first element for the chain.
2107 * The function also removes static subexpressions that are no longer used.
2108 * The elements are processed in reverse order to correctly detect static
2109 * subexpressions referred to by other static subexpressions. All other
2110 * processing is independent of the order of the elements.
2113 process_roots(t_selelem
*root
, gmx_ana_index_t
*gall
)
2118 root
= reverse_selelem_chain(root
);
2122 root
= init_root_item(root
, gall
);
2128 while (root
== next
);
2130 while (item
&& item
->next
)
2132 next
= item
->next
->next
;
2133 item
->next
= init_root_item(item
->next
, gall
);
2143 return reverse_selelem_chain(root
);
2147 /********************************************************************
2148 * SUBEXPRESSION OPTIMIZATION PASS
2149 ********************************************************************/
2152 * Optimizes subexpression evaluation.
2154 * \param sel Root of the selection subtree to process.
2156 * Optimizes away some unnecessary evaluation of subexpressions that are only
2160 optimize_item_subexpressions(t_selelem
*sel
)
2164 /* Call recursively for all children unless the children have already been processed */
2165 if (sel
->type
!= SEL_SUBEXPRREF
)
2170 optimize_item_subexpressions(child
);
2171 child
= child
->next
;
2175 /* Optimize the evaluation of subexpressions that are used only once */
2176 if (sel
->type
== SEL_SUBEXPRREF
&& (sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
)
2177 && sel
->child
->refcount
== 2)
2179 /* The evaluation functions are not always needed, and they do some
2180 * extra work, but it should be neglible compared to other factors
2181 * in the evaluation, so set them always for simplicity. */
2182 sel
->evaluate
= &_gmx_sel_evaluate_subexprref_pass
;
2185 sel
->cdata
->evaluate
= sel
->evaluate
;
2187 /* Replace the value of the child */
2188 _gmx_selelem_free_values(sel
->child
);
2189 sel
->child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
2190 _gmx_selvalue_setstore(&sel
->child
->v
, sel
->v
.u
.ptr
);
2191 sel
->child
->evaluate
= &_gmx_sel_evaluate_subexpr_pass
;
2192 if (sel
->child
->cdata
)
2194 sel
->child
->cdata
->evaluate
= sel
->child
->evaluate
;
2196 /* Replace the value of the grandchild */
2197 _gmx_selelem_free_values(sel
->child
->child
);
2198 sel
->child
->child
->flags
&= ~(SEL_ALLOCVAL
| SEL_ALLOCDATA
);
2199 _gmx_selvalue_setstore(&sel
->child
->child
->v
, sel
->v
.u
.ptr
);
2204 /********************************************************************
2205 * COM CALCULATION COMPILER PASS
2206 ********************************************************************/
2209 * Initializes COM/COG calculation for method expressions that require it.
2211 * \param sel Selection subtree to process.
2212 * \param[in,out] pcc Position calculation collection to use.
2213 * \param[in] type Default position calculation type.
2214 * \param[in] flags Flags for default position calculation.
2215 * \returns 0 on success, a non-zero error code on error.
2217 * Searches recursively through the selection tree for dynamic
2218 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
2220 * For each such element found, position calculation is initialized
2221 * for the maximal evaluation group.
2222 * The type of the calculation is determined by \p type and \p flags.
2223 * No calculation is initialized if \p type equals \ref POS_ATOM and
2224 * the method also defines the \c gmx_ana_selmethod_t::update method.
2227 init_item_comg(t_selelem
*sel
, gmx_ana_poscalc_coll_t
*pcc
,
2228 e_poscalc_t type
, int flags
)
2233 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
2234 if (sel
->type
== SEL_EXPRESSION
&& sel
->u
.expr
.method
2235 && sel
->u
.expr
.method
->pupdate
)
2237 if (!sel
->u
.expr
.method
->update
|| type
!= POS_ATOM
)
2239 /* Create a default calculation if one does not yet exist */
2242 if (!(sel
->cdata
->flags
& SEL_CDATA_STATICEVAL
))
2244 cflags
|= POS_DYNAMIC
;
2246 if (!sel
->u
.expr
.pc
)
2249 rc
= gmx_ana_poscalc_create(&sel
->u
.expr
.pc
, pcc
, type
, cflags
);
2257 gmx_ana_poscalc_set_flags(sel
->u
.expr
.pc
, cflags
);
2259 gmx_ana_poscalc_set_maxindex(sel
->u
.expr
.pc
, sel
->cdata
->gmax
);
2260 snew(sel
->u
.expr
.pos
, 1);
2261 gmx_ana_poscalc_init_pos(sel
->u
.expr
.pc
, sel
->u
.expr
.pos
);
2265 /* Call recursively for all children unless the children have already been processed */
2266 if (sel
->type
!= SEL_SUBEXPRREF
)
2271 rc
= init_item_comg(child
, pcc
, type
, flags
);
2276 child
= child
->next
;
2283 /********************************************************************
2284 * FREE COMPILER DATA PASS
2285 ********************************************************************/
2288 * Frees the allocated compiler data recursively.
2290 * \param sel Root of the selection subtree to process.
2292 * Frees the data allocated for the compilation process.
2295 free_item_compilerdata(t_selelem
*sel
)
2299 /* Free compilation data */
2300 _gmx_selelem_free_compiler_data(sel
);
2302 /* Call recursively for all children unless the children have already been processed */
2303 if (sel
->type
!= SEL_SUBEXPRREF
)
2308 free_item_compilerdata(child
);
2309 child
= child
->next
;
2315 /********************************************************************
2316 * INFORMATION UPDATE
2317 ********************************************************************/
2320 * Updates the information about the selection.
2322 * \param[in] top Topology information.
2323 * \param[in] ngrps Number of elements in the \p sel array.
2324 * \param[in,out] sel Array of selections to update.
2325 * \param[in] bMaskOnly TRUE if the positions will always be calculated
2326 * for all atoms, i.e., the masses/charges do not change.
2328 * Initializes total masses and charges.
2331 update_info(t_topology
*top
, int ngrps
, gmx_ana_selection_t
*sel
[],
2336 for (g
= 0; g
< ngrps
; ++g
)
2338 sel
[g
]->g
= sel
[g
]->p
.g
;
2339 snew(sel
[g
]->orgm
, sel
[g
]->p
.nr
);
2340 snew(sel
[g
]->orgq
, sel
[g
]->p
.nr
);
2341 for (b
= 0; b
< sel
[g
]->p
.nr
; ++b
)
2343 sel
[g
]->orgq
[b
] = 0;
2346 sel
[g
]->orgm
[b
] = 0;
2347 for (i
= sel
[g
]->p
.m
.mapb
.index
[b
]; i
< sel
[g
]->p
.m
.mapb
.index
[b
+1]; ++i
)
2349 sel
[g
]->orgm
[b
] += top
->atoms
.atom
[sel
[g
]->g
->index
[i
]].m
;
2350 sel
[g
]->orgq
[b
] += top
->atoms
.atom
[sel
[g
]->g
->index
[i
]].q
;
2355 sel
[g
]->orgm
[b
] = 1;
2358 if (sel
[g
]->bDynamic
&& !bMaskOnly
)
2360 snew(sel
[g
]->m
, sel
[g
]->p
.nr
);
2361 snew(sel
[g
]->q
, sel
[g
]->p
.nr
);
2362 for (b
= 0; b
< sel
[g
]->p
.nr
; ++b
)
2364 sel
[g
]->m
[b
] = sel
[g
]->orgm
[b
];
2365 sel
[g
]->q
[b
] = sel
[g
]->orgq
[b
];
2370 sel
[g
]->m
= sel
[g
]->orgm
;
2371 sel
[g
]->q
= sel
[g
]->orgq
;
2377 /********************************************************************
2378 * MAIN COMPILATION FUNCTION
2379 ********************************************************************/
2382 * \param[in,out] sc Selection collection to be compiled.
2383 * \returns 0 on successful compilation, a non-zero error code on error.
2385 * Before compilation, the selection collection should have been initialized
2386 * with gmx_ana_selcollection_parse_*().
2387 * The compiled selection collection can be passed to
2388 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2389 * If an error occurs, \p sc is cleared.
2391 * The covered fraction information in \p sc is initialized to
2395 gmx_ana_selcollection_compile(gmx_ana_selcollection_t
*sc
)
2397 gmx_sel_evaluate_t evaldata
;
2403 _gmx_sel_evaluate_init(&evaldata
, &sc
->gall
, sc
->top
, NULL
, NULL
);
2405 /* Clear the symbol table because it is not possible to parse anything
2406 * after compilation, and variable references in the symbol table can
2407 * also mess up the compilation and/or become invalid.
2409 _gmx_selcollection_clear_symtab(sc
);
2411 /* Extract subexpressions into separate roots */
2412 sc
->root
= extract_subexpressions(sc
->root
, &sc
->gall
);
2414 /* Initialize the evaluation callbacks and process the tree structure
2415 * to conform to the expectations of the callback functions. */
2416 /* Also, initialize and allocate the compiler data structure */
2420 /* Process boolean and arithmetic expressions. */
2421 optimize_boolean_expressions(item
);
2422 reorder_boolean_static_children(item
);
2423 if (!optimize_arithmetic_expressions(item
))
2425 /* FIXME: Clean up the collection */
2428 /* Initialize evaluation */
2429 if (!init_item_evaluation(item
))
2431 /* FIXME: Clean up the collection */
2434 /* Initialize the compiler data */
2435 init_item_compilerdata(item
);
2436 init_item_staticeval(item
);
2439 /* Initialize the evaluation index groups */
2440 initialize_evalgrps(sc
);
2442 /* Evaluate all static parts of the selection and analyze the tree
2443 * to allocate enough memory to store the value of each dynamic subtree. */
2447 if (item
->child
->type
== SEL_SUBEXPR
&& item
->child
->refcount
> 2)
2449 mark_subexpr_dynamic(item
->child
, TRUE
);
2451 set_evaluation_function(item
, &analyze_static
);
2452 rc
= item
->evaluate(&evaldata
, item
, NULL
);
2455 /* FIXME: Clean up the collection */
2461 /* Do a second pass to evaluate static parts of common subexpressions */
2462 /* Note that the refcount check skips constant subexpressions completely
2463 * since they were already evaluated by analyze_static(). */
2467 if (item
->child
->type
== SEL_SUBEXPR
&& item
->child
->refcount
> 2)
2469 mark_subexpr_dynamic(item
->child
, FALSE
);
2470 item
->child
->u
.cgrp
.isize
= 0;
2471 /* We won't clear item->child->child->v.u.g here, because it may
2472 * be static, and hence actually point to item->child->cdata->gmax,
2473 * which is used below. We could also check whether this is the
2474 * case and only clear the group otherwise, but because the value
2475 * is actually overwritten immediately in the evaluate call, we
2476 * won't, because similar problems may arise if gmax handling ever
2477 * changes and the check were not updated. */
2478 set_evaluation_function(item
, &analyze_static2
);
2479 rc
= item
->evaluate(&evaldata
, item
->child
, item
->child
->cdata
->gmax
);
2482 /* FIXME: Clean up the collection */
2489 /* Initialize evaluation groups and remove unused subexpressions. */
2490 sc
->root
= process_roots(sc
->root
, &sc
->gall
);
2492 /* Initialize position calculations for methods, perform some final
2493 * optimization and free the memory allocated for the compilation. */
2494 /* By default, use whole residues/molecules. */
2495 flags
= POS_COMPLWHOLE
;
2496 rc
= gmx_ana_poscalc_type_from_enum(sc
->rpost
, &post
, &flags
);
2499 gmx_bug("invalid default reference position type");
2500 /* FIXME: Clean up the collection */
2506 optimize_item_subexpressions(item
);
2507 rc
= init_item_comg(item
, sc
->pcc
, post
, flags
);
2510 /* FIXME: Clean up the collection */
2513 free_item_compilerdata(item
);
2517 /* Finish up by updating some information */
2518 update_info(sc
->top
, sc
->nr
, sc
->sel
, sc
->bMaskOnly
);