SelectionData::SelectionData(SelectionTreeElement *elem, const char *selstr) : name_(elem->name()), selectionText_(selstr), rootElement_(*elem), coveredFractionType_(CFRAC_NONE), coveredFraction_(1.0), averageCoveredFraction_(1.0), bDynamic_(false), bDynamicCoveredFraction_(false) { gmx_ana_pos_clear(&rawPositions_); if (elem->child->type == SEL_CONST) { // TODO: This is not exception-safe if any called function throws. gmx_ana_pos_copy(&rawPositions_, elem->child->v.u.p, true); } else { SelectionTreeElementPointer child = elem->child; child->flags &= ~SEL_ALLOCVAL; _gmx_selvalue_setstore(&child->v, &rawPositions_); /* We should also skip any modifiers to determine the dynamic * status. */ while (child->type == SEL_MODIFIER) { child = child->child; if (child->type == SEL_SUBEXPRREF) { child = child->child; /* Because most subexpression elements are created * during compilation, we need to check for them * explicitly here. */ if (child->type == SEL_SUBEXPR) { child = child->child; } } } /* For variable references, we should skip the * SEL_SUBEXPRREF and SEL_SUBEXPR elements. */ if (child->type == SEL_SUBEXPRREF) { child = child->child->child; } bDynamic_ = (child->child->flags & SEL_DYNAMIC); } initCoveredFraction(CFRAC_NONE); }
/*! * \param[in] top Topology data structure. * \param[in,out] out Pointer to output data structure. * \param[in,out] data Should point to \c t_methoddata_permute. */ static void init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data) { t_methoddata_permute *d = (t_methoddata_permute *)data; int i, j, b; gmx_ana_pos_copy(out->u.p, &d->p, true); gmx_ana_pos_set_evalgrp(out->u.p, &d->g); d->g.isize = 0; gmx_ana_pos_empty_init(out->u.p); for (i = 0; i < d->p.nr; i += d->n) { for (j = 0; j < d->n; ++j) { b = i + d->rperm[j]; gmx_ana_pos_append_init(out->u.p, &d->g, &d->p, b); } } }
/*! * \param[in,out] sc Selection collection to append to. * \param sel Selection to append to \p sc (can be NULL, in which * case nothing is done). * \param last Last selection in \p sc, or NULL if not present or not * known. * \returns The last selection in \p sc after the append. * * Appends \p sel after the last root element in \p sc, and returns either * \p sel (if it was non-NULL) or the last element in \p sc (if \p sel was * NULL). */ t_selelem * _gmx_sel_append_selection(gmx_ana_selcollection_t *sc, t_selelem *sel, t_selelem *last) { if (last) { last->next = sel; } else { if (sc->root) { last = sc->root; while (last->next) { last = last->next; } last->next = sel; } else { sc->root = sel; } } if (sel) { last = sel; /* Add the new selection to the collection if it is not a variable. */ if (sel->child->type != SEL_SUBEXPR) { int i; sc->nr++; srenew(sc->sel, sc->nr); i = sc->nr - 1; snew(sc->sel[i], 1); if (sel->child->type == SEL_CONST) { gmx_ana_pos_copy(&sc->sel[i]->p, sel->child->v.u.p, TRUE); sc->sel[i]->bDynamic = FALSE; } else { t_selelem *child; child = sel->child; child->flags &= ~SEL_ALLOCVAL; _gmx_selvalue_setstore(&child->v, &sc->sel[i]->p); /* We should also skip any modifiers to determine the dynamic * status. */ while (child->type == SEL_MODIFIER) { child = child->child; } /* For variable references, we should skip the * SEL_SUBEXPRREF and SEL_SUBEXPR elements. */ if (child->type == SEL_SUBEXPRREF) { child = child->child->child; } sc->sel[i]->bDynamic = (child->child->flags & SEL_DYNAMIC); } /* The group will be set after compilation */ sc->sel[i]->g = NULL; sc->sel[i]->selelem = sel; gmx_ana_selection_init_coverfrac(sc->sel[i], CFRAC_NONE); } } return last; }
/*! * \param[in] data Data for the current frame. * \param[in] sel Selection element being evaluated. * \param[in] g Group for which \p sel should be evaluated. * \returns 0 on success, a non-zero error code on error. * * If the value type is \ref POS_VALUE, the value of the child is simply * copied to set the value of \p sel (the child subexpression should * already have been evaluated by its root). * If the value type is something else, the child is evaluated for the * group \p g, and the value of the child is then copied. * There should be only one child element. * * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPRREF * elements. */ void _gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g) { t_selelem *expr; int i, j; if (g) { sel->child->evaluate(data, sel->child, g); } expr = sel->child; switch (sel->v.type) { case INT_VALUE: if (!g) { sel->v.nr = expr->v.nr; memcpy(sel->v.u.i, expr->v.u.i, sel->v.nr*sizeof(*sel->v.u.i)); } else { sel->v.nr = g->isize; /* Extract the values corresponding to g */ for (i = j = 0; i < g->isize; ++i, ++j) { while (sel->child->u.cgrp.index[j] < g->index[i]) { ++j; } sel->v.u.i[i] = expr->v.u.i[j]; } } break; case REAL_VALUE: if (!g) { sel->v.nr = expr->v.nr; memcpy(sel->v.u.r, expr->v.u.r, sel->v.nr*sizeof(*sel->v.u.r)); } else { sel->v.nr = g->isize; /* Extract the values corresponding to g */ for (i = j = 0; i < g->isize; ++i, ++j) { while (sel->child->u.cgrp.index[j] < g->index[i]) { ++j; } sel->v.u.r[i] = expr->v.u.r[j]; } } break; case STR_VALUE: if (!g) { sel->v.nr = expr->v.nr; memcpy(sel->v.u.s, expr->v.u.s, sel->v.nr*sizeof(*sel->v.u.s)); } else { sel->v.nr = g->isize; /* Extract the values corresponding to g */ for (i = j = 0; i < g->isize; ++i, ++j) { while (sel->child->u.cgrp.index[j] < g->index[i]) { ++j; } sel->v.u.s[i] = expr->v.u.s[j]; } } break; case POS_VALUE: /* Currently, there is no need to do anything fancy here, * but some future extensions may need a more flexible * implementation. */ gmx_ana_pos_copy(sel->v.u.p, expr->v.u.p, false); break; case GROUP_VALUE: if (!g) { gmx_ana_index_copy(sel->v.u.g, expr->v.u.g, false); } else { gmx_ana_index_intersection(sel->v.u.g, expr->v.u.g, g); } break; default: /* should not be reached */ GMX_THROW(gmx::InternalError("Invalid subexpression reference type")); } /* Store the number of values if needed */ if (sel->u.param) { sel->u.param->val.nr = sel->v.nr; if (sel->u.param->nvalptr) { *sel->u.param->nvalptr = sel->u.param->val.nr; } } }