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