Esempio n. 1
0
void SelectionTreeElement::mempoolRelease()
{
    if (!mempool)
    {
        return;
    }
    switch (v.type)
    {
    case INT_VALUE:
    case REAL_VALUE:
        _gmx_sel_mempool_free(mempool, v.u.ptr);
        _gmx_selvalue_setstore(&v, NULL);
        break;

    case GROUP_VALUE:
        if (v.u.g)
        {
            _gmx_sel_mempool_free_group(mempool, v.u.g);
        }
        break;

    default:
        GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
    }
}
Esempio n. 2
0
/*!
 * \param[in,out] sel   Selection element to release.
 *
 * Releases the memory allocated for the values of \p sel from the
 * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
 */
void
_gmx_selelem_mempool_release(t_selelem *sel)
{
    if (!sel->mempool)
    {
        return;
    }
    switch (sel->v.type)
    {
        case INT_VALUE:
        case REAL_VALUE:
            _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
            _gmx_selvalue_setstore(&sel->v, NULL);
            break;

        case GROUP_VALUE:
            if (sel->v.u.g)
            {
                _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
            }
            break;

        default:
            GMX_THROW(gmx::InternalError("Memory pooling not implemented for requested type"));
    }
}
Esempio n. 3
0
 void assign(t_selelem *sel, t_selelem *vsource)
 {
     GMX_RELEASE_ASSERT(sel_ == NULL, "Can only assign one element with one instance");
     old_ptr_ = sel->v.u.ptr;
     old_nalloc_ = sel->v.nalloc;
     _gmx_selvalue_setstore(&sel->v, vsource->v.u.ptr);
     sel_ = sel;
 }
Esempio n. 4
0
/*!
 * \param[in] sel Selection to free.
 */
void
_gmx_selelem_free_values(t_selelem *sel)
{
    int   i, n;

    _gmx_selelem_mempool_release(sel);
    if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
    {
        /* The number of position/group structures is constant, so the
         * backup of using sel->v.nr should work for them.
         * For strings, we report an error if we don't know the allocation
         * size here. */
        n = (sel->v.nalloc > 0) ? sel->v.nalloc : sel->v.nr;
        switch (sel->v.type)
        {
            case STR_VALUE:
                if (sel->v.nalloc == 0)
                {
                    gmx_bug("SEL_ALLOCDATA should only be set for allocated STR_VALUE values");
                    break;
                }
                for (i = 0; i < n; ++i)
                {
                    sfree(sel->v.u.s[i]);
                }
                break;
            case POS_VALUE:
                for (i = 0; i < n; ++i)
                {
                    gmx_ana_pos_deinit(&sel->v.u.p[i]);
                }
                break;
            case GROUP_VALUE:
                for (i = 0; i < n; ++i)
                {
                    gmx_ana_index_deinit(&sel->v.u.g[i]);
                }
                break;
            default: /* No special handling for other types */
                break;
        }
    }
    if (sel->flags & SEL_ALLOCVAL)
    {
        sfree(sel->v.u.ptr);
    }
    _gmx_selvalue_setstore(&sel->v, NULL);
    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
    {
        sel->u.param->val.u.ptr = NULL;
    }
}
Esempio n. 5
0
/*! \brief
 * Parses an expression value for a parameter that takes a variable number of values.
 * 
 * \param[in] nval   Number of values in \p values.
 * \param[in] values Pointer to the list of values.
 * \param     param  Parameter to parse.
 * \param     root   Selection element to which child expressions are added.
 * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
 */
static gmx_bool
parse_values_varnum_expr(int nval, t_selexpr_value *values,
                         gmx_ana_selparam_t *param, t_selelem *root)
{
    t_selexpr_value    *value;
    t_selelem          *child;
    t_selelem          *expr;

    if (nval != 1 || !values->bExpr)
    {
        gmx_bug("internal error");
        return FALSE;
    }

    value = values;
    child = add_child(root, param, value->u.expr);
    value->u.expr = NULL;
    if (!child)
    {
        return FALSE;
    }

    /* Process single-valued expressions */
    /* TODO: We should also handle SEL_SINGLEVAL expressions here */
    if (child->v.type == POS_VALUE || child->v.type == GROUP_VALUE)
    {
        /* Set the value storage */
        _gmx_selvalue_setstore(&child->v, param->val.u.ptr);
        param->val.nr = 1;
        if (param->nvalptr)
        {
            *param->nvalptr = param->val.nr;
        }
        param->nvalptr = NULL;
        return TRUE;
    }

    if (!(child->flags & SEL_VARNUMVAL))
    {
        _gmx_selparser_error("invalid expression value for parameter '%s'",
                             param->name);
        return FALSE;
    }

    child->flags   |= SEL_ALLOCVAL;
    param->val.nr   = -1;
    *param->nvalptr = param->val.nr;
    /* Rest of the initialization is done during compilation in
     * init_method(). */

    return TRUE;
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
/*!
 * \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 for success.
 *
 * Sets the value pointers of the child and its child to point to the same
 * memory as the value pointer of this element to avoid copying, and then
 * evaluates evaluates the child.
 *
 * This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
 * elements for which the \ref SEL_SUBEXPR does not have other references.
 */
void
_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
{
    if (g)
    {
        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
        _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
                                     sel->child->child->v.nalloc);
        sel->child->evaluate(data, sel->child, g);
    }
    sel->v.nr = sel->child->v.nr;
    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;
        }
    }
}
Esempio n. 8
0
/*! \brief
 * Initializes the method parameter data of \ref SEL_EXPRESSION and
 * \ref SEL_MODIFIER elements.
 *
 * \param[in]     sc     Selection collection.
 * \param[in,out] sel    Selection element to initialize.
 *
 * A deep copy of the parameters is made to allow several
 * expressions with the same method to coexist peacefully.
 * Calls sel_datafunc() if one is specified for the method.
 */
