1 // ==========================================================================
2 //                 SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2015, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 //       notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above copyright
13 //       notice, this list of conditions and the following disclaimer in the
14 //       documentation and/or other materials provided with the distribution.
15 //     * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 //       its contributors may be used to endorse or promote products derived
17 //       from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Stephan Aiche <stephan.aiche@fu-berlin.de>
33 // ==========================================================================
34 
35 #include <stack>
36 
37 // TODO(holtgrew): Get rid of this?
38 //#define SEQAN_HIRSCHBERG_DEBUG_CUT
39 
40 #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_
41 #define SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_
42 
43 namespace seqan {
44 
45 // ============================================================================
46 // Forwards
47 // ============================================================================
48 
49 // ============================================================================
50 // Tags, Classes, Enums
51 // ============================================================================
52 
53 struct Hirschberg_;
54 typedef Tag<Hirschberg_> Hirschberg;
55 
56 // ----------------------------------------------------------------------------
57 // Helper Class HirschbergSet_
58 // ----------------------------------------------------------------------------
59 
60 // State for the implementation of Hirschberg's algorithm.
61 
62 class HirschbergSet_
63 {
64 public:
65     int x1,x2,y1,y2;
66     int score;
67 
HirschbergSet_()68     HirschbergSet_()
69         : x1(0), x2(0), y1(0), y2(0), score(0)
70     {}
71 
HirschbergSet_(int a1,int a2,int b1,int b2,int sc)72     HirschbergSet_(int a1,int a2,int b1,int b2,int sc)
73         : x1(a1), x2(a2), y1(b1), y2(b2), score(sc)
74     {
75         SEQAN_ASSERT_LEQ(a1, a2);
76         SEQAN_ASSERT_LEQ(b1, b2);
77     }
78 
79     HirschbergSet_ &
80     operator=(HirschbergSet_ const & other_)
81     {
82         x1 = other_.x1;
83         x2 = other_.x2;
84         y1 = other_.y1;
85         y2 = other_.y2;
86         score = other_.score;
87         return *this;
88     }
89 
90 };
91 
92 // ============================================================================
93 // Metafunctions
94 // ============================================================================
95 
96 // ============================================================================
97 // Functions
98 // ============================================================================
99 
100 // ----------------------------------------------------------------------------
101 // Function _begin1()
102 // ----------------------------------------------------------------------------
103 
104 inline int&
_begin1(HirschbergSet_ & me)105 _begin1(HirschbergSet_ & me) {
106     return me.x1;
107 }
108 
109 
110 inline int const&
_begin1(HirschbergSet_ const & me)111 _begin1(HirschbergSet_ const & me) {
112     return me.x1;
113 }
114 
115 // ----------------------------------------------------------------------------
116 // Function _setBegin1()
117 // ----------------------------------------------------------------------------
118 
119 inline void
_setBegin1(HirschbergSet_ & me,int const & new_begin)120 _setBegin1(HirschbergSet_ & me, int const & new_begin) {
121     me.x1 = new_begin;
122 }
123 
124 // ----------------------------------------------------------------------------
125 // Function _end1()
126 // ----------------------------------------------------------------------------
127 
128 inline int&
_end1(HirschbergSet_ & me)129 _end1(HirschbergSet_ & me) {
130     return me.x2;
131 }
132 
133 inline int const&
_end1(HirschbergSet_ const & me)134 _end1(HirschbergSet_ const & me) {
135     return me.x2;
136 }
137 
138 // ----------------------------------------------------------------------------
139 // Function _setEnd1()
140 // ----------------------------------------------------------------------------
141 
142 inline void
_setEnd1(HirschbergSet_ & me,int const & new_end)143 _setEnd1(HirschbergSet_ & me, int const & new_end) {
144     me.x2 = new_end;
145 }
146 
147 // ----------------------------------------------------------------------------
148 // Function _begin2()
149 // ----------------------------------------------------------------------------
150 
151 inline int&
_begin2(HirschbergSet_ & me)152 _begin2(HirschbergSet_ & me) {
153     return me.y1;
154 }
155 
156 inline int const&
_begin2(HirschbergSet_ const & me)157 _begin2(HirschbergSet_ const & me) {
158     return me.y1;
159 }
160 
161 // ----------------------------------------------------------------------------
162 // Function _setBegin2()
163 // ----------------------------------------------------------------------------
164 
165 inline void
_setBegin2(HirschbergSet_ & me,int const & new_begin)166 _setBegin2(HirschbergSet_ & me, int const & new_begin) {
167     me.y1 = new_begin;
168 }
169 
170 // ----------------------------------------------------------------------------
171 // Function _end2()
172 // ----------------------------------------------------------------------------
173 
174 inline int&
_end2(HirschbergSet_ & me)175 _end2(HirschbergSet_ & me) {
176     return me.y2;
177 }
178 
179 inline int const&
_end2(HirschbergSet_ const & me)180 _end2(HirschbergSet_ const & me) {
181     return me.y2;
182 }
183 
184 // ----------------------------------------------------------------------------
185 // Function _setEnd2()
186 // ----------------------------------------------------------------------------
187 
188 inline void
_setEnd2(HirschbergSet_ & me,int const & new_end)189 _setEnd2(HirschbergSet_ & me, int const & new_end) {
190     me.y2 = new_end;
191 }
192 
193 // ----------------------------------------------------------------------------
194 // Function _score()
195 // ----------------------------------------------------------------------------
196 
197 inline int&
_score(HirschbergSet_ & me)198 _score(HirschbergSet_ & me)    {
199     return me.score;
200 }
201 
202 // ----------------------------------------------------------------------------
203 // Function _score()
204 // ----------------------------------------------------------------------------
205 
206 inline int const&
_score(HirschbergSet_ const & me)207 _score(HirschbergSet_ const & me)
208 {
209     return me.score;
210 }
211 
212 // ----------------------------------------------------------------------------
213 // Function _setScore()
214 // ----------------------------------------------------------------------------
215 
216 inline void
_setScore(HirschbergSet_ & me,int new_score)217 _setScore(HirschbergSet_ & me,int new_score) {
218     me.score = new_score;
219 }
220 
221 // ----------------------------------------------------------------------------
222 // Function _setBegin2()
223 // ----------------------------------------------------------------------------
224 
225 // //////////////////////////////////////////////////////////////////////////////////////////////
226 //  Debug Methods
227 //        functions are only used for debugging or verbose output, therefore they
228 //      are only active in SEQAN_DEBUG
229 // //////////////////////////////////////////////////////////////////////////////////////////////
230 #ifdef SEQAN_DEBUG
231 
232 inline
233 void
print(HirschbergSet_ const & me)234 print(HirschbergSet_ const & me)
235 {
236     std::cout << me.x1 << " " << me.x2 << "\t" << me.y1 << " " << me.y2 << std::endl;
237 }
238 #endif
239 
240 // ----------------------------------------------------------------------------
241 // Function operator==()
242 // ----------------------------------------------------------------------------
243 
244 inline bool
245 operator==(HirschbergSet_ const & lhs,
246            HirschbergSet_ const & rhs)
247 {
248     return ((_begin1(lhs) == _begin1(rhs)) && (_end1(lhs) == _end1(rhs)) &&
249             (_begin2(lhs) == _begin2(rhs)) && (_end2(lhs) == _end2(rhs)));
250 }
251 
252 // ----------------------------------------------------------------------------
253 // Function _writeDebugMatrix()
254 // ----------------------------------------------------------------------------
255 
256 #ifdef SEQAN_HIRSCHBERG_DEBUG_CUT
257     template<typename TSource>
_writeDebugMatrix(TSource s1,TSource s2)258     void _writeDebugMatrix(TSource s1,TSource s2)
259     {
260         int l1 = length(s1);
261         int l2 = length(s2);
262 
263         int i,j,sg,sd;
264 
265         String<String<int> > fMatrix,rMatrix,tMatrix;
266 
267         resize(fMatrix,l1 + 1);
268         resize(rMatrix,l1 + 1);
269         resize(tMatrix,l1 + 1);
270 
271         for(i = 0;i <= l1;++i)
272         {
273             resize(fMatrix[i],l2 + 1);
274             resize(rMatrix[i],l2 + 1);
275             resize(tMatrix[i],l2 + 1);
276         }
277 
278         for(i = 0;i <= l1;++i)
279             fMatrix[i][0] = i * (-1);
280 
281         for(i = l1;i >= 0;--i)
282             rMatrix[i][l2] = (l1 - i) * (-1);
283 
284         // calculate forward matrix
285         for(j = 1;j <= l2;++j)
286         {
287             fMatrix[0][j] = j*(-1);
288             for(i = 1;i <= l1;++i)
289             {
290                 sg = -1 + ((fMatrix[i-1][j] > fMatrix[i][j-1]) ? fMatrix[i-1][j] : fMatrix[i][j-1]);
291                 sd = fMatrix[i-1][j-1] + ((s1[i - 1] == s2[j-1]) ? 0 : -1 );
292 
293                 fMatrix[i][j] = ((sg > sd) ? sg : sd);
294             }
295         }
296 
297         // calculate reverse matrix
298         for(j = l2 - 1;j >= 0;--j)
299         {
300             rMatrix[l1][j] = (l2 - j)*(-1);
301             for(i = l1 - 1;i >= 0;--i)
302             {
303                 sg = -1 + ((rMatrix[i+1][j] > rMatrix[i][j+1]) ? rMatrix[i+1][j] : rMatrix[i][j+1]);
304                 sd = rMatrix[i+1][j+1] + ((s1[i] == s2[j]) ? 0 : -1 );
305 
306                 rMatrix[i][j] = ((sg > sd) ? sg : sd);
307             }
308         }
309 
310         // print fMatrix
311         std::cout << ";-;";
312         for(i = 0;i < l1;++i)
313             std::cout << s1[i] << ";";
314 
315         std::cout << std::endl << "-;";
316         for(j = 0;j <= l2;++j)
317         {
318             if(j != 0) std::cout << s2[j-1] << ";";
319             for(i = 0;i <= l1;++i)
320             {
321                 std::cout << fMatrix[i][j] << ";";
322             }
323             std::cout << std::endl;
324         }
325         // print rMatrix
326         std::cout << ";";
327         for(i = 0;i < l1;++i)
328             std::cout << s1[i] << ";";
329         std::cout << "-;" << std::endl;
330 
331         for(j = 0;j <= l2;++j)
332         {
333             if(j != l2) std::cout << s2[j] << ";";
334             else std::cout << "-;";
335             for(i = 0;i <= l1;++i)
336             {
337                 std::cout << rMatrix[i][j] << ";";
338             }
339             std::cout << std::endl;
340         }
341 
342         // fill and print target matrix
343         std::cout << ";-;";
344         for(i = 0;i < l1;++i)
345             std::cout << s1[i] << ";";
346 
347         std::cout << std::endl << "-;";
348         for(j = 0;j <= l2;++j)
349         {
350             if(j != 0) std::cout << s2[j-1] << ";";
351             for(i = 0;i <= l1;++i)
352             {
353                 tMatrix[i][j] = fMatrix[i][j] + rMatrix[i][j];
354                 std::cout << tMatrix[i][j] << ";";
355             }
356             std::cout << std::endl;
357         }
358     }
359 
360 #endif
361 
362 // debug flag .. define to see where Hirschberg cuts the sequences
363 //#define SEQAN_HIRSCHBERG_DEBUG_CUT
364 
365 // ----------------------------------------------------------------------------
366 // Function globalAlignment()
367 // ----------------------------------------------------------------------------
368 
369 template <typename TSequenceH, typename TGapsSpecH, typename TSequenceV, typename TGapsSpecV,
370           typename TScoreValue, typename TScoreSpec>
371 TScoreValue
_globalAlignment(Gaps<TSequenceH,TGapsSpecH> & gapsH,Gaps<TSequenceV,TGapsSpecV> & gapsV,Score<TScoreValue,TScoreSpec> const & score_,Hirschberg const &)372 _globalAlignment(Gaps<TSequenceH, TGapsSpecH> & gapsH,
373                  Gaps<TSequenceV, TGapsSpecV> & gapsV,
374                  Score<TScoreValue, TScoreSpec> const & score_,
375                  Hirschberg const & /*algorithmTag*/)
376 {
377     TSequenceH const & s1 = source(gapsH);
378     TSequenceV const & s2 = source(gapsV);
379 
380     TScoreValue total_score = 0;
381 
382     typedef typename Value<TSequenceV>::Type TValueV;
383 
384     typedef typename Size<TSequenceH>::Type TStringSize;
385 
386     typedef typename Iterator<TSequenceH const, Standard>::Type TSequenceHIter;
387     typedef typename Iterator<TSequenceV const, Standard>::Type TSequenceVIter;
388 
389     typedef typename Iterator<Gaps<TSequenceH, TGapsSpecH> >::Type TGapsHIter;
390     typedef typename Iterator<Gaps<TSequenceV, TGapsSpecV> >::Type TGapsVIter;
391 
392     TGapsHIter target_0 = begin(gapsH);
393     TGapsVIter target_1 = begin(gapsV);
394 
395     typedef typename Iterator<Matrix<TScoreValue> >::Type TMatrixIterator;
396 
397     TValueV v;
398 
399     TStringSize len1 = length(s1);
400     TStringSize len2 = length(s2);
401 
402     // string to store the score values for the currently active cell
403     String<TScoreValue> c_score;
404     resize(c_score,len2 + 1);
405     // string to strore the backpointers
406     String<int> pointer;
407     resize(pointer,len2 + 1);
408 
409     // scoring-scheme specific score values
410     TScoreValue score_match = scoreMatch(score_);
411     TScoreValue score_mismatch = scoreMismatch(score_);
412     TScoreValue score_gap = scoreGapExtend(score_);
413 
414     TScoreValue border,s,sg,sd,sg1,sg2;
415     int dp;
416 
417     std::stack<HirschbergSet_> to_process;
418     HirschbergSet_ target;
419 
420     int i,j;
421 
422     HirschbergSet_ hs_complete(0,len1,0,len2,0);
423     to_process.push(hs_complete);
424 
425     while(!to_process.empty())
426     {
427         target = to_process.top();
428         to_process.pop();
429 
430         if(_begin2(target) == _end2(target))
431         {
432             for(i = 0;i < (_end1(target) - _begin1(target));++i)
433             {
434                 insertGap(target_1);
435                 ++target_0;
436                 ++target_1;
437             }
438         }
439         if(_begin1(target) == _end1(target))
440         {
441             for(i = 0;i < (_end2(target) - _begin2(target));++i)
442             {
443                 insertGap(target_0);
444                 ++target_0;
445                 ++target_1;
446             }
447         }
448         else if(_begin1(target) + 1 == _end1(target) || _begin2(target) + 1 == _end2(target))
449         {
450             /* ALIGN */
451 #ifdef SEQAN_HIRSCHBERG_DEBUG_CUT
452             std::cout << "align s1 " << _begin1(target) << " to " << _end1(target) << " and s2 " << _begin2(target) << " to " << _end2(target) << std::endl;
453             std::cout << "align " << infix(s1,_begin1(target),_end1(target)) << " and " << infix(s2,_begin2(target),_end2(target)) << std::endl << std::endl;
454 #endif
455 
456             TStringSize len_1 = _end1(target) - _begin1(target);
457             TStringSize len_2 = _end2(target) - _begin2(target);
458 
459             Matrix<TScoreValue> matrix_;
460 
461             setDimension(matrix_, 2);
462             setLength(matrix_, 0, len_1 + 1);
463             setLength(matrix_, 1, len_2 + 1);
464             resize(matrix_);
465 
466             /* init matrix */
467             TSequenceHIter x_begin = iter(s1, _begin1(target), Standard()) - 1;
468             TSequenceHIter x_end = iter(s1, _end1(target), Standard()) - 1;
469             TSequenceVIter y_begin = iter(s2, _begin2(target), Standard()) - 1;
470             TSequenceVIter y_end = iter(s2, _end2(target), Standard()) - 1;
471 
472             TSequenceHIter x = x_end;
473             TSequenceVIter y;
474 
475             TMatrixIterator col_ = end(matrix_) - 1;
476             TMatrixIterator finger1;
477             TMatrixIterator finger2;
478 
479 
480             TScoreValue h = 0;
481             TScoreValue border_ = score_gap;
482             TScoreValue v = border_;
483 
484 
485             //-------------------------------------------------------------------------
486             // init
487 
488             finger1 = col_;
489             *finger1 = 0;
490             for (x = x_end; x != x_begin; --x)
491             {
492                 goPrevious(finger1, 0);
493                 *finger1 = border_;
494                 border_ += score_gap;
495             }
496 
497             //-------------------------------------------------------------------------
498             //fill matrix
499             border_ = 0;
500             for (y = y_end; y != y_begin; --y)
501             {
502                 TValueV cy = *y;
503                 h = border_;
504                 border_ += score_gap;
505                 v = border_;
506 
507                 finger2 = col_;
508                 goPrevious(col_, 1);
509                 finger1 = col_;
510 
511                 *finger1 = v;
512 
513                 for (x = x_end; x != x_begin; --x)
514                 {
515                     goPrevious(finger1, 0);
516                     goPrevious(finger2, 0);
517                     if (*x == cy)
518                     {
519                         v = h + score_match;
520                         h = *finger2;
521                     }
522                     else
523                     {
524                         TScoreValue s1 = h + score_mismatch;
525                         h = *finger2;
526                         TScoreValue s2 = score_gap + ((h > v) ? h : v);
527                         v = (s1 > s2) ? s1 : s2;
528                     }
529                     *finger1 = v;
530                 }
531             }
532             total_score += value(matrix_, 0,0);
533 #ifdef SEQAN_HIRSCHBERG_DEBUG_CUT
534             std::cout << "alignment score is " << total_score << std::endl << std::endl;
535 #endif
536 
537             /* TRACE BACK */
538             finger1 = begin(matrix_);
539             x = iter(s1,_begin1(target));
540             y = iter(s2,_begin2(target));
541             x_end = iter(s1,_end1(target));
542             y_end = iter(s2,_end2(target));
543 
544             while ((x != x_end) && (y != y_end))
545             {
546                 bool gv;
547                 bool gh;
548 
549                 if (*x == *y)
550                 {
551                     gv = gh = true;
552                 }
553                 else
554                 {
555                     TMatrixIterator it_ = finger1;
556 
557                     goNext(it_, 0);
558                     TScoreValue v = *it_;
559 
560                     goNext(it_, 1);
561                     TScoreValue d = *it_;
562 
563                     it_ = finger1;
564                     goNext(it_, 1);
565                     TScoreValue h = *it_;
566 
567                     gv = (v >= h) | (d >= h);
568                     gh = (h >= v) | (d >= v);
569                 }
570 
571                 if (gv)
572                 {
573                     ++x;
574                     goNext(finger1, 0);
575                 }
576                 else
577                 {
578                     insertGap(target_0);
579                 }
580 
581                 if (gh)
582                 {
583                     ++y;
584                     goNext(finger1, 1);
585                 }
586                 else
587                 {
588                     insertGap(target_1);
589                 }
590 
591                 ++target_0;
592                 ++target_1;
593             }
594 
595             // if x or y did not reached there end position, fill the rest with gaps
596             while(x != x_end)
597             {
598                 insertGap(target_1);
599                 ++target_0;
600                 ++target_1;
601                 ++x;
602             }
603 
604             while(y != y_end)
605             {
606                 insertGap(target_0);
607                 ++target_0;
608                 ++target_1;
609                 ++y;
610             }
611             /* END ALIGN */
612         }
613         else
614         {
615             /*
616                 Calculate cut using the algorithm as proposed in the lecture of Clemens Gröpl
617                 using a backpointer to remember the position where the optimal alignment passes
618                 the mid column
619             */
620             int mid = static_cast<int>(floor( static_cast<double>((_begin1(target) + _end1(target))/2) ));
621 
622 #ifdef SEQAN_HIRSCHBERG_DEBUG_CUT
623             std::cout << "calculate cut for s1 " << _begin1(target) << " to " << _end1(target) << " and s2 " << _begin2(target) << " to " << _end2(target) << std::endl;
624             std::cout << "calculate cut for " << infix(s1,_begin1(target),_end1(target)) << " and " << infix(s2,_begin2(target),_end2(target)) << std::endl;
625             std::cout << "cut is in row " << mid << " symbol is " << getValue(s1,mid-1) << std::endl << std::endl;
626 
627 
628             _writeDebugMatrix(infix(s1,_begin1(target),_end1(target)),infix(s2,_begin2(target),_end2(target)));
629 #endif
630 
631             border = 0;
632             for(i = _begin2(target);i <= _end2(target);++i)
633             {
634                 c_score[i] = border;
635                 border += score_gap;
636                 pointer[i] = i;
637             }
638 
639             // iterate over s1 until the mid column is reached
640             border = score_gap;
641             for(i = _begin1(target) + 1;i <= mid;++i)
642             {
643                 s = c_score[_begin2(target)];
644                 c_score[_begin2(target)] = border;
645                 border += score_gap;
646                 v = getValue(s1,i-1);
647                 for(j = _begin2(target) + 1;j <= _end2(target);++j)
648                 {
649                     sg = score_gap + ((c_score[j] > c_score[j - 1]) ? c_score[j] : c_score[j - 1]);
650                     sd = s + ((v == getValue(s2,j-1)) ? score_match : score_mismatch);
651 
652                     s = c_score[j];
653                     c_score[j] = (sg > sd) ? sg : sd;
654                 }
655             }
656 
657             // from here, rememeber the cell of mid-column, where optimal alignment passed
658             for(i = mid + 1;i <= _end1(target);++i)
659             {
660                 s = c_score[_begin2(target)];
661                 c_score[_begin2(target)] = border;
662                 border += score_gap;
663                 v = getValue(s1,i-1);
664 
665                 dp = _begin2(target);
666 
667                 for(j = _begin2(target) + 1;j <= _end2(target);++j)
668                 {
669                     sg1 = score_gap + c_score[j];
670                     sg2 = score_gap + c_score[j - 1];
671 
672                     sd = s + ((v == getValue(s2,j-1)) ? score_match : score_mismatch);
673 
674                     s = c_score[j];
675                     sg = pointer[j];
676                     if(sd >= _max(sg1,sg2))
677                     {
678                         c_score[j] = sd;
679                         pointer[j] = dp;
680                     }
681                     else
682                     {
683                         if(sg2 > sg1)
684                         {
685                             c_score[j] = sg2;
686                             pointer[j] = pointer[j-1];
687                         }
688                         else
689                         {
690                             // gap introduced from left
691                             // no update for the pointer
692                             c_score[j] = sg1;
693                         }
694                     }
695                     dp = sg;
696                 }
697             }
698 
699 #ifdef SEQAN_HIRSCHBERG_DEBUG_CUT
700             std::cout << "hirschberg calculates cut in column " << mid << " and row " << pointer[_end2(target)] << std::endl;
701             std::cout << "requested position in c_score and pointer is " << _end2(target) << std::endl;
702             std::cout << "alignment score is " << c_score[_end2(target)] << std::endl << std::endl;
703 #endif
704             to_process.push(HirschbergSet_(mid,_end1(target),pointer[_end2(target)],_end2(target),0));
705             to_process.push(HirschbergSet_(_begin1(target),mid,_begin2(target),pointer[_end2(target)],0));
706         }
707         /* END CUT */
708     }
709     return total_score;
710 }
711 
712 }  // namespace seqan
713 
714 #endif  // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_GLOBAL_ALIGNMENT_HIRSCHBERG_IMPL_H_
715