Fixed memory handling issues in selections.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / selection / compiler.c
blob559d24ffafc34bb6072f351ec0e55663a6cabcb9
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.
44 /*! \internal
45 * \page selcompiler Selection compilation
47 * The compiler takes the selection element tree from the selection parser
48 * (see \ref selparser) as input. It initializes missing fields, reorganizes,
49 * simplifies and optimizes the tree, and evaluates static parts of the
50 * selections.
51 * The compilation is a global process, i.e., all selections are compiled
52 * and optimized simultaneously. Hence, all the selections should be parsed
53 * before the compiler can be called.
55 * \todo
56 * Write documentation for the overall structure of the compiler and
57 * the optimizations that the compiler does.
59 * \todo
60 * Describe the selection element tree after compilation in more detail.
63 * \section selcompiler_tree Element tree after compilation
65 * After the compilation, the selection element tree is suitable for
66 * gmx_ana_selcollection_evaluate(). Here, the structure of the tree
67 * is described.
68 * Enough memory has been allocated for \ref t_selelem::v
69 * (and \ref t_selelem::cgrp for \ref SEL_SUBEXPR elements) to allow the
70 * selection to be evaluated without allocating any memory.
73 * \subsection selcompiler_tree_root Root elements
75 * The top level of the tree consists of a chain of \ref SEL_ROOT elements.
76 * These are used for two purposes:
77 * -# A selection that should be evaluated.
78 * These elements appear in the same order as the selections in the input.
79 * For these elements, \ref t_selelem::v has been set to the maximum
80 * possible group that the selection can evaluate to, and
81 * \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
82 * -# A subexpression that appears in one or more selections.
83 * Each selection that gives a value for a method parameter is a
84 * potential subexpression, as is any variable value.
85 * Only subexpressions that require evaluation for each frame are left
86 * after the selection is compiled.
87 * Each subexpression appears in the chain before any references to it.
88 * For these elements, \c t_selelem::cgrp has been set to the group
89 * that should be used to evaluate the subexpression.
90 * If \c t_selelem::cgrp is empty, the total evaluation group is not known
91 * in advance. If this is the case, \c t_selelem::evaluate is also NULL.
93 * The children of the \ref SEL_ROOT elements can be used to distinguish
94 * the two types of root elements from each other; the rules are the same
95 * as for the parsed tree (see \ref selparser_tree_root).
96 * Subexpressions are treated as if they had been provided through variables.
98 * Selection names are stored as after parsing (see \ref selparser_tree_root),
99 * with the exception that default names have been generated for selections
100 * that did not have an explicit name.
103 * \subsection selcompiler_tree_const Constant elements
105 * All (sub)selections that do not require particle positions have been
106 * replaced with \ref SEL_CONST elements.
107 * Constant elements from the parser are also retained if present in
108 * dynamic parts of the selections.
109 * Several constant elements with a NULL \c t_selelem::evaluate are left for
110 * debugging purposes; only the ones for \ref BOOL_OR expressions are used
111 * during evaluation.
113 * The value is stored in \c t_selelem::v, and for group values with an
114 * evaluation function set, also in \c t_selelem::cgrp.
115 * For \ref GROUP_VALUE elements, unnecessary atoms (i.e., atoms that
116 * could never be selected) have been removed from the value.
118 * \ref SEL_CONST elements have no children.
121 * \subsection selcompiler_tree_method Method evaluation elements
123 * (to be written)
126 * \subsection selcompiler_tree_subexpr Subexpression elements
128 * As described in \ref selcompiler_tree_root, subexpressions are created
129 * for each variable and each expression that gives a value to a selection
130 * method parameter. As the only child of the \ref SEL_ROOT element,
131 * these elements have a \ref SEL_SUBEXPR element. The \ref SEL_SUBEXPR
132 * element has a single child, which evaluates the actual expression.
133 * After compilation, only subexpressions that require particle positions
134 * for evaluation are left.
135 * For non-variable subexpression, automatic names have been generated to
136 * help in debugging.
138 * (write about the contents of \ref SEL_SUBEXPR elements)
140 * \ref SEL_SUBEXPRREF elements are used to describe references to
141 * subexpressions. They have always a single child, which is the
142 * \ref SEL_SUBEXPR element being referenced.
144 * If a subexpression is used only once and can be evaluated statically,
145 * the evaluation has been optimized by setting the child of the
146 * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
147 * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
148 * and \ref SEL_SUBEXPR elements only propagate some status information,
149 * but do not unnecessarily copy the values.
152 * \subsection selcompiler_tree_bool Boolean elements
154 * \ref SEL_BOOLEAN elements have been merged such that one element
155 * may carry out evaluation of more than one operation of the same type.
156 * The static parts of the expressions have been evaluated, and are placed
157 * in the first child. These are followed by the dynamic expressions, in the
158 * order provided by the user.
160 #ifdef HAVE_CONFIG_H
161 #include <config.h>
162 #endif
164 #include <stdarg.h>
166 #include <smalloc.h>
167 #include <string2.h>
168 #include <vec.h>
170 #include <indexutil.h>
171 #include <poscalc.h>
172 #include <selection.h>
173 #include <selmethod.h>
175 #include "evaluate.h"
176 #include "keywords.h"
177 #include "selcollection.h"
178 #include "selelem.h"
180 /*! \internal \brief
181 * Internal data structure used by the compiler.
183 typedef struct t_compiler_data
185 /** The real evaluation method. */
186 sel_evalfunc evaluate;
187 /*! \brief
188 * Whether the element is a method parameter.
190 * This flag is set for \ref SEL_SUBEXPR elements that are used to
191 * evaluate non-atom-valued selection method parameters.
193 bool bMethodParam;
194 /*! \brief
195 * TRUE if the whole subexpression should be treated static.
197 * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
198 * but it is also FALSE for static elements within common subexpressions.
200 bool bStatic;
201 /** TRUE if the subexpression will always be evaluated with the same group. */
202 bool bStaticEval;
203 /** TRUE if the compiler evaluation routine should return the maximal selection. */
204 bool bEvalMax;
205 /** Smallest selection that can be selected by the subexpression. */
206 gmx_ana_index_t *gmin;
207 /** Largest selection that can be selected by the subexpression. */
208 gmx_ana_index_t *gmax;
209 /** TRUE if memory has been allocated for \p gmin and \p gmax. */
210 bool bMinMaxAlloc;
211 } t_compiler_data;
214 /********************************************************************
215 * COMPILER UTILITY FUNCTIONS
216 ********************************************************************/
219 * \param sel Selection to free.
221 * This function only frees the data for the given selection, not its children.
222 * It is safe to call the function when compiler data has not been allocated
223 * or has already been freed; in such a case, nothing is done.
225 void
226 _gmx_selelem_free_compiler_data(t_selelem *sel)
228 if (sel->cdata)
230 sel->evaluate = sel->cdata->evaluate;
231 if (sel->cdata->bMinMaxAlloc)
233 sel->cdata->gmin->name = NULL;
234 sel->cdata->gmax->name = NULL;
235 gmx_ana_index_deinit(sel->cdata->gmin);
236 gmx_ana_index_deinit(sel->cdata->gmax);
237 sfree(sel->cdata->gmin);
238 sfree(sel->cdata->gmax);
240 sfree(sel->cdata);
242 sel->cdata = NULL;
245 /*! \brief
246 * Allocates memory for storing the evaluated value of a selection element.
248 * \param sel Selection element to initialize
249 * \param[in] isize Maximum evaluation group size.
250 * \param[in] bChildEval TRUE if children have already been processed.
251 * \returns TRUE if the memory was allocated, FALSE if children need to
252 * be processed first.
254 * If called more than once, memory is (re)allocated to ensure that the
255 * maximum of the \p isize values can be stored.
257 static bool
258 alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
260 int nalloc;
262 /* Find out the number of elements to allocate */
263 if (sel->flags & SEL_SINGLEVAL)
265 nalloc = 1;
267 else if (sel->flags & SEL_ATOMVAL)
269 nalloc = isize;
271 else /* sel->flags should contain SEL_VARNUMVAL */
273 t_selelem *child;
275 if (!bChildEval)
277 return FALSE;
279 child = (sel->type == SEL_SUBEXPRREF ? sel->child : sel);
280 if (child->type == SEL_SUBEXPR)
282 child = child->child;
284 nalloc = (sel->v.type == POS_VALUE) ? child->v.u.p->nr : child->v.nr;
286 /* For positions, we actually want to allocate just a single structure
287 * for nalloc positions. */
288 if (sel->v.type == POS_VALUE)
290 isize = nalloc;
291 nalloc = 1;
293 /* Allocate memory for sel->v.u if needed */
294 if ((sel->flags & SEL_ALLOCVAL)
295 || (sel->type == SEL_SUBEXPRREF && sel->u.param
296 && (sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL))))
298 _gmx_selvalue_reserve(&sel->v, nalloc);
300 /* Reserve memory inside group and position structures if
301 * SEL_ALLOCDATA is set. */
302 if (sel->flags & SEL_ALLOCDATA)
304 if (sel->v.type == GROUP_VALUE)
306 gmx_ana_index_reserve(sel->v.u.g, isize);
308 else if (sel->v.type == POS_VALUE)
310 gmx_ana_pos_reserve(sel->v.u.p, isize, 0);
313 return TRUE;
316 /*! \brief
317 * Replace the evaluation function of each element in the subtree.
319 * \param sel Root of the selection subtree to process.
320 * \param[in] eval The new evaluation function.
322 static void
323 set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
325 sel->evaluate = eval;
326 if (sel->type != SEL_SUBEXPRREF)
328 t_selelem *child = sel->child;
329 while (child)
331 set_evaluation_function(child, eval);
332 child = child->next;
337 /********************************************************************
338 * SUBEXPRESSION EXTRACTION COMPILER PASS
339 ********************************************************************/
341 /*! \brief
342 * Creates a name with a running number for a subexpression.
344 * \param[in,out] sel The subexpression to be named.
345 * \param[in] i Running number for the subexpression.
347 * The name of the selection becomes "SubExpr N", where N is \p i;
348 * Memory is allocated for the name and the name is stored both in
349 * \c t_selelem::name and \c t_selelem::u::cgrp::name; the latter
350 * is freed by _gmx_selelem_free().
352 static void
353 create_subexpression_name(t_selelem *sel, int i)
355 int len, ret;
356 char *name;
358 len = 8 + 4;
359 snew(name, len+1);
360 ret = snprintf(name, len+1, "SubExpr %d", i);
361 if (ret < 0 || ret > len)
363 sfree(name);
364 name = NULL;
366 sel->name = name;
367 sel->u.cgrp.name = name;
370 /*! \brief
371 * Processes and extracts subexpressions from a given selection subtree.
373 * \param sel Root of the subtree to process.
374 * \param[in] gall Index group that contains all the input atoms.
375 * \param subexprn Pointer to a subexpression counter.
376 * \returns Pointer to a chain of subselections, or NULL if none were found.
378 * This function finds recursively all \ref SEL_SUBEXPRREF elements below
379 * the given root element and ensures that their children are within
380 * \ref SEL_SUBEXPR elements. It also creates a chain of \ref SEL_ROOT elements
381 * that contain the subexpression as their children and returns the first
382 * of these root elements.
384 static t_selelem *
385 extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
387 t_selelem *root;
388 t_selelem *subexpr;
389 t_selelem *child;
391 root = subexpr = NULL;
392 child = sel->child;
393 while (child)
395 if (!root)
397 root = subexpr = extract_item_subselections(child, gall, subexprn);
399 else
401 subexpr->next = extract_item_subselections(child, gall, subexprn);
403 while (subexpr && subexpr->next)
405 subexpr = subexpr->next;
407 /* The latter check excludes variable references */
408 if (child->type == SEL_SUBEXPRREF && child->child->type != SEL_SUBEXPR)
410 /* Create the root element for the subexpression */
411 if (!root)
413 root = subexpr = _gmx_selelem_create(SEL_ROOT);
415 else
417 subexpr->next = _gmx_selelem_create(SEL_ROOT);
418 subexpr = subexpr->next;
420 /* Set the evaluation group to all atoms */
421 if (!(child->flags & SEL_ATOMVAL))
423 gmx_ana_index_set(&subexpr->u.cgrp, gall->isize, gall->index, NULL, 0);
425 /* Create the subexpression element */
426 subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
427 _gmx_selelem_set_vtype(subexpr->child, child->v.type);
428 create_subexpression_name(subexpr->child, ++*subexprn);
429 /* Move the actual subexpression under the created element */
430 subexpr->child->child = child->child;
431 child->child = subexpr->child;
432 subexpr->child->refcount = 2;
433 /* Set the flags for the created elements */
434 subexpr->flags |= (child->flags & SEL_VALFLAGMASK);
435 subexpr->child->flags |= (child->flags & SEL_VALFLAGMASK);
437 child = child->next;
440 return root;
443 /*! \brief
444 * Extracts subexpressions of the selection chain.
446 * \param sel First selection in the whole selection chain.
447 * \param[in] gall Index group that contains all the input atoms.
448 * \returns The new first element for the chain.
450 * Finds all the subexpressions (and their subexpressions) in the
451 * selection chain starting from \p sel and creates \ref SEL_SUBEXPR
452 * elements for them.
453 * \ref SEL_ROOT elements are also created for each subexpression
454 * and inserted into the selection chain before the expressions that
455 * refer to them.
457 static t_selelem *
458 extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
460 t_selelem *root, *item, *next;
461 int subexprn;
463 subexprn = 0;
464 root = NULL;
465 next = sel;
466 while (next)
468 item = extract_item_subselections(next, gall, &subexprn);
469 if (item)
471 if (!root)
473 root = item;
475 else
477 sel->next = item;
479 while (item->next)
481 item = item->next;
483 item->next = next;
485 else if (!root)
487 root = next;
489 sel = next;
490 next = next->next;
492 return root;
495 /********************************************************************
496 * BOOLEAN OPERATION REORDERING COMPILER PASS
497 ********************************************************************/
499 /*! \brief
500 * Removes redundant boolean selection elements.
502 * \param sel Root of the selection subtree to optimize.
504 * This function merges similar boolean operations (e.g., (A or B) or C becomes
505 * a single OR operation with three operands).
507 static void
508 optimize_boolean_expressions(t_selelem *sel)
510 t_selelem *child, *prev;
512 /* Do recursively for children */
513 if (sel->type != SEL_SUBEXPRREF)
515 prev = NULL;
516 child = sel->child;
517 while (child)
519 optimize_boolean_expressions(child);
520 /* Remove double negations */
521 if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT
522 && child->child->type == SEL_BOOLEAN && child->child->u.boolt == BOOL_NOT)
524 /* Move the doubly negated expression up two levels */
525 if (!prev)
527 sel->child = child->child->child;
528 prev = sel->child;
530 else
532 prev->next = child->child->child;
533 prev = prev->next;
535 child->child->child->next = child->next;
536 /* Remove the two negations */
537 child->child->child = NULL;
538 child->next = NULL;
539 _gmx_selelem_free(child);
540 child = prev;
542 prev = child;
543 child = child->next;
546 if (sel->type != SEL_BOOLEAN || sel->u.boolt == BOOL_NOT)
548 return;
550 /* Merge subsequent binary operations */
551 prev = NULL;
552 child = sel->child;
553 while (child)
555 if (child->type == SEL_BOOLEAN && child->u.boolt == sel->u.boolt)
557 if (!prev)
559 sel->child = child->child;
560 prev = sel->child;
562 else
564 prev->next = child->child;
566 while (prev->next)
568 prev = prev->next;
570 prev->next = child->next;
571 sfree(child->v.u.g);
572 sfree(child);
573 child = prev->next;
575 else
577 prev = child;
578 child = child->next;
583 /*! \brief
584 * Reorders children of boolean expressions such that static selections
585 * come first.
587 * \param sel Root of the selection subtree to reorder.
589 * The relative order of static expressions does not change.
590 * The same is true for the dynamic expressions.
592 static void
593 reorder_boolean_static_children(t_selelem *sel)
595 t_selelem *child, *prev, *next;
597 /* Do recursively for children */
598 if (sel->type != SEL_SUBEXPRREF)
600 child = sel->child;
601 while (child)
603 reorder_boolean_static_children(child);
604 child = child->next;
608 /* Reorder boolean expressions such that static selections come first */
609 if (sel->type == SEL_BOOLEAN && (sel->flags & SEL_DYNAMIC))
611 t_selelem start;
613 start.next = sel->child;
614 prev = &start;
615 child = &start;
616 while (child->next)
618 /* child is the last handled static expression */
619 /* prev is the last handled non-static expression */
620 next = prev->next;
621 while (next && (next->flags & SEL_DYNAMIC))
623 prev = next;
624 next = next->next;
626 /* next is now the first static expression after child */
627 if (!next)
629 break;
631 /* Reorder such that next comes after child */
632 if (prev != child)
634 prev->next = next->next;
635 next->next = child->next;
636 child->next = next;
638 else
640 prev = prev->next;
642 /* Advance child by one */
643 child = next;
646 sel->child = start.next;
650 /********************************************************************
651 * EVALUATION PREPARATION COMPILER PASS
652 ********************************************************************/
654 /*! \brief
655 * Initializes the evaluation groups for the selections.
657 * \param[in,out] sc Selection collection data.
659 * The evaluation group of each \ref SEL_ROOT element corresponding to a
660 * selection in \p sc is set to \p gall.
662 static void
663 initialize_evalgrps(gmx_ana_selcollection_t *sc)
665 t_selelem *item;
666 int i;
668 /* Initialize the output */
669 for (i = 0; i < sc->nr; ++i)
671 item = sc->sel[i]->selelem;
672 /* Set the evaluation group to all atoms */
673 gmx_ana_index_set(&item->u.cgrp, sc->gall.isize, sc->gall.index,
674 item->u.cgrp.name, 0);
678 /*! \brief
679 * Prepares the selection (sub)tree for evaluation.
681 * \param[in,out] sel Root of the selection subtree to prepare.
682 * \returns TRUE on success, FALSE if any subexpression fails.
684 * This function sets the evaluation function (\c t_selelem::evaluate)
685 * for the selection elements.
686 * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
687 * structure if required.
689 static bool
690 init_item_evaluation(t_selelem *sel)
692 t_selelem *child;
694 /* Process children */
695 if (sel->type != SEL_SUBEXPRREF)
697 child = sel->child;
698 while (child)
700 if (!init_item_evaluation(child))
702 return FALSE;
704 child = child->next;
708 /* Make sure that the group/position structure is allocated */
709 if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
711 if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
713 _gmx_selvalue_reserve(&sel->v, 1);
714 sel->v.nr = 1;
718 /* Set the evaluation function */
719 switch (sel->type)
721 case SEL_CONST:
722 if (sel->v.type == GROUP_VALUE)
724 sel->evaluate = &_gmx_sel_evaluate_static;
726 break;
728 case SEL_EXPRESSION:
729 sel->evaluate = &_gmx_sel_evaluate_method;
730 break;
732 case SEL_MODIFIER:
733 if (sel->v.type != NO_VALUE)
735 sel->evaluate = &_gmx_sel_evaluate_modifier;
737 break;
739 case SEL_BOOLEAN:
740 switch (sel->u.boolt)
742 case BOOL_NOT: sel->evaluate = &_gmx_sel_evaluate_not; break;
743 case BOOL_AND: sel->evaluate = &_gmx_sel_evaluate_and; break;
744 case BOOL_OR: sel->evaluate = &_gmx_sel_evaluate_or; break;
745 case BOOL_XOR:
746 gmx_impl("xor expressions not implemented");
747 return FALSE;
749 break;
751 case SEL_ROOT:
752 sel->evaluate = &_gmx_sel_evaluate_root;
753 break;
755 case SEL_SUBEXPR:
756 sel->evaluate = &_gmx_sel_evaluate_subexpr;
757 break;
759 case SEL_SUBEXPRREF:
760 sel->name = sel->child->name;
761 sel->evaluate = &_gmx_sel_evaluate_subexprref;
762 break;
765 return TRUE;
769 /********************************************************************
770 * COMPILER DATA INITIALIZATION PASS
771 ********************************************************************/
773 /*! \brief
774 * Allocates memory for the compiler data and initializes the structure.
776 * \param sel Root of the selection subtree to process.
778 static void
779 init_item_compilerdata(t_selelem *sel)
781 t_selelem *child;
783 /* Allocate the compiler data structure */
784 snew(sel->cdata, 1);
786 /* Store the real evaluation method because the compiler will replace it */
787 sel->cdata->evaluate = sel->evaluate;
789 /* Initialize the flags */
790 sel->cdata->bMethodParam = FALSE;
791 sel->cdata->bStatic = !(sel->flags & SEL_DYNAMIC);
792 sel->cdata->bStaticEval = TRUE;
793 sel->cdata->bEvalMax = (sel->type == SEL_SUBEXPR ? TRUE : FALSE);
794 /* Set the method parameter flag for non-atom-valued parameters */
795 if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
797 child = sel->child;
798 while (child)
800 if (!(child->flags & SEL_ATOMVAL))
802 child->child->cdata->bMethodParam = TRUE;
804 child = child->next;
808 /* Initialize children */
809 if (sel->type != SEL_SUBEXPRREF)
811 child = sel->child;
812 while (child)
814 init_item_compilerdata(child);
815 child = child->next;
819 /* Determine whether we should evaluate the minimum or the maximum
820 * for the children of this element. */
821 if (sel->type == SEL_BOOLEAN)
823 bool bEvalMax;
825 bEvalMax = (sel->u.boolt == BOOL_AND);
826 child = sel->child;
827 while (child)
829 child->cdata->bEvalMax = bEvalMax;
830 if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
832 child->child->cdata->bEvalMax = !bEvalMax;
834 child = child->next;
837 else if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER
838 || sel->type == SEL_SUBEXPR)
840 child = sel->child;
841 while (child)
843 child->cdata->bEvalMax = TRUE;
844 child = child->next;
848 /* Initialize the minimum and maximum evaluation groups */
849 sel->cdata->bMinMaxAlloc = FALSE;
850 if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
852 if (sel->type == SEL_SUBEXPR)
854 sel->cdata->gmin = sel->child->cdata->gmin;
855 sel->cdata->gmax = sel->child->cdata->gmax;
857 else if (sel->v.type == GROUP_VALUE && sel->cdata->bStatic)
859 sel->cdata->gmin = sel->v.u.g;
860 sel->cdata->gmax = sel->v.u.g;
862 else
864 sel->cdata->bMinMaxAlloc = TRUE;
865 snew(sel->cdata->gmin, 1);
866 snew(sel->cdata->gmax, 1);
871 /*! \brief
872 * Initializes the static evaluation flag for a selection subtree.
874 * \param[in,out] sel Root of the selection subtree to process.
876 * Sets the \c bStaticEval in the compiler data structure:
877 * for any element for which the evaluation group may depend on the trajectory
878 * frame, the flag is cleared.
880 * reorder_boolean_static_children() should have been called.
882 static void
883 init_item_staticeval(t_selelem *sel)
885 t_selelem *child;
887 /* Non-atom-valued method parameters should always have bStaticEval,
888 * so don't do anything if a reference to them is encountered. */
889 if (sel->type == SEL_SUBEXPRREF && sel->child->cdata->bMethodParam)
891 return;
894 /* Propagate the bStaticEval flag to children if it is not set */
895 if (!sel->cdata->bStaticEval)
897 child = sel->child;
898 while (child)
900 if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
901 || (child->flags & SEL_ATOMVAL))
903 if (child->cdata->bStaticEval)
905 child->cdata->bStaticEval = FALSE;
906 init_item_staticeval(child);
909 child = child->next;
912 else /* bStaticEval is set */
914 /* For boolean expressions, any expression after the first dynamic
915 * expression should not have bStaticEval. */
916 if (sel->type == SEL_BOOLEAN)
918 child = sel->child;
919 while (child && !(child->flags & SEL_DYNAMIC))
921 child = child->next;
923 if (child)
925 child = child->next;
927 while (child)
929 child->cdata->bStaticEval = FALSE;
930 child = child->next;
934 /* Process the children */
935 child = sel->child;
936 while (child)
938 init_item_staticeval(child);
939 child = child->next;
945 /********************************************************************
946 * STATIC ANALYSIS COMPILER PASS
947 ********************************************************************/
949 /*! \brief
950 * Marks a subtree completely dynamic or undoes such a change.
952 * \param sel Selection subtree to mark.
953 * \param[in] bDynamic If TRUE, the \p bStatic flag of the whole
954 * selection subtree is cleared. If FALSE, the flag is restored to
955 * using \ref SEL_DYNAMIC.
957 * Does not descend into parameters of methods unless the parameters
958 * are evaluated for each atom.
960 static void
961 mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
963 t_selelem *child;
965 sel->cdata->bStatic = (!bDynamic && !(sel->flags & SEL_DYNAMIC));
966 child = sel->child;
967 while (child)
969 if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
970 || (child->u.param->flags & SPAR_ATOMVAL))
972 mark_subexpr_dynamic(child, bDynamic);
974 child = child->next;
978 /*! \brief
979 * Makes an evaluated selection element static.
981 * \param sel Selection element to make static.
983 * The evaluated value becomes the value of the static element.
984 * The element type is changed to SEL_CONST and the children are
985 * deleted.
987 static void
988 make_static(t_selelem *sel)
990 /* Free the expression data as it is no longer needed */
991 _gmx_selelem_free_exprdata(sel);
992 /* Make the item static */
993 sel->name = NULL;
994 sel->type = SEL_CONST;
995 sel->evaluate = NULL;
996 sel->cdata->evaluate = NULL;
997 /* Free the children */
998 _gmx_selelem_free_chain(sel->child);
999 sel->child = NULL;
1000 /* Set the group value.
1001 * None of the elements for which this function may be called uses
1002 * the cgrp group, so we can simply overwrite the contents without
1003 * worrying about memory leaks. */
1004 if (sel->v.type == GROUP_VALUE)
1006 gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
1010 /*! \brief
1011 * Evaluates a constant expression during analyze_static() and analyze_static2().
1013 * \param[in] data Evaluation data.
1014 * \param[in,out] sel Selection to process.
1015 * \param[in] g The evaluation group.
1016 * \returns 0 on success, a non-zero error code on error.
1018 static int
1019 process_const(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1021 int rc;
1023 rc = 0;
1024 if (sel->v.type == GROUP_VALUE)
1026 if (sel->cdata->evaluate)
1028 rc = sel->cdata->evaluate(data, sel, g);
1031 /* Other constant expressions do not need evaluation */
1032 return rc;
1035 /*! \brief
1036 * Sets the parameter value pointer for \ref SEL_SUBEXPRREF params.
1038 * \param[in,out] sel Selection to process.
1040 * Copies the value pointer of \p sel to \c sel->u.param if one is present
1041 * and should receive the value from the compiler
1042 * (most parameter values are handled during parsing).
1043 * If \p sel is not of type \ref SEL_SUBEXPRREF, or if \c sel->u.param is NULL,
1044 * the function does nothing.
1045 * Also, if the \c sel->u.param does not have \ref SPAR_VARNUM or
1046 * \ref SPAR_ATOMVAL, the function returns immediately.
1048 static void
1049 store_param_val(t_selelem *sel)
1051 /* Return immediately if there is no parameter. */
1052 if (sel->type != SEL_SUBEXPRREF || !sel->u.param)
1054 return;
1057 /* Or if the value does not need storing. */
1058 if (!(sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
1060 return;
1063 if (sel->v.type == INT_VALUE || sel->v.type == REAL_VALUE
1064 || sel->v.type == STR_VALUE)
1066 _gmx_selvalue_setstore(&sel->u.param->val, sel->v.u.ptr);
1070 /*! \brief
1071 * Handles the initialization of a selection method during analyze_static() pass.
1073 * \param[in,out] sel Selection element to process.
1074 * \param[in] top Topology structure.
1075 * \param[in] isize Size of the evaluation group for the element.
1076 * \returns 0 on success, a non-zero error code on return.
1078 * Calls sel_initfunc() (and possibly sel_outinitfunc()) to initialize the
1079 * method.
1080 * If no \ref SPAR_ATOMVAL parameters are present, multiple initialization
1081 * is prevented by using \ref SEL_METHODINIT and \ref SEL_OUTINIT flags.
1083 static int
1084 init_method(t_selelem *sel, t_topology *top, int isize)
1086 t_selelem *child;
1087 bool bAtomVal;
1088 int rc;
1090 /* Find out whether there are any atom-valued parameters */
1091 bAtomVal = FALSE;
1092 child = sel->child;
1093 while (child)
1095 if (child->flags & SEL_ATOMVAL)
1097 bAtomVal = TRUE;
1099 child = child->next;
1102 /* Initialize the method */
1103 if (sel->u.expr.method->init
1104 && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
1106 sel->flags |= SEL_METHODINIT;
1107 /* The allocation flags are cleared first to not to free anything if
1108 * initialization fails. */
1109 child = sel->child;
1110 if (sel->type == SEL_MODIFIER && sel->v.type != NO_VALUE)
1112 child = child->next;
1114 while (child)
1116 child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1117 child = child->next;
1119 rc = sel->u.expr.method->init(top, sel->u.expr.method->nparams,
1120 sel->u.expr.method->param, sel->u.expr.mdata);
1121 if (rc != 0)
1123 return rc;
1126 if (bAtomVal || !(sel->flags & SEL_OUTINIT))
1128 sel->flags |= SEL_OUTINIT;
1129 if (sel->u.expr.method->outinit)
1131 rc = sel->u.expr.method->outinit(top, &sel->v, sel->u.expr.mdata);
1132 if (rc != 0)
1134 return rc;
1137 else
1139 alloc_selection_data(sel, isize, TRUE);
1140 if ((sel->flags & SEL_DYNAMIC)
1141 && sel->v.type != GROUP_VALUE && sel->v.type != POS_VALUE)
1143 sel->v.nr = isize;
1145 /* If the method is char-valued, pre-allocate the strings. */
1146 if (sel->u.expr.method->flags & SMETH_CHARVAL)
1148 int i;
1150 /* A sanity check */
1151 if (sel->v.type != STR_VALUE)
1153 gmx_bug("internal error");
1154 return -1;
1156 sel->flags |= SEL_ALLOCDATA;
1157 for (i = 0; i < isize; ++i)
1159 if (sel->v.u.s[i] == NULL)
1161 snew(sel->v.u.s[i], 2);
1168 return 0;
1171 /*! \brief
1172 * Evaluates the static part of a boolean expression.
1174 * \param[in] data Evaluation data.
1175 * \param[in,out] sel Boolean selection element whose children should be
1176 * processed.
1177 * \param[in] g The evaluation group.
1178 * \returns 0 on success, a non-zero error code on error.
1180 * reorder_item_static_children() should have been called.
1182 static int
1183 evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
1184 gmx_ana_index_t *g)
1186 t_selelem *child, *next;
1187 int rc;
1189 /* Find the last static subexpression */
1190 child = sel->child;
1191 while (child->next && child->next->cdata->bStatic)
1193 child = child->next;
1195 if (!child->cdata->bStatic)
1197 return 0;
1200 /* Evalute the static part if there is more than one expression */
1201 if (child != sel->child)
1203 next = child->next;
1204 child->next = NULL;
1205 rc = sel->cdata->evaluate(data, sel, g);
1206 if (rc != 0)
1208 return rc;
1210 /* Replace the subexpressions with the result */
1211 _gmx_selelem_free_chain(sel->child);
1212 snew(child, 1);
1213 child->type = SEL_CONST;
1214 child->flags = SEL_FLAGSSET | SEL_SINGLEVAL | SEL_ALLOCVAL | SEL_ALLOCDATA;
1215 _gmx_selelem_set_vtype(child, GROUP_VALUE);
1216 child->evaluate = NULL;
1217 _gmx_selvalue_reserve(&child->v, 1);
1218 gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
1219 init_item_compilerdata(child);
1220 child->cdata->bStaticEval = sel->cdata->bStaticEval;
1221 child->next = next;
1222 sel->child = child;
1224 else if (child->evaluate)
1226 rc = child->evaluate(data, child, g);
1227 if (rc != 0)
1229 return rc;
1232 /* Set the evaluation function for the constant element.
1233 * We never need to evaluate the element again during compilation,
1234 * but we may need to evaluate the static part again if the
1235 * expression is not an OR with a static evaluation group.
1236 * If we reach here with a NOT expression, the NOT expression
1237 * is also static, and will be made a constant later, so don't waste
1238 * time copying the group. */
1239 child->evaluate = NULL;
1240 if (sel->u.boolt == BOOL_NOT
1241 || (sel->cdata->bStaticEval && sel->u.boolt == BOOL_OR))
1243 child->cdata->evaluate = NULL;
1245 else
1247 child->cdata->evaluate = &_gmx_sel_evaluate_static;
1248 /* The cgrp has only been allocated if it originated from an
1249 * external index group. In that case, we need special handling
1250 * to preserve the name of the group and to not leak memory.
1251 * If cgrp has been set in make_static(), it is not allocated,
1252 * and hence we can overwrite it safely. */
1253 if (child->u.cgrp.nalloc_index > 0)
1255 char *name = child->u.cgrp.name;
1256 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, FALSE);
1257 gmx_ana_index_squeeze(&child->u.cgrp);
1258 child->u.cgrp.name = name;
1260 else
1262 gmx_ana_index_copy(&child->u.cgrp, child->v.u.g, TRUE);
1265 return 0;
1268 /*! \brief
1269 * Evaluates the minimum and maximum groups for a boolean expression.
1271 * \param[in] sel \ref SEL_BOOLEAN element currently being evaluated.
1272 * \param[in] g Group for which \p sel has been evaluated.
1273 * \param[out] gmin Largest subset of the possible values of \p sel.
1274 * \param[out] gmax Smallest superset of the possible values of \p sel.
1276 * This is a helper function for analyze_static() that is called for
1277 * dynamic \ref SEL_BOOLEAN elements after they have been evaluated.
1278 * It uses the minimum and maximum groups of the children to calculate
1279 * the minimum and maximum groups for \p sel, and also updates the static
1280 * part of \p sel (which is in the first child) if the children give
1281 * cause for this.
1283 * This function may allocate some extra memory for \p gmin and \p gmax,
1284 * but as these groups are freed at the end of analyze_static() (which is
1285 * reached shortly after this function returns), this should not be a major
1286 * problem.
1288 static void
1289 evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
1290 gmx_ana_index_t *gmin, gmx_ana_index_t *gmax)
1292 t_selelem *child;
1294 switch (sel->u.boolt)
1296 case BOOL_NOT:
1297 gmx_ana_index_reserve(gmin, g->isize);
1298 gmx_ana_index_reserve(gmax, g->isize);
1299 gmx_ana_index_difference(gmax, g, sel->child->cdata->gmin);
1300 gmx_ana_index_difference(gmin, g, sel->child->cdata->gmax);
1301 break;
1303 case BOOL_AND:
1304 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, TRUE);
1305 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, TRUE);
1306 child = sel->child->next;
1307 while (child && gmax->isize > 0)
1309 gmx_ana_index_intersection(gmin, gmin, child->cdata->gmin);
1310 gmx_ana_index_intersection(gmax, gmax, child->cdata->gmax);
1311 child = child->next;
1313 /* Update the static part if other expressions limit it */
1314 if (sel->child->cdata->bStatic
1315 && sel->child->v.u.g->isize > gmax->isize)
1317 gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
1318 gmx_ana_index_squeeze(sel->child->v.u.g);
1319 if (sel->child->u.cgrp.isize > 0)
1321 gmx_ana_index_copy(&sel->child->u.cgrp, gmax, FALSE);
1322 gmx_ana_index_squeeze(&sel->child->u.cgrp);
1325 break;
1327 case BOOL_OR:
1328 /* We can assume here that the gmin of children do not overlap
1329 * because of the way _gmx_sel_evaluate_or() works. */
1330 gmx_ana_index_reserve(gmin, g->isize);
1331 gmx_ana_index_reserve(gmax, g->isize);
1332 gmx_ana_index_copy(gmin, sel->child->cdata->gmin, FALSE);
1333 gmx_ana_index_copy(gmax, sel->child->cdata->gmax, FALSE);
1334 child = sel->child->next;
1335 while (child && gmin->isize < g->isize)
1337 gmx_ana_index_merge(gmin, gmin, child->cdata->gmin);
1338 gmx_ana_index_union(gmax, gmax, child->cdata->gmax);
1339 child = child->next;
1341 /* Update the static part if other expressions have static parts
1342 * that are not included. */
1343 if (sel->child->cdata->bStatic
1344 && sel->child->v.u.g->isize < gmin->isize)
1346 gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
1347 gmx_ana_index_copy(sel->child->v.u.g, gmin, FALSE);
1348 if (sel->child->u.cgrp.isize > 0)
1350 gmx_ana_index_reserve(&sel->child->u.cgrp, gmin->isize);
1351 gmx_ana_index_copy(&sel->child->u.cgrp, gmin, FALSE);
1354 break;
1356 case BOOL_XOR: /* Should not be reached */
1357 gmx_impl("xor expressions not implemented");
1358 break;
1362 /*! \brief
1363 * Evaluates the static parts of \p sel and analyzes the structure.
1365 * \param[in] data Evaluation data.
1366 * \param[in,out] sel Selection currently being evaluated.
1367 * \param[in] g Group for which \p sel should be evaluated.
1368 * \returns 0 on success, a non-zero error code on error.
1370 * This function is used as the replacement for the \c t_selelem::evaluate
1371 * function pointer.
1372 * It does the single most complex task in the compiler: after all elements
1373 * have been processed, the \p gmin and \p gmax fields of \p t_compiler_data
1374 * have been properly initialized, enough memory has been allocated for
1375 * storing the value of each expression, and the static parts of the
1376 * expressions have been evaluated.
1377 * The above is exactly true only for elements other than subexpressions:
1378 * another pass is required for subexpressions that are referred to more than
1379 * once to evaluate the static parts.
1380 * This second pass is performed by analyze_static2().
1382 * \see analyze_static2()
1384 static int
1385 analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1387 t_selelem *child, *next;
1388 gmx_ana_index_t gmin, gmax;
1389 bool bDelayAlloc;
1390 int rc;
1392 gmx_ana_index_clear(&gmin);
1393 gmx_ana_index_clear(&gmax);
1394 bDelayAlloc = FALSE;
1396 if (sel->type != SEL_ROOT && g)
1398 bDelayAlloc = !alloc_selection_data(sel, g->isize, FALSE);
1401 /* TODO: This switch is awfully long... */
1402 rc = 0;
1403 switch (sel->type)
1405 case SEL_CONST:
1406 rc = process_const(data, sel, g);
1407 break;
1409 case SEL_EXPRESSION:
1410 case SEL_MODIFIER:
1411 rc = _gmx_sel_evaluate_method_params(data, sel, g);
1412 if (rc != 0)
1414 return rc;
1416 rc = init_method(sel, data->top, g->isize);
1417 if (rc != 0)
1419 return rc;
1421 if (sel->type == SEL_MODIFIER || !(sel->flags & SEL_DYNAMIC))
1423 rc = sel->cdata->evaluate(data, sel, g);
1424 if (rc == 0 && sel->cdata->bStatic)
1426 make_static(sel);
1429 else
1431 gmx_ana_index_copy(&gmax, g, TRUE);
1433 break;
1435 case SEL_BOOLEAN:
1436 if (!(sel->flags & SEL_DYNAMIC))
1438 rc = sel->cdata->evaluate(data, sel, g);
1439 if (rc == 0 && sel->cdata->bStatic)
1441 make_static(sel);
1444 else
1446 /* Evalute the static part if there is more than one expression */
1447 rc = evaluate_boolean_static_part(data, sel, g);
1448 if (rc != 0)
1450 return rc;
1453 /* Evaluate the selection.
1454 * If the type is boolean, we must explicitly handle the
1455 * static part evaluated in evaluate_boolean_static_part()
1456 * here because g may be larger. */
1457 if (sel->u.boolt == BOOL_AND && sel->child->type == SEL_CONST)
1459 rc = sel->cdata->evaluate(data, sel, sel->child->v.u.g);
1461 else
1463 rc = sel->cdata->evaluate(data, sel, g);
1465 if (rc != 0)
1467 return rc;
1470 /* Evaluate minimal and maximal selections */
1471 evaluate_boolean_minmax_grps(sel, g, &gmin, &gmax);
1473 break;
1475 case SEL_ROOT:
1476 rc = sel->cdata->evaluate(data, sel, g);
1477 break;
1479 case SEL_SUBEXPR:
1480 if (sel->u.cgrp.isize == 0)
1482 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
1483 if (bDelayAlloc)
1485 /* We need to evaluate the child before we can allocate the
1486 * memory. */
1487 rc = sel->child->evaluate(data, sel->child, g);
1488 if (rc != 0)
1490 return rc;
1492 alloc_selection_data(sel, g->isize, TRUE);
1493 /* Do not evaluate the child again */
1494 sel->child->evaluate = NULL;
1495 rc = sel->cdata->evaluate(data, sel, g);
1496 sel->child->evaluate = &analyze_static;
1498 else
1500 alloc_selection_data(sel->child, g->isize, FALSE);
1501 rc = sel->cdata->evaluate(data, sel, g);
1504 else
1506 int isize = gmx_ana_index_difference_size(g, &sel->u.cgrp);
1507 if (isize > 0)
1509 isize += sel->u.cgrp.isize;
1510 gmx_ana_index_reserve(&sel->u.cgrp, isize);
1511 if (sel->v.type == GROUP_VALUE || (sel->flags & SEL_ATOMVAL))
1513 alloc_selection_data(sel->child, isize, FALSE);
1514 alloc_selection_data(sel, isize, FALSE);
1516 rc = sel->cdata->evaluate(data, sel, g);
1518 else
1520 rc = sel->cdata->evaluate(data, sel, g);
1523 break;
1525 case SEL_SUBEXPRREF:
1526 /* Evaluate the subexpression if it is not yet evaluated.
1527 * Can happen when a variable is passed as a parameter or as
1528 * a selection. */
1529 if (sel->child->u.cgrp.isize == 0)
1531 rc = sel->child->evaluate(data, sel->child, g ? g : data->gall);
1532 if (rc != 0)
1534 return rc;
1536 /* Prevent another evaluation of the child. */
1537 sel->child->evaluate = NULL;
1538 alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
1540 if (!g)
1542 alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
1544 /* TODO: This is not general enough if/when position references
1545 * can be evaluated more than once (that is, if there are position
1546 * methods that do not have SMETH_SINGLEVAL or SMETH_VARNUMVAL). */
1547 if (sel->v.type == POS_VALUE && !(sel->flags & SEL_OUTINIT))
1549 gmx_ana_indexmap_copy(&sel->v.u.p->m, &sel->child->child->v.u.p->m, TRUE);
1550 sel->flags |= SEL_OUTINIT;
1552 rc = sel->cdata->evaluate(data, sel, g);
1553 sel->child->evaluate = &analyze_static;
1554 if (rc != 0)
1556 return rc;
1558 /* Store the parameter value if required */
1559 store_param_val(sel);
1560 if (!(sel->flags & SEL_DYNAMIC))
1562 if (sel->cdata->bStatic)
1564 make_static(sel);
1567 else
1569 if (sel->child->refcount <= 2 || !g)
1571 gmx_ana_index_copy(&gmin, sel->child->cdata->gmin, TRUE);
1572 gmx_ana_index_copy(&gmax, sel->child->cdata->gmax, TRUE);
1574 else
1576 gmx_ana_index_reserve(&gmin, min(g->isize, sel->child->cdata->gmin->isize));
1577 gmx_ana_index_reserve(&gmax, min(g->isize, sel->child->cdata->gmax->isize));
1578 gmx_ana_index_intersection(&gmin, sel->child->cdata->gmin, g);
1579 gmx_ana_index_intersection(&gmax, sel->child->cdata->gmax, g);
1582 break;
1584 /* Exit if there was some problem */
1585 if (rc != 0)
1587 return rc;
1590 /* Update the minimal and maximal evaluation groups */
1591 if (sel->cdata->bMinMaxAlloc)
1593 gmx_ana_index_reserve(sel->cdata->gmin, sel->cdata->gmin->isize + gmin.isize);
1594 gmx_ana_index_reserve(sel->cdata->gmax, sel->cdata->gmax->isize + gmax.isize);
1595 gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin, &gmin);
1596 gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax, &gmax);
1598 /* Replace the result of the evaluation */
1599 /* This is not necessary for subexpressions or for boolean negations
1600 * because the evaluation function already has done it properly. */
1601 if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
1602 && sel->type != SEL_SUBEXPR
1603 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
1605 if (sel->cdata->bEvalMax)
1607 gmx_ana_index_copy(sel->v.u.g, &gmax, FALSE);
1609 else
1611 gmx_ana_index_copy(sel->v.u.g, &gmin, FALSE);
1614 gmx_ana_index_deinit(&gmin);
1615 gmx_ana_index_deinit(&gmax);
1617 /* Make sure that enough data storage has been allocated */
1618 /* TODO: Constant expressions could be handled here more intelligently */
1619 if (sel->type != SEL_ROOT && sel->cdata->bStaticEval)
1621 alloc_selection_data(sel, sel->cdata->gmax->isize, TRUE);
1622 /* Make sure that the new value pointer is stored if required */
1623 store_param_val(sel);
1626 return 0;
1629 /*! \brief
1630 * Evaluates the static parts of \p sel and analyzes the structure.
1632 * \param[in] data Evaluation data.
1633 * \param[in,out] sel Selection currently being evaluated.
1634 * \param[in] g Group for which \p sel should be evaluated.
1635 * \returns 0 on success, a non-zero error code on error.
1637 * This function is a simpler version of analyze_static() that is used
1638 * during a second evaluation round, and can thus use information calculated
1639 * by analyze_static().
1640 * It is also used as the replacement for the \c t_selelem::evaluate
1641 * function pointer.
1642 * It is used to evaluate the static parts of subexpressions that could not
1643 * be evaluated during the analyze_static() pass.
1645 * \see analyze_static()
1647 static int
1648 analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
1650 int rc;
1652 rc = 0;
1653 switch (sel->type)
1655 case SEL_CONST:
1656 rc = process_const(data, sel, g);
1657 break;
1659 case SEL_EXPRESSION:
1660 case SEL_BOOLEAN:
1661 case SEL_SUBEXPRREF:
1662 if (sel->cdata->bStatic)
1664 rc = sel->cdata->evaluate(data, sel, g);
1665 if (rc == 0)
1667 make_static(sel);
1670 else if (sel->type == SEL_BOOLEAN)
1672 rc = evaluate_boolean_static_part(data, sel, g);
1673 if (rc == 0)
1675 rc = sel->cdata->evaluate(data, sel, g);
1678 break;
1680 case SEL_ROOT: /* Roots should not be present here */
1681 case SEL_MODIFIER: /* Modifiers should not be present here */
1682 case SEL_SUBEXPR:
1683 rc = sel->cdata->evaluate(data, sel, g);
1684 break;
1686 /* Exit if there was some problem */
1687 if (rc != 0)
1689 return rc;
1692 /* Replace the result of the evaluation */
1693 /* This is not necessary for subexpressions or for boolean negations
1694 * because the evaluation function already has done it properly. */
1695 if (sel->v.type == GROUP_VALUE && !sel->cdata->bStatic
1696 && sel->type != SEL_SUBEXPR
1697 && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
1699 if (sel->cdata->bEvalMax)
1701 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
1703 else
1705 gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmin, FALSE);
1709 return 0;
1713 /********************************************************************
1714 * ROOT ITEM INITIALIZATION COMPILER PASS
1715 ********************************************************************/
1717 /*! \brief
1718 * Initializes a \ref SEL_ROOT element.
1720 * \param root Root element to initialize.
1721 * \returns Pointer to the selection element that should replace \p root.
1722 * Can be \p root itself or NULL if the selection should be removed.
1724 * Checks whether it is necessary to evaluate anything through the root
1725 * element, and either clears the evaluation function or initializes the
1726 * evaluation group.
1728 * If the function returns NULL, the memory allocated for \p root is
1729 * automatically freed.
1731 static t_selelem *
1732 init_root_item(t_selelem *root)
1734 t_selelem *expr;
1735 char *name;
1737 /* Get the name for constant expressions if it is not yet there */
1738 if (!root->name)
1740 if (root->child->type == SEL_CONST
1741 || root->child->type == SEL_SUBEXPRREF)
1743 root->name = root->child->name;
1745 else if (root->child->type == SEL_EXPRESSION
1746 && root->child->child->type == SEL_CONST)
1748 root->name = root->child->child->name;
1752 /* Process subexpressions */
1753 if (root->child->type == SEL_SUBEXPR)
1755 if (root->child->refcount == 1)
1757 /* Free subexpressions that are no longer used */
1758 _gmx_selelem_free(root);
1759 return NULL;
1761 else if (root->child->v.type == POS_VALUE)
1763 /* Position values only need to be evaluated once, by the root */
1765 else if (!root->child->cdata->bStaticEval)
1767 /* Subexpressions with non-static evaluation group should not be
1768 * evaluated by the root. */
1769 root->evaluate = NULL;
1770 if (root->cdata)
1772 root->cdata->evaluate = NULL;
1777 /* Set the evaluation group */
1778 name = root->u.cgrp.name;
1779 if (root->evaluate)
1781 expr = root->child;
1782 if (expr->type == SEL_SUBEXPR)
1784 gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
1786 else
1788 /* expr should evaluate the positions for a selection */
1789 if (expr->v.u.p->g)
1791 _gmx_selelem_set_vtype(root, GROUP_VALUE);
1792 root->flags |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
1793 _gmx_selvalue_reserve(&root->v, 1);
1794 gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
1796 gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
1799 else
1801 gmx_ana_index_clear(&root->u.cgrp);
1803 root->u.cgrp.name = name;
1804 return root;
1807 /*! \brief
1808 * Initializes the evaluation groups for \ref SEL_ROOT items.
1810 * \param root First selection in the whole selection chain.
1811 * \returns The new first element for the chain.
1813 * The function also removes static subexpressions that are no longer used.
1815 static t_selelem *
1816 process_roots(t_selelem *root)
1818 t_selelem *item;
1819 t_selelem *next;
1823 next = root->next;
1824 root = init_root_item(root);
1825 if (!root)
1827 root = next;
1830 while (root == next);
1831 item = root;
1832 while (item && item->next)
1834 next = item->next->next;
1835 item->next = init_root_item(item->next);
1836 if (!item->next)
1838 item->next = next;
1840 else
1842 item = item->next;
1845 return root;
1849 /********************************************************************
1850 * SUBEXPRESSION OPTIMIZATION PASS
1851 ********************************************************************/
1853 /*! \brief
1854 * Optimizes subexpression evaluation.
1856 * \param sel Root of the selection subtree to process.
1858 * Optimizes away some unnecessary evaluation of subexpressions that are only
1859 * referenced once.
1861 static void
1862 optimize_item_subexpressions(t_selelem *sel)
1864 t_selelem *child;
1866 /* Call recursively for all children unless the children have already been processed */
1867 if (sel->type != SEL_SUBEXPRREF)
1869 child = sel->child;
1870 while (child)
1872 optimize_item_subexpressions(child);
1873 child = child->next;
1877 /* Optimize the evaluation of subexpressions that are used only once */
1878 if (sel->type == SEL_SUBEXPRREF && sel->cdata->bStaticEval && sel->child->refcount == 2)
1880 /* The evaluation functions are not always needed, and they do some
1881 * extra work, but it should be neglible compared to other factors
1882 * in the evaluation, so set them always for simplicity. */
1883 sel->evaluate = &_gmx_sel_evaluate_subexprref_pass;
1884 if (sel->cdata)
1886 sel->cdata->evaluate = sel->evaluate;
1888 /* Replace the value of the child */
1889 _gmx_selelem_free_values(sel->child);
1890 sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1891 _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
1892 sel->child->evaluate = &_gmx_sel_evaluate_subexpr_pass;
1893 if (sel->child->cdata)
1895 sel->child->cdata->evaluate = sel->child->evaluate;
1897 /* Replace the value of the grandchild */
1898 _gmx_selelem_free_values(sel->child->child);
1899 sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
1900 _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
1905 /********************************************************************
1906 * COM CALCULATION COMPILER PASS
1907 ********************************************************************/
1909 /*! \brief
1910 * Initializes COM/COG calculation for method expressions that require it.
1912 * \param sel Selection subtree to process.
1913 * \param[in,out] pcc Position calculation collection to use.
1914 * \param[in] type Default position calculation type.
1915 * \param[in] flags Flags for default position calculation.
1916 * \returns 0 on success, a non-zero error code on error.
1918 * Searches recursively through the selection tree for dynamic
1919 * \ref SEL_EXPRESSION elements that define the \c gmx_ana_selmethod_t::pupdate
1920 * function.
1921 * For each such element found, position calculation is initialized
1922 * for the maximal evaluation group.
1923 * The type of the calculation is determined by \p type and \p flags.
1924 * No calculation is initialized if \p type equals \ref POS_ATOM and
1925 * the method also defines the \c gmx_ana_selmethod_t::update method.
1927 static int
1928 init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
1929 e_poscalc_t type, int flags)
1931 t_selelem *child;
1932 int rc;
1934 /* Initialize COM calculation for dynamic selections now that we know the maximal evaluation group */
1935 if (sel->type == SEL_EXPRESSION && sel->u.expr.method
1936 && sel->u.expr.method->pupdate)
1938 if (!sel->u.expr.method->update || type != POS_ATOM)
1940 /* Create a default calculation if one does not yet exist */
1941 int cflags;
1942 cflags = 0;
1943 if (!sel->cdata->bStaticEval)
1945 cflags |= POS_DYNAMIC;
1947 if (!sel->u.expr.pc)
1949 cflags |= flags;
1950 rc = gmx_ana_poscalc_create(&sel->u.expr.pc, pcc, type, cflags);
1951 if (rc != 0)
1953 return rc;
1956 else
1958 gmx_ana_poscalc_set_flags(sel->u.expr.pc, cflags);
1960 gmx_ana_poscalc_set_maxindex(sel->u.expr.pc, sel->cdata->gmax);
1961 snew(sel->u.expr.pos, 1);
1962 gmx_ana_poscalc_init_pos(sel->u.expr.pc, sel->u.expr.pos);
1966 /* Call recursively for all children unless the children have already been processed */
1967 if (sel->type != SEL_SUBEXPRREF)
1969 child = sel->child;
1970 while (child)
1972 rc = init_item_comg(child, pcc, type, flags);
1973 if (rc != 0)
1975 return rc;
1977 child = child->next;
1980 return 0;
1984 /********************************************************************
1985 * FREE COMPILER DATA PASS
1986 ********************************************************************/
1988 /*! \brief
1989 * Frees the allocated compiler data recursively.
1991 * \param sel Root of the selection subtree to process.
1993 * Frees the data allocated for the compilation process.
1995 static void
1996 free_item_compilerdata(t_selelem *sel)
1998 t_selelem *child;
2000 /* Free compilation data */
2001 _gmx_selelem_free_compiler_data(sel);
2003 /* Call recursively for all children unless the children have already been processed */
2004 if (sel->type != SEL_SUBEXPRREF)
2006 child = sel->child;
2007 while (child)
2009 free_item_compilerdata(child);
2010 child = child->next;
2016 /********************************************************************
2017 * INFORMATION UPDATE
2018 ********************************************************************/
2020 /*! \brief
2021 * Updates the information about the selection.
2023 * \param[in] top Topology information.
2024 * \param[in] ngrps Number of elements in the \p sel array.
2025 * \param[in,out] sel Array of selections to update.
2026 * \param[in] bMaskOnly TRUE if the positions will always be calculated
2027 * for all atoms, i.e., the masses/charges do not change.
2029 * Initializes total masses and charges.
2031 static void
2032 update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
2033 bool bMaskOnly)
2035 int g, b, i;
2037 for (g = 0; g < ngrps; ++g)
2039 sel[g]->g = sel[g]->p.g;
2040 snew(sel[g]->orgm, sel[g]->p.nr);
2041 snew(sel[g]->orgq, sel[g]->p.nr);
2042 for (b = 0; b < sel[g]->p.nr; ++b)
2044 sel[g]->orgq[b] = 0;
2045 if (top)
2047 sel[g]->orgm[b] = 0;
2048 for (i = sel[g]->p.m.mapb.index[b]; i < sel[g]->p.m.mapb.index[b+1]; ++i)
2050 sel[g]->orgm[b] += top->atoms.atom[sel[g]->g->index[i]].m;
2051 sel[g]->orgq[b] += top->atoms.atom[sel[g]->g->index[i]].q;
2054 else
2056 sel[g]->orgm[b] = 1;
2059 if (sel[g]->bDynamic && !bMaskOnly)
2061 snew(sel[g]->m, sel[g]->p.nr);
2062 snew(sel[g]->q, sel[g]->p.nr);
2063 for (b = 0; b < sel[g]->p.nr; ++b)
2065 sel[g]->m[b] = sel[g]->orgm[b];
2066 sel[g]->q[b] = sel[g]->orgq[b];
2069 else
2071 sel[g]->m = sel[g]->orgm;
2072 sel[g]->q = sel[g]->orgq;
2078 /********************************************************************
2079 * GROUP NAME INITIALIZATION
2080 ********************************************************************/
2082 /*! \brief
2083 * Initializes the names of the output index groups.
2085 * \param[in] ngrps Number of elements in the \p sel array.
2086 * \param[in,out] sel Output selections.
2088 * The name for the index group is either taken from the \p name field
2089 * of the root selection element, or set to "Selection N" (for the N'th
2090 * group).
2092 static void set_group_names(int ngrps, gmx_ana_selection_t *sel[])
2094 int g;
2096 for (g = 0; g < ngrps; ++g)
2098 char *name = NULL;
2100 if (sel[g]->selelem->name)
2102 name = strdup(sel[g]->selelem->name);
2104 if (!name)
2106 snew(name, 14);
2107 snprintf(name, 14, "Selection %d", g+1);
2109 if (!sel[g]->selelem->name)
2111 sel[g]->selelem->name = name;
2113 sel[g]->name = name;
2118 /********************************************************************
2119 * MAIN COMPILATION FUNCTION
2120 ********************************************************************/
2123 * \param[in,out] sc Selection collection to be compiled.
2124 * \returns 0 on successful compilation, a non-zero error code on error.
2126 * Before compilation, the selection collection should have been initialized
2127 * with gmx_ana_selcollection_parse_*().
2128 * The compiled selection collection can be passed to
2129 * gmx_ana_selcollection_evaluate() to evaluate the selection for a frame.
2130 * If an error occurs, \p sc is cleared.
2132 * The covered fraction information in \p sc is initialized to
2133 * \ref CFRAC_NONE.
2136 gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
2138 gmx_sel_evaluate_t evaldata;
2139 t_selelem *item;
2140 e_poscalc_t post;
2141 int flags;
2142 int rc;
2144 _gmx_sel_evaluate_init(&evaldata, &sc->gall, sc->top, NULL, NULL);
2146 /* Clear the symbol table because it is not possible to parse anything
2147 * after compilation, and variable references in the symbol table can
2148 * also mess up the compilation and/or become invalid.
2150 _gmx_selcollection_clear_symtab(sc);
2152 /* Extract subexpressions into separate roots */
2153 sc->root = extract_subexpressions(sc->root, &sc->gall);
2155 /* Initialize the evaluation callbacks and process the tree structure
2156 * to conform to the expectations of the callback functions. */
2157 /* Also, initialize and allocate the compiler data structure */
2158 item = sc->root;
2159 while (item)
2161 /* Process boolean expressions */
2162 optimize_boolean_expressions(item);
2163 reorder_boolean_static_children(item);
2164 /* Initialize evaluation */
2165 if (!init_item_evaluation(item))
2167 /* FIXME: Clean up the collection */
2168 return -1;
2170 /* Initialize the compiler data */
2171 init_item_compilerdata(item);
2172 init_item_staticeval(item);
2173 item = item->next;
2175 /* Initialize the evaluation index groups */
2176 initialize_evalgrps(sc);
2178 /* Evaluate all static parts of the selection and analyze the tree
2179 * to allocate enough memory to store the value of each dynamic subtree. */
2180 item = sc->root;
2181 while (item)
2183 if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
2185 mark_subexpr_dynamic(item->child, TRUE);
2187 set_evaluation_function(item, &analyze_static);
2188 rc = item->evaluate(&evaldata, item, NULL);
2189 if (rc != 0)
2191 /* FIXME: Clean up the collection */
2192 return rc;
2194 item = item->next;
2197 /* Do a second pass to evaluate static parts of common subexpressions */
2198 /* Note that the refcount check skips constant subexpressions completely
2199 * since they were already evaluated by analyze_static(). */
2200 item = sc->root;
2201 while (item)
2203 if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
2205 mark_subexpr_dynamic(item->child, FALSE);
2206 item->child->u.cgrp.isize = 0;
2207 if (item->child->v.type == GROUP_VALUE)
2209 item->child->child->v.u.g->isize = 0;
2211 set_evaluation_function(item, &analyze_static2);
2212 rc = item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
2213 if (rc != 0)
2215 /* FIXME: Clean up the collection */
2216 return rc;
2219 item = item->next;
2222 /* Create the root elements if they do not yet exist. */
2223 /* The evaluation group of an existing root is also initialized here. */
2224 sc->root = process_roots(sc->root);
2226 /* Initialize position calculations for methods, perform some final
2227 * optimization and free the memory allocated for the compilation. */
2228 /* By default, use whole residues/molecules. */
2229 flags = POS_COMPLWHOLE;
2230 rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &post, &flags);
2231 if (rc != 0)
2233 gmx_bug("invalid default reference position type");
2234 /* FIXME: Clean up the collection */
2235 return rc;
2237 item = sc->root;
2238 while (item)
2240 optimize_item_subexpressions(item);
2241 rc = init_item_comg(item, sc->pcc, post, flags);
2242 if (rc != 0)
2244 /* FIXME: Clean up the collection */
2245 return rc;
2247 free_item_compilerdata(item);
2248 item = item->next;
2251 /* Finish up by updating some information */
2252 update_info(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
2253 set_group_names(sc->nr, sc->sel);
2255 return 0;