1 /****************************************************************\
2 * *
3 * C4 dynamic programming library - SDP Lookahead Object *
4 * *
5 * Guy St.C. Slater.. mailto:guy@ebi.ac.uk *
6 * Copyright (C) 2000-2009. All Rights Reserved. *
7 * *
8 * This source code is distributed under the terms of the *
9 * GNU General Public License, version 3. See the file COPYING *
10 * or http://www.gnu.org/licenses/gpl.txt for details *
11 * *
12 * If you use this code, please keep this notice intact. *
13 * *
14 \****************************************************************/
15
16 #include "lookahead.h"
17
18 /**/
19
20 #define Lookahead_index_pos(lookahead, advance) \
21 (((lookahead)->pos + (advance)) & (Lookahead_Mask_WIDTH-1))
22
23 #define Lookahead_pos_is_set(lookahead, advance) \
24 ((lookahead)->mask \
25 & (1 << Lookahead_index_pos((lookahead), (advance))))
26
Lookahead_create(gint reset_pos,gint max_advance,Lookahead_FreeFunc free_func,gpointer user_data)27 Lookahead *Lookahead_create(gint reset_pos, gint max_advance,
28 Lookahead_FreeFunc free_func,
29 gpointer user_data){
30 register Lookahead *lookahead = g_new0(Lookahead, 1);
31 g_assert(max_advance > 0);
32 g_assert(max_advance <= Lookahead_Mask_WIDTH);
33 lookahead->reset_pos = reset_pos;
34 lookahead->pos = reset_pos;
35 lookahead->max_advance = max_advance;
36 lookahead->free_func = free_func;
37 lookahead->user_data = user_data;
38 return lookahead;
39 }
40
Lookahead_orientate_mask(Lookahead * lookahead)41 static Lookahead_Mask Lookahead_orientate_mask(Lookahead *lookahead){
42 register gint index_pos = Lookahead_index_pos(lookahead, 0);
43 return (lookahead->mask >> index_pos)
44 | (lookahead->mask << (Lookahead_Mask_WIDTH-index_pos));
45 }
46
Lookahead_next_pos(Lookahead * lookahead)47 static gint Lookahead_next_pos(Lookahead *lookahead){
48 g_assert(lookahead->mask); /* Not currently called when empty */
49 return Lookahead_Mask_ffs(Lookahead_orientate_mask(lookahead)) - 1;
50 }
51 /* Returns advance of next occupied or -1 when nothing is set
52 */
53
Lookahead_destroy(Lookahead * lookahead)54 void Lookahead_destroy(Lookahead *lookahead){
55 if(lookahead->mask){ /* Not empty */
56 /* Move to first occupied pos */
57 Lookahead_move(lookahead, lookahead->pos
58 + Lookahead_next_pos(lookahead));
59 while(lookahead->mask) /* Not empty */
60 Lookahead_next(lookahead); /* Move to next position */
61 }
62 g_free(lookahead);
63 return;
64 }
65
Lookahead_reset(Lookahead * lookahead)66 void Lookahead_reset(Lookahead *lookahead){
67 Lookahead_move(lookahead, lookahead->pos + Lookahead_Mask_WIDTH);
68 g_assert(!lookahead->mask);
69 lookahead->pos = lookahead->reset_pos;
70 return;
71 }
72
Lookahead_get(Lookahead * lookahead,gint advance)73 gpointer Lookahead_get(Lookahead *lookahead, gint advance){
74 g_assert(advance >= 0);
75 g_assert(advance <= lookahead->max_advance);
76 return lookahead->index[Lookahead_index_pos(lookahead, advance)];
77 }
78
Lookahead_set(Lookahead * lookahead,gint advance,gpointer data)79 void Lookahead_set(Lookahead *lookahead, gint advance, gpointer data){
80 register gint index_pos = Lookahead_index_pos(lookahead, advance);
81 g_assert(advance >= 0);
82 g_assert(advance <= lookahead->max_advance);
83 g_assert(!Lookahead_get(lookahead, advance));
84 lookahead->index[index_pos] = data;
85 lookahead->mask |= (1 << index_pos);
86 return;
87 }
88
Lookahead_clear(Lookahead * lookahead,gint advance)89 static void Lookahead_clear(Lookahead *lookahead, gint advance){
90 register gint index_pos = Lookahead_index_pos(lookahead, advance);
91 g_assert(advance >= 0);
92 g_assert(advance <= lookahead->max_advance);
93 g_assert(lookahead->index[index_pos]);
94 lookahead->free_func(lookahead->index[index_pos],
95 lookahead->user_data);
96 lookahead->index[index_pos] = NULL;
97 lookahead->mask &= (~(1 << index_pos));
98 return;
99 }
100
Lookahead_next(Lookahead * lookahead)101 gint Lookahead_next(Lookahead *lookahead){
102 g_assert(Lookahead_pos_is_set(lookahead, 0));
103 Lookahead_clear(lookahead, 0);
104 if(lookahead->mask) /* not empty */
105 lookahead->pos += Lookahead_next_pos(lookahead);
106 else
107 lookahead->pos = lookahead->reset_pos; /* empty */
108 return lookahead->pos;
109 }
110
Lookahead_move(Lookahead * lookahead,gint pos)111 void Lookahead_move(Lookahead *lookahead, gint pos){
112 register gint next_advance, max_advance = pos - lookahead->pos;
113 g_assert(pos >= lookahead->pos);
114 g_assert(max_advance >= 0);
115 while(lookahead->mask){
116 next_advance = Lookahead_next_pos(lookahead);
117 g_assert(next_advance >= 0);
118 g_assert(next_advance <= lookahead->max_advance);
119 if(next_advance < max_advance){
120 Lookahead_clear(lookahead, next_advance);
121 } else {
122 break;
123 }
124 }
125 lookahead->pos = pos; /* update the position */
126 return;
127 }
128
129 /**/
130
131