1 | |
---|
2 | /* version 3.6. (c) Copyright 1993-2002 by the University of Washington. |
---|
3 | Written by Joseph Felsenstein, Akiko Fuseki, Sean Lamont, Andrew Keeffe, |
---|
4 | and Dan Fineman. |
---|
5 | Permission is granted to copy and use this program provided no fee is |
---|
6 | charged for it and provided that this copyright notice is not removed. */ |
---|
7 | |
---|
8 | #include <stdio.h> |
---|
9 | #include <signal.h> |
---|
10 | #ifdef WIN32 |
---|
11 | #include <windows.h> |
---|
12 | /* for console code (clear screen, text color settings) */ |
---|
13 | CONSOLE_SCREEN_BUFFER_INFO savecsbi; |
---|
14 | HANDLE hConsoleOutput; |
---|
15 | |
---|
16 | void phyClearScreen(); |
---|
17 | void phySaveConsoleAttributes(); |
---|
18 | void phySetConsoleAttributes(); |
---|
19 | void phyRestoreConsoleAttributes(); |
---|
20 | void phyFillScreenColor(); |
---|
21 | #endif |
---|
22 | |
---|
23 | #include "phylip.h" |
---|
24 | |
---|
25 | #ifndef OLDC |
---|
26 | static void crash_handler(int signum); |
---|
27 | |
---|
28 | #endif |
---|
29 | |
---|
30 | FILE *infile, *outfile, *intree, *intree2, *outtree, *weightfile, *catfile, *ancfile, *mixfile, *factfile; |
---|
31 | long spp, words, bits; |
---|
32 | boolean ibmpc, ansi, tranvsp; |
---|
33 | naym *nayme; /* names of species */ |
---|
34 | |
---|
35 | static void crash_handler(int sig_num) |
---|
36 | { /* when we crash, lets print out something usefull */ |
---|
37 | printf("ERROR: "); |
---|
38 | switch(sig_num) { |
---|
39 | #ifdef SIGSEGV |
---|
40 | case SIGSEGV: |
---|
41 | puts("This program has caused a Segmentation fault."); |
---|
42 | break; |
---|
43 | #endif /* SIGSEGV */ |
---|
44 | #ifdef SIGFPE |
---|
45 | case SIGFPE: |
---|
46 | puts("This program has caused a Floating Point Exception"); |
---|
47 | break; |
---|
48 | #endif /* SIGFPE */ |
---|
49 | #ifdef SIGILL |
---|
50 | case SIGILL: |
---|
51 | puts("This program has attempted an illegal instruction"); |
---|
52 | break; |
---|
53 | #endif /* SIGILL */ |
---|
54 | #ifdef SIGPIPE |
---|
55 | case SIGPIPE: |
---|
56 | puts("This program tried to write to a broken pipe"); |
---|
57 | break; |
---|
58 | #endif /* SIGPIPE */ |
---|
59 | #ifdef SIGBUS |
---|
60 | case SIGBUS: |
---|
61 | puts("This program had a bus error"); |
---|
62 | break; |
---|
63 | #endif /* SIGBUS */ |
---|
64 | } |
---|
65 | if (sig_num == SIGSEGV) { |
---|
66 | puts(" This may have been caused by an incorrectly formatted"); |
---|
67 | puts(" input tree file or input file. You should check those"); |
---|
68 | puts(" files carefully."); |
---|
69 | puts(" If this seems to be a bug, please mail joe@gs.washington.edu"); |
---|
70 | } |
---|
71 | else { |
---|
72 | puts(" Most likely, you have encountered a bug in the program."); |
---|
73 | puts(" Since this seems to be a bug, please mail joe@gs.washington.edu"); |
---|
74 | } |
---|
75 | puts(" with the name of the program, your computer system type,"); |
---|
76 | puts(" a full description of the problem, and with the input data file."); |
---|
77 | puts(" (which should be in the body of the message, not as an Attachment)."); |
---|
78 | |
---|
79 | #ifdef WIN32 |
---|
80 | puts ("Hit Enter or Return to close program."); |
---|
81 | puts(" You may have to hit Enter or Return twice."); |
---|
82 | getchar (); |
---|
83 | getchar (); |
---|
84 | phyRestoreConsoleAttributes(); |
---|
85 | #endif |
---|
86 | abort(); |
---|
87 | } |
---|
88 | |
---|
89 | |
---|
90 | void init(int UNUSED_argc, char** UNUSED_argv) |
---|
91 | { /* initialization routine for all programs |
---|
92 | * anything done at the beginig for every program should be done here */ |
---|
93 | |
---|
94 | /* set up signal handler for |
---|
95 | * segfault,floating point exception, illeagal instruction, bad pipe, bus error |
---|
96 | * there are more signals that can cause a crash, but these are the most common |
---|
97 | * even these aren't found on all machines. */ |
---|
98 | |
---|
99 | (void)UNUSED_argc; |
---|
100 | (void)UNUSED_argv; |
---|
101 | |
---|
102 | #ifdef SIGSEGV |
---|
103 | signal(SIGSEGV, crash_handler); |
---|
104 | #endif /* SIGSEGV */ |
---|
105 | #ifdef SIGFPE |
---|
106 | signal(SIGFPE, crash_handler); |
---|
107 | #endif /* SIGFPE */ |
---|
108 | #ifdef SIGILL |
---|
109 | signal(SIGILL, crash_handler); |
---|
110 | #endif /* SIGILL */ |
---|
111 | #ifdef SIGPIPE |
---|
112 | signal(SIGPIPE, crash_handler); |
---|
113 | #endif /* SIGPIPE */ |
---|
114 | #ifdef SIGBUS |
---|
115 | signal(SIGBUS, crash_handler); |
---|
116 | #endif /* SIGBUS */ |
---|
117 | |
---|
118 | #ifdef WIN32 |
---|
119 | phySetConsoleAttributes(); |
---|
120 | phyClearScreen(); |
---|
121 | #endif |
---|
122 | |
---|
123 | } |
---|
124 | |
---|
125 | void scan_eoln(FILE *f) |
---|
126 | { /* eat everything to the end of line or eof*/ |
---|
127 | char ch; |
---|
128 | |
---|
129 | while (!eoff(f) && !eoln(f)) |
---|
130 | gettc(f); |
---|
131 | if (!eoff(f)) |
---|
132 | ch = gettc(f); |
---|
133 | if (ch == '\r' && !eoff(f) && eoln(f)) |
---|
134 | gettc(f); |
---|
135 | } |
---|
136 | |
---|
137 | |
---|
138 | boolean eoff(FILE *f) |
---|
139 | { /* check for end of file */ |
---|
140 | int ch; |
---|
141 | |
---|
142 | if (feof(f)) |
---|
143 | return true; |
---|
144 | ch = getc(f); |
---|
145 | if (ch == EOF) { |
---|
146 | ungetc(ch, f); |
---|
147 | return true; |
---|
148 | } |
---|
149 | ungetc(ch, f); |
---|
150 | return false; |
---|
151 | } /*eoff*/ |
---|
152 | |
---|
153 | |
---|
154 | boolean eoln(FILE *f) |
---|
155 | { /* check for end of line or eof*/ |
---|
156 | register int ch; |
---|
157 | |
---|
158 | ch = getc(f); |
---|
159 | if (ch == EOF) |
---|
160 | return true; |
---|
161 | ungetc(ch, f); |
---|
162 | return ((ch == '\n') || (ch == '\r')); |
---|
163 | } /*eoln*/ |
---|
164 | |
---|
165 | |
---|
166 | int filexists(char *filename) |
---|
167 | { /* check whether file already exists */ |
---|
168 | FILE *fp; |
---|
169 | fp =fopen(filename,"r"); |
---|
170 | if (fp) { |
---|
171 | fclose(fp); |
---|
172 | return 1; |
---|
173 | } else |
---|
174 | return 0; |
---|
175 | } /*filexists*/ |
---|
176 | |
---|
177 | |
---|
178 | const char* get_command_name (const char *vektor) |
---|
179 | { /* returns the name of the program from vektor without the whole path */ |
---|
180 | char *last_slash; |
---|
181 | |
---|
182 | /* Point to the last slash... */ |
---|
183 | last_slash = strrchr (vektor, DELIMITER); |
---|
184 | |
---|
185 | if (last_slash) |
---|
186 | /* If there was a last slash, return the character after it */ |
---|
187 | return last_slash + 1; |
---|
188 | else |
---|
189 | /* If not, return the vector */ |
---|
190 | return vektor; |
---|
191 | |
---|
192 | } /*get_command_name*/ |
---|
193 | |
---|
194 | |
---|
195 | void getstryng(char *fname) |
---|
196 | { /* read in a file name from stdin and take off newline if any */ |
---|
197 | |
---|
198 | fname = fgets(fname, 100, stdin); |
---|
199 | if (strchr(fname, '\n') != NULL) |
---|
200 | *strchr(fname, '\n') = '\0'; |
---|
201 | } /* getstryng */ |
---|
202 | |
---|
203 | |
---|
204 | void countup(long *loopcount, long maxcount) |
---|
205 | { /* count how many times this loop has tried to read data, bail out |
---|
206 | if exceeds maxcount */ |
---|
207 | |
---|
208 | (*loopcount)++; |
---|
209 | if ((*loopcount) >= maxcount) { |
---|
210 | printf("\nERROR: Made %ld attempts to read input in loop. Aborting run.\n", |
---|
211 | *loopcount); |
---|
212 | exxit(-1); |
---|
213 | } |
---|
214 | } /* countup */ |
---|
215 | |
---|
216 | |
---|
217 | void openfile(FILE **fp,const char *filename,const char *filedesc, |
---|
218 | const char *mode,const char *application, char *perm) |
---|
219 | { /* open a file, testing whether it exists etc. */ |
---|
220 | FILE *of; |
---|
221 | char file[FNMLNGTH]; |
---|
222 | char filemode[2]; |
---|
223 | char input[FNMLNGTH]; |
---|
224 | char ch; |
---|
225 | const char *progname_without_path; |
---|
226 | long loopcount, loopcount2; |
---|
227 | |
---|
228 | progname_without_path = get_command_name(application); |
---|
229 | |
---|
230 | strcpy(file,filename); |
---|
231 | strcpy(filemode,mode); |
---|
232 | loopcount = 0; |
---|
233 | while (1){ |
---|
234 | if (filemode[0] == 'w' && filexists(file)){ |
---|
235 | printf("\n%s: the file \"%s\" that you wanted to\n", |
---|
236 | progname_without_path, file); |
---|
237 | printf(" use as %s already exists.\n", filedesc); |
---|
238 | printf(" Do you want to Replace it, Append to it,\n"); |
---|
239 | printf(" write to a new File, or Quit?\n"); |
---|
240 | loopcount2 = 0; |
---|
241 | do { |
---|
242 | printf(" (please type R, A, F, or Q) \n"); |
---|
243 | #ifdef WIN32 |
---|
244 | phyFillScreenColor(); |
---|
245 | #endif |
---|
246 | fgets(input, sizeof(input), stdin); |
---|
247 | ch = input[0]; |
---|
248 | uppercase(&ch); |
---|
249 | countup(&loopcount2, 10); |
---|
250 | } while (ch != 'A' && ch != 'R' && ch != 'F' && ch != 'Q'); |
---|
251 | if (ch == 'Q') |
---|
252 | exxit(-1); |
---|
253 | if (ch == 'A') { |
---|
254 | strcpy(filemode,"a"); |
---|
255 | continue; |
---|
256 | } |
---|
257 | else if (ch == 'F') { |
---|
258 | file[0] = '\0'; |
---|
259 | loopcount2 = 0; |
---|
260 | while (file[0] =='\0') { |
---|
261 | printf("Please enter a new file name> "); |
---|
262 | getstryng(file); |
---|
263 | countup(&loopcount2, 10); |
---|
264 | } |
---|
265 | strcpy(filemode,"w"); |
---|
266 | continue; |
---|
267 | } |
---|
268 | } |
---|
269 | of = fopen(file,filemode); |
---|
270 | if (of) |
---|
271 | break; |
---|
272 | else { |
---|
273 | switch (filemode[0]){ |
---|
274 | |
---|
275 | case 'r': |
---|
276 | printf("%s: can't find %s \"%s\"\n", progname_without_path, |
---|
277 | filedesc, file); |
---|
278 | file[0] = '\0'; |
---|
279 | loopcount2 = 0; |
---|
280 | while (file[0] =='\0'){ |
---|
281 | printf("Please enter a new file name> "); |
---|
282 | countup(&loopcount2, 10); |
---|
283 | getstryng(file);} |
---|
284 | break; |
---|
285 | |
---|
286 | case 'w': |
---|
287 | case 'a': |
---|
288 | printf("%s: can't write %s file %s\n", progname_without_path, |
---|
289 | filedesc, file); |
---|
290 | file[0] = '\0'; |
---|
291 | loopcount2 = 0; |
---|
292 | while (file[0] =='\0'){ |
---|
293 | printf("Please enter a new file name> "); |
---|
294 | countup(&loopcount2, 10); |
---|
295 | getstryng(file);} |
---|
296 | continue; |
---|
297 | default: |
---|
298 | printf("There is some error in the call of openfile. Unknown mode.\n"); |
---|
299 | exxit(-1); |
---|
300 | } |
---|
301 | } |
---|
302 | countup(&loopcount, 20); |
---|
303 | } |
---|
304 | *fp = of; |
---|
305 | if (perm != NULL) |
---|
306 | strcpy(perm,file); |
---|
307 | } /* openfile */ |
---|
308 | |
---|
309 | |
---|
310 | void cleerhome() |
---|
311 | { /* home cursor and clear screen, if possible */ |
---|
312 | printf("%s", ((ibmpc || ansi) ? ("\033[2J\033[H") : "\n\n")); |
---|
313 | } /* cleerhome */ |
---|
314 | |
---|
315 | |
---|
316 | double randum(longer seed) |
---|
317 | { /* random number generator -- slow but machine independent |
---|
318 | This is a multiplicative congruential 32-bit generator |
---|
319 | x(t+1) = 1664525 * x(t) mod 2^32, one that passes the |
---|
320 | Coveyou-Macpherson and Lehmer tests, see Knuth ACP vol. 2 */ |
---|
321 | long i, j, k, sum; |
---|
322 | longer mult, newseed; |
---|
323 | double x; |
---|
324 | |
---|
325 | mult[0] = 13; /* these four statements set the multiplier */ |
---|
326 | mult[1] = 24; /* -- they are its "digits" in a base-64 */ |
---|
327 | mult[2] = 22; /* notation: 1664525 = 13*64^3+24*64^2 */ |
---|
328 | mult[3] = 6; /* +22*64+6 */ |
---|
329 | for (i = 0; i <= 5; i++) |
---|
330 | newseed[i] = 0; |
---|
331 | for (i = 0; i <= 5; i++) { |
---|
332 | sum = newseed[i]; |
---|
333 | k = i; |
---|
334 | if (i > 3) |
---|
335 | k = 3; |
---|
336 | for (j = 0; j <= k; j++) |
---|
337 | sum += mult[j] * seed[i - j]; |
---|
338 | newseed[i] = sum; |
---|
339 | for (j = i; j <= 4; j++) { |
---|
340 | newseed[j + 1] += newseed[j] / 64; |
---|
341 | newseed[j] &= 63; |
---|
342 | } |
---|
343 | } |
---|
344 | memcpy(seed, newseed, sizeof(longer)); |
---|
345 | seed[5] &= 3; |
---|
346 | x = 0.0; |
---|
347 | for (i = 0; i <= 5; i++) |
---|
348 | x = x / 64.0 + seed[i]; |
---|
349 | x /= 4.0; |
---|
350 | return x; |
---|
351 | } /* randum */ |
---|
352 | |
---|
353 | |
---|
354 | void randumize(longer seed, long *enterorder) |
---|
355 | { /* randomize input order of species */ |
---|
356 | long i, j, k; |
---|
357 | |
---|
358 | for (i = 0; i < spp; i++) { |
---|
359 | j = (long)(randum(seed) * (i+1)); |
---|
360 | k = enterorder[j]; |
---|
361 | enterorder[j] = enterorder[i]; |
---|
362 | enterorder[i] = k; |
---|
363 | } |
---|
364 | } /* randumize */ |
---|
365 | |
---|
366 | |
---|
367 | double normrand(longer seed) |
---|
368 | {/* standardized Normal random variate */ |
---|
369 | double x; |
---|
370 | |
---|
371 | x = randum(seed)+randum(seed)+randum(seed)+randum(seed) |
---|
372 | + randum(seed)+randum(seed)+randum(seed)+randum(seed) |
---|
373 | + randum(seed)+randum(seed)+randum(seed)+randum(seed)-6.0; |
---|
374 | return(x); |
---|
375 | } /* normrand */ |
---|
376 | |
---|
377 | |
---|
378 | long readlong(const char *prompt) |
---|
379 | { /* read a long */ |
---|
380 | long res, loopcount; |
---|
381 | char string[100]; |
---|
382 | |
---|
383 | loopcount = 0; |
---|
384 | do { |
---|
385 | printf("%s",prompt); |
---|
386 | getstryng(string); |
---|
387 | if (sscanf(string,"%ld",&res) == 1) |
---|
388 | break; |
---|
389 | countup(&loopcount, 10); |
---|
390 | } while (1); |
---|
391 | return res; |
---|
392 | } /* readlong */ |
---|
393 | |
---|
394 | |
---|
395 | void uppercase(Char *ch) |
---|
396 | { /* convert ch to upper case */ |
---|
397 | *ch = (islower (*ch) ? toupper(*ch) : (*ch)); |
---|
398 | } /* uppercase */ |
---|
399 | |
---|
400 | |
---|
401 | void initseed(long *inseed, long *inseed0, longer seed) |
---|
402 | { /* input random number seed */ |
---|
403 | long i, loopcount; |
---|
404 | |
---|
405 | loopcount = 0; |
---|
406 | do { |
---|
407 | printf("Random number seed (must be odd)?\n"); |
---|
408 | scanf("%ld%*[^\n]", inseed); |
---|
409 | getchar(); |
---|
410 | countup(&loopcount, 10); |
---|
411 | } while (((*inseed) < 0) || ((*inseed) & 1) == 0); |
---|
412 | *inseed0 = *inseed; |
---|
413 | for (i = 0; i <= 5; i++) |
---|
414 | seed[i] = 0; |
---|
415 | i = 0; |
---|
416 | do { |
---|
417 | seed[i] = *inseed & 63; |
---|
418 | *inseed /= 64; |
---|
419 | i++; |
---|
420 | } while (*inseed != 0); |
---|
421 | } /*initseed*/ |
---|
422 | |
---|
423 | |
---|
424 | void initjumble(long *inseed, long *inseed0, longer seed, long *njumble) |
---|
425 | { /* input number of jumblings for jumble option */ |
---|
426 | long loopcount; |
---|
427 | |
---|
428 | initseed(inseed, inseed0, seed); |
---|
429 | loopcount = 0; |
---|
430 | do { |
---|
431 | printf("Number of times to jumble?\n"); |
---|
432 | scanf("%ld%*[^\n]", njumble); |
---|
433 | getchar(); |
---|
434 | countup(&loopcount, 10); |
---|
435 | } while ((*njumble) < 1); |
---|
436 | } /*initjumble*/ |
---|
437 | |
---|
438 | |
---|
439 | void initoutgroup(long *outgrno, long local_spp) |
---|
440 | { /* input outgroup number */ |
---|
441 | long loopcount; |
---|
442 | boolean done; |
---|
443 | |
---|
444 | loopcount = 0; |
---|
445 | do { |
---|
446 | printf("Type number of the outgroup:\n"); |
---|
447 | scanf("%ld%*[^\n]", outgrno); |
---|
448 | getchar(); |
---|
449 | done = (*outgrno >= 1 && *outgrno <= local_spp); |
---|
450 | if (!done) { |
---|
451 | printf("BAD OUTGROUP NUMBER: %ld\n", *outgrno); |
---|
452 | printf(" Must be in range 1 - %ld\n", local_spp); |
---|
453 | } |
---|
454 | countup(&loopcount, 10); |
---|
455 | } while (done != true); |
---|
456 | } /*initoutgroup*/ |
---|
457 | |
---|
458 | |
---|
459 | void initthreshold(double *threshold) |
---|
460 | { /* input threshold for threshold parsimony option */ |
---|
461 | long loopcount; |
---|
462 | boolean done; |
---|
463 | |
---|
464 | loopcount = 0; |
---|
465 | do { |
---|
466 | printf("What will be the threshold value?\n"); |
---|
467 | scanf("%lf%*[^\n]", threshold); |
---|
468 | getchar(); |
---|
469 | done = (*threshold >= 1.0); |
---|
470 | if (!done) |
---|
471 | printf("BAD THRESHOLD VALUE: it must be greater than 1\n"); |
---|
472 | else |
---|
473 | *threshold = (long)(*threshold * 10.0 + 0.5) / 10.0; |
---|
474 | countup(&loopcount, 10); |
---|
475 | } while (done != true); |
---|
476 | } /*initthreshold*/ |
---|
477 | |
---|
478 | |
---|
479 | void initcatn(long *categs) |
---|
480 | { /* initialize category number for rate categories */ |
---|
481 | long loopcount; |
---|
482 | |
---|
483 | loopcount = 0; |
---|
484 | do { |
---|
485 | printf("Number of categories (1-%d)?\n", maxcategs); |
---|
486 | scanf("%ld%*[^\n]", categs); |
---|
487 | getchar(); |
---|
488 | countup(&loopcount, 10); |
---|
489 | } while (*categs > maxcategs || *categs < 1); |
---|
490 | } /*initcatn*/ |
---|
491 | |
---|
492 | |
---|
493 | void initcategs(long categs, double *rate) |
---|
494 | { /* initialize category rates for HMM rates */ |
---|
495 | long i, loopcount, scanned; |
---|
496 | char line[100], rest[100]; |
---|
497 | boolean done; |
---|
498 | |
---|
499 | loopcount = 0; |
---|
500 | for (;;){ |
---|
501 | printf("Rate for each category? (use a space to separate)\n"); |
---|
502 | getstryng(line); |
---|
503 | done = true; |
---|
504 | for (i = 0; i < categs; i++){ |
---|
505 | scanned = sscanf(line,"%lf %[^\n]", &rate[i],rest); |
---|
506 | if ((scanned < 2 && i < (categs - 1)) || |
---|
507 | (scanned < 1 && i == (categs - 1))){ |
---|
508 | printf("Please enter exactly %ld values.\n",categs); |
---|
509 | done = false; |
---|
510 | break; |
---|
511 | } |
---|
512 | strcpy(line,rest); |
---|
513 | } |
---|
514 | if (done) |
---|
515 | break; |
---|
516 | countup(&loopcount, 100); |
---|
517 | } |
---|
518 | } /*initcategs*/ |
---|
519 | |
---|
520 | |
---|
521 | void initprobcat(long categs, double *probsum, double *probcat) |
---|
522 | { /* input probabilities of rate categores for HMM rates */ |
---|
523 | long i, loopcount, scanned; |
---|
524 | boolean done; |
---|
525 | char line[100], rest[100]; |
---|
526 | |
---|
527 | loopcount = 0; |
---|
528 | do { |
---|
529 | printf("Probability for each category?"); |
---|
530 | printf(" (use a space to separate)\n"); |
---|
531 | getstryng(line); |
---|
532 | done = true; |
---|
533 | for (i = 0; i < categs; i++){ |
---|
534 | scanned = sscanf(line,"%lf %[^\n]",&probcat[i],rest); |
---|
535 | if ((scanned < 2 && i < (categs - 1)) || |
---|
536 | (scanned < 1 && i == (categs - 1))){ |
---|
537 | done = false; |
---|
538 | printf("Please enter exactly %ld values.\n",categs); |
---|
539 | break;} |
---|
540 | strcpy(line,rest); |
---|
541 | } |
---|
542 | if (!done) |
---|
543 | continue; |
---|
544 | *probsum = 0.0; |
---|
545 | for (i = 0; i < categs; i++) |
---|
546 | *probsum += probcat[i]; |
---|
547 | if (fabs(1.0 - (*probsum)) > 0.001) { |
---|
548 | done = false; |
---|
549 | printf("Probabilities must add up to"); |
---|
550 | printf(" 1.0, plus or minus 0.001.\n"); |
---|
551 | } |
---|
552 | countup(&loopcount, 100); |
---|
553 | } while (!done); |
---|
554 | } /*initprobcat*/ |
---|
555 | |
---|
556 | |
---|
557 | void lgr(long m, double b, raterootarray lgroot) |
---|
558 | { /* For use by initgammacat. Get roots of m-th Generalized Laguerre |
---|
559 | polynomial, given roots of (m-1)-th, these are to be |
---|
560 | stored in lgroot[m][] */ |
---|
561 | long i; |
---|
562 | double upper, lower, x, y; |
---|
563 | boolean dwn; /* is function declining in this interval? */ |
---|
564 | |
---|
565 | if (m == 1) { |
---|
566 | lgroot[1][1] = 1.0+b; |
---|
567 | } else { |
---|
568 | dwn = true; |
---|
569 | for (i=1; i<=m; i++) { |
---|
570 | if (i < m) { |
---|
571 | if (i == 1) |
---|
572 | lower = 0.0; |
---|
573 | else |
---|
574 | lower = lgroot[m-1][i-1]; |
---|
575 | upper = lgroot[m-1][i]; |
---|
576 | } else { /* i == m, must search above */ |
---|
577 | lower = lgroot[m-1][i-1]; |
---|
578 | x = lgroot[m-1][m-1]; |
---|
579 | do { |
---|
580 | x = 2.0*x; |
---|
581 | y = glaguerre(m, b,x); |
---|
582 | } while ((dwn && (y > 0.0)) || ((!dwn) && (y < 0.0))); |
---|
583 | upper = x; |
---|
584 | } |
---|
585 | while (upper-lower > 0.000000001) { |
---|
586 | x = (upper+lower)/2.0; |
---|
587 | if (glaguerre(m, b, x) > 0.0) { |
---|
588 | if (dwn) |
---|
589 | lower = x; |
---|
590 | else |
---|
591 | upper = x; |
---|
592 | } else { |
---|
593 | if (dwn) |
---|
594 | upper = x; |
---|
595 | else |
---|
596 | lower = x; |
---|
597 | } |
---|
598 | } |
---|
599 | lgroot[m][i] = (lower+upper)/2.0; |
---|
600 | dwn = !dwn; /* switch for next one */ |
---|
601 | } |
---|
602 | } |
---|
603 | } /* lgr */ |
---|
604 | |
---|
605 | |
---|
606 | double logfac (long n) |
---|
607 | { /* log(n!) values were calculated with Mathematica |
---|
608 | with a precision of 30 digits */ |
---|
609 | long i; |
---|
610 | double x; |
---|
611 | |
---|
612 | switch (n) |
---|
613 | { |
---|
614 | case 0: |
---|
615 | return 0.; |
---|
616 | case 1: |
---|
617 | return 0.; |
---|
618 | case 2: |
---|
619 | return 0.693147180559945309417232121458; |
---|
620 | case 3: |
---|
621 | return 1.791759469228055000812477358381; |
---|
622 | case 4: |
---|
623 | return 3.1780538303479456196469416013; |
---|
624 | case 5: |
---|
625 | return 4.78749174278204599424770093452; |
---|
626 | case 6: |
---|
627 | return 6.5792512120101009950601782929; |
---|
628 | case 7: |
---|
629 | return 8.52516136106541430016553103635; |
---|
630 | case 8: |
---|
631 | return 10.60460290274525022841722740072; |
---|
632 | case 9: |
---|
633 | return 12.80182748008146961120771787457; |
---|
634 | case 10: |
---|
635 | return 15.10441257307551529522570932925; |
---|
636 | case 11: |
---|
637 | return 17.50230784587388583928765290722; |
---|
638 | case 12: |
---|
639 | return 19.98721449566188614951736238706; |
---|
640 | default: |
---|
641 | x = 19.98721449566188614951736238706; |
---|
642 | for (i = 13; i <= n; i++) |
---|
643 | x += log(i); |
---|
644 | return x; |
---|
645 | } |
---|
646 | } |
---|
647 | |
---|
648 | |
---|
649 | double glaguerre(long m, double b, double x) |
---|
650 | { /* Generalized Laguerre polynomial computed recursively. |
---|
651 | For use by initgammacat */ |
---|
652 | long i; |
---|
653 | double local_gln, glnm1, glnp1; /* L_n, L_(n-1), L_(n+1) */ |
---|
654 | |
---|
655 | if (m == 0) |
---|
656 | return 1.0; |
---|
657 | else { |
---|
658 | if (m == 1) |
---|
659 | return 1.0 + b - x; |
---|
660 | else { |
---|
661 | local_gln = 1.0+b-x; |
---|
662 | glnm1 = 1.0; |
---|
663 | for (i=2; i <= m; i++) { |
---|
664 | glnp1 = ((2*(i-1)+b+1.0-x)*local_gln - (i-1+b)*glnm1)/i; |
---|
665 | glnm1 = local_gln; |
---|
666 | local_gln = glnp1; |
---|
667 | } |
---|
668 | return local_gln; |
---|
669 | } |
---|
670 | } |
---|
671 | } /* glaguerre */ |
---|
672 | |
---|
673 | |
---|
674 | void initlaguerrecat(long categs, double alpha, double *rate, double *probcat) |
---|
675 | { /* calculate rates and probabilities to approximate Gamma distribution |
---|
676 | of rates with "categs" categories and shape parameter "alpha" using |
---|
677 | rates and weights from Generalized Laguerre quadrature */ |
---|
678 | long i; |
---|
679 | raterootarray lgroot; /* roots of GLaguerre polynomials */ |
---|
680 | double f, x, xi, y; |
---|
681 | |
---|
682 | alpha = alpha - 1.0; |
---|
683 | lgroot[1][1] = 1.0+alpha; |
---|
684 | for (i = 2; i <= categs; i++) |
---|
685 | lgr(i, alpha, lgroot); /* get roots for L^(a)_n */ |
---|
686 | /* here get weights */ |
---|
687 | /* Gamma weights are (1+a)(1+a/2) ... (1+a/n)*x_i/((n+1)^2 [L_{n+1}^a(x_i)]^2) */ |
---|
688 | f = 1; |
---|
689 | for (i = 1; i <= categs; i++) |
---|
690 | f *= (1.0+alpha/i); |
---|
691 | for (i = 1; i <= categs; i++) { |
---|
692 | xi = lgroot[categs][i]; |
---|
693 | y = glaguerre(categs+1, alpha, xi); |
---|
694 | x = f*xi/((categs+1)*(categs+1)*y*y); |
---|
695 | rate[i-1] = xi/(1.0+alpha); |
---|
696 | probcat[i-1] = x; |
---|
697 | } |
---|
698 | } /* initlaguerrecat */ |
---|
699 | |
---|
700 | |
---|
701 | double hermite(long n, double x) |
---|
702 | { /* calculates hermite polynomial with degree n and parameter x */ |
---|
703 | /* seems to be unprecise for n>13 -> root finder does not converge*/ |
---|
704 | double h1 = 1.; |
---|
705 | double h2 = 2. * x; |
---|
706 | double xx = 2. * x; |
---|
707 | long i; |
---|
708 | |
---|
709 | for (i = 1; i < n; i++) { |
---|
710 | xx = 2. * x * h2 - 2. * (i) * h1; |
---|
711 | h1 = h2; |
---|
712 | h2 = xx; |
---|
713 | } |
---|
714 | return xx; |
---|
715 | } /* hermite */ |
---|
716 | |
---|
717 | |
---|
718 | void root_hermite(long n, double *hroot) |
---|
719 | { /* find roots of Hermite polynmials */ |
---|
720 | long z; |
---|
721 | long ii; |
---|
722 | long start; |
---|
723 | |
---|
724 | if (n % 2 == 0) { |
---|
725 | start = n/2; |
---|
726 | z = 1; |
---|
727 | } else { |
---|
728 | start = n/2 + 1; |
---|
729 | z=2; |
---|
730 | hroot[start-1] = 0.0; |
---|
731 | } |
---|
732 | for (ii = start; ii < n; ii++) { /* search only upwards*/ |
---|
733 | hroot[ii] = halfroot(hermite,n,hroot[ii-1]+EPSILON, 1./n); |
---|
734 | hroot[start - z] = -hroot[ii]; |
---|
735 | z++; |
---|
736 | } |
---|
737 | } /* root_hermite */ |
---|
738 | |
---|
739 | |
---|
740 | double halfroot(double (*func)(long m, double x), long n, double startx, |
---|
741 | double delta) |
---|
742 | { /* searches from the bound (startx) only in one direction |
---|
743 | (by positive or negative delta, which results in |
---|
744 | other-bound=startx+delta) |
---|
745 | delta should be small. |
---|
746 | (*func) is a function with two arguments */ |
---|
747 | double xl; |
---|
748 | double xu; |
---|
749 | double xm; |
---|
750 | double fu; |
---|
751 | double fl; |
---|
752 | double fm = 100000.; |
---|
753 | double gradient; |
---|
754 | boolean dwn; |
---|
755 | |
---|
756 | /* decide if we search above or below startx and escapes to trace back |
---|
757 | to the starting point that most often will be |
---|
758 | the root from the previous calculation */ |
---|
759 | if (delta < 0) { |
---|
760 | xu = startx; |
---|
761 | xl = xu + delta; |
---|
762 | } else { |
---|
763 | xl = startx; |
---|
764 | xu = xl + delta; |
---|
765 | } |
---|
766 | delta = fabs(delta); |
---|
767 | fu = (*func)(n, xu); |
---|
768 | fl = (*func)(n, xl); |
---|
769 | gradient = (fl-fu)/(xl-xu); |
---|
770 | while(fabs(fm) > EPSILON) { /* is root outside of our bracket?*/ |
---|
771 | if ((fu<0.0 && fl<0.0) || (fu>0.0 && fl > 0.0)) { |
---|
772 | xu += delta; |
---|
773 | fu = (*func)(n, xu); |
---|
774 | fl = (*func)(n, xl); |
---|
775 | gradient = (fl-fu)/(xl-xu); |
---|
776 | dwn = (gradient < 0.0) ? true : false; |
---|
777 | } else { |
---|
778 | xm = xl - fl / gradient; |
---|
779 | fm = (*func)(n, xm); |
---|
780 | if (dwn) { |
---|
781 | if (fm > 0.) { |
---|
782 | xl = xm; |
---|
783 | fl = fm; |
---|
784 | } else { |
---|
785 | xu = xm; |
---|
786 | fu = fm; |
---|
787 | } |
---|
788 | } else { |
---|
789 | if (fm > 0.) { |
---|
790 | xu = xm; |
---|
791 | fu = fm; |
---|
792 | } else { |
---|
793 | xl = xm; |
---|
794 | fl = fm; |
---|
795 | } |
---|
796 | } |
---|
797 | gradient = (fl-fu)/(xl-xu); |
---|
798 | } |
---|
799 | } |
---|
800 | return xm; |
---|
801 | } /* halfroot */ |
---|
802 | |
---|
803 | |
---|
804 | void hermite_weight(long n, double * hroot, double * weights) |
---|
805 | { |
---|
806 | /* calculate the weights for the hermite polynomial at the roots |
---|
807 | using formula Abramowitz and Stegun chapter 25.4.46 p.890 */ |
---|
808 | long i; |
---|
809 | double hr2; |
---|
810 | double numerator; |
---|
811 | |
---|
812 | numerator = exp(0.6931471805599 * ( n-1.) + logfac(n)) / (n*n); |
---|
813 | for (i = 0; i < n; i++) { |
---|
814 | hr2 = hermite(n-1, hroot[i]); |
---|
815 | weights[i] = numerator / (hr2*hr2); |
---|
816 | } |
---|
817 | } /* hermiteweight */ |
---|
818 | |
---|
819 | |
---|
820 | void inithermitcat(long categs, double alpha, double *rate, double *probcat) |
---|
821 | { /* calculates rates and probabilities */ |
---|
822 | long i; |
---|
823 | double *hroot; |
---|
824 | double std; |
---|
825 | |
---|
826 | std = SQRT2 /sqrt(alpha); |
---|
827 | hroot = (double *) Malloc((categs+1) * sizeof(double)); |
---|
828 | root_hermite(categs, hroot); /* calculate roots */ |
---|
829 | hermite_weight(categs, hroot, probcat); /* set weights */ |
---|
830 | for (i=0; i<categs; i++) { /* set rates */ |
---|
831 | rate[i] = 1.0 + std * hroot[i]; |
---|
832 | probcat[i] = probcat[i]; |
---|
833 | } |
---|
834 | free(hroot); |
---|
835 | } /* inithermitcat */ |
---|
836 | |
---|
837 | |
---|
838 | void initgammacat (long categs, double alpha, double *rate, double *probcat) |
---|
839 | { /* calculate rates and probabilities to approximate Gamma distribution |
---|
840 | of rates with "categs" categories and shape parameter "alpha" using |
---|
841 | rates and weights from Generalized Laguerre quadrature or from |
---|
842 | Hermite quadrature */ |
---|
843 | |
---|
844 | if (alpha >= 100.0) |
---|
845 | inithermitcat(categs, alpha, rate, probcat); |
---|
846 | else |
---|
847 | initlaguerrecat(categs, alpha, rate, probcat); |
---|
848 | } /* initgammacat */ |
---|
849 | |
---|
850 | |
---|
851 | void inithowmany(long *howmany, long howoften) |
---|
852 | {/* input how many cycles */ |
---|
853 | long loopcount; |
---|
854 | |
---|
855 | loopcount = 0; |
---|
856 | do { |
---|
857 | printf("How many cycles of %4ld trees?\n", howoften); |
---|
858 | scanf("%ld%*[^\n]", howmany); |
---|
859 | getchar(); |
---|
860 | countup(&loopcount, 10); |
---|
861 | } while (*howmany <= 0); |
---|
862 | } /*inithowmany*/ |
---|
863 | |
---|
864 | |
---|
865 | |
---|
866 | void inithowoften(long *howoften) |
---|
867 | { /* input how many trees per cycle */ |
---|
868 | long loopcount; |
---|
869 | |
---|
870 | loopcount = 0; |
---|
871 | do { |
---|
872 | printf("How many trees per cycle?\n"); |
---|
873 | scanf("%ld%*[^\n]", howoften); |
---|
874 | getchar(); |
---|
875 | countup(&loopcount, 10); |
---|
876 | } while (*howoften <= 0); |
---|
877 | } /*inithowoften*/ |
---|
878 | |
---|
879 | |
---|
880 | void initlambda(double *lambda) |
---|
881 | { /* input patch length parameter for autocorrelated HMM rates */ |
---|
882 | long loopcount; |
---|
883 | |
---|
884 | loopcount = 0; |
---|
885 | do { |
---|
886 | printf("Mean block length of sites having the same rate (greater than 1)?\n"); |
---|
887 | scanf("%lf%*[^\n]", lambda); |
---|
888 | getchar(); |
---|
889 | countup(&loopcount, 10); |
---|
890 | } while (*lambda <= 1.0); |
---|
891 | *lambda = 1.0 / *lambda; |
---|
892 | } /*initlambda*/ |
---|
893 | |
---|
894 | |
---|
895 | void initfreqs(double *freqa, double *freqc, double *freqg, double *freqt) |
---|
896 | { /* input frequencies of the four bases */ |
---|
897 | char input[100]; |
---|
898 | long scanned, loopcount; |
---|
899 | |
---|
900 | printf("Base frequencies for A, C, G, T/U (use blanks to separate)?\n"); |
---|
901 | loopcount = 0; |
---|
902 | do { |
---|
903 | getstryng(input); |
---|
904 | scanned = sscanf(input,"%lf%lf%lf%lf%*[^\n]", freqa, freqc, freqg, freqt); |
---|
905 | if (scanned == 4) |
---|
906 | break; |
---|
907 | else |
---|
908 | printf("Please enter exactly 4 values.\n"); |
---|
909 | countup(&loopcount, 100); |
---|
910 | } while (1); |
---|
911 | } /* initfreqs */ |
---|
912 | |
---|
913 | |
---|
914 | void initratio(double *ttratio) |
---|
915 | { /* input transition/transversion ratio */ |
---|
916 | long loopcount; |
---|
917 | |
---|
918 | loopcount = 0; |
---|
919 | do { |
---|
920 | printf("Transition/transversion ratio?\n"); |
---|
921 | scanf("%lf%*[^\n]", ttratio); |
---|
922 | getchar(); |
---|
923 | countup(&loopcount, 10); |
---|
924 | } while (*ttratio < 0.0); |
---|
925 | } /* initratio */ |
---|
926 | |
---|
927 | |
---|
928 | void initpower(double *power) |
---|
929 | { |
---|
930 | printf("New power?\n"); |
---|
931 | scanf("%lf%*[^\n]", power); |
---|
932 | getchar(); |
---|
933 | } /*initpower*/ |
---|
934 | |
---|
935 | |
---|
936 | void initdatasets(long *datasets) |
---|
937 | { |
---|
938 | /* handle multi-data set option */ |
---|
939 | long loopcount; |
---|
940 | boolean done; |
---|
941 | |
---|
942 | loopcount = 0; |
---|
943 | do { |
---|
944 | printf("How many data sets?\n"); |
---|
945 | scanf("%ld%*[^\n]", datasets); |
---|
946 | getchar(); |
---|
947 | done = (*datasets > 1); |
---|
948 | if (!done) |
---|
949 | printf("Bad data sets number: it must be greater than 1\n"); |
---|
950 | countup(&loopcount, 10); |
---|
951 | } while (!done); |
---|
952 | } /* initdatasets */ |
---|
953 | |
---|
954 | |
---|
955 | void justweights(long *datasets) |
---|
956 | { |
---|
957 | /* handle multi-data set option by weights */ |
---|
958 | long loopcount; |
---|
959 | boolean done; |
---|
960 | |
---|
961 | loopcount = 0; |
---|
962 | do { |
---|
963 | printf("How many sets of weights?\n"); |
---|
964 | scanf("%ld%*[^\n]", datasets); |
---|
965 | getchar(); |
---|
966 | done = (*datasets >= 1); |
---|
967 | if (!done) |
---|
968 | printf("BAD NUMBER: it must be greater than 1\n"); |
---|
969 | countup(&loopcount, 10); |
---|
970 | } while (!done); |
---|
971 | } /* justweights */ |
---|
972 | |
---|
973 | |
---|
974 | void initterminal(boolean *local_ibmpc, boolean *local_ansi) |
---|
975 | { |
---|
976 | /* handle terminal option */ |
---|
977 | if (*local_ibmpc) { |
---|
978 | *local_ibmpc = false; |
---|
979 | *local_ansi = true; |
---|
980 | } else if (*local_ansi) |
---|
981 | *local_ansi = false; |
---|
982 | else |
---|
983 | *local_ibmpc = true; |
---|
984 | } /*initterminal*/ |
---|
985 | |
---|
986 | |
---|
987 | void initnumlines(long *screenlines) |
---|
988 | { |
---|
989 | long loopcount; |
---|
990 | |
---|
991 | loopcount = 0; |
---|
992 | do { |
---|
993 | *screenlines = readlong("Number of lines on screen?\n"); |
---|
994 | countup(&loopcount, 10); |
---|
995 | } while (*screenlines <= 12); |
---|
996 | } /*initnumlines*/ |
---|
997 | |
---|
998 | |
---|
999 | void initbestrees(bestelm *bestrees, long maxtrees, boolean glob) |
---|
1000 | { |
---|
1001 | /* initializes either global or local field of each array in bestrees */ |
---|
1002 | long i; |
---|
1003 | |
---|
1004 | if (glob) |
---|
1005 | for (i = 0; i < maxtrees; i++) |
---|
1006 | bestrees[i].gloreange = false; |
---|
1007 | else |
---|
1008 | for (i = 0; i < maxtrees; i++) |
---|
1009 | bestrees[i].locreange = false; |
---|
1010 | } /* initbestrees */ |
---|
1011 | |
---|
1012 | |
---|
1013 | void newline(FILE *filename, long i, long j, long k) |
---|
1014 | { |
---|
1015 | /* go to new line if i is a multiple of j, indent k spaces */ |
---|
1016 | long m; |
---|
1017 | |
---|
1018 | if ((i - 1) % j != 0 || i <= 1) |
---|
1019 | return; |
---|
1020 | putc('\n', filename); |
---|
1021 | for (m = 1; m <= k; m++) |
---|
1022 | putc(' ', filename); |
---|
1023 | } /* newline */ |
---|
1024 | |
---|
1025 | void inputnumbersold(long *local_spp, long *chars, long *nonodes, long n) |
---|
1026 | { |
---|
1027 | /* input the numbers of species and of characters */ |
---|
1028 | |
---|
1029 | if (fscanf(infile, "%ld%ld", local_spp, chars) != 2 || *local_spp <= 0 || *chars <= 0) { |
---|
1030 | printf( |
---|
1031 | "ERROR: Unable to read the number of species or characters in data set\n"); |
---|
1032 | printf( |
---|
1033 | "The input file is incorrect (perhaps it was not saved text only).\n"); |
---|
1034 | } |
---|
1035 | *nonodes = *local_spp * 2 - n; |
---|
1036 | } /* inputnumbersold */ |
---|
1037 | |
---|
1038 | |
---|
1039 | |
---|
1040 | void inputnumbers(long *local_spp, long *chars, long *nonodes, long n) |
---|
1041 | { |
---|
1042 | /* input the numbers of species and of characters */ |
---|
1043 | |
---|
1044 | if (fscanf(infile, "%ld%ld", local_spp, chars) != 2 || *local_spp <= 0 || *chars <= 0) { |
---|
1045 | printf( |
---|
1046 | "ERROR: Unable to read the number of species or characters in data set\n"); |
---|
1047 | printf( |
---|
1048 | "The input file is incorrect (perhaps it was not saved text only).\n"); |
---|
1049 | } |
---|
1050 | fscanf(infile, "%*[^\n]"); |
---|
1051 | *nonodes = *local_spp * 2 - n; |
---|
1052 | } /* inputnumbers */ |
---|
1053 | |
---|
1054 | |
---|
1055 | void inputnumbers2(long *local_spp, long *nonodes, long n) |
---|
1056 | { |
---|
1057 | /* read species number */ |
---|
1058 | |
---|
1059 | if (fscanf(infile, "%ld", local_spp) != 1 || *local_spp <= 0) { |
---|
1060 | printf("ERROR: Unable to read the number of species in data set\n"); |
---|
1061 | printf( |
---|
1062 | "The input file is incorrect (perhaps it was not saved text only).\n"); |
---|
1063 | } |
---|
1064 | fscanf(infile, "%*[^\n]"); |
---|
1065 | fprintf(outfile, "\n%4ld Populations\n", *local_spp); |
---|
1066 | *nonodes = *local_spp * 2 - n; |
---|
1067 | } /* inputnumbers2 */ |
---|
1068 | |
---|
1069 | |
---|
1070 | void inputnumbers3(long *local_spp, long *chars) |
---|
1071 | { |
---|
1072 | /* input the numbers of species and of characters */ |
---|
1073 | |
---|
1074 | if (fscanf(infile, "%ld%ld", local_spp, chars) != 2 || *local_spp <= 0 || *chars <= 0) { |
---|
1075 | printf( |
---|
1076 | "ERROR: Unable to read the number of species or characters in data set\n"); |
---|
1077 | printf( |
---|
1078 | "The input file is incorrect (perhaps it was not saved text only).\n"); |
---|
1079 | exxit(-1); |
---|
1080 | } |
---|
1081 | } /* inputnumbers3 */ |
---|
1082 | |
---|
1083 | |
---|
1084 | void samenumsp(long *chars, long ith) |
---|
1085 | { |
---|
1086 | /* check if spp is same as the first set in other data sets */ |
---|
1087 | long cursp, curchs; |
---|
1088 | |
---|
1089 | if (eoln(infile)) |
---|
1090 | scan_eoln(infile); |
---|
1091 | fscanf(infile, "%ld%ld", &cursp, &curchs); |
---|
1092 | if (cursp != spp) { |
---|
1093 | printf( |
---|
1094 | "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith); |
---|
1095 | exxit(-1); |
---|
1096 | } |
---|
1097 | *chars = curchs; |
---|
1098 | } /* samenumsp */ |
---|
1099 | |
---|
1100 | |
---|
1101 | void samenumsp2(long ith) |
---|
1102 | { |
---|
1103 | /* check if spp is same as the first set in other data sets */ |
---|
1104 | long cursp; |
---|
1105 | |
---|
1106 | if (eoln(infile)) |
---|
1107 | scan_eoln(infile); |
---|
1108 | if (fscanf(infile, "%ld", &cursp) != 1) { |
---|
1109 | printf("\n\nERROR: Unable to read number of species in data set %ld\n", |
---|
1110 | ith); |
---|
1111 | printf( |
---|
1112 | "The input file is incorrect (perhaps it was not saved text only).\n"); |
---|
1113 | exxit(-1); |
---|
1114 | } |
---|
1115 | if (cursp != spp) { |
---|
1116 | printf( |
---|
1117 | "\n\nERROR: Inconsistent number of species in data set %ld\n\n", ith); |
---|
1118 | exxit(-1); |
---|
1119 | } |
---|
1120 | } /* samenumsp2 */ |
---|
1121 | |
---|
1122 | |
---|
1123 | void readoptions(long *extranum, const char *options) |
---|
1124 | { /* read option characters from input file */ |
---|
1125 | Char ch; |
---|
1126 | |
---|
1127 | while (!(eoln(infile))) { |
---|
1128 | ch = gettc(infile); |
---|
1129 | uppercase(&ch); |
---|
1130 | if (strchr(options, ch) != NULL) |
---|
1131 | (* extranum)++; |
---|
1132 | else if (!(ch == ' ' || ch == '\t')) { |
---|
1133 | printf("BAD OPTION CHARACTER: %c\n", ch); |
---|
1134 | exxit(-1); |
---|
1135 | } |
---|
1136 | } |
---|
1137 | scan_eoln(infile); |
---|
1138 | } /* readoptions */ |
---|
1139 | |
---|
1140 | |
---|
1141 | void matchoptions(Char *ch, const char *options) |
---|
1142 | { /* match option characters to those in auxiliary options line */ |
---|
1143 | |
---|
1144 | *ch = gettc(infile); |
---|
1145 | uppercase(ch); |
---|
1146 | if (strchr(options, *ch) == NULL) { |
---|
1147 | printf("ERROR: Incorrect auxiliary options line"); |
---|
1148 | printf(" which starts with %c\n", *ch); |
---|
1149 | exxit(-1); |
---|
1150 | } |
---|
1151 | } /* matchoptions */ |
---|
1152 | |
---|
1153 | |
---|
1154 | void inputweightsold(long chars, steptr weight, boolean *weights) |
---|
1155 | { |
---|
1156 | Char ch; |
---|
1157 | int i; |
---|
1158 | |
---|
1159 | for (i = 1; i < nmlngth ; i++) |
---|
1160 | getc(infile); |
---|
1161 | |
---|
1162 | for (i = 0; i < chars; i++) { |
---|
1163 | do { |
---|
1164 | if (eoln(infile)) |
---|
1165 | scan_eoln(infile); |
---|
1166 | ch = gettc(infile); |
---|
1167 | if (ch == '\n') |
---|
1168 | ch = ' '; |
---|
1169 | } while (ch == ' '); |
---|
1170 | weight[i] = 1; |
---|
1171 | if (isdigit(ch)) |
---|
1172 | weight[i] = ch - '0'; |
---|
1173 | else if (isalpha(ch)) { |
---|
1174 | uppercase(&ch); |
---|
1175 | weight[i] = ch - 'A' + 10; |
---|
1176 | } else { |
---|
1177 | printf("\n\nERROR: Bad weight character: %c\n\n", ch); |
---|
1178 | exxit(-1); |
---|
1179 | } |
---|
1180 | } |
---|
1181 | scan_eoln(infile); |
---|
1182 | *weights = true; |
---|
1183 | } /*inputweightsold*/ |
---|
1184 | |
---|
1185 | void inputweights(long chars, steptr weight, boolean *weights) |
---|
1186 | { |
---|
1187 | /* input the character weights, 0-9 and A-Z for weights 0 - 35 */ |
---|
1188 | Char ch; |
---|
1189 | long i; |
---|
1190 | |
---|
1191 | for (i = 0; i < chars; i++) { |
---|
1192 | do { |
---|
1193 | if (eoln(weightfile)) |
---|
1194 | scan_eoln(weightfile); |
---|
1195 | ch = gettc(weightfile); |
---|
1196 | if (ch == '\n') |
---|
1197 | ch = ' '; |
---|
1198 | } while (ch == ' '); |
---|
1199 | weight[i] = 1; |
---|
1200 | if (isdigit(ch)) |
---|
1201 | weight[i] = ch - '0'; |
---|
1202 | else if (isalpha(ch)) { |
---|
1203 | uppercase(&ch); |
---|
1204 | weight[i] = ch - 'A' + 10; |
---|
1205 | } else { |
---|
1206 | printf("\n\nERROR: Bad weight character: %c\n\n", ch); |
---|
1207 | exxit(-1); |
---|
1208 | } |
---|
1209 | } |
---|
1210 | scan_eoln(weightfile); |
---|
1211 | *weights = true; |
---|
1212 | } /* inputweights */ |
---|
1213 | |
---|
1214 | |
---|
1215 | void inputweights2(long a, long b, long *weightsum, |
---|
1216 | steptr weight, boolean *weights, const char *prog) |
---|
1217 | { |
---|
1218 | /* input the character weights, 0 or 1 */ |
---|
1219 | Char ch; |
---|
1220 | long i; |
---|
1221 | |
---|
1222 | *weightsum = 0; |
---|
1223 | for (i = a; i < b; i++) { |
---|
1224 | do { |
---|
1225 | if (eoln(weightfile)) |
---|
1226 | scan_eoln(weightfile); |
---|
1227 | ch = gettc(weightfile); |
---|
1228 | } while (ch == ' '); |
---|
1229 | weight[i] = 1; |
---|
1230 | if (ch == '0' || ch == '1') |
---|
1231 | weight[i] = ch - '0'; |
---|
1232 | else { |
---|
1233 | printf("\n\nERROR: Bad weight character: %c -- ", ch); |
---|
1234 | printf("weights in %s must be 0 or 1\n", prog); |
---|
1235 | exxit(-1); |
---|
1236 | } |
---|
1237 | *weightsum += weight[i]; |
---|
1238 | } |
---|
1239 | *weights = true; |
---|
1240 | scan_eoln(weightfile); |
---|
1241 | } /* inputweights2 */ |
---|
1242 | |
---|
1243 | |
---|
1244 | void printweights(FILE *filename, long inc, long chars, |
---|
1245 | steptr weight, const char *letters) |
---|
1246 | { |
---|
1247 | /* print out the weights of sites */ |
---|
1248 | long i, j; |
---|
1249 | boolean letterweights; |
---|
1250 | |
---|
1251 | letterweights = false; |
---|
1252 | for (i = 0; i < chars; i++) |
---|
1253 | if (weight[i] > 9) |
---|
1254 | letterweights = true; |
---|
1255 | fprintf(filename, "\n %s are weighted as follows:",letters); |
---|
1256 | if (letterweights) |
---|
1257 | fprintf(filename, " (A = 10, B = 11, etc.)\n"); |
---|
1258 | else |
---|
1259 | putc('\n', filename); |
---|
1260 | for (i = 0; i < chars; i++) { |
---|
1261 | if (i % 60 == 0) { |
---|
1262 | putc('\n', filename); |
---|
1263 | for (j = 1; j <= nmlngth + 3; j++) |
---|
1264 | putc(' ', filename); |
---|
1265 | } |
---|
1266 | if (weight[i+inc] < 10) |
---|
1267 | fprintf(filename, "%ld", weight[i + inc]); |
---|
1268 | else |
---|
1269 | fprintf(filename, "%c", 'A'-10+(int)weight[i + inc]); |
---|
1270 | if ((i+1) % 5 == 0 && (i+1) % 60 != 0) |
---|
1271 | putc(' ', filename); |
---|
1272 | } |
---|
1273 | fprintf(filename, "\n\n"); |
---|
1274 | } /* printweights */ |
---|
1275 | |
---|
1276 | |
---|
1277 | void inputcategs(long a, long b, steptr category, long categs,const char *prog) |
---|
1278 | { |
---|
1279 | /* input the categories, 1-9 */ |
---|
1280 | Char ch; |
---|
1281 | long i; |
---|
1282 | |
---|
1283 | for (i = a; i < b; i++) { |
---|
1284 | do { |
---|
1285 | if (eoln(catfile)) |
---|
1286 | scan_eoln(catfile); |
---|
1287 | ch = gettc(catfile); |
---|
1288 | } while (ch == ' '); |
---|
1289 | if ((ch >= '1') && (ch <= ('0'+categs))) |
---|
1290 | category[i] = ch - '0'; |
---|
1291 | else { |
---|
1292 | printf("\n\nERROR: Bad category character: %c", ch); |
---|
1293 | printf(" -- categories in %s are currently 1-%ld\n", prog, categs); |
---|
1294 | exxit(-1); |
---|
1295 | } |
---|
1296 | } |
---|
1297 | scan_eoln(catfile); |
---|
1298 | } /* inputcategs */ |
---|
1299 | |
---|
1300 | |
---|
1301 | void printcategs(FILE *filename, long chars, steptr category, |
---|
1302 | const char *letters) |
---|
1303 | { |
---|
1304 | /* print out the sitewise categories */ |
---|
1305 | long i, j; |
---|
1306 | |
---|
1307 | fprintf(filename, "\n %s are:\n",letters); |
---|
1308 | for (i = 0; i < chars; i++) { |
---|
1309 | if (i % 60 == 0) { |
---|
1310 | putc('\n', filename); |
---|
1311 | for (j = 1; j <= nmlngth + 3; j++) |
---|
1312 | putc(' ', filename); |
---|
1313 | } |
---|
1314 | fprintf(filename, "%ld", category[i]); |
---|
1315 | if ((i+1) % 10 == 0 && (i+1) % 60 != 0) |
---|
1316 | putc(' ', filename); |
---|
1317 | } |
---|
1318 | fprintf(filename, "\n\n"); |
---|
1319 | } /* printcategs */ |
---|
1320 | |
---|
1321 | |
---|
1322 | void inputfactors(long chars, Char *factor, boolean *factors) |
---|
1323 | { |
---|
1324 | /* reads the factor symbols */ |
---|
1325 | long i; |
---|
1326 | |
---|
1327 | for (i = 1; i < nmlngth; i++) |
---|
1328 | gettc(infile); |
---|
1329 | for (i = 0; i < (chars); i++) { |
---|
1330 | if (eoln(infile)) |
---|
1331 | scan_eoln(infile); |
---|
1332 | factor[i] = gettc(infile); |
---|
1333 | if (factor[i] == '\n') |
---|
1334 | factor[i] = ' '; |
---|
1335 | } |
---|
1336 | scan_eoln(infile); |
---|
1337 | *factors = true; |
---|
1338 | } /* inputfactors */ |
---|
1339 | |
---|
1340 | void inputfactorsnew(long chars, Char *factor, boolean *factors) |
---|
1341 | { |
---|
1342 | /* reads the factor symbols */ |
---|
1343 | long i; |
---|
1344 | |
---|
1345 | for (i = 0; i < (chars); i++) { |
---|
1346 | if (eoln(factfile)) |
---|
1347 | scan_eoln(factfile); |
---|
1348 | factor[i] = gettc(factfile); |
---|
1349 | if (factor[i] == '\n') |
---|
1350 | factor[i] = ' '; |
---|
1351 | } |
---|
1352 | scan_eoln(factfile); |
---|
1353 | *factors = true; |
---|
1354 | } /* inputfactorsnew */ |
---|
1355 | |
---|
1356 | void printfactors(FILE *filename, long chars, Char *factor, const char *letters) |
---|
1357 | { |
---|
1358 | /* print out list of factor symbols */ |
---|
1359 | long i; |
---|
1360 | |
---|
1361 | fprintf(filename, "Factors%s:\n\n", letters); |
---|
1362 | for (i = 1; i <= nmlngth - 5; i++) |
---|
1363 | putc(' ', filename); |
---|
1364 | for (i = 1; i <= (chars); i++) { |
---|
1365 | newline(filename, i, 55, nmlngth + 3); |
---|
1366 | putc(factor[i - 1], filename); |
---|
1367 | if (i % 5 == 0) |
---|
1368 | putc(' ', filename); |
---|
1369 | } |
---|
1370 | putc('\n', filename); |
---|
1371 | } /* printfactors */ |
---|
1372 | |
---|
1373 | |
---|
1374 | void headings(long chars, const char *letters1, const char *letters2) |
---|
1375 | { |
---|
1376 | long i, j; |
---|
1377 | |
---|
1378 | putc('\n', outfile); |
---|
1379 | j = nmlngth + (chars + (chars - 1) / 10) / 2 - 5; |
---|
1380 | if (j < nmlngth - 1) |
---|
1381 | j = nmlngth - 1; |
---|
1382 | if (j > 37) |
---|
1383 | j = 37; |
---|
1384 | fprintf(outfile, "Name"); |
---|
1385 | for (i = 1; i <= j; i++) |
---|
1386 | putc(' ', outfile); |
---|
1387 | fprintf(outfile, "%s\n", letters1); |
---|
1388 | fprintf(outfile, "----"); |
---|
1389 | for (i = 1; i <= j; i++) |
---|
1390 | putc(' ', outfile); |
---|
1391 | fprintf(outfile, "%s\n\n", letters2); |
---|
1392 | } /* headings */ |
---|
1393 | |
---|
1394 | |
---|
1395 | void initname(long i) |
---|
1396 | { |
---|
1397 | /* read in species name */ |
---|
1398 | long j; |
---|
1399 | |
---|
1400 | for (j = 0; j < nmlngth; j++) { |
---|
1401 | if (eoff(infile) || eoln(infile)) { |
---|
1402 | int j2; |
---|
1403 | if (eoff(infile)) { |
---|
1404 | printf("\n\nERROR: end-of-file"); |
---|
1405 | } |
---|
1406 | else { |
---|
1407 | printf("\n\nERROR: end-of-line"); |
---|
1408 | } |
---|
1409 | |
---|
1410 | printf(" in the middle of species name for species %ld (got '", i+1); |
---|
1411 | for (j2 = 0; j2<j; ++j2) fputc(nayme[i][j2], stdout); |
---|
1412 | printf("')\n\n"); |
---|
1413 | exxit(-1); |
---|
1414 | } |
---|
1415 | nayme[i][j] = gettc(infile); |
---|
1416 | if ((nayme[i][j] == '(') || (nayme[i][j] == ')') || (nayme[i][j] == ':') |
---|
1417 | || (nayme[i][j] == ',') || (nayme[i][j] == ';') || (nayme[i][j] == '[') |
---|
1418 | || (nayme[i][j] == ']')) { |
---|
1419 | printf("\nERROR: Species name may not contain characters ( ) : ; , [ ] \n"); |
---|
1420 | printf(" In name of species number %ld there is character %c\n\n", |
---|
1421 | i+1, nayme[i][j]); |
---|
1422 | exxit(-1); |
---|
1423 | } |
---|
1424 | } |
---|
1425 | } /* initname */ |
---|
1426 | |
---|
1427 | |
---|
1428 | void findtree(boolean *found,long *pos,long nextree,long *place,bestelm *bestrees) |
---|
1429 | { |
---|
1430 | /* finds tree given by array place in array bestrees by binary search */ |
---|
1431 | /* used by dnacomp, dnapars, dollop, mix, & protpars */ |
---|
1432 | long i, lower, upper; |
---|
1433 | boolean below, done; |
---|
1434 | |
---|
1435 | below = false; |
---|
1436 | lower = 1; |
---|
1437 | upper = nextree - 1; |
---|
1438 | (*found) = false; |
---|
1439 | while (!(*found) && lower <= upper) { |
---|
1440 | (*pos) = (lower + upper) / 2; |
---|
1441 | i = 3; |
---|
1442 | done = false; |
---|
1443 | while (!done) { |
---|
1444 | done = (i > spp); |
---|
1445 | if (!done) |
---|
1446 | done = (place[i - 1] != bestrees[(*pos) - 1].btree[i - 1]); |
---|
1447 | if (!done) |
---|
1448 | i++; |
---|
1449 | } |
---|
1450 | (*found) = (i > spp); |
---|
1451 | if (*found) |
---|
1452 | break; |
---|
1453 | below = (place[i - 1] < bestrees[(*pos )- 1].btree[i - 1]); |
---|
1454 | if (below) |
---|
1455 | upper = (*pos) - 1; |
---|
1456 | else |
---|
1457 | lower = (*pos) + 1; |
---|
1458 | } |
---|
1459 | if (!(*found) && !below) |
---|
1460 | (*pos)++; |
---|
1461 | } /* findtree */ |
---|
1462 | |
---|
1463 | |
---|
1464 | void addtree(long pos,long *nextree,boolean collapse,long *place,bestelm *bestrees) |
---|
1465 | { |
---|
1466 | /* puts tree from array place in its proper position in array bestrees */ |
---|
1467 | /* used by dnacomp, dnapars, dollop, mix, & protpars */ |
---|
1468 | long i; |
---|
1469 | |
---|
1470 | for (i = *nextree - 1; i >= pos; i--){ |
---|
1471 | memcpy(bestrees[i].btree, bestrees[i - 1].btree, spp * sizeof(long)); |
---|
1472 | bestrees[i].gloreange = bestrees[i - 1].gloreange; |
---|
1473 | bestrees[i - 1].gloreange = false; |
---|
1474 | bestrees[i].locreange = bestrees[i - 1].locreange; |
---|
1475 | bestrees[i - 1].locreange = false; |
---|
1476 | bestrees[i].collapse = bestrees[i - 1].collapse; |
---|
1477 | } |
---|
1478 | for (i = 0; i < spp; i++) |
---|
1479 | bestrees[pos - 1].btree[i] = place[i]; |
---|
1480 | bestrees[pos - 1].collapse = collapse; |
---|
1481 | (*nextree)++; |
---|
1482 | } /* addtree */ |
---|
1483 | |
---|
1484 | |
---|
1485 | long findunrearranged(bestelm *bestrees, long nextree, boolean glob) |
---|
1486 | { |
---|
1487 | /* finds bestree with either global or local field false */ |
---|
1488 | long i; |
---|
1489 | |
---|
1490 | if (glob) { |
---|
1491 | for (i = 0; i < nextree - 1; i++) |
---|
1492 | if (!bestrees[i].gloreange) |
---|
1493 | return i; |
---|
1494 | } else { |
---|
1495 | for (i = 0; i < nextree - 1; i++) |
---|
1496 | if (!bestrees[i].locreange) |
---|
1497 | return i; |
---|
1498 | } |
---|
1499 | return -1; |
---|
1500 | } /* findunrearranged */ |
---|
1501 | |
---|
1502 | |
---|
1503 | boolean torearrange(bestelm *bestrees, long nextree) |
---|
1504 | { /* sees if any best tree is yet to be rearranged */ |
---|
1505 | |
---|
1506 | if (findunrearranged(bestrees, nextree, true) >= 0) |
---|
1507 | return true; |
---|
1508 | else if (findunrearranged(bestrees, nextree, false) >= 0) |
---|
1509 | return true; |
---|
1510 | else |
---|
1511 | return false; |
---|
1512 | } /* torearrange */ |
---|
1513 | |
---|
1514 | |
---|
1515 | void reducebestrees(bestelm *bestrees, long *nextree) |
---|
1516 | { |
---|
1517 | /* finds best trees with collapsible branches and deletes them */ |
---|
1518 | long i, j; |
---|
1519 | |
---|
1520 | i = 0; |
---|
1521 | j = *nextree - 2; |
---|
1522 | do { |
---|
1523 | while (!bestrees[i].collapse && i < *nextree - 1) i++; |
---|
1524 | while (bestrees[j].collapse && j >= 0) j--; |
---|
1525 | if (i < j) { |
---|
1526 | memcpy(bestrees[i].btree, bestrees[j].btree, spp * sizeof(long)); |
---|
1527 | bestrees[i].gloreange = bestrees[j].gloreange; |
---|
1528 | bestrees[i].locreange = bestrees[j].locreange; |
---|
1529 | bestrees[i].collapse = false; |
---|
1530 | bestrees[j].collapse = true; |
---|
1531 | } |
---|
1532 | } while (i < j); |
---|
1533 | *nextree = i + 1; |
---|
1534 | } /* reducebestrees */ |
---|
1535 | |
---|
1536 | |
---|
1537 | void shellsort(double *a, long *b, long n) |
---|
1538 | { /* Shell sort keeping a, b in same order */ |
---|
1539 | /* used by dnapenny, dolpenny, & penny */ |
---|
1540 | long gap, i, j, itemp; |
---|
1541 | double rtemp; |
---|
1542 | |
---|
1543 | gap = n / 2; |
---|
1544 | while (gap > 0) { |
---|
1545 | for (i = gap + 1; i <= n; i++) { |
---|
1546 | j = i - gap; |
---|
1547 | while (j > 0) { |
---|
1548 | if (a[j - 1] > a[j + gap - 1]) { |
---|
1549 | rtemp = a[j - 1]; |
---|
1550 | a[j - 1] = a[j + gap - 1]; |
---|
1551 | a[j + gap - 1] = rtemp; |
---|
1552 | itemp = b[j - 1]; |
---|
1553 | b[j - 1] = b[j + gap - 1]; |
---|
1554 | b[j + gap - 1] = itemp; |
---|
1555 | } |
---|
1556 | j -= gap; |
---|
1557 | } |
---|
1558 | } |
---|
1559 | gap /= 2; |
---|
1560 | } |
---|
1561 | } /* shellsort */ |
---|
1562 | |
---|
1563 | |
---|
1564 | void getch(Char *c, long *parens, FILE *treefile) |
---|
1565 | { /* get next nonblank character */ |
---|
1566 | |
---|
1567 | do { |
---|
1568 | if (eoln(treefile)) |
---|
1569 | scan_eoln(treefile); |
---|
1570 | (*c) = gettc(treefile); |
---|
1571 | |
---|
1572 | if ((*c) == '\n' || (*c) == '\t') |
---|
1573 | (*c) = ' '; |
---|
1574 | } while ( *c == ' ' && !eoff(treefile) ); |
---|
1575 | if ((*c) == '(') |
---|
1576 | (*parens)++; |
---|
1577 | if ((*c) == ')') |
---|
1578 | (*parens)--; |
---|
1579 | } /* getch */ |
---|
1580 | |
---|
1581 | |
---|
1582 | void getch2(Char *c, long *parens) |
---|
1583 | { /* get next nonblank character */ |
---|
1584 | do { |
---|
1585 | if (eoln(intree)) |
---|
1586 | scan_eoln(intree); |
---|
1587 | *c = gettc(intree); |
---|
1588 | if (*c == '\n' || *c == '\t') |
---|
1589 | *c = ' '; |
---|
1590 | } while (!(*c != ' ' || eoff(intree))); |
---|
1591 | if (*c == '(') |
---|
1592 | (*parens)++; |
---|
1593 | if (*c == ')') |
---|
1594 | (*parens)--; |
---|
1595 | } /* getch2 */ |
---|
1596 | |
---|
1597 | |
---|
1598 | void findch(Char c, Char *ch, long which) |
---|
1599 | { /* scan forward until find character c */ |
---|
1600 | boolean done; |
---|
1601 | long dummy_parens; |
---|
1602 | done = false; |
---|
1603 | while (!done) { |
---|
1604 | if (c == ',') { |
---|
1605 | if (*ch == '(' || *ch == ')' || *ch == ';') { |
---|
1606 | printf( |
---|
1607 | "\n\nERROR in user tree %ld: unmatched parenthesis or missing comma\n\n", |
---|
1608 | which); |
---|
1609 | exxit(-1); |
---|
1610 | } else if (*ch == ',') |
---|
1611 | done = true; |
---|
1612 | } else if (c == ')') { |
---|
1613 | if (*ch == '(' || *ch == ',' || *ch == ';') { |
---|
1614 | printf("\n\nERROR in user tree %ld: ", which); |
---|
1615 | printf("unmatched parenthesis or non-bifurcated node\n\n"); |
---|
1616 | exxit(-1); |
---|
1617 | } else { |
---|
1618 | if (*ch == ')') |
---|
1619 | done = true; |
---|
1620 | } |
---|
1621 | } else if (c == ';') { |
---|
1622 | if (*ch != ';') { |
---|
1623 | printf("\n\nERROR in user tree %ld: ", which); |
---|
1624 | printf("unmatched parenthesis or missing semicolon\n\n"); |
---|
1625 | exxit(-1); |
---|
1626 | } else |
---|
1627 | done = true; |
---|
1628 | } |
---|
1629 | if (*ch != ')' && done) |
---|
1630 | continue; |
---|
1631 | getch(ch, &dummy_parens, intree); |
---|
1632 | } |
---|
1633 | } /* findch */ |
---|
1634 | |
---|
1635 | |
---|
1636 | void findch2(Char c, long *lparens, long *rparens, Char *ch) |
---|
1637 | { /* skip forward in user tree until find character c */ |
---|
1638 | boolean done; |
---|
1639 | long dummy_parens; |
---|
1640 | done = false; |
---|
1641 | while (!done) { |
---|
1642 | if (c == ',') { |
---|
1643 | if (*ch == '(' || *ch == ')' || *ch == ':' || *ch == ';') { |
---|
1644 | printf("\n\nERROR in user tree: "); |
---|
1645 | printf("unmatched parenthesis, missing comma"); |
---|
1646 | printf(" or non-trifurcated base\n\n"); |
---|
1647 | exxit(-1); |
---|
1648 | } else if (*ch == ',') |
---|
1649 | done = true; |
---|
1650 | } else if (c == ')') { |
---|
1651 | if (*ch == '(' || *ch == ',' || *ch == ':' || *ch == ';') { |
---|
1652 | printf( |
---|
1653 | "\n\nERROR in user tree: unmatched parenthesis or non-bifurcated node\n\n"); |
---|
1654 | exxit(-1); |
---|
1655 | } else if (*ch == ')') { |
---|
1656 | (*rparens)++; |
---|
1657 | if ((*lparens) > 0 && (*lparens) == (*rparens)) { |
---|
1658 | if ((*lparens) == spp - 2) { |
---|
1659 | getch(ch, &dummy_parens, intree); |
---|
1660 | if (*ch != ';') { |
---|
1661 | printf( "\n\nERROR in user tree: "); |
---|
1662 | printf("unmatched parenthesis or missing semicolon\n\n"); |
---|
1663 | exxit(-1); |
---|
1664 | } |
---|
1665 | } |
---|
1666 | } |
---|
1667 | done = true; |
---|
1668 | } |
---|
1669 | } |
---|
1670 | if (*ch != ')' && done) |
---|
1671 | continue; |
---|
1672 | if (*ch == ')') |
---|
1673 | getch(ch, &dummy_parens, intree); |
---|
1674 | } |
---|
1675 | } /* findch2 */ |
---|
1676 | |
---|
1677 | void processlength(double *valyew, double *divisor, Char *ch, |
---|
1678 | boolean *minusread, FILE *treefile, long *parens) |
---|
1679 | { /* read a branch length from a treefile */ |
---|
1680 | long digit, ordzero; |
---|
1681 | boolean pointread; |
---|
1682 | |
---|
1683 | ordzero = '0'; |
---|
1684 | *minusread = false; |
---|
1685 | pointread = false; |
---|
1686 | *valyew = 0.0; |
---|
1687 | *divisor = 1.0; |
---|
1688 | getch(ch, parens, treefile); |
---|
1689 | digit = (long)(*ch - ordzero); |
---|
1690 | while ( ((digit <= 9) && (digit >= 0)) || *ch == '.' || *ch == '-') { |
---|
1691 | if (*ch == '.' ) |
---|
1692 | pointread = true; |
---|
1693 | else if (*ch == '-' ) |
---|
1694 | *minusread = true; |
---|
1695 | else { |
---|
1696 | *valyew = *valyew * 10.0 + digit; |
---|
1697 | if (pointread) |
---|
1698 | *divisor *= 10.0; |
---|
1699 | } |
---|
1700 | getch(ch, parens, treefile); |
---|
1701 | digit = (long)(*ch - ordzero); |
---|
1702 | } |
---|
1703 | if (*minusread) |
---|
1704 | *valyew = -(*valyew); |
---|
1705 | } /* processlength */ |
---|
1706 | |
---|
1707 | |
---|
1708 | void writename(long start, long n, long *enterorder) |
---|
1709 | { /* write species name and number in entry order */ |
---|
1710 | long i, j; |
---|
1711 | |
---|
1712 | for (i = start; i < start+n; i++) { |
---|
1713 | printf(" %3ld. ", i+1); |
---|
1714 | for (j = 0; j < nmlngth; j++) |
---|
1715 | putchar(nayme[enterorder[i] - 1][j]); |
---|
1716 | putchar('\n'); |
---|
1717 | fflush(stdout); |
---|
1718 | } |
---|
1719 | } /* writename */ |
---|
1720 | |
---|
1721 | |
---|
1722 | void memerror() |
---|
1723 | { |
---|
1724 | printf("Error allocating memory\n"); |
---|
1725 | exxit(-1); |
---|
1726 | } /* memerror */ |
---|
1727 | |
---|
1728 | |
---|
1729 | void odd_malloc(long x) |
---|
1730 | { /* error message if attempt to malloc too little or too much memory */ |
---|
1731 | printf ("ERROR: a function asked for an inappropriate amount of memory:"); |
---|
1732 | printf (" %ld bytes\n", x); |
---|
1733 | printf (" This can mean one of two things:\n"); |
---|
1734 | printf (" 1. The input file is incorrect"); |
---|
1735 | printf (" (perhaps it was not saved as Text Only),\n"); |
---|
1736 | printf (" 2. There is a bug in the program.\n"); |
---|
1737 | printf (" Please check your input file carefully.\n"); |
---|
1738 | printf (" If it seems to be a bug, please mail joe@gs.washington.edu\n"); |
---|
1739 | printf (" with the name of the program, your computer system type,\n"); |
---|
1740 | printf (" a full description of the problem, and with the input data file.\n"); |
---|
1741 | printf (" (which should be in the body of the message, not as an Attachment).\n"); |
---|
1742 | |
---|
1743 | /* abort() can be used to crash |
---|
1744 | * for debugging */ |
---|
1745 | |
---|
1746 | exxit(-1); |
---|
1747 | } |
---|
1748 | |
---|
1749 | |
---|
1750 | MALLOCRETURN *mymalloc(long x) |
---|
1751 | { /* wrapper for malloc, allowing error message if too little, too much */ |
---|
1752 | MALLOCRETURN *new_block; |
---|
1753 | |
---|
1754 | if ((x <= 0) || |
---|
1755 | (x > TOO_MUCH_MEMORY)) |
---|
1756 | odd_malloc(x); |
---|
1757 | |
---|
1758 | new_block = (MALLOCRETURN *)calloc(1,x); |
---|
1759 | |
---|
1760 | if (!new_block) { |
---|
1761 | memerror(); |
---|
1762 | return (MALLOCRETURN *) new_block; |
---|
1763 | } else |
---|
1764 | return (MALLOCRETURN *) new_block; |
---|
1765 | } /* mymalloc */ |
---|
1766 | |
---|
1767 | |
---|
1768 | void gnu(node **grbg, node **p) |
---|
1769 | { /* this and the following are do-it-yourself garbage collectors. |
---|
1770 | Make a new node or pull one off the garbage list */ |
---|
1771 | |
---|
1772 | if (*grbg != NULL) { |
---|
1773 | *p = *grbg; |
---|
1774 | *grbg = (*grbg)->next; |
---|
1775 | } else |
---|
1776 | *p = (node *)Malloc(sizeof(node)); |
---|
1777 | |
---|
1778 | (*p)->back = NULL; |
---|
1779 | (*p)->next = NULL; |
---|
1780 | (*p)->tip = false; |
---|
1781 | (*p)->times_in_tree = 0.0; |
---|
1782 | (*p)->r = 0.0; |
---|
1783 | (*p)->theta = 0.0; |
---|
1784 | (*p)->x = NULL; |
---|
1785 | (*p)->protx = NULL; /* for the sake of proml */ |
---|
1786 | } /* gnu */ |
---|
1787 | |
---|
1788 | |
---|
1789 | void chuck(node **grbg, node *p) |
---|
1790 | { /* collect garbage on p -- put it on front of garbage list */ |
---|
1791 | p->back = NULL; |
---|
1792 | p->next = *grbg; |
---|
1793 | *grbg = p; |
---|
1794 | } /* chuck */ |
---|
1795 | |
---|
1796 | |
---|
1797 | void zeronumnuc(node *p, long endsite) |
---|
1798 | { |
---|
1799 | long i,j; |
---|
1800 | |
---|
1801 | for (i = 0; i < endsite; i++) |
---|
1802 | for (j = (long)A; j <= (long)O; j++) |
---|
1803 | p->numnuc[i][j] = 0; |
---|
1804 | } /* zeronumnuc */ |
---|
1805 | |
---|
1806 | |
---|
1807 | void zerodiscnumnuc(node *p, long endsite) |
---|
1808 | { |
---|
1809 | long i,j; |
---|
1810 | |
---|
1811 | for (i = 0; i < endsite; i++) |
---|
1812 | for (j = (long)ZERO; j <= (long)SEVEN; j++) |
---|
1813 | p->discnumnuc[i][j] = 0; |
---|
1814 | } /* zerodiscnumnuc */ |
---|
1815 | |
---|
1816 | |
---|
1817 | void allocnontip(node *p, long *zeros, long endsite) |
---|
1818 | { /* allocate an interior node */ |
---|
1819 | /* used by dnacomp, dnapars, & dnapenny */ |
---|
1820 | |
---|
1821 | p->numsteps = (steptr)Malloc(endsite*sizeof(long)); |
---|
1822 | p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long)); |
---|
1823 | p->base = (baseptr)Malloc(endsite*sizeof(long)); |
---|
1824 | p->oldbase = (baseptr)Malloc(endsite*sizeof(long)); |
---|
1825 | p->numnuc = (nucarray *)Malloc(endsite*sizeof(nucarray)); |
---|
1826 | memcpy(p->base, zeros, endsite*sizeof(long)); |
---|
1827 | memcpy(p->numsteps, zeros, endsite*sizeof(long)); |
---|
1828 | memcpy(p->oldbase, zeros, endsite*sizeof(long)); |
---|
1829 | memcpy(p->oldnumsteps, zeros, endsite*sizeof(long)); |
---|
1830 | zeronumnuc(p, endsite); |
---|
1831 | } /* allocnontip */ |
---|
1832 | |
---|
1833 | |
---|
1834 | void allocdiscnontip(node *p, long *zeros, unsigned char *zeros2, long endsite) |
---|
1835 | { /* allocate an interior node */ |
---|
1836 | /* used by pars */ |
---|
1837 | |
---|
1838 | p->numsteps = (steptr)Malloc(endsite*sizeof(long)); |
---|
1839 | p->oldnumsteps = (steptr)Malloc(endsite*sizeof(long)); |
---|
1840 | p->discbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char)); |
---|
1841 | p->olddiscbase = (discbaseptr)Malloc(endsite*sizeof(unsigned char)); |
---|
1842 | p->discnumnuc = (discnucarray *)Malloc(endsite*sizeof(discnucarray)); |
---|
1843 | memcpy(p->discbase, zeros2, endsite*sizeof(unsigned char)); |
---|
1844 | memcpy(p->numsteps, zeros, endsite*sizeof(long)); |
---|
1845 | memcpy(p->olddiscbase, zeros2, endsite*sizeof(unsigned char)); |
---|
1846 | memcpy(p->oldnumsteps, zeros, endsite*sizeof(long)); |
---|
1847 | zerodiscnumnuc(p, endsite); |
---|
1848 | } /* allocdiscnontip */ |
---|
1849 | |
---|
1850 | |
---|
1851 | void allocnode(node **anode, long *zeros, long endsite) |
---|
1852 | { /* allocate a node */ |
---|
1853 | /* used by dnacomp, dnapars, & dnapenny */ |
---|
1854 | |
---|
1855 | *anode = (node *)Malloc(sizeof(node)); |
---|
1856 | allocnontip(*anode, zeros, endsite); |
---|
1857 | } /* allocnode */ |
---|
1858 | |
---|
1859 | |
---|
1860 | void allocdiscnode(node **anode, long *zeros, unsigned char *zeros2, |
---|
1861 | long endsite) |
---|
1862 | { /* allocate a node */ |
---|
1863 | /* used by pars */ |
---|
1864 | |
---|
1865 | *anode = (node *)Malloc(sizeof(node)); |
---|
1866 | allocdiscnontip(*anode, zeros, zeros2, endsite); |
---|
1867 | } /* allocdiscnontip */ |
---|
1868 | |
---|
1869 | |
---|
1870 | void gnutreenode(node **grbg, node **p, long i, long endsite, long *zeros) |
---|
1871 | { /* this and the following are do-it-yourself garbage collectors. |
---|
1872 | Make a new node or pull one off the garbage list */ |
---|
1873 | |
---|
1874 | if (*grbg != NULL) { |
---|
1875 | *p = *grbg; |
---|
1876 | *grbg = (*grbg)->next; |
---|
1877 | memcpy((*p)->numsteps, zeros, endsite*sizeof(long)); |
---|
1878 | memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long)); |
---|
1879 | memcpy((*p)->base, zeros, endsite*sizeof(long)); |
---|
1880 | memcpy((*p)->oldbase, zeros, endsite*sizeof(long)); |
---|
1881 | zeronumnuc(*p, endsite); |
---|
1882 | } else |
---|
1883 | allocnode(p, zeros, endsite); |
---|
1884 | (*p)->back = NULL; |
---|
1885 | (*p)->next = NULL; |
---|
1886 | (*p)->tip = false; |
---|
1887 | (*p)->visited = false; |
---|
1888 | (*p)->index = i; |
---|
1889 | (*p)->numdesc = 0; |
---|
1890 | (*p)->sumsteps = 0.0; |
---|
1891 | } /* gnutreenode */ |
---|
1892 | |
---|
1893 | |
---|
1894 | void gnudisctreenode(node **grbg, node **p, long i, |
---|
1895 | long endsite, long *zeros, unsigned char *zeros2) |
---|
1896 | { /* this and the following are do-it-yourself garbage collectors. |
---|
1897 | Make a new node or pull one off the garbage list */ |
---|
1898 | |
---|
1899 | if (*grbg != NULL) { |
---|
1900 | *p = *grbg; |
---|
1901 | *grbg = (*grbg)->next; |
---|
1902 | memcpy((*p)->numsteps, zeros, endsite*sizeof(long)); |
---|
1903 | memcpy((*p)->oldnumsteps, zeros, endsite*sizeof(long)); |
---|
1904 | memcpy((*p)->discbase, zeros2, endsite*sizeof(unsigned char)); |
---|
1905 | memcpy((*p)->olddiscbase, zeros2, endsite*sizeof(unsigned char)); |
---|
1906 | zerodiscnumnuc(*p, endsite); |
---|
1907 | } else |
---|
1908 | allocdiscnode(p, zeros, zeros2, endsite); |
---|
1909 | (*p)->back = NULL; |
---|
1910 | (*p)->next = NULL; |
---|
1911 | (*p)->tip = false; |
---|
1912 | (*p)->visited = false; |
---|
1913 | (*p)->index = i; |
---|
1914 | (*p)->numdesc = 0; |
---|
1915 | (*p)->sumsteps = 0.0; |
---|
1916 | } /* gnudisctreenode */ |
---|
1917 | |
---|
1918 | |
---|
1919 | void chucktreenode(node **grbg, node *p) |
---|
1920 | { /* collect garbage on p -- put it on front of garbage list */ |
---|
1921 | |
---|
1922 | p->back = NULL; |
---|
1923 | p->next = *grbg; |
---|
1924 | *grbg = p; |
---|
1925 | } /* chucktreenode */ |
---|
1926 | |
---|
1927 | |
---|
1928 | void setupnode(node *p, long i) |
---|
1929 | { /* initialization of node pointers, variables */ |
---|
1930 | |
---|
1931 | p->next = NULL; |
---|
1932 | p->back = NULL; |
---|
1933 | p->times_in_tree = (double) i * 1.0; |
---|
1934 | p->index = i; |
---|
1935 | p->tip = false; |
---|
1936 | } /* setupnode */ |
---|
1937 | |
---|
1938 | |
---|
1939 | long count_sibs (node *p) |
---|
1940 | { /* Count the number of nodes in a ring, return the total number of */ |
---|
1941 | /* nodes excluding the one passed into the function (siblings) */ |
---|
1942 | node *q; |
---|
1943 | long return_int = 0; |
---|
1944 | |
---|
1945 | if (p->tip) { |
---|
1946 | printf ("Error: the function count_sibs called on a tip. This is a bug.\n"); |
---|
1947 | exxit (-1); |
---|
1948 | } |
---|
1949 | |
---|
1950 | q = p->next; |
---|
1951 | while (q != p) { |
---|
1952 | if (q == NULL) { |
---|
1953 | printf ("Error: a loop of nodes was not closed.\n"); |
---|
1954 | exxit (-1); |
---|
1955 | } else { |
---|
1956 | return_int++; |
---|
1957 | q = q->next; |
---|
1958 | } |
---|
1959 | } |
---|
1960 | |
---|
1961 | return return_int; |
---|
1962 | } /* count_sibs */ |
---|
1963 | |
---|
1964 | |
---|
1965 | void inittrav (node *p) |
---|
1966 | { /* traverse to set pointers uninitialized on inserting */ |
---|
1967 | long i, num_sibs; |
---|
1968 | node *sib_ptr; |
---|
1969 | |
---|
1970 | if (p == NULL) |
---|
1971 | return; |
---|
1972 | if (p->tip) |
---|
1973 | return; |
---|
1974 | num_sibs = count_sibs (p); |
---|
1975 | sib_ptr = p; |
---|
1976 | for (i=0; i < num_sibs; i++) { |
---|
1977 | sib_ptr = sib_ptr->next; |
---|
1978 | sib_ptr->initialized = false; |
---|
1979 | inittrav(sib_ptr->back); |
---|
1980 | } |
---|
1981 | } /* inittrav */ |
---|
1982 | |
---|
1983 | |
---|
1984 | void commentskipper(FILE ***fppp_intree, long *bracket) |
---|
1985 | { /* skip over comment bracket contents in reading tree */ |
---|
1986 | char c; |
---|
1987 | |
---|
1988 | c = gettc(**fppp_intree); |
---|
1989 | |
---|
1990 | while (c != ']') { |
---|
1991 | |
---|
1992 | if(feof(**fppp_intree)) { |
---|
1993 | printf("\n\nERROR: Unmatched comment brackets\n\n"); |
---|
1994 | exxit(-1); |
---|
1995 | } |
---|
1996 | |
---|
1997 | if(c == '[') { |
---|
1998 | (*bracket)++; |
---|
1999 | commentskipper(fppp_intree, bracket); |
---|
2000 | } |
---|
2001 | c = gettc(**fppp_intree); |
---|
2002 | } |
---|
2003 | (*bracket)--; |
---|
2004 | } /* commentskipper */ |
---|
2005 | |
---|
2006 | |
---|
2007 | long countcomma(FILE **treefile, long *comma) |
---|
2008 | { |
---|
2009 | /* Modified by Dan F. 11/10/96 */ |
---|
2010 | |
---|
2011 | /* The next line inserted so this function leaves the file pointing |
---|
2012 | to where it found it, not just re-winding it. */ |
---|
2013 | long orig_position = ftell (*treefile); |
---|
2014 | |
---|
2015 | Char c; |
---|
2016 | long lparen = 0; |
---|
2017 | long bracket = 0; |
---|
2018 | (*comma) = 0; |
---|
2019 | |
---|
2020 | |
---|
2021 | for (;;){ |
---|
2022 | c = getc(*treefile); |
---|
2023 | if (feof(*treefile)) |
---|
2024 | break; |
---|
2025 | if (c == ';') |
---|
2026 | break; |
---|
2027 | if (c == ',') |
---|
2028 | (*comma)++; |
---|
2029 | if (c == '(') |
---|
2030 | lparen++; |
---|
2031 | if (c == '[') { |
---|
2032 | bracket++; |
---|
2033 | commentskipper(&treefile, &bracket); |
---|
2034 | } |
---|
2035 | } |
---|
2036 | |
---|
2037 | /* Don't just rewind, */ |
---|
2038 | /* rewind (*treefile); */ |
---|
2039 | /* Re-set to where it pointed when the function was called */ |
---|
2040 | |
---|
2041 | fseek (*treefile, orig_position, SEEK_SET); |
---|
2042 | |
---|
2043 | return lparen + (*comma); |
---|
2044 | } /*countcomma*/ |
---|
2045 | /* countcomma rewritten so it passes back both lparen+comma to allocate nodep |
---|
2046 | and a pointer to the comma variable. This allows the tree to know how many |
---|
2047 | species exist, and the tips to be placed in the front of the nodep array */ |
---|
2048 | |
---|
2049 | |
---|
2050 | long countsemic(FILE **treefile) |
---|
2051 | { /* Used to determine the number of user trees. Return |
---|
2052 | either a: the number of semicolons in the file outside comments |
---|
2053 | or b: the first integer in the file */ |
---|
2054 | Char c; |
---|
2055 | long return_val, semic = 0; |
---|
2056 | long bracket = 0; |
---|
2057 | |
---|
2058 | /* Eat all whitespace */ |
---|
2059 | c = gettc(*treefile); |
---|
2060 | while ((c == ' ') || |
---|
2061 | (c == '\t') || |
---|
2062 | (c == '\n')) { |
---|
2063 | c = gettc(*treefile); |
---|
2064 | } |
---|
2065 | |
---|
2066 | /* Then figure out if the first non-white character is a digit; if |
---|
2067 | so, return it */ |
---|
2068 | if (isdigit (c)) { |
---|
2069 | return_val = atoi(&c); |
---|
2070 | } else { |
---|
2071 | |
---|
2072 | /* Loop past all characters, count the number of semicolons |
---|
2073 | outside of comments */ |
---|
2074 | for (;;){ |
---|
2075 | c = fgetc(*treefile); |
---|
2076 | if (feof(*treefile)) |
---|
2077 | break; |
---|
2078 | if (c == ';') |
---|
2079 | semic++; |
---|
2080 | if (c == '[') { |
---|
2081 | bracket++; |
---|
2082 | commentskipper(&treefile, &bracket); |
---|
2083 | } |
---|
2084 | } |
---|
2085 | return_val = semic; |
---|
2086 | } |
---|
2087 | |
---|
2088 | rewind (*treefile); |
---|
2089 | return return_val; |
---|
2090 | } /* countsemic */ |
---|
2091 | |
---|
2092 | |
---|
2093 | void hookup(node *p, node *q) |
---|
2094 | { /* hook together two nodes */ |
---|
2095 | |
---|
2096 | p->back = q; |
---|
2097 | q->back = p; |
---|
2098 | } /* hookup */ |
---|
2099 | |
---|
2100 | |
---|
2101 | void link_trees(long local_nextnum, long nodenum, long local_nodenum, |
---|
2102 | pointarray nodep) |
---|
2103 | { |
---|
2104 | if(local_nextnum == 0) |
---|
2105 | hookup(nodep[nodenum],nodep[local_nodenum]); |
---|
2106 | else if(local_nextnum == 1) |
---|
2107 | hookup(nodep[nodenum], nodep[local_nodenum]->next); |
---|
2108 | else if(local_nextnum == 2) |
---|
2109 | hookup(nodep[nodenum],nodep[local_nodenum]->next->next); |
---|
2110 | else |
---|
2111 | printf("Error in Link_Trees()"); |
---|
2112 | } /* link_trees() */ |
---|
2113 | |
---|
2114 | |
---|
2115 | void allocate_nodep(pointarray *nodep, FILE **treefile, long *precalc_tips) |
---|
2116 | { /* pre-compute space and allocate memory for nodep */ |
---|
2117 | |
---|
2118 | long numnodes; /* returns number commas & ( */ |
---|
2119 | long numcom = 0; /* returns number commas */ |
---|
2120 | |
---|
2121 | numnodes = countcomma(treefile, &numcom) + 1; |
---|
2122 | *nodep = (pointarray)Malloc(2*numnodes*sizeof(node *)); |
---|
2123 | |
---|
2124 | (*precalc_tips) = numcom + 1; /* this will be used in placing the |
---|
2125 | tip nodes in the front region of |
---|
2126 | nodep. Used for species check? */ |
---|
2127 | } /* allocate_nodep -plc */ |
---|
2128 | |
---|
2129 | |
---|
2130 | void malloc_pheno (node *p, long endsite, long rcategs) |
---|
2131 | { /* Allocate the phenotype arrays; used by dnaml */ |
---|
2132 | long i; |
---|
2133 | |
---|
2134 | p->x = (phenotype)Malloc(endsite*sizeof(ratelike)); |
---|
2135 | for (i = 0; i < endsite; i++) |
---|
2136 | p->x[i] = (ratelike)Malloc(rcategs*sizeof(sitelike)); |
---|
2137 | } /* malloc_pheno */ |
---|
2138 | |
---|
2139 | |
---|
2140 | void malloc_ppheno (node *p,long endsite, long rcategs) |
---|
2141 | { |
---|
2142 | /* Allocate the phenotype arrays; used by proml */ |
---|
2143 | long i; |
---|
2144 | |
---|
2145 | p->protx = (pphenotype)Malloc(endsite*sizeof(pratelike)); |
---|
2146 | for (i = 0; i < endsite; i++) |
---|
2147 | p->protx[i] = (pratelike)Malloc(rcategs*sizeof(psitelike)); |
---|
2148 | } /* malloc_ppheno */ |
---|
2149 | |
---|
2150 | |
---|
2151 | long take_name_from_tree (Char *ch, Char *str, FILE *treefile) |
---|
2152 | { |
---|
2153 | /* This loop takes in the name from the tree. |
---|
2154 | Return the length of the name string. */ |
---|
2155 | |
---|
2156 | long name_length = 0; |
---|
2157 | |
---|
2158 | do { |
---|
2159 | if ((*ch) == '_') |
---|
2160 | (*ch) = ' '; |
---|
2161 | str[name_length++] = (*ch); |
---|
2162 | if (eoln(treefile)) |
---|
2163 | scan_eoln(treefile); |
---|
2164 | (*ch) = gettc(treefile); |
---|
2165 | if (*ch == '\n') |
---|
2166 | *ch = ' '; |
---|
2167 | } while ((*ch) != ':' && (*ch) != ',' && (*ch) != ')' && |
---|
2168 | (*ch) != '[' && (*ch) != ';' && name_length <= MAXNCH); |
---|
2169 | return name_length; |
---|
2170 | } /* take_name_from_tree */ |
---|
2171 | |
---|
2172 | |
---|
2173 | void match_names_to_data (Char *str, pointarray treenode, node **p, long local_spp) |
---|
2174 | { |
---|
2175 | /* This loop matches names taken from treefile to indexed names in |
---|
2176 | the data file */ |
---|
2177 | |
---|
2178 | boolean found; |
---|
2179 | long i, n; |
---|
2180 | |
---|
2181 | n = 1; |
---|
2182 | do { |
---|
2183 | found = true; |
---|
2184 | for (i = 0; i < nmlngth; i++) { |
---|
2185 | found = (found && ((str[i] == nayme[n - 1][i]) || |
---|
2186 | (((nayme[n - 1][i] == '_') && (str[i] == ' ')) || |
---|
2187 | ((nayme[n - 1][i] == ' ') && (str[i] == '\0'))))); |
---|
2188 | } |
---|
2189 | |
---|
2190 | if (found) |
---|
2191 | *p = treenode[n - 1]; |
---|
2192 | else |
---|
2193 | n++; |
---|
2194 | |
---|
2195 | } while (!(n > local_spp || found)); |
---|
2196 | |
---|
2197 | if (n > local_spp) { |
---|
2198 | printf("\n\nERROR: Cannot find species: "); |
---|
2199 | for (i = 0; (str[i] != '\0') && (i < MAXNCH); i++) |
---|
2200 | putchar(str[i]); |
---|
2201 | printf(" in data file\n\n"); |
---|
2202 | exxit(-1); |
---|
2203 | } |
---|
2204 | } /* match_names_to_data */ |
---|
2205 | |
---|
2206 | |
---|
2207 | void addelement(node **p, node *q, Char *ch, long *parens, FILE *treefile, |
---|
2208 | pointarray treenode, boolean *goteof, boolean *first, pointarray nodep, |
---|
2209 | long *nextnode, long *ntips, boolean *haslengths, node **grbg, |
---|
2210 | initptr initnode) |
---|
2211 | { |
---|
2212 | /* Recursive procedure adds nodes to user-defined tree |
---|
2213 | This is the main (new) tree-reading procedure */ |
---|
2214 | |
---|
2215 | node *pfirst; |
---|
2216 | long i, len = 0, nodei = 0; |
---|
2217 | boolean notlast; |
---|
2218 | Char str[MAXNCH]; |
---|
2219 | node *r; |
---|
2220 | |
---|
2221 | if ((*ch) == '(') { |
---|
2222 | (*nextnode)++; /* get ready to use new interior node */ |
---|
2223 | nodei = *nextnode; /* do what needs to be done at bottom */ |
---|
2224 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2225 | parens, bottom, treenode, nodep, str, ch, treefile); |
---|
2226 | pfirst = (*p); |
---|
2227 | notlast = true; |
---|
2228 | while (notlast) { /* loop through immediate descendants */ |
---|
2229 | (*initnode)(&(*p)->next, grbg, q, |
---|
2230 | len, nodei, ntips, parens, nonbottom, treenode, |
---|
2231 | nodep, str, ch, treefile); |
---|
2232 | /* ... doing what is done before each */ |
---|
2233 | r = (*p)->next; |
---|
2234 | getch(ch, parens, treefile); /* look for next character */ |
---|
2235 | |
---|
2236 | addelement(&(*p)->next->back, (*p)->next, ch, parens, treefile, |
---|
2237 | treenode, goteof, first, nodep, nextnode, ntips, |
---|
2238 | haslengths, grbg, initnode); /* call self recursively */ |
---|
2239 | |
---|
2240 | (*initnode)(&r, grbg, q, len, nodei, ntips, |
---|
2241 | parens, hslength, treenode, nodep, str, ch, treefile); |
---|
2242 | /* do what is done after each about length */ |
---|
2243 | pfirst->numdesc++; /* increment number of descendants */ |
---|
2244 | *p = r; /* make r point back to p */ |
---|
2245 | |
---|
2246 | if ((*ch) == ')') { |
---|
2247 | notlast = false; |
---|
2248 | do { |
---|
2249 | getch(ch, parens, treefile); |
---|
2250 | } while ((*ch) != ',' && (*ch) != ')' && |
---|
2251 | (*ch) != '[' && (*ch) != ';' && (*ch) != ':'); |
---|
2252 | } |
---|
2253 | } |
---|
2254 | |
---|
2255 | (*p)->next = pfirst; |
---|
2256 | (*p) = pfirst; |
---|
2257 | |
---|
2258 | } else if ((*ch) != ')') { /* if it's a species name */ |
---|
2259 | for (i = 0; i < MAXNCH; i++) /* fill string with nulls */ |
---|
2260 | str[i] = '\0'; |
---|
2261 | |
---|
2262 | len = take_name_from_tree (ch, str, treefile); /* get the name */ |
---|
2263 | |
---|
2264 | if ((*ch) == ')') |
---|
2265 | (*parens)--; /* decrement count of open parentheses */ |
---|
2266 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2267 | parens, tip, treenode, nodep, str, ch, treefile); |
---|
2268 | /* do what needs to be done at a tip */ |
---|
2269 | } else |
---|
2270 | getch(ch, parens, treefile); |
---|
2271 | if (q != NULL) |
---|
2272 | hookup(q, (*p)); /* now hook up */ |
---|
2273 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2274 | parens, iter, treenode, nodep, str, ch, treefile); |
---|
2275 | if ((*ch) == ':') |
---|
2276 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2277 | parens, length, treenode, nodep, str, ch, treefile); |
---|
2278 | /* do what needs to be done with length */ |
---|
2279 | else if ((*ch) != ';' && (*ch) != '[') |
---|
2280 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2281 | parens, hsnolength, treenode, nodep, str, ch, treefile); |
---|
2282 | /* ... or what needs to be done when no length */ |
---|
2283 | if ((*ch) == '[') |
---|
2284 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2285 | parens, treewt, treenode, nodep, str, ch, treefile); |
---|
2286 | /* ... for processing a tree weight */ |
---|
2287 | else if ((*ch) == ';') /* ... and at end of tree */ |
---|
2288 | (*initnode)(p, grbg, q, len, nodei, ntips, |
---|
2289 | parens, unittrwt, treenode, nodep, str, ch, treefile); |
---|
2290 | } /* addelement */ |
---|
2291 | |
---|
2292 | |
---|
2293 | void treeread (FILE *treefile, node **root, pointarray treenode, |
---|
2294 | boolean *goteof, boolean *first, pointarray nodep, |
---|
2295 | long *nextnode, boolean *haslengths, node **grbg, initptr initnode) |
---|
2296 | { |
---|
2297 | /* read in user-defined tree and set it up */ |
---|
2298 | char ch; |
---|
2299 | long parens = 0; |
---|
2300 | long ntips = 0; |
---|
2301 | |
---|
2302 | (*goteof) = false; |
---|
2303 | (*nextnode) = spp; |
---|
2304 | |
---|
2305 | /* eat blank lines */ |
---|
2306 | while (eoln(treefile) && !eoff(treefile)) |
---|
2307 | scan_eoln(treefile); |
---|
2308 | |
---|
2309 | if (eoff(treefile)) { |
---|
2310 | (*goteof) = true; |
---|
2311 | return; |
---|
2312 | } |
---|
2313 | |
---|
2314 | getch(&ch, &parens, treefile); |
---|
2315 | |
---|
2316 | while (ch != '(') { |
---|
2317 | /* Eat everything in the file (i.e. digits, tabs) until you |
---|
2318 | encounter an open-paren */ |
---|
2319 | getch(&ch, &parens, treefile); |
---|
2320 | } |
---|
2321 | (*haslengths) = true; |
---|
2322 | addelement(root, NULL, &ch, &parens, treefile, |
---|
2323 | treenode, goteof, first, nodep, nextnode, &ntips, |
---|
2324 | haslengths, grbg, initnode); |
---|
2325 | |
---|
2326 | /* Eat blank lines and end of current line*/ |
---|
2327 | do { |
---|
2328 | scan_eoln(treefile); |
---|
2329 | } |
---|
2330 | while (eoln(treefile) && !eoff(treefile)); |
---|
2331 | |
---|
2332 | (*first) = false; |
---|
2333 | if (parens != 0) { |
---|
2334 | printf("\n\nERROR in tree file: unmatched parentheses\n\n"); |
---|
2335 | exxit(-1); |
---|
2336 | } |
---|
2337 | } /* treeread */ |
---|
2338 | |
---|
2339 | |
---|
2340 | void addelement2(node *q, Char *ch, long *parens, FILE *treefile, |
---|
2341 | pointarray treenode, boolean lngths, double *trweight, boolean *goteof, |
---|
2342 | long *nextnode, long *ntips, long no_species, boolean *haslengths) |
---|
2343 | { |
---|
2344 | /* recursive procedure adds nodes to user-defined tree |
---|
2345 | -- old-style bifurcating-only version */ |
---|
2346 | node *pfirst = NULL, *p; |
---|
2347 | long i, len, current_loop_index; |
---|
2348 | boolean notlast, minusread; |
---|
2349 | Char str[MAXNCH]; |
---|
2350 | double valyew, divisor; |
---|
2351 | |
---|
2352 | if ((*ch) == '(') { |
---|
2353 | |
---|
2354 | current_loop_index = (*nextnode) + spp; |
---|
2355 | (*nextnode)++; |
---|
2356 | |
---|
2357 | /* This is an assignment of an interior node */ |
---|
2358 | p = treenode[current_loop_index]; |
---|
2359 | pfirst = p; |
---|
2360 | notlast = true; |
---|
2361 | while (notlast) { |
---|
2362 | /* This while loop goes through a circle (triad for |
---|
2363 | bifurcations) of nodes */ |
---|
2364 | p = p->next; |
---|
2365 | /* added to ensure that non base nodes in loops have indices */ |
---|
2366 | p->index = current_loop_index + 1; |
---|
2367 | |
---|
2368 | getch(ch, parens, treefile); |
---|
2369 | |
---|
2370 | addelement2(p, ch, parens, treefile, treenode, lngths, trweight, |
---|
2371 | goteof, nextnode, ntips, no_species, haslengths); |
---|
2372 | |
---|
2373 | if ((*ch) == ')') { |
---|
2374 | notlast = false; |
---|
2375 | do { |
---|
2376 | getch(ch, parens, treefile); |
---|
2377 | } while ((*ch) != ',' && (*ch) != ')' && |
---|
2378 | (*ch) != '[' && (*ch) != ';' && (*ch) != ':'); |
---|
2379 | } |
---|
2380 | } |
---|
2381 | |
---|
2382 | } else if ((*ch) != ')') { |
---|
2383 | for (i = 0; i < MAXNCH; i++) |
---|
2384 | str[i] = '\0'; |
---|
2385 | len = take_name_from_tree (ch, str, treefile); |
---|
2386 | match_names_to_data (str, treenode, &p, spp); |
---|
2387 | pfirst = p; |
---|
2388 | if ((*ch) == ')') |
---|
2389 | (*parens)--; |
---|
2390 | (*ntips)++; |
---|
2391 | strncpy (p->nayme, str, len); |
---|
2392 | } else |
---|
2393 | getch(ch, parens, treefile); |
---|
2394 | |
---|
2395 | if ((*ch) == '[') { /* getting tree weight from last comment field */ |
---|
2396 | if (!eoln(treefile)) { |
---|
2397 | fscanf(treefile, "%lf", trweight); |
---|
2398 | getch(ch, parens, treefile); |
---|
2399 | if (*ch != ']') { |
---|
2400 | printf("\n\nERROR: Missing right square bracket\n\n"); |
---|
2401 | exxit(-1); |
---|
2402 | } |
---|
2403 | else { |
---|
2404 | getch(ch, parens, treefile); |
---|
2405 | if (*ch != ';') { |
---|
2406 | printf("\n\nERROR: Missing semicolon after square brackets\n\n"); |
---|
2407 | exxit(-1); |
---|
2408 | } |
---|
2409 | } |
---|
2410 | } |
---|
2411 | } |
---|
2412 | else if ((*ch) == ';') { |
---|
2413 | (*trweight) = 1.0 ; |
---|
2414 | if (!eoln(treefile)) |
---|
2415 | printf("WARNING: tree weight set to 1.0\n"); |
---|
2416 | } |
---|
2417 | else |
---|
2418 | (*haslengths) = ((*haslengths) && q == NULL); |
---|
2419 | |
---|
2420 | if (q != NULL) |
---|
2421 | hookup(q, pfirst); |
---|
2422 | if (q != NULL) { |
---|
2423 | if (q->branchnum < pfirst->branchnum) |
---|
2424 | pfirst->branchnum = q->branchnum; |
---|
2425 | else |
---|
2426 | q->branchnum = pfirst->branchnum; |
---|
2427 | } |
---|
2428 | |
---|
2429 | if ((*ch) == ':') { |
---|
2430 | processlength(&valyew, &divisor, ch, |
---|
2431 | &minusread, treefile, parens); |
---|
2432 | if (q != NULL) { |
---|
2433 | if (!minusread) |
---|
2434 | q->oldlen = valyew / divisor; |
---|
2435 | else |
---|
2436 | q->oldlen = 0.0; |
---|
2437 | if (lngths) { |
---|
2438 | q->v = valyew / divisor; |
---|
2439 | q->back->v = q->v; |
---|
2440 | q->iter = false; |
---|
2441 | q->back->iter = false; |
---|
2442 | q->back->iter = false; |
---|
2443 | } |
---|
2444 | } |
---|
2445 | } |
---|
2446 | |
---|
2447 | } /* addelement2 */ |
---|
2448 | |
---|
2449 | |
---|
2450 | void treeread2 (FILE *treefile, node **root, pointarray treenode, |
---|
2451 | boolean lngths, double *trweight, boolean *goteof, |
---|
2452 | boolean *haslengths, long *no_species) |
---|
2453 | { |
---|
2454 | /* read in user-defined tree and set it up |
---|
2455 | -- old-style bifurcating-only version */ |
---|
2456 | char ch; |
---|
2457 | long parens = 0; |
---|
2458 | long ntips = 0; |
---|
2459 | long nextnode; |
---|
2460 | |
---|
2461 | (*goteof) = false; |
---|
2462 | nextnode = 0; |
---|
2463 | |
---|
2464 | /* Eats all blank lines at start of file */ |
---|
2465 | while (eoln(treefile) && !eoff(treefile)) |
---|
2466 | scan_eoln(treefile); |
---|
2467 | |
---|
2468 | if (eoff(treefile)) { |
---|
2469 | (*goteof) = true; |
---|
2470 | return; |
---|
2471 | } |
---|
2472 | |
---|
2473 | getch(&ch, &parens, treefile); |
---|
2474 | |
---|
2475 | while (ch != '(') { |
---|
2476 | /* Eat everything in the file (i.e. digits, tabs) until you |
---|
2477 | encounter an open-paren */ |
---|
2478 | getch(&ch, &parens, treefile); |
---|
2479 | } |
---|
2480 | |
---|
2481 | addelement2(NULL, &ch, &parens, treefile, treenode, lngths, trweight, |
---|
2482 | goteof, &nextnode, &ntips, (*no_species), haslengths); |
---|
2483 | (*root) = treenode[*no_species]; |
---|
2484 | |
---|
2485 | /*eat blank lines */ |
---|
2486 | while (eoln(treefile) && !eoff(treefile)) |
---|
2487 | scan_eoln(treefile); |
---|
2488 | |
---|
2489 | (*root)->oldlen = 0.0; |
---|
2490 | |
---|
2491 | if (parens != 0) { |
---|
2492 | printf("\n\nERROR in tree file: unmatched parentheses\n\n"); |
---|
2493 | exxit(-1); |
---|
2494 | } |
---|
2495 | } /* treeread2 */ |
---|
2496 | |
---|
2497 | void exxit(int exitcode) |
---|
2498 | { |
---|
2499 | #ifdef WIN32 |
---|
2500 | if (exitcode == 0) |
---|
2501 | #endif |
---|
2502 | exit (exitcode); |
---|
2503 | #ifdef WIN32 |
---|
2504 | else { |
---|
2505 | puts ("Hit Enter or Return to close program."); |
---|
2506 | puts(" You may have to hit Enter or Return twice."); |
---|
2507 | getchar (); |
---|
2508 | getchar (); |
---|
2509 | phyRestoreConsoleAttributes(); |
---|
2510 | exit (exitcode); |
---|
2511 | } |
---|
2512 | #endif |
---|
2513 | } /* exxit */ |
---|
2514 | |
---|
2515 | |
---|
2516 | char gettc(FILE* file) |
---|
2517 | { /* catch eof's so that other functions not expecting an eof |
---|
2518 | * won't have to worry about it */ |
---|
2519 | int ch; |
---|
2520 | |
---|
2521 | ch = getc(file); |
---|
2522 | |
---|
2523 | if (ch == EOF ) { |
---|
2524 | puts("Unexpected End of File"); |
---|
2525 | exxit(-1); |
---|
2526 | } |
---|
2527 | /* printf("ch='%c'\n", (char)ch); */ |
---|
2528 | return ch; |
---|
2529 | } /* gettc */ |
---|
2530 | |
---|
2531 | |
---|
2532 | #ifdef WIN32 |
---|
2533 | void phySaveConsoleAttributes() |
---|
2534 | { |
---|
2535 | GetConsoleScreenBufferInfo( hConsoleOutput, &savecsbi ); |
---|
2536 | } /* PhySaveConsoleAttributes */ |
---|
2537 | |
---|
2538 | |
---|
2539 | void phySetConsoleAttributes() |
---|
2540 | { |
---|
2541 | hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); |
---|
2542 | |
---|
2543 | phySaveConsoleAttributes(); |
---|
2544 | |
---|
2545 | SetConsoleTextAttribute(hConsoleOutput, |
---|
2546 | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY); |
---|
2547 | } /* phySetConsoleAttributes */ |
---|
2548 | |
---|
2549 | |
---|
2550 | void phyRestoreConsoleAttributes() |
---|
2551 | { |
---|
2552 | COORD coordScreen = { 0, 0 }; |
---|
2553 | DWORD cCharsWritten; |
---|
2554 | DWORD dwConSize; |
---|
2555 | |
---|
2556 | dwConSize = savecsbi.dwSize.X * savecsbi.dwSize.Y; |
---|
2557 | |
---|
2558 | SetConsoleTextAttribute(hConsoleOutput, savecsbi.wAttributes); |
---|
2559 | |
---|
2560 | FillConsoleOutputAttribute( hConsoleOutput, savecsbi.wAttributes, |
---|
2561 | dwConSize, coordScreen, &cCharsWritten ); |
---|
2562 | } /* phyRestoreConsoleAttributes */ |
---|
2563 | |
---|
2564 | |
---|
2565 | void phyFillScreenColor() |
---|
2566 | { |
---|
2567 | COORD coordScreen = { 0, 0 }; |
---|
2568 | DWORD cCharsWritten; |
---|
2569 | CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ |
---|
2570 | DWORD dwConSize; |
---|
2571 | |
---|
2572 | GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ); |
---|
2573 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
---|
2574 | |
---|
2575 | FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes, |
---|
2576 | dwConSize, coordScreen, &cCharsWritten ); |
---|
2577 | } /* PhyFillScreenColor */ |
---|
2578 | |
---|
2579 | |
---|
2580 | void phyClearScreen() |
---|
2581 | { |
---|
2582 | COORD coordScreen = { 0, 0 }; /* here's where we'll home the |
---|
2583 | cursor */ |
---|
2584 | DWORD cCharsWritten; |
---|
2585 | CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ |
---|
2586 | DWORD dwConSize; /* number of character cells in |
---|
2587 | the current buffer */ |
---|
2588 | |
---|
2589 | /* get the number of character cells in the current buffer */ |
---|
2590 | |
---|
2591 | GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ); |
---|
2592 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; |
---|
2593 | |
---|
2594 | /* fill the entire screen with blanks */ |
---|
2595 | |
---|
2596 | FillConsoleOutputCharacter( hConsoleOutput, (TCHAR) ' ', |
---|
2597 | dwConSize, coordScreen, &cCharsWritten ); |
---|
2598 | |
---|
2599 | /* get the current text attribute */ |
---|
2600 | |
---|
2601 | GetConsoleScreenBufferInfo( hConsoleOutput, &csbi ); |
---|
2602 | |
---|
2603 | /* now set the buffer's attributes accordingly */ |
---|
2604 | |
---|
2605 | FillConsoleOutputAttribute( hConsoleOutput, csbi.wAttributes, |
---|
2606 | dwConSize, coordScreen, &cCharsWritten ); |
---|
2607 | |
---|
2608 | /* put the cursor at (0, 0) */ |
---|
2609 | |
---|
2610 | SetConsoleCursorPosition( hConsoleOutput, coordScreen ); |
---|
2611 | return; |
---|
2612 | } /* PhyClearScreen */ |
---|
2613 | #endif |
---|
2614 | |
---|