예제 #1
0
/*! \brief
 * Converts a floating point value to integer.
 *
 * \param[in]     n      Number of values in the \p val->u array.
 * \param[in,out] val    Value to convert.
 * \param[in]     cmpt   Comparison operator type.
 * \param[in]     bRight true if \p val appears on the right hand size of
 *   \p cmpt.
 * \returns       0 on success, EINVAL on error.
 *
 * The values are rounded such that the same comparison operator can be used.
 */
static void
convert_real_int(int n, t_compare_value *val, e_comparison_t cmpt, bool bRight)
{
    int   i;
    int  *iv;

    if (!bRight)
    {
        cmpt = reverse_comparison_type(cmpt);
    }
    snew(iv, n);
    /* Round according to the comparison type */
    for (i = 0; i < n; ++i)
    {
        switch (cmpt)
        {
            case CMP_LESS:
            case CMP_GEQ:
                iv[i] = static_cast<int>(std::ceil(val->r[i]));
                break;
            case CMP_GTR:
            case CMP_LEQ:
                iv[i] = static_cast<int>(std::floor(val->r[i]));
                break;
            case CMP_EQUAL:
            case CMP_NEQ:
                sfree(iv);
                /* TODO: Implement, although it isn't typically very useful.
                 * Implementation is only a matter of proper initialization,
                 * the evaluation function can already handle this case with
                 * proper preparations. */
                GMX_THROW(gmx::NotImplementedError("Equality comparison between dynamic integer and static real expressions not implemented"));
            case CMP_INVALID: /* Should not be reached */
                sfree(iv);
                GMX_THROW(gmx::InternalError("Invalid comparison type"));
        }
    }
    /* Free the previous value if one is present. */
    sfree(val->i);
    val->i      = iv;
    val->flags &= ~CMP_REALVAL;
    val->flags |= CMP_ALLOCINT;
}
예제 #2
0
/* \brief
 * Converts a floating point value to integer.
 *
 * \param[in]     n      Number of values in the \p val->u array.
 * \param[in,out] val    Value to convert.
 * \param[in]     cmpt   Comparison operator type.
 * \param[in]     bRight TRUE if \p val appears on the right hand size of
 *   \p cmpt.
 * \returns       0 on success, EINVAL on error.
 *
 * The values are rounded such that the same comparison operator can be used.
 */
