Simpler special case subexpression handling.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / selection / compiler.c
blob63d10f823802dba08dc2f97cc18d31808e3d46b6
1 /*
3 * This source code is part of
5 * G R O M A C S
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
31 /*! \internal \file
32 * \brief Selection compilation and optimization.
34 * \todo
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.
41 * \todo
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
48 * evaluation.
50 /*! \internal
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
60 * called.
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
76 * \c t_selelem tree.
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
81 * here.
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.
92 * .
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.
128 * \todo
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
222 * help in debugging.
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.
248 #ifdef HAVE_CONFIG_H
249 #include <config.h>
250 #endif
252 #include <math.h>
253 #include <stdarg.h>
255 #include <smalloc.h>
256 #include <string2.h>
257 #include <vec.h>
259 #include <indexutil.h>
260 #include <poscalc.h>
261 #include <selection.h>
262 #include <selmethod.h>
264 #include "evaluate.h"
265 #include "keywords.h"
266 #include "selcollection.h"
267 #include "selelem.h"
269 /*! \internal \brief
270 * Compiler flags.
272 enum
274 /*! \brief
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,
282 /*! \brief
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,
297 /*! \internal \brief
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. */
305 int flags;
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;
310 } t_compiler_data;
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.
324 void
325 _gmx_selelem_free_compiler_data(t_selelem *sel)
327 if (sel->cdata)
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);
339 sfree(sel->cdata);
341 sel->cdata = NULL;
344 /*! \brief
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.
356 static bool
357 alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
359 int nalloc;
361 /* Find out the number of elements to allocate */
362 if (sel->flags & SEL_SINGLEVAL)
364 nalloc = 1;
366 else if (sel->flags & SEL_ATOMVAL)
368 nalloc = isize;
370 else /* sel->flags should contain SEL_VARNUMVAL */
372 t_selelem *child;
374 if (!bChildEval)
376 return FALSE;
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)
389 isize = nalloc;
390 nalloc = 1;
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);
412 return TRUE;
415 /*! \brief
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.
421 static void
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;
428 while (child)
430 set_evaluation_function(child, eval);
431 child = child->next;
436 /********************************************************************
437 * SUBEXPRESSION EXTRACTION COMPILER PASS
438 ********************************************************************/
440 /*! \brief
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().
451 static void
452 create_subexpression_name(t_selelem *sel, int i)
454 int len, ret;
455 char *name;
457 len = 8 + (int)log10(abs(i)) + 3;
458 snew(name, len+1);
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)
465 sfree(name);
466 name = NULL;
468 sel->name = name;
469 sel->u.cgrp.name = name;
472 /*! \brief
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.
486 static t_selelem *
487 extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
489 t_selelem *root;
490 t_selelem *subexpr;
491 t_selelem *child;
493 root = subexpr = NULL;
494 child = sel->child;
495 while (child)
497 if (!root)
499 root = subexpr = extract_item_subselections(child, gall, subexprn);
501 else
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
512 * encountered.
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 */
520 if (!root)
522 root = subexpr = _gmx_selelem_create(SEL_ROOT);
524 else
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;
538 else
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);
548 child = child->next;
551 return root;
554 /*! \brief
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
563 * elements for them.
564 * \ref SEL_ROOT elements are also created for each subexpression
565 * and inserted into the selection chain before the expressions that
566 * refer to them.
568 static t_selelem *
569 extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
571 t_selelem *root, *item, *next;
572 int subexprn;
574 subexprn = 0;
575 root = NULL;
576 next = sel;
577 while (next)
579 item = extract_item_subselections(next, gall, &subexprn);
580 if (item)
582 if (!root)
584 root = item;
586 else
588 sel->next = item;
590 while (item->next)
592 item = item->next;
594 item->next = next;
596 else if (!root)
598 root = next;
600 sel = next;
601 next = next->next;
603 return root;
606 /********************************************************************
607 * BOOLEAN OPERATION REORDERING COMPILER PASS
608 ********************************************************************/
610 /*! \brief
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).
618 static void
619 optimize_boolean_expressions(t_selelem *sel)
621 t_selelem *child, *prev;
623 /* Do recursively for children */
624 if (sel->type != SEL_SUBEXPRREF)
626 prev = NULL;
627 child = sel->child;
628 while (child)
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 */
636 if (!prev)
638 sel->child = child->child->child;
639 prev = sel->child;
641 else
643 prev->next = child->child->child;
644 prev = prev->next;
646 child->child->child->next = child->next;
647 /* Remove the two negations */
648 child->child->child = NULL;
649 child->next = NULL;
650 _gmx_selelem_free(child);
651 child = prev;
653 prev = child;
654 child = child->next;
657 if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
659 return;
661 /* Merge subsequent binary operations */
662 prev = NULL;
663 child = sel->child;
664 while (child)
666 if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
668 if (!prev)
670 sel->child = child->child;
671 prev = sel->child;
673 else
675 prev->next = child->child;
677 while (prev->next)
679 prev = prev->next;
681 prev->next = child->next;
682 sfree(child->v.u.g);
683 sfree(child);
684 child = prev->next;
686 else
688 prev = child;
689 child = child->next;
694 /*! \brief
695 * Reorders children of boolean expressions such that static selections
696 * come first.
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.
703 static void
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)
711 child = sel->child;
712 while (child)
714 reorder_boolean_static_children(child);
715 child = child->next;
719 /* Reorder boolean expressions such that static selections come first */
720 if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
722 t_selelem start;
724 start.next = sel->child;
725 prev = &start;
726 child = &start;
727 while (child->next)
729 /* child is the last handled static expression */
730 /* prev is the last handled non-static expression */
731 next = prev->next;
732 while (next && (next->flags & SEL_DYNAMIC))
734 prev = next;
735 next = next->next;
737 /* next is now the first static expression after child */
738 if (!next)
740 break;
742 /* Reorder such that next comes after child */
743 if (prev != child)
745 prev->next = next->next;
746 next->next = child->next;
747 child->next = next;
749 else
751 prev = prev->next;
753 /* Advance child by one */
754 child = next;
757 sel->child = start.next;
761 /********************************************************************
762 * ARITHMETIC EXPRESSION PROCESSING
763 ********************************************************************/
765 /*! \brief
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.
773 static bool
774 optimize_arithmetic_expressions(t_selelem *sel)
776 t_selelem *child;
777 bool bOk;
779 /* Do recursively for children. */
780 if (sel->type != SEL_SUBEXPRREF)
782 child = sel->child;
783 while (child)
785 bOk = optimize_arithmetic_expressions(child);
786 if (!bOk)
788 return bOk;
790 child = child->next;
794 if (sel->type != SEL_ARITHMETIC)
796 return TRUE;
799 /* Convert integer constants to reals. */
800 child = sel->child;
801 while (child)
803 if (child->v.type == INT_VALUE)
805 real *r;
807 if (child->type != SEL_CONST)
809 gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
810 return FALSE;
812 snew(r, 1);
813 r[0] = child->v.u.i[0];
814 sfree(child->v.u.i);
815 child->v.u.r = r;
816 child->v.type = REAL_VALUE;
818 else if (child->v.type != REAL_VALUE)
820 gmx_bug("Internal error");
821 return FALSE;
823 child = child->next;
825 return TRUE;
828 /********************************************************************
829 * EVALUATION PREPARATION COMPILER PASS
830 ********************************************************************/
832 /*! \brief
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.
843 static bool
844 init_item_evaluation(t_selelem *sel)
846 t_selelem *child;
848 /* Process children */
849 if (sel->type != SEL_SUBEXPRREF)
851 child = sel->child;
852 while (child)
854 if (!init_item_evaluation(child))
856 return FALSE;
858 child = child->next;
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);
868 sel->v.nr = 1;
872 /* Set the evaluation function */
873 switch (sel->type)
875 case SEL_CONST:
876 if (sel->v.type == GROUP_VALUE)
878 sel->evaluate = &_gmx_sel_evaluate_static;
880 break;
882 case SEL_EXPRESSION:
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;
889 break;
891 case SEL_ARITHMETIC:
892 sel->evaluate = &_gmx_sel_evaluate_arithmetic;
893 break;
895 case SEL_MODIFIER:
896 if (sel->v.type != NO_VALUE)
898 sel->evaluate = &_gmx_sel_evaluate_modifier;
900 break;
902 case SEL_BOOLEAN:
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;
908 case BOOL_XOR:
909 gmx_impl("xor expressions not implemented");
910 return FALSE;
912 break;
914 case SEL_ROOT:
915 sel->evaluate = &_gmx_sel_evaluate_root;
916 break;
918 case SEL_SUBEXPR:
919 sel->evaluate = &_gmx_sel_evaluate_subexpr;
920 break;
922 case SEL_SUBEXPRREF:
923 sel->name = sel->child->name;
924 sel->evaluate = &_gmx_sel_evaluate_subexprref;
925 break;
928 return TRUE;
932 /********************************************************************
933 * COMPILER DATA INITIALIZATION PASS
934 ********************************************************************/
936 /*! \brief
937 * Allocates memory for the compiler data and initializes the structure.
939 * \param sel Root of the selection subtree to process.
941 static void
942 init_item_compilerdata(t_selelem *sel)
944 t_selelem *child;
946 /* Allocate the compiler data structure */
947 snew(sel->cdata, 1);
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)
967 child = sel->child;
968 while (child)
970 if (!(child->flags & SEL_ATOMVAL))
972 child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
974 child = child->next;
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)
985 child = sel->child;
986 while (child)
988 init_item_compilerdata(child);
989 child = child->next;
993 /* Determine whether we should evaluate the minimum or the maximum
994 * for the children of this element. */
995 if (sel->type == SEL_BOOLEAN)
997 bool bEvalMax;
999 bEvalMax = (sel->u.boolt == BOOL_AND);
1000 child = sel->child;
1001 while (child)
1003 if (bEvalMax)
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)
1017 child = sel->child;
1018 while (child)
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;
1039 else
1041 sel->cdata->flags |= SEL_CDATA_MINMAXALLOC;
1042 snew(sel->cdata->gmin, 1);
1043 snew(sel->cdata->gmax, 1);
1048 /*! \brief
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.
1059 static void
1060 init_item_staticeval(t_selelem *sel)
1062 t_selelem *child;
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))
1069 return;
1072 /* Propagate the bStaticEval flag to children if it is not set */
1073 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
1075 child = sel->child;
1076 while (child)
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)
1096 child = sel->child;
1097 while (child && !(child->flags & SEL_DYNAMIC))
1099 child = child->next;
1101 if (child)
1103 child = child->next;
1105 while (child)
1107 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1108 child = child->next;
1112 /* Process the children */
1113 child = sel->child;
1114 while (child)
1116 init_item_staticeval(child);
1117 child = child->next;
1122 /********************************************************************
1123 * EVALUATION GROUP INITIALIZATION
1124 ********************************************************************/
1126 /*! \brief
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.
1135 static void
1136 initialize_evalgrps(gmx_ana_selcollection_t *sc)
1138 t_selelem *root;
1139 int i;
1141 root = sc->root;
1142 while (root)
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);
1150 root = root->next;
1155 /********************************************************************
1156 * STATIC ANALYSIS COMPILER PASS
1157 ********************************************************************/
1159 /*! \brief
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.
1170 static void
1171 mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
1173 t_selelem *child;
1175 if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
1177 sel->cdata->flags |= SEL_CDATA_STATIC;
1179 else
1181 sel->cdata->flags &= ~SEL_CDATA_STATIC;
1183 child = sel->child;
1184 while (child)
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;
1195 /*! \brief
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.
1207 static void
1208 release_subexpr_memory(t_selelem *sel)
1210 t_selelem *child;
1212 child = sel->child;
1213 while (child)
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);
1225 sel->child = NULL;
1229 /*! \brief
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
1236 * deleted.
1238 static void
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 */
1244 sel->name = NULL;
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);
1251 sel->child = NULL;
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);
1260 /*! \brief
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.
1268 static int
1269 process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1271 int rc;
1273 rc = 0;
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 */
1282 return rc;
1285 /*! \brief
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.
1298 static void
1299 store_param_val(t_selelem *sel)
1301 /* Return immediately if there is no parameter. */
1302 if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
1304 return;
1307 /* Or if the value does not need storing. */
1308 if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1310 return;
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);
1320 /*! \brief
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
1329 * method.
1330 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1331 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1333 static int
1334 init_method(t_selelem *sel, t_topology *top, int isize)
1336 t_selelem *child;
1337 bool bAtomVal;
1338 int rc;
1340 /* Find out whether there are any atom-valued parameters */
1341 bAtomVal = FALSE;
1342 child = sel->child;
1343 while (child)
1345 if (child->flags & SEL_ATOMVAL)
1347 bAtomVal = TRUE;
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. */
1359 child = sel->child;
1360 if (sel->type == SEL_MODIFIER && sel->v.type != NO_VALUE)
1362 child = child->next;
1364 while (child)
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);
1371 if (rc != 0)
1373 return rc;
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);
1382 if (rc != 0)
1384 return rc;
1386 if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
1388 alloc_selection_data(sel, isize, TRUE);
1391 else
1393 alloc_selection_data(sel, isize, TRUE);
1394 if ((sel->flags & SEL_DYNAMIC)
1395 && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
1397 sel->v.nr = isize;
1399 /* If the method is char-valued, pre-allocate the strings. */
1400 if (sel->u.expr.method->flags & SMETH_CHARVAL)
1402 int i;
1404 /* A sanity check */
1405 if (sel->v.type != STR_VALUE)
1407 gmx_bug("internal error");
1408 return -1;
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);
1422 return 0;
1425 /*! \brief
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
1430 * processed.
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.
1436 static int
1437 evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
1438 gmx_ana_index_t *g)
1440 t_selelem *child, *next;
1441 int rc;
1443 /* Find the last static subexpression */
1444 child = sel->child;
1445 while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
1447 child = child->next;
1449 if (!(child->cdata->flags & SEL_CDATA_STATIC))
1451 return 0;
1454 /* Evalute the static part if there is more than one expression */
1455 if (child != sel->child)
1457 next = child->next;
1458 child->next = NULL;
1459 rc = sel->cdata->evaluate(data, sel, g);
1460 if (rc != 0)
1462 return rc;
1464 /* Replace the subexpressions with the result */
1465 _gmx_selelem_free_chain(sel->child);
1466 snew(child, 1);
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;
1476 child->next = next;
1477 sel->child = child;
1479 else if (child->evaluate)
1481 rc = child->evaluate(data, child, g);
1482 if (rc != 0)
1484 return rc;
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;
1501 else
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;
1516 else
1518 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, TRUE);
1521 return 0;
1524 /*! \brief
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
1537 * cause for this.
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
1542 * problem.
1544 static void
1545 evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
1546 gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
1548 t_selelem *child;
1550 switch (sel->u.boolt)
1552 case BOOL_NOT:
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);
1557 break;
1559 case BOOL_AND:
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);
1581 break;
1583 case BOOL_OR:
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);
1610 break;
1612 case BOOL_XOR: /* Should not be reached */
1613 gmx_impl("xor expressions not implemented");
1614 break;
1618 /*! \brief
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
1627 * function pointer.
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()
1640 static int
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;
1645 bool bDelayAlloc;
1646 int rc;
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... */
1658 rc = 0;
1659 switch (sel->type)
1661 case SEL_CONST:
1662 rc = process_const(data, sel, g);
1663 break;
1665 case SEL_EXPRESSION:
1666 case SEL_MODIFIER:
1667 rc = _gmx_sel_evaluate_method_params(data, sel, g);
1668 if (rc != 0)
1670 return rc;
1672 rc = init_method(sel, data->top, g->isize);
1673 if (rc != 0)
1675 return rc;
1677 if (!(sel->flags & SEL_DYNAMIC))
1679 rc = sel->cdata->evaluate(data, sel, g);
1680 if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
1682 make_static(sel);
1685 else
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);
1696 break;
1698 case SEL_BOOLEAN:
1699 if (!(sel->flags & SEL_DYNAMIC))
1701 rc = sel->cdata->evaluate(data, sel, g);
1702 if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
1704 make_static(sel);
1707 else
1709 /* Evalute the static part if there is more than one expression */
1710 rc = evaluate_boolean_static_part(data, sel, g);
1711 if (rc != 0)
1713 return rc;
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);
1724 else
1726 rc = sel->cdata->evaluate(data, sel, g);
1728 if (rc != 0)
1730 return rc;
1733 /* Evaluate minimal and maximal selections */
1734 evaluate_boolean_minmax_grps(sel, g, &gmin, &gmax);
1736 break;
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))
1744 make_static(sel);
1747 else
1749 rc = _gmx_sel_evaluate_children(data, sel, g);
1750 if (rc != 0)
1752 return rc;
1754 gmx_ana_index_copy(&gmax, g, TRUE);
1756 break;
1758 case SEL_ROOT:
1759 rc = sel->cdata->evaluate(data, sel, g);
1760 break;
1762 case SEL_SUBEXPR:
1763 if (sel->u.cgrp.isize == 0)
1765 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
1766 if (bDelayAlloc)
1768 /* We need to evaluate the child before we can allocate the
1769 * memory. */
1770 rc = sel->child->evaluate(data, sel->child, g);
1771 if (rc != 0)
1773 return rc;
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;
1781 else
1783 alloc_selection_data(sel->child, g->isize, FALSE);
1784 rc = sel->cdata->evaluate(data, sel, g);
1787 else
1789 int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
1790 if (isize > 0)
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);
1801 else
1803 rc = sel->cdata->evaluate(data, sel, g);
1806 break;
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
1811 * selection). */
1812 if (!g)
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);
1825 if (rc != 0)
1827 return rc;
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)
1835 make_static(sel);
1838 else
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);
1845 else
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);
1853 break;
1855 /* Exit if there was some problem */
1856 if (rc != 0)
1858 return rc;
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);
1880 else
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);
1897 return 0;
1900 /*! \brief
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
1912 * function pointer.
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()
1918 static int
1919 analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1921 int rc;
1923 rc = 0;
1924 switch (sel->type)
1926 case SEL_CONST:
1927 rc = process_const(data, sel, g);
1928 break;
1930 case SEL_EXPRESSION:
1931 case SEL_BOOLEAN:
1932 case SEL_SUBEXPRREF:
1933 case SEL_ARITHMETIC:
1934 if (sel->cdata->flags & SEL_CDATA_STATIC)
1936 rc = sel->cdata->evaluate(data, sel, g);
1937 if (rc == 0)
1939 make_static(sel);
1942 else if (sel->type == SEL_BOOLEAN)
1944 rc = evaluate_boolean_static_part(data, sel, g);
1945 if (rc == 0)
1947 rc = sel->cdata->evaluate(data, sel, g);
1950 break;
1952 case SEL_ROOT: /* Roots should not be present here */
1953 case SEL_MODIFIER: /* Modifiers should not be present here */
1954 case SEL_SUBEXPR:
1955 rc = sel->cdata->evaluate(data, sel, g);
1956 break;
1958 /* Exit if there was some problem */
1959 if (rc != 0)
1961 return rc;
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);
1975 else
1977 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, FALSE);
1981 return 0;
1985 /********************************************************************
1986 * ROOT ITEM INITIALIZATION COMPILER PASS
1987 ********************************************************************/
1989 /*! \brief
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
1999 * evaluation group.
2001 * If the function returns NULL, the memory allocated for \p root is
2002 * automatically freed.
2004 static t_selelem *
2005 init_root_item(t_selelem *root, gmx_ana_index_t *gall)
2007 t_selelem *expr;
2008 char *name;
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);
2017 return NULL;
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;
2028 if (root->cdata)
2030 root->cdata->evaluate = NULL;
2035 /* Set the evaluation group */
2036 name = root->u.cgrp.name;
2037 if (root->evaluate)
2039 expr = root->child;
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);
2052 else
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);
2067 else
2069 gmx_ana_index_clear(&root->u.cgrp);
2071 root->u.cgrp.name = name;
2072 return root;
2075 /*! \brief
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.
2081 static t_selelem *
2082 reverse_selelem_chain(t_selelem *root)
2084 t_selelem *item;
2085 t_selelem *prev;
2086 t_selelem *next;
2088 prev = NULL;
2089 item = root;
2090 while (item)
2092 next = item->next;
2093 item->next = prev;
2094 prev = item;
2095 item = next;
2097 return prev;
2100 /*! \brief
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.
2112 static t_selelem *
2113 process_roots(t_selelem *root, gmx_ana_index_t *gall)
2115 t_selelem *item;
2116 t_selelem *next;
2118 root = reverse_selelem_chain(root);
2121 next = root->next;
2122 root = init_root_item(root, gall);
2123 if (!root)
2125 root = next;
2128 while (root == next);
2129 item = root;
2130 while (item && item->next)
2132 next = item->next->next;
2133 item->next = init_root_item(item->next, gall);
2134 if (!item->next)
2136 item->next = next;
2138 else
2140 item = item->next;
2143 return reverse_selelem_chain(root);
2147 /********************************************************************
2148 * SUBEXPRESSION OPTIMIZATION PASS
2149 ********************************************************************/
2151 /*! \brief
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
2157 * referenced once.
2159 static void
2160 optimize_item_subexpressions(t_selelem *sel)
2162 t_selelem *child;
2164 /* Call recursively for all children unless the children have already been processed */
2165 if (sel->type != SEL_SUBEXPRREF)
2167 child = sel->child;
2168 while (child)
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;
2183 if (sel->cdata)
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 ********************************************************************/
2208 /*! \brief
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
2219 * function.
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.
2226 static int
2227 init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
2228 e_poscalc_t type, int flags)
2230 t_selelem *child;
2231 int rc;
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 */
2240 int cflags;
2241 cflags = 0;
2242 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
2244 cflags |= POS_DYNAMIC;
2246 if (!sel->u.expr.pc)
2248 cflags |= flags;
2249 rc = gmx_ana_poscalc_create(&sel->u.expr.pc, pcc, type, cflags);
2250 if (rc != 0)
2252 return rc;
2255 else
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)
2268 child = sel->child;
2269 while (child)
2271 rc = init_item_comg(child, pcc, type, flags);
2272 if (rc != 0)
2274 return rc;
2276 child = child->next;
2279 return 0;
2283 /********************************************************************
2284 * FREE COMPILER DATA PASS
2285 ********************************************************************/
2287 /*! \brief
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.
2294 static void
2295 free_item_compilerdata(t_selelem *sel)
2297 t_selelem *child;
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)
2305 child = sel->child;
2306 while (child)
2308 free_item_compilerdata(child);
2309 child = child->next;
2315 /********************************************************************
2316 * INFORMATION UPDATE
2317 ********************************************************************/
2319 /*! \brief
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.
2330 static void
2331 update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
2332 bool bMaskOnly)
2334 int g, b, i;
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;
2344 if (top)
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;
2353 else
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];
2368 else
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
2392 * \ref CFRAC_NONE.
2395 gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
2397 gmx_sel_evaluate_t evaldata;
2398 t_selelem *item;
2399 e_poscalc_t post;
2400 int flags;
2401 int rc;
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 */
2417 item = sc->root;
2418 while (item)
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 */
2426 return -1;
2428 /* Initialize evaluation */
2429 if (!init_item_evaluation(item))
2431 /* FIXME: Clean up the collection */
2432 return -1;
2434 /* Initialize the compiler data */
2435 init_item_compilerdata(item);
2436 init_item_staticeval(item);
2437 item = item->next;
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. */
2444 item = sc->root;
2445 while (item)
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);
2453 if (rc != 0)
2455 /* FIXME: Clean up the collection */
2456 return rc;
2458 item = item->next;
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(). */
2464 item = sc->root;
2465 while (item)
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);
2480 if (rc != 0)
2482 /* FIXME: Clean up the collection */
2483 return rc;
2486 item = item->next;
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);
2497 if (rc != 0)
2499 gmx_bug("invalid default reference position type");
2500 /* FIXME: Clean up the collection */
2501 return rc;
2503 item = sc->root;
2504 while (item)
2506 optimize_item_subexpressions(item);
2507 rc = init_item_comg(item, sc->pcc, post, flags);
2508 if (rc != 0)
2510 /* FIXME: Clean up the collection */
2511 return rc;
2513 free_item_compilerdata(item);
2514 item = item->next;
2517 /* Finish up by updating some information */
2518 update_info(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
2520 return 0;