/* Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator */ /* From input file "sorth.p" */ #include /* sorth: sort helix list thomas schneider module libraries required: delman, prgmods, delmods, auxmods */ /* end of program */ /* begin module version */ #define version 2.42 /* of sorth.p 1995 July 26 origin: 1984 feb 4 (* end module version */ /* begin module describe.sorth */ /* name sorth: sort helix list synopsis sorth(hlist: in, shlist: out, list: out, sorthp: in, output: out) files hlist: a list of helixes generated from program helix. shlist: a list of helixes, where the longest or strongest helix has been chosen from each piece to piece comparison ('set'). list: progress of the program. sorthp: parameters to control the program. 1. characters on the first line of the file determine the priority order for sorting the helixes. all commands must end with 'a' to indicate 'ambiguous'. the commands are: ea - sort on energies (see technical notes) la - sort on lengths (see technical notes) ela - sort first on energies then on lengths. lea - sort first on lengths then on energies. 2. the second line of the file must contain one integer, 'top'. up to 'top' of the strongest helixes will be written to shlist. if 'top' = 1, then any set of helixes that are ambiguous are not copied to the shlist. this allows one to find the strongest unambiguous helix in each set. 3. the third line is the minimum length or maximum energy of helixes to be sorted. output: messages to the user. description the strongest helixes in hlist are sorted and copied to shlist. the user can sort on energy, length, energy then length, or length then energy. the user may chose more than one helix to be output (eg, the top 10). see also helix.p author thomas dana schneider bugs none known technical notes when only one variable is sorted on, the order of the other variable will not be meaningful because it is determined by the way the sort algorithm works. the constant 'maxhelix' determines the maximum number of helixes that can be sorted. */ /* end module describe.sorth */ /* begin module sorth.const */ #define prime '"' /* single quote mark */ #define lowpriority 3 /* the number of priority levels: 1 to this. see the operations type */ #define maxhelix 1000 /* one more than the largest number of helixes the program can handle. */ /* end module sorth.const */ /* begin module sorth.type */ typedef struct operations { /* the order that the sorting operations should take place. the priority array gives the order. e = energy, l = length, a = ambiguous */ Char priority[lowpriority]; long low; /* the lowest priority used in the priority array */ boolean getenergy; /* whether or not energy is to be gotten */ long top; /* the top 'top' helixes are printed to shlist */ double minlenmaxene; /* the minimum length or maximum energy of helixes to be accepted from hlist */ boolean doinglength; /* true when minlenmaxene is positive */ } operations; typedef short position; /* the positions of helixes */ typedef struct helix { /* information about a helix */ long x, y; /* the coordinates of a helix */ long length; /* the length of a helix */ double energy; /* the energy of a helix */ } helix; /* end module sorth.type */ /* begin module sorth.var */ Static _TEXT hlist; /* helix list from helix */ Static _TEXT shlist; /* sorted list of helixes */ Static _TEXT list; /* progress of the program */ Static _TEXT sorthp; /* parameters of the program */ /* globals used by the lessthan, swap and doset */ Static position ordering[maxhelix]; /* the order of the helixes */ Static helix helixes[maxhelix]; /* the helixes in the order that they were read in */ Static Char sorton; /* what to sort the helixes on (by reordering the ordering array) */ Static boolean both; Static jmp_buf _JL1; /* true means that sorting should be done on both length and energy, using the value of sorton to tell which to do first. */ /* end module sorth.var */ /* begin module package.primitive */ /* ************************************************************************ */ /* begin module halt */ Static Void halt() { /* stop the program. the procedure performs a goto to the end of the program. you must have a label: label 1; declared, and also the end of the program must have this label: 1: end. examples are in the module libraries. this is the only goto in the delila system. */ printf(" program halt.\n"); longjmp(_JL1, 1); } /* end module halt version = 'delmod 6.51 85 apr 17 tds/gds' */ /* begin module copyaline */ Static Void copyaline(fin, fout) _TEXT *fin, *fout; { /* copy a line from file fin to file fout */ while (!P_eoln(fin->f)) { putc(P_peek(fin->f), fout->f); getc(fin->f); } fscanf(fin->f, "%*[^\n]"); getc(fin->f); putc('\n', fout->f); } /* copyaline */ /* end module copyaline version = 'delmod 6.51 85 apr 17 tds/gds' */ /* begin module copylines */ Static long copylines(fin, fout, n) _TEXT *fin, *fout; long n; { /* copy n lines of file fin to file fout. the actual number of lines copied is returned. */ long index = 0; /* the current line number */ while (!BUFEOF(fin->f) && index < n) { copyaline(fin, fout); index++; } return index; } /* copylines */ Local Void die() { printf(" no helix list data\n"); halt(); } /* end module copylines version = 'delmod 6.51 85 apr 17 tds/gds' */ /* ************************************************************************ */ /* end module package.primitive version = 'delmod 6.51 85 apr 17 tds/gds' */ /* begin module findcolon */ Static Void findcolon(thefile) _TEXT *thefile; { /* move the file to the characters just past ': ' (colon, space) */ boolean found = false; while (!found) { if (BUFEOF(thefile->f)) { die(); continue; } if (P_peek(thefile->f) != ':') { getc(thefile->f); continue; } getc(thefile->f); if (BUFEOF(thefile->f)) die(); else if (P_peek(thefile->f) == ' ') { getc(thefile->f); found = true; } } } /* end module findcolon version = 'auxmod 1.37 85 apr 4 gds/tds'; */ /* begin module gethelix */ Static Void gethelix(hlist, x, y, length, getenergy, energy, done) _TEXT *hlist; long *x, *y, *length; boolean getenergy; double *energy; boolean *done; { /* get the (x,y,length) info on some helix listed in hlist. if the x,y pair changes, then done is true and no values are returned. checknames may be used at this point to start the next pair. if getenergy is true, then the routine expects that there will be an energy on the helix line */ if (BUFEOF(hlist->f)) { *done = true; return; } getc(hlist->f); /* skip the blank */ if (P_peek(hlist->f) != ' ') { *done = true; return; } *done = false; findcolon(hlist); fscanf(hlist->f, "%ld", x); findcolon(hlist); fscanf(hlist->f, "%ld", y); findcolon(hlist); fscanf(hlist->f, "%ld", length); if (getenergy) fscanf(hlist->f, "%lg", energy); else *energy = 0.0; fscanf(hlist->f, "%*[^\n]"); getc(hlist->f); } /* gethelix */ /* Local variables for lessthan: */ struct LOC_lessthan { position a, b; double ea, eb; /* the absolute value of the energy values at positions a and b */ long la, lb; /* the length values at a and b */ } ; Local boolean byenergy(LINK) struct LOC_lessthan *LINK; { /* give the function less than using energies */ LINK->ea = fabs(helixes[ordering[LINK->a-1] - 1].energy); LINK->eb = fabs(helixes[ordering[LINK->b-1] - 1].energy); return (LINK->ea < LINK->eb); } /* byenergy */ Local boolean bylength(LINK) struct LOC_lessthan *LINK; { /* give the function less than using lengths */ LINK->la = helixes[ordering[LINK->a-1] - 1].length; LINK->lb = helixes[ordering[LINK->b-1] - 1].length; return (LINK->la < LINK->lb); } /* bylength */ /* end module gethelix version = 'auxmod 1.37 85 apr 4 gds/tds'; */ /* begin module sorth.sortfunctions */ Static boolean lessthan(a_, b_) position a_, b_; { /* see quicksort */ struct LOC_lessthan V; boolean Result; V.a = a_; V.b = b_; switch (sorton) { case 'e': if (byenergy(&V)) Result = true; else if (both) { if (V.ea == V.eb) Result = bylength(&V); else Result = false; } else Result = false; break; case 'l': if (bylength(&V)) Result = true; else if (both) { if (V.la == V.lb) Result = byenergy(&V); else Result = false; } else Result = false; break; } return Result; } /* lessthan */ Static Void swap_(a, b) position a, b; { /* see quicksort */ position hold; /* for swapping */ hold = ordering[a-1]; ordering[a-1] = ordering[b-1]; ordering[b-1] = hold; } /* swap */ /* end module sorth.sortfunctions */ /* begin module quicksort */ Static Void quicksort(left, right) position left, right; { /* quick sort a list between positions left and right, into ascending order. a position is simply a scalar of the form 0..max. the array to be sorted is dimensioned 1..max. (the difference in the ranges is important to the correct operation of the sort...) two external routines are used: function lessthan(a, b: position): boolean is a generalized test for value-at-a < value-at-b. procedure swap(a, b: position) switches the items at positions a and b. since these routines are external, the procedure is general. this procedure taken from the book 'algorithms + data structures = programs' by niklaus wirth, prentice-hall, inc., englewood cliffs, n.j.(1976), pp. 76-82 */ position lower = left; position upper; /* the positions looked at currently */ position center; /* the rough center of the region being sorted */ center = (left + right) / 2; upper = right; do { while (lessthan(lower, center)) lower++; while (lessthan(center, upper)) upper--; if (lower <= upper) { /* keep track of the center through the map: */ if (lower == center) center = upper; else if (upper == center) center = lower; swap_(lower, upper); lower++; upper--; } } while (lower <= upper); if (left < upper) quicksort(left, upper); if (lower < right) quicksort(lower, right); } /* end module quicksort version = 'prgmod 3.97 85 may 5 tds'; */ /* begin module sorth.hcopy */ Static Void hcopy(hlist, shlist, list) _TEXT *hlist, *shlist, *list; { /* hlist copy. copy the header of hlist to shlist and list. */ long dummy; /* to capture output of copylines */ if (*hlist->name != '\0') { if (hlist->f != NULL) hlist->f = freopen(hlist->name, "r", hlist->f); else hlist->f = fopen(hlist->name, "r"); } else rewind(hlist->f); if (hlist->f == NULL) _EscIO2(FileNotFound, hlist->name); RESETBUF(hlist->f, Char); if (*shlist->name != '\0') { if (shlist->f != NULL) shlist->f = freopen(shlist->name, "w", shlist->f); else shlist->f = fopen(shlist->name, "w"); } else { if (shlist->f != NULL) rewind(shlist->f); else shlist->f = tmpfile(); } if (shlist->f == NULL) _EscIO2(FileNotFound, shlist->name); SETUPBUF(shlist->f, Char); fprintf(shlist->f, " sorth %4.2f sorted helixes from ", version); /* do a minimal check that the hlist is reasonable: */ if (copylines(hlist, shlist, 8L) != 8) { printf("hlist does not have a header\n"); halt(); } if (*hlist->name != '\0') { if (hlist->f != NULL) hlist->f = freopen(hlist->name, "r", hlist->f); else hlist->f = fopen(hlist->name, "r"); } else rewind(hlist->f); if (hlist->f == NULL) _EscIO2(FileNotFound, hlist->name); RESETBUF(hlist->f, Char); if (*list->name != '\0') { if (list->f != NULL) list->f = freopen(list->name, "w", list->f); else list->f = fopen(list->name, "w"); } else { if (list->f != NULL) rewind(list->f); else list->f = tmpfile(); } if (list->f == NULL) _EscIO2(FileNotFound, list->name); SETUPBUF(list->f, Char); fprintf(list->f, " sorth %4.2f sorted helixes from ", version); dummy = copylines(hlist, list, 7L); /* skip first header line for gethelix */ fscanf(hlist->f, "%*[^\n]"); getc(hlist->f); } /* hcopy */ /* end module sorth.hcopy */ /* begin module sorth.getparams */ Static Void getparams(hlist, sorthp, order, list) _TEXT *hlist, *sorthp; operations *order; _TEXT *list; { /* get whether energies are in the hlist, and learn from sorthp what priority order should be used. learn the top number of helixes to print. report the results to list. */ long i; /* general index */ long doe = 0, dol = 0; /* counts of the priorities 'e' and 'l' */ long FORLIM; /* first pick up data from hlist */ if (*hlist->name != '\0') { if (hlist->f != NULL) hlist->f = freopen(hlist->name, "r", hlist->f); else hlist->f = fopen(hlist->name, "r"); } else rewind(hlist->f); if (hlist->f == NULL) _EscIO2(FileNotFound, hlist->name); RESETBUF(hlist->f, Char); for (i = 1; i <= 5; i++) { /* move to energy data */ fscanf(hlist->f, "%*[^\n]"); getc(hlist->f); } getc(hlist->f); /* skip the blank */ /* determine if one has the potential to sorton energies: */ if (P_peek(hlist->f) == 'e') order->getenergy = true; else order->getenergy = false; /* move to first set of helixes */ for (i = 1; i <= 3; i++) { fscanf(hlist->f, "%*[^\n]"); getc(hlist->f); } /* read the order and see if it is consistant with getenergy */ if (*sorthp->name != '\0') { if (sorthp->f != NULL) sorthp->f = freopen(sorthp->name, "r", sorthp->f); else sorthp->f = fopen(sorthp->name, "r"); } else rewind(sorthp->f); if (sorthp->f == NULL) _EscIO2(FileNotFound, sorthp->name); RESETBUF(sorthp->f, Char); if (BUFEOF(sorthp->f)) { printf("sorthp parameter file is empty\n"); halt(); } order->low = 0; while (!P_eoln(sorthp->f) && order->low < lowpriority) { if (P_peek(sorthp->f) == ' ') { /* skip spaces */ getc(sorthp->f); continue; } order->low++; order->priority[order->low - 1] = getc(sorthp->f); if (order->priority[order->low - 1] == '\n') order->priority[order->low - 1] = ' '; if (order->priority[order->low - 1] == 'e') { doe++; continue; } if (order->priority[order->low - 1] == 'l') dol++; else if (order->priority[order->low - 1] != 'a') { printf("priority \"%c\" is not allowed\n", order->priority[order->low - 1]); halt(); } } if (doe > 1 || dol > 1) { printf("eea and lla are not allowed parameters\n"); halt(); } if (order->low < 2) { printf("priority list is too short in file sorthp\n"); halt(); } if (order->priority[order->low - 1] != 'a') { printf("priority list in file sorthp must end with an \"a\"\n"); halt(); } /* check that priority does not depend on energy when energy is not in the hlist */ if (!order->getenergy) { i = 1; while (i < order->low && order->priority[i-1] != 'e') i++; if (order->priority[i-1] == 'e') { printf("sorthp requests sorting by energy\n"); printf("but there are no energies in hlist\n"); halt(); } } fscanf(sorthp->f, "%*[^\n]"); getc(sorthp->f); /* determine top */ if (BUFEOF(sorthp->f)) { order->top = 1; order->minlenmaxene = 0.0; } else { fscanf(sorthp->f, "%ld%*[^\n]", &order->top); getc(sorthp->f); if (order->top < 1) { printf(" \"top\" parameter must be > 1\n"); halt(); } if (BUFEOF(sorthp->f)) order->minlenmaxene = 0.0; else { fscanf(sorthp->f, "%lg%*[^\n]", &order->minlenmaxene); getc(sorthp->f); } } order->doinglength = (order->minlenmaxene > 0.0 || !order->getenergy); /* display priorities to list file */ putc(' ', list->f); FORLIM = order->low; for (i = 0; i < FORLIM; i++) putc(order->priority[i], list->f); fprintf(list->f, " priority order of sorting:"); FORLIM = order->low - 2; for (i = 0; i <= FORLIM; i++) { switch (order->priority[i]) { case 'e': fprintf(list->f, " energy"); break; case 'l': fprintf(list->f, " length"); break; } fprintf(list->f, " then"); } fprintf(list->f, " ambiguous.\n"); fprintf(list->f, " %4ld helixes or fewer are written to shlist. ", order->top); if (order->top > maxhelix) fprintf(list->f, "all helixes guaranteed to be written.\n"); else fprintf(list->f, "some helixes may be removed.\n"); if (order->doinglength) fprintf(list->f, " %ld is the minimum length helix recorded\n", (long)order->minlenmaxene); else fprintf(list->f, " %7.2f is the maximum energy helix recorded\n", order->minlenmaxene); /* set the global "both" */ if (order->low == 3) both = true; else both = false; } /* getparams */ /* end module sorth.getparams */ /* begin module sorth.hrecord */ Static Void hrecord(hlist, x, y, length, doenergy, energy) _TEXT *hlist; long x, y, length; boolean doenergy; double energy; { /* record the helix information in hlist, just like hrecord in program helix does. do energy if doenergy is true. */ fprintf(hlist->f, " x5%c: %6ld y5%c: %6ld length: %3ld", prime, x, prime, y, length); if (doenergy) fprintf(hlist->f, " %7.2f kcal", energy); putc('\n', hlist->f); } /* hrecord */ /* end module sorth.hrecord */ /* begin module sorth.doset */ Static Void doset(hlist, shlist, order, n, u, e, l, a) _TEXT *hlist, *shlist; operations order; long *n, *u, *e, *l, *a; { /* do a set of helixes from hlist (one set is the helixes from the comparision of two pieces). use the order given to select those helixes to put into shlist. record the results in the totals: n, u, e, l, a (none, unique, energy, length or ambiguous cases). note the references to globals: ordering, helixes, sorton and both these are necessary because quicksort must use lessthan and swap which in turn must do the dirty work. see sorth.var. */ boolean done; /* when there are no more helixes in a set */ long h = 0; /* which helix is being read, then the number of helixes */ long s; /* output sorting index */ helix *WITH; do { /* advance to next open position of helixes and ordering array */ h++; if (h > maxhelix) { printf(" there are more helixes than can be handled.\n"); printf(" (there are at least %ld of them.) increase constant maxhelix.\n", (long)maxhelix); halt(); } WITH = &helixes[h-1]; gethelix(hlist, &WITH->x, &WITH->y, &WITH->length, order.getenergy, &WITH->energy, &done); if (done) h--; /* the last h is not used */ else { /* using two cases is faster */ ordering[h-1] = h; /* initial ordering is 1 to 1 */ /* reject unwanted helixes by decreasing h */ switch (order.doinglength) { case true: if (helixes[h-1].length < order.minlenmaxene) h--; break; case false: if (helixes[h-1].energy > order.minlenmaxene) h--; break; } } } while (!done); if (h == 0) /* no helixes in this set */ sorton = 'n'; else if (h == 1) { /* got a unique helix */ WITH = &helixes[ordering[h-1] - 1]; hrecord(shlist, WITH->x, WITH->y, WITH->length, order.getenergy, WITH->energy); sorton = 'u'; } else { sorton = order.priority[0]; /* first priority sort follows */ quicksort(1, (int)h); if (!lessthan((int)(h - 1), (int)h) && order.top == 1) sorton = 'a'; /* it is ambiguous... */ else { s = h; while (s > 0 && s > h - order.top) { WITH = &helixes[ordering[s-1] - 1]; hrecord(shlist, WITH->x, WITH->y, WITH->length, order.getenergy, WITH->energy); s--; /* choose the top helix */ } } } /* more than one helix to do */ /* display the findings to list. make sure that no top is specified if none was found */ fprintf(list.f, " helixes: %3ld", h); if (sorton == 'a' || sorton == 'n') fprintf(list.f, " %3c", ' '); else fprintf(list.f, " top: %3d", ordering[h-1]); fprintf(list.f, " by: %c", sorton); switch (sorton) { case 'n': /* no helixes */ (*n)++; break; case 'u': /* unique helix */ (*u)++; break; case 'e': /* energy */ (*e)++; break; case 'l': /* length */ (*l)++; break; case 'a': /* ambigous */ (*a)++; break; } /* copy the next id line if not end of file */ if (!BUFEOF(hlist->f)) { putc(' ', shlist->f); /* replace space lost to gethelix procedure */ copyaline(hlist, shlist); } } /* doset */ /* end module sorth.doset */ /* begin module sorth.themain */ Static Void themain(hlist, shlist, list, sorthp) _TEXT *hlist, *shlist, *list, *sorthp; { /* the main procedure of sorth. only the strongest helixes of hlist are copied to shlist, according to the parameter rules sorthp. report in list. */ operations order; /* the order of sorting operations */ /* totals for the various possible cases for each set: none, unique, energy, length and ambiguous. */ long n = 0, u = 0, e = 0, l = 0, a = 0, sets = 0; /* set number */ boolean endofline; /* triggers end of lines in the list file */ printf(" sorth %4.2f\n", version); hcopy(hlist, shlist, list); getparams(hlist, sorthp, &order, list); /* pick up sets of helixes and chose one. */ while (!BUFEOF(hlist->f)) { sets++; endofline = ((sets & 1) == 1); if (endofline) putc('\n', list->f); fprintf(list->f, " set: %3ld", sets); doset(hlist, shlist, order, &n, &u, &e, &l, &a); if (endofline) putc('.', list->f); } fprintf(list->f, "\n\n classification of sets in hlist by number of helixes:\n"); fprintf(list->f, " none: %4ld no helixes\n", n); fprintf(list->f, " unique: %4ld one helix\n", u); fprintf(list->f, " energy: %4ld sorted by energy first\n", e); fprintf(list->f, " length: %4ld sorted by length first\n", l); fprintf(list->f, " ambiguous: %4ld sorted, with no single unambiguous strongest helix\n", a); fprintf(list->f, " total: %4ld\n", n + u + e + l + a); printf(" %ld sets of helixes sorted\n", sets); if (n + u + e + l + a != sets) { printf("sorth.themain, program error\n"); halt(); } } /* themain */ /* end module sorth.themain */ main(argc, argv) int argc; Char *argv[]; { PASCAL_MAIN(argc, argv); if (setjmp(_JL1)) goto _L1; sorthp.f = NULL; strcpy(sorthp.name, "sorthp"); list.f = NULL; strcpy(list.name, "list"); shlist.f = NULL; strcpy(shlist.name, "shlist"); hlist.f = NULL; strcpy(hlist.name, "hlist"); themain(&hlist, &shlist, &list, &sorthp); _L1: if (hlist.f != NULL) fclose(hlist.f); if (shlist.f != NULL) fclose(shlist.f); if (list.f != NULL) fclose(list.f); if (sorthp.f != NULL) fclose(sorthp.f); exit(EXIT_SUCCESS); } /* sorth */ /* End. */