static int
convert_real_int(int n, t_compare_value *val, e_comparison_t cmpt, gmx_bool bRight)
{
    int   i;
    int  *iv;

    if (!bRight)
    {
        cmpt = reverse_comparison_type(cmpt);
    }
    snew(iv, n);
    /* Round according to the comparison type */
    for (i = 0; i < n; ++i)
    {
        switch (cmpt)
        {
            case CMP_LESS:
            case CMP_GEQ:
                iv[i] = (int)ceil(val->r[i]);
                break;
            case CMP_GTR:
            case CMP_LEQ:
                iv[i] = (int)floor(val->r[i]);
                break;
            case CMP_EQUAL:
            case CMP_NEQ:
                fprintf(stderr, "comparing equality an integer expression and a real value\n");
                sfree(iv);
                return EINVAL;
            case CMP_INVALID: /* Should not be reached */
                gmx_bug("internal error");
                sfree(iv);
                return EINVAL;
        }
    }
    /* Free the previous value if one is present. */
    sfree(val->i);
    val->i      = iv;
    val->flags &= ~CMP_REALVAL;
    val->flags |= CMP_ALLOCINT;
    return 0;
}
예제 #3
0
static void
init_compare(t_topology * /* top */, int /* npar */, gmx_ana_selparam_t *param, void *data)
{
    t_methoddata_compare *d = (t_methoddata_compare *)data;
    int                   n1, n2;

    /* Store the values */
    n1 = init_comparison_value(&d->left, &param[0]);
    n2 = init_comparison_value(&d->right, &param[3]);
    /* Store the comparison type */
    d->cmpt = comparison_type(d->cmpop);
    if (d->cmpt == CMP_INVALID)
    {
        GMX_THROW(gmx::InternalError("Invalid comparison type"));
    }
    /* Convert the values to the same type */
    /* TODO: Currently, there are no dynamic integer-valued selection methods,
     * which means that only the branches with convert_int_real() will ever be
     * taken. It should be considered whether it is necessary to support these
     * other cases at all.
     */
    if ((d->left.flags & CMP_REALVAL) && !(d->right.flags & CMP_REALVAL))
    {
        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
        {
            /* Nothing can be done */
        }
        else if (!(d->right.flags & CMP_DYNAMICVAL))
        {
            convert_int_real(n2, &d->right);
        }
        else /* d->left is static */
        {
            convert_real_int(n1, &d->left, d->cmpt, false);
        }
    }
    else if (!(d->left.flags & CMP_REALVAL) && (d->right.flags & CMP_REALVAL))
    {
        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
        {
            /* Reverse the sides to place the integer on the right */
            int    flags;
            d->left.r      = d->right.r;
            d->right.r     = NULL;
            d->right.i     = d->left.i;
            d->left.i      = NULL;
            flags          = d->left.flags;
            d->left.flags  = d->right.flags;
            d->right.flags = flags;
            d->cmpt        = reverse_comparison_type(d->cmpt);
        }
        else if (!(d->left.flags & CMP_DYNAMICVAL))
        {
            convert_int_real(n1, &d->left);
        }
        else /* d->right is static */
        {
            convert_real_int(n2, &d->right, d->cmpt, true);
        }
    }
}
예제 #4
0
/*!
 * \param[in] top   Not used.
 * \param[in] npar  Not used (should be 5).
 * \param[in] param Method parameters (should point to \ref smparams_compare).
 * \param[in] data  Should point to a \c t_methoddata_compare.
 * \returns   0 if the input data is valid, -1 on error.
 */
static int
init_compare(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
{
    t_methoddata_compare *d = (t_methoddata_compare *)data;
    int                   n1, n2;

    /* Store the values */
    n1 = init_comparison_value(&d->left, &param[0]);
    n2 = init_comparison_value(&d->right, &param[3]);
    if (n1 == 0 || n2 == 0)
    {
        gmx_bug("one of the values for comparison missing");
        return -1;
    }
    /* Store the comparison type */
    d->cmpt = comparison_type(d->cmpop);
    if (d->cmpt == CMP_INVALID)
    {
        gmx_bug("invalid comparison type");
        return -1;
    }
    /* Convert the values to the same type */
    if ((d->left.flags & CMP_REALVAL) && !(d->right.flags & CMP_REALVAL))
    {
        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
        {
            /* Nothing can be done */
        }
        else if (!(d->right.flags & CMP_DYNAMICVAL))
        {
            convert_int_real(n2, &d->right);
        }
        else /* d->left is static */
        {
            if (convert_real_int(n1, &d->left, d->cmpt, FALSE))
            {
                return -1;
            }
        }
    }
    else if (!(d->left.flags & CMP_REALVAL) && (d->right.flags & CMP_REALVAL))
    {
        if (d->left.flags & d->right.flags & CMP_DYNAMICVAL)
        {
            /* Reverse the sides to place the integer on the right */
            int    flags;
            d->left.r  = d->right.r;
            d->right.r = NULL;
            d->right.i = d->left.i;
            d->left.i  = NULL;
            flags          = d->left.flags;
            d->left.flags  = d->right.flags;
            d->right.flags = flags;
            d->cmpt = reverse_comparison_type(d->cmpt);
        }
        else if (!(d->left.flags & CMP_DYNAMICVAL))
        {
            convert_int_real(n1, &d->left);
        }
        else /* d->right is static */
        {
            if (convert_real_int(n2, &d->right, d->cmpt, TRUE))
            {
                return -1;
            }
        }
    }
    return 0;
}