source: branches/profile/PRIMER_DESIGN/PRD_SearchFIFO.cxx

Last change on this file was 8902, checked in by westram, 12 years ago
  • fixed cppcheck warnings
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : PRD_SearchFIFO.cxx                                //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Coded by Wolfram Foerster in February 2001                    //
7//   Institute of Microbiology (Technical University Munich)       //
8//   http://www.arb-home.de/                                       //
9//                                                                 //
10// =============================================================== //
11
12#include "PRD_SearchFIFO.hxx"
13#include <cmath>
14
15using std::printf;
16using std::fabs;
17
18//
19// Constructor
20//
21void SearchFIFO::init(Node *root_, PRD_Sequence_Pos min_distance_to_next_match_, bool expand_IUPAC_Codes_)
22{
23    begin   = NULL;
24    end     = NULL;
25    current = NULL;
26
27    root                       = root_;
28    expand_IUPAC_Codes         = expand_IUPAC_Codes_;
29    min_distance_to_next_match = min_distance_to_next_match_;
30}
31
32SearchFIFO::SearchFIFO (Node *root_, PRD_Sequence_Pos min_distance_to_next_match_, bool expand_IUPAC_Codes_)
33{
34    init(root_, min_distance_to_next_match_, expand_IUPAC_Codes_);
35}
36
37SearchFIFO::SearchFIFO ()
38{
39    init(NULL, -1, false);
40}
41
42
43//
44// Destructor
45//
46SearchFIFO::~SearchFIFO ()
47{
48    flush();
49}
50
51
52//
53// flush : clear FIFO
54//
55void SearchFIFO::flush ()
56{
57    SearchParameter *to_delete;
58
59    current = begin;
60    while (current != NULL)
61    {
62        to_delete = current;
63        current   = current->next;
64        delete to_delete;
65    }
66
67    begin   = NULL;
68    end     = NULL;
69    current = NULL;
70}
71
72
73//
74// append new SearchParameter to the FIFO
75//
76// the current_node is determined from root with the given base
77// multiple parameters are generated for unsure bases like 'N'
78//
79void SearchFIFO::push (unsigned char base_)
80{
81    unsigned int     bits = CHAR2BIT.FIELD[base_];
82    Node            *child_of_root;
83    SearchParameter *new_parameter;
84
85    if (bits & 1) {
86        child_of_root = root->child[2];   // 2 = A
87        if (child_of_root != NULL) {
88            new_parameter = new SearchParameter;
89
90            new_parameter->node      = child_of_root;
91            new_parameter->next      = NULL;
92            new_parameter->previous  = end;
93
94            if (end   != NULL) end->next = new_parameter;
95            if (begin == NULL) begin = new_parameter;
96            end = new_parameter;
97        }
98    }
99
100    if (bits & 2) {
101        child_of_root = root->child[3];   // 3 = T/U
102        if (child_of_root != NULL) {
103            new_parameter = new SearchParameter;
104
105            new_parameter->node      = child_of_root;
106            new_parameter->next      = NULL;
107            new_parameter->previous  = end;
108
109            if (end   != NULL) end->next = new_parameter;
110            if (begin == NULL) begin = new_parameter;
111            end = new_parameter;
112        }
113    }
114
115    if (bits & 4) {
116        child_of_root = root->child[0];   // 0 = C
117        if (child_of_root != NULL) {
118            new_parameter = new SearchParameter;
119
120            new_parameter->node      = child_of_root;
121            new_parameter->next      = NULL;
122            new_parameter->previous  = end;
123
124            if (end   != NULL) end->next = new_parameter;
125            if (begin == NULL) begin = new_parameter;
126            end = new_parameter;
127        }
128    }
129
130    if (bits & 8) {
131        child_of_root = root->child[1];   // 1 = G
132        if (child_of_root != NULL) {
133            new_parameter = new SearchParameter;
134
135            new_parameter->node      = child_of_root;
136            new_parameter->next      = NULL;
137            new_parameter->previous  = end;
138
139            if (end   != NULL) end->next = new_parameter;
140            if (begin == NULL) begin = new_parameter;
141            end = new_parameter;
142        }
143    }
144
145}
146
147
148//
149// step down in tree at all the SearchParameters with the given base(s)
150//
151void SearchFIFO::push_front(Node *child_of_current_)
152{
153    SearchParameter *new_parameter = new SearchParameter;
154
155    new_parameter->node      = child_of_current_;
156    new_parameter->next      = begin;
157    new_parameter->previous  = NULL;
158
159    if (end   == NULL) end             = new_parameter;
160    if (begin != NULL) begin->previous = new_parameter;
161    begin = new_parameter;
162}
163
164void SearchFIFO::iterateWith (PRD_Sequence_Pos pos_, unsigned char base_) {
165    if (begin == NULL) return;
166
167    current = begin;
168
169    if (!expand_IUPAC_Codes) {
170        while (current != NULL) {
171
172            // get childnode of parameters current node
173            Node *child = current->node->childByBase(base_);
174
175            // erase parameter if child doesn't exist
176            if (child == NULL) {
177                erase(current);
178            }
179            else {
180                // step down as child exists
181                current->node = child;
182
183                // invalidate if node is primer and is in range
184                if (child->isValidPrimer()) {
185                    if (min_distance_to_next_match <= 0) {
186                        child->last_base_index = -pos_;
187                    }
188                    else {
189                        if (min_distance_to_next_match >= fabs(double(pos_ - child->last_base_index))) child->last_base_index = -pos_;
190                    }
191                }
192
193                // erase parameter if child is leaf
194                if (child->isLeaf()) {
195                    erase(current);
196
197                    // erase node in tree if leaf and invalid primer
198                    if (!child->isValidPrimer()) {
199                        // remove child from parent
200                        child->parent->child[CHAR2CHILD.INDEX[base_]] = NULL;
201                        child->parent->child_bits &= ~CHAR2BIT.FIELD[base_];
202                        // erase node
203                        delete child;
204                    }
205                }
206            }
207
208            // next parameter (or begin if erase killed current while pointing to begin)
209            current = (current == NULL) ? begin : current->next;
210        }
211    }
212    else { // expand IUPAC-Codes
213        while (current != NULL) {
214            int bits = current->node->child_bits & CHAR2BIT.FIELD[base_];
215
216            if (bits & 1) {   // A
217                Node *child = current->node->child[2];   // 2 = A
218
219                // invalidate if node is primer and is in range
220                if (child->isValidPrimer()) {
221                    if (min_distance_to_next_match <= 0) {
222                        child->last_base_index = -pos_;
223                    }
224                    else {
225                        if (min_distance_to_next_match >= fabs(double(pos_ - child->last_base_index))) child->last_base_index = -pos_;
226                    }
227                }
228
229                // erase child if child is leaf
230                if (child->isLeaf()) {
231                    // erase node in tree if leaf and invalid primer
232                    if (!child->isValidPrimer()) {
233                        // remove child from parent
234                        child->parent->child[CHAR2CHILD.INDEX[base_]] = NULL;
235                        child->parent->child_bits &= ~CHAR2BIT.FIELD[base_];
236                        // erase node
237                        delete child;
238                    }
239                }
240                else { // add new parameter at the begin of fifo
241                    push_front(child);
242                }
243            }
244
245            if (bits & 2) {   // T/U
246                Node *child = current->node->child[3];   // 3 = T/U
247
248                // invalidate if node is primer and is in range
249                if (child->isValidPrimer()) {
250                    if (min_distance_to_next_match <= 0) {
251                        child->last_base_index = -pos_;
252                    }
253                    else {
254                        if (min_distance_to_next_match >= fabs(double(pos_ - child->last_base_index))) child->last_base_index = -pos_;
255                    }
256                }
257
258                // erase child if child is leaf
259                if (child->isLeaf()) {
260                    // erase node in tree if leaf and invalid primer
261                    if (!child->isValidPrimer()) {
262                        // remove child from parent
263                        child->parent->child[CHAR2CHILD.INDEX[base_]] = NULL;
264                        child->parent->child_bits &= ~CHAR2BIT.FIELD[base_];
265                        // erase node
266                        delete child;
267                    }
268                }
269                else { // add new parameter at the begin of fifo
270                    push_front(child);
271                }
272            }
273
274            if (bits & 4) {   // C
275                Node *child = current->node->child[0];   // 0 = C
276
277                // invalidate if node is primer and is in range
278                if (child->isValidPrimer()) {
279                    if (min_distance_to_next_match <= 0) {
280                        child->last_base_index = -pos_;
281                    }
282                    else {
283                        if (min_distance_to_next_match >= fabs(double(pos_ - child->last_base_index))) child->last_base_index = -pos_;
284                    }
285                }
286
287                // erase child if child is leaf
288                if (child->isLeaf()) {
289                    // erase node in tree if leaf and invalid primer
290                    if (!child->isValidPrimer()) {
291                        // remove child from parent
292                        child->parent->child[CHAR2CHILD.INDEX[base_]] = NULL;
293                        child->parent->child_bits &= ~CHAR2BIT.FIELD[base_];
294                        // erase node
295                        delete child;
296                    }
297                }
298                else { // add new parameter at the begin of fifo
299                    push_front(child);
300                }
301            }
302
303            if (bits & 8) {   // G
304                Node *child = current->node->child[1];   // 1 = G
305
306                // invalidate if node is primer and is in range
307                if (child->isValidPrimer()) {
308                    if (min_distance_to_next_match <= 0) {
309                        child->last_base_index = -pos_;
310                    }
311                    else {
312                        if (min_distance_to_next_match >= fabs(double(pos_ - child->last_base_index))) child->last_base_index = -pos_;
313                    }
314                }
315
316                // erase child if child is leaf
317                if (child->isLeaf()) {
318                    // erase node in tree if leaf and invalid primer
319                    if (!child->isValidPrimer()) {
320                        // remove child from parent
321                        child->parent->child[CHAR2CHILD.INDEX[base_]] = NULL;
322                        child->parent->child_bits &= ~CHAR2BIT.FIELD[base_];
323                        // erase node
324                        delete child;
325                    }
326                }
327                else { // add new parameter at the begin of fifo
328                    push_front(child);
329                }
330            }
331
332            // erase old parameter
333            erase(current);
334
335            // next parameter (or begin if erase killed current while pointing to begin)
336            current = (current == NULL) ? begin : current->next;
337        }
338    }
339}
340
341
342//
343// erase given parameter while not invalidating current
344//
345void SearchFIFO::erase (SearchParameter *param_)
346{
347    // unlink from doublelinked list
348    if (param_->next     != NULL) param_->next->previous = param_->previous; else end   = param_->previous;
349    if (param_->previous != NULL) param_->previous->next = param_->next;       else begin = param_->next;
350
351    // set current to current->previous if current is to delete
352    if (param_ == current) current = param_->previous;
353
354    delete param_;
355}
356
357
358//
359// print positions-list
360//
361void SearchFIFO::print ()
362{
363    current = begin;
364    if (begin != NULL)
365        printf("print : begin %p (%p[%c],%p,%p)\t", begin, begin->node, begin->node->base, begin->previous, begin->next);
366    else
367        printf("print : begin (nil)\n");
368
369    if (end != NULL)
370        printf("end %p (%p[%c],%p,%p)\n", end, end->node, end->node->base, end->previous, end->next);
371    else
372        printf("end (nil)\n");
373
374    while (current != NULL) {
375        printf("print : %p (%p[%c],%p,%p)\n", current, current->node, current->node->base, current->previous, current->next);
376        current = current->next;
377    }
378}
Note: See TracBrowser for help on using the repository browser.