Exemplo n.º 1
0
/**
 * Pop a previous match state back into the match
 * @param m the match state
 * @return 1 if the pop was possible else 0
 */
int match_pop( match *m )
{
    if ( m->queue == NULL )
        return 0;
    else
    {
        match *n = match_deepest_queued( m );
        match_state *ms = n->queue;
        n->queue = match_state_next( ms );
        n->start = match_state_start(ms);
        n->end = match_state_end(ms);
        n->prev = match_state_prev(ms);
        n->maximal = match_state_maximal(ms);
        match_state_loc( ms, &n->loc );
        n->text_off = match_state_text_off( ms );
        n->len = match_state_len( ms );
        if ( n->bs != NULL )
        {
            bitset_dispose( n->bs );
            n->bs = NULL;
        }
        if ( match_state_bs(ms) != NULL )
            n->bs = bitset_clone( match_state_bs(ms) );
        if ( n->prev_bs != NULL )
        {
            bitset_dispose( n->prev_bs );
            n->prev_bs = NULL;
        }
        if ( match_state_prev_bs(ms) != NULL )
            n->prev_bs = bitset_clone( match_state_prev_bs(ms) );
        n->freq = 0;
        match_state_dispose( ms );
        return 1;
    }
}
Exemplo n.º 2
0
/**
 * Make an exact deep copy of a match
 * @param mt the match to copy
 * @param log the log to report errors to
 * @return a copy of mt or NULL on failure
 */
match *match_copy( match *mt, plugin_log *log )
{
    match *mt2 = calloc( 1, sizeof(match) );
    if ( mt2 != NULL )
    {
        mt2->start = mt->start;
        mt2->end = mt->end;
        mt2->prev = mt->prev;
        if ( mt->prev_bs != NULL )
            mt2->prev_bs = bitset_clone( mt->prev_bs );
        if ( mt->bs != NULL )
            mt2->bs = bitset_clone( mt->bs );
        mt2->st_off = mt->st_off;
        //mt2->text_off = 0;
        mt2->text_off = mt->text_off;
        mt2->len = mt->len;
        mt2->maximal = mt->maximal;
        mt2->freq = mt->freq;
        mt2->cards = mt->cards;
        mt2->st = mt->st;
        if ( mt->next != NULL )
            mt2->next = match_copy( mt->next, log );
        if ( mt->queue != NULL )
            mt2->queue = match_state_copy(mt->queue,log);
        mt2->loc = mt->loc;
    }
    else
        plugin_log_add( log, "match: failed to duplicate match object\n");
    return mt2;
}
Exemplo n.º 3
0
/**
 * Add a card AFTER a node. c->right will be displaced by one 
 * card. Although this will increase the node's overhang, the increase
 * is exactly that of the displaced card's versions, which will reattach 
 * via the overhang, instead of the forced rule.
 * @param c the incoming pair of a node
 * @param after the card to add into lp's node. must intersect with lp.
 * @param verify if 1 then check that the resulting node is OK
 * @return 1 if the new node is a bona fide node
 */
int card_add_at_node( card *c, card *after, int verify )
{
    int res = 0;
    int dispose = 0;
    bitset *bs1 = pair_versions(c->p);
    if ( pair_is_hint(card_pair(c->right)) ) 
    {
        bs1 = bitset_clone(bs1);
        if ( bs1 != NULL )
        {
            c = c->right;
            dispose = 1;
            // bs1 is the amalgam of leading pair+hint
            bitset_or( bs1, pair_versions(c->p) );
        }
    }
    if ( bs1 != NULL )
    {
        after->right = c->right;
        after->left = c;
        if ( c->right != NULL )
            c->right->left = after;
        c->right = after;
        res = (verify)?bitset_intersects(bs1,pair_versions(after->p)):1;
        if ( dispose )
            bitset_dispose( bs1 );
    }
    return res;
}
Exemplo n.º 4
0
/* Make an estimate of the total cost of determining the given condition
 * with the given set of still-needed variables.  Return true on success,
 * and then also set soln_mincost with the cost of running all generators
 * and the condition, and set soln_generators (which must be allocated)
 * to the set of generators used to get to this point.
 *
 * This cost estimator assumes that vartab_analyse_cheapest_generators()
 * has already been run, and it only succeeds when all varsneeded have
 * a generator assigned to them (which should be caught out by that prior
 * phase, but it nonetheless returns an OK as a boolean).
 *
 * The soln_mincost represents the minimum cost estimation for setting up
 * all the variables.  The soln_generators provides the generators that
 * need to run before the varsneeded have been generated, ordered by
 * ascending weight.  The soln_generator_count provides the number of
 * entries filled into this table; the assumption made is that at least
 * as many entries are available as the number of elements in varsneeded.
 * Room up to this point may be overwritten by this routine, even if this
 * exceeds the impression given by a lower soln_generator_count.
 */
