1/*
2 *  This file contains hard constraint wrappers required by both, MFE and
3 *  partition function version of exterior loop evaluation
4 */
5
6struct hc_ext_def_dat {
7  unsigned int              n;
8  unsigned char             *mx;
9  unsigned char             **mx_window;
10  unsigned int              *sn;
11  int                       *hc_up;
12  void                      *hc_dat;
13  vrna_callback_hc_evaluate *hc_f;
14};
15
16PRIVATE unsigned char
17hc_ext_cb_def(int           i,
18              int           j,
19              int           k,
20              int           l,
21              unsigned char d,
22              void          *data);
23
24
25PRIVATE unsigned char
26hc_ext_cb_sn(int            i,
27             int            j,
28             int            k,
29             int            l,
30             unsigned char  d,
31             void           *data);
32
33
34PRIVATE unsigned char
35hc_ext_cb_def_window(int            i,
36                     int            j,
37                     int            k,
38                     int            l,
39                     unsigned char  d,
40                     void           *data);
41
42
43PRIVATE unsigned char
44hc_ext_cb_def_user(int            i,
45                   int            j,
46                   int            k,
47                   int            l,
48                   unsigned char  d,
49                   void           *data);
50
51
52PRIVATE unsigned char
53hc_ext_cb_def_sn_user(int           i,
54                      int           j,
55                      int           k,
56                      int           l,
57                      unsigned char d,
58                      void          *data);
59
60
61PRIVATE unsigned char
62hc_ext_cb_def_user_window(int           i,
63                          int           j,
64                          int           k,
65                          int           l,
66                          unsigned char d,
67                          void          *data);
68
69
70PRIVATE INLINE vrna_callback_hc_evaluate *
71prepare_hc_ext_def(vrna_fold_compound_t   *fc,
72                   struct hc_ext_def_dat  *dat);
73
74
75PRIVATE INLINE vrna_callback_hc_evaluate *
76prepare_hc_ext_def_window(vrna_fold_compound_t  *fc,
77                          struct hc_ext_def_dat *dat);
78
79
80/*
81 #################################
82 # BEGIN OF FUNCTION DEFINITIONS #
83 #################################
84 */
85PRIVATE unsigned char
86hc_ext_cb_def(int           i,
87              int           j,
88              int           k,
89              int           l,
90              unsigned char d,
91              void          *data)
92{
93  int                   di, dj;
94  unsigned char         eval;
95  unsigned int          n;
96  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
97
98  eval  = (unsigned char)0;
99  di    = k - i;
100  dj    = j - l;
101  n     = dat->n;
102
103  switch (d) {
104    case VRNA_DECOMP_EXT_EXT_STEM:
105      if (dat->mx[n * j + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
106        eval = (unsigned char)1;
107        if (i != l) {
108          /* otherwise, stem spans from i to j */
109          di = l - k - 1;
110          if ((di != 0) && (dat->hc_up[k + 1] < di))
111            eval = (unsigned char)0;
112        }
113      }
114
115      break;
116
117    case VRNA_DECOMP_EXT_STEM_EXT:
118      if (dat->mx[n * k + i] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
119        eval = (unsigned char)1;
120        if (i != l) {
121          /* otherwise, stem spans from i to j */
122          di = l - k - 1;
123          if ((di != 0) && (dat->hc_up[k + 1] < di))
124            eval = (unsigned char)0;
125        }
126      }
127
128      break;
129
130    case VRNA_DECOMP_EXT_EXT_STEM1:
131      if (dat->mx[n * (j - 1) + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
132        eval = (unsigned char)1;
133        if (dat->hc_up[j] == 0)
134          eval = (unsigned char)0;
135
136        if (i != l) {
137          /* otherwise, stem spans from i to j - 1 */
138          di = l - k - 1;
139
140          if ((di != 0) && (dat->hc_up[k + 1] < di))
141            eval = (unsigned char)0;
142        }
143      }
144
145      break;
146
147    case VRNA_DECOMP_EXT_EXT_EXT:
148      eval  = (unsigned char)1;
149      di    = l - k - 1;
150      if ((di != 0) && (dat->hc_up[k + 1] < di))
151        eval = (unsigned char)0;
152
153      break;
154
155    case VRNA_DECOMP_EXT_STEM:
156      if (dat->mx[n * k + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
157        eval = (unsigned char)1;
158        if ((di != 0) && (dat->hc_up[i] < di))
159          eval = (unsigned char)0;
160
161        if ((dj != 0) && (dat->hc_up[l + 1] < dj))
162          eval = (unsigned char)0;
163      }
164
165      break;
166
167    case VRNA_DECOMP_EXT_EXT:
168      eval = (unsigned char)1;
169      if ((di != 0) && (dat->hc_up[i] < di))
170        eval = (unsigned char)0;
171
172      if ((dj != 0) && (dat->hc_up[l + 1] < dj))
173        eval = (unsigned char)0;
174
175      break;
176
177    case VRNA_DECOMP_EXT_UP:
178      di    = j - i + 1;
179      eval  = (dat->hc_up[i] >= di) ? (unsigned char)1 : (unsigned char)0;
180      break;
181
182    case VRNA_DECOMP_EXT_STEM_OUTSIDE:
183      if (dat->mx[n * k + l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP)
184        eval = (unsigned char)1;
185
186      break;
187
188    default:
189      vrna_message_warning("hc_cb@exterior_loops.c: "
190                           "Unrecognized decomposition %d",
191                           d);
192  }
193
194  return eval;
195}
196
197
198PRIVATE unsigned char
199hc_ext_cb_sn(int            i,
200             int            j,
201             int            k,
202             int            l,
203             unsigned char  d,
204             void           *data)
205{
206  unsigned int          *sn;
207  unsigned char         eval;
208  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
209
210  sn    = dat->sn;
211  eval  = (unsigned char)0;
212
213  /* for now with the 'old' cofold implementation, we allow for any decomposition */
214  return (unsigned char)1;
215
216  switch (d) {
217    case VRNA_DECOMP_EXT_EXT_STEM1:
218      if (sn[j - 1] != sn[j])
219        break;
220
221    /* fall through */
222    case VRNA_DECOMP_EXT_EXT_STEM:
223    /* fall through */
224    case VRNA_DECOMP_EXT_STEM_EXT:
225    /* fall through */
226    case VRNA_DECOMP_EXT_EXT_EXT:
227      if (sn[k] == sn[l])
228        eval = (unsigned char)1;
229
230      break;
231
232    case VRNA_DECOMP_EXT_STEM:
233    /* fall through */
234    case VRNA_DECOMP_EXT_EXT:
235      if ((sn[i] == sn[k]) && (sn[l] == sn[j]))
236        eval = (unsigned char)1;
237
238      break;
239
240    case VRNA_DECOMP_EXT_UP:
241      if (sn[i] == sn[j])
242        eval = (unsigned char)1;
243
244      break;
245
246    default:
247      vrna_message_warning("hc_cb@exterior_loops.c: "
248                           "Unrecognized decomposition %d",
249                           d);
250  }
251
252  return eval;
253}
254
255
256PRIVATE unsigned char
257hc_ext_cb_def_window(int            i,
258                     int            j,
259                     int            k,
260                     int            l,
261                     unsigned char  d,
262                     void           *data)
263{
264  int                   di, dj;
265  unsigned char         eval;
266  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
267
268  eval  = (unsigned char)0;
269  di    = k - i;
270  dj    = j - l;
271
272  switch (d) {
273    case VRNA_DECOMP_EXT_EXT_STEM:
274      if (dat->mx_window[l][j - l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
275        eval = (unsigned char)1;
276        if (i != l) {
277          /* otherwise, stem spans from i to j */
278          di = l - k - 1;
279          if ((di != 0) && (dat->hc_up[k + 1] < di))
280            eval = (unsigned char)0;
281        }
282      }
283
284      break;
285
286    case VRNA_DECOMP_EXT_STEM_EXT:
287      if (dat->mx_window[i][k - i] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
288        eval = (unsigned char)1;
289        if (j != k) {
290          /* otherwise, stem spans from i to j */
291          dj = l - k - 1;
292          if ((dj != 0) && (dat->hc_up[k + 1] < dj))
293            eval = (unsigned char)0;
294        }
295      }
296
297      break;
298
299    case VRNA_DECOMP_EXT_EXT_STEM1:
300      if (dat->mx_window[l][j - 1 - l] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
301        eval = (unsigned char)1;
302
303        if (dat->hc_up[j] == 0)
304          eval = (unsigned char)0;
305
306        if (i != l) {
307          /* otherwise, stem spans from i to j - 1 */
308          di = l - k - 1;
309
310          if ((di != 0) && (dat->hc_up[k + 1] < di))
311            eval = (unsigned char)0;
312        }
313      }
314
315      break;
316
317    case VRNA_DECOMP_EXT_STEM_EXT1:
318      if (dat->mx_window[i + 1][k - (i + 1)] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
319        eval = (unsigned char)1;
320
321        if (dat->hc_up[i] == 0)
322          eval = (unsigned char)0;
323
324        if (j != k) {
325          /* otherwise, stem spans from i + 1 to j */
326          dj = l - k - 1;
327
328          if ((dj != 0) && (dat->hc_up[k + 1] < dj))
329            eval = (unsigned char)0;
330        }
331      }
332
333      break;
334
335    case VRNA_DECOMP_EXT_STEM:
336      if (dat->mx_window[k][l - k] & VRNA_CONSTRAINT_CONTEXT_EXT_LOOP) {
337        eval = (unsigned char)1;
338        if ((di != 0) && (dat->hc_up[i] < di))
339          eval = (unsigned char)0;
340
341        if ((dj != 0) && (dat->hc_up[l + 1] < dj))
342          eval = (unsigned char)0;
343      }
344
345      break;
346
347    case VRNA_DECOMP_EXT_EXT_EXT:
348      eval  = (unsigned char)1;
349      di    = l - k - 1;
350      if ((di != 0) && (dat->hc_up[k + 1] < di))
351        eval = (unsigned char)0;
352
353      break;
354
355    case VRNA_DECOMP_EXT_EXT:
356      eval = (unsigned char)1;
357      if ((di != 0) && (dat->hc_up[i] < di))
358        eval = (unsigned char)0;
359
360      if ((dj != 0) && (dat->hc_up[l + 1] < dj))
361        eval = (unsigned char)0;
362
363      break;
364
365    case VRNA_DECOMP_EXT_UP:
366      di    = j - i + 1;
367      eval  = (dat->hc_up[i] >= di) ? (unsigned char)1 : (unsigned char)0;
368      break;
369
370    default:
371      vrna_message_warning("hc_cb@exterior_loops.c: "
372                           "Unrecognized decomposition %d",
373                           d);
374  }
375
376  return eval;
377}
378
379
380PRIVATE unsigned char
381hc_ext_cb_def_sn(int            i,
382                 int            j,
383                 int            k,
384                 int            l,
385                 unsigned char  d,
386                 void           *data)
387{
388  unsigned char eval;
389
390  eval  = hc_ext_cb_def(i, j, k, l, d, data);
391  eval  = hc_ext_cb_sn(i, j, k, l, d, data) ? eval : (unsigned char)0;
392
393  return eval;
394}
395
396
397PRIVATE unsigned char
398hc_ext_cb_def_user(int            i,
399                   int            j,
400                   int            k,
401                   int            l,
402                   unsigned char  d,
403                   void           *data)
404{
405  unsigned char         eval;
406  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
407
408  eval  = hc_ext_cb_def(i, j, k, l, d, data);
409  eval  = (dat->hc_f(i, j, k, l, d, dat->hc_dat)) ? eval : (unsigned char)0;
410
411  return eval;
412}
413
414
415PRIVATE unsigned char
416hc_ext_cb_def_sn_user(int           i,
417                      int           j,
418                      int           k,
419                      int           l,
420                      unsigned char d,
421                      void          *data)
422{
423  unsigned char         eval;
424  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
425
426  eval  = hc_ext_cb_def(i, j, k, l, d, data);
427  eval  = hc_ext_cb_sn(i, j, k, l, d, data) ? eval : (unsigned char)0;
428  eval  = dat->hc_f(i, j, k, l, d, dat->hc_dat) ? eval : (unsigned char)0;
429
430  return eval;
431}
432
433
434PRIVATE unsigned char
435hc_ext_cb_def_user_window(int           i,
436                          int           j,
437                          int           k,
438                          int           l,
439                          unsigned char d,
440                          void          *data)
441{
442  unsigned char         eval;
443  struct hc_ext_def_dat *dat = (struct hc_ext_def_dat *)data;
444
445  eval  = hc_ext_cb_def_window(i, j, k, l, d, data);
446  eval  = dat->hc_f(i, j, k, l, d, dat->hc_dat) ? eval : (unsigned char)0;
447
448  return eval;
449}
450
451
452PRIVATE INLINE vrna_callback_hc_evaluate *
453prepare_hc_ext_def(vrna_fold_compound_t   *fc,
454                   struct hc_ext_def_dat  *dat)
455{
456  dat->mx     = fc->hc->mx;
457  dat->n      = fc->length;
458  dat->hc_up  = fc->hc->up_ext;
459  dat->sn     = fc->strand_number;
460
461  if (fc->hc->f) {
462    dat->hc_f   = fc->hc->f;
463    dat->hc_dat = fc->hc->data;
464    return (fc->strands == 1) ? &hc_ext_cb_def_user : &hc_ext_cb_def_sn_user;
465  }
466
467  return (fc->strands == 1) ? &hc_ext_cb_def : &hc_ext_cb_def_sn;
468}
469
470
471PRIVATE INLINE vrna_callback_hc_evaluate *
472prepare_hc_ext_def_window(vrna_fold_compound_t  *fc,
473                          struct hc_ext_def_dat *dat)
474{
475  dat->mx_window  = fc->hc->matrix_local;
476  dat->hc_up      = fc->hc->up_ext;
477  dat->sn         = fc->strand_number;
478
479  if (fc->hc->f) {
480    dat->hc_f   = fc->hc->f;
481    dat->hc_dat = fc->hc->data;
482    return &hc_ext_cb_def_user_window;
483  }
484
485  return &hc_ext_cb_def_window;
486}
487