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