uint32_t init_tag_versions(ctx_t &ctx)
{
    dfa_t &dfa = ctx.dfa;
    const size_t ntags = dfa.tags.size();

    // all-zero tag configuration must have static number zero
    ctx.dc_tagvertbl.insert_const(TAGVER_ZERO);
    DASSERT(ZERO_TAGS == ctx.dc_tagvertbl.insert_const(TAGVER_ZERO));

    // initial tag versions: [1 .. N]
    const tcid_t INITIAL_TAGS = ctx.dc_tagvertbl.insert_succ(1);

    // other versions: [ .. -(N + 1)] and [N + 1 .. ]
    dfa.maxtagver = static_cast<tagver_t>(ntags);

    // final/fallback versions will be assigned on the go
    dfa.finvers = new tagver_t[ntags];
    for (size_t i = 0; i < ntags; ++i) {
        dfa.finvers[i] = fixed(dfa.tags[i]) ? TAGVER_ZERO : ++dfa.maxtagver;
    }

    // mark tags with history (initial and final)
    for (size_t i = 0; i < ntags; ++i) {
        if (history(dfa.tags[i])) {
            tagver_t v = static_cast<tagver_t>(i) + 1, f = dfa.finvers[i];
            if (f != TAGVER_ZERO) {
                dfa.mtagvers.insert(f);
            }
            dfa.mtagvers.insert(v);
        }
    }

    return INITIAL_TAGS;
}
uint32_t init_tag_versions(ctx_t &ctx)
{
    dfa_t &dfa = ctx.dfa;
    const size_t ntags = dfa.tags.size();

     
    ctx.dc_tagvertbl.insert_const(TAGVER_ZERO);
    DASSERT(ZERO_TAGS == ctx.dc_tagvertbl.insert_const(TAGVER_ZERO));

     
    const tcid_t INITIAL_TAGS = ctx.dc_tagvertbl.insert_succ(1);

     
    dfa.maxtagver = static_cast<tagver_t>(ntags);

     
    dfa.finvers = new tagver_t[ntags];
    for (size_t i = 0; i < ntags; ++i) {
        dfa.finvers[i] = fixed(dfa.tags[i]) ? TAGVER_ZERO : ++dfa.maxtagver;
    }

     
    for (size_t i = 0; i < ntags; ++i) {
        if (history(dfa.tags[i])) {
            tagver_t v = static_cast<tagver_t>(i) + 1, f = dfa.finvers[i];
            if (f != TAGVER_ZERO) {
                dfa.mtagvers.insert(f);
            }
            dfa.mtagvers.insert(v);
        }
    }

    return INITIAL_TAGS;
}