1 /* gcc -fopenmp -g3 -DTEST_FINDPATH findpath.c -o FINDpath -lRNA -lm -I../ -L./ */
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <limits.h>
11 
12 #include "ViennaRNA/datastructures/basic.h"
13 #include "ViennaRNA/model.h"
14 #include "ViennaRNA/params/basic.h"
15 #include "ViennaRNA/fold.h"
16 #include "ViennaRNA/cofold.h"
17 #include "ViennaRNA/fold_vars.h"
18 #include "ViennaRNA/utils/basic.h"
19 #include "ViennaRNA/utils/strings.h"
20 #include "ViennaRNA/utils/structures.h"
21 #include "ViennaRNA/landscape/findpath.h"
22 
23 
24 #ifndef VRNA_DISABLE_BACKWARD_COMPATIBILITY
25 
26 #ifdef _OPENMP
27 #include <omp.h>
28 #endif
29 
30 #endif
31 
32 #define LOOP_EN
33 
34 #define   PATH_DIRECT_FINDPATH     1U
35 
36 /**
37  *  @brief
38  */
39 typedef struct move {
40   int i;    /* i,j>0 insert; i,j<0 delete */
41   int j;
42   int when; /* 0 if still available, else resulting distance from start */
43   int E;
44 } move_t;
45 
46 /**
47  *  @brief
48  */
49 typedef struct intermediate {
50   short   *pt;      /**<  @brief  pair table */
51   int     Sen;      /**<  @brief  saddle energy so far */
52   int     curr_en;  /**<  @brief  current energy */
53   move_t  *moves;   /**<  @brief  remaining moves to target */
54 } intermediate_t;
55 
56 
57 struct vrna_path_options_s {
58   unsigned int  type;
59   unsigned int  method;
60 
61   int           width;
62 };
63 
64 /*
65  #################################
66  # GLOBAL VARIABLES              #
67  #################################
68  */
69 
70 /*
71  #################################
72  # PRIVATE VARIABLES             #
73  #################################
74  */
75 PRIVATE int                   BP_dist;
76 PRIVATE move_t                *path = NULL;
77 PRIVATE int                   path_fwd; /* 1: s1->s2, else s2 -> s1 */
78 
79 
80 #ifndef VRNA_DISABLE_BACKWARD_COMPATIBILITY
81 
82 PRIVATE vrna_fold_compound_t  *backward_compat_compound = NULL;
83 
84 #ifdef _OPENMP
85 
86 /* NOTE: all variables are assumed to be uninitialized if they are declared as threadprivate
87  */
88 #pragma omp threadprivate(BP_dist, path, path_fwd, backward_compat_compound)
89 
90 #endif
91 
92 #endif
93 
94 /*
95  #################################
96  # PRIVATE FUNCTION DECLARATIONS #
97  #################################
98  */
99 PRIVATE move_t *
100 copy_moves(move_t *mvs);
101 
102 
103 PRIVATE int
104 compare_ptable(const void *A,
105                const void *B);
106 
107 
108 PRIVATE int
109 compare_energy(const void *A,
110                const void *B);
111 
112 
113 PRIVATE int
114 compare_moves_when(const void *A,
115                    const void *B);
116 
117 
118 PRIVATE void
119 free_intermediate(intermediate_t *i);
120 
121 
122 #ifdef TEST_FINDPATH
123 
124 /* TEST_FINDPATH, COFOLD */
125 PRIVATE void
126 usage(void);
127 
128 
129 #endif
130 
131 PRIVATE int
132 find_path_once(vrna_fold_compound_t *vc,
133                short                *pt1,
134                short                *pt2,
135                int                  maxl,
136                int                  maxE);
137 
138 
139 PRIVATE int
140 try_moves(vrna_fold_compound_t  *vc,
141           intermediate_t        c,
142           int                   maxE,
143           intermediate_t        *next,
144           int                   dist);
145 
146 
147 /*
148  #################################
149  # BEGIN OF FUNCTION DEFINITIONS #
150  #################################
151  */
152 PUBLIC void
vrna_path_free(vrna_path_t * path)153 vrna_path_free(vrna_path_t *path)
154 {
155   vrna_path_t *tmp = path;
156 
157   if (tmp) {
158     if (tmp->type == VRNA_PATH_TYPE_DOT_BRACKET) {
159       while (tmp->s) {
160         free(tmp->s);
161         tmp++;
162       }
163     } else if (tmp->type == VRNA_PATH_TYPE_MOVES) {
164       while ((tmp->move.pos_5)) {
165         vrna_move_list_free(tmp->move.next);
166         tmp++;
167       }
168     }
169 
170     free(path);
171   }
172 }
173 
174 
175 PUBLIC int
vrna_path_findpath_saddle(vrna_fold_compound_t * vc,const char * s1,const char * s2,int width)176 vrna_path_findpath_saddle(vrna_fold_compound_t  *vc,
177                           const char            *s1,
178                           const char            *s2,
179                           int                   width)
180 {
181   return vrna_path_findpath_saddle_ub(vc, s1, s2, width, INT_MAX - 1);
182 }
183 
184 
185 PUBLIC int
vrna_path_findpath_saddle_ub(vrna_fold_compound_t * vc,const char * s1,const char * s2,int width,int maxE)186 vrna_path_findpath_saddle_ub(vrna_fold_compound_t *vc,
187                              const char           *s1,
188                              const char           *s2,
189                              int                  width,
190                              int                  maxE)
191 {
192   int     maxl;
193   short   *ptr, *pt1, *pt2;
194   move_t  *bestpath = NULL;
195   int     dir;
196 
197   path_fwd  = dir = 0;
198   pt1       = vrna_ptable(s1);
199   pt2       = vrna_ptable(s2);
200 
201   maxl = 1;
202   do {
203     int saddleE;
204     path_fwd = !path_fwd;
205     if (maxl > width)
206       maxl = width;
207 
208     if (path)
209       free(path);
210 
211     saddleE = find_path_once(vc, pt1, pt2, maxl, maxE);
212     if (saddleE < maxE) {
213       maxE = saddleE;
214       if (bestpath)
215         free(bestpath);
216 
217       bestpath  = path;
218       path      = NULL;
219       dir       = path_fwd;
220     } else {
221       free(path);
222       path = NULL;
223     }
224 
225     ptr   = pt1;
226     pt1   = pt2;
227     pt2   = ptr;
228     maxl  *= 2;
229   } while (maxl < 2 * width);
230 
231   /* (re)set some globals */
232   path      = bestpath;
233   path_fwd  = dir;
234 
235   free(pt1);
236   free(pt2);
237 
238   return maxE;
239 }
240 
241 
242 PUBLIC vrna_path_t *
vrna_path_findpath(vrna_fold_compound_t * fc,const char * s1,const char * s2,int width)243 vrna_path_findpath(vrna_fold_compound_t *fc,
244                    const char           *s1,
245                    const char           *s2,
246                    int                  width)
247 {
248   struct vrna_path_options_s  *opt;
249   vrna_path_t                 *path;
250 
251   opt   = vrna_path_options_findpath(width, VRNA_PATH_TYPE_DOT_BRACKET);
252   path  = vrna_path_direct_ub(fc,
253                               s1,
254                               s2,
255                               INT_MAX - 1,
256                               opt);
257 
258   free(opt);
259 
260   return path;
261 }
262 
263 
264 PUBLIC vrna_path_t *
vrna_path_findpath_ub(vrna_fold_compound_t * fc,const char * s1,const char * s2,int width,int maxE)265 vrna_path_findpath_ub(vrna_fold_compound_t  *fc,
266                       const char            *s1,
267                       const char            *s2,
268                       int                   width,
269                       int                   maxE)
270 {
271   struct vrna_path_options_s  *opt;
272   vrna_path_t                 *path;
273 
274   opt   = vrna_path_options_findpath(width, VRNA_PATH_TYPE_DOT_BRACKET);
275   path  = vrna_path_direct_ub(fc,
276                               s1,
277                               s2,
278                               maxE,
279                               opt);
280 
281   free(opt);
282 
283   return path;
284 }
285 
286 
287 PUBLIC struct vrna_path_options_s *
vrna_path_options_findpath(int width,unsigned int type)288 vrna_path_options_findpath(int          width,
289                            unsigned int type)
290 {
291   struct vrna_path_options_s *options =
292     (struct vrna_path_options_s *)vrna_alloc(sizeof(struct vrna_path_options_s));
293 
294   options->type   = type;
295   options->method = PATH_DIRECT_FINDPATH;
296   options->width  = width;
297 
298   return options;
299 }
300 
301 
302 PUBLIC void
vrna_path_options_free(struct vrna_path_options_s * options)303 vrna_path_options_free(struct vrna_path_options_s *options)
304 {
305   free(options);
306 }
307 
308 
309 PRIVATE vrna_path_t *
findpath_method(vrna_fold_compound_t * fc,const char * s1,const char * s2,int width,int maxE,unsigned int return_type)310 findpath_method(vrna_fold_compound_t  *fc,
311                 const char            *s1,
312                 const char            *s2,
313                 int                   width,
314                 int                   maxE,
315                 unsigned int          return_type)
316 {
317   int         E, d;
318   float       last_E;
319   vrna_path_t *route = NULL;
320 
321   E = vrna_path_findpath_saddle_ub(fc, s1, s2, width, maxE);
322 
323   /* did we find a better path than one with saddle maxE? */
324   if (E < maxE) {
325     route = (vrna_path_t *)vrna_alloc((BP_dist + 2) * sizeof(vrna_path_t));
326 
327     qsort(path, BP_dist, sizeof(move_t), compare_moves_when);
328 
329     switch (return_type) {
330       case VRNA_PATH_TYPE_MOVES:
331         if (path_fwd) {
332           last_E = vrna_eval_structure(fc, s1);
333           for (d = 0; d < BP_dist; d++) {
334             route[d].type = return_type;
335             route[d].move = vrna_move_init(path[d].i,
336                                            path[d].j);
337             route[d].en = (path[d].E / 100.0) - last_E;
338             last_E      = path[d].E / 100.0;
339           }
340 
341           route[BP_dist].type = return_type;
342           route[BP_dist].move = vrna_move_init(0, 0);
343         } else {
344           last_E = vrna_eval_structure(fc, s2);
345           for (d = 0; d < BP_dist; d++) {
346             route[BP_dist - d - 2].type = return_type;
347             route[BP_dist - d - 2].move = vrna_move_init(path[d].i,
348                                                          path[d].j);
349             route[BP_dist - d - 2].en = last_E - (path[d].E / 100.0);
350             last_E                    = path[d].E / 100;
351           }
352 
353           route[BP_dist].type = return_type;
354           route[BP_dist].move = vrna_move_init(0, 0);
355         }
356 
357         break;
358 
359       case VRNA_PATH_TYPE_DOT_BRACKET:
360       /* fall through */
361 
362       default:
363         if (path_fwd) {
364           /* memorize start of path */
365           route[0].type = return_type;
366           route[0].s    = strdup(s1);
367           route[0].en   = vrna_eval_structure(fc, s1);
368 
369           for (d = 0; d < BP_dist; d++) {
370             int i, j;
371             route[d + 1].type = return_type;
372             route[d + 1].s    = strdup(route[d].s);
373             i                 = path[d].i;
374             j                 = path[d].j;
375             if (i < 0) {
376               /* delete */
377               route[d + 1].s[(-i) - 1] = route[d + 1].s[(-j) - 1] = '.';
378             } else {
379               route[d + 1].s[i - 1] = '(';
380               route[d + 1].s[j - 1] = ')';
381             }
382 
383             route[d + 1].en = path[d].E / 100.0;
384           }
385         } else {
386           /* memorize start of path */
387           route[0].type     = return_type;
388           route[BP_dist].s  = strdup(s2);
389           route[BP_dist].en = vrna_eval_structure(fc, s2);
390 
391           for (d = 0; d < BP_dist; d++) {
392             int i, j;
393             route[BP_dist - d - 1].type = return_type;
394             route[BP_dist - d - 1].s    = strdup(route[BP_dist - d].s);
395             i                           = path[d].i;
396             j                           = path[d].j;
397             if (i < 0) {
398               /* delete */
399               route[BP_dist - d - 1].s[(-i) - 1] = route[BP_dist - d - 1].s[(-j) - 1] = '.';
400             } else {
401               route[BP_dist - d - 1].s[i - 1] = '(';
402               route[BP_dist - d - 1].s[j - 1] = ')';
403             }
404 
405             route[BP_dist - d - 1].en = path[d].E / 100.0;
406           }
407         }
408 
409         break;
410     }
411 
412 #if _DEBUG_FINDPATH_
413     if (return_type & VRNA_PATH_TYPE_DOT_BRACKET) {
414       fprintf(stderr, "\n%s\n%s\n%s\n\n", seq, s1, s2);
415       for (d = 0; d <= BP_dist; d++)
416         fprintf(stderr, "%s %6.2f\n", route[d].s, route[d].en);
417       fprintf(stderr, "%d\n", *num_entry);
418     }
419 
420 #endif
421   }
422 
423   free(path);
424   path = NULL;
425 
426   return route;
427 }
428 
429 
430 PUBLIC vrna_path_t *
vrna_path_direct(vrna_fold_compound_t * fc,const char * s1,const char * s2,struct vrna_path_options_s * options)431 vrna_path_direct(vrna_fold_compound_t       *fc,
432                  const char                 *s1,
433                  const char                 *s2,
434                  struct vrna_path_options_s *options)
435 {
436   return vrna_path_direct_ub(fc,
437                              s1,
438                              s2,
439                              INT_MAX - 1,
440                              options);
441 }
442 
443 
444 PUBLIC vrna_path_t *
vrna_path_direct_ub(vrna_fold_compound_t * fc,const char * s1,const char * s2,int maxE,struct vrna_path_options_s * options)445 vrna_path_direct_ub(vrna_fold_compound_t        *fc,
446                     const char                  *s1,
447                     const char                  *s2,
448                     int                         maxE,
449                     struct vrna_path_options_s  *options)
450 {
451   int                         E, d;
452   struct vrna_path_options_s  *o;
453   vrna_path_t                 *route = NULL;
454 
455   /* we default to findpath method */
456   o = options ? options : vrna_path_options_findpath(10,
457                                                      VRNA_PATH_TYPE_DOT_BRACKET);
458 
459   switch (o->method) {
460     case PATH_DIRECT_FINDPATH:
461     /* fall through */
462     default:
463       route = findpath_method(fc, s1, s2, o->width, maxE, o->type);
464       break;
465   }
466 
467   if (!options)
468     vrna_path_options_free(o);
469 
470   return route;
471 }
472 
473 
474 #ifdef TEST_FINDPATH
475 
476 PUBLIC void
print_path(const char * seq,const char * struc)477 print_path(const char *seq,
478            const char *struc)
479 {
480   int   d;
481   char  *s;
482 
483   s = strdup(struc);
484   if (cut_point == -1) {
485     printf("%s\n%s\n", seq, s);
486   }
487   /* printf("%s\n%s %6.2f\n", seq, s, vrna_eval_structure_simple(seq,s)); */
488   else {
489     char *pstruct, *pseq;
490     pstruct = vrna_cut_point_insert(s, cut_point);
491     pseq    = vrna_cut_point_insert(seq, cut_point);
492     printf("%s\n%s\n", pseq, pstruct);
493     /* printf("%s\n%s %6.2f\n", pseq, pstruct, vrna_eval_structure_simple(seq,s)); */
494     free(pstruct);
495     free(pseq);
496   }
497 
498   qsort(path, BP_dist, sizeof(move_t), compare_moves_when);
499   for (d = 0; d < BP_dist; d++) {
500     int i, j;
501     i = path[d].i;
502     j = path[d].j;
503     if (i < 0) {
504       /* delete */
505       s[(-i) - 1] = s[(-j) - 1] = '.';
506     } else {
507       s[i - 1]  = '(';
508       s[j - 1]  = ')';
509     }
510 
511     /* printf("%s %6.2f - %6.2f\n", s, vrna_eval_structure_simple(seq,s), path[d].E/100.0); */
512   }
513   free(s);
514 }
515 
516 
517 int
main(int argc,char * argv[])518 main(int  argc,
519      char *argv[])
520 {
521   char        *line, *seq, *s1, *s2;
522   int         E, maxkeep = 1000;
523   int         verbose = 0, i;
524   vrna_path_t *route, *r;
525 
526   for (i = 1; i < argc; i++) {
527     switch (argv[i][1]) {
528       case 'm':
529         if (strcmp(argv[i], "-m") == 0)
530           sscanf(argv[++i], "%d", &maxkeep);
531 
532         break;
533       case 'v':
534         verbose = !strcmp(argv[i], "-v");
535         break;
536       case 'd':
537         if (strcmp(argv[i], "-d") == 0)
538           sscanf(argv[++i], "%d", &dangles);
539 
540         break;
541       default:
542         usage();
543     }
544   }
545 
546   cut_point = -1;
547   line      = vrna_read_line(stdin);
548   seq       = vrna_cut_point_remove(line, &cut_point);
549   free(line);
550   line  = vrna_read_line(stdin);
551   s1    = vrna_cut_point_remove(line, &cut_point);
552   free(line);
553   line  = vrna_read_line(stdin);
554   s2    = vrna_cut_point_remove(line, &cut_point);
555   free(line);
556 
557   E = find_saddle(seq, s1, s2, maxkeep);
558   printf("saddle_energy = %6.2f\n", E / 100.);
559   if (verbose) {
560     if (path_fwd)
561       print_path(seq, s1);
562     else
563       print_path(seq, s2);
564 
565     free(path);
566     path  = NULL;
567     route = get_path(seq, s1, s2, maxkeep);
568     for (r = route; r->s; r++) {
569       if (cut_point == -1) {
570         printf("%s %6.2f\n", r->s, r->en);
571         /* printf("%s %6.2f - %6.2f\n", r->s, vrna_eval_structure_simple(seq,r->s), r->en); */
572       } else {
573         char *pstruct;
574         pstruct = vrna_cut_point_insert(r->s, cut_point);
575         printf("%s %6.2f\n", pstruct, r->en);
576         /* printf("%s %6.2f - %6.2f\n", pstruct, vrna_eval_structure_simple(seq,r->s), r->en); */
577         free(pstruct);
578       }
579 
580       free(r->s);
581     }
582     free(route);
583   }
584 
585   free(seq);
586   free(s1);
587   free(s2);
588   return EXIT_SUCCESS;
589 }
590 
591 
592 static void
usage(void)593 usage(void)
594 {
595   vrna_message_error("usage: findpath.c  [-m depth] [-d[0|1|2]] [-v]");
596 }
597 
598 
599 #endif
600 
601 
602 /*
603  #################################
604  # STATIC helper functions below #
605  #################################
606  */
607 PRIVATE int
try_moves(vrna_fold_compound_t * vc,intermediate_t c,int maxE,intermediate_t * next,int dist)608 try_moves(vrna_fold_compound_t  *vc,
609           intermediate_t        c,
610           int                   maxE,
611           intermediate_t        *next,
612           int                   dist)
613 {
614   int     *loopidx, len, num_next = 0, en, oldE;
615   move_t  *mv;
616   short   *pt;
617 
618   len     = c.pt[0];
619   loopidx = vrna_loopidx_from_ptable(c.pt);
620   oldE    = c.Sen;
621   for (mv = c.moves; mv->i != 0; mv++) {
622     int i, j;
623     if (mv->when > 0)
624       continue;
625 
626     i   = mv->i;
627     j   = mv->j;
628     pt  = (short *)vrna_alloc(sizeof(short) * (len + 1));
629     memcpy(pt, c.pt, (len + 1) * sizeof(short));
630     if (j < 0) {
631       /*it's a delete move */
632       pt[-i]  = 0;
633       pt[-j]  = 0;
634     } else {
635       /* insert move */
636       if ((loopidx[i] == loopidx[j]) && /* i and j belong to same loop */
637           (pt[i] == 0) && (pt[j] == 0)  /* ... and are unpaired */
638           ) {
639         pt[i] = j;
640         pt[j] = i;
641       } else {
642         free(pt);
643         continue; /* llegal move, try next; */
644       }
645     }
646 
647 #ifdef LOOP_EN
648     en = c.curr_en + vrna_eval_move_pt(vc, c.pt, i, j);
649 #else
650     en = vrna_eval_structure_pt(vc, pt);
651 #endif
652     if (en < maxE) {
653       next[num_next].Sen      = (en > oldE) ? en : oldE;
654       next[num_next].curr_en  = en;
655       next[num_next].pt       = pt;
656       mv->when                = dist;
657       mv->E                   = en;
658       next[num_next++].moves  = copy_moves(c.moves);
659       mv->when                = 0;
660     } else {
661       free(pt);
662     }
663   }
664   free(loopidx);
665   return num_next;
666 }
667 
668 
669 PRIVATE int
find_path_once(vrna_fold_compound_t * vc,short * pt1,short * pt2,int maxl,int maxE)670 find_path_once(vrna_fold_compound_t *vc,
671                short                *pt1,
672                short                *pt2,
673                int                  maxl,
674                int                  maxE)
675 {
676   move_t          *mlist;
677   int             i, len, d, dist = 0, result;
678   short           *pt;
679   intermediate_t  *current, *next;
680 
681   len = (int)pt1[0];
682   pt  = vrna_ptable_copy(pt1);
683 
684   mlist = (move_t *)vrna_alloc(sizeof(move_t) * len); /* bp_dist < n */
685 
686   for (i = 1; i <= len; i++) {
687     if (pt[i] != pt2[i]) {
688       if (i < pt[i]) {
689         /* need to delete this pair */
690         mlist[dist].i       = -i;
691         mlist[dist].j       = -pt[i];
692         mlist[dist++].when  = 0;
693       }
694 
695       if (i < pt2[i]) {
696         /* need to insert this pair */
697         mlist[dist].i       = i;
698         mlist[dist].j       = pt2[i];
699         mlist[dist++].when  = 0;
700       }
701     }
702   }
703 
704   BP_dist           = dist;
705   current           = (intermediate_t *)vrna_alloc(sizeof(intermediate_t) * (maxl + 1));
706   current[0].pt     = pt;
707   current[0].Sen    = current[0].curr_en = vrna_eval_structure_pt(vc, pt);
708   current[0].moves  = mlist;
709   next              = (intermediate_t *)vrna_alloc(sizeof(intermediate_t) * (dist * maxl + 1));
710 
711   for (d = 1; d <= dist; d++) {
712     /* go through the distance classes */
713     int             c, u, num_next = 0;
714     intermediate_t  *cc;
715 
716     for (c = 0; current[c].pt != NULL; c++)
717       num_next += try_moves(vc, current[c], maxE, next + num_next, d);
718     if (num_next == 0) {
719       for (cc = current; cc->pt != NULL; cc++)
720         free_intermediate(cc);
721       current[0].Sen = INT_MAX;
722       break;
723     }
724 
725     /* remove duplicates via sort|uniq
726      * if this becomes a bottleneck we can use a hash instead */
727     qsort(next, num_next, sizeof(intermediate_t), compare_ptable);
728     for (u = 0, c = 1; c < num_next; c++) {
729       if (memcmp(next[u].pt, next[c].pt, sizeof(short) * len) != 0)
730         next[++u] = next[c];
731       else
732         free_intermediate(next + c);
733     }
734     num_next = u + 1;
735     qsort(next, num_next, sizeof(intermediate_t), compare_energy);
736     /* free the old stuff */
737     for (cc = current; cc->pt != NULL; cc++)
738       free_intermediate(cc);
739     for (u = 0; u < maxl && u < num_next; u++)
740       current[u] = next[u];
741     for (; u < num_next; u++)
742       free_intermediate(next + u);
743     num_next = 0;
744   }
745   free(next);
746   path    = current[0].moves;
747   result  = current[0].Sen;
748   free(current[0].pt);
749   free(current);
750   return result;
751 }
752 
753 
754 PRIVATE void
free_intermediate(intermediate_t * i)755 free_intermediate(intermediate_t *i)
756 {
757   free(i->pt);
758   free(i->moves);
759   i->pt     = NULL;
760   i->moves  = NULL;
761   i->Sen    = INT_MAX;
762 }
763 
764 
765 PRIVATE int
compare_ptable(const void * A,const void * B)766 compare_ptable(const void *A,
767                const void *B)
768 {
769   intermediate_t  *a, *b;
770   int             c;
771 
772   a = (intermediate_t *)A;
773   b = (intermediate_t *)B;
774 
775   c = memcmp(a->pt, b->pt, a->pt[0] * sizeof(short));
776   if (c != 0)
777     return c;
778 
779   if ((a->Sen - b->Sen) != 0)
780     return a->Sen - b->Sen;
781 
782   return a->curr_en - b->curr_en;
783 }
784 
785 
786 PRIVATE int
compare_energy(const void * A,const void * B)787 compare_energy(const void *A,
788                const void *B)
789 {
790   intermediate_t *a, *b;
791 
792   a = (intermediate_t *)A;
793   b = (intermediate_t *)B;
794 
795   if ((a->Sen - b->Sen) != 0)
796     return a->Sen - b->Sen;
797 
798   return a->curr_en - b->curr_en;
799 }
800 
801 
802 PRIVATE int
compare_moves_when(const void * A,const void * B)803 compare_moves_when(const void *A,
804                    const void *B)
805 {
806   move_t *a, *b;
807 
808   a = (move_t *)A;
809   b = (move_t *)B;
810 
811   return a->when - b->when;
812 }
813 
814 
815 PRIVATE move_t *
copy_moves(move_t * mvs)816 copy_moves(move_t *mvs)
817 {
818   move_t *new;
819 
820   new = (move_t *)vrna_alloc(sizeof(move_t) * (BP_dist + 1));
821   memcpy(new, mvs, sizeof(move_t) * (BP_dist + 1));
822   return new;
823 }
824 
825 
826 /*
827  *###########################################
828  *# deprecated functions below              #
829  *###########################################
830  */
831 
832 #ifndef VRNA_DISABLE_BACKWARD_COMPATIBILITY
833 
834 PUBLIC void
free_path(vrna_path_t * path)835 free_path(vrna_path_t *path)
836 {
837   vrna_path_free(path);
838 }
839 
840 
841 PUBLIC int
find_saddle(const char * seq,const char * s1,const char * s2,int width)842 find_saddle(const char  *seq,
843             const char  *s1,
844             const char  *s2,
845             int         width)
846 {
847   int                   maxE;
848   char                  *sequence;
849   vrna_fold_compound_t  *vc;
850   vrna_md_t             md, *md_p;
851 
852   vc = NULL;
853   set_model_details(&md);
854 
855   if (backward_compat_compound) {
856     if (!strcmp(seq, backward_compat_compound->sequence)) {
857       /* check if sequence is the same as before */
858       md.window_size  = backward_compat_compound->length;
859       md.max_bp_span  = backward_compat_compound->length;
860       md_p            = &(backward_compat_compound->params->model_details);
861       if (!memcmp(&md, md_p, sizeof(vrna_md_t)))  /* check if model_details are the same as before */
862         vc = backward_compat_compound;            /* re-use previous vrna_fold_compound_t */
863     }
864   }
865 
866   if (!vc) {
867     vrna_fold_compound_free(backward_compat_compound);
868 
869     sequence = vrna_cut_point_insert(seq, cut_point);
870 
871     backward_compat_compound = vc = vrna_fold_compound(sequence, &md, VRNA_OPTION_EVAL_ONLY);
872 
873     free(sequence);
874   }
875 
876   maxE = vrna_path_findpath_saddle(vc, s1, s2, width);
877 
878   return maxE;
879 }
880 
881 
882 PUBLIC vrna_path_t *
get_path(const char * seq,const char * s1,const char * s2,int maxkeep)883 get_path(const char *seq,
884          const char *s1,
885          const char *s2,
886          int        maxkeep)
887 {
888   vrna_path_t           *route = NULL;
889   char                  *sequence = NULL;
890   vrna_fold_compound_t  *vc = NULL;
891   vrna_md_t             md, *md_p;
892 
893   set_model_details(&md);
894 
895   if (backward_compat_compound) {
896     if (!strcmp(seq, backward_compat_compound->sequence)) {
897       /* check if sequence is the same as before */
898       md.window_size  = backward_compat_compound->length;
899       md.max_bp_span  = backward_compat_compound->length;
900       md_p            = &(backward_compat_compound->params->model_details);
901       if (!memcmp(&md, md_p, sizeof(vrna_md_t)))  /* check if model_details are the same as before */
902         vc = backward_compat_compound;            /* re-use previous vrna_fold_compound_t */
903     }
904   }
905 
906   if (!vc) {
907     vrna_fold_compound_free(backward_compat_compound);
908 
909     sequence = vrna_cut_point_insert(seq, cut_point);
910 
911     backward_compat_compound = vc = vrna_fold_compound(sequence, &md, VRNA_OPTION_EVAL_ONLY);
912 
913     free(sequence);
914   }
915 
916   route = vrna_path_findpath(vc, s1, s2, maxkeep);
917 
918   return route;
919 }
920 
921 
922 #endif
923