1 #ifndef VIENNA_RNA_PACKAGE_LOOPS_INTERNAL_H
2 #define VIENNA_RNA_PACKAGE_LOOPS_INTERNAL_H
3
4 #include <ViennaRNA/utils/basic.h>
5 #include <ViennaRNA/params/default.h>
6 #include <ViennaRNA/datastructures/basic.h>
7 #include <ViennaRNA/fold_compound.h>
8 #include <ViennaRNA/params/basic.h>
9 #include <ViennaRNA/constraints/hard.h>
10 #include <ViennaRNA/constraints/soft.h>
11
12 #ifdef VRNA_WARN_DEPRECATED
13 # if defined(DEPRECATED)
14 # undef DEPRECATED
15 # endif
16 # if defined(__clang__)
17 # define DEPRECATED(func, msg) func __attribute__ ((deprecated("", msg)))
18 # elif defined(__GNUC__)
19 # define DEPRECATED(func, msg) func __attribute__ ((deprecated(msg)))
20 # else
21 # define DEPRECATED(func, msg) func
22 # endif
23 #else
24 # define DEPRECATED(func, msg) func
25 #endif
26
27 #ifdef __GNUC__
28 # define INLINE inline
29 #else
30 # define INLINE
31 #endif
32
33 /**
34 * @file ViennaRNA/loops/internal.h
35 * @ingroup eval, eval_loops, eval_loops_int
36 * @brief Energy evaluation of interior loops for MFE and partition function calculations
37 */
38
39 /**
40 * @addtogroup eval_loops_int
41 * @{
42 * @brief Functions to evaluate the free energy contributions for internal loops
43 */
44
45
46 /**
47 * @name Basic free energy interface
48 * @{
49 */
50 int
51 vrna_E_int_loop(vrna_fold_compound_t *fc,
52 int i,
53 int j);
54
55
56 /**
57 * @brief Evaluate the free energy contribution of an interior loop with delimiting
58 * base pairs @f$(i,j)@f$ and @f$(k,l)@f$
59 *
60 * @note This function is polymorphic, i.e. it accepts #vrna_fold_compound_t of type
61 * #VRNA_FC_TYPE_SINGLE as well as #VRNA_FC_TYPE_COMPARATIVE
62 */
63 int
64 vrna_eval_int_loop(vrna_fold_compound_t *fc,
65 int i,
66 int j,
67 int k,
68 int l);
69
70
71 int
72 vrna_E_ext_int_loop(vrna_fold_compound_t *fc,
73 int i,
74 int j,
75 int *ip,
76 int *iq);
77
78
79 int
80 vrna_E_stack(vrna_fold_compound_t *fc,
81 int i,
82 int j);
83
84
85 /* End basic interface */
86 /**@}*/
87
88
89 /**
90 * @name Boltzmann weight (partition function) interface
91 * @{
92 */
93
94
95 /* j < i indicates circular folding, i.e. collect contributions for exterior int loops */
96 FLT_OR_DBL
97 vrna_exp_E_int_loop(vrna_fold_compound_t *fc,
98 int i,
99 int j);
100
101
102 FLT_OR_DBL
103 vrna_exp_E_interior_loop(vrna_fold_compound_t *fc,
104 int i,
105 int j,
106 int k,
107 int l);
108
109
110 /* End partition function interface */
111 /**@}*/
112
113 /**
114 * @}
115 */
116
117
118 /**
119 * @addtogroup mfe_backtracking
120 * @{
121 */
122
123
124 /**
125 * @brief Backtrack a stacked pair closed by @f$ (i,j) @f$
126 *
127 */
128 int
129 vrna_BT_stack(vrna_fold_compound_t *fc,
130 int *i,
131 int *j,
132 int *en,
133 vrna_bp_stack_t *bp_stack,
134 int *stack_count);
135
136
137 /**
138 * @brief Backtrack an interior loop closed by @f$ (i,j) @f$
139 *
140 */
141 int
142 vrna_BT_int_loop(vrna_fold_compound_t *fc,
143 int *i,
144 int *j,
145 int en,
146 vrna_bp_stack_t *bp_stack,
147 int *stack_count);
148
149
150 /**
151 * @}
152 */
153
154
155 #ifndef VRNA_DISABLE_BACKWARD_COMPATIBILITY
156 /**
157 * @addtogroup eval_deprecated
158 * @{
159 */
160
161
162 #ifdef ON_SAME_STRAND
163 #undef ON_SAME_STRAND
164 #endif
165
166 #define ON_SAME_STRAND(I, J, C) (((I) >= (C)) || ((J) < (C)))
167
168 /**
169 * <H2>Compute the Energy of an interior-loop</H2>
170 * This function computes the free energy @f$\Delta G@f$ of an interior-loop with the
171 * following structure: <BR>
172 * <PRE>
173 * 3' 5'
174 * | |
175 * U - V
176 * a_n b_1
177 * . .
178 * . .
179 * . .
180 * a_1 b_m
181 * X - Y
182 * | |
183 * 5' 3'
184 * </PRE>
185 * This general structure depicts an interior-loop that is closed by the base pair (X,Y).
186 * The enclosed base pair is (V,U) which leaves the unpaired bases a_1-a_n and b_1-b_n
187 * that constitute the loop. In this example, the length of the interior-loop is @f$(n+m)@f$
188 * where n or m may be 0 resulting in a bulge-loop or base pair stack.
189 * The mismatching nucleotides for the closing pair (X,Y) are:<BR>
190 * 5'-mismatch: a_1<BR>
191 * 3'-mismatch: b_m<BR>
192 * and for the enclosed base pair (V,U):<BR>
193 * 5'-mismatch: b_1<BR>
194 * 3'-mismatch: a_n<BR>
195 * @note Base pairs are always denoted in 5'->3' direction. Thus the enclosed base pair
196 * must be 'turned arround' when evaluating the free energy of the interior-loop
197 * @see scale_parameters()
198 * @see vrna_param_t
199 * @note This function is threadsafe
200 *
201 * @param n1 The size of the 'left'-loop (number of unpaired nucleotides)
202 * @param n2 The size of the 'right'-loop (number of unpaired nucleotides)
203 * @param type The pair type of the base pair closing the interior loop
204 * @param type_2 The pair type of the enclosed base pair
205 * @param si1 The 5'-mismatching nucleotide of the closing pair
206 * @param sj1 The 3'-mismatching nucleotide of the closing pair
207 * @param sp1 The 3'-mismatching nucleotide of the enclosed pair
208 * @param sq1 The 5'-mismatching nucleotide of the enclosed pair
209 * @param P The datastructure containing scaled energy parameters
210 * @return The Free energy of the Interior-loop in dcal/mol
211 */
212 PRIVATE INLINE int E_IntLoop(int n1,
213 int n2,
214 int type,
215 int type_2,
216 int si1,
217 int sj1,
218 int sp1,
219 int sq1,
220 vrna_param_t *P);
221
222
223 /**
224 * <H2>Compute Boltzmann weight @f$e^{-\Delta G/kT} @f$ of interior loop</H2>
225 * multiply by scale[u1+u2+2] for scaling
226 * @see get_scaled_pf_parameters()
227 * @see vrna_exp_param_t
228 * @see E_IntLoop()
229 * @note This function is threadsafe
230 *
231 * @param u1 The size of the 'left'-loop (number of unpaired nucleotides)
232 * @param u2 The size of the 'right'-loop (number of unpaired nucleotides)
233 * @param type The pair type of the base pair closing the interior loop
234 * @param type2 The pair type of the enclosed base pair
235 * @param si1 The 5'-mismatching nucleotide of the closing pair
236 * @param sj1 The 3'-mismatching nucleotide of the closing pair
237 * @param sp1 The 3'-mismatching nucleotide of the enclosed pair
238 * @param sq1 The 5'-mismatching nucleotide of the enclosed pair
239 * @param P The datastructure containing scaled Boltzmann weights of the energy parameters
240 * @return The Boltzmann weight of the Interior-loop
241 */
242 PRIVATE INLINE FLT_OR_DBL exp_E_IntLoop(int u1,
243 int u2,
244 int type,
245 int type2,
246 short si1,
247 short sj1,
248 short sp1,
249 short sq1,
250 vrna_exp_param_t *P);
251
252
253 PRIVATE INLINE int E_IntLoop_Co(int type,
254 int type_2,
255 int i,
256 int j,
257 int p,
258 int q,
259 int cutpoint,
260 short si1,
261 short sj1,
262 short sp1,
263 short sq1,
264 int dangles,
265 vrna_param_t *P);
266
267
268 /*
269 * ugly but fast interior loop evaluation
270 *
271 * Avoid including this function in your own code. It only serves
272 * as a fast inline block internally re-used throughout the RNAlib. It
273 * evalutes the free energy of interior loops in single sequences or sequence
274 * hybrids. Soft constraints are also applied if available.
275 *
276 * NOTE: do not include into doxygen reference manual!
277 */
278 PRIVATE INLINE int
ubf_eval_int_loop(int i,int j,int p,int q,int i1,int j1,int p1,int q1,short si,short sj,short sp,short sq,unsigned char type,unsigned char type_2,int * rtype,int ij,int cp,vrna_param_t * P,vrna_sc_t * sc)279 ubf_eval_int_loop(int i,
280 int j,
281 int p,
282 int q,
283 int i1,
284 int j1,
285 int p1,
286 int q1,
287 short si,
288 short sj,
289 short sp,
290 short sq,
291 unsigned char type,
292 unsigned char type_2,
293 int *rtype,
294 int ij,
295 int cp,
296 vrna_param_t *P,
297 vrna_sc_t *sc)
298 {
299 int energy, u1, u2;
300
301 u1 = p1 - i;
302 u2 = j1 - q;
303
304 if ((cp < 0) || (ON_SAME_STRAND(i, p, cp) && ON_SAME_STRAND(q, j, cp))) {
305 /* regular interior loop */
306 energy = E_IntLoop(u1, u2, type, type_2, si, sj, sp, sq, P);
307 } else {
308 /* interior loop like cofold structure */
309 short Si, Sj;
310 Si = ON_SAME_STRAND(i, i1, cp) ? si : -1;
311 Sj = ON_SAME_STRAND(j1, j, cp) ? sj : -1;
312 energy = E_IntLoop_Co(rtype[type], rtype[type_2],
313 i, j, p, q,
314 cp,
315 Si, Sj,
316 sp, sq,
317 P->model_details.dangles,
318 P);
319 }
320
321 /* add soft constraints */
322 if (sc) {
323 if (sc->energy_up)
324 energy += sc->energy_up[i1][u1]
325 + sc->energy_up[q1][u2];
326
327 if (sc->energy_bp)
328 energy += sc->energy_bp[ij];
329
330 if (sc->energy_stack)
331 if (u1 + u2 == 0) {
332 int a = sc->energy_stack[i]
333 + sc->energy_stack[p]
334 + sc->energy_stack[q]
335 + sc->energy_stack[j];
336 energy += a;
337 }
338
339 if (sc->f)
340 energy += sc->f(i, j, p, q, VRNA_DECOMP_PAIR_IL, sc->data);
341 }
342
343 return energy;
344 }
345
346
347 PRIVATE INLINE int
ubf_eval_int_loop2(int i,int j,int p,int q,int i1,int j1,int p1,int q1,short si,short sj,short sp,short sq,unsigned char type,unsigned char type_2,int * rtype,int ij,unsigned int * sn,unsigned int * ss,vrna_param_t * P,vrna_sc_t * sc)348 ubf_eval_int_loop2(int i,
349 int j,
350 int p,
351 int q,
352 int i1,
353 int j1,
354 int p1,
355 int q1,
356 short si,
357 short sj,
358 short sp,
359 short sq,
360 unsigned char type,
361 unsigned char type_2,
362 int *rtype,
363 int ij,
364 unsigned int *sn,
365 unsigned int *ss,
366 vrna_param_t *P,
367 vrna_sc_t *sc)
368 {
369 int energy, u1, u2;
370
371 u1 = p1 - i;
372 u2 = j1 - q;
373
374 if ((sn[i] == sn[p]) && (sn[q] == sn[j])) {
375 /* regular interior loop */
376 energy = E_IntLoop(u1, u2, type, type_2, si, sj, sp, sq, P);
377 } else {
378 /* interior loop like cofold structure */
379 short Si, Sj;
380 Si = (sn[i1] == sn[i]) ? si : -1;
381 Sj = (sn[j] == sn[j1]) ? sj : -1;
382 energy = E_IntLoop_Co(rtype[type], rtype[type_2],
383 i, j, p, q,
384 ss[1],
385 Si, Sj,
386 sp, sq,
387 P->model_details.dangles,
388 P);
389 }
390
391 /* add soft constraints */
392 if (sc) {
393 if (sc->energy_up)
394 energy += sc->energy_up[i1][u1]
395 + sc->energy_up[q1][u2];
396
397 if (sc->energy_bp)
398 energy += sc->energy_bp[ij];
399
400 if (sc->energy_stack)
401 if (u1 + u2 == 0) {
402 int a = sc->energy_stack[i]
403 + sc->energy_stack[p]
404 + sc->energy_stack[q]
405 + sc->energy_stack[j];
406 energy += a;
407 }
408
409 if (sc->f)
410 energy += sc->f(i, j, p, q, VRNA_DECOMP_PAIR_IL, sc->data);
411 }
412
413 return energy;
414 }
415
416
417 /*
418 * ugly but fast exterior interior loop evaluation
419 *
420 * Avoid including this function in your own code. It only serves
421 * as a fast inline block internally re-used throughout the RNAlib. It
422 * evalutes the free energy of interior loops in single sequences or sequence
423 * hybrids. Soft constraints are also applied if available.
424 *
425 * NOTE: do not include into doxygen reference manual!
426 */
427 PRIVATE INLINE int
ubf_eval_ext_int_loop(int i,int j,int p,int q,int i1,int j1,int p1,int q1,short si,short sj,short sp,short sq,unsigned char type,unsigned char type_2,int length,vrna_param_t * P,vrna_sc_t * sc)428 ubf_eval_ext_int_loop(int i,
429 int j,
430 int p,
431 int q,
432 int i1,
433 int j1,
434 int p1,
435 int q1,
436 short si,
437 short sj,
438 short sp,
439 short sq,
440 unsigned char type,
441 unsigned char type_2,
442 int length,
443 vrna_param_t *P,
444 vrna_sc_t *sc)
445 {
446 int energy, u1, u2, u3;
447
448 u1 = i1;
449 u2 = p1 - j;
450 u3 = length - q;
451
452 energy = E_IntLoop(u2, u1 + u3, type, type_2, si, sj, sp, sq, P);
453
454 /* add soft constraints */
455 if (sc) {
456 if (sc->energy_up) {
457 energy += sc->energy_up[j1][u2]
458 + ((u3 > 0) ? sc->energy_up[q1][u3] : 0)
459 + ((u1 > 0) ? sc->energy_up[1][u1] : 0);
460 }
461
462 if (sc->energy_stack)
463 if (u1 + u2 + u3 == 0)
464 energy += sc->energy_stack[i]
465 + sc->energy_stack[p]
466 + sc->energy_stack[q]
467 + sc->energy_stack[j];
468
469 if (sc->f)
470 energy += sc->f(i, j, p, q, VRNA_DECOMP_PAIR_IL, sc->data);
471 }
472
473 return energy;
474 }
475
476
477 PRIVATE INLINE int
E_IntLoop(int n1,int n2,int type,int type_2,int si1,int sj1,int sp1,int sq1,vrna_param_t * P)478 E_IntLoop(int n1,
479 int n2,
480 int type,
481 int type_2,
482 int si1,
483 int sj1,
484 int sp1,
485 int sq1,
486 vrna_param_t *P)
487 {
488 /* compute energy of degree 2 loop (stack bulge or interior) */
489 int nl, ns, u, energy;
490
491 if (n1 > n2) {
492 nl = n1;
493 ns = n2;
494 } else {
495 nl = n2;
496 ns = n1;
497 }
498
499 if (nl == 0)
500 return P->stack[type][type_2]; /* stack */
501
502 if (ns == 0) {
503 /* bulge */
504 energy = (nl <= MAXLOOP) ? P->bulge[nl] :
505 (P->bulge[30] + (int)(P->lxc * log(nl / 30.)));
506 if (nl == 1) {
507 energy += P->stack[type][type_2];
508 } else {
509 if (type > 2)
510 energy += P->TerminalAU;
511
512 if (type_2 > 2)
513 energy += P->TerminalAU;
514 }
515
516 return energy;
517 } else {
518 /* interior loop */
519 if (ns == 1) {
520 if (nl == 1) /* 1x1 loop */
521 return P->int11[type][type_2][si1][sj1];
522
523 if (nl == 2) {
524 /* 2x1 loop */
525 if (n1 == 1)
526 energy = P->int21[type][type_2][si1][sq1][sj1];
527 else
528 energy = P->int21[type_2][type][sq1][si1][sp1];
529
530 return energy;
531 } else {
532 /* 1xn loop */
533 energy =
534 (nl + 1 <=
535 MAXLOOP) ? (P->internal_loop[nl + 1]) : (P->internal_loop[30] +
536 (int)(P->lxc * log((nl + 1) / 30.)));
537 energy += MIN2(MAX_NINIO, (nl - ns) * P->ninio[2]);
538 energy += P->mismatch1nI[type][si1][sj1] + P->mismatch1nI[type_2][sq1][sp1];
539 return energy;
540 }
541 } else if (ns == 2) {
542 if (nl == 2) {
543 /* 2x2 loop */
544 return P->int22[type][type_2][si1][sp1][sq1][sj1];
545 } else if (nl == 3) {
546 /* 2x3 loop */
547 energy = P->internal_loop[5] + P->ninio[2];
548 energy += P->mismatch23I[type][si1][sj1] + P->mismatch23I[type_2][sq1][sp1];
549 return energy;
550 }
551 }
552
553 {
554 /* generic interior loop (no else here!)*/
555 u = nl + ns;
556 energy =
557 (u <=
558 MAXLOOP) ? (P->internal_loop[u]) : (P->internal_loop[30] + (int)(P->lxc * log((u) / 30.)));
559
560 energy += MIN2(MAX_NINIO, (nl - ns) * P->ninio[2]);
561
562 energy += P->mismatchI[type][si1][sj1] + P->mismatchI[type_2][sq1][sp1];
563 }
564 }
565
566 return energy;
567 }
568
569
570 PRIVATE INLINE FLT_OR_DBL
exp_E_IntLoop(int u1,int u2,int type,int type2,short si1,short sj1,short sp1,short sq1,vrna_exp_param_t * P)571 exp_E_IntLoop(int u1,
572 int u2,
573 int type,
574 int type2,
575 short si1,
576 short sj1,
577 short sp1,
578 short sq1,
579 vrna_exp_param_t *P)
580 {
581 int ul, us, no_close = 0;
582 double z = 0.;
583 int noGUclosure = P->model_details.noGUclosure;
584
585 if ((noGUclosure) && ((type2 == 3) || (type2 == 4) || (type == 3) || (type == 4)))
586 no_close = 1;
587
588 if (u1 > u2) {
589 ul = u1;
590 us = u2;
591 } else {
592 ul = u2;
593 us = u1;
594 }
595
596 if (ul == 0) {
597 /* stack */
598 z = P->expstack[type][type2];
599 } else if (!no_close) {
600 if (us == 0) {
601 /* bulge */
602 z = P->expbulge[ul];
603 if (ul == 1) {
604 z *= P->expstack[type][type2];
605 } else {
606 if (type > 2)
607 z *= P->expTermAU;
608
609 if (type2 > 2)
610 z *= P->expTermAU;
611 }
612
613 return (FLT_OR_DBL)z;
614 } else if (us == 1) {
615 if (ul == 1) /* 1x1 loop */
616 return (FLT_OR_DBL)(P->expint11[type][type2][si1][sj1]);
617
618 if (ul == 2) {
619 /* 2x1 loop */
620 if (u1 == 1)
621 return (FLT_OR_DBL)(P->expint21[type][type2][si1][sq1][sj1]);
622 else
623 return (FLT_OR_DBL)(P->expint21[type2][type][sq1][si1][sp1]);
624 } else {
625 /* 1xn loop */
626 z = P->expinternal[ul + us] * P->expmismatch1nI[type][si1][sj1] *
627 P->expmismatch1nI[type2][sq1][sp1];
628 return (FLT_OR_DBL)(z * P->expninio[2][ul - us]);
629 }
630 } else if (us == 2) {
631 if (ul == 2) {
632 /* 2x2 loop */
633 return (FLT_OR_DBL)(P->expint22[type][type2][si1][sp1][sq1][sj1]);
634 } else if (ul == 3) {
635 /* 2x3 loop */
636 z = P->expinternal[5] * P->expmismatch23I[type][si1][sj1] *
637 P->expmismatch23I[type2][sq1][sp1];
638 return (FLT_OR_DBL)(z * P->expninio[2][1]);
639 }
640 }
641
642 /* generic interior loop (no else here!)*/
643 z = P->expinternal[ul + us] * P->expmismatchI[type][si1][sj1] *
644 P->expmismatchI[type2][sq1][sp1];
645 return (FLT_OR_DBL)(z * P->expninio[2][ul - us]);
646 }
647
648 return (FLT_OR_DBL)z;
649 }
650
651
652 PRIVATE INLINE int
E_IntLoop_Co(int type,int type_2,int i,int j,int p,int q,int cutpoint,short si1,short sj1,short sp1,short sq1,int dangles,vrna_param_t * P)653 E_IntLoop_Co(int type,
654 int type_2,
655 int i,
656 int j,
657 int p,
658 int q,
659 int cutpoint,
660 short si1,
661 short sj1,
662 short sp1,
663 short sq1,
664 int dangles,
665 vrna_param_t *P)
666 {
667 int e, energy, ci, cj, cp, cq, d3, d5, d5_2, d3_2, tmm, tmm_2;
668
669 energy = 0;
670 if (type > 2)
671 energy += P->TerminalAU;
672
673 if (type_2 > 2)
674 energy += P->TerminalAU;
675
676 if (!dangles)
677 return energy;
678
679 ci = ON_SAME_STRAND(i, i + 1, cutpoint);
680 cj = ON_SAME_STRAND(j - 1, j, cutpoint);
681 cp = ON_SAME_STRAND(p - 1, p, cutpoint);
682 cq = ON_SAME_STRAND(q, q + 1, cutpoint);
683
684 d3 = ci ? P->dangle3[type][si1] : 0;
685 d5 = cj ? P->dangle5[type][sj1] : 0;
686 d5_2 = cp ? P->dangle5[type_2][sp1] : 0;
687 d3_2 = cq ? P->dangle3[type_2][sq1] : 0;
688
689 tmm = (cj && ci) ? P->mismatchExt[type][sj1][si1] : d5 + d3;
690 tmm_2 = (cp && cq) ? P->mismatchExt[type_2][sp1][sq1] : d5_2 + d3_2;
691
692 if (dangles == 2)
693 return energy + tmm + tmm_2;
694
695 /* now we may have non-double dangles only */
696 if (p - i > 2) {
697 if (j - q > 2) {
698 /* all degrees of freedom */
699 e = MIN2(tmm, d5);
700 e = MIN2(e, d3);
701 energy += e;
702 e = MIN2(tmm_2, d5_2);
703 e = MIN2(e, d3_2);
704 energy += e;
705 } else if (j - q == 2) {
706 /* all degrees of freedom in 5' part between i and p */
707 e = MIN2(tmm + d5_2, d3 + d5_2);
708 e = MIN2(e, d5 + d5_2);
709 e = MIN2(e, d3 + tmm_2);
710 e = MIN2(e, d3 + d3_2);
711 e = MIN2(e, tmm_2); /* no dangles on enclosing pair */
712 e = MIN2(e, d5_2); /* no dangles on enclosing pair */
713 e = MIN2(e, d3_2); /* no dangles on enclosing pair */
714 energy += e;
715 } else {
716 /* no unpaired base between q and j */
717 energy += d3 + d5_2;
718 }
719 } else if (p - i == 2) {
720 if (j - q > 2) {
721 /* all degrees of freedom in 3' part between q and j */
722 e = MIN2(tmm + d3_2, d5 + d3_2);
723 e = MIN2(e, d5 + d3_2);
724 e = MIN2(e, d3 + d3_2);
725 e = MIN2(e, d5 + tmm_2);
726 e = MIN2(e, tmm_2);
727 e = MIN2(e, d5_2);
728 e = MIN2(e, d3_2);
729 energy += e;
730 } else if (j - q == 2) {
731 /* one possible dangling base between either side */
732 e = MIN2(tmm, tmm_2);
733 e = MIN2(e, d3);
734 e = MIN2(e, d5);
735 e = MIN2(e, d5_2);
736 e = MIN2(e, d3_2);
737 e = MIN2(e, d3 + d3_2);
738 e = MIN2(e, d5 + d5_2);
739 energy += e;
740 } else {
741 /* one unpaired base between i and p */
742 energy += MIN2(d3, d5_2);
743 }
744 } else {
745 /* no unpaired base between i and p */
746 if (j - q > 2) {
747 /* all degrees of freedom in 3' part between q and j */
748 energy += d5 + d3_2;
749 } else if (j - q == 2) {
750 /* one unpaired base between q and j */
751 energy += MIN2(d5, d3_2);
752 }
753 }
754
755 return energy;
756 }
757
758
759 /**
760 * @}
761 */
762
763 #endif
764
765 #endif
766