bool cnd_estimate_total_cost (struct cndtab *cctab, cndnum_t cndnum,
				bitset_t *varsneeded,
				float *soln_mincost,
				struct gentab *gentab,
				unsigned int *soln_generator_count,
				gennum_t soln_generators []) {
	bitset_iter_t v;
	bitset_t *vneeded;
	*soln_generator_count = 0;
	//
	// Find the cheapest generator for each of the varsneeded
	bitset_iterator_init (&v, varsneeded);
	while (bitset_iterator_next_one (&v, NULL)) {
		gennum_t unit_gen;
		bitset_t *genvars;
		unsigned int gi = bitset_iterator_bitnum (&v);
		//
		// The first step generates a list with the cheapest generators;
		// this could actually return an ordered _list_ of generators
		// and would cut off the most expensive ones when varsneeded
		// are generated as by-products in other generators.
		// This leads to more accurate estimates, and more efficiency.
		if (!var_get_cheapest_generator (
					vartab_from_type (cctab->vartype),
					gi,
					&unit_gen, NULL)) {
			return false;
		}
		soln_generators [*soln_generator_count++] = unit_gen;
	}
	//
	// Now sort the soln_generators by their weight.
	//
	// This is a sort for optimisation purposes; if it returns an error,
	// then the cause is normally memory shortage, in which case the
	// lost efficiency here is less vital than other things going awry.
	QSORT_R(soln_generators,
			*soln_generator_count,
			sizeof (struct generator *),
			gentab,
			_qsort_gen_cmp_weight);
	//
	// From the sorted soln_generators list, subtract generated variables
	// from varsneeded until all are done.  Cut off the output list at
	// that point by returning a possibly lower soln_generator_count.
	//
	//TODO// Might be able to skip generators that add nothing of interest
	*soln_generator_count = 0;
	*soln_mincost = cnd_get_weight (cctab, cndnum);
	vneeded = bitset_clone (varsneeded);
	while (!bitset_isempty (vneeded)) {
		gennum_t g = soln_generators [*soln_generator_count++];
		*soln_mincost *= gen_get_weight (gentab, g);
		bitset_t *genvars = gen_share_variables (gentab, g);
		bitset_subtract (vneeded, genvars);
	}
	bitset_destroy (vneeded);
	return true;
}
Exemplo n.º 5
0
static void match_push_versions( match *m )
{
    if ( m->prev_bs != NULL )
    {
        bitset_clear( m->prev_bs );
        bitset_or( m->prev_bs, m->bs );
    }
    else
        m->prev_bs = bitset_clone( m->bs );
}
Exemplo n.º 6
0
/**
 * Compute the overlap between the versions of this card and another
 * @param c the current card
 * @param bs the versions of the other card that may overlap those in c
 * @return an allocated set of bits in bs that not in c, or NULL if none
 */
bitset *card_overlap( card *c, bitset *bs )
{
    bitset *overlap = NULL;
    bitset *p_versions = pair_versions( c->p );
    if ( !bitset_equals(bs,p_versions) )
    {
        overlap = bitset_clone( bs );
        bitset_and_not( overlap, p_versions );
        if ( bitset_empty(overlap) )
        {
            bitset_dispose( overlap );
            overlap = NULL;
        }
    }
    return overlap;
}
Exemplo n.º 7
0
/**
 * Create a hint object
 * @param versions the versions to clone
 * @return a finished hint or NULL
 */
hint *hint_create( bitset *versions, vgnode *n )
{
    hint *h = calloc( 1, sizeof(hint) );
    if ( h != NULL )
    {
        h->n = n;
        h->bs = bitset_clone( versions );
        if ( h->bs == NULL )
        {
            hint_dispose( h );
            h = NULL;
        }
    }
    else
        fprintf(stderr,"hint: failed to crate object\n");
    return h;
}
Exemplo n.º 8
0
/* Make an estimate of the total cost of determining the given condition
 * with the given set of still-needed variables.  Return true on success,
 * and then also set soln_mincost with the cost of running all generators
 * and the condition, and set soln_generators (which must be allocated)
 * to the set of generators used to get to this point.
 */
bool DEPRECATED_cnd_estimate_total_cost (struct condition *cc,
				bitset_t *varsneeded,
				float *soln_mincost,
				bitset_t *soln_generators) {
	//
	// First, for all varsneeded, determine their cheapest generator
	//
	struct iter_var_gen ivg;
	ivg.okay = true;
	ivg.vartab = cc->vartab;
	ivg.total_cost = cc->weight;
	ivg.varneed = bitset_clone (varsneeded);
	ivg.generate = soln_generators;
	bitset_empty (ivg.generate);
	bitset_iterate (varsneeded, var_cheap_generator_it, &ivg);
	bitset_destroy (ivg.varneed);
	*soln_mincost = ivg.total_cost;
	return ivg.okay;
}
Exemplo n.º 9
0
/**
 * Complete a single match between the pairs list and the suffixtree
 * @param m the match all ready to go
 * @param text the text of the new version
 * @param v the new version id
 * @param log the log to save errors in
 * @return 1 if the match was at least 1 char long else 0
 */
int match_single( match *m, UChar *text, int v, plugin_log *log, int popped )
{
    UChar c;
    // go to the deepest match if not the first one (as usual)
    while ( m->next != NULL )
        m = m->next;
    pos *loc = &m->loc;
    // preserve popped location in suffix tree
    if ( !popped ) 
    {
        loc->v = suffixtree_root( m->st );
        loc->loc = node_start(loc->v)-1;
        m->maximal = 0;
    }
    do 
    {
        UChar *data = pair_data(card_pair(m->end.current));
        c = data[m->end.pos];
        if ( suffixtree_advance_pos(m->st,loc,c) )
        {
            if ( m->bs == NULL )
                m->bs = bitset_clone( pair_versions(card_pair(m->end.current)) );
            if ( !m->maximal && node_is_leaf(loc->v) )
            {
                m->text_off = m->st_off + node_start(loc->v)-m->len;
                if ( !is_maximal(m,text) )
                    break;
                else
                    m->maximal = 1;
            }
            // we are already matched, so increase length
            m->len++;
            if ( !match_advance(m,loc,v,log) )
                break;
        }
        else
            break;
    }
    while ( 1 );
    return m->maximal;
}