static void
init_method_params(gmx_ana_selcollection_t *sc, t_selelem *sel)
{
    int                 nparams;
    gmx_ana_selparam_t *orgparam;
    gmx_ana_selparam_t *param;
    int                 i;
    void               *mdata;

    nparams   = sel->u.expr.method->nparams;
    orgparam  = sel->u.expr.method->param;
    snew(param, nparams);
    memcpy(param, orgparam, nparams*sizeof(gmx_ana_selparam_t));
    for (i = 0; i < nparams; ++i)
    {
        param[i].flags &= ~SPAR_SET;
        _gmx_selvalue_setstore(&param[i].val, NULL);
        if (param[i].flags & SPAR_VARNUM)
        {
            param[i].val.nr = -1;
        }
    }
    mdata = NULL;
    if (sel->u.expr.method->init_data)
    {
        mdata = sel->u.expr.method->init_data(nparams, param);
        if (mdata == NULL)
        {
            gmx_fatal(FARGS, "Method data initialization failed");
        }
    }
    if (sel->u.expr.method->set_poscoll)
    {
        sel->u.expr.method->set_poscoll(sc->pcc, mdata);
    }
    /* Store the values */
    sel->u.expr.method->param = param;
    sel->u.expr.mdata         = mdata;
}
Esempio n. 9
0
/*!
 * \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;
}
Esempio n. 10
0
/*! \brief
 * Parses the values for a parameter that takes a variable number of values.
 * 
 * \param[in] nval   Number of values in \p values.
 * \param[in] values Pointer to the list of values.
 * \param     param  Parameter to parse.
 * \param     root   Selection element to which child expressions are added.
 * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
 *
 * For integer ranges, the sequence of numbers from the first to second value
 * is stored, each as a separate value.
 */
static gmx_bool
parse_values_varnum(int nval, t_selexpr_value *values,
                    gmx_ana_selparam_t *param, t_selelem *root)
{
    t_selexpr_value    *value;
    int                 i, j;

    param->flags &= ~SPAR_DYNAMIC;
    /* Update nval if there are integer ranges. */
    if (param->val.type == INT_VALUE)
    {
        value = values;
        while (value)
        {
            if (value->type == INT_VALUE && !value->bExpr)
            {
                nval += abs(value->u.i.i2 - value->u.i.i1);
            }
            value = value->next;
        }
    }

    /* Check that the value type is actually implemented */
    if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE
        && param->val.type != STR_VALUE && param->val.type != POS_VALUE)
    {
        gmx_bug("internal error");
        return FALSE;
    }

    /* Reserve appropriate amount of memory */
    if (param->val.type == POS_VALUE)
    {
        gmx_ana_pos_reserve(param->val.u.p, nval, 0);
        gmx_ana_pos_set_nr(param->val.u.p, nval);
        gmx_ana_indexmap_init(&param->val.u.p->m, NULL, NULL, INDEX_UNKNOWN);
    }
    else
    {
        _gmx_selvalue_reserve(&param->val, nval);
    }

    value = values;
    i     = 0;
    while (value)
    {
        if (value->bExpr)
        {
            _gmx_selparser_error("expressions not supported within value lists");
            return FALSE;
        }
        if (value->type != param->val.type)
        {
            gmx_bug("internal error");
            return FALSE;
        }
        switch (param->val.type)
        {
            case INT_VALUE:
                if (value->u.i.i1 <= value->u.i.i2)
                {
                    for (j = value->u.i.i1; j <= value->u.i.i2; ++j)
                    {
                        param->val.u.i[i++] = j;
                    }
                }
                else
                {
                    for (j = value->u.i.i1; j >= value->u.i.i2; --j)
                    {
                        param->val.u.i[i++] = j;
                    }
                }
                break;
            case REAL_VALUE:
                if (value->u.r.r1 != value->u.r.r2)
                {
                    _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name);
                    return FALSE;
                }
                param->val.u.r[i++] = value->u.r.r1;
                break;
            case STR_VALUE:  param->val.u.s[i++] = strdup(value->u.s); break;
            case POS_VALUE:  copy_rvec(value->u.x, param->val.u.p->x[i++]); break;
            default: /* Should not be reached */
                gmx_bug("internal error");
                return FALSE;
        }
        value = value->next;
    }
    param->val.nr = i;
    if (param->nvalptr)
    {
        *param->nvalptr = param->val.nr;
    }
    param->nvalptr = NULL;
    /* Create a dummy child element to store the string values.
     * This element is responsible for freeing the values, but carries no
     * other function. */
    if (param->val.type == STR_VALUE)
    {
        t_selelem *child;

        child = _gmx_selelem_create(SEL_CONST);
        _gmx_selelem_set_vtype(child, STR_VALUE);
        child->name = param->name;
        child->flags &= ~SEL_ALLOCVAL;
        child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
        child->v.nr = param->val.nr;
        _gmx_selvalue_setstore(&child->v, param->val.u.s);
        /* Because the child is not group-valued, the u union is not used
         * for anything, so we can abuse it by storing the parameter value
         * as place_child() expects, but this is really ugly... */
        child->u.param = param;
        place_child(root, child, param);
    }

    return TRUE;
}