Removed obsolete selection code.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / selection / compiler.c
blobea8820edff37941d4a7e0ea17dffcc028d65bcc0
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 * At least, the main compilation function leaves the selection collection in
37 * a bad state if an error occurs.
39 * \todo
40 * The memory usage could be optimized.
41 * Currently, each selection element allocates a separate block of memory to
42 * hold the evaluated value, but most of this memory is not used
43 * simultaneously. Perhaps the cleanest solution (avoiding constant allocation
44 * and deallocation) would be to have a memory pool whose maximum size is
45 * determined at compilation time and allocate memory from the pool during
46 * evaluation.
48 /*! \internal
49 * \page selcompiler Selection compilation
51 * The compiler takes the selection element tree from the selection parser
52 * (see \ref selparser) as input. The selection parser is quite independent of
53 * selection evaluation details, and the compiler processes the tree to
54 * conform to what the evaluation functions expect.
55 * For better control and optimization possibilities, the compilation is
56 * done on all selections simultaneously.
57 * Hence, all the selections should be parsed before the compiler can be
58 * called.
60 * The compiler initializes all fields in \c t_selelem not initialized by
61 * the parser: \c t_selelem::v (some fields have already been initialized by
62 * the parser), \c t_selelem::evaluate, and \c t_selelem::u (again, some
63 * elements have been initialized in the parser).
64 * The \c t_selelem::cdata field is used during the compilation to store
65 * internal data, but the data is freed when the compiler returns.
67 * In addition to initializing the elements, the compiler reorganizes the tree
68 * to simplify and optimize evaluation. The compiler also evaluates the static
69 * parts of the selection: in the end of the compilation, static parts have
70 * been replaced by the result of the evaluation.
72 * The compiler is called by calling gmx_ana_selcollection_compile().
73 * This functions then does the compilation in several passes over the
74 * \c t_selelem tree.
75 * -# Subexpressions are extracted: a separate root is created for each
76 * subexpression, and placed before the expression is first used.
77 * Currently, only variables and expressions used to evaluate parameter
78 * values are extracted, but common subexpression could also be detected
79 * here.
80 * -# A second pass with simple reordering and initialization is done:
81 * -# Boolean expressions are combined such that one element can evaluate,
82 * e.g., "A and B and C". The subexpressions in boolean expression are
83 * reordered such that static expressions come first without otherwise
84 * altering the relative order of the expressions.
85 * -# The \c t_selelem::evaluate field is set to the correct evaluation
86 * function from evaluate.h.
87 * -# The compiler data structure is allocated for each element, and
88 * the fields are initialized, with the exception of the contents of
89 * \c gmax and \c gmin fields.
90 * .
91 * -# The evaluation function of all elements is replaced with the
92 * analyze_static() function to be able to initialize the element before
93 * the actual evaluation function is called.
94 * The evaluation machinery is then called to initialize the whole tree,
95 * while simultaneously evaluating the static expressions.
96 * During the evaluation, track is kept of the smallest and largest
97 * possible selections, and these are stored in the internal compiler
98 * data structure for each element.
99 * To be able to do this for all possible values of dynamical expressions,
100 * special care needs to be taken with boolean expressions because they
101 * are short-circuiting. This is done through the
102 * \c t_compiler_data::bEvalMax flag, which makes dynamic child expressions
103 * of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
104 * of \c BOOL_AND are evaluated to largest possible groups.
105 * Memory is also allocated to store the results of the evaluation.
106 * For each element, analyze_static() calls the actual evaluation function
107 * after the element has been properly initialized.
108 * -# Another evaluation pass is done over subexpressions with more than
109 * one reference to them. These cannot be completely processed during the
110 * first pass, because it is not known whether later references require
111 * additional evaluation of static expressions.
112 * -# Most of the processing is now done, and the next pass simply sets the
113 * evaluation group of root elements to the largest selection as determined
114 * in pass 3. Subexpressions that were evaluated to constants are no
115 * longer referenced at this time, and are removed.
116 * -# The next pass eliminates some unnecessary evaluation calls from
117 * subexpressions that are referenced only once, as well as initializing
118 * the position calculation data for selection method elements that require
119 * it. Compiler data is also freed as it is no longer needed.
120 * -# A final pass initializes the total masses and charges in the
121 * \c gmx_ana_selection_t data structures.
123 * The actual evaluation of the selection is described in the documentation
124 * of the functions in evaluate.h.
126 * \todo
127 * Some combinations of method parameter flags are not yet properly treated by
128 * the compiler or the evaluation functions in evaluate.c. All the ones used by
129 * currently implemented methods should work, but new combinations might not.
132 * \section selcompiler_tree Element tree after compilation
134 * After the compilation, the selection element tree is suitable for
135 * gmx_ana_selcollection_evaluate().
136 * Enough memory has been allocated for \ref t_selelem::v
137 * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
138 * selection to be evaluated without allocating any memory.
141 * \subsection selcompiler_tree_root Root elements
143 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
144 * These are used for two purposes:
145 * -# A selection that should be evaluated.
146 * These elements appear in the same order as the selections in the input.
147 * For these elements, \ref t_selelem::v has been set to the maximum
148 * possible group that the selection can evaluate to, and
149 * \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
150 * -# A subexpression that appears in one or more selections.
151 * Each selection that gives a value for a method parameter is a
152 * potential subexpression, as is any variable value.
153 * Only subexpressions that require evaluation for each frame are left
154 * after the selection is compiled.
155 * Each subexpression appears in the chain before any references to it.
156 * For these elements, \c t_selelem::cgrp has been set to the group
157 * that should be used to evaluate the subexpression.
158 * If \c t_selelem::cgrp is empty, the total evaluation group is not known
159 * in advance. If this is the case, \c t_selelem::evaluate is also NULL.
161 * The children of the \ref SEL_ROOT elements can be used to distinguish
162 * the two types of root elements from each other; the rules are the same
163 * as for the parsed tree (see \ref selparser_tree_root).
164 * Subexpressions are treated as if they had been provided through variables.
166 * Selection names are stored as after parsing (see \ref selparser_tree_root).
169 * \subsection selcompiler_tree_const Constant elements
171 * All (sub)selections that do not require particle positions have been
172 * replaced with \ref SEL_CONST elements.
173 * Constant elements from the parser are also retained if present in
174 * dynamic parts of the selections.
175 * Several constant elements with a NULL \c t_selelem::evaluate are left for
176 * debugging purposes; of these, only the ones for \ref BOOL_OR expressions are
177 * used during evaluation.
179 * The value is stored in \c t_selelem::v, and for group values with an
180 * evaluation function set, also in \c t_selelem::cgrp.
181 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
182 * could never be selected) have been removed from the value.
184 * \ref SEL_CONST elements have no children.
187 * \subsection selcompiler_tree_method Method evaluation elements
189 * All selection methods that need to be evaluated dynamically are described
190 * by a \ref SEL_EXPRESSION element. The \c t_selelem::method and
191 * \c t_selelem::mdata fields have already been initialized by the parser,
192 * and the compiler only calls the initialization functions in the method
193 * data structure to do some additional initialization of these fields at
194 * appropriate points. If the \c t_selelem::pc data field has been created by
195 * the parser, the compiler initializes the data structure properly once the
196 * required positions are known. If the \c t_selelem::pc field is NULL after
197 * the parser, but the method provides only sel_updatefunc_pos(), an
198 * appropriate position calculation data structure is created.
199 * If \c t_selelem::pc is not NULL, \c t_selelem::pos is also initialized
200 * to hold the positions calculated.
202 * Children of these elements are of type \ref SEL_SUBEXPRREF, and describe
203 * parameter values that need to be evaluated for each frame. See the next
204 * section for more details.
205 * \ref SEL_CONST children can also appear, and stand for parameters that get
206 * their value from a static expression. These elements are present only for
207 * debugging purposes: they always have a NULL evaluation function.
210 * \subsection selcompiler_tree_subexpr Subexpression elements
212 * As described in \ref selcompiler_tree_root, subexpressions are created
213 * for each variable and each expression that gives a value to a selection
214 * method parameter. As the only child of the \ref SEL_ROOT element,
215 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
216 * element has a single child, which evaluates the actual expression.
217 * After compilation, only subexpressions that require particle positions
218 * for evaluation are left.
219 * For non-variable subexpression, automatic names have been generated to
220 * help in debugging.
222 * For \ref SEL_SUBEXPR elements, memory has been allocated for
223 * \c t_selelem::cgrp to store the group for which the expression has been
224 * evaluated during the current frame.
226 * \ref SEL_SUBEXPRREF elements are used to describe references to
227 * subexpressions. They have always a single child, which is the
228 * \ref SEL_SUBEXPR element being referenced.
230 * If a subexpression is used only once and can be evaluated statically,
231 * the evaluation has been optimized by setting the child of the
232 * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
233 * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
234 * and \ref SEL_SUBEXPR elements only propagate some status information,
235 * but do not unnecessarily copy the values.
238 * \subsection selcompiler_tree_bool Boolean elements
240 * \ref SEL_BOOLEAN elements have been merged such that one element
241 * may carry out evaluation of more than one operation of the same type.
242 * The static parts of the expressions have been evaluated, and are placed
243 * in the first child. These are followed by the dynamic expressions, in the
244 * order provided by the user.
246 #ifdef HAVE_CONFIG_H
247 #include <config.h>
248 #endif
250 #include <math.h>
251 #include <stdarg.h>
253 #include <smalloc.h>
254 #include <string2.h>
255 #include <vec.h>
257 #include <indexutil.h>
258 #include <poscalc.h>
259 #include <selection.h>
260 #include <selmethod.h>
262 #include "evaluate.h"
263 #include "keywords.h"
264 #include "mempool.h"
265 #include "selcollection.h"
266 #include "selelem.h"
268 /*! \internal \brief
269 * Compiler flags.
271 enum
273 /*! \brief
274 * Whether a subexpression needs to evaluated for all atoms.
276 * This flag is set for \ref SEL_SUBEXPR elements that are used to
277 * evaluate non-atom-valued selection method parameters, as well as
278 * those that are used directly as values of selections.
280 SEL_CDATA_FULLEVAL = 1,
281 /*! \brief
282 * Whether the whole subexpression should be treated as static.
284 * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
285 * but it is also FALSE for static elements within common subexpressions.
287 SEL_CDATA_STATIC = 2,
288 /** Whether the subexpression will always be evaluated in the same group. */
289 SEL_CDATA_STATICEVAL = 4,
290 /** Whether the compiler evaluation routine should return the maximal selection. */
291 SEL_CDATA_EVALMAX = 8,
292 /** Whether memory has been allocated for \p gmin and \p gmax. */
293 SEL_CDATA_MINMAXALLOC = 16,
294 /** Whether subexpressions use simple pass evaluation functions. */
295 SEL_CDATA_SIMPLESUBEXPR = 32,
298 /*! \internal \brief
299 * Internal data structure used by the compiler.
301 typedef struct t_compiler_data
303 /** The real evaluation method. */
304 sel_evalfunc evaluate;
305 /** Flags for specifying how to treat this element during compilation. */
306 int flags;
307 /** Smallest selection that can be selected by the subexpression. */
308 gmx_ana_index_t *gmin;
309 /** Largest selection that can be selected by the subexpression. */
310 gmx_ana_index_t *gmax;
311 } t_compiler_data;
314 /********************************************************************
315 * COMPILER UTILITY FUNCTIONS
316 ********************************************************************/
319 * \param sel Selection to free.
321 * This function only frees the data for the given selection, not its children.
322 * It is safe to call the function when compiler data has not been allocated
323 * or has already been freed; in such a case, nothing is done.
325 void
326 _gmx_selelem_free_compiler_data(t_selelem *sel)
328 if (sel->cdata)
330 sel->evaluate = sel->cdata->evaluate;
331 if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
333 sel->cdata->gmin->name = NULL;
334 sel->cdata->gmax->name = NULL;
335 gmx_ana_index_deinit(sel->cdata->gmin);
336 gmx_ana_index_deinit(sel->cdata->gmax);
337 sfree(sel->cdata->gmin);
338 sfree(sel->cdata->gmax);
340 sfree(sel->cdata);
342 sel->cdata = NULL;
345 /*! \brief
346 * Allocates memory for storing the evaluated value of a selection element.
348 * \param sel Selection element to initialize
349 * \param[in] isize Maximum evaluation group size.
350 * \param[in] bChildEval TRUE if children have already been processed.
351 * \returns TRUE if the memory was allocated, FALSE if children need to
352 * be processed first.
354 * If called more than once, memory is (re)allocated to ensure that the
355 * maximum of the \p isize values can be stored.
357 static bool
358 alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
360 int nalloc;
362 if (sel->mempool)
364 return TRUE;
366 /* Find out the number of elements to allocate */
367 if (sel->flags & SEL_SINGLEVAL)
369 nalloc = 1;
371 else if (sel->flags & SEL_ATOMVAL)
373 nalloc = isize;
375 else /* sel->flags should contain SEL_VARNUMVAL */
377 t_selelem *child;
379 if (!bChildEval)
381 return FALSE;
383 child = (sel->type == SEL_SUBEXPRREF ? sel->child : sel);
384 if (child->type == SEL_SUBEXPR)
386 child = child->child;
388 nalloc = (sel->v.type == POS_VALUE) ? child->v.u.p->nr : child->v.nr;
390 /* For positions, we actually want to allocate just a single structure
391 * for nalloc positions. */
392 if (sel->v.type == POS_VALUE)
394 isize = nalloc;
395 nalloc = 1;
397 /* Allocate memory for sel->v.u if needed */
398 if (sel->flags & SEL_ALLOCVAL)
400 _gmx_selvalue_reserve(&sel->v, nalloc);
402 /* Reserve memory inside group and position structures if
403 * SEL_ALLOCDATA is set. */
404 if (sel->flags & SEL_ALLOCDATA)
406 if (sel->v.type == GROUP_VALUE)
408 gmx_ana_index_reserve(sel->v.u.g, isize);
410 else if (sel->v.type == POS_VALUE)
412 gmx_ana_pos_reserve(sel->v.u.p, isize, 0);
415 return TRUE;
418 /*! \brief
419 * Replace the evaluation function of each element in the subtree.
421 * \param sel Root of the selection subtree to process.
422 * \param[in] eval The new evaluation function.
424 static void
425 set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
427 sel->evaluate = eval;
428 if (sel->type != SEL_SUBEXPRREF)
430 t_selelem *child = sel->child;
431 while (child)
433 set_evaluation_function(child, eval);
434 child = child->next;
439 /********************************************************************
440 * SUBEXPRESSION PROCESSING
441 ********************************************************************/
443 /*! \brief
444 * Reverses the chain of selection elements starting at \p root.
446 * \param root First selection in the whole selection chain.
447 * \returns The new first element for the chain.
449 static t_selelem *
450 reverse_selelem_chain(t_selelem *root)
452 t_selelem *item;
453 t_selelem *prev;
454 t_selelem *next;
456 prev = NULL;
457 item = root;
458 while (item)
460 next = item->next;
461 item->next = prev;
462 prev = item;
463 item = next;
465 return prev;
468 /*! \brief
469 * Removes subexpressions that don't have any references.
471 * \param root First selection in the whole selection chain.
472 * \returns The new first element for the chain.
474 * The elements are processed in reverse order to correctly detect
475 * subexpressions only referred to by other subexpressions.
477 static t_selelem *
478 remove_unused_subexpressions(t_selelem *root)
480 t_selelem *item;
481 t_selelem *prev;
482 t_selelem *next;
484 root = reverse_selelem_chain(root);
485 while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
487 next = root->next;
488 _gmx_selelem_free(root);
489 root = next;
491 prev = root;
492 item = root->next;
493 while (item)
495 next = item->next;
496 if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
498 prev->next = next;
499 _gmx_selelem_free(item);
501 else
503 prev = item;
505 item = next;
507 return reverse_selelem_chain(root);
510 /*! \brief
511 * Creates a name with a running number for a subexpression.
513 * \param[in,out] sel The subexpression to be named.
514 * \param[in] i Running number for the subexpression.
516 * The name of the selection becomes "SubExpr N", where N is \p i;
517 * Memory is allocated for the name and the name is stored both in
518 * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
519 * is freed by _gmx_selelem_free().
521 static void
522 create_subexpression_name(t_selelem *sel, int i)
524 int len, ret;
525 char *name;
527 len = 8 + (int)log10(abs(i)) + 3;
528 snew(name, len+1);
529 /* FIXME: snprintf used to be used here for extra safety, but this
530 * requires extra checking on Windows since it only provides a
531 * non-C99-conforming implementation as _snprintf()... */
532 ret = sprintf(name, "SubExpr %d", i);
533 if (ret < 0 || ret > len)
535 sfree(name);
536 name = NULL;
538 sel->name = name;
539 sel->u.cgrp.name = name;
542 /*! \brief
543 * Processes and extracts subexpressions from a given selection subtree.
545 * \param sel Root of the subtree to process.
546 * \param subexprn Pointer to a subexpression counter.
547 * \returns Pointer to a chain of subselections, or NULL if none were found.
549 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
550 * the given root element and ensures that their children are within
551 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
552 * that contain the subexpression as their children and returns the first
553 * of these root elements.
555 static t_selelem *
556 extract_item_subselections(t_selelem *sel, int *subexprn)
558 t_selelem *root;
559 t_selelem *subexpr;
560 t_selelem *child;
562 root = subexpr = NULL;
563 child = sel->child;
564 while (child)
566 if (!root)
568 root = subexpr = extract_item_subselections(child, subexprn);
570 else
572 subexpr->next = extract_item_subselections(child, subexprn);
574 while (subexpr && subexpr->next)
576 subexpr = subexpr->next;
578 /* The latter check excludes variable references.
579 * It also excludes subexpression elements that have already been
580 * processed, because they are given a name when they are first
581 * encountered.
582 * TODO: There should be a more robust mechanism (probably a dedicated
583 * flag) for detecting parser-generated subexpressions than relying on
584 * a NULL name field. */
585 if (child->type == SEL_SUBEXPRREF && (child->child->type != SEL_SUBEXPR
586 || child->child->name == NULL))
588 /* Create the root element for the subexpression */
589 if (!root)
591 root = subexpr = _gmx_selelem_create(SEL_ROOT);
593 else
595 subexpr->next = _gmx_selelem_create(SEL_ROOT);
596 subexpr = subexpr->next;
598 /* Create the subexpression element and/or
599 * move the actual subexpression under the created element. */
600 if (child->child->type != SEL_SUBEXPR)
602 subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
603 _gmx_selelem_set_vtype(subexpr->child, child->v.type);
604 subexpr->child->child = child->child;
605 child->child = subexpr->child;
607 else
609 subexpr->child = child->child;
611 create_subexpression_name(subexpr->child, ++*subexprn);
612 subexpr->child->refcount++;
613 /* Set the flags for the created elements */
614 subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
615 subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
617 child = child->next;
620 return root;
623 /*! \brief
624 * Extracts subexpressions of the selection chain.
626 * \param sel First selection in the whole selection chain.
627 * \returns The new first element for the chain.
629 * Finds all the subexpressions (and their subexpressions) in the
630 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
631 * elements for them.
632 * \ref SEL_ROOT elements are also created for each subexpression
633 * and inserted into the selection chain before the expressions that
634 * refer to them.
636 static t_selelem *
637 extract_subexpressions(t_selelem *sel)
639 t_selelem *root, *item, *next;
640 int subexprn;
642 subexprn = 0;
643 root = NULL;
644 next = sel;
645 while (next)
647 item = extract_item_subselections(next, &subexprn);
648 if (item)
650 if (!root)
652 root = item;
654 else
656 sel->next = item;
658 while (item->next)
660 item = item->next;
662 item->next = next;
664 else if (!root)
666 root = next;
668 sel = next;
669 next = next->next;
671 return root;
675 /********************************************************************
676 * BOOLEAN OPERATION REORDERING COMPILER PASS
677 ********************************************************************/
679 /*! \brief
680 * Removes redundant boolean selection elements.
682 * \param sel Root of the selection subtree to optimize.
684 * This function merges similar boolean operations (e.g., (A or B) or C becomes
685 * a single OR operation with three operands).
687 static void
688 optimize_boolean_expressions(t_selelem *sel)
690 t_selelem *child, *prev;
692 /* Do recursively for children */
693 if (sel->type != SEL_SUBEXPRREF)
695 prev = NULL;
696 child = sel->child;
697 while (child)
699 optimize_boolean_expressions(child);
700 /* Remove double negations */
701 if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
702 && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
704 /* Move the doubly negated expression up two levels */
705 if (!prev)
707 sel->child = child->child->child;
708 prev = sel->child;
710 else
712 prev->next = child->child->child;
713 prev = prev->next;
715 child->child->child->next = child->next;
716 /* Remove the two negations */
717 child->child->child = NULL;
718 child->next = NULL;
719 _gmx_selelem_free(child);
720 child = prev;
722 prev = child;
723 child = child->next;
726 if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
728 return;
730 /* Merge subsequent binary operations */
731 prev = NULL;
732 child = sel->child;
733 while (child)
735 if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
737 if (!prev)
739 sel->child = child->child;
740 prev = sel->child;
742 else
744 prev->next = child->child;
746 while (prev->next)
748 prev = prev->next;
750 prev->next = child->next;
751 sfree(child->v.u.g);
752 sfree(child);
753 child = prev->next;
755 else
757 prev = child;
758 child = child->next;
763 /*! \brief
764 * Reorders children of boolean expressions such that static selections
765 * come first.
767 * \param sel Root of the selection subtree to reorder.
769 * The relative order of static expressions does not change.
770 * The same is true for the dynamic expressions.
772 static void
773 reorder_boolean_static_children(t_selelem *sel)
775 t_selelem *child, *prev, *next;
777 /* Do recursively for children */
778 if (sel->type != SEL_SUBEXPRREF)
780 child = sel->child;
781 while (child)
783 reorder_boolean_static_children(child);
784 child = child->next;
788 /* Reorder boolean expressions such that static selections come first */
789 if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
791 t_selelem start;
793 start.next = sel->child;
794 prev = &start;
795 child = &start;
796 while (child->next)
798 /* child is the last handled static expression */
799 /* prev is the last handled non-static expression */
800 next = prev->next;
801 while (next && (next->flags & SEL_DYNAMIC))
803 prev = next;
804 next = next->next;
806 /* next is now the first static expression after child */
807 if (!next)
809 break;
811 /* Reorder such that next comes after child */
812 if (prev != child)
814 prev->next = next->next;
815 next->next = child->next;
816 child->next = next;
818 else
820 prev = prev->next;
822 /* Advance child by one */
823 child = next;
826 sel->child = start.next;
830 /********************************************************************
831 * ARITHMETIC EXPRESSION PROCESSING
832 ********************************************************************/
834 /*! \brief
835 * Processes arithmetic expressions to simplify and speed up evaluation.
837 * \param sel Root of the selection subtree to process.
839 * Currently, this function only converts integer constants to reals
840 * within arithmetic expressions.
842 static bool
843 optimize_arithmetic_expressions(t_selelem *sel)
845 t_selelem *child;
846 bool bOk;
848 /* Do recursively for children. */
849 if (sel->type != SEL_SUBEXPRREF)
851 child = sel->child;
852 while (child)
854 bOk = optimize_arithmetic_expressions(child);
855 if (!bOk)
857 return bOk;
859 child = child->next;
863 if (sel->type != SEL_ARITHMETIC)
865 return TRUE;
868 /* Convert integer constants to reals. */
869 child = sel->child;
870 while (child)
872 if (child->v.type == INT_VALUE)
874 real *r;
876 if (child->type != SEL_CONST)
878 gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
879 return FALSE;
881 snew(r, 1);
882 r[0] = child->v.u.i[0];
883 sfree(child->v.u.i);
884 child->v.u.r = r;
885 child->v.type = REAL_VALUE;
887 else if (child->v.type != REAL_VALUE)
889 gmx_bug("Internal error");
890 return FALSE;
892 child = child->next;
894 return TRUE;
897 /********************************************************************
898 * EVALUATION PREPARATION COMPILER PASS
899 ********************************************************************/
901 /*! \brief
902 * Sets the evaluation functions for the selection (sub)tree.
904 * \param[in,out] sel Root of the selection subtree to process.
905 * \returns TRUE on success, FALSE if any subexpression fails.
907 * This function sets the evaluation function (\c t_selelem::evaluate)
908 * for the selection elements.
910 static bool
911 init_item_evalfunc(t_selelem *sel)
913 /* Process children. */
914 if (sel->type != SEL_SUBEXPRREF)
916 t_selelem *child;
918 child = sel->child;
919 while (child)
921 if (!init_item_evalfunc(child))
923 return FALSE;
925 child = child->next;
929 /* Set the evaluation function */
930 switch (sel->type)
932 case SEL_CONST:
933 if (sel->v.type == GROUP_VALUE)
935 sel->evaluate = &_gmx_sel_evaluate_static;
937 break;
939 case SEL_EXPRESSION:
940 if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
941 && sel->u.expr.method->init_frame)
943 sel->flags |= SEL_INITFRAME;
945 sel->evaluate = &_gmx_sel_evaluate_method;
946 break;
948 case SEL_ARITHMETIC:
949 sel->evaluate = &_gmx_sel_evaluate_arithmetic;
950 break;
952 case SEL_MODIFIER:
953 if (sel->v.type != NO_VALUE)
955 sel->evaluate = &_gmx_sel_evaluate_modifier;
957 break;
959 case SEL_BOOLEAN:
960 switch (sel->u.boolt)
962 case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
963 case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
964 case BOOL_OR: sel->evaluate = &_gmx_sel_evaluate_or; break;
965 case BOOL_XOR:
966 gmx_impl("xor expressions not implemented");
967 return FALSE;
969 break;
971 case SEL_ROOT:
972 sel->evaluate = &_gmx_sel_evaluate_root;
973 break;
975 case SEL_SUBEXPR:
976 sel->evaluate = (sel->refcount == 2
977 ? &_gmx_sel_evaluate_subexpr_simple
978 : &_gmx_sel_evaluate_subexpr);
979 break;
981 case SEL_SUBEXPRREF:
982 sel->name = sel->child->name;
983 sel->evaluate = (sel->child->refcount == 2
984 ? &_gmx_sel_evaluate_subexprref_simple
985 : &_gmx_sel_evaluate_subexprref);
986 break;
989 return TRUE;
992 /*! \brief
993 * Sets the memory pool for selection elements that can use it.
995 * \param sel Root of the selection subtree to process.
996 * \param[in] mempool Memory pool to use.
998 static void
999 setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
1001 if (sel->type != SEL_SUBEXPRREF)
1003 t_selelem *child;
1005 child = sel->child;
1006 while (child)
1008 if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
1009 || (sel->type == SEL_SUBEXPR && sel->refcount > 2))
1011 child->mempool = mempool;
1012 if (child->type == SEL_SUBEXPRREF
1013 && child->child->refcount == 2)
1015 child->child->child->mempool = mempool;
1018 setup_memory_pooling(child, mempool);
1019 child = child->next;
1024 /*! \brief
1025 * Prepares the selection (sub)tree for evaluation.
1027 * \param[in,out] sel Root of the selection subtree to prepare.
1029 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
1030 * structure if required.
1032 static void
1033 init_item_evaloutput(t_selelem *sel)
1035 /* Process children. */
1036 if (sel->type != SEL_SUBEXPRREF)
1038 t_selelem *child;
1040 child = sel->child;
1041 while (child)
1043 init_item_evaloutput(child);
1044 child = child->next;
1048 if (sel->type == SEL_SUBEXPR && sel->refcount == 2)
1050 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1051 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1053 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1056 else if (sel->type == SEL_SUBEXPR
1057 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
1059 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
1060 sel->cdata->evaluate = sel->evaluate;
1061 sel->child->mempool = NULL;
1062 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1063 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1065 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1068 else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
1070 if (sel->v.u.ptr)
1072 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
1073 _gmx_selelem_free_values(sel->child->child);
1074 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1075 sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
1076 _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
1078 else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1080 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
1082 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1085 /* Make sure that the group/position structure is allocated. */
1086 if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
1088 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
1090 _gmx_selvalue_reserve(&sel->v, 1);
1091 sel->v.nr = 1;
1096 /********************************************************************
1097 * COMPILER DATA INITIALIZATION PASS
1098 ********************************************************************/
1100 /*! \brief
1101 * Allocates memory for the compiler data and initializes the structure.
1103 * \param sel Root of the selection subtree to process.
1105 static void
1106 init_item_compilerdata(t_selelem *sel)
1108 t_selelem *child;
1110 /* Allocate the compiler data structure */
1111 snew(sel->cdata, 1);
1113 /* Store the real evaluation method because the compiler will replace it */
1114 sel->cdata->evaluate = sel->evaluate;
1116 /* Initialize the flags */
1117 sel->cdata->flags = SEL_CDATA_STATICEVAL;
1118 if (!(sel->flags & SEL_DYNAMIC))
1120 sel->cdata->flags |= SEL_CDATA_STATIC;
1122 if (sel->type == SEL_SUBEXPR)
1124 sel->cdata->flags |= SEL_CDATA_EVALMAX;
1125 if (sel->refcount == 2)
1127 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1130 if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
1132 sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
1134 /* Set the full evaluation flag for subexpressions that require it;
1135 * the subexpression has already been initialized, so we can simply
1136 * access its compilation flags.*/
1137 if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
1139 child = sel->child;
1140 while (child)
1142 if (!(child->flags & SEL_ATOMVAL) && child->child)
1144 child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1146 child = child->next;
1149 else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
1151 sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
1154 /* Initialize children */
1155 if (sel->type != SEL_SUBEXPRREF)
1157 child = sel->child;
1158 while (child)
1160 init_item_compilerdata(child);
1161 child = child->next;
1165 /* Determine whether we should evaluate the minimum or the maximum
1166 * for the children of this element. */
1167 if (sel->type == SEL_BOOLEAN)
1169 bool bEvalMax;
1171 bEvalMax = (sel->u.boolt == BOOL_AND);
1172 child = sel->child;
1173 while (child)
1175 if (bEvalMax)
1177 child->cdata->flags |= SEL_CDATA_EVALMAX;
1179 else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
1181 child->child->cdata->flags |= SEL_CDATA_EVALMAX;
1183 child = child->next;
1186 else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
1187 || sel->type == SEL_SUBEXPR)
1189 child = sel->child;
1190 while (child)
1192 child->cdata->flags |= SEL_CDATA_EVALMAX;
1193 child = child->next;
1198 /*! \brief
1199 * Initializes the static evaluation flag for a selection subtree.
1201 * \param[in,out] sel Root of the selection subtree to process.
1203 * Sets the \c bStaticEval in the compiler data structure:
1204 * for any element for which the evaluation group may depend on the trajectory
1205 * frame, the flag is cleared.
1207 * reorder_boolean_static_children() should have been called.
1209 static void
1210 init_item_staticeval(t_selelem *sel)
1212 t_selelem *child;
1214 /* Subexpressions with full evaluation should always have bStaticEval,
1215 * so don't do anything if a reference to them is encountered. */
1216 if (sel->type == SEL_SUBEXPRREF
1217 && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
1219 return;
1222 /* Propagate the bStaticEval flag to children if it is not set */
1223 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
1225 child = sel->child;
1226 while (child)
1228 if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
1229 || (child->flags & SEL_ATOMVAL))
1231 if (child->cdata->flags & SEL_CDATA_STATICEVAL)
1233 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1234 init_item_staticeval(child);
1237 child = child->next;
1240 else /* bStaticEval is set */
1242 /* For boolean expressions, any expression after the first dynamic
1243 * expression should not have bStaticEval. */
1244 if (sel->type == SEL_BOOLEAN)
1246 child = sel->child;
1247 while (child && !(child->flags & SEL_DYNAMIC))
1249 child = child->next;
1251 if (child)
1253 child = child->next;
1255 while (child)
1257 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1258 child = child->next;
1262 /* Process the children */
1263 child = sel->child;
1264 while (child)
1266 init_item_staticeval(child);
1267 child = child->next;
1272 /*! \brief
1273 * Initializes the gmin and gmax fields of the compiler data structure.
1275 * \param sel Root of the selection subtree to process.
1277 static void
1278 init_item_minmax_groups(t_selelem *sel)
1280 /* Process children. */
1281 if (sel->type != SEL_SUBEXPRREF)
1283 t_selelem *child;
1285 child = sel->child;
1286 while (child)
1288 init_item_minmax_groups(child);
1289 child = child->next;
1293 /* Initialize the minimum and maximum evaluation groups. */
1294 if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
1296 if (sel->v.type == GROUP_VALUE
1297 && (sel->cdata->flags & SEL_CDATA_STATIC))
1299 sel->cdata->gmin = sel->v.u.g;
1300 sel->cdata->gmax = sel->v.u.g;
1302 else if (sel->type == SEL_SUBEXPR)
1304 sel->cdata->gmin = sel->child->cdata->gmin;
1305 sel->cdata->gmax = sel->child->cdata->gmax;
1307 else
1309 sel->cdata->flags |= SEL_CDATA_MINMAXALLOC;
1310 snew(sel->cdata->gmin, 1);
1311 snew(sel->cdata->gmax, 1);
1316 /********************************************************************
1317 * EVALUATION GROUP INITIALIZATION
1318 ********************************************************************/
1320 /*! \brief
1321 * Initializes evaluation groups for root items.
1323 * \param[in,out] sc Selection collection data.
1325 * The evaluation group of each \ref SEL_ROOT element corresponding to a
1326 * selection in \p sc is set to \p gall. The same is done for \ref SEL_ROOT
1327 * elements corresponding to subexpressions that need full evaluation.
1329 static void
1330 initialize_evalgrps(gmx_ana_selcollection_t *sc)
1332 t_selelem *root;
1334 root = sc->root;
1335 while (root)
1337 if (root->child->type != SEL_SUBEXPR
1338 || (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
1340 gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
1341 root->u.cgrp.name, 0);
1343 root = root->next;
1348 /********************************************************************
1349 * STATIC ANALYSIS COMPILER PASS
1350 ********************************************************************/
1352 /*! \brief
1353 * Marks a subtree completely dynamic or undoes such a change.
1355 * \param sel Selection subtree to mark.
1356 * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
1357 * selection subtree is cleared. If FALSE, the flag is restored to
1358 * using \ref SEL_DYNAMIC.
1360 * Does not descend into parameters of methods unless the parameters
1361 * are evaluated for each atom.
1363 static void
1364 mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
1366 t_selelem *child;
1368 if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
1370 sel->cdata->flags |= SEL_CDATA_STATIC;
1372 else
1374 sel->cdata->flags &= ~SEL_CDATA_STATIC;
1376 child = sel->child;
1377 while (child)
1379 if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
1380 || (child->u.param->flags & SPAR_ATOMVAL))
1382 mark_subexpr_dynamic(child, bDynamic);
1384 child = child->next;
1388 /*! \brief
1389 * Frees memory for subexpressions that are no longer needed.
1391 * \param sel Selection subtree to check.
1393 * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
1394 * elements that are not referred to by anything else except their own root
1395 * element. If such elements are found, all memory allocated for them is freed
1396 * except the actual element. The element is left because otherwise a dangling
1397 * pointer would be left at the root element, which is not traversed by this
1398 * function. Later compilation passes remove the stub elements.
1400 static void
1401 release_subexpr_memory(t_selelem *sel)
1403 if (sel->type == SEL_SUBEXPR)
1405 if (sel->refcount == 2)
1407 release_subexpr_memory(sel->child);
1408 sel->name = NULL;
1409 _gmx_selelem_free_chain(sel->child);
1410 _gmx_selelem_free_values(sel);
1411 _gmx_selelem_free_exprdata(sel);
1412 _gmx_selelem_free_compiler_data(sel);
1413 sel->child = NULL;
1416 else
1418 t_selelem *child;
1420 child = sel->child;
1421 while (child)
1423 release_subexpr_memory(child);
1424 child = child->next;
1429 /*! \brief
1430 * Makes an evaluated selection element static.
1432 * \param sel Selection element to make static.
1434 * The evaluated value becomes the value of the static element.
1435 * The element type is changed to SEL_CONST and the children are
1436 * deleted.
1438 static void
1439 make_static(t_selelem *sel)
1441 /* If this is a subexpression reference and the data is stored in the
1442 * child, we transfer data ownership before doing anything else. */
1443 if (sel->type == SEL_SUBEXPRREF
1444 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
1446 if (sel->child->child->flags & SEL_ALLOCDATA)
1448 sel->flags |= SEL_ALLOCDATA;
1449 sel->child->child->flags &= ~SEL_ALLOCDATA;
1451 if (sel->child->child->flags & SEL_ALLOCVAL)
1453 sel->flags |= SEL_ALLOCVAL;
1454 sel->v.nalloc = sel->child->child->v.nalloc;
1455 sel->child->child->flags &= ~SEL_ALLOCVAL;
1456 sel->child->child->v.nalloc = -1;
1459 /* When we reach here for parameter elements, the value is already
1460 * stored in the parent element, so make sure that it is not freed
1461 * through this element. */
1462 if (sel->type == SEL_SUBEXPRREF && sel->u.param)
1464 sel->u.param->val.nalloc = sel->v.nalloc;
1465 sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1466 sel->v.nalloc = -1;
1468 /* Free the children. */
1469 release_subexpr_memory(sel);
1470 _gmx_selelem_free_chain(sel->child);
1471 sel->child = NULL;
1472 /* Free the expression data as it is no longer needed */
1473 _gmx_selelem_free_exprdata(sel);
1474 /* Make the item static */
1475 sel->name = NULL;
1476 sel->type = SEL_CONST;
1477 sel->evaluate = NULL;
1478 sel->cdata->evaluate = NULL;
1479 /* Set the group value.
1480 * free_exprdata above frees the cgrp group, so we can just override it. */
1481 if (sel->v.type == GROUP_VALUE)
1483 gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
1487 /*! \brief
1488 * Evaluates a constant expression during analyze_static() and analyze_static2().
1490 * \param[in] data Evaluation data.
1491 * \param[in,out] sel Selection to process.
1492 * \param[in] g The evaluation group.
1493 * \returns 0 on success, a non-zero error code on error.
1495 static int
1496 process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1498 int rc;
1500 rc = 0;
1501 if (sel->v.type == GROUP_VALUE)
1503 if (sel->cdata->evaluate)
1505 rc = sel->cdata->evaluate(data, sel, g);
1508 /* Other constant expressions do not need evaluation */
1509 return rc;
1512 /*! \brief
1513 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1515 * \param[in,out] sel Selection to process.
1517 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1518 * and should receive the value from the compiler
1519 * (most parameter values are handled during parsing).
1520 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1521 * the function does nothing.
1522 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1523 * \ref SPAR_ATOMVAL, the function returns immediately.
1525 static void
1526 store_param_val(t_selelem *sel)
1528 /* Return immediately if there is no parameter. */
1529 if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
1531 return;
1534 /* Or if the value does not need storing. */
1535 if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1537 return;
1540 if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
1541 || sel->v.type == STR_VALUE)
1543 _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
1547 /*! \brief
1548 * Handles the initialization of a selection method during analyze_static() pass.
1550 * \param[in,out] sel Selection element to process.
1551 * \param[in] top Topology structure.
1552 * \param[in] isize Size of the evaluation group for the element.
1553 * \returns 0 on success, a non-zero error code on return.
1555 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1556 * method.
1557 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1558 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1560 static int
1561 init_method(t_selelem *sel, t_topology *top, int isize)
1563 t_selelem *child;
1564 bool bAtomVal;
1565 int rc;
1567 /* Find out whether there are any atom-valued parameters */
1568 bAtomVal = FALSE;
1569 child = sel->child;
1570 while (child)
1572 if (child->flags & SEL_ATOMVAL)
1574 bAtomVal = TRUE;
1576 child = child->next;
1579 /* Initialize the method */
1580 if (sel->u.expr.method->init
1581 && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
1583 sel->flags |= SEL_METHODINIT;
1584 rc = sel->u.expr.method->init(top, sel->u.expr.method->nparams,
1585 sel->u.expr.method->param, sel->u.expr.mdata);
1586 if (rc != 0)
1588 return rc;
1591 if (bAtomVal || !(sel->flags & SEL_OUTINIT))
1593 sel->flags |= SEL_OUTINIT;
1594 if (sel->u.expr.method->outinit)
1596 rc = sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
1597 if (rc != 0)
1599 return rc;
1601 if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
1603 alloc_selection_data(sel, isize, TRUE);
1606 else
1608 alloc_selection_data(sel, isize, TRUE);
1609 if ((sel->flags & SEL_DYNAMIC)
1610 && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
1612 sel->v.nr = isize;
1614 /* If the method is char-valued, pre-allocate the strings. */
1615 if (sel->u.expr.method->flags & SMETH_CHARVAL)
1617 int i;
1619 /* A sanity check */
1620 if (sel->v.type != STR_VALUE)
1622 gmx_bug("internal error");
1623 return -1;
1625 sel->flags |= SEL_ALLOCDATA;
1626 for (i = 0; i < isize; ++i)
1628 if (sel->v.u.s[i] == NULL)
1630 snew(sel->v.u.s[i], 2);
1637 return 0;
1640 /*! \brief
1641 * Evaluates the static part of a boolean expression.
1643 * \param[in] data Evaluation data.
1644 * \param[in,out] sel Boolean selection element whose children should be
1645 * processed.
1646 * \param[in] g The evaluation group.
1647 * \returns 0 on success, a non-zero error code on error.
1649 * reorder_item_static_children() should have been called.
1651 static int
1652 evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
1653 gmx_ana_index_t *g)
1655 t_selelem *child, *next;
1656 int rc;
1658 /* Find the last static subexpression */
1659 child = sel->child;
1660 while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
1662 child = child->next;
1664 if (!(child->cdata->flags & SEL_CDATA_STATIC))
1666 return 0;
1669 /* Evalute the static part if there is more than one expression */
1670 if (child != sel->child)
1672 next = child->next;
1673 child->next = NULL;
1674 rc = sel->cdata->evaluate(data, sel, g);
1675 if (rc != 0)
1677 return rc;
1679 /* Replace the subexpressions with the result */
1680 _gmx_selelem_free_chain(sel->child);
1681 snew(child, 1);
1682 child->type = SEL_CONST;
1683 child->flags = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
1684 _gmx_selelem_set_vtype(child, GROUP_VALUE);
1685 child->evaluate = NULL;
1686 _gmx_selvalue_reserve(&child->v, 1);
1687 gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
1688 init_item_compilerdata(child);
1689 init_item_minmax_groups(child);
1690 child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
1691 child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
1692 child->next = next;
1693 sel->child = child;
1695 else if (child->evaluate)
1697 rc = child->evaluate(data, child, g);
1698 if (rc != 0)
1700 return rc;
1703 /* Set the evaluation function for the constant element.
1704 * We never need to evaluate the element again during compilation,
1705 * but we may need to evaluate the static part again if the
1706 * expression is not an OR with a static evaluation group.
1707 * If we reach here with a NOT expression, the NOT expression
1708 * is also static, and will be made a constant later, so don't waste
1709 * time copying the group. */
1710 child->evaluate = NULL;
1711 if (sel->u.boolt == BOOL_NOT
1712 || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
1713 && sel->u.boolt == BOOL_OR))
1715 child->cdata->evaluate = NULL;
1717 else
1719 child->cdata->evaluate = &_gmx_sel_evaluate_static;
1720 /* The cgrp has only been allocated if it originated from an
1721 * external index group. In that case, we need special handling
1722 * to preserve the name of the group and to not leak memory.
1723 * If cgrp has been set in make_static(), it is not allocated,
1724 * and hence we can overwrite it safely. */
1725 if (child->u.cgrp.nalloc_index > 0)
1727 char *name = child->u.cgrp.name;
1728 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, FALSE);
1729 gmx_ana_index_squeeze(&child->u.cgrp);
1730 child->u.cgrp.name = name;
1732 else
1734 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, TRUE);
1737 return 0;
1740 /*! \brief
1741 * Evaluates the minimum and maximum groups for a boolean expression.
1743 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
1744 * \param[in] g Group for which \p sel has been evaluated.
1745 * \param[out] gmin Largest subset of the possible values of \p sel.
1746 * \param[out] gmax Smallest superset of the possible values of \p sel.
1748 * This is a helper function for analyze_static() that is called for
1749 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
1750 * It uses the minimum and maximum groups of the children to calculate
1751 * the minimum and maximum groups for \p sel, and also updates the static
1752 * part of \p sel (which is in the first child) if the children give
1753 * cause for this.
1755 * This function may allocate some extra memory for \p gmin and \p gmax,
1756 * but as these groups are freed at the end of analyze_static() (which is
1757 * reached shortly after this function returns), this should not be a major
1758 * problem.
1760 static void
1761 evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
1762 gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
1764 t_selelem *child;
1766 switch (sel->u.boolt)
1768 case BOOL_NOT:
1769 gmx_ana_index_reserve(gmin, g->isize);
1770 gmx_ana_index_reserve(gmax, g->isize);
1771 gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
1772 gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
1773 break;
1775 case BOOL_AND:
1776 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, TRUE);
1777 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, TRUE);
1778 child = sel->child->next;
1779 while (child && gmax->isize > 0)
1781 gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
1782 gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
1783 child = child->next;
1785 /* Update the static part if other expressions limit it */
1786 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
1787 && sel->child->v.u.g->isize > gmax->isize)
1789 gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
1790 gmx_ana_index_squeeze(sel->child->v.u.g);
1791 if (sel->child->u.cgrp.isize > 0)
1793 gmx_ana_index_copy(&sel->child->u.cgrp, gmax, FALSE);
1794 gmx_ana_index_squeeze(&sel->child->u.cgrp);
1797 break;
1799 case BOOL_OR:
1800 /* We can assume here that the gmin of children do not overlap
1801 * because of the way _gmx_sel_evaluate_or() works. */
1802 gmx_ana_index_reserve(gmin, g->isize);
1803 gmx_ana_index_reserve(gmax, g->isize);
1804 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, FALSE);
1805 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, FALSE);
1806 child = sel->child->next;
1807 while (child && gmin->isize < g->isize)
1809 gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
1810 gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
1811 child = child->next;
1813 /* Update the static part if other expressions have static parts
1814 * that are not included. */
1815 if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
1816 && sel->child->v.u.g->isize < gmin->isize)
1818 gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
1819 gmx_ana_index_copy(sel->child->v.u.g, gmin, FALSE);
1820 if (sel->child->u.cgrp.isize > 0)
1822 gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
1823 gmx_ana_index_copy(&sel->child->u.cgrp, gmin, FALSE);
1826 break;
1828 case BOOL_XOR: /* Should not be reached */
1829 gmx_impl("xor expressions not implemented");
1830 break;
1834 /*! \brief
1835 * Evaluates the static parts of \p sel and analyzes the structure.
1837 * \param[in] data Evaluation data.
1838 * \param[in,out] sel Selection currently being evaluated.
1839 * \param[in] g Group for which \p sel should be evaluated.
1840 * \returns 0 on success, a non-zero error code on error.
1842 * This function is used as the replacement for the \c t_selelem::evaluate
1843 * function pointer.
1844 * It does the single most complex task in the compiler: after all elements
1845 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
1846 * have been properly initialized, enough memory has been allocated for
1847 * storing the value of each expression, and the static parts of the
1848 * expressions have been evaluated.
1849 * The above is exactly true only for elements other than subexpressions:
1850 * another pass is required for subexpressions that are referred to more than
1851 * once to evaluate the static parts.
1852 * This second pass is performed by analyze_static2().
1854 * \see analyze_static2()
1856 static int
1857 analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1859 t_selelem *child, *next;
1860 gmx_ana_index_t gmin, gmax;
1861 bool bDelayAlloc;
1862 int rc;
1864 gmx_ana_index_clear(&gmin);
1865 gmx_ana_index_clear(&gmax);
1866 bDelayAlloc = FALSE;
1868 if (sel->type != SEL_ROOT && g)
1870 bDelayAlloc = !alloc_selection_data(sel, g->isize, FALSE);
1873 /* TODO: This switch is awfully long... */
1874 rc = 0;
1875 switch (sel->type)
1877 case SEL_CONST:
1878 rc = process_const(data, sel, g);
1879 break;
1881 case SEL_EXPRESSION:
1882 case SEL_MODIFIER:
1883 rc = _gmx_sel_evaluate_method_params(data, sel, g);
1884 if (rc != 0)
1886 return rc;
1888 rc = init_method(sel, data->top, g->isize);
1889 if (rc != 0)
1891 return rc;
1893 if (!(sel->flags & SEL_DYNAMIC))
1895 rc = sel->cdata->evaluate(data, sel, g);
1896 if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
1898 make_static(sel);
1901 else
1903 /* Modifiers need to be evaluated even though they process
1904 * positions to get the modified output groups from the
1905 * maximum possible selections. */
1906 if (sel->type == SEL_MODIFIER)
1908 rc = sel->cdata->evaluate(data, sel, g);
1910 gmx_ana_index_copy(&gmax, g, TRUE);
1912 break;
1914 case SEL_BOOLEAN:
1915 if (!(sel->flags & SEL_DYNAMIC))
1917 rc = sel->cdata->evaluate(data, sel, g);
1918 if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
1920 make_static(sel);
1923 else
1925 /* Evalute the static part if there is more than one expression */
1926 rc = evaluate_boolean_static_part(data, sel, g);
1927 if (rc != 0)
1929 return rc;
1932 /* Evaluate the selection.
1933 * If the type is boolean, we must explicitly handle the
1934 * static part evaluated in evaluate_boolean_static_part()
1935 * here because g may be larger. */
1936 if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
1938 rc = sel->cdata->evaluate(data, sel, sel->child->v.u.g);
1940 else
1942 rc = sel->cdata->evaluate(data, sel, g);
1944 if (rc != 0)
1946 return rc;
1949 /* Evaluate minimal and maximal selections */
1950 evaluate_boolean_minmax_grps(sel, g, &gmin, &gmax);
1952 break;
1954 case SEL_ARITHMETIC:
1955 if (!(sel->flags & SEL_DYNAMIC))
1957 rc = sel->cdata->evaluate(data, sel, g);
1958 if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
1960 make_static(sel);
1963 else
1965 rc = _gmx_sel_evaluate_children(data, sel, g);
1966 if (rc != 0)
1968 return rc;
1970 sel->v.nr = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
1971 gmx_ana_index_copy(&gmax, g, TRUE);
1973 break;
1975 case SEL_ROOT:
1976 rc = sel->cdata->evaluate(data, sel, g);
1977 break;
1979 case SEL_SUBEXPR:
1980 if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
1982 rc = sel->cdata->evaluate(data, sel, g);
1983 _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
1985 else if (sel->u.cgrp.isize == 0)
1987 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
1988 rc = sel->cdata->evaluate(data, sel, g);
1990 else
1992 int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
1993 if (isize > 0)
1995 isize += sel->u.cgrp.isize;
1996 gmx_ana_index_reserve(&sel->u.cgrp, isize);
1997 alloc_selection_data(sel, isize, FALSE);
1999 rc = sel->cdata->evaluate(data, sel, g);
2001 break;
2003 case SEL_SUBEXPRREF:
2004 if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2006 /* The subexpression should have been evaluated if g is NULL
2007 * (i.e., this is a method parameter or a direct value of a
2008 * selection). */
2009 alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
2011 rc = sel->cdata->evaluate(data, sel, g);
2012 if (rc != 0)
2014 return rc;
2016 if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2017 && (sel->child->child->flags & SEL_ALLOCVAL))
2019 _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
2021 /* Store the parameter value if required */
2022 store_param_val(sel);
2023 if (!(sel->flags & SEL_DYNAMIC))
2025 if (sel->cdata->flags & SEL_CDATA_STATIC)
2027 make_static(sel);
2030 else
2032 if (sel->child->refcount <= 2 || !g)
2034 gmx_ana_index_copy(&gmin, sel->child->cdata->gmin, TRUE);
2035 gmx_ana_index_copy(&gmax, sel->child->cdata->gmax, TRUE);
2037 else
2039 gmx_ana_index_reserve(&gmin, min(g->isize, sel->child->cdata->gmin->isize));
2040 gmx_ana_index_reserve(&gmax, min(g->isize, sel->child->cdata->gmax->isize));
2041 gmx_ana_index_intersection(&gmin, sel->child->cdata->gmin, g);
2042 gmx_ana_index_intersection(&gmax, sel->child->cdata->gmax, g);
2045 break;
2047 /* Exit if there was some problem */
2048 if (rc != 0)
2050 return rc;
2053 /* Update the minimal and maximal evaluation groups */
2054 if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
2056 gmx_ana_index_reserve(sel->cdata->gmin, sel->cdata->gmin->isize + gmin.isize);
2057 gmx_ana_index_reserve(sel->cdata->gmax, sel->cdata->gmax->isize + gmax.isize);
2058 gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin, &gmin);
2059 gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax, &gmax);
2061 /* Replace the result of the evaluation */
2062 /* This is not necessary for subexpressions or for boolean negations
2063 * because the evaluation function already has done it properly. */
2064 if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
2065 && sel->type != SEL_SUBEXPR
2066 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
2068 if (sel->cdata->flags & SEL_CDATA_EVALMAX)
2070 gmx_ana_index_copy(sel->v.u.g, &gmax, FALSE);
2072 else
2074 gmx_ana_index_copy(sel->v.u.g, &gmin, FALSE);
2077 gmx_ana_index_deinit(&gmin);
2078 gmx_ana_index_deinit(&gmax);
2080 /* Make sure that enough data storage has been allocated */
2081 if (sel->type != SEL_ROOT
2082 && ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
2083 || (!(sel->flags & SEL_DYNAMIC)
2084 && !(sel->cdata->flags & SEL_CDATA_STATIC))))
2086 alloc_selection_data(sel, sel->cdata->gmax->isize, TRUE);
2087 /* Make sure that the new value pointer is stored if required */
2088 store_param_val(sel);
2090 return 0;
2093 /*! \brief
2094 * Evaluates the static parts of \p sel and analyzes the structure.
2096 * \param[in] data Evaluation data.
2097 * \param[in,out] sel Selection currently being evaluated.
2098 * \param[in] g Group for which \p sel should be evaluated.
2099 * \returns 0 on success, a non-zero error code on error.
2101 * This function is a simpler version of analyze_static() that is used
2102 * during a second evaluation round, and can thus use information calculated
2103 * by analyze_static().
2104 * It is also used as the replacement for the \c t_selelem::evaluate
2105 * function pointer.
2106 * It is used to evaluate the static parts of subexpressions that could not
2107 * be evaluated during the analyze_static() pass.
2109 * \see analyze_static()
2111 static int
2112 analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
2114 int rc;
2116 rc = 0;
2117 switch (sel->type)
2119 case SEL_CONST:
2120 rc = process_const(data, sel, g);
2121 break;
2123 case SEL_EXPRESSION:
2124 case SEL_BOOLEAN:
2125 case SEL_SUBEXPRREF:
2126 case SEL_ARITHMETIC:
2127 if (sel->cdata->flags & SEL_CDATA_STATIC)
2129 rc = sel->cdata->evaluate(data, sel, g);
2130 if (rc == 0)
2132 make_static(sel);
2135 else if (sel->type == SEL_BOOLEAN)
2137 rc = evaluate_boolean_static_part(data, sel, g);
2138 if (rc == 0)
2140 rc = sel->cdata->evaluate(data, sel, g);
2143 break;
2145 case SEL_ROOT: /* Roots should not be present here */
2146 case SEL_MODIFIER: /* Modifiers should not be present here */
2147 case SEL_SUBEXPR:
2148 rc = sel->cdata->evaluate(data, sel, g);
2149 break;
2151 /* Exit if there was some problem */
2152 if (rc != 0)
2154 return rc;
2157 /* Replace the result of the evaluation */
2158 /* This is not necessary for subexpressions or for boolean negations
2159 * because the evaluation function already has done it properly. */
2160 if (sel->v.type == GROUP_VALUE && !(sel->cdata->flags & SEL_CDATA_STATIC)
2161 && sel->type != SEL_SUBEXPR
2162 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
2164 if (sel->cdata->flags & SEL_CDATA_EVALMAX)
2166 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
2168 else
2170 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, FALSE);
2174 return 0;
2178 /********************************************************************
2179 * ROOT ITEM INITIALIZATION COMPILER PASS
2180 ********************************************************************/
2182 /*! \brief
2183 * Initializes a \ref SEL_ROOT element.
2185 * \param root Root element to initialize.
2186 * \param[in] gall Group of all atoms.
2188 * Checks whether it is necessary to evaluate anything through the root
2189 * element, and either clears the evaluation function or initializes the
2190 * evaluation group.
2192 static void
2193 init_root_item(t_selelem *root, gmx_ana_index_t *gall)
2195 t_selelem *expr;
2196 char *name;
2198 /* Process subexpressions */
2199 if (root->child->type == SEL_SUBEXPR)
2201 if (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
2202 || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2203 && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL)))
2205 /* Subexpressions with non-static evaluation group should not be
2206 * evaluated by the root. */
2207 root->evaluate = NULL;
2208 if (root->cdata)
2210 root->cdata->evaluate = NULL;
2215 /* Set the evaluation group */
2216 name = root->u.cgrp.name;
2217 if (root->evaluate)
2219 expr = root->child;
2220 /* Non-atom-valued non-group expressions don't care about the group, so
2221 * don't allocate any memory for it. */
2222 if ((expr->flags & SEL_VARNUMVAL)
2223 || ((expr->flags & SEL_SINGLEVAL) && expr->type != GROUP_VALUE))
2225 gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
2227 else if (expr->cdata->gmax->isize == gall->isize)
2229 /* Save some memory by only referring to the global group. */
2230 gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
2232 else
2234 gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
2236 /* For selections, store the maximum group for
2237 * gmx_ana_selcollection_evaluate_fin() as the value of the root
2238 * element (unused otherwise). */
2239 if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
2241 _gmx_selelem_set_vtype(root, GROUP_VALUE);
2242 root->flags |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
2243 _gmx_selvalue_reserve(&root->v, 1);
2244 gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
2247 else
2249 gmx_ana_index_clear(&root->u.cgrp);
2251 root->u.cgrp.name = name;
2255 /********************************************************************
2256 * SUBEXPRESSION OPTIMIZATION PASS
2257 ********************************************************************/
2259 /*! \brief
2260 * Optimizes subexpression evaluation.
2262 * \param sel Root of the selection subtree to process.
2264 * Optimizes away some unnecessary evaluation of subexpressions that are only
2265 * referenced once.
2267 static void
2268 postprocess_item_subexpressions(t_selelem *sel)
2270 /* Process children. */
2271 if (sel->type != SEL_SUBEXPRREF)
2273 t_selelem *child;
2275 child = sel->child;
2276 while (child)
2278 postprocess_item_subexpressions(child);
2279 child = child->next;
2283 /* Replace the evaluation function of statically evaluated subexpressions
2284 * for which the static group was not known in advance. */
2285 if (sel->type == SEL_SUBEXPR && sel->refcount > 2
2286 && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
2287 && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
2289 char *name;
2291 /* We need to free memory allocated for the group, because it is no
2292 * longer needed (and would be lost on next call to the evaluation
2293 * function). But we need to preserve the name. */
2294 name = sel->u.cgrp.name;
2295 gmx_ana_index_deinit(&sel->u.cgrp);
2296 sel->u.cgrp.name = name;
2298 sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
2299 if (sel->cdata)
2301 sel->cdata->evaluate = sel->evaluate;
2303 _gmx_selelem_free_values(sel->child);
2304 sel->child->mempool = NULL;
2305 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
2306 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2309 /* Adjust memory allocation flags for subexpressions that are used only
2310 * once. This is not strictly necessary, but we do it to have the memory
2311 * managed consistently for all types of subexpressions. */
2312 if (sel->type == SEL_SUBEXPRREF
2313 && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
2315 if (sel->child->child->flags & SEL_ALLOCVAL)
2317 sel->flags |= SEL_ALLOCVAL;
2318 sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
2319 sel->v.nalloc = sel->child->child->v.nalloc;
2320 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2321 sel->child->child->v.nalloc = -1;
2325 /* Do the same for subexpressions that are evaluated at once for all atoms. */
2326 if (sel->type == SEL_SUBEXPR
2327 && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
2328 && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
2330 sel->flags |= SEL_ALLOCVAL;
2331 sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
2332 sel->v.nalloc = sel->child->v.nalloc;
2333 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
2334 sel->child->v.nalloc = -1;
2339 /********************************************************************
2340 * COM CALCULATION COMPILER PASS
2341 ********************************************************************/
2343 /*! \brief
2344 * Initializes COM/COG calculation for method expressions that require it.
2346 * \param sel Selection subtree to process.
2347 * \param[in,out] pcc Position calculation collection to use.
2348 * \param[in] type Default position calculation type.
2349 * \param[in] flags Flags for default position calculation.
2350 * \returns 0 on success, a non-zero error code on error.
2352 * Searches recursively through the selection tree for dynamic
2353 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
2354 * function.
2355 * For each such element found, position calculation is initialized
2356 * for the maximal evaluation group.
2357 * The type of the calculation is determined by \p type and \p flags.
2358 * No calculation is initialized if \p type equals \ref POS_ATOM and
2359 * the method also defines the \c gmx_ana_selmethod_t::update method.
2361 static int
2362 init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
2363 e_poscalc_t type, int flags)
2365 t_selelem *child;
2366 int rc;
2368 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
2369 if (sel->type == SEL_EXPRESSION && sel->u.expr.method
2370 && sel->u.expr.method->pupdate)
2372 if (!sel->u.expr.method->update || type != POS_ATOM)
2374 /* Create a default calculation if one does not yet exist */
2375 int cflags;
2376 cflags = 0;
2377 if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
2379 cflags |= POS_DYNAMIC;
2381 if (!sel->u.expr.pc)
2383 cflags |= flags;
2384 rc = gmx_ana_poscalc_create(&sel->u.expr.pc, pcc, type, cflags);
2385 if (rc != 0)
2387 return rc;
2390 else
2392 gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
2394 gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
2395 snew(sel->u.expr.pos, 1);
2396 gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
2400 /* Call recursively for all children unless the children have already been processed */
2401 if (sel->type != SEL_SUBEXPRREF)
2403 child = sel->child;
2404 while (child)
2406 rc = init_item_comg(child, pcc, type, flags);
2407 if (rc != 0)
2409 return rc;
2411 child = child->next;
2414 return 0;
2418 /********************************************************************
2419 * FREE COMPILER DATA PASS
2420 ********************************************************************/
2422 /*! \brief
2423 * Frees the allocated compiler data recursively.
2425 * \param sel Root of the selection subtree to process.
2427 * Frees the data allocated for the compilation process.
2429 static void
2430 free_item_compilerdata(t_selelem *sel)
2432 t_selelem *child;
2434 /* Free compilation data */
2435 _gmx_selelem_free_compiler_data(sel);
2437 /* Call recursively for all children unless the children have already been processed */
2438 if (sel->type != SEL_SUBEXPRREF)
2440 child = sel->child;
2441 while (child)
2443 free_item_compilerdata(child);
2444 child = child->next;
2450 /********************************************************************
2451 * INFORMATION UPDATE
2452 ********************************************************************/
2454 /*! \brief
2455 * Updates the information about the selection.
2457 * \param[in] top Topology information.
2458 * \param[in] ngrps Number of elements in the \p sel array.
2459 * \param[in,out] sel Array of selections to update.
2460 * \param[in] bMaskOnly TRUE if the positions will always be calculated
2461 * for all atoms, i.e., the masses/charges do not change.
2463 * Initializes total masses and charges.
2465 static void
2466 update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
2467 bool bMaskOnly)
2469 int g, b, i;
2471 for (g = 0; g < ngrps; ++g)
2473 sel[g]->g = sel[g]->p.g;
2474 snew(sel[g]->orgm, sel[g]->p.nr);
2475 snew(sel[g]->orgq, sel[g]->p.nr);
2476 for (b = 0; b < sel[g]->p.nr; ++b)
2478 sel[g]->orgq[b] = 0;
2479 if (top)
2481 sel[g]->orgm[b] = 0;
2482 for (i = sel[g]->p.m.mapb.index[b]; i < sel[g]->p.m.mapb.index[b+1]; ++i)
2484 sel[g]->orgm[b] += top->atoms.atom[sel[g]->g->index[i]].m;
2485 sel[g]->orgq[b] += top->atoms.atom[sel[g]->g->index[i]].q;
2488 else
2490 sel[g]->orgm[b] = 1;
2493 if (sel[g]->bDynamic && !bMaskOnly)
2495 snew(sel[g]->m, sel[g]->p.nr);
2496 snew(sel[g]->q, sel[g]->p.nr);
2497 for (b = 0; b < sel[g]->p.nr; ++b)
2499 sel[g]->m[b] = sel[g]->orgm[b];
2500 sel[g]->q[b] = sel[g]->orgq[b];
2503 else
2505 sel[g]->m = sel[g]->orgm;
2506 sel[g]->q = sel[g]->orgq;
2512 /********************************************************************
2513 * MAIN COMPILATION FUNCTION
2514 ********************************************************************/
2517 * \param[in,out] sc Selection collection to be compiled.
2518 * \returns 0 on successful compilation, a non-zero error code on error.
2520 * Before compilation, the selection collection should have been initialized
2521 * with gmx_ana_selcollection_parse_*().
2522 * The compiled selection collection can be passed to
2523 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2524 * If an error occurs, \p sc is cleared.
2526 * The covered fraction information in \p sc is initialized to
2527 * \ref CFRAC_NONE.
2530 gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
2532 gmx_sel_evaluate_t evaldata;
2533 t_selelem *item;
2534 e_poscalc_t post;
2535 int flags;
2536 int rc;
2538 rc = _gmx_sel_mempool_create(&sc->mempool);
2539 if (rc != 0)
2541 return rc;
2543 _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
2544 sc->top, NULL, NULL);
2546 /* Clear the symbol table because it is not possible to parse anything
2547 * after compilation, and variable references in the symbol table can
2548 * also mess up the compilation and/or become invalid.
2550 _gmx_selcollection_clear_symtab(sc);
2552 /* Remove any unused variables. */
2553 sc->root = remove_unused_subexpressions(sc->root);
2554 /* Extract subexpressions into separate roots */
2555 sc->root = extract_subexpressions(sc->root);
2557 /* Initialize the evaluation callbacks and process the tree structure
2558 * to conform to the expectations of the callback functions. */
2559 /* Also, initialize and allocate the compiler data structure */
2560 item = sc->root;
2561 while (item)
2563 /* Process boolean and arithmetic expressions. */
2564 optimize_boolean_expressions(item);
2565 reorder_boolean_static_children(item);
2566 if (!optimize_arithmetic_expressions(item))
2568 /* FIXME: Clean up the collection */
2569 return -1;
2571 /* Initialize evaluation function. */
2572 if (!init_item_evalfunc(item))
2574 /* FIXME: Clean up the collection */
2575 return -1;
2577 setup_memory_pooling(item, sc->mempool);
2578 /* Initialize the compiler data */
2579 init_item_compilerdata(item);
2580 init_item_staticeval(item);
2581 item = item->next;
2583 /* Initialize evaluation output.
2584 * Requires compiler flags for the full tree. */
2585 item = sc->root;
2586 while (item)
2588 init_item_evaloutput(item);
2589 item = item->next;
2591 /* Initialize minimum/maximum index groups.
2592 * Requires evaluation output for the full tree. */
2593 item = sc->root;
2594 while (item)
2596 init_item_minmax_groups(item);
2597 item = item->next;
2599 /* Initialize the evaluation index groups */
2600 initialize_evalgrps(sc);
2602 /* Evaluate all static parts of the selection and analyze the tree
2603 * to allocate enough memory to store the value of each dynamic subtree. */
2604 item = sc->root;
2605 while (item)
2607 if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2
2608 && !(item->child->cdata->flags & SEL_CDATA_FULLEVAL))
2610 mark_subexpr_dynamic(item->child, TRUE);
2612 set_evaluation_function(item, &analyze_static);
2613 rc = item->evaluate(&evaldata, item, NULL);
2614 if (rc != 0)
2616 /* FIXME: Clean up the collection */
2617 return rc;
2619 item = item->next;
2622 /* At this point, static subexpressions no longer have references to them,
2623 * so they can be removed. */
2624 sc->root = remove_unused_subexpressions(sc->root);
2626 /* Do a second pass to evaluate static parts of common subexpressions */
2627 /* Note that the refcount check skips constant subexpressions completely
2628 * since they were already evaluated by analyze_static(). */
2629 item = sc->root;
2630 while (item)
2632 if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2
2633 && !(item->child->cdata->flags & SEL_CDATA_FULLEVAL))
2635 mark_subexpr_dynamic(item->child, FALSE);
2636 item->child->u.cgrp.isize = 0;
2637 /* We won't clear item->child->v.u.g here, because it may
2638 * be static, and hence actually point to item->child->cdata->gmax,
2639 * which is used below. We could also check whether this is the
2640 * case and only clear the group otherwise, but because the value
2641 * is actually overwritten immediately in the evaluate call, we
2642 * won't, because similar problems may arise if gmax handling ever
2643 * changes and the check were not updated. */
2644 set_evaluation_function(item, &analyze_static2);
2645 rc = item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
2646 if (rc != 0)
2648 /* FIXME: Clean up the collection */
2649 return rc;
2652 item = item->next;
2655 /* We need a yet another pass of subexpression removal to remove static
2656 * subexpressions referred to by common dynamic subexpressions. */
2657 sc->root = remove_unused_subexpressions(sc->root);
2659 /* Initialize evaluation groups, position calculations for methods, perform
2660 * some final optimization, and free the memory allocated for the
2661 * compilation. */
2662 /* By default, use whole residues/molecules. */
2663 flags = POS_COMPLWHOLE;
2664 rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &post, &flags);
2665 if (rc != 0)
2667 gmx_bug("invalid default reference position type");
2668 /* FIXME: Clean up the collection */
2669 return rc;
2671 item = sc->root;
2672 while (item)
2674 init_root_item(item, &sc->gall);
2675 postprocess_item_subexpressions(item);
2676 rc = init_item_comg(item, sc->pcc, post, flags);
2677 if (rc != 0)
2679 /* FIXME: Clean up the collection */
2680 return rc;
2682 free_item_compilerdata(item);
2683 item = item->next;
2686 /* Allocate memory for the evaluation memory pool. */
2687 rc = _gmx_sel_mempool_reserve(sc->mempool, 0);
2688 if (rc != 0)
2690 return rc;
2693 /* Finish up by updating some information */
2694 update_info(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
2696 return 0;