Next version of JABA
[jabaws.git] / binaries / src / fasta34 / work_thr.c
1 /* copyright (c) 1996, 1997, 1998, 1999 William R. Pearson and the
2    U. of Virginia */
3
4 /* $Name: fa_34_26_5 $ - $Id: work_thr.c,v 1.23 2007/04/26 18:33:20 wrp Exp $ */
5
6 /* work_thr.c - threaded worker */
7
8 /* modified 21-Oct-1998 to work with reverse complement for DNA */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
14 #include <sys/types.h>
15 #include <signal.h>
16
17 #include "defs.h"               /* various constants */
18 #include "mw.h"                 /* defines beststr */
19 #include "structs.h"
20 #include "param.h"              /* pstruct, thr_str, buf_head, rstruct */
21
22 /***************************************/
23 /* thread global variable declarations */
24 /***************************************/
25
26 #define XTERNAL
27 #include "thr.h"
28 #undef XTERNAL
29
30 void alloc_pam (int, int, struct pstruct *);
31 int **alloc_pam2p(int, int);
32 void revcomp(unsigned char *seq, int n, int *c_nt);
33 #ifdef WIN32
34 void pthread_exit(void *);
35 #else
36 void THR_EXIT(void *);
37 #endif
38
39 /* functions getting/sending buffers to threads (thr_sub.c) */
40 extern void wait_thr(void);
41 extern int get_wbuf(struct buf_head **cur_buf, int max_work_buf);
42 extern void put_wbuf(struct buf_head *cur_buf, int max_work_buf);
43
44 /* dropxx.c functions */
45 extern void init_work (unsigned char *aa0, int n0,
46                        struct pstruct *ppst, void **f_arg);
47
48 extern void do_work (unsigned char *aa0, int n0, unsigned char *aa1, int n1,
49                      int frame,
50                      struct pstruct *ppst, void *f_str, int qr_flg,
51                      struct rstruct *rst);
52
53 extern void close_work (unsigned char *, int, struct pstruct *, void **);
54
55 extern void irand(int);
56 extern int shuffle(unsigned char *, unsigned char *, int);
57 extern int wshuffle(unsigned char *, unsigned char *, int, int, int *);
58 extern void qshuffle(unsigned char *aa0, int n0, int nm0);
59 extern void free_pam2p(int **);
60
61 void
62 work_thread (struct thr_str *work_info)
63 {
64   struct buf_head *cur_buf;
65   struct buf_str *cur_buf_p;
66   struct buf_str *p_rbuf;
67   unsigned char *aa1s;
68   int cur_cnt;
69   int my_worker;
70   int i, j, npam, n0, nm0;
71   int ix_score, debug_lib, zsflag, zs_win, do_shuffle, ieven=0;
72   int frame;
73
74   struct rstruct rrst;
75   struct pstruct my_pst, *my_ppst;
76   unsigned char *aa0[6], *aa0s;
77   void *f_str[6], *qf_str;
78
79   my_worker = work_info->worker;
80
81   wait_thr();   /* wait for start_thread predicate to drop to  0 */
82
83   /* do init_work */
84
85   /* let each thread have its own copy of the query */
86   n0 = work_info->n0;
87   nm0 = work_info->nm0;
88
89   if ((aa0[0]=(unsigned char *)calloc((size_t)n0+2,sizeof(unsigned char)))
90       ==NULL) {
91     fprintf(stderr," cannot allocate aa00[%d] for worker %d\n",
92             n0, my_worker);
93     exit(1);
94   }
95   *aa0[0]='\0';
96   aa0[0]++;
97   memcpy(aa0[0],work_info->aa0,n0+1);
98
99   /* make certain that all but 0 have their own copy of pst */
100   if (my_worker) {
101     my_ppst = &my_pst;
102     memcpy(my_ppst,work_info->ppst,sizeof(struct pstruct));
103
104     alloc_pam(MAXSQ, MAXSQ, my_ppst);
105
106     npam = (my_pst.ext_sq_set) ? my_pst.nsqx : my_pst.nsq;
107
108     for (i=0; i<=npam; i++) {
109       for (j=0; j<=npam; j++) {
110         my_pst.pam2[0][i][j] = work_info->ppst->pam2[0][i][j];
111         my_pst.pam2[1][i][j] = work_info->ppst->pam2[1][i][j];
112       }
113     }
114
115     if (work_info->ppst->pam_pssm && work_info->ppst->pam2p[0]) {
116       my_ppst->pam2p[0] = alloc_pam2p(n0,npam);
117       my_ppst->pam2p[1] = alloc_pam2p(n0,npam);
118       for (i=0; i<n0; i++) {
119         for (j=0; j <= npam; j++) {
120           my_pst.pam2p[0][i][j] = work_info->ppst->pam2p[0][i][j];
121           my_pst.pam2p[1][i][j] = work_info->ppst->pam2p[1][i][j];
122         }
123       }
124     }
125   }
126   else my_ppst=work_info->ppst;
127
128   /* note that aa[5,4,3,2] are never used, but are provided so that frame
129      can range from 0 .. 5; likewise for f_str[5..2] */
130
131   aa0[5] = aa0[4] = aa0[3] = aa0[2] = aa0[1] = aa0[0];
132   init_work (aa0[0], n0, my_ppst, &f_str[0]);
133
134   f_str[5] = f_str[4] = f_str[3] = f_str[2] = f_str[1] = f_str[0];
135
136   if (work_info->qframe == 2) {
137     if ((aa0[1]=(unsigned char *)calloc((size_t)n0+2,sizeof(unsigned char)))==NULL) {
138       fprintf(stderr," cannot allocate aa01[%d] for worker %d\n",
139             n0, my_worker);
140     }
141     *aa0[1]='\0';
142     aa0[1]++;
143     memcpy(aa0[1],work_info->aa0,n0+1);
144     revcomp(aa0[1],n0,my_ppst->c_nt);
145     init_work (aa0[1], n0, my_ppst, &f_str[1]);
146   }
147
148   if (work_info->qshuffle) {
149     if ((aa0s=(unsigned char *)calloc(n0+2,sizeof(char)))==NULL) {
150       fprintf(stderr,"cannot allocate aa0s[%d]\n",n0+2);
151       exit(1);
152     }
153     *aa0s='\0';
154     aa0s++;
155     memcpy(aa0s,aa0[0],n0);
156     qshuffle(aa0s,n0,nm0);
157     init_work (aa0s, n0, my_ppst, &qf_str);
158   }
159
160   ix_score = my_ppst->score_ix;
161   debug_lib = my_ppst->debug_lib;
162   zsflag = my_ppst->zsflag;
163   zs_win = my_ppst->zs_win;
164
165   if (zsflag >= 10) {
166     if((aa1s=calloc(work_info->max_tot+1,sizeof(char))) == NULL) {
167       fprintf(stderr,"unable to allocate shuffled library sequence\n");
168     }
169     else {
170       *aa1s=0;
171       aa1s++;
172       do_shuffle =1;
173       irand(0);
174     }
175   }
176   else {do_shuffle = 0;}
177
178   /* main work loop */
179   while (get_wbuf(&cur_buf,work_info->max_work_buf)) {
180
181     cur_cnt = cur_buf->buf_cnt;
182     if (cur_cnt == -1) break;
183     cur_buf_p = cur_buf->buf;
184
185     while (cur_cnt--) { /* count down the number of sequences */
186       p_rbuf = cur_buf_p++;   /* step through each sequence */
187       p_rbuf->rst.score[0] = p_rbuf->rst.score[1] = p_rbuf->rst.score[2] = 0;
188       frame = p_rbuf->frame;
189
190 #ifdef DEBUG
191       if (debug_lib) {
192         if (frame >= 2) fprintf(stderr,"* frame: %d\n",frame);
193         for (i=0; i<p_rbuf->n1; i++)
194           if (p_rbuf->aa1b[i]>=my_ppst->nsqx) {
195             fprintf(stderr,
196                     "%s residue[%d/%d] %d range (%d)\n",
197                     p_rbuf->libstr,i,p_rbuf->n1,p_rbuf->aa1b[i],my_ppst->nsqx);
198             p_rbuf->aa1b[i]=0;
199             p_rbuf->n1=i-1;
200             break;
201           }
202       }
203 #endif
204
205       do_work (aa0[frame], n0, p_rbuf->aa1b, p_rbuf->n1, frame,
206                my_ppst, f_str[frame], 0, &p_rbuf->rst);
207       
208       if (work_info->qshuffle) {
209         do_work(aa0s,n0,p_rbuf->aa1b, p_rbuf->n1, frame,
210                 my_ppst, qf_str, 1, &rrst);
211         p_rbuf->qr_score = rrst.score[ix_score];
212         p_rbuf->qr_escore = rrst.escore;
213       }
214
215       if (do_shuffle) {
216         if (zs_win > 0) wshuffle(p_rbuf->aa1b,aa1s,p_rbuf->n1,zs_win,&ieven);
217         else shuffle(p_rbuf->aa1b,aa1s,p_rbuf->n1);
218
219         do_work (aa0[frame], n0, aa1s, p_rbuf->n1, frame,
220                  my_ppst, f_str[frame], 0, &rrst);
221         p_rbuf->r_score = rrst.score[ix_score];
222         p_rbuf->r_escore = rrst.escore;
223       }
224     }
225
226     cur_buf->have_results = 1;
227
228     put_wbuf(cur_buf,work_info->max_work_buf);
229
230   } /* end main while */
231
232   close_work(aa0[0], n0, my_ppst, &f_str[0]);
233   free(aa0[0]-1);
234   if (work_info->qframe == 2) {
235     close_work(aa0[1], n0, my_ppst, &f_str[1]);
236     free(aa0[1]-1);
237   }
238
239   if (do_shuffle) free(aa1s-1);
240
241   if (my_worker) {
242     free(my_pst.pam2[1][0]);
243     free(my_pst.pam2[0][0]);
244     free(my_pst.pam2[1]);
245     free(my_pst.pam2[0]);
246     
247     if (my_pst.pam_pssm) {
248       free_pam2p(my_pst.pam2p[0]);
249       free_pam2p(my_pst.pam2p[1]);
250     }
251   }
252
253 #ifdef WIN32
254   pthread_exit(&work_info->status);
255 #else
256   THR_EXIT(&work_info->status);
257 #endif
258
259 }  /* end work_thread */
260