void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr begin, node_ptr end) { node_ptr* pos = &next_group(begin); if(*pos != begin) { // The node is at the beginning of a group. // Find the previous node pointer: pos = &b.next_; while(*pos != begin) pos = &next_group(*pos); // Remove from group if(BOOST_UNORDERED_BORLAND_BOOL(end)) split_group(end); } else { node_ptr group1 = split_group(begin); if(BOOST_UNORDERED_BORLAND_BOOL(end)) { node_ptr group2 = split_group(end); if(begin == group2) { node_ptr end1 = get(group1).group_prev_; node_ptr end2 = get(group2).group_prev_; get(group1).group_prev_ = end2; get(group2).group_prev_ = end1; } } } *pos = end; }
static void edit_index(int natoms, t_atoms *atoms, rvec *x, t_blocka *block, char ***gn, gmx_bool bVerbose) { static char **atnames, *ostring; static gmx_bool bFirst = TRUE; char inp_string[STRLEN], *string; char gname[STRLEN], gname1[STRLEN], gname2[STRLEN]; int i, i0, i1, sel_nr, sel_nr2, newgroup; atom_id nr, nr1, nr2, *index, *index1, *index2; gmx_bool bAnd, bOr, bPrintOnce; if (bFirst) { bFirst = FALSE; snew(atnames, MAXNAMES); for (i = 0; i < MAXNAMES; i++) { snew(atnames[i], NAME_LEN+1); } } string = NULL; snew(index, natoms); snew(index1, natoms); snew(index2, natoms); newgroup = NOTSET; bPrintOnce = TRUE; do { gname1[0] = '\0'; if (bVerbose || bPrintOnce || newgroup != NOTSET) { printf("\n"); if (bVerbose || bPrintOnce || newgroup == NOTSET) { i0 = 0; i1 = block->nr; } else { i0 = newgroup; i1 = newgroup+1; } for (i = i0; i < i1; i++) { printf("%3d %-20s: %5d atoms\n", i, (*gn)[i], block->index[i+1]-block->index[i]); } newgroup = NOTSET; } if (bVerbose || bPrintOnce) { printf("\n"); printf(" nr : group ! 'name' nr name 'splitch' nr Enter: list groups\n"); printf(" 'a': atom & 'del' nr 'splitres' nr 'l': list residues\n"); printf(" 't': atom type | 'keep' nr 'splitat' nr 'h': help\n"); printf(" 'r': residue 'res' nr 'chain' char\n"); printf(" \"name\": group 'case': case %s 'q': save and quit\n", bCase ? "insensitive" : "sensitive "); printf(" 'ri': residue index\n"); bPrintOnce = FALSE; } printf("\n"); printf("> "); if (NULL == fgets(inp_string, STRLEN, stdin)) { gmx_fatal(FARGS, "Error reading user input"); } inp_string[strlen(inp_string)-1] = 0; printf("\n"); string = inp_string; while (string[0] == ' ') { string++; } ostring = string; nr = 0; if (string[0] == 'h') { printf(" nr : selects an index group by number or quoted string.\n"); printf(" The string is first matched against the whole group name,\n"); printf(" then against the beginning and finally against an\n"); printf(" arbitrary substring. A multiple match is an error.\n"); printf(" 'a' nr1 [nr2 ...] : selects atoms, atom numbering starts at 1.\n"); printf(" 'a' nr1 - nr2 : selects atoms in the range from nr1 to nr2.\n"); printf(" 'a' name1[*] [name2[*] ...] : selects atoms by name(s), '?' matches any char,\n"); printf(" wildcard '*' allowed at the end of a name.\n"); printf(" 't' type1[*] [type2[*] ...] : as 'a', but for type, run input file required.\n"); printf(" 'r' nr1[ic1] [nr2[ic2] ...] : selects residues by number and insertion code.\n"); printf(" 'r' nr1 - nr2 : selects residues in the range from nr1 to nr2.\n"); printf(" 'r' name1[*] [name2[*] ...] : as 'a', but for residue names.\n"); printf(" 'ri' nr1 - nr2 : selects residue indices, 1-indexed, (as opposed to numbers) in the range from nr1 to nr2.\n"); printf(" 'chain' ch1 [ch2 ...] : selects atoms by chain identifier(s),\n"); printf(" not available with a .gro file as input.\n"); printf(" ! : takes the complement of a group with respect to all\n"); printf(" the atoms in the input file.\n"); printf(" & | : AND and OR, can be placed between any of the options\n"); printf(" above, the input is processed from left to right.\n"); printf(" 'name' nr name : rename group nr to name.\n"); printf(" 'del' nr1 [- nr2] : deletes one group or groups in the range from nr1 to nr2.\n"); printf(" 'keep' nr : deletes all groups except nr.\n"); printf(" 'case' : make all name compares case (in)sensitive.\n"); printf(" 'splitch' nr : split group into chains using CA distances.\n"); printf(" 'splitres' nr : split group into residues.\n"); printf(" 'splitat' nr : split group into atoms.\n"); printf(" 'res' nr : interpret numbers in group as residue numbers\n"); printf(" Enter : list the currently defined groups and commands\n"); printf(" 'l' : list the residues.\n"); printf(" 'h' : show this help.\n"); printf(" 'q' : save and quit.\n"); printf("\n"); printf(" Examples:\n"); printf(" > 2 | 4 & r 3-5\n"); printf(" selects all atoms from group 2 and 4 that have residue numbers 3, 4 or 5\n"); printf(" > a C* & !a C CA\n"); printf(" selects all atoms starting with 'C' but not the atoms 'C' and 'CA'\n"); printf(" > \"protein\" & ! \"backb\"\n"); printf(" selects all atoms that are in group 'protein' and not in group 'backbone'\n"); if (bVerbose) { printf("\npress Enter "); getchar(); } } else if (strncmp(string, "del", 3) == 0) { string += 3; if (parse_int(&string, &sel_nr)) { while (string[0] == ' ') { string++; } if (string[0] == '-') { string++; parse_int(&string, &sel_nr2); } else { sel_nr2 = NOTSET; } while (string[0] == ' ') { string++; } if (string[0] == '\0') { remove_group(sel_nr, sel_nr2, block, gn); } else { printf("\nSyntax error: \"%s\"\n", string); } } } else if (strncmp(string, "keep", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { remove_group(sel_nr+1, block->nr-1, block, gn); remove_group(0, sel_nr-1, block, gn); } } else if (strncmp(string, "name", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { if ((sel_nr >= 0) && (sel_nr < block->nr)) { sscanf(string, "%s", gname); sfree((*gn)[sel_nr]); (*gn)[sel_nr] = strdup(gname); } } } else if (strncmp(string, "case", 4) == 0) { bCase = !bCase; printf("Switched to case %s\n", bCase ? "sensitive" : "insensitive"); } else if (string[0] == 'v') { bVerbose = !bVerbose; printf("Turned verbose %s\n", bVerbose ? "on" : "off"); } else if (string[0] == 'l') { if (check_have_atoms(atoms, ostring) ) { list_residues(atoms); } } else if (strncmp(string, "splitch", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_chain(atoms, x, sel_nr, block, gn); } } else if (strncmp(string, "splitres", 8) == 0) { string += 8; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, FALSE); } } else if (strncmp(string, "splitat", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, TRUE); } } else if (string[0] == '\0') { bPrintOnce = TRUE; } else if (string[0] != 'q') { nr1 = -1; nr2 = -1; if (parse_entry(&string, natoms, atoms, block, gn, &nr, index, gname)) { do { while (string[0] == ' ') { string++; } bAnd = FALSE; bOr = FALSE; if (string[0] == '&') { bAnd = TRUE; } else if (string[0] == '|') { bOr = TRUE; } if (bAnd || bOr) { string++; nr1 = nr; for (i = 0; i < nr; i++) { index1[i] = index[i]; } strcpy(gname1, gname); if (parse_entry(&string, natoms, atoms, block, gn, &nr2, index2, gname2)) { if (bOr) { or_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_%s", gname1, gname2); } else { and_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_&_%s", gname1, gname2); } } } } while (bAnd || bOr); } while (string[0] == ' ') { string++; } if (string[0]) { printf("\nSyntax error: \"%s\"\n", string); } else if (nr > 0) { copy2block(nr, index, block); srenew(*gn, block->nr); newgroup = block->nr-1; (*gn)[newgroup] = strdup(gname); } else { printf("Group is empty\n"); } } } while (string[0] != 'q'); sfree(index); sfree(index1); sfree(index2); }
void grouped_node_base<A>::unlink_nodes(bucket& b, node_ptr end) { split_group(end); b.next_ = end; }
/* ***************************************************************** This procedure sort the strings a[0] ... a[n-1] with the help of an anchor. The real sorting is done by the procedure anchor_sort(). Here we choose the anchor. The parameter depth is the number of chars that a[0] ... a[n-1] are known to have in common (thus a direct comparison among a[i] and a[j] should start from position depth) Note that a[] is a subsection of the sa therefore a[0] ... a[n-1] are starting position of suffixes For every a[i] we look at the anchor a[i]/Anchor_dist and the one after that. This justifies the definition of Anchor_num (the size of Anchor_ofset[] and Anchor_rank[] defined in ds_sort()) as Anchor_num = 2 + (n-1)/Anchor_dist ***************************************************************** */ void helped_sort(Int32 *a, int n, int depth) { Int32 i, curr_sb, diff, toffset, aoffset; Int32 text_pos, anchor_pos, anchor, anchor_rank; Int32 min_forw_offset, min_forw_offset_buc, max_back_offset; Int32 best_forw_anchor, best_forw_anchor_buc, best_back_anchor; Int32 forw_anchor_index, forw_anchor_index_buc, back_anchor_index; Calls_helped_sort++; // update count if(n==1) goto done_sorting; // simplest case: only one string // if there are no anchors use pseudo-anchors or deep_sort if(Anchor_dist==0) { pseudo_or_deep_sort(a, n, depth); return; } // compute the current bucket curr_sb = Get_small_bucket(a[0]); // init best anchor variables with illegal values min_forw_offset = min_forw_offset_buc = INT_MAX; max_back_offset = INT_MIN; best_forw_anchor = best_forw_anchor_buc = best_back_anchor = -1; forw_anchor_index = forw_anchor_index_buc = back_anchor_index = -1; // look at the anchor preceeding each a[i] for(i=0;i<n;i++) { text_pos = a[i]; // get anchor preceeding text_pos=a[i] anchor = text_pos/Anchor_dist; toffset = text_pos % Anchor_dist; // distance of a[i] from anchor aoffset = Anchor_offset[anchor]; // distance of sorted suf from anchor if(aoffset<Anchor_dist) { // check if it is a "sorted" anchor diff = aoffset - toffset; assert(diff!=0); if(diff>0) { // anchor <= a[i] < (sorted suffix) if(curr_sb!=Get_small_bucket(text_pos+diff)) { if(diff<min_forw_offset) { min_forw_offset = diff; best_forw_anchor = anchor; forw_anchor_index = i; } } else { // the sorted suffix belongs to the same bucket of a[0]..a[n-1] if(diff<min_forw_offset_buc) { min_forw_offset_buc = diff; best_forw_anchor_buc = anchor; forw_anchor_index_buc = i; } } } else { // diff<0 => anchor <= (sorted suffix) < a[i] if(diff>max_back_offset) { max_back_offset = diff; best_back_anchor = anchor; back_anchor_index = i; } // try to find a sorted suffix > a[i] by looking at next anchor aoffset = Anchor_offset[++anchor]; if(aoffset<Anchor_dist) { diff = Anchor_dist + aoffset - toffset; assert(diff>0); if(curr_sb!=Get_small_bucket(text_pos+diff)) { if(diff<min_forw_offset) { min_forw_offset = diff; best_forw_anchor = anchor; forw_anchor_index = i; } } else { if(diff<min_forw_offset_buc) { min_forw_offset_buc = diff; best_forw_anchor_buc = anchor; forw_anchor_index_buc = i; } } } } } } // ------ if forward anchor_sort is possible, do it! -------- if(best_forw_anchor>=0 && min_forw_offset<depth-1) { Calls_anchor_sort_forw++; assert(min_forw_offset<2*Anchor_dist); anchor_pos = a[forw_anchor_index] + min_forw_offset; anchor_rank = Anchor_rank[best_forw_anchor]; assert(Sa[anchor_rank]==anchor_pos); general_anchor_sort(a,n,anchor_pos,anchor_rank,min_forw_offset); goto done_sorting; } // ------ if backward anchor_sort is possible do it! --------- if(best_back_anchor>=0) { UChar *T0, *Ti; int j; assert(max_back_offset>-Anchor_dist && max_back_offset<0); // make sure that the offset is legal for all a[i] for(i=0;i<n;i++) { if(a[i]+max_back_offset<0) goto fail; // illegal offset, give up } // make sure that a[0] .. a[n-1] are preceded by the same substring T0 = Text + a[0]; for(i=1;i<n;i++) { Ti = Text + a[i]; for(j=max_back_offset; j<= -1; j++) if(T0[j]!=Ti[j]) goto fail; // mismatch, give up } // backward anchor sorting is possible Calls_anchor_sort_backw++; anchor_pos = a[back_anchor_index] + max_back_offset; anchor_rank = Anchor_rank[best_back_anchor]; assert(Sa[anchor_rank]==anchor_pos); general_anchor_sort(a,n,anchor_pos,anchor_rank,max_back_offset); goto done_sorting; } fail: // ----- try forward anchor_sort with anchor in the same bucket if(best_forw_anchor_buc>=0 && min_forw_offset_buc<depth-1) { int equal,lower,upper; assert(min_forw_offset_buc<2*Anchor_dist); anchor_pos = a[forw_anchor_index_buc] + min_forw_offset_buc; anchor_rank = Anchor_rank[best_forw_anchor_buc]; assert(Sa[anchor_rank]==anchor_pos); // establish how many suffixes can be sorted using anchor_sort() equal=split_group(a,n,depth,min_forw_offset_buc, forw_anchor_index_buc,&lower); if(equal==n) { Calls_anchor_sort_forw++; general_anchor_sort(a,n,anchor_pos,anchor_rank,min_forw_offset_buc); } else { // -- a[0] ... a[n-1] are split into 3 groups: lower, equal, upper upper = n-equal-lower; assert(upper>=0); // printf("Warning! lo=%d eq=%d up=%d a=%x\n",lower,equal,upper,(int)a); // sort the equal group Calls_anchor_sort_forw++; if(equal>1) general_anchor_sort(a+lower,equal,anchor_pos,anchor_rank, min_forw_offset_buc); // sort upper and lower groups using deep_sort if(lower>1) pseudo_or_deep_sort(a,lower,depth); if(upper>1) pseudo_or_deep_sort(a+lower+equal,upper,depth); } // end if(equal==n) ... else goto done_sorting; } // end hard case // --------------------------------------------------------------- // If we get here it means that everything failed // In this case we simply deep_sort a[0] ... a[n-1] // --------------------------------------------------------------- pseudo_or_deep_sort(a, n, depth); done_sorting: // -------- update Anchor_rank[], Anchor_offset[] ------- if(Anchor_dist>0) update_anchors(a, n); }