BDD bits_range_bdd(uint32_t low_bits,uint32_t high_bits) { BDD rval,tail,newbdd; int i; uint32_t b; if (low_bits>0) { tail=bddtrue; for (i=31,b=1;i>=0;i--,b<<=1) { if (low_bits&b) newbdd=bdd_addref(bdd_and(bdd_ithvar(i),tail)); else newbdd=bdd_addref(bdd_or(bdd_ithvar(i),tail)); bdd_delref(tail); tail=newbdd; } rval=tail; } else rval=bddtrue; if (high_bits<UINT32_MAX) { tail=bddtrue; for (i=31,b=1;i>=0;i--,b<<=1) { if (high_bits&b) newbdd=bdd_addref(bdd_or(bdd_nithvar(i),tail)); else newbdd=bdd_addref(bdd_and(bdd_nithvar(i),tail)); bdd_delref(tail); tail=newbdd; } rval=bdd_addref(bdd_and(rval,tail)); bdd_delref(tail); } return rval; }
/* NAME {* fdd\_domain *} SECTION {* fdd *} SHORT {* BDD encoding of the domain of a FDD variable *} PROTO {* BDD fdd_domain(int var) *} DESCR {* Returns what corresponds to a disjunction of all possible values of the variable {\tt var}. This is more efficient than doing {\tt fdd\_ithvar(var,0) OR fdd\_ithvar(var,1) ...} explicitely for all values in the domain of {\tt var}. *} RETURN {* The encoding of the domain*} */ BDD fdd_domain(int var) { int n,val; Domain *dom; BDD d; if (!bddrunning) { bdd_error(BDD_RUNNING); return bddfalse; } if (var < 0 || var >= fdvarnum) { bdd_error(BDD_VAR); return bddfalse; } /* Encode V<=X-1. V is the variables in 'var' and X is the domain size */ dom = &domain[var]; val = dom->realsize-1; d = bddtrue; for (n=0 ; n<dom->binsize ; n++) { BDD tmp; if (val & 0x1) tmp = bdd_apply( bdd_nithvar(dom->ivar[n]), d, bddop_or ); else tmp = bdd_apply( bdd_nithvar(dom->ivar[n]), d, bddop_and ); val >>= 1; bdd_addref(tmp); bdd_delref(d); d = tmp; } return d; }
/* NAME {* fdd\_ithvar *} SECTION {* fdd *} SHORT {* the BDD for the i'th FDD set to a specific value *} PROTO {* BDD fdd_ithvar(int var, int val) *} DESCR {* Returns the BDD that defines the value {\tt val} for the finite domain block {\tt var}. The encoding places the Least Significant Bit at the top of the BDD tree (which means they will have the lowest variable index). The returned BDD will be $V_0 \conj V_1 \conj \ldots \conj V_N$ where each $V_i$ will be in positive or negative form depending on the value of {\tt val}. *} RETURN {* The correct BDD or the constant false BDD on error. *} ALSO {* fdd\_ithset *} */ BDD fdd_ithvar(int var, int val) { int n; int v=1, tmp; if (!bddrunning) { bdd_error(BDD_RUNNING); return bddfalse; } if (var < 0 || var >= fdvarnum) { bdd_error(BDD_VAR); return bddfalse; } if (val < 0 || val >= domain[var].realsize) { bdd_error(BDD_RANGE); return bddfalse; } for (n=0 ; n<domain[var].binsize ; n++) { bdd_addref(v); if (val & 0x1) tmp = bdd_apply(bdd_ithvar(domain[var].ivar[n]), v, bddop_and); else tmp = bdd_apply(bdd_nithvar(domain[var].ivar[n]), v, bddop_and); bdd_delref(v); v = tmp; val >>= 1; } return v; }
/* ML type: varnum-> bdd */ EXTERNML value mlbdd_bdd_nithvar(value i) /* ML */ { return mlbdd_make(bdd_nithvar(Int_val(i))); }
void create_bdds(TransitionSystem *model) { // printf("%d\ttotal states before merge\n", initial_numstates); // merge_similar_parents(&PSEUDO_END); // merge_similar_children(model->pseudo_initial); //merging children spoiles the calculation of support model->states_size = assign_id_and_collect_labels(model, model->pseudo_initial); // printf("%d\ttotal states after merge\n", model->states_size); // printf("%d\tstates removed\n", initial_numstates - model->states_size); get_transitions(model, NULL, model->pseudo_initial); init_buddy(model->states_size); int state_vars = ceil_of_log2_of(model->states_size); int bdd_vars = state_vars * 2; bdd_setvarnum(bdd_vars); BDD unprimed2primed = bdd_addref(0); model->states_bdds = malloc(sizeof(int *) * model->states_size); model->states_primed_bdds = malloc(sizeof(int *) * model->states_size); model->all_states = bdd_addref(0); //encode states as binary functions for (int i = 1; i < model->states_size; i++) { BDD tmp = bdd_addref(1); BDD tmpp = bdd_addref(1); for (int j = 0; j < state_vars; j++) { int test = (i >> (state_vars - 1 - j)) & 1; if (test == 1) { tmp = f_bdd_and_with(tmp, bdd_ithvar(j)); tmpp = f_bdd_and_with(tmpp, bdd_ithvar(j + state_vars)); } else { tmp = f_bdd_and_with(tmp, bdd_nithvar(j)); tmpp = f_bdd_and_with(tmpp, bdd_nithvar(j + state_vars)); } } model->states_bdds[i] = bdd_addref(tmp); model->states_primed_bdds[i] = bdd_addref(tmpp); model->all_states = f_bdd_or_with(model->all_states, tmp); BDD tt = bdd_addref(bdd_and(tmp, tmpp)); unprimed2primed = f_bdd_or_with(unprimed2primed, tt); bdd_delref(tt); bdd_delref(tmp); bdd_delref(tmpp); } model->pseudo_end = model->states_bdds[PSEUDO_END.id]; //remove pseudo end BDD tmp = bdd_addref(model->all_states); bdd_delref(model->all_states); model->all_states = bdd_apply(tmp, model->pseudo_end, bddop_diff); bdd_delref(tmp); model->unprimed2primed = bdd_addref(unprimed2primed); bdd_delref(unprimed2primed); //create helper of unprimed and primed variables BDD unprimed_vars = bdd_addref(1); BDD primed_vars = bdd_addref(1); for (int i = 0; i < state_vars; i++) { unprimed_vars = f_bdd_and_with(unprimed_vars, bdd_ithvar(i)); primed_vars = f_bdd_and_with(primed_vars, bdd_ithvar(i + state_vars)); } model->unprimed_vars = unprimed_vars; model->primed_vars = primed_vars; //create function for transitions BDD transitions_bdd = bdd_addref(0); for (int i = 0; i < model->transition_size; i++) { // printf("(%d, %d), ", model->transitions[i]->src, model->transitions[i]->dest); BDD tt = bdd_addref(bdd_and(model->states_bdds[model->transitions[i]->src], model->states_primed_bdds[model->transitions[i]->dest])); transitions_bdd = f_bdd_or_with(transitions_bdd, tt); bdd_delref(tt); } //transition from end to end to complete Kripke structure // BDD tt = bdd_addref(bdd_and(model->states_bdds[PSEUDO_END.id], model->states_primed_bdds[PSEUDO_END.id])); // transitions_bdd = f_bdd_or_with(transitions_bdd, tt); // bdd_delref(tt); model->initial_states = 0; State *child; // printf("children %d\n", model->pseudo_initial->children_size); for (int i = 0; i < model->pseudo_initial->children_size; i++) { child = model->pseudo_initial->children[i]; if (child == NULL) continue; // removed model->initial_states = f_bdd_or_with(model->initial_states, model->states_bdds[child->id]); } model->transitions_bdd = transitions_bdd; for (int i = 0; i < model->activities_size; i++) { Labels *l = model->labels[i]; l->states_bdd = bdd_addref(0); for (int j = 0; j < l->states_size; j++) { l->states_bdd = f_bdd_or_with(l->states_bdd, model->states_bdds[l->states[j]]); } } }
int main(int argc,char **argv) { char ambiguous_treatment='A'; char linebuff[1024]; char *parseptr; PARSE_STATE ps; uint32_t low_code,high_code; int width,i,j,vi,vj; FILE *unicode_db; BDD x,y,child[8]; BDD *queue; int queue_low,queue_high,queue_max; puts("/*\n" " * GENERATED CODE - DO NOT EDIT!\n" " * Edit mkwcw.c, which generates this, or the input to that\n" " * program, instead. Distributions of IDSgrep will nonetheless\n" " * usually include a ready-made copy of this file because\n" " * compiling and running mkwcw.c requires a library and data\n" " * file that, although free, not everyone is expected to have.\n" " */\n\n" "#include \"_stdint.h\"\n" ); if (argc>1) ambiguous_treatment=argv[1][0]&~32; bdd_init(1000000,15625); bdd_setcacheratio(64); bdd_setvarnum(32); bdd_gbc_hook(NULL); defined_codes=bddfalse; zero_codes=bddfalse; wide_codes=bddfalse; /* yes, unfortunately UnicodeData.txt and EastAsianWidth.txt are just * different enough to need separate parsers, at least if the parsers * are as stupid as I'd like these ones to be */ if (argc>2) { unicode_db=fopen(argv[2],"rt"); while (1) { fgets(linebuff,sizeof(linebuff),unicode_db); if (feof(unicode_db)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr==';') ps=psSEMI; else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psSEMI: if (*parseptr==';') ps=psWIDTH; break; case psWIDTH: if (((parseptr[0]=='M') && ((parseptr[1]=='e') || (parseptr[1]=='n'))) || ((parseptr[0]=='C') && (parseptr[1]=='f'))) width=0; /* FALL THROUGH */ default: ps=psSTOP; break; } if (width==0) set_range_width(low_code,low_code,0); } fclose(unicode_db); } while (1) { fgets(linebuff,sizeof(linebuff),stdin); if (feof(stdin)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; high_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr=='.') ps=psHIGH; else if (*parseptr==';') { high_code=low_code; ps=psWIDTH; } else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psHIGH: if ((*parseptr>='0') && (*parseptr<='9')) high_code=(high_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) high_code=(high_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) high_code=(high_code<<4)+(*parseptr-'A'+10); else if ((*parseptr=='.') || (*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces, tabs, and dots */ } else if (*parseptr==';') ps=psWIDTH; else ps=psSTOP; break; case psWIDTH: if (*parseptr=='A') *parseptr=ambiguous_treatment; switch (*parseptr) { case 'F': /* full-width treated as wide */ case 'W': /* wide */ width=2; break; case 'H': /* half-width treated as narrow */ case 'N': /* narrow or neutral */ width=1; break; case '0': /* zero-width - should only appear in user database */ width=0; break; default: /* ignore all others */ break; } /* FALL THROUGH */ default: ps=psSTOP; break; } if (width>=0) set_range_width(low_code,high_code,width); } printf("/* node counts before simplification: %d %d %d */\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); x=bdd_addref(bdd_simplify(wide_codes,defined_codes)); bdd_delref(wide_codes); wide_codes=x; x=bdd_addref(bdd_apply(defined_codes,wide_codes,bddop_diff)); bdd_delref(defined_codes); defined_codes=x; x=bdd_addref(bdd_simplify(zero_codes,defined_codes)); bdd_delref(zero_codes); zero_codes=x; printf("/* node counts after simplification: %d %d %d */\n\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); bdd_varblockall(); bdd_intaddvarblock(0,7,0); bdd_intaddvarblock(8,15,0); bdd_intaddvarblock(16,23,0); bdd_intaddvarblock(24,31,0); bdd_intaddvarblock(0,31,1); bdd_reorder_probe(&reordering_size_callback); puts("typedef struct _WIDTH_BBD_ENT {\n" " int16_t child[8];\n" " char byte,shift;\n" "} WIDTH_BDD_ENT;\n\n" "static WIDTH_BDD_ENT width_bdd[]={"); queue=(BDD *)malloc(sizeof(BDD)*1000); queue_max=1000; queue_low=2; queue_high=4; queue[0]=bddfalse; queue[1]=bddtrue; queue[2]=wide_codes; queue[3]=zero_codes; while (queue_low<queue_high) { if (queue_high+8>queue_max) { queue_max/=3; queue_max*=4; queue=(BDD *)realloc(queue,sizeof(BDD)*queue_max); } reorder_focus=queue[queue_low]; bdd_reorder(BDD_REORDER_WIN2ITE); vj=bdd_var(queue[queue_low]); vi=(vj/8)*8; vj=((vj-vi+1)/3)*3-1; if (vj<0) vj=0; x=bdd_addref(bdd_restrict(queue[queue_low],bdd_nithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[0]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[1]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[2]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[3]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); x=bdd_addref(bdd_restrict(queue[queue_low],bdd_ithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[4]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[5]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[6]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[7]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); fputs(" {{",stdout); for (i=0;i<8;i++) { queue[queue_high]=child[i]; for (j=0;queue[j]!=child[i];j++); if (j==queue_high) queue_high++; else bdd_delref(child[i]); printf("%d",j-2); if (i<7) putchar(','); } printf("},%d,%d},\n",vi/8,5-vj); queue_low++; } puts("};\n\n" "int idsgrep_utf8cw(char *);\n" "\n" "#define WBS width_bdd[search]\n" "\n" "int idsgrep_utf8cw(char *cp) {\n" " int search;\n" "\n" " for (search=0;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " if (search==-1)\n" " return 2;\n" " for (search=1;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " return ((-1)-search);\n" "}\n"); bdd_done(); exit(0); }
BDD code_range_bdd(uint32_t low_code,uint32_t high_code) { BDD rval,subrange,srx; if (low_code<0x80) rval=bits_range_bdd((low_code<<24), (high_code>=0x80? 0x7FFFFFFF: high_code<<24)); else rval=bddfalse; if ((low_code<0x800) && (high_code>=0x80)) { subrange=bits_range_bdd((low_code<0x80? 0xC2800000: ((low_code& 0x3F)<<16)+ ((low_code&0x7C0)<<18)+ 0xC0800000), (high_code>=0x800? 0xDFBFFFFF: ((high_code& 0x3F)<<16)+ ((high_code&0x7C0)<<18)+ 0xC080FFFF)); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(9))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(8))); bdd_delref(srx); srx=bdd_addref(bdd_or(rval,subrange)); bdd_delref(rval); bdd_delref(subrange); rval=srx; } if ((low_code<0x10000) && (high_code>=0x800)) { subrange=bits_range_bdd((low_code<0x800? 0xE0A00000: ((low_code& 0x3F)<<8)+ ((low_code& 0xFC0)<<10)+ ((low_code&0xF000)<<12)+ 0xE0808000), (high_code>=0x10000? 0xEFBFBFFF: ((high_code& 0x3F)<<8)+ ((high_code& 0xFC0)<<10)+ ((high_code&0xF000)<<12)+ 0xE08080FF)); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(17))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(16))); bdd_delref(srx); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(9))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(8))); bdd_delref(srx); srx=bdd_addref(bdd_or(rval,subrange)); bdd_delref(rval); bdd_delref(subrange); rval=srx; } if (high_code>=0x10000) { subrange=bits_range_bdd((low_code<0x10000? 0xF0900000: (low_code& 0x3F)+ ((low_code& 0xFC0)<<2)+ ((low_code& 0x3F000)<<4)+ ((low_code&0x1C0000)<<6)+ 0xF0808080), (high_code& 0x3F)+ ((high_code& 0xFC0)<<2)+ ((high_code& 0x3F000)<<4)+ ((high_code&0x1C0000)<<6)+ 0xF0808080); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(25))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(24))); bdd_delref(srx); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(17))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(16))); bdd_delref(srx); srx=bdd_addref(bdd_and(subrange,bdd_nithvar(9))); bdd_delref(subrange); subrange=bdd_addref(bdd_and(srx,bdd_ithvar(8))); bdd_delref(srx); srx=bdd_addref(bdd_or(rval,subrange)); bdd_delref(rval); bdd_delref(subrange); rval=srx; } return rval; }