/** * This function tries to resolve the conditions of the graph #n. * It returns 1 if at least one condition was resolved. */ int resolve_conditions_for_one_graph(int n,ConditionList* conditions, Fst2State* states,int* initial_states,U_FILE*ferr) { int modification=0; int matches_E=DOES_NOT_KNOW_IF_E_IS_MATCHED; if (conditions[n]==NULL) { error("NULL internal error in resolve_conditions_for_one_graph for graph %d\n",n); if (ferr != NULL) u_fprintf(ferr,"NULL internal error in resolve_conditions_for_one_graph for graph %d\n",n); return modification; } conditions[n]=resolve_condition_list(conditions[n],states,initial_states,&modification,&matches_E,ferr); if (matches_E==E_IS_MATCHED) { /* If at least one condition was verified */ set_bit_mask(&(states[initial_states[n]]->control),UNCONDITIONAL_E_MATCH); /* We can free the conditions */ free_ConditionList(conditions[n]); conditions[n]=NULL; return 1; } if (conditions[n]==NULL) { /* If the graph has no more condition, then we mark it as unable to match <E> */ set_bit_mask(&(states[initial_states[n]]->control),DOES_NOT_MATCH_E); free_ConditionList(conditions[n]); conditions[n]=NULL; return 1; } return modification; }
/** * Explores the transitions that outgo from the given state. * Returns 1 if a recursion is found; 0 otherwise. */ int explore_state(int state_number,struct list_int* l,Fst2* fst2,int* graphs_matching_E,U_FILE*ferr) { Fst2State s=fst2->states[state_number]; int ret=0; if (s==NULL) return 0; if (is_bit_mask_set(s->control,TMP_LOOP_MARK|VISITED_MARK)) { /* If this state has already been processed */ return 0; } set_bit_mask(&(s->control),TMP_LOOP_MARK|VISITED_MARK); Transition* list=s->transitions; while (list!=NULL) { if (list->tag_number<0) { /* If we have a subgraph call */ if (look_for_recursion(-(list->tag_number),l,fst2,graphs_matching_E,ferr)) { /* If there is a recursion */ return 1; } if (graphs_matching_E[-list->tag_number] && explore_state(list->state_number,l,fst2,graphs_matching_E,ferr)) { /* If the graph matches <E> */ return 1; } } else if (fst2->tags[list->tag_number]->control==1) { /* If we have a transition that can match <E> */ if (explore_state(list->state_number,l,fst2,graphs_matching_E,ferr)) { return 1; } } list=list->next; } unset_bit_mask(&(s->control),TMP_LOOP_MARK); return ret; }
/** * Returns 1 if the given state has already been visited; 0 otherwise. */ int look_for_E_loop_in_state(int state_number,Fst2* fst2,int* graphs_matching_E) { Transition* l; Fst2State e=fst2->states[state_number]; if (is_bit_mask_set(e->control,TMP_LOOP_MARK)) { /* If we have already visited this state */ unset_bit_mask(&(e->control),TMP_LOOP_MARK); return 1; } set_bit_mask(&(e->control),TMP_LOOP_MARK); l=e->transitions; while (l!=NULL) { if (l->tag_number<0) { /* If we have a graph call */ if (graphs_matching_E[-l->tag_number]) { /* And if we can cross it because it matches <E> */ if (look_for_E_loop_in_state(l->state_number,fst2,graphs_matching_E)) { /* And if we have reached the current state via an <E> loop */ unset_bit_mask(&(e->control),TMP_LOOP_MARK); return 1; } } } else if (fst2->tags[l->tag_number]->control==1) { /* If we have a tag that can match <E> */ if (look_for_E_loop_in_state(l->state_number,fst2,graphs_matching_E)) { /* And if we have reached the current state via an <E> loop */ unset_bit_mask(&(e->control),TMP_LOOP_MARK); return 1; } } l=l->next; } unset_bit_mask(&(e->control),TMP_LOOP_MARK); return 0; }
/** * This function looks for each graph if it can resolve a condition. * * It returns a non zero value if some conditions have been resolved, * even just one; 0 otherwise. */ int resolve_conditions(ConditionList* conditions,int n_graphs, Fst2State* states,int* initial_states,U_FILE*ferr) { int modification=0; for (int i=1;i<n_graphs+1;i++) { if (!is_bit_mask_set(states[initial_states[i]]->control, UNCONDITIONAL_E_MATCH|DOES_NOT_MATCH_E)) { /* If we don't already know the status of the current graph */ if (!is_bit_mask_set(states[initial_states[i]]->control,CONDITIONAL_E_MATCH)) { /* If there is no conditionnal match, then we say that it does * not match <E> */ set_bit_mask(&(states[initial_states[i]]->control),DOES_NOT_MATCH_E); modification++; } else { /* Otherwise, we try to solve the conditions of the graph */ modification=modification+resolve_conditions_for_one_graph(i,conditions,states,initial_states,ferr); } } } return modification; }
/** * Returns a control byte that represents the characteristics of the given token. */ unsigned char get_control_byte(const unichar* token,const Alphabet* alph,struct string_hash* err,TokenizationPolicy tokenization_policy) { int i; int tmp; unsigned char c=0; if (token==NULL || token[0]=='\0') { fatal_error("NULL or empty token in get_control_byte\n"); } /* We consider that a token starting with a letter is a word */ if (is_letter(token[0],alph)) { set_bit_mask(&c,MOT_TOKEN_BIT_MASK); /* If a token is a word, we check if it is in the 'err' word list * in order to answer the question <!DIC>. We perform this test in order * to avoid taking "priori" as an unknown word if the compound "a priori" * is in the text. */ if (err!=NULL && get_value_index(token,err,DONT_INSERT)!=-1) { set_bit_mask(&c,NOT_DIC_TOKEN_BIT_MASK); } if (is_upper(token[0],alph)) { set_bit_mask(&c,PRE_TOKEN_BIT_MASK); i=0; tmp=0; while (token[i]!='\0') { if (is_lower(token[i],alph)) { tmp=1; break; } i++; } if (!tmp) { set_bit_mask(&c,MAJ_TOKEN_BIT_MASK); } return c; } i=0; tmp=0; while (token[i]!='\0') { if (is_upper(token[i],alph)) { tmp=1; break; } i++; } if (!tmp) { set_bit_mask(&c,MIN_TOKEN_BIT_MASK); } return c; } /* If the token doesn't start with a letter, we start with * checking if it is a tag like {today,.ADV} */ if (token[0]=='{' && u_strcmp(token,"{S}") && u_strcmp(token,"{STOP}")) { /* Anyway, such a tag is classed as verifying <MOT> and <DIC> */ set_bit_mask(&c,MOT_TOKEN_BIT_MASK|DIC_TOKEN_BIT_MASK|TDIC_TOKEN_BIT_MASK); struct dela_entry* temp=tokenize_tag_token(token); if (is_upper(temp->inflected[0],alph)) { set_bit_mask(&c,PRE_TOKEN_BIT_MASK); i=0; tmp=0; while (temp->inflected[i]!='\0') { if (is_letter(temp->inflected[i],alph) && is_lower(temp->inflected[i],alph)) { tmp=1; break; } i++; } if (!tmp) { set_bit_mask(&c,MAJ_TOKEN_BIT_MASK); } } else { i=0; tmp=0; while (temp->inflected[i]!='\0') { if (is_letter(temp->inflected[i],alph) && is_upper(temp->inflected[i],alph)) { tmp=1; break; } i++; } if (!tmp) { set_bit_mask(&c,MIN_TOKEN_BIT_MASK); } } if (!is_a_simple_word(temp->inflected,tokenization_policy,alph)) { /* If the tag is a compound word, we say that it verifies the <CDIC> pattern */ set_bit_mask(&c,CDIC_TOKEN_BIT_MASK); } free_dela_entry(temp); } return c; }
/** * This function analyses the inputs of all the tags of the given .fst2 in * order to determine their kind. 'tokens' contains all the text tokens. * After the execution of the function, 'number_of_patterns' will contain * the number of patterns found in the grammar, and 'is_DIC'/'is_CDIC'/'is_SDIC'/'is_TDIC' * will contain 1 if the tag 'DIC'/'CDIC'/'SDIC'/'TDIC' has been found. See * the comment below about the special case for '<!DIC>'. */ void process_tags(int *number_of_patterns, struct string_hash* semantic_codes, int *is_DIC,int *is_CDIC, int *is_SDIC,struct locate_parameters* parameters, Abstract_allocator prv_alloc) { (*number_of_patterns)=0; (*is_DIC)=0; (*is_CDIC)=0; (*is_SDIC)=0; Fst2* fst2=parameters->fst2; struct string_hash* tokens=parameters->tokens; Fst2Tag* tag=fst2->tags; /* We get the number of the SPACE token */ unichar t[2]; t[0]=' '; t[1]='\0'; parameters->SPACE=get_value_index(t,tokens,DONT_INSERT); /* Then, we test all the tags */ for (int i=0;i<fst2->number_of_tags;i++) { if (tag[i]->type!=UNDEFINED_TAG) { /* We don't need to process again things like variables and contexts * that have already been processed at the time of loading the fst2 */ continue; } int length=u_strlen(tag[i]->input); if (!u_strcmp(tag[i]->input,"#")) { /* If we have a #, we must check if it is the meta one that * forbids space or the "#" token */ if (is_bit_mask_set(tag[i]->control,RESPECT_CASE_TAG_BIT_MASK)) { /* If the case respect bit is set to 1, then we have the "#" token */ tag[i]->type=PATTERN_TAG; tag[i]->pattern=build_token_pattern(tag[i]->input,prv_alloc); } else { /* If we have the meta # */ tag[i]->type=META_TAG; tag[i]->meta=META_SHARP; } } else if (!u_strcmp(tag[i]->input,"<E>")) { /* If we have a transition tagged by the empty word epsilon */ tag[i]->type=META_TAG; tag[i]->meta=META_EPSILON; } else { int token_number=get_value_index(tag[i]->input,tokens,DONT_INSERT); if (token_number!=-1) { /* If the input is an existing token */ if (token_number==parameters->SPACE) { /* If it is a space */ tag[i]->type=META_TAG; tag[i]->meta=META_SPACE; } else { /* If it is a normal token */ tag[i]->type=PATTERN_TAG; tag[i]->pattern=build_token_pattern(tag[i]->input,prv_alloc); } } else { /* This input is not an existing token. Two cases can happen: * 1) metas like <!MOT> or patterns like <V:K> * 2) a word that is not in the text tokens */ if (tag[i]->input[0]!='<' || tag[i]->input[length-1]!='>') { /* If we are in case 2, it may not be an error. For instance, * if the tag contains "foo" and if it is a tag that allows * case variations, we could match "FOO" if this token is in the * text. */ tag[i]->type=PATTERN_TAG; tag[i]->pattern=build_token_pattern(tag[i]->input,prv_alloc); } else { /* If we have something of the form <...>, we must test first if it is * or not a negative tag like <!XXX> */ int negative_tag=(tag[i]->input[1]=='!')?1:0; if (negative_tag) { set_bit_mask(&(tag[i]->control),NEGATION_TAG_BIT_MASK); } /* Then, we must test if we have or not a meta. To do that, we * extract the content without < > and ! if any.*/ unichar* content=u_strdup(&(tag[i]->input[1+negative_tag]),length-2-negative_tag,prv_alloc); /* And we test all the possible metas */ if (!u_strcmp(content,"MOT")) { tag[i]->type=META_TAG; tag[i]->meta=META_MOT; } else if (!u_strcmp(content,"DIC")) { tag[i]->type=META_TAG; tag[i]->meta=META_DIC; if (!negative_tag) { /* We mark that the DIC tag has been found, but only * if it is not the negative one (<!DIC>). We do this * because things matched by <DIC> will be taken from * the 'dlf' and 'dlc' files, whereas things matched by <!DIC> * will be taken from the 'err' file. Such a trick is necessary * if we don't want 'priori' to be taken as an unknown word since * it is part of the compound word 'a priori' */ (*is_DIC)=1; } } else if (!u_strcmp(content,"CDIC")) { tag[i]->type=META_TAG; tag[i]->meta=META_CDIC; (*is_CDIC)=1; } else if (!u_strcmp(content,"SDIC")) { tag[i]->type=META_TAG; tag[i]->meta=META_SDIC; (*is_SDIC)=1; } else if (!u_strcmp(content,"TDIC")) { tag[i]->type=META_TAG; tag[i]->meta=META_TDIC; } else if (!u_strcmp(content,"MAJ")) { tag[i]->type=META_TAG; tag[i]->meta=META_MAJ; } else if (!u_strcmp(content,"MIN")) { tag[i]->type=META_TAG; tag[i]->meta=META_MIN; } else if (!u_strcmp(content,"PRE")) { tag[i]->type=META_TAG; tag[i]->meta=META_PRE; } else if (!u_strcmp(content,"NB")) { tag[i]->type=META_TAG; tag[i]->meta=META_NB; if (negative_tag) { error("Negative mark will be ignored in <!NB>\n"); } } else if (!u_strcmp(content,"TOKEN")) { tag[i]->type=META_TAG; tag[i]->meta=META_TOKEN; } else { /* If we arrive here, we have not a meta but a pattern like * <be>, <be.V>, <V:K>, ... */ tag[i]->type=PATTERN_TAG; tag[i]->pattern=build_pattern(content,semantic_codes,parameters->tilde_negation_operator,prv_alloc); if (tag[i]->pattern->type==CODE_PATTERN || tag[i]->pattern->type==LEMMA_AND_CODE_PATTERN || tag[i]->pattern->type==FULL_PATTERN || tag[i]->pattern->type==INFLECTED_AND_LEMMA_PATTERN) { /* If the pattern we obtain contains grammatical/semantic * codes, then we put it in the pattern tree and we note its number. */ tag[i]->pattern_number=add_pattern(number_of_patterns,tag[i]->pattern,parameters->pattern_tree_root,prv_alloc); if (tag[i]->pattern->type==CODE_PATTERN) { /* If we have a code pattern, then the tag will just need to contain * the pattern number, BUT, WE DO NOT FREE THE PATTERN, * since this pattern still could be used in morphological mode */ tag[i]->type=PATTERN_NUMBER_TAG; } } } /* We don't forget to free the content */ free_cb(content,prv_alloc); } } } } }
static PetscErrorCode set_pairwise(gs_id *gs) { PetscInt i, j; PetscInt p_mask_size; PetscInt *p_mask, *sh_proc_mask, *tmp_proc_mask; PetscInt *ngh_buf, *buf2; PetscInt offset; PetscInt *msg_list, *msg_size, **msg_nodes, nprs; PetscInt *pairwise_elm_list, len_pair_list=0; PetscInt *iptr, t1, i_start, nel, *elms; PetscInt ct; PetscErrorCode ierr; PetscFunctionBegin; /* to make life easier */ nel = gs->nel; elms = gs->elms; ngh_buf = gs->ngh_buf; sh_proc_mask = gs->pw_nghs; /* need a few temp masks */ p_mask_size = len_bit_mask(num_nodes); p_mask = (PetscInt*) malloc(p_mask_size); tmp_proc_mask = (PetscInt*) malloc(p_mask_size); /* set mask to my my_id's bit mask */ ierr = set_bit_mask(p_mask,p_mask_size,my_id);CHKERRQ(ierr); p_mask_size /= sizeof(PetscInt); len_pair_list=gs->len_pw_list; gs->pw_elm_list=pairwise_elm_list=(PetscInt*)malloc((len_pair_list+1)*sizeof(PetscInt)); /* how many processors (nghs) do we have to exchange with? */ nprs=gs->num_pairs=ct_bits((char *)sh_proc_mask,p_mask_size*sizeof(PetscInt)); /* allocate space for gs_gop() info */ gs->pair_list = msg_list = (PetscInt *) malloc(sizeof(PetscInt)*nprs); gs->msg_sizes = msg_size = (PetscInt *) malloc(sizeof(PetscInt)*nprs); gs->node_list = msg_nodes = (PetscInt **) malloc(sizeof(PetscInt*)*(nprs+1)); /* init msg_size list */ ierr = ivec_zero(msg_size,nprs);CHKERRQ(ierr); /* expand from bit mask list to int list */ ierr = bm_to_proc((char *)sh_proc_mask,p_mask_size*sizeof(PetscInt),msg_list);CHKERRQ(ierr); /* keep list of elements being handled pairwise */ for (i=j=0;i<nel;i++) { if (elms[i] & TOP_BIT) {elms[i] ^= TOP_BIT; pairwise_elm_list[j++] = i;} } pairwise_elm_list[j] = -1; gs->msg_ids_out = (MPI_Request *) malloc(sizeof(MPI_Request)*(nprs+1)); gs->msg_ids_out[nprs] = MPI_REQUEST_NULL; gs->msg_ids_in = (MPI_Request *) malloc(sizeof(MPI_Request)*(nprs+1)); gs->msg_ids_in[nprs] = MPI_REQUEST_NULL; gs->pw_vals = (PetscScalar *) malloc(sizeof(PetscScalar)*len_pair_list*vec_sz); /* find who goes to each processor */ for (i_start=i=0;i<nprs;i++) { /* processor i's mask */ ierr = set_bit_mask(p_mask,p_mask_size*sizeof(PetscInt),msg_list[i]);CHKERRQ(ierr); /* det # going to processor i */ for (ct=j=0;j<len_pair_list;j++) { buf2 = ngh_buf+(pairwise_elm_list[j]*p_mask_size); ierr = ivec_and3(tmp_proc_mask,p_mask,buf2,p_mask_size);CHKERRQ(ierr); if (ct_bits((char *)tmp_proc_mask,p_mask_size*sizeof(PetscInt))) {ct++;} } msg_size[i] = ct; i_start = PetscMax(i_start,ct); /*space to hold nodes in message to first neighbor */ msg_nodes[i] = iptr = (PetscInt*) malloc(sizeof(PetscInt)*(ct+1)); for (j=0;j<len_pair_list;j++) { buf2 = ngh_buf+(pairwise_elm_list[j]*p_mask_size); ierr = ivec_and3(tmp_proc_mask,p_mask,buf2,p_mask_size);CHKERRQ(ierr); if (ct_bits((char *)tmp_proc_mask,p_mask_size*sizeof(PetscInt))) {*iptr++ = j;} } *iptr = -1; } msg_nodes[nprs] = NULL; j=gs->loc_node_pairs=i_start; t1 = GL_MAX; ierr = giop(&i_start,&offset,1,&t1);CHKERRQ(ierr); gs->max_node_pairs = i_start; i_start=j; t1 = GL_MIN; ierr = giop(&i_start,&offset,1,&t1);CHKERRQ(ierr); gs->min_node_pairs = i_start; i_start=j; t1 = GL_ADD; ierr = giop(&i_start,&offset,1,&t1);CHKERRQ(ierr); gs->avg_node_pairs = i_start/num_nodes + 1; i_start=nprs; t1 = GL_MAX; giop(&i_start,&offset,1,&t1); gs->max_pairs = i_start; /* remap pairwise in tail of gsi_via_bit_mask() */ gs->msg_total = ivec_sum(gs->msg_sizes,nprs); gs->out = (PetscScalar *) malloc(sizeof(PetscScalar)*gs->msg_total*vec_sz); gs->in = (PetscScalar *) malloc(sizeof(PetscScalar)*gs->msg_total*vec_sz); /* reset malloc pool */ free((void*)p_mask); free((void*)tmp_proc_mask); PetscFunctionReturn(0); }
static PetscErrorCode get_ngh_buf(gs_id *gs) { PetscInt i, j, npw=0, ntree_map=0; PetscInt p_mask_size, ngh_buf_size, buf_size; PetscInt *p_mask, *sh_proc_mask, *pw_sh_proc_mask; PetscInt *ngh_buf, *buf1, *buf2; PetscInt offset, per_load, num_loads, or_ct, start, end; PetscInt *ptr1, *ptr2, i_start, negl, nel, *elms; PetscInt oper=GL_B_OR; PetscInt *ptr3, *t_mask, level, ct1, ct2; PetscErrorCode ierr; PetscFunctionBegin; /* to make life easier */ nel = gs->nel; elms = gs->elms; level = gs->level; /* det #bytes needed for processor bit masks and init w/mask cor. to my_id */ p_mask = (PetscInt*) malloc(p_mask_size=len_bit_mask(num_nodes)); ierr = set_bit_mask(p_mask,p_mask_size,my_id);CHKERRQ(ierr); /* allocate space for masks and info bufs */ gs->nghs = sh_proc_mask = (PetscInt*) malloc(p_mask_size); gs->pw_nghs = pw_sh_proc_mask = (PetscInt*) malloc(p_mask_size); gs->ngh_buf_sz = ngh_buf_size = p_mask_size*nel; t_mask = (PetscInt*) malloc(p_mask_size); gs->ngh_buf = ngh_buf = (PetscInt*) malloc(ngh_buf_size); /* comm buffer size ... memory usage bounded by ~2*msg_buf */ /* had thought I could exploit rendezvous threshold */ /* default is one pass */ per_load = negl = gs->negl; gs->num_loads = num_loads = 1; i=p_mask_size*negl; /* possible overflow on buffer size */ /* overflow hack */ if (i<0) {i=INT_MAX;} buf_size = PetscMin(msg_buf,i); /* can we do it? */ if (p_mask_size>buf_size) SETERRQ2(PETSC_ERR_PLIB,"get_ngh_buf() :: buf<pms :: %d>%d\n",p_mask_size,buf_size); /* get giop buf space ... make *only* one malloc */ buf1 = (PetscInt*) malloc(buf_size<<1); /* more than one gior exchange needed? */ if (buf_size!=i) { per_load = buf_size/p_mask_size; buf_size = per_load*p_mask_size; gs->num_loads = num_loads = negl/per_load + (negl%per_load>0); } /* convert buf sizes from #bytes to #ints - 32 bit only! */ p_mask_size/=sizeof(PetscInt); ngh_buf_size/=sizeof(PetscInt); buf_size/=sizeof(PetscInt); /* find giop work space */ buf2 = buf1+buf_size; /* hold #ints needed for processor masks */ gs->mask_sz=p_mask_size; /* init buffers */ ierr = ivec_zero(sh_proc_mask,p_mask_size);CHKERRQ(ierr); ierr = ivec_zero(pw_sh_proc_mask,p_mask_size);CHKERRQ(ierr); ierr = ivec_zero(ngh_buf,ngh_buf_size);CHKERRQ(ierr); /* HACK reset tree info */ tree_buf=NULL; tree_buf_sz=ntree=0; /* ok do it */ for (ptr1=ngh_buf,ptr2=elms,end=gs->gl_min,or_ct=i=0; or_ct<num_loads; or_ct++) { /* identity for bitwise or is 000...000 */ ivec_zero(buf1,buf_size); /* load msg buffer */ for (start=end,end+=per_load,i_start=i; (offset=*ptr2)<end; i++, ptr2++) { offset = (offset-start)*p_mask_size; ivec_copy(buf1+offset,p_mask,p_mask_size); } /* GLOBAL: pass buffer */ ierr = giop(buf1,buf2,buf_size,&oper);CHKERRQ(ierr); /* unload buffer into ngh_buf */ ptr2=(elms+i_start); for(ptr3=buf1,j=start; j<end; ptr3+=p_mask_size,j++) { /* I own it ... may have to pairwise it */ if (j==*ptr2) { /* do i share it w/anyone? */ ct1 = ct_bits((char *)ptr3,p_mask_size*sizeof(PetscInt)); /* guess not */ if (ct1<2) {ptr2++; ptr1+=p_mask_size; continue;} /* i do ... so keep info and turn off my bit */ ivec_copy(ptr1,ptr3,p_mask_size); ierr = ivec_xor(ptr1,p_mask,p_mask_size);CHKERRQ(ierr); ierr = ivec_or(sh_proc_mask,ptr1,p_mask_size);CHKERRQ(ierr); /* is it to be done pairwise? */ if (--ct1<=level) { npw++; /* turn on high bit to indicate pw need to process */ *ptr2++ |= TOP_BIT; ierr = ivec_or(pw_sh_proc_mask,ptr1,p_mask_size);CHKERRQ(ierr); ptr1+=p_mask_size; continue; } /* get set for next and note that I have a tree contribution */ /* could save exact elm index for tree here -> save a search */ ptr2++; ptr1+=p_mask_size; ntree_map++; } /* i don't but still might be involved in tree */ else { /* shared by how many? */ ct1 = ct_bits((char *)ptr3,p_mask_size*sizeof(PetscInt)); /* none! */ if (ct1<2) continue; /* is it going to be done pairwise? but not by me of course!*/ if (--ct1<=level) continue; } /* LATER we're going to have to process it NOW */ /* nope ... tree it */ ierr = place_in_tree(j);CHKERRQ(ierr); } } free((void*)t_mask); free((void*)buf1); gs->len_pw_list=npw; gs->num_nghs = ct_bits((char *)sh_proc_mask,p_mask_size*sizeof(PetscInt)); /* expand from bit mask list to int list and save ngh list */ gs->nghs = (PetscInt*) malloc(gs->num_nghs * sizeof(PetscInt)); bm_to_proc((char *)sh_proc_mask,p_mask_size*sizeof(PetscInt),gs->nghs); gs->num_pw_nghs = ct_bits((char *)pw_sh_proc_mask,p_mask_size*sizeof(PetscInt)); oper = GL_MAX; ct1 = gs->num_nghs; ierr = giop(&ct1,&ct2,1,&oper);CHKERRQ(ierr); gs->max_nghs = ct1; gs->tree_map_sz = ntree_map; gs->max_left_over=ntree; free((void*)p_mask); free((void*)sh_proc_mask); PetscFunctionReturn(0); }
/** * Returns 1 if we can match <E> from the current state, with or without * conditions; 0 otherwise. */ int graph_matches_E(int initial_state,int current_state,const Fst2State* states,Fst2Tag* tags, int current_graph,unichar** graph_names, ConditionList conditions_for_states[], ConditionList *graph_conditions) { Transition* l; Fst2State s; int ret_value=0; int ret; *graph_conditions=NULL; s=states[current_state]; if (is_final_state(s)) { /* If we are arrived in a final state, then the graph matches <E> */ set_bit_mask(&(s->control),UNCONDITIONAL_E_MATCH); return 1; } if (is_bit_mask_set(s->control,TMP_LOOP_MARK)) { /* If we have a loop, we do nothing, because they will be * dealt with later. */ return 0; } if (is_bit_mask_set(s->control,VISITED_MARK)) { /* If we are in state that has already been visited */ if (is_bit_mask_set(s->control,UNCONDITIONAL_E_MATCH)) { /* If this state can match <E> without conditions, then we have finished */ return 1; } if (is_bit_mask_set(s->control,CONDITIONAL_E_MATCH)) { /* If this state can match <E> with conditions, then we have finished, but * we copy the necessary conditions in 'graph_conditions'. */ *graph_conditions=clone_ConditionList(conditions_for_states[current_state-initial_state]); return 1; } /* If the state has been visited and if it does not match <E>, then we return OK */ return 0; } set_bit_mask(&(s->control),VISITED_MARK); set_bit_mask(&(s->control),TMP_LOOP_MARK); l=s->transitions; /* We look all the outgoing transitions */ while (l!=NULL) { if (l->tag_number<0) { /* If we have a subgraph, we test if it matches <E> */ *graph_conditions=NULL; ret=graph_matches_E(initial_state,l->state_number,states,tags,current_graph,graph_names,conditions_for_states,graph_conditions); if (ret==1) { /* If the subgraph matches <E>, we say that the current state matches * <E>, modulo the conditions to be verified */ set_bit_mask(&(s->control),CONDITIONAL_E_MATCH); /* We insert the new condition in first position... */ insert_graph_in_conditions(-(l->tag_number),graph_conditions); /* ...and we merge the new conditions with the existing ones for this state */ merge_condition_lists(&conditions_for_states[current_state-initial_state],*graph_conditions); *graph_conditions=NULL; } ret_value=ret_value|ret; } else if (tags[l->tag_number]->control&1) { /* If we have an <E> transition, we explore the rest of the graph from it */ *graph_conditions=NULL; ret=graph_matches_E(initial_state,l->state_number,states,tags,current_graph,graph_names,conditions_for_states,graph_conditions); if (ret==1) { /* If we can match <E> from the <E>-transition's destination state, then * we can match it from the current state. */ if (*graph_conditions==NULL) { /* If there is no condition */ set_bit_mask(&(s->control),UNCONDITIONAL_E_MATCH); } else { /* Otherwise, we add the condition to the existing ones */ set_bit_mask(&(s->control),CONDITIONAL_E_MATCH); merge_condition_lists(&conditions_for_states[current_state-initial_state],*graph_conditions); *graph_conditions=NULL; } } ret_value=ret_value|ret; } l=l->next; } unset_bit_mask(&(s->control),TMP_LOOP_MARK); *graph_conditions=clone_ConditionList(conditions_for_states[current_state-initial_state]); return ret_value; }