NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gotoh_banded_inl.h
Go to the documentation of this file.
1 /*
2  * nvbio
3  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 #include <nvbio/basic/types.h>
31 #include <nvbio/basic/numbers.h>
32 
33 namespace nvbio {
34 namespace aln {
35 
36 namespace priv {
37 namespace banded {
38 
41 
42 #define SW_F_INITIALIZED_TO_INF
43 
44 // initialize the zero-th row of the banded DP-matrix with Gotoh scoring
45 //
46 template <uint32 BAND_LEN, AlignmentType TYPE, typename H_band_type, typename F_band_type, typename scoring_type, typename score_type>
49  H_band_type& H_band,
50  F_band_type& F_band,
51  const scoring_type& scoring,
52  const score_type infimum)
53 {
54  H_band[0] = 0;
55  #pragma unroll
56  for (uint32 j = 1; j < BAND_LEN; ++j)
57  H_band[j] = TYPE == GLOBAL ? scoring.text_gap_open() + (j-1)*scoring.text_gap_extension() : 0;
58 
59  #if defined(SW_F_INITIALIZED_TO_INF)
60  // F[0,*] = -inf
61  #pragma unroll
62  for (uint32 j = 0; j < BAND_LEN; ++j)
63  F_band[j] = infimum;
64  #else
65  // F[0,*] = 0
66  #pragma unroll
67  for (uint32 j = 0; j < BAND_LEN; ++j)
68  F_band[j] = 0;
69  #endif
70 
71  // The following is the initialization code for the "post" F-loop, i.e. for the case in which
72  // F is updated _after_ updating H
73  // F[0,*] = -inf, so F[1,*] is the gap open cost, except F[1,BAND_LEN-1] remains -inf
74  //#pragma unroll
75  //for (uint32 j = 0; j < BAND_LEN-1; ++j)
76  // F_band[j] = scoring.pattern_gap_open();
77 }
78 
87 template <uint32 BAND_LEN, AlignmentType TYPE>
89 {
90  template <typename H_band_type, typename F_band_type, typename scoring_type, typename score_type>
92  void init(
93  const uint32 i,
94  H_band_type& H_band,
95  F_band_type& F_band,
96  const scoring_type& scoring,
97  const score_type infimum)
98  {
99  init_row_zero<BAND_LEN,TYPE>( H_band, F_band, scoring, infimum );
100  }
101 
102  template <typename H_band_type, typename F_band_type>
105  const uint32 i,
106  const H_band_type& H_band,
107  const F_band_type& F_band) {}
108 
109  template <typename H_band_type, typename F_band_type>
111  void last_row(
112  const uint32 i,
113  const H_band_type& H_band,
114  const F_band_type& F_band) {}
115 
116  // dir, edir, fdir are backtracking arrows for H,E and F submatrices, respectively at this cell
117  template <typename score_type>
119  void new_cell(
120  const uint32 i,
121  const uint32 j,
122  const score_type score,
123  const DirectionVector dir,
124  const DirectionVector edir,
125  const DirectionVector fdir) {}
126 };
127 
132 template <uint32 BAND_LEN, AlignmentType TYPE, typename checkpoint_type>
134 {
137  m_checkpoints( checkpoints ) {}
138 
139  template <typename H_band_type, typename F_band_type, typename scoring_type, typename score_type>
141  void init(
142  const uint32 i,
143  H_band_type& H_band,
144  F_band_type& F_band,
145  const scoring_type& scoring,
146  const score_type infimum)
147  {
148  // check whether this is the first row
149  if (i == 0)
150  init_row_zero<BAND_LEN,TYPE>( H_band, F_band, scoring, infimum );
151  else
152  {
153  // load from checkpoint
154  #pragma unroll
155  for (uint32 j = 0; j < BAND_LEN; ++j)
156  {
157  H_band[j] = m_checkpoints[j].x;
158  F_band[j] = m_checkpoints[j].y;
159  }
160  }
161  }
162 
163  template <typename H_band_type, typename F_band_type>
166  const uint32 i,
167  const H_band_type& H_band,
168  const F_band_type& F_band) {}
169 
170  template <typename H_band_type, typename F_band_type>
172  void last_row(
173  const uint32 i,
174  const H_band_type& H_band,
175  const F_band_type& F_band)
176  {
177  const short infimum = Field_traits<short>::min() + 32;
178 
179  // save the last row
180  #pragma unroll
181  for (uint32 j = 0; j < BAND_LEN; ++j)
182  m_checkpoints[j] = make_short2(
183  nvbio::max( H_band[j], infimum ),
184  nvbio::max( F_band[j], infimum ) );
185  }
186 
187  // dir, edir, fdir are backtracking arrows for H,E and F submatrices, respectively at this cell
188  template <typename score_type>
190  void new_cell(
191  const uint32 i,
192  const uint32 j,
193  const score_type score,
194  const DirectionVector dir,
195  const DirectionVector edir,
196  const DirectionVector fdir) {}
197 
198  checkpoint_type m_checkpoints;
199 };
200 
205 template <uint32 BAND_LEN, AlignmentType TYPE, uint32 CHECKPOINTS, typename checkpoint_type>
207 {
210  m_checkpoints( checkpoints ) {}
211 
212  template <typename H_band_type, typename F_band_type, typename scoring_type, typename score_type>
214  void init(
215  const uint32 i,
216  H_band_type& H_band,
217  F_band_type& F_band,
218  const scoring_type& scoring,
219  const score_type infimum)
220  {
221  init_row_zero<BAND_LEN,TYPE>( H_band, F_band, scoring, infimum );
222  }
223 
224  template <typename H_band_type, typename F_band_type>
227  const uint32 i,
228  const H_band_type& H_band,
229  const F_band_type& F_band)
230  {
231  // save checkpoint
232  if ((i & (CHECKPOINTS-1)) == 0u)
233  {
234  const short infimum = Field_traits<short>::min() + 32;
235 
236  for (uint32 j = 0; j < BAND_LEN; ++j)
237  m_checkpoints[BAND_LEN*(i/CHECKPOINTS) + j] = make_short2(
238  nvbio::max( H_band[j], infimum ),
239  nvbio::max( F_band[j], infimum ) );
240  }
241  }
242 
243  template <typename H_band_type, typename F_band_type>
245  void last_row(
246  const uint32 i,
247  const H_band_type& H_band,
248  const F_band_type& F_band)
249  {
250  const short infimum = Field_traits<short>::min() + 32;
251 
252  // save the last row
253  const uint32 checkpoint_row = (i+CHECKPOINTS-1)/CHECKPOINTS;
254  for (uint32 j = 0; j < BAND_LEN; ++j)
255  m_checkpoints[BAND_LEN*checkpoint_row + j] = make_short2(
256  nvbio::max( H_band[j], infimum ),
257  nvbio::max( F_band[j], infimum ) );
258  }
259 
260  // dir, edir, fdir are backtracking arrows for H,E and F submatrices, respectively at this cell
261  template <typename score_type>
263  void new_cell(
264  const uint32 i,
265  const uint32 j,
266  const score_type score,
267  const DirectionVector dir,
268  const DirectionVector edir,
269  const DirectionVector fdir) {}
270 
271  checkpoint_type m_checkpoints;
272 };
273 
278 template <uint32 BAND_LEN, AlignmentType TYPE, uint32 CHECKPOINTS, typename checkpoint_type, typename submatrix_type>
280 {
283  const checkpoint_type checkpoints,
284  const uint32 checkpoint_id,
285  submatrix_type submatrix) :
286  m_checkpoints( checkpoints ),
287  m_checkpoint_id( checkpoint_id ),
288  m_submatrix( submatrix ) {}
289 
290  template <typename H_band_type, typename F_band_type, typename scoring_type, typename score_type>
292  void init(
293  const uint32 i,
294  H_band_type& H_band,
295  F_band_type& F_band,
296  const scoring_type& scoring,
297  const score_type infimum)
298  {
299  // restore the checkpoint
300  #pragma unroll
301  for (uint32 j = 0; j < BAND_LEN; ++j)
302  {
303  const short2 f = m_checkpoints[m_checkpoint_id*BAND_LEN + j];
304  H_band[j] = f.x;
305  F_band[j] = f.y;
306  }
307  }
308 
309  template <typename H_band_type, typename F_band_type>
312  const uint32 i,
313  const H_band_type& H_band,
314  const F_band_type& F_band) {}
315 
316  template <typename H_band_type, typename F_band_type>
318  void last_row(
319  const uint32 i,
320  const H_band_type& H_band,
321  const F_band_type& F_band) {}
322 
323  template <typename score_type>
325  void new_cell(
326  const uint32 i,
327  const uint32 j,
328  const score_type score,
329  const DirectionVector hdir,
330  const DirectionVector edir,
331  const DirectionVector fdir)
332  {
333  // save the direction vectors for H,E,F
334  const uint8 cdir =
335  (TYPE == LOCAL ? (score == 0 ? SINK : hdir) : hdir) | edir | fdir;
336 
337  const uint32 offset = m_checkpoint_id * CHECKPOINTS;
338  m_submatrix[ (i - offset)*BAND_LEN + j ] = cdir;
339  }
340 
341  checkpoint_type m_checkpoints;
343  submatrix_type m_submatrix;
344 };
345 
349 template <uint32 BAND_LEN, AlignmentType TYPE>
351 {
406  template <
407  typename pattern_type,
408  typename qual_type,
409  typename text_type,
410  typename scoring_type,
411  typename context_type,
412  typename sink_type>
414  static
415  bool run(
416  const scoring_type& scoring,
417  pattern_type pattern,
418  qual_type quals,
419  text_type text,
420  const uint32 window_begin,
421  const uint32 window_end,
422  const uint32 pos,
423  const int32 min_score,
424  context_type& context,
425  sink_type& sink)
426  {
427  const uint32 pattern_len = pattern.length();
428  const uint32 text_len = text.length();
429  const uint32 start = pos;
430 
431  if (text_len < pattern_len)
432  return false;
433 
434  typedef int32 score_type;
435 
436  typedef typename Reference_cache<BAND_LEN>::type text_cache_type;
437  uint32 text_cache_storage[Reference_cache<BAND_LEN>::BAND_WORDS];
438  text_cache_type text_cache( text_cache_storage );
439 
440  // load first band of text
441  for (uint32 j = 0; j < BAND_LEN-1; ++j)
442  text_cache[j] = text[start+window_begin+j];
443 
444  const score_type G_o = scoring.pattern_gap_open();
445  const score_type G_e = scoring.pattern_gap_extension();
446  const score_type infimum = Field_traits<short>::min() -
447  nvbio::max( nvbio::max( G_o, G_e ),
448  nvbio::max( scoring.text_gap_open(), scoring.text_gap_extension() ) );
449 
450  // initialize the first band (corresponding to the 0-th row of the DP matrix)
451  score_type H_band[BAND_LEN];
452  score_type F_band[BAND_LEN];
453 
454  // initialize bands
455  context.init(
456  window_begin,
457  H_band,
458  F_band,
459  scoring,
460  infimum );
461 
462  // loop across the short edge of the DP matrix: each band is a segment of the long columns
463  for (uint32 i = window_begin; i < window_end; ++i)
464  {
465  // pass the previous row to the context
466  context.previous_row( i, H_band, F_band );
467 
468  // load the new pattern character
469  const uint8 q = pattern[i];
470  const uint8 qq = quals[i];
471 
472  //const score_type V = scoring.match(qq);
473 
474  //
475  // arrows for backtracking - in the E,F case, SUBSTITUTION means the score came from H,
476  // INSERTION means from E or F respectively (to fit in 1 bit we use INSERTION = 1 for both)
477  // note for hdir we have separate values for INSERTION (from F), DELETION (from E)
478  //
481 
482  // j == 0 case
483  {
484  // update F
485  const score_type ftop = F_band[1] + G_e;
486  const score_type htop = H_band[1] + G_o;
487  F_band[0] = nvbio::max( ftop, htop );
488  const DirectionVector fdir = ftop > htop ? DELETION_EXT : SUBSTITUTION;
489 
490  const uint8 g = text_cache[0];
491  //const score_type S_ij = (g == q) ? V : scoring.mismatch( g, q, qq );
492  const score_type S_ij = scoring.substitution( i+0, i, g, q, qq );
493  const score_type diagonal = H_band[0] + S_ij;
494  const score_type top = F_band[0];
495  score_type hi = nvbio::max( top, diagonal );
496 
497  if (TYPE == LOCAL)
498  {
499  hi = nvbio::max( hi, score_type(0) ); // clamp to zero
500  hdir = ( hi == score_type(0) ) ? SINK : hdir; // a score of 0 would terminate backtracking
501  sink.report( hi, make_uint2( i+1, i+1 ) );
502  }
503  H_band[0] = hi;
504 
505  // update the maximum score
506  //max_score = hi;
507 
508  // pass the new cell to the context (we save the fdir vector at the end of the previous iteration)
509  context.new_cell(
510  i, 0u,
511  hi,
512  (hdir == SINK) ? SINK : (top > diagonal ? INSERTION : SUBSTITUTION),
513  SUBSTITUTION,
514  fdir );
515  }
516  // compute E_1
517  score_type E_j = H_band[0] + G_o;
518 
519  #pragma unroll
520  for (uint32 j = 1; j < BAND_LEN-1; ++j)
521  {
522  // update F
523  const score_type ftop = F_band[j+1] + G_e;
524  const score_type htop = H_band[j+1] + G_o;
525  F_band[j] = nvbio::max( ftop, htop );
526  const DirectionVector fdir = ftop > htop ? DELETION_EXT : SUBSTITUTION;
527  /*DirectionVector fdir;
528  if (j < BAND_LEN-2)
529  {
530  const score_type ftop = F_band[j+1] + G_e;
531  const score_type htop = H_band[j+1] + G_o;
532  F_band[j] = nvbio::max( ftop, htop );
533  fdir = ftop > htop ? DELETION_EXT : SUBSTITUTION;
534  }
535  else
536  {
537  // except for the special case i = 0, F[BAND_LEN-1] = -inf, so F[BAND_LEN-2] = H[BAND_LEN-1] + G_o
538  F_band[ BAND_LEN-2 ] = H_band[BAND_LEN-1] + G_o;
539  fdir = SUBSTITUTION;
540  }*/
541 
542  const uint32 g = text_cache[j]; text_cache[j-1] = g;
543  //const score_type S_ij = (g == q) ? V : scoring.mismatch( g, q, qq );
544  const score_type S_ij = scoring.substitution( i+j, i, g, q, qq );
545  const score_type diagonal = H_band[j] + S_ij;
546  const score_type top = F_band[j];
547  const score_type left = E_j;
548  score_type hi = nvbio::max3( top, left, diagonal );
549  hdir = SUBSTITUTION;
550  if (TYPE == LOCAL)
551  {
552  hi = nvbio::max( hi, score_type(0) ); // clamp to zero
553  hdir = ( hi == score_type(0) ) ? SINK : hdir; //at a score of 0 we would terminate backtracking in LOCAL alignment
554  sink.report( hi, make_uint2( i + j + 1, i+1 ) );
555  }
556  H_band[j] = hi;
557 
558  // update the maximum score
559  //max_score = nvbio::max( max_score, hi );
560 
561  // pass the new cell to the context, again fdir is saved in the previous iteration
562  context.new_cell(
563  i, j,
564  hi,
565  (hdir == SINK) ? SINK :
566  (top > left ?
567  (top > diagonal ? INSERTION : SUBSTITUTION) :
568  (left > diagonal ? DELETION : SUBSTITUTION)),
569  edir,
570  fdir );
571 
572  // update E for the next round, i.e. j+1
573  const score_type eleft = E_j + G_e;
574  const score_type ediagonal = hi + G_o;
575  edir = (eleft > ediagonal) ? INSERTION_EXT : SUBSTITUTION;
576  E_j = nvbio::max( ediagonal, eleft );
577  }
578 
579  // load the new text character and fill last entry of the band cache
580  const uint8 g = start+i+BAND_LEN-1 < text_len ? text[start+i+BAND_LEN-1] : 255u;
581  text_cache[ BAND_LEN-2 ] = g;
582 
583  // j == BAND_LEN-1 case
584  {
585  // F[BAND_LEN] && H[BAND_LEN] = -inf so the max here is always -inf
586  F_band[ BAND_LEN-1 ] = infimum;
587  const DirectionVector fdir = SUBSTITUTION;
588 
589  // udpate H
590  //const score_type S_ij = (g == q) ? V : scoring.mismatch( g, q, qq );
591  const score_type S_ij = scoring.substitution( i+BAND_LEN-1, i, g, q, qq );
592  const score_type diagonal = H_band[BAND_LEN-1] + S_ij;
593  const score_type left = E_j;
594  score_type hi = nvbio::max( left, diagonal );
595  hdir = SUBSTITUTION;
596  if (TYPE == LOCAL)
597  {
598  hi = nvbio::max( hi, score_type(0) ); // clamp to zero
599  hdir = ( hi == score_type(0) ) ? SINK : hdir; // a score of 0 terminates backtracking in LOCAL alignment
600  sink.report( hi, make_uint2( i + BAND_LEN, i+1 ) );
601  }
602  H_band[ BAND_LEN-1 ] = hi;
603 
604  // update the maximum score
605  //max_score = nvbio::max( max_score, hi );
606 
607  // pass the new cell to the context
608  context.new_cell(
609  i, BAND_LEN-1,
610  hi,
611  (hdir == SINK) ? SINK : (left > diagonal ? DELETION : SUBSTITUTION),
612  edir,
613  fdir );
614  }
615 
616  // check whether min_score is within reach
617  //const score_type threshold_score = score_type( min_score ) + score_type(pattern_len - i - 1)*scoring.match(0);
618  //if (max_score < threshold_score)
619  // return false;
620  }
621 
622  if (window_end < pattern_len)
623  {
624  // compute the maximum score we got
625  score_type max_score = H_band[0];
626  #pragma unroll
627  for (uint32 j = 1; j < BAND_LEN; ++j)
628  max_score = nvbio::max( max_score, H_band[j] );
629 
630  // and check whether min_score is within reach
631  const score_type threshold_score = score_type( min_score ) + score_type(pattern_len - window_end)*scoring.match(0);
632  if (max_score < threshold_score)
633  return false;
634  }
635 
636  // pass the last row to the context
637  context.last_row( window_end, H_band, F_band );
638 
639  if (window_end == pattern_len)
640  {
641  if (TYPE == GLOBAL)
642  sink.report( H_band[ BAND_LEN-1 ], make_uint2( pattern_len + BAND_LEN-1, pattern_len ) );
643  else if (TYPE == SEMI_GLOBAL)
644  {
645  const uint32 m = nvbio::min( pattern_len + BAND_LEN - 1u, text_len ) - (pattern_len-1u);
646 
647  // get the highest score along the long edge of the path graph
648  sink.report( H_band[0], make_uint2( pattern_len + 0, pattern_len ) );
649  #pragma unroll
650  for (uint32 j = 1; j < BAND_LEN; ++j)
651  {
652  if (j < m)
653  sink.report( H_band[j], make_uint2( pattern_len + j, pattern_len ) );
654  }
655  }
656  }
657  return true;
658  }
659 };
660 
662 
663 } // namespace banded
664 
667 
680 template <
681  uint32 BAND_LEN,
683  typename scoring_type,
684  typename pattern_type,
685  typename qual_type,
686  typename text_type,
687  typename sink_type>
690  const GotohAligner<TYPE,scoring_type>& aligner,
691  pattern_type pattern,
692  qual_type quals,
693  text_type text,
694  const int32 min_score,
695  sink_type& sink)
696 {
698 
699  return priv::banded::gotoh_alignment_score_dispatch<BAND_LEN,TYPE>::run( aligner.scheme, pattern, quals, text, 0u, pattern.length(), 0u, min_score, context, sink );
700 }
701 
715 template <
716  uint32 BAND_LEN,
718  typename scoring_type,
719  typename pattern_type,
720  typename qual_type,
721  typename text_type,
722  typename sink_type,
723  typename checkpoint_type>
726  const GotohAligner<TYPE,scoring_type>& aligner,
727  pattern_type pattern,
728  qual_type quals,
729  text_type text,
730  const int32 min_score,
731  const uint32 window_begin,
732  const uint32 window_end,
733  sink_type& sink,
734  checkpoint_type checkpoint)
735 {
737 
738  return priv::banded::gotoh_alignment_score_dispatch<BAND_LEN,TYPE>::run( aligner.scheme, pattern, quals, text, window_begin, window_end, 0u, min_score, context, sink );
739 }
740 
763 template <
764  uint32 BAND_LEN,
765  uint32 CHECKPOINTS,
767  typename scoring_type,
768  typename pattern_type,
769  typename qual_type,
770  typename text_type,
771  typename sink_type,
772  typename checkpoint_type>
775  const GotohAligner<TYPE,scoring_type>& aligner,
776  pattern_type pattern,
777  qual_type quals,
778  text_type text,
779  const int32 min_score,
780  sink_type& sink,
781  checkpoint_type checkpoints)
782 {
784 
785  return priv::banded::gotoh_alignment_score_dispatch<BAND_LEN,TYPE>::run( aligner.scheme, pattern, quals, text, 0u, pattern.length(), 0u, min_score, context, sink );
786 }
787 
820 template <
821  uint32 BAND_LEN,
822  uint32 CHECKPOINTS,
824  typename scoring_type,
825  typename pattern_string,
826  typename qual_string,
827  typename text_string,
828  typename checkpoint_type,
829  typename submatrix_type>
832  const GotohAligner<TYPE,scoring_type>& aligner,
833  pattern_string pattern,
834  qual_string quals,
835  text_string text,
836  const int32 min_score,
837  checkpoint_type checkpoints,
838  const uint32 checkpoint_id,
839  submatrix_type submatrix)
840 {
842  const uint32 window_begin = checkpoint_id * CHECKPOINTS;
843  const uint32 window_end = nvbio::min( window_begin + CHECKPOINTS, uint32(pattern.length()) );
844  NullSink sink;
845 
846  priv::banded::gotoh_alignment_score_dispatch<BAND_LEN,TYPE>::run( aligner.scheme, pattern, quals, text, window_begin, window_end, 0u, min_score, context, sink );
847 
848  return window_end - window_begin;
849 }
850 
886 template <
887  uint32 BAND_LEN,
888  uint32 CHECKPOINTS,
890  typename scoring_type,
891  typename checkpoint_type,
892  typename submatrix_type,
893  typename backtracer_type>
896  const GotohAligner<TYPE,scoring_type>& aligner,
897  checkpoint_type checkpoints,
898  const uint32 checkpoint_id,
899  submatrix_type submatrix,
900  const uint32 submatrix_height,
901  uint8& state,
902  uint2& sink,
903  backtracer_type& backtracer)
904 {
905  // Backtrack from the second checkpoint to the first looking up the flow submatrices H,E,F
906  // and keeping track of which we are in via state
907 
908  int32 current_entry = sink.x - sink.y;
909  int32 current_row = sink.y - checkpoint_id*CHECKPOINTS - 1u;
910 
911  NVBIO_CUDA_DEBUG_ASSERT( current_entry >= 0 &&
912  current_entry < BAND_LEN, "sw::banded_alignment_backtrack(): sink (%u,%u) -> local x coordinate %d not in [0,%d[\n", sink.x, sink.y, current_entry, BAND_LEN );
913  NVBIO_CUDA_DEBUG_ASSERT( current_row >= 0, "sw::banded_alignment_backtrack(): sink (%u,%u) -> local y coordinate %d not in [0,%u[\n", sink.x, sink.y, current_row, submatrix_height );
914  NVBIO_CUDA_DEBUG_ASSERT( current_row < submatrix_height, "sw::banded_alignment_backtrack(): sink (%u,%u) -> local y coordinate %d not in [0,%u[\n", sink.x, sink.y, current_row, submatrix_height );
915 
916  while (current_row >= 0)
917  {
918  const uint32 submatrix_cell = current_row * BAND_LEN + current_entry;
919  const uint8 op = submatrix[ submatrix_cell ];
920  const uint8 h_op = op & HMASK;
921 
922  if (TYPE == LOCAL)
923  {
924  if (state == HSTATE && h_op == SINK)
925  {
926  sink.y = current_row + checkpoint_id*CHECKPOINTS + 1u;
927  sink.x = current_entry + sink.y;
928  return true;
929  }
930  }
931 
932  if (state == ESTATE)
933  {
934  if ((op & INSERTION_EXT) == 0u) state = HSTATE;
935  --current_entry;
936  backtracer.push( DELETION );
937  }
938  else if (state == FSTATE)
939  {
940  if ((op & DELETION_EXT) == 0u) state = HSTATE;
941  ++current_entry; --current_row;
942  backtracer.push( INSERTION );
943  }
944  else
945  {
946  if (h_op == DELETION)
947  state = ESTATE;
948  else if (h_op == INSERTION)
949  state = FSTATE;
950  else
951  {
952  --current_row;
953  backtracer.push( SUBSTITUTION );
954  }
955 
956  }
957  NVBIO_CUDA_ASSERT( current_entry >= 0 && current_entry < BAND_LEN );
958  }
959  sink.y = checkpoint_id*CHECKPOINTS;
960  sink.x = current_entry + sink.y;
961  return false;
962 }
963 
965 
966 } // namespace priv
967 
968 } // namespace sw
969 } // namespace nvbio