1/*
2 *  This file contains soft constraints wrappers for exterior loop evaluation (partition function version)
3 */
4struct sc_ext_exp_dat;
5
6typedef FLT_OR_DBL (sc_ext_exp_cb)(int                    i,
7                                   int                    j,
8                                   int                    k,
9                                   int                    l,
10                                   struct sc_ext_exp_dat  *data);
11
12typedef FLT_OR_DBL (sc_ext_exp_red_up)(int                    i,
13                                       int                    j,
14                                       struct sc_ext_exp_dat  *data);
15
16typedef FLT_OR_DBL (sc_ext_exp_split)(int                   i,
17                                      int                   j,
18                                      int                   k,
19                                      struct sc_ext_exp_dat *data);
20
21struct sc_ext_exp_dat {
22  FLT_OR_DBL                  **up;
23
24  sc_ext_exp_cb               *red_ext;
25  sc_ext_exp_cb               *red_stem;
26  sc_ext_exp_red_up           *red_up;
27  sc_ext_exp_split            *split;
28
29  vrna_callback_sc_exp_energy *user_cb;
30  void                        *user_data;
31
32  /* below attributes are for comparative structure prediction */
33  int                         n_seq;
34  unsigned int                **a2s;
35  FLT_OR_DBL                  ***up_comparative;
36
37  vrna_callback_sc_exp_energy **user_cb_comparative;
38  void                        **user_data_comparative;
39};
40
41
42PRIVATE INLINE FLT_OR_DBL
43sc_ext_exp_cb_red(int                   i,
44                  int                   j,
45                  int                   k,
46                  int                   l,
47                  struct sc_ext_exp_dat *data);
48
49
50PRIVATE INLINE FLT_OR_DBL
51sc_ext_exp_cb_red_comparative(int                   i,
52                              int                   j,
53                              int                   k,
54                              int                   l,
55                              struct sc_ext_exp_dat *data);
56
57
58PRIVATE INLINE FLT_OR_DBL
59sc_ext_exp_cb_red_user_to_ext(int                   i,
60                              int                   j,
61                              int                   k,
62                              int                   l,
63                              struct sc_ext_exp_dat *data);
64
65
66PRIVATE INLINE FLT_OR_DBL
67sc_ext_exp_cb_red_user_to_ext_comparative(int                   i,
68                                          int                   j,
69                                          int                   k,
70                                          int                   l,
71                                          struct sc_ext_exp_dat *data);
72
73
74PRIVATE INLINE FLT_OR_DBL
75sc_ext_exp_cb_red_user_def_to_ext(int                   i,
76                                  int                   j,
77                                  int                   k,
78                                  int                   l,
79                                  struct sc_ext_exp_dat *data);
80
81
82PRIVATE INLINE FLT_OR_DBL
83sc_ext_exp_cb_red_user_def_to_ext_comparative(int                   i,
84                                              int                   j,
85                                              int                   k,
86                                              int                   l,
87                                              struct sc_ext_exp_dat *data);
88
89
90PRIVATE INLINE FLT_OR_DBL
91sc_ext_exp_cb_red_user_to_stem(int                    i,
92                               int                    j,
93                               int                    k,
94                               int                    l,
95                               struct sc_ext_exp_dat  *data);
96
97
98PRIVATE INLINE FLT_OR_DBL
99sc_ext_exp_cb_red_user_to_stem_comparative(int                    i,
100                                           int                    j,
101                                           int                    k,
102                                           int                    l,
103                                           struct sc_ext_exp_dat  *data);
104
105
106PRIVATE INLINE FLT_OR_DBL
107sc_ext_exp_cb_red_user_def_to_stem(int                    i,
108                                   int                    j,
109                                   int                    k,
110                                   int                    l,
111                                   struct sc_ext_exp_dat  *data);
112
113
114PRIVATE INLINE FLT_OR_DBL
115sc_ext_exp_cb_red_user_def_to_stem_comparative(int                    i,
116                                               int                    j,
117                                               int                    k,
118                                               int                    l,
119                                               struct sc_ext_exp_dat  *data);
120
121
122PRIVATE INLINE FLT_OR_DBL
123sc_ext_exp_cb_up(int                    i,
124                 int                    j,
125                 struct sc_ext_exp_dat  *data);
126
127
128PRIVATE INLINE FLT_OR_DBL
129sc_ext_exp_cb_up_comparative(int                    i,
130                             int                    j,
131                             struct sc_ext_exp_dat  *data);
132
133
134PRIVATE INLINE FLT_OR_DBL
135sc_ext_exp_cb_up_user(int                   i,
136                      int                   j,
137                      struct sc_ext_exp_dat *data);
138
139
140PRIVATE INLINE FLT_OR_DBL
141sc_ext_exp_cb_up_user_comparative(int                   i,
142                                  int                   j,
143                                  struct sc_ext_exp_dat *data);
144
145
146PRIVATE INLINE FLT_OR_DBL
147sc_ext_exp_cb_up_user_def(int                   i,
148                          int                   j,
149                          struct sc_ext_exp_dat *data);
150
151
152PRIVATE INLINE FLT_OR_DBL
153sc_ext_exp_cb_up_user_def_comparative(int                   i,
154                                      int                   j,
155                                      struct sc_ext_exp_dat *data);
156
157
158PRIVATE INLINE FLT_OR_DBL
159sc_ext_exp_cb_split_user(int                    i,
160                         int                    j,
161                         int                    k,
162                         struct sc_ext_exp_dat  *data);
163
164
165PRIVATE INLINE FLT_OR_DBL
166sc_ext_exp_cb_split_user_comparative(int                    i,
167                                     int                    j,
168                                     int                    k,
169                                     struct sc_ext_exp_dat  *data);
170
171
172PRIVATE INLINE void
173init_sc_ext_exp(vrna_fold_compound_t  *fc,
174                struct sc_ext_exp_dat *sc_wrapper);
175
176
177PRIVATE INLINE void
178free_sc_ext_exp(struct sc_ext_exp_dat *sc_wrapper);
179
180
181PRIVATE INLINE FLT_OR_DBL
182sc_ext_exp_cb_red(int                   i,
183                  int                   j,
184                  int                   k,
185                  int                   l,
186                  struct sc_ext_exp_dat *data)
187{
188  unsigned int  start_2, length_1, length_2;
189  FLT_OR_DBL    q_sc, **sc_up;
190
191  sc_up = data->up;
192
193  q_sc = 1.;
194
195  length_1  = k - i;
196  start_2   = l + 1;
197  length_2  = j - l;
198
199  if (length_1 != 0)
200    q_sc *= sc_up[i][length_1];
201
202  if (length_2 != 0)
203    q_sc *= sc_up[start_2][length_2];
204
205  return q_sc;
206}
207
208
209PRIVATE INLINE FLT_OR_DBL
210sc_ext_exp_cb_red_comparative(int                   i,
211                              int                   j,
212                              int                   k,
213                              int                   l,
214                              struct sc_ext_exp_dat *data)
215{
216  unsigned int  s, start_2, length_1, length_2, **a2s;
217  FLT_OR_DBL    q_sc, ***sc_up;
218
219  sc_up = data->up_comparative;
220  a2s   = data->a2s;
221
222  q_sc = 1.;
223
224  for (s = 0; s < data->n_seq; s++) {
225    if (sc_up[s]) {
226      length_1  = a2s[s][k] - a2s[s][i];
227      start_2   = a2s[s][l] + 1;
228      length_2  = a2s[s][j] - a2s[s][l];
229
230      if (length_1 != 0)
231        q_sc *= sc_up[s][a2s[s][i]][length_1];
232
233      if (length_2 != 0)
234        q_sc *= sc_up[s][start_2][length_2];
235    }
236  }
237
238  return q_sc;
239}
240
241
242PRIVATE INLINE FLT_OR_DBL
243sc_ext_exp_cb_red_user_to_ext(int                   i,
244                              int                   j,
245                              int                   k,
246                              int                   l,
247                              struct sc_ext_exp_dat *data)
248{
249  return data->user_cb(i, j, k, l, VRNA_DECOMP_EXT_EXT, data->user_data);
250}
251
252
253PRIVATE INLINE FLT_OR_DBL
254sc_ext_exp_cb_red_user_to_ext_comparative(int                   i,
255                                          int                   j,
256                                          int                   k,
257                                          int                   l,
258                                          struct sc_ext_exp_dat *data)
259{
260  unsigned int  s;
261  FLT_OR_DBL    q_sc;
262
263  q_sc = 1.;
264
265  for (s = 0; s < data->n_seq; s++)
266    q_sc *=
267      data->user_cb_comparative[s](i, j, k, l, VRNA_DECOMP_EXT_EXT, data->user_data_comparative[s]);
268
269  return q_sc;
270}
271
272
273PRIVATE INLINE FLT_OR_DBL
274sc_ext_exp_cb_red_user_def_to_ext(int                   i,
275                                  int                   j,
276                                  int                   k,
277                                  int                   l,
278                                  struct sc_ext_exp_dat *data)
279{
280  return sc_ext_exp_cb_red(i, j, k, l, data) *
281         sc_ext_exp_cb_red_user_to_ext(i, j, k, l, data);
282}
283
284
285PRIVATE INLINE FLT_OR_DBL
286sc_ext_exp_cb_red_user_def_to_ext_comparative(int                   i,
287                                              int                   j,
288                                              int                   k,
289                                              int                   l,
290                                              struct sc_ext_exp_dat *data)
291{
292  return sc_ext_exp_cb_red_comparative(i, j, k, l, data) *
293         sc_ext_exp_cb_red_user_to_ext_comparative(i, j, k, l, data);
294}
295
296
297PRIVATE INLINE FLT_OR_DBL
298sc_ext_exp_cb_red_user_to_stem(int                    i,
299                               int                    j,
300                               int                    k,
301                               int                    l,
302                               struct sc_ext_exp_dat  *data)
303{
304  return data->user_cb(i, j, k, l, VRNA_DECOMP_EXT_STEM, data->user_data);
305}
306
307
308PRIVATE INLINE FLT_OR_DBL
309sc_ext_exp_cb_red_user_to_stem_comparative(int                    i,
310                                           int                    j,
311                                           int                    k,
312                                           int                    l,
313                                           struct sc_ext_exp_dat  *data)
314{
315  unsigned int  s;
316  FLT_OR_DBL    q_sc;
317
318  q_sc = 1.;
319
320  for (s = 0; s < data->n_seq; s++)
321    q_sc *=
322      data->user_cb_comparative[s](i, j, k, l, VRNA_DECOMP_EXT_STEM,
323                                   data->user_data_comparative[s]);
324
325  return q_sc;
326}
327
328
329PRIVATE INLINE FLT_OR_DBL
330sc_ext_exp_cb_red_user_def_to_stem(int                    i,
331                                   int                    j,
332                                   int                    k,
333                                   int                    l,
334                                   struct sc_ext_exp_dat  *data)
335{
336  return sc_ext_exp_cb_red(i, j, k, l, data) *
337         sc_ext_exp_cb_red_user_to_stem(i, j, k, l, data);
338}
339
340
341PRIVATE INLINE FLT_OR_DBL
342sc_ext_exp_cb_red_user_def_to_stem_comparative(int                    i,
343                                               int                    j,
344                                               int                    k,
345                                               int                    l,
346                                               struct sc_ext_exp_dat  *data)
347{
348  return sc_ext_exp_cb_red_comparative(i, j, k, l, data) *
349         sc_ext_exp_cb_red_user_to_stem_comparative(i, j, k, l, data);
350}
351
352
353PRIVATE INLINE FLT_OR_DBL
354sc_ext_exp_cb_up(int                    i,
355                 int                    j,
356                 struct sc_ext_exp_dat  *data)
357{
358  unsigned int  length;
359  FLT_OR_DBL    q_sc, **sc_up;
360
361  sc_up   = data->up;
362  length  = j - i + 1;
363  q_sc    = 1.;
364
365  if (length != 0)
366    q_sc *= sc_up[i][length];
367
368  return q_sc;
369}
370
371
372PRIVATE INLINE FLT_OR_DBL
373sc_ext_exp_cb_up_comparative(int                    i,
374                             int                    j,
375                             struct sc_ext_exp_dat  *data)
376{
377  unsigned int  length, s, **a2s;
378  FLT_OR_DBL    q_sc, ***sc_up;
379
380  a2s   = data->a2s;
381  sc_up = data->up_comparative;
382
383  q_sc = 1.;
384
385  for (s = 0; s < data->n_seq; s++) {
386    length = a2s[s][j - 1] - a2s[s][i];
387
388    if (length != 0)
389      q_sc *= sc_up[s][a2s[s][i]][length];
390  }
391
392  return q_sc;
393}
394
395
396PRIVATE INLINE FLT_OR_DBL
397sc_ext_exp_cb_up_user(int                   i,
398                      int                   j,
399                      struct sc_ext_exp_dat *data)
400{
401  return data->user_cb(i, j, i, j, VRNA_DECOMP_EXT_UP, data->user_data);
402}
403
404
405PRIVATE INLINE FLT_OR_DBL
406sc_ext_exp_cb_up_user_comparative(int                   i,
407                                  int                   j,
408                                  struct sc_ext_exp_dat *data)
409{
410  unsigned int  s;
411  FLT_OR_DBL    q_sc;
412
413  q_sc = 1.;
414  for (s = 0; s < data->n_seq; s++)
415    q_sc *=
416      data->user_cb_comparative[s](i, j, i, j, VRNA_DECOMP_EXT_UP, data->user_data_comparative[s]);
417
418  return q_sc;
419}
420
421
422PRIVATE INLINE FLT_OR_DBL
423sc_ext_exp_cb_up_user_def(int                   i,
424                          int                   j,
425                          struct sc_ext_exp_dat *data)
426{
427  return sc_ext_exp_cb_up(i, j, data) *
428         sc_ext_exp_cb_up_user(i, j, data);
429}
430
431
432PRIVATE INLINE FLT_OR_DBL
433sc_ext_exp_cb_up_user_def_comparative(int                   i,
434                                      int                   j,
435                                      struct sc_ext_exp_dat *data)
436{
437  return sc_ext_exp_cb_up_comparative(i, j, data) *
438         sc_ext_exp_cb_up_user_comparative(i, j, data);
439}
440
441
442PRIVATE INLINE FLT_OR_DBL
443sc_ext_exp_cb_split_user(int                    i,
444                         int                    j,
445                         int                    k,
446                         struct sc_ext_exp_dat  *data)
447{
448  return data->user_cb(i, j, k - 1, k, VRNA_DECOMP_EXT_EXT_EXT, data->user_data);
449}
450
451
452PRIVATE INLINE FLT_OR_DBL
453sc_ext_exp_cb_split_user_comparative(int                    i,
454                                     int                    j,
455                                     int                    k,
456                                     struct sc_ext_exp_dat  *data)
457{
458  unsigned int  s;
459  FLT_OR_DBL    q_sc;
460
461  q_sc = 1.;
462
463  for (s = 0; s < data->n_seq; s++)
464    q_sc *=
465      data->user_cb_comparative[s](i, j, k - 1, k, VRNA_DECOMP_EXT_EXT_EXT,
466                                   data->user_data_comparative[s]);
467
468  return q_sc;
469}
470
471
472PRIVATE INLINE void
473init_sc_ext_exp(vrna_fold_compound_t  *fc,
474                struct sc_ext_exp_dat *sc_wrapper)
475{
476  vrna_sc_t *sc, **scs;
477
478  sc_wrapper->up                    = NULL;
479  sc_wrapper->user_cb               = NULL;
480  sc_wrapper->user_data             = NULL;
481  sc_wrapper->n_seq                 = 1;
482  sc_wrapper->a2s                   = NULL;
483  sc_wrapper->up_comparative        = NULL;
484  sc_wrapper->user_cb_comparative   = NULL;
485  sc_wrapper->user_data_comparative = NULL;
486
487  /* no soft constraints by default */
488  sc_wrapper->red_ext   = NULL;
489  sc_wrapper->red_stem  = NULL;
490  sc_wrapper->red_up    = NULL;
491  sc_wrapper->split     = NULL;
492
493  switch (fc->type) {
494    case VRNA_FC_TYPE_SINGLE:
495      sc = fc->sc;
496
497      if (sc) {
498        sc_wrapper->up        = sc->exp_energy_up;
499        sc_wrapper->user_cb   = sc->exp_f;
500        sc_wrapper->user_data = sc->data;
501
502        /* bind correct wrapper functions */
503        if (sc->exp_energy_up) {
504          if (sc->exp_f) {
505            sc_wrapper->red_ext   = &sc_ext_exp_cb_red_user_def_to_ext;
506            sc_wrapper->red_stem  = &sc_ext_exp_cb_red_user_def_to_stem;
507            sc_wrapper->red_up    = &sc_ext_exp_cb_up_user_def;
508            sc_wrapper->split     = &sc_ext_exp_cb_split_user;
509          } else {
510            sc_wrapper->red_ext   = &sc_ext_exp_cb_red;
511            sc_wrapper->red_stem  = &sc_ext_exp_cb_red;
512            sc_wrapper->red_up    = &sc_ext_exp_cb_up;
513          }
514        } else if (sc->exp_f) {
515          sc_wrapper->red_ext   = &sc_ext_exp_cb_red_user_to_ext;
516          sc_wrapper->red_stem  = &sc_ext_exp_cb_red_user_to_stem;
517          sc_wrapper->red_up    = &sc_ext_exp_cb_up_user;
518          sc_wrapper->split     = &sc_ext_exp_cb_split_user;
519        }
520      }
521
522      break;
523
524    case VRNA_FC_TYPE_COMPARATIVE:
525      scs               = fc->scs;
526      sc_wrapper->n_seq = fc->n_seq;
527      sc_wrapper->a2s   = fc->a2s;
528
529      if (scs) {
530        unsigned int s;
531
532        sc_wrapper->up_comparative = (FLT_OR_DBL ***)vrna_alloc(
533          sizeof(FLT_OR_DBL * *) * fc->n_seq);
534        sc_wrapper->user_cb_comparative =
535          (vrna_callback_sc_exp_energy **)vrna_alloc(
536            sizeof(vrna_callback_sc_exp_energy *) * fc->n_seq);
537        sc_wrapper->user_data_comparative = (void **)vrna_alloc(sizeof(void *) * fc->n_seq);
538
539        int provides_sc_up      = 0;
540        int provides_sc_user_cb = 0;
541
542        for (s = 0; s < fc->n_seq; s++) {
543          if (scs[s]) {
544            sc_wrapper->up_comparative[s]         = scs[s]->exp_energy_up;
545            sc_wrapper->user_cb_comparative[s]    = scs[s]->exp_f;
546            sc_wrapper->user_data_comparative[s]  = scs[s]->data;
547            if (scs[s]->exp_energy_up)
548              provides_sc_up = 1;
549
550            if (scs[s]->exp_f)
551              provides_sc_user_cb = 1;
552
553            /* bind the correct wrapper functions */
554            if (provides_sc_up) {
555              if (provides_sc_user_cb) {
556                sc_wrapper->red_ext   = &sc_ext_exp_cb_red_user_def_to_ext_comparative;
557                sc_wrapper->red_stem  = &sc_ext_exp_cb_red_user_def_to_stem_comparative;
558                sc_wrapper->red_up    = &sc_ext_exp_cb_up_user_def_comparative;
559                sc_wrapper->split     = &sc_ext_exp_cb_split_user_comparative;
560              } else {
561                sc_wrapper->red_ext   = &sc_ext_exp_cb_red_comparative;
562                sc_wrapper->red_stem  = &sc_ext_exp_cb_red_comparative;
563                sc_wrapper->red_up    = &sc_ext_exp_cb_up_comparative;
564              }
565            } else if (provides_sc_user_cb) {
566              sc_wrapper->red_ext   = &sc_ext_exp_cb_red_user_to_ext_comparative;
567              sc_wrapper->red_stem  = &sc_ext_exp_cb_red_user_to_stem_comparative;
568              sc_wrapper->red_up    = &sc_ext_exp_cb_up_user_comparative;
569              sc_wrapper->split     = &sc_ext_exp_cb_split_user_comparative;
570            }
571          }
572        }
573      }
574
575      break;
576  }
577}
578
579
580PRIVATE INLINE void
581free_sc_ext_exp(struct sc_ext_exp_dat *sc_wrapper)
582{
583  free(sc_wrapper->up_comparative);
584  free(sc_wrapper->user_cb_comparative);
585  free(sc_wrapper->user_data_comparative);
586}
587