1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 #include "ViennaRNA/utils/basic.h"
5 #include "ViennaRNA/landscape/move.h"
6 
7 
8 PUBLIC vrna_move_t
vrna_move_init(int pos_5,int pos_3)9 vrna_move_init(int  pos_5,
10                int  pos_3)
11 {
12   return (vrna_move_t){
13            pos_5, pos_3, NULL
14   };
15 }
16 
17 
18 PUBLIC void
vrna_move_list_free(vrna_move_t * moves)19 vrna_move_list_free(vrna_move_t *moves)
20 {
21   if (moves) {
22     for (vrna_move_t *move = moves; move->pos_5 != 0; move++) {
23       if (move->next != NULL)
24         if (move->next->pos_5 != 0)
25           vrna_move_list_free(move->next);
26     }
27     free(moves);
28   }
29 }
30 
31 
32 PUBLIC void
vrna_move_apply(short * pt,const vrna_move_t * m)33 vrna_move_apply(short             *pt,
34                 const vrna_move_t *m)
35 {
36   /* deletion */
37   if (vrna_move_is_removal(m)) {
38     pt[-m->pos_5] = 0;
39     pt[-m->pos_3] = 0;
40   } else if (vrna_move_is_insertion(m)) {
41     pt[m->pos_5]  = m->pos_3;
42     pt[m->pos_3]  = m->pos_5;
43   } else
44   /* shift right */
45   if (m->pos_5 > 0 && m->pos_3 < 0) {
46     short previousPairedPosition = pt[m->pos_5];
47     pt[previousPairedPosition] = 0;
48     short newPairedPosition = -m->pos_3;
49     pt[m->pos_5]          = newPairedPosition;
50     pt[newPairedPosition] = m->pos_5;
51   } else
52 
53   /* shift left */
54   if (m->pos_5 < 0 && m->pos_3 > 0) {
55     short previousPairedPosition = pt[m->pos_3];
56     pt[previousPairedPosition] = 0;
57     short newPairedPosition = -m->pos_5;
58     pt[m->pos_3]          = newPairedPosition;
59     pt[newPairedPosition] = m->pos_3;
60   }
61 
62   /* apply successive moves if m.next is a list */
63   if (m->next != NULL)
64     for (vrna_move_t *move = m->next; move->pos_5 != 0; move++)
65       vrna_move_apply(pt, move);
66 }
67 
68 
69 PUBLIC void
vrna_move_apply_db(char * structure,const short * pt,const vrna_move_t * m)70 vrna_move_apply_db(char               *structure,
71                    const short        *pt,
72                    const vrna_move_t  *m)
73 {
74   /* deletion */
75   if (vrna_move_is_removal(m)) {
76     structure[-m->pos_5 - 1]  = '.';
77     structure[-m->pos_3 - 1]  = '.';
78     return;
79   }
80 
81   /* insertion */
82   if (vrna_move_is_insertion(m)) {
83     structure[m->pos_5 - 1] = '(';
84     structure[m->pos_3 - 1] = ')';
85     return;
86   }
87 
88   /* shift right */
89   if (m->pos_5 > 0) {
90     short previousPairedPosition = pt[m->pos_5];
91     structure[previousPairedPosition - 1] = '.';
92     int   left  = m->pos_5 - 1;
93     int   right = -m->pos_3 - 1;
94     structure[left]   = '(';
95     structure[right]  = ')';
96     return;
97   }
98 
99   /* shift left */
100   if (m->pos_5 < 0) {
101     short previousPairedPosition = pt[m->pos_3];
102     structure[previousPairedPosition - 1] = '.';
103     int   left  = -m->pos_5 - 1;
104     int   right = m->pos_3 - 1;
105     structure[left]   = '(';
106     structure[right]  = ')';
107     return;
108   }
109 }
110 
111 
112 PUBLIC int
vrna_move_is_removal(const vrna_move_t * m)113 vrna_move_is_removal(const vrna_move_t *m)
114 {
115   return (m->pos_5 < 0) && (m->pos_3 < 0);
116 }
117 
118 
119 PUBLIC int
vrna_move_is_insertion(const vrna_move_t * m)120 vrna_move_is_insertion(const vrna_move_t *m)
121 {
122   return (m->pos_5 > 0) && (m->pos_3 > 0);
123 }
124 
125 
126 PUBLIC int
vrna_move_is_shift(const vrna_move_t * m)127 vrna_move_is_shift(const vrna_move_t *m)
128 {
129   return ((m->pos_5 < 0) && (m->pos_3 > 0)) ||
130          ((m->pos_5 > 0) && (m->pos_3 < 0));
131 }
132 
133 
134 PUBLIC int
vrna_move_compare(const vrna_move_t * a,const vrna_move_t * b,const short * ptable)135 vrna_move_compare(const vrna_move_t *a,
136                   const vrna_move_t *b,
137                   const short       *ptable)
138 {
139   /* assume, both moves a and b are compatible with current structure */
140 
141   if (vrna_move_is_removal(a)) {
142     if (vrna_move_is_removal(b)) {
143       if (a->pos_5 > b->pos_5)
144         return 1;
145       else if (a->pos_5 < b->pos_5)
146         return -1;
147       else
148         return 0;
149     } else if (vrna_move_is_insertion(b)) {
150       return 1;
151     } else {
152       /*
153        * 'b' is shift move
154        * Implement me!
155        */
156     }
157   } else if (vrna_move_is_insertion(a)) {
158     if (vrna_move_is_insertion(b)) {
159       if (a->pos_5 < b->pos_5)
160         return -1;
161       else if (a->pos_5 > b->pos_5)
162         return 1;
163       else if (a->pos_3 < b->pos_3)
164         return -1;
165       else if (a->pos_3 > b->pos_3)
166         return 1;
167       else
168         return 0;
169     } else if (vrna_move_is_removal(b)) {
170       return -1;
171     } else {
172       /*
173        * 'b' is shift move
174        * Implement me!
175        */
176     }
177   } else {
178     /*
179      * 'a' is shift move
180      * Implement me!
181      */
182   }
183 
184   return 0;
185 }
186