3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 * \brief Implementation of functions in selelem.h.
39 #include <gmx_fatal.h>
41 #include <indexutil.h>
44 #include <selmethod.h>
52 * \param[in] sel Selection for which the string is requested
53 * \returns Pointer to a string that corresponds to \p sel->type.
55 * The return value points to a string constant and should not be \p free'd.
57 * The function returns NULL if \p sel->type is not one of the valid values.
60 _gmx_selelem_type_str(t_selelem
*sel
)
64 case SEL_CONST
: return "CONST";
65 case SEL_EXPRESSION
: return "EXPR";
66 case SEL_BOOLEAN
: return "BOOL";
67 case SEL_ARITHMETIC
: return "ARITH";
68 case SEL_ROOT
: return "ROOT";
69 case SEL_SUBEXPR
: return "SUBEXPR";
70 case SEL_SUBEXPRREF
: return "REF";
71 case SEL_MODIFIER
: return "MODIFIER";
77 * \param[in] val Value structore for which the string is requested.
78 * \returns Pointer to a string that corresponds to \p val->type,
79 * NULL if the type value is invalid.
81 * The return value points to a string constant and should not be \p free'd.
84 _gmx_sel_value_type_str(gmx_ana_selvalue_t
*val
)
88 case NO_VALUE
: return "NONE";
89 case INT_VALUE
: return "INT";
90 case REAL_VALUE
: return "REAL";
91 case STR_VALUE
: return "STR";
92 case POS_VALUE
: return "VEC";
93 case GROUP_VALUE
: return "GROUP";
98 /*! \copydoc _gmx_selelem_type_str() */
100 _gmx_selelem_boolean_type_str(t_selelem
*sel
)
102 switch (sel
->u
.boolt
)
104 case BOOL_NOT
: return "NOT"; break;
105 case BOOL_AND
: return "AND"; break;
106 case BOOL_OR
: return "OR"; break;
107 case BOOL_XOR
: return "XOR"; break;
113 * \param[in] type Type of selection element to allocate.
114 * \returns Pointer to the newly allocated and initialized element.
116 * \c t_selelem::type is set to \p type,
117 * \c t_selelem::v::type is set to \ref GROUP_VALUE for boolean and comparison
118 * expressions and \ref NO_VALUE for others,
119 * \ref SEL_ALLOCVAL is set for non-root elements (\ref SEL_ALLOCDATA is also
120 * set for \ref SEL_BOOLEAN elements),
121 * and \c t_selelem::refcount is set to one.
122 * All the pointers are set to NULL.
125 _gmx_selelem_create(e_selelem_t type
)
132 sel
->flags
= (type
!= SEL_ROOT
) ? SEL_ALLOCVAL
: 0;
133 if (type
== SEL_BOOLEAN
)
135 sel
->v
.type
= GROUP_VALUE
;
136 sel
->flags
|= SEL_ALLOCDATA
;
140 sel
->v
.type
= NO_VALUE
;
142 _gmx_selvalue_clear(&sel
->v
);
143 sel
->evaluate
= NULL
;
153 * \param[in,out] sel Selection element to set the type for.
154 * \param[in] vtype Value type for the selection element.
155 * \returns 0 on success, EINVAL if the value type is invalid.
157 * If the new type is \ref GROUP_VALUE or \ref POS_VALUE, the
158 * \ref SEL_ALLOCDATA flag is also set.
160 * This function should only be called at most once for each element,
161 * preferably right after calling _gmx_selelem_create().
164 _gmx_selelem_set_vtype(t_selelem
*sel
, e_selvalue_t vtype
)
166 if (sel
->type
== SEL_BOOLEAN
&& vtype
!= GROUP_VALUE
)
168 gmx_bug("internal error");
171 if (sel
->v
.type
!= NO_VALUE
&& vtype
!= sel
->v
.type
)
173 gmx_call("_gmx_selelem_set_vtype() called more than once");
177 if (vtype
== GROUP_VALUE
|| vtype
== POS_VALUE
)
179 sel
->flags
|= SEL_ALLOCDATA
;
185 * \param[in,out] sel Selection element to reserve.
186 * \param[in] count Number of values to reserve memory for.
187 * \returns 0 on success or if no memory pool, non-zero on error.
189 * Reserves memory for the values of \p sel from the \p sel->mempool
190 * memory pool. If no memory pool is set, nothing is done.
193 _gmx_selelem_mempool_reserve(t_selelem
*sel
, int count
)
204 rc
= _gmx_sel_mempool_alloc(sel
->mempool
, (void **)&sel
->v
.u
.i
,
205 sizeof(*sel
->v
.u
.i
)*count
);
209 rc
= _gmx_sel_mempool_alloc(sel
->mempool
, (void **)&sel
->v
.u
.r
,
210 sizeof(*sel
->v
.u
.r
)*count
);
214 rc
= _gmx_sel_mempool_alloc_group(sel
->mempool
, sel
->v
.u
.g
, count
);
218 gmx_incons("mem pooling not implemented for requested type");
225 * \param[in,out] sel Selection element to release.
227 * Releases the memory allocated for the values of \p sel from the
228 * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
231 _gmx_selelem_mempool_release(t_selelem
*sel
)
241 _gmx_sel_mempool_free(sel
->mempool
, sel
->v
.u
.ptr
);
247 _gmx_sel_mempool_free_group(sel
->mempool
, sel
->v
.u
.g
);
252 gmx_incons("mem pooling not implemented for requested type");
258 * \param[in] sel Selection to free.
261 _gmx_selelem_free_values(t_selelem
*sel
)
265 _gmx_selelem_mempool_release(sel
);
266 if ((sel
->flags
& SEL_ALLOCDATA
) && sel
->v
.u
.ptr
)
268 /* The number of position/group structures is constant, so the
269 * backup of using sel->v.nr should work for them.
270 * For strings, we report an error if we don't know the allocation
272 n
= (sel
->v
.nalloc
> 0) ? sel
->v
.nalloc
: sel
->v
.nr
;
276 if (sel
->v
.nalloc
== 0)
278 gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
281 for (i
= 0; i
< n
; ++i
)
283 sfree(sel
->v
.u
.s
[i
]);
287 for (i
= 0; i
< n
; ++i
)
289 gmx_ana_pos_deinit(&sel
->v
.u
.p
[i
]);
293 for (i
= 0; i
< n
; ++i
)
295 gmx_ana_index_deinit(&sel
->v
.u
.g
[i
]);
298 default: /* No special handling for other types */
302 if (sel
->flags
& SEL_ALLOCVAL
)
306 _gmx_selvalue_setstore(&sel
->v
, NULL
);
307 if (sel
->type
== SEL_SUBEXPRREF
&& sel
->u
.param
)
309 sel
->u
.param
->val
.u
.ptr
= NULL
;
314 * \param[in] method Method to free.
315 * \param[in] mdata Method data to free.
318 _gmx_selelem_free_method(gmx_ana_selmethod_t
*method
, void *mdata
)
320 sel_freefunc free_func
= NULL
;
322 /* Save the pointer to the free function. */
323 if (method
&& method
->free
)
325 free_func
= method
->free
;
328 /* Free the method itself.
329 * Has to be done before freeing the method data, because parameter
330 * values are typically stored in the method data, and here we may
336 /* Free the memory allocated for the parameters that are not managed
337 * by the selection method itself. */
338 for (i
= 0; i
< method
->nparams
; ++i
)
340 gmx_ana_selparam_t
*param
= &method
->param
[i
];
342 if (param
->val
.u
.ptr
)
344 if (param
->val
.type
== GROUP_VALUE
)
346 for (j
= 0; j
< param
->val
.nr
; ++j
)
348 gmx_ana_index_deinit(¶m
->val
.u
.g
[j
]);
351 else if (param
->val
.type
== POS_VALUE
)
353 for (j
= 0; j
< param
->val
.nr
; ++j
)
355 gmx_ana_pos_deinit(¶m
->val
.u
.p
[j
]);
359 if (param
->val
.nalloc
> 0)
361 sfree(param
->val
.u
.ptr
);
365 sfree(method
->param
);
368 /* Free method data. */
380 * \param[in] sel Selection to free.
383 _gmx_selelem_free_exprdata(t_selelem
*sel
)
385 if (sel
->type
== SEL_EXPRESSION
|| sel
->type
== SEL_MODIFIER
)
387 _gmx_selelem_free_method(sel
->u
.expr
.method
, sel
->u
.expr
.mdata
);
388 sel
->u
.expr
.mdata
= NULL
;
389 sel
->u
.expr
.method
= NULL
;
390 /* Free position data */
393 gmx_ana_pos_free(sel
->u
.expr
.pos
);
394 sel
->u
.expr
.pos
= NULL
;
396 /* Free position calculation data */
399 gmx_ana_poscalc_free(sel
->u
.expr
.pc
);
400 sel
->u
.expr
.pc
= NULL
;
403 if (sel
->type
== SEL_ARITHMETIC
)
405 sfree(sel
->u
.arith
.opstr
);
406 sel
->u
.arith
.opstr
= NULL
;
408 if (sel
->type
== SEL_SUBEXPR
|| sel
->type
== SEL_ROOT
409 || (sel
->type
== SEL_CONST
&& sel
->v
.type
== GROUP_VALUE
))
411 gmx_ana_index_deinit(&sel
->u
.cgrp
);
416 * \param[in] sel Selection to free.
418 * Decrements \ref t_selelem::refcount "sel->refcount" and frees the
419 * memory allocated for \p sel and all its children if the reference count
423 _gmx_selelem_free(t_selelem
*sel
)
425 /* Decrement the reference counter and do nothing if references remain */
427 if (sel
->refcount
> 0)
432 /* Free the children.
433 * Must be done before freeing other data, because the children may hold
434 * references to data in this element. */
435 _gmx_selelem_free_chain(sel
->child
);
437 /* Free value storage */
438 _gmx_selelem_free_values(sel
);
440 /* Free other storage */
441 _gmx_selelem_free_exprdata(sel
);
443 /* Free temporary compiler data if present */
444 _gmx_selelem_free_compiler_data(sel
);
450 * \param[in] first First selection to free.
452 * Frees \p first and all selections accessible through the
453 * \ref t_selelem::next "first->next" pointer.
456 _gmx_selelem_free_chain(t_selelem
*first
)
458 t_selelem
*child
, *prev
;
465 _gmx_selelem_free(prev
);
470 * Writes out a human-readable name for the evaluation function.
472 * \param[in] fp File handle to receive the output.
473 * \param[in] sel Selection element for which the evaluation function is printed.
476 print_evaluation_func(FILE *fp
, t_selelem
*sel
)
478 fprintf(fp
, " eval=");
481 else if (sel
->evaluate
== &_gmx_sel_evaluate_root
)
483 else if (sel
->evaluate
== &_gmx_sel_evaluate_static
)
484 fprintf(fp
, "static");
485 else if (sel
->evaluate
== &_gmx_sel_evaluate_subexpr_simple
)
486 fprintf(fp
, "subexpr_simple");
487 else if (sel
->evaluate
== &_gmx_sel_evaluate_subexpr_staticeval
)
488 fprintf(fp
, "subexpr_staticeval");
489 else if (sel
->evaluate
== &_gmx_sel_evaluate_subexpr
)
490 fprintf(fp
, "subexpr");
491 else if (sel
->evaluate
== &_gmx_sel_evaluate_subexprref_simple
)
492 fprintf(fp
, "ref_simple");
493 else if (sel
->evaluate
== &_gmx_sel_evaluate_subexprref
)
495 else if (sel
->evaluate
== &_gmx_sel_evaluate_method
)
496 fprintf(fp
, "method");
497 else if (sel
->evaluate
== &_gmx_sel_evaluate_modifier
)
499 else if (sel
->evaluate
== &_gmx_sel_evaluate_not
)
501 else if (sel
->evaluate
== &_gmx_sel_evaluate_and
)
503 else if (sel
->evaluate
== &_gmx_sel_evaluate_or
)
505 else if (sel
->evaluate
== &_gmx_sel_evaluate_arithmetic
)
506 fprintf(fp
, "arithmetic");
508 fprintf(fp
, "%p", (void*)(sel
->evaluate
));
512 * \param[in] fp File handle to receive the output.
513 * \param[in] sel Root of the selection subtree to print.
514 * \param[in] bValues If TRUE, the evaluated values of selection elements
515 * are printed as well.
516 * \param[in] level Indentation level, starting from zero.
519 _gmx_selelem_print_tree(FILE *fp
, t_selelem
*sel
, bool bValues
, int level
)
524 fprintf(fp
, "%*c %s %s", level
*2+1, '*',
525 _gmx_selelem_type_str(sel
), _gmx_sel_value_type_str(&sel
->v
));
528 fprintf(fp
, " \"%s\"", sel
->name
);
530 fprintf(fp
, " flg=");
531 if (sel
->flags
& SEL_FLAGSSET
)
535 if (sel
->flags
& SEL_SINGLEVAL
)
539 if (sel
->flags
& SEL_ATOMVAL
)
543 if (sel
->flags
& SEL_VARNUMVAL
)
547 if (sel
->flags
& SEL_DYNAMIC
)
551 if (!(sel
->flags
& SEL_VALFLAGMASK
))
559 if (sel
->type
== SEL_CONST
)
561 if (sel
->v
.type
== INT_VALUE
)
563 fprintf(fp
, " %d", sel
->v
.u
.i
[0]);
565 else if (sel
->v
.type
== REAL_VALUE
)
567 fprintf(fp
, " %f", sel
->v
.u
.r
[0]);
569 else if (sel
->v
.type
== GROUP_VALUE
)
571 gmx_ana_index_t
*g
= sel
->v
.u
.g
;
572 if (!g
|| g
->isize
== 0)
574 fprintf(fp
, " (%d atoms)", g
->isize
);
577 else if (sel
->type
== SEL_BOOLEAN
)
579 fprintf(fp
, " %s", _gmx_selelem_boolean_type_str(sel
));
581 else if (sel
->type
== SEL_EXPRESSION
582 && sel
->u
.expr
.method
->name
== sm_compare
.name
)
584 _gmx_selelem_print_compare_info(fp
, sel
->u
.expr
.mdata
);
588 print_evaluation_func(fp
, sel
);
590 if (sel
->refcount
> 1)
592 fprintf(fp
, " refc=%d", sel
->refcount
);
594 if (!(sel
->flags
& SEL_ALLOCVAL
))
596 fprintf(fp
, " (ext. output)");
600 if ((sel
->type
== SEL_CONST
&& sel
->v
.type
== GROUP_VALUE
) || sel
->type
== SEL_ROOT
)
602 gmx_ana_index_t
*g
= sel
->v
.u
.g
;
603 if (!g
|| g
->isize
== 0 || sel
->evaluate
!= NULL
)
609 fprintf(fp
, "%*c group:", level
*2+1, ' ');
612 for (i
= 0; i
< g
->isize
; ++i
)
614 fprintf(fp
, " %d", g
->index
[i
] + 1);
619 fprintf(fp
, " %d atoms", g
->isize
);
624 else if (sel
->type
== SEL_EXPRESSION
)
628 fprintf(fp
, "%*c COM", level
*2+3, '*');
633 if (bValues
&& sel
->type
!= SEL_CONST
&& sel
->type
!= SEL_ROOT
&& sel
->v
.u
.ptr
)
635 fprintf(fp
, "%*c value: ", level
*2+1, ' ');
639 /* In normal use, the pointer should never be NULL, but it's
640 * useful to have the check for debugging to avoid accidental
641 * segfaults when printing the selection tree. */
644 fprintf(fp
, "(%f, %f, %f)",
645 sel
->v
.u
.p
->x
[0][XX
], sel
->v
.u
.p
->x
[0][YY
],
646 sel
->v
.u
.p
->x
[0][ZZ
]);
650 fprintf(fp
, "(null)");
654 fprintf(fp
, "%d atoms", sel
->v
.u
.g
->isize
);
655 if (sel
->v
.u
.g
->isize
< 20)
657 if (sel
->v
.u
.g
->isize
> 0)
661 for (i
= 0; i
< sel
->v
.u
.g
->isize
; ++i
)
663 fprintf(fp
, " %d", sel
->v
.u
.g
->index
[i
] + 1);
674 /* Print the subexpressions with one more level of indentation */
678 if (!(sel
->type
== SEL_SUBEXPRREF
&& child
->type
== SEL_SUBEXPR
))
680 _gmx_selelem_print_tree(fp
, child
, bValues
, level
+1);
687 * \param[in] root Root of the subtree to query.
688 * \returns TRUE if \p root or any any of its elements require topology
689 * information, FALSE otherwise.
692 _gmx_selelem_requires_top(t_selelem
*root
)
696 if (root
->type
== SEL_EXPRESSION
|| root
->type
== SEL_MODIFIER
)
698 if (root
->u
.expr
.method
&& (root
->u
.expr
.method
->flags
& SMETH_REQTOP
))
702 if (root
->u
.expr
.pc
&& gmx_ana_poscalc_requires_top(root
->u
.expr
.pc
))
710 if (_gmx_selelem_requires_top(child
))