item.cc

来自「This is a resource based on j2me embedde」· CC 代码 · 共 1,241 行 · 第 1/2 页

CC
1,241
字号
	rulelist_iterator	rl_i;	rule *			r;	item		i;	item		cookie_max;	item_cost *		item_costset_set;	int			changed; // Boolean	unsigned		sum_cost;	int			n_instances;	// allocate a item_costset array: fill it with absent elements.	cookie_max = ptp->n()-1;	item_costset_set = allocate_item_costset_array( ptp->n() );	/*	 * start the item_costset_set with all items in which the symbol	 * appears on the rhs.	 */	rl_i = symp->rhs();	n_instances = 0;	while( (r = rl_i.next() ) != 0 ){		n_instances +=		    find_instance( item_costset_set, symp, r, ptp, 0 );	}	if ( n_instances == 0 ){		/*		 * this is very boring: there is nothin in the core		 * set. Give back the storage. Return smaller,		 * empty sets.		 */		free_item_costset_space( item_costset_set );		if ( core_set_p != 0 ){			*core_set_p = item_costset( ptp, 0 );		}		return item_costset( ptp, 0 );	}	if ( core_set_p != 0 ){		item_cost * core_p = allocate_item_costset_space( ptp->n());		memcpy(core_p, item_costset_set, ptp->n()*sizeof( item_cost ));		*core_set_p = item_costset( ptp, core_p );	}	changed = 1;	while( changed ){		changed = 0;		/*		 * for every item in the item_costset_set corresponding		 * to a fullmatch of a rule, r,		 * add to the set all items where r's lhs appear		 * in the (new) item's rhs. Cost is cost of matching r		 * plus r's cost.		 * Of course, consider that the set is changed only		 * if (a) the new item wasn't in the set, or		 * (b) if it was but at greater cost.		 */		for ( i = 0; i <= cookie_max; i++ ){			if (item_costset_set[i] != item_cost_none			    && ptp->item_subpart(i)==item_table::fullmatch){				r = ptp->item_rule(i);				sum_cost = item_costset_set[i]+r->principle_cost();				assert( sum_cost <= item_cost_max );				symp = r->lhs();				rl_i = symp->rhs();				while( (r = rl_i.next() ) != 0 ){					changed += find_instance(						item_costset_set,						symp,						r,						ptp,						sum_cost );				}			}		}	}	return item_costset( ptp, item_costset_set );}/* * Manipulate item_costsets: * first: add a new item with cost to a item_costset. */intitem_costset::cost_add( item cook, item_cost c ){	if ( c == item_cost_none )		return 0; // not the best move.	if (item_costset_p == 0 ){		// instantiate it.		item_costset_p = allocate_item_costset_array( item_costset_table->n() );	}	assert( cook < item_costset_table->n() );	if ( item_costset_p[cook] == item_cost_none	||   item_costset_p[cook] > c ){		item_costset_p[cook] = c;		return 1;	} else {		return 0;	}}/* * cost_bias: add a constant +/- item_cost c to the cost of * every item in the set. Absent items, and ininstantiated sets * are uneffected. */void item_costset::cost_bias( int c ){	item i, cookie_max = item_costset_table->n()-1;	item_cost * cp;	if ( c == 0 )		return;	if (item_costset_p == 0 )		return;	for( i = 0, cp = item_costset_p ; i <= cookie_max ; i++, cp++ ){		if ( *cp != item_cost_none ){			*cp += c;		}	}}/* * normalize: find the least item_cost, and subtract it from the * cost of all present items. Works in place. */void item_costset::normalize(){	unsigned ncosts;	int lowcost = item_cost_none;	register unsigned i;	register item_cost * cp;	register int v;	ncosts = item_costset_table->n();	cp = item_costset_p;	if ( cp == 0 )		return;	for( i = 0; i < ncosts ; i++ ){		v = cp[i];		if ( v < lowcost ){			lowcost = v;		}	}	if ( lowcost != item_cost_none )		cost_bias( -lowcost );}/* * Union together two item_costsets, with cost bias */voiditem_costset::cost_union( const item_costset & other, item_cost bias ){	unsigned i, maxp1;	unsigned sumcost;	int	is_it_empty;	if ( other.item_costset_p == 0 ){		// other set empty. Nothing to do.		return;	}	if (item_costset_p == 0 ){		// instantiate it.		item_costset_p = allocate_item_costset_array( item_costset_table->n() );	}	is_it_empty = 1;	assert( bias <= item_cost_max );	maxp1 = item_costset_table->n();	for ( i = 0; i < maxp1; i++){		if ( (sumcost=other.item_costset_p[i]) != item_cost_none ){				sumcost += bias;			if ( item_costset_p[i] == item_cost_none			||   item_costset_p[i] > sumcost ){				item_costset_p[i] = sumcost;			}			is_it_empty = 0;		} else if (item_costset_p[i] != item_cost_none){			is_it_empty = 0;		}	}	if (is_it_empty!=0){		/*		 * its an empty set.		 * deallocate storage.		 */		free_item_costset_space( item_costset_p );		item_costset_p = 0;	}	return;}/* * Intersect two item_costsets, with cost bias */voiditem_costset::cost_intersect( const item_costset & other, item_cost bias ){	unsigned i, maxp1;	unsigned sumcost;	int is_it_empty;	if (item_costset_p == 0 ){		// this set empty. Intersection is empty.		return;	}	assert( bias <= item_cost_max );	maxp1 = item_costset_table->n();	if ( other.item_costset_p == 0 ){		// other set empty. Intersection is empty.		free_item_costset_space( item_costset_p );		item_costset_p = 0;		return;	}	// away we go	is_it_empty = 1;	for ( i = 0; i < maxp1; i++){		if ( (sumcost=other.item_costset_p[i]) == item_cost_none ){				// not in other set: not in intersection.			item_costset_p[i] = item_cost_none;		} else {			sumcost += bias;			if ( item_costset_p[i] != item_cost_none ){				item_costset_p[i] += sumcost;				is_it_empty = 0;			}		}	}	if (is_it_empty != 0 ){		/*		 * empty result.		 */		free_item_costset_space( item_costset_p );		item_costset_p = 0;	}	return;}intitem_costset::n()const{	// count items present in item_costset	unsigned i, maxp1;	int nmembers;	if (item_costset_p == 0 ){		// empty set		return 0;	} else {		nmembers = 0;		maxp1 = item_costset_table->n();		for( i = 0; i < maxp1; i++ )			if ( item_costset_p[i] != item_cost_none )				nmembers += 1;		return nmembers;	}}/* * A cheaper test if all you need to know is existance: *     1=> empty set *     0=> non empty set */intitem_costset::private_is_empty() const{	unsigned i, maxp1;	if (item_costset_p != 0 ){		maxp1 = item_costset_table->n();		for( i = 0; i < maxp1; i++ )			if ( item_costset_p[i] != item_cost_none )				return 0;	}	return 1;}item_costsetitem_costset::copy()const{	item_costset result( item_costset_table );	unsigned ncosts;	if (item_costset_p == 0 ){		// empty set		return result;	} else {		// allocate array. Bcopy.		ncosts = item_costset_table->n();		result.item_costset_p = allocate_item_costset_space( ncosts );		memcpy(result.item_costset_p, item_costset_p, ncosts*sizeof(item_cost));		return result;	}}/*  * For prt == parent_table::leftpart * construct a item_costset of all cookies "b", such that *	item "a" is a member of item_costset l; *	and  "a" is of the form [ x -> alpha s < treeL > beta ; c ] *					for unary symbol s or  *				[ x -> alpha s < treeL > treeR  beta ; c ] *					for binary s *      then "b" is		[ x -> alpha < s treeL > beta; c] *			     or [ x-> alpha <s treeL treeR > beta; c ] *      correspondingly. */item_costsetitem_costset::parent_allmatch(	item_table::subgraph_part prt,	symbol *s ) const{	register item_table *t = item_costset_table;	register item_cost * p;	register item v, vmaxp1;	item vparent;	item_cost c;	item_costset result(t);	p = item_costset_p;	if ( p == 0 ){		// empty set in, empty set out.		return result;	}	vmaxp1 = t->n();	for( v = 0; v < vmaxp1; v++ ){		if ( (c = p[v] ) == item_cost_none ){			// v not in set.			continue;		}		if (t->item_subpart(v) == prt ){			vparent = t->item_parent( v );			if ( t->item_subtree(vparent)->node == s )				result.cost_add( vparent, c );		}	}	return result;}int item_costset_equal( const item_costset &a, const item_costset &b ){	// look for the special cases:	// expanded and unexpanded empty sets.	if ( a.item_costset_p == 0 ){		// "a" is empty.		return ( b.is_empty() );	} else if ( b.item_costset_p == 0 ){		// "b" is empty, and even though "a" is allocated,		// it might be empty anyway.		// this case is unlikely.		return ( a.is_empty() );	}	// else neither is empty.	// do byte-by-byte equality check.	return memcmp( a.item_costset_p, b.item_costset_p, a.item_costset_table->n()*sizeof(item_cost) ) == 0;}/* * funky comparison: would this set be equal to the other * if both were normalized. Thus ignoring differences of a  * constant cost bias, as this will wash out after minimization. * This costs lots and lots more than operator==, but if applied * earlier in the state building process, may shortcut other * more expensive operations. */intitem_costset_normalized_equal( const item_costset &a, const item_costset &b ){	// look for the special cases:	// expanded and unexpanded empty sets.	// (starts like item_costset_equal, doesn't it?)	if ( a.item_costset_p == 0 ){		return ( b.n() == 0 );	} else if ( b.item_costset_p == 0 ){		// other is empty		return ( a.n() == 0 );	}	register unsigned i, maxp1;	register int  bias = item_cost_none;	register item_cost this_v, other_v;	register item_cost * this_p, * other_p;	maxp1 = a.item_costset_table->n();	this_p = a.item_costset_p;	other_p = b.item_costset_p;	// first, compare as much of the set as possible	// for simple emptyness.	for (i=0; i<maxp1; i++ ){		if (this_p[i] != item_cost_none )			break;		if (other_p[i] != item_cost_none )			break;	}	if ( i >= maxp1 ){		// both entirely empty		return 1;	}	// found the first case where one or the other is not missing.	this_v = this_p[i];	other_v = other_p[i];	if ( this_v == item_cost_none || other_v == item_cost_none ){		// one not missing, but one is missing.		return 0;	}	// neither missing. Compute the bias only once.	bias = this_v - other_v;	// continue comparison more carefully.	for (i=i+1; i<maxp1; i++ ){		this_v = this_p[i];		other_v = other_p[i];		if ( this_v == item_cost_none ){			if ( other_v == item_cost_none ){				// element i is missing from both				continue;			} else {				// element i is missing from this				// but in other: not equal				return 0;			}		} else if ( other_v == item_cost_none ) {			// element i is missing from other			return 0;		} else {			// make sure cost difference is same.			if ( this_v - other_v != bias )					return 0;		}	}	// end of for loop: found no unequal elements	return 1;}// how to get rid of one:// only deallocates the allocated array:// does not deallocate the item_costset struct itself.voiditem_costset::destruct(){	if ( item_costset_p != 0 ){		free_item_costset_space( item_costset_p);		item_costset_p = 0;	}}/* * Operations on sparse item cost sets. These are used in  * "compute_parental_matchsets", where even the non-empty sets have, * generally, < 3 things in them. These are lots smaller, and can * easily support the operational subset required. */intsparse_item_costset::cost_add( item p, item_cost c ){	register unsigned	i;	register item_pair *	pp;	assert( p < item_costset_table->n() );	if ( c == item_cost_none )		return 0; // very dopy thing to do.	if (max_pairs <= SPARSE_ITEM_COSTSET_ARRAY_SIZE)		pp = stuff;	else		pp = pair_array;	/*	 * iterate through table, looking for match.	 */	for ( i = 0 ; i < n_pairs ; i ++ ){		if ( pp[i].ino == p ){			// found			if ( c < pp[i].c ){				pp[i].c = c;				return 1;			} else				return 0; // was already there cheaper.		}	}	/*	 * didn't find. add at end.	 */	if ( max_pairs <= SPARSE_ITEM_COSTSET_ARRAY_SIZE ){		// allocate at end of builtin array if it fits...		max_pairs = SPARSE_ITEM_COSTSET_ARRAY_SIZE;		if ( n_pairs < SPARSE_ITEM_COSTSET_ARRAY_SIZE ){			// will fit			pp = &stuff[n_pairs];		} else { 			// won't fit. Will allocate and copy.			max_pairs *=2;			pair_array = (item_pair *) malloc(			    max_pairs*sizeof(item_pair) );			DID_SPARSEALLOC( max_pairs );			assert( pair_array != 0 );			memcpy(pair_array, stuff, (SPARSE_ITEM_COSTSET_ARRAY_SIZE)*sizeof(item_pair) );			pp = &pair_array[n_pairs];		}	} else {		// allocate at end of allocated array if it fits...		if ( n_pairs >= max_pairs ){			// must reallocate.			max_pairs *=2;			pair_array = (item_pair *) realloc(			    (char*)pair_array, max_pairs*sizeof(item_pair) );			DID_SPARSE_REALLOC( max_pairs );			assert( pair_array != 0 );		}		pp = &pair_array[n_pairs];	} 	pp->ino = p;	pp->c = c;	n_pairs +=1;	return 1;}item_costsetsparse_item_costset::get() const{	item_costset v( item_costset_table ); // construct an empty one.	register unsigned		i;	register const item_pair *	pp;	if (max_pairs <= SPARSE_ITEM_COSTSET_ARRAY_SIZE)		pp = stuff;	else		pp = pair_array;	for ( i = 0 ; i < n_pairs ; i += 1 ){		v.cost_add( pp[i].ino, pp[i].c );	}	return v;}voidsparse_item_costset::private_destruct(){	if ( max_pairs > SPARSE_ITEM_COSTSET_ARRAY_SIZE ){		// free allocated memory		free( (char *)pair_array );		DID_SPARSEFREE( max_pairs );	}	n_pairs = 0;	max_pairs = 0;}voidsparse_item_costset::print( FILE * out ) const{	unsigned i;	for( i = 0; i <= n_pairs; i++ ){		fputs( "\t[ ", out);		item_costset_table->item_print( pair_array[i].ino, out );		fprintf( out, " ; %d ]\n", pair_array[i].c );	}}/****************************************************************************/voidclose_symbols(){	symbollist_iterator sl_i = all_symbols;	symbol * sp;	item_costset core_set;	/*	 * compute item_costset for nonterminals. And while we're at it,	 * compute itemsets for leaf terminals. Others should have	 * empty item_costset sets.	 */	while( ( sp = sl_i.next() ) != 0 ){		switch( sp->type() ){		case symbol::binaryop:		case symbol::unaryop:			// build an empty one.			sp->add_closure( item_costset( &all_items ) );			break;		case symbol::terminal:		case symbol::nonterminal:			sp->add_closure(			    item_costset::compute_item_costset( sp, &all_items, &core_set ) );			sp->add_core_set( core_set );		}	}}voidprint_closures( int print_core_sets ){	symbollist_iterator sl_i = all_symbols;	symbol *s;	puts("\nCLOSURE SETS");	while( (s=sl_i.next() ) != 0 ){		printf("%s: {\n", s->name());		s->get_closure().print(stdout);		puts("}");		if (print_core_sets ){			printf("core of %s: {\n", s->name());			s->get_core_set().print(stdout);			puts("}");		}	}}voidprint_item_costset( const item_costset * cp ){	cp->print( stdout );	fflush(stdout);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?