~ubuntu-branches/ubuntu/edgy/ncbi-tools6/edgy

« back to all changes in this revision

Viewing changes to algo/blast/core/blast_extend.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2006-07-19 23:28:07 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060719232807-et3cdmcjgmnyleyx
Tags: 6.1.20060507-3ubuntu1
Re-merge with Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: blast_extend.c,v 1.90 2005/12/05 16:36:50 papadopo Exp $
 
1
/* $Id: blast_extend.c,v 1.94 2006/01/03 17:55:37 papadopo Exp $
2
2
 * ===========================================================================
3
3
 *
4
4
 *                            PUBLIC DOMAIN NOTICE
30
30
 
31
31
#ifndef SKIP_DOXYGEN_PROCESSING
32
32
static char const rcsid[] = 
33
 
    "$Id: blast_extend.c,v 1.90 2005/12/05 16:36:50 papadopo Exp $";
 
33
    "$Id: blast_extend.c,v 1.94 2006/01/03 17:55:37 papadopo Exp $";
34
34
#endif /* SKIP_DOXYGEN_PROCESSING */
35
35
 
36
36
#include <algo/blast/core/blast_extend.h>
267
267
   return TRUE;
268
268
}
269
269
 
270
 
/** Perform ungapped extension of a word hit
 
270
/** Perform ungapped extension of a word hit, using a score
 
271
 *  matrix and extending one base at a time
271
272
 * @param query The query sequence [in]
272
273
 * @param subject The subject sequence [in]
273
274
 * @param matrix The scoring matrix [in]
275
276
 * @param s_off The offset of a word in subject [in]
276
277
 * @param X The drop-off parameter for the ungapped extension [in]
277
278
 * @param ungapped_data The ungapped extension information [out]
278
 
 * @return Status: 0 on success, -1 if memory allocation failed.
279
279
 */
280
 
static Int2
281
 
s_NuclUngappedExtend(BLAST_SequenceBlk* query, 
 
280
static void
 
281
s_NuclUngappedExtendExact(BLAST_SequenceBlk* query, 
282
282
   BLAST_SequenceBlk* subject, Int4** matrix, 
283
283
   Int4 q_off, Int4 s_off, Int4 X, 
284
284
   BlastUngappedData* ungapped_data)
306
306
      remainder = 3;
307
307
   }
308
308
   
309
 
   /* Find where positive scoring starts & ends within the word hit */
310
309
   score = 0;
311
310
   sum = 0;
312
311
 
340
339
   }
341
340
        
342
341
   /* extend to the right */
343
 
   q = q_end;
344
 
   s = s_end;
 
342
   q = query->sequence + q_off;
 
343
   s = subject0 + s_off/COMPRESSION_RATIO;
345
344
   sum = 0;
346
345
   base = 3 - (s_off % COMPRESSION_RATIO);
347
 
   
 
346
 
348
347
   while (s < sf || (s == sf && base > remainder)) {
349
348
      ch = *s;
350
349
      if ((sum += matrix[*q++][NCBI2NA_UNPACK_BASE(ch, base)]) > 0) {
362
361
   
363
362
   ungapped_data->length = q_end - q_beg;
364
363
   ungapped_data->score = score;
 
364
}
 
365
 
 
366
/** Perform ungapped extension of a word hit. Use an approximate method
 
367
 * and revert to rigorous ungapped alignment if the approximate score
 
368
 * is high enough
 
369
 * @param query The query sequence [in]
 
370
 * @param subject The subject sequence [in]
 
371
 * @param matrix The scoring matrix [in]
 
372
 * @param q_off The offset of a word in query [in]
 
373
 * @param s_match_end The first offset in the subject sequence that 
 
374
 *              is not known to exactly match the query sequence [in]
 
375
 * @param s_off The offset of a word in subject [in]
 
376
 * @param X The drop-off parameter for the ungapped extension [in]
 
377
 * @param ungapped_data The ungapped extension information [out]
 
378
 * @param score_table Array containing precompute sums of
 
379
 *                    match and mismatch scores [in]
 
380
 * @param reduced_cutoff Score beyond which a rigorous extension is used [in]
 
381
 */
 
382
static void
 
383
s_NuclUngappedExtend(BLAST_SequenceBlk* query, 
 
384
   BLAST_SequenceBlk* subject, Int4** matrix, 
 
385
   Int4 q_off, Int4 s_match_end, Int4 s_off,
 
386
   Int4 X, BlastUngappedData* ungapped_data,
 
387
   const Int4 *score_table, Int4 reduced_cutoff)
 
388
{
 
389
   Uint1* q_start = query->sequence;
 
390
   Uint1* s_start = subject->sequence;
 
391
   Uint1* q;
 
392
   Uint1* s;
 
393
   Int4 sum, score;
 
394
   Int4 i, len;
 
395
   Uint1* new_q;
 
396
   Int4 q_ext, s_ext;
365
397
   
366
 
   return 0;
 
398
   /* The left extension begins behind (q_ext,s_ext); this
 
399
      is the first 4-base boundary after s_off. */
 
400
 
 
401
   len = (COMPRESSION_RATIO - (s_off % COMPRESSION_RATIO)) %
 
402
                         COMPRESSION_RATIO;
 
403
   q_ext = q_off + len;
 
404
   s_ext = s_off + len;
 
405
   q = q_start + q_ext;
 
406
   s = s_start + s_ext / COMPRESSION_RATIO;
 
407
   len = MIN(q_ext, s_ext) / COMPRESSION_RATIO;
 
408
 
 
409
   score = 0;
 
410
   sum = 0;
 
411
   new_q = q;
 
412
 
 
413
   for (i = 0; i < len; s--, q -= 4, i++) {
 
414
       Uint1 s_byte = s[-1];
 
415
       Uint1 q_byte = (q[-4]<<6) | (q[-3]<<4) | (q[-2]<<2) | q[-1];
 
416
 
 
417
       sum += score_table[q_byte ^ s_byte];
 
418
       if (sum > 0) {
 
419
           new_q = q - 4; score += sum; sum = 0;
 
420
       }
 
421
       if (sum < X) {
 
422
           break;
 
423
       }
 
424
   }
 
425
 
 
426
   /* record the start point of the extension */
 
427
 
 
428
   ungapped_data->q_start = new_q - q_start;
 
429
   ungapped_data->s_start = s_ext - (q_ext - ungapped_data->q_start);
 
430
 
 
431
   /* the right extension begins at the first bases not
 
432
      examined by the previous loop */
 
433
 
 
434
   q = q_start + q_ext;
 
435
   s = s_start + s_ext / COMPRESSION_RATIO;
 
436
   len = MIN(query->length - q_ext, subject->length - s_ext) /
 
437
                        COMPRESSION_RATIO;
 
438
   sum = 0;
 
439
   new_q = q;
 
440
 
 
441
   for (i = 0; i < len; s++, q += 4, i++) {
 
442
       Uint1 s_byte = s[0];
 
443
       Uint1 q_byte = (q[0]<<6) | (q[1]<<4) | (q[2]<<2) | q[3];
 
444
 
 
445
       sum += score_table[q_byte ^ s_byte];
 
446
       if (sum > 0) {
 
447
           new_q = q + 3; score += sum; sum = 0;
 
448
       }
 
449
       if (sum < X) {
 
450
           break;
 
451
       }
 
452
   }
 
453
 
 
454
   if (score > reduced_cutoff) {
 
455
       /* the current score is high enough; throw away the
 
456
          alignment and recompute it rigorously */
 
457
       s_NuclUngappedExtendExact(query, subject, matrix, q_off,
 
458
                                 s_off, X, ungapped_data);
 
459
   }
 
460
   else {
 
461
       /* record the length and score of the extension. Make
 
462
          sure the alignment extends at least to s_match_end */
 
463
       ungapped_data->score = score;
 
464
       ungapped_data->length = MAX(s_match_end - ungapped_data->s_start,
 
465
                               (new_q - q_start) - ungapped_data->q_start + 1);
 
466
   }
367
467
}
368
468
 
369
469
/** Mask for encoding in one integer a hit offset and whether that hit has 
444
544
      if (word_params->options->ungapped_extension) {
445
545
         /* Perform ungapped extension */
446
546
         ungapped_data = &dummy_ungapped_data;
447
 
         s_NuclUngappedExtend(query, subject, matrix, q_off, s_off, 
448
 
                              -word_params->x_dropoff, ungapped_data);
 
547
         s_NuclUngappedExtend(query, subject, matrix, q_off, s_end, s_off, 
 
548
                              -word_params->x_dropoff, ungapped_data,
 
549
                              word_params->nucl_score_table,
 
550
                              word_params->reduced_nucl_cutoff_score);
449
551
      
450
552
         last_hit = ungapped_data->length + ungapped_data->s_start 
451
553
            + diag_table->offset;
593
695
            if (word_params->options->ungapped_extension) {
594
696
               /* Perform ungapped extension */
595
697
               ungapped_data = &dummy_ungapped_data;
596
 
               s_NuclUngappedExtend(query, subject, matrix, q_off, s_off, 
597
 
                                    -word_params->x_dropoff, ungapped_data);
 
698
               s_NuclUngappedExtend(query, subject, matrix, q_off, s_end, s_off,
 
699
                                    -word_params->x_dropoff, ungapped_data,
 
700
                                    word_params->nucl_score_table,
 
701
                                    word_params->reduced_nucl_cutoff_score);
598
702
      
599
703
               last_hit = ungapped_data->length + ungapped_data->s_start;
600
704
            } else {
661
765
      if (word_params->options->ungapped_extension) {
662
766
         /* Perform ungapped extension */
663
767
         ungapped_data = &dummy_ungapped_data;
664
 
         s_NuclUngappedExtend(query, subject, matrix, q_off, s_off, 
665
 
                              -word_params->x_dropoff, ungapped_data);
 
768
         s_NuclUngappedExtend(query, subject, matrix, q_off, s_end, s_off, 
 
769
                              -word_params->x_dropoff, ungapped_data,
 
770
                              word_params->nucl_score_table,
 
771
                              word_params->reduced_nucl_cutoff_score);
666
772
         stack[stack_top].level = 
667
773
            (ungapped_data->length + ungapped_data->s_start);
668
774
      } else {
802
908
                   Int4** matrix, Blast_ExtendWord* ewp, 
803
909
                   BlastInitHitList* init_hitlist)
804
910
{
 
911
   Int4 index;
 
912
   Uint4 query_length = query->length;
 
913
   Uint4 subject_length = subject->length;
 
914
   Uint1* q_start = query->sequence;
805
915
   Uint1* s_start = subject->sequence;
806
 
   Uint1* q_start = query->sequence;
807
 
   Int4 i;
808
 
   Uint1* s;
809
 
   Uint1* q;
810
 
   Uint4 word_length, compressed_wordsize, compressed_word_length;
811
 
   Uint4 reduced_word_length, reduced_wordsize;
812
 
   Uint4 extra_bytes_needed;
813
 
   Uint4 extra_bases, left, right;
 
916
   Uint4 word_length, lut_word_length;
 
917
   Uint4 q_off, s_off;
 
918
   Uint4 max_bases_left, max_bases_right;
 
919
   Uint4 extended_left, extended_right;
 
920
   Uint4 extra_bases;
 
921
   Uint1* q, *s;
 
922
   Uint4 min_step = 0;
814
923
   Int4 hits_extended = 0;
815
 
   Boolean extend_partial_byte = FALSE;
816
 
   Uint4 min_step = 0;
817
924
   Uint1 template_length = 0;
818
 
 
819
 
   if (lookup_wrap->lut_type == MB_LOOKUP_TABLE) {
820
 
      BlastMBLookupTable* mb_lt = (BlastMBLookupTable*)lookup_wrap->lut;
821
 
      word_length = mb_lt->word_length;
822
 
      reduced_wordsize = 
823
 
         (word_length - COMPRESSION_RATIO + 1)/COMPRESSION_RATIO;
824
 
      compressed_wordsize = mb_lt->compressed_wordsize;
825
 
      extend_partial_byte = !mb_lt->variable_wordsize;
826
 
      /* When ungapped extension is not performed, the hit will be new only if
827
 
         it more than scan_step away from the previous hit. */
828
 
      if(!word_params->options->ungapped_extension)
829
 
         min_step = mb_lt->scan_step;
830
 
      template_length = mb_lt->template_length;
831
 
   } else {
832
 
      BlastLookupTable* lookup = (BlastLookupTable*)lookup_wrap->lut;
833
 
      word_length = lookup->word_length;
834
 
      reduced_wordsize = lookup->wordsize;
835
 
      compressed_wordsize = lookup->reduced_wordsize;
836
 
      extend_partial_byte = !lookup->variable_wordsize;
837
 
      /* When ungapped extension is not performed, the hit will be new only if
838
 
         it more than scan_step away from the previous hit. */
839
 
      if(!word_params->options->ungapped_extension)
840
 
         min_step = lookup->scan_step;
841
 
   }
842
 
 
843
 
   extra_bytes_needed = reduced_wordsize - compressed_wordsize;
844
 
 
845
 
   if (!extend_partial_byte) {
846
 
      /* If partial bytes are not checked, we need to check one full extra byte
847
 
         at the end of the word. */
848
 
      ++extra_bytes_needed;
849
 
   }
850
 
 
851
 
   reduced_word_length = COMPRESSION_RATIO*reduced_wordsize;
852
 
   compressed_word_length = COMPRESSION_RATIO*compressed_wordsize;
853
 
   extra_bases = word_length - reduced_word_length;
854
 
 
855
 
   for (i = 0; i < num_hits; ++i) {
856
 
      Uint4 q_offset = offset_pairs[i].qs_offsets.q_off;
857
 
      Uint4 s_offset = offset_pairs[i].qs_offsets.s_off;
858
 
      /* Here it is guaranteed that subject offset is divisible by 4,
859
 
         because we only extend to the right, so scanning stride must be
860
 
         equal to 4. */
861
 
      s = s_start + s_offset/COMPRESSION_RATIO;
 
925
   Boolean hit_ready;
 
926
   BlastLookupTable* lut;
 
927
 
 
928
   ASSERT(lookup_wrap->lut_type != MB_LOOKUP_TABLE);
 
929
   lut = (BlastLookupTable*)lookup_wrap->lut;
 
930
   word_length = lut->word_length;
 
931
   lut_word_length = lut->lut_word_length;
 
932
   extra_bases = word_length - lut_word_length;
 
933
 
 
934
   for (index = 0; index < num_hits; ++index) {
 
935
      Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
 
936
      Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
937
      
 
938
      /* begin with the left extension; the initialization
 
939
         is slightly faster. q below points to the first base
 
940
         of the lookup table hit and s points to the first
 
941
         four bases of the hit (which is guaranteed to be 
 
942
         aligned on a byte boundary) */
 
943
 
 
944
      max_bases_left = MIN(extra_bases, MIN(q_offset, s_offset));
862
945
      q = q_start + q_offset;
863
 
      
864
 
      /* Check for extra bytes if required for longer words. */
865
 
      if (extra_bytes_needed && 
866
 
          !BlastNaCompareExtraBytes(q+compressed_word_length, 
867
 
              s+compressed_wordsize, extra_bytes_needed))
868
 
         continue;
869
 
 
870
 
      if (extend_partial_byte) {
871
 
         /* mini extension to the left */
872
 
         Uint1 max_bases = MIN(COMPRESSION_RATIO, MIN(q_offset, s_offset));
873
 
         left = BlastNaMiniExtendLeft(q, s-1, max_bases);
874
 
         
875
 
         /* mini extension to the right */
876
 
         max_bases =
877
 
            MIN(COMPRESSION_RATIO, 
878
 
                MIN(subject->length - s_offset - reduced_word_length,
879
 
                    query->length - q_offset - reduced_word_length));
880
 
         
881
 
         right = 0;
882
 
         if (max_bases > 0) {
883
 
            s += reduced_wordsize;
884
 
            q += reduced_word_length;
885
 
            right = BlastNaMiniExtendRight(q, s, max_bases);
 
946
      s = s_start + s_offset / COMPRESSION_RATIO;
 
947
 
 
948
      for (extended_left = 0; extended_left < max_bases_left;
 
949
                            s--, q -= 4, extended_left++) {
 
950
         Uint1 byte = s[-1];
 
951
 
 
952
         if ((byte & 3) != q[-1] || ++extended_left == max_bases_left)
 
953
            break;
 
954
         if (((byte>>2) & 3) != q[-2] || ++extended_left == max_bases_left)
 
955
            break;
 
956
         if (((byte>>4) & 3) != q[-3] || ++extended_left == max_bases_left)
 
957
            break;
 
958
         if ((byte>>6) != q[-4])
 
959
            break;
 
960
      }
 
961
 
 
962
      /* do the right extension if the left extension did not
 
963
         find all the bases required. Begin at the first base 
 
964
         past the lookup table hit and move forwards */
 
965
 
 
966
      s_off = s_offset + lut_word_length;
 
967
      extended_right = 0;
 
968
 
 
969
      if (extended_left < extra_bases) {
 
970
         q_off = q_offset + lut_word_length;
 
971
         q = q_start + q_off;
 
972
         s = s_start + s_off / COMPRESSION_RATIO;
 
973
         max_bases_right = MIN(extra_bases - extended_left,
 
974
                               MIN(query_length - q_off, 
 
975
                                   subject_length - s_off));
 
976
 
 
977
         for (; extended_right < max_bases_right;
 
978
                               s++, q += 4, extended_right++) {
 
979
            Uint1 byte = s[0];
 
980
   
 
981
            if ((byte>>6) != q[0] || ++extended_right == max_bases_right)
 
982
               break;
 
983
            if (((byte>>4) & 3) != q[1] || ++extended_right == max_bases_right)
 
984
               break;
 
985
            if (((byte>>2) & 3) != q[2] || ++extended_right == max_bases_right)
 
986
               break;
 
987
            if ((byte & 3) != q[3])
 
988
               break;
886
989
         }
 
990
 
 
991
         /* check if enough extra matches were found */
 
992
 
 
993
         if (extended_left + extended_right < extra_bases)
 
994
            continue;
 
995
      }
 
996
 
 
997
      /* check the diagonal on which the hit lies. The boundaries
 
998
         extend from the first match of the hit to one beyond the
 
999
         last match */
 
1000
 
 
1001
      if (word_params->container_type == eWordStacks) {
 
1002
         hit_ready = s_BlastnStacksExtendInitialHit(query, subject, min_step,
 
1003
                                           template_length, word_params, 
 
1004
                                           matrix, ewp->stack_table, 
 
1005
                                           q_offset - extended_left, 
 
1006
                                           s_off + extended_right,
 
1007
                                           s_offset - extended_left, 
 
1008
                                           init_hitlist);
887
1009
      } else {
888
 
         left = 0;
889
 
         right = COMPRESSION_RATIO;
890
 
      }
891
 
 
892
 
      if (left + right >= extra_bases) {
893
 
         Boolean hit_ready = FALSE;
894
 
         /* Check if this diagonal has already been explored. */
895
 
         if (word_params->container_type == eWordStacks) {
896
 
            hit_ready = 
897
 
               s_BlastnStacksExtendInitialHit(query, subject, min_step, template_length,
898
 
                  word_params, matrix, ewp->stack_table, q_offset, 
899
 
                  s_offset + reduced_word_length + right, 
900
 
                  s_offset, init_hitlist);
901
 
         } else {
902
 
            hit_ready = 
903
 
               s_BlastnDiagExtendInitialHit(query, subject, min_step, template_length,
904
 
                  word_params, matrix, ewp->diag_table, q_offset, 
905
 
                  s_offset + reduced_word_length + right, 
906
 
                  s_offset, init_hitlist);
907
 
         }
908
 
         if (hit_ready)
909
 
            ++hits_extended;
910
 
      }
 
1010
         hit_ready = s_BlastnDiagExtendInitialHit(query, subject, min_step, 
 
1011
                                         template_length, word_params, 
 
1012
                                         matrix, ewp->diag_table, 
 
1013
                                         q_offset - extended_left, 
 
1014
                                         s_off + extended_right,
 
1015
                                         s_offset - extended_left, 
 
1016
                                         init_hitlist);
 
1017
      }
 
1018
      if (hit_ready)
 
1019
         ++hits_extended;
911
1020
   }
912
1021
   return hits_extended;
913
1022
}
929
1038
   Int4 hits_extended = 0;
930
1039
   Int4 start_offset, last_start, next_start;
931
1040
 
932
 
   last_start = subject->length - COMPRESSION_RATIO*lookup->wordsize;
 
1041
   last_start = subject->length - lookup->lut_word_length;
933
1042
   start_offset = 0;
934
1043
 
935
1044
   while (start_offset <= last_start) {
959
1068
   return 0;
960
1069
961
1070
 
962
 
/** Extend an exact match in both directions up to the provided 
963
 
 * maximal length. 
964
 
 * @param q_start Pointer to the start of the extension in query [in]
965
 
 * @param s_start Pointer to the start of the extension in subject [in]
966
 
 * @param max_bases_left At most how many bases to extend to the left [in]
967
 
 * @param max_bases_right At most how many bases to extend to the right [in]
968
 
 * @param max_length The length of the required exact match [in]
969
 
 * @param extend_partial_byte Should partial byte extension be perfomed?[in]
970
 
 * @param extended_right How far has extension succeeded to the right? [out]
971
 
 * @return TRUE if extension successful 
972
 
 */
973
 
static Boolean 
974
 
s_BlastNaExactMatchExtend(Uint1* q_start, Uint1* s_start, 
975
 
   Uint4 max_bases_left, Uint4 max_bases_right, Uint4 max_length, 
976
 
   Boolean extend_partial_byte, Uint4* extended_right)
977
 
{
978
 
   Uint4 length;
979
 
   Uint1* q,* s;
980
 
   
981
 
   *extended_right = 0;
982
 
 
983
 
   length = 0;
984
 
 
985
 
   /* Extend to the right; start from the firstt byte (it must be the 
986
 
      first one that's guaranteed to match by the lookup table hit). */
987
 
 
988
 
   q = q_start;
989
 
   s = s_start;
990
 
   while (length < max_length && max_bases_right >= COMPRESSION_RATIO) {
991
 
      if (*s != PACK_WORD(q))
992
 
         break;
993
 
      length += COMPRESSION_RATIO;
994
 
      ++s;
995
 
      q += COMPRESSION_RATIO;
996
 
      max_bases_right -= COMPRESSION_RATIO;
997
 
   }
998
 
   if (extend_partial_byte) {
999
 
      if (max_bases_right > 0) {
1000
 
         length += BlastNaMiniExtendRight(q, s, 
1001
 
                      (Uint1) MIN(max_bases_right, COMPRESSION_RATIO));
1002
 
      }
1003
 
   }
1004
 
 
1005
 
   *extended_right = length;
1006
 
 
1007
 
   if (length >= max_length)
1008
 
      return TRUE;
1009
 
 
1010
 
   if (max_bases_left < max_length - length)
1011
 
      return FALSE;
1012
 
   else
1013
 
      max_bases_left = max_length - length;
1014
 
 
1015
 
   /* Extend to the left; start with the byte just before the first. */
1016
 
   q = q_start - COMPRESSION_RATIO;
1017
 
   s = s_start - 1;
1018
 
   while (length < max_length && max_bases_left >= COMPRESSION_RATIO) {
1019
 
      if (*s != PACK_WORD(q))
1020
 
         break;
1021
 
      length += COMPRESSION_RATIO;
1022
 
      --s;
1023
 
      q -= COMPRESSION_RATIO;
1024
 
      max_bases_left -= COMPRESSION_RATIO;
1025
 
   }
1026
 
   if (length >= max_length)
1027
 
      return TRUE;
1028
 
   if (extend_partial_byte && max_bases_left > 0) {
1029
 
      length += BlastNaMiniExtendLeft(q+COMPRESSION_RATIO, s, 
1030
 
                   (Uint1) MIN(max_bases_left, COMPRESSION_RATIO));
1031
 
   }
1032
 
 
1033
 
   return (length >= max_length);
1034
 
}
1035
 
 
1036
1071
Int4 
1037
1072
BlastNaExtendRightAndLeft(const BlastOffsetPair* offset_pairs, Int4 num_hits, 
1038
1073
                          const BlastInitialWordParameters* word_params,
1046
1081
   Uint4 subject_length = subject->length;
1047
1082
   Uint1* q_start = query->sequence;
1048
1083
   Uint1* s_start = subject->sequence;
1049
 
   Uint4 word_length = 0;
 
1084
   Uint4 word_length, lut_word_length;
1050
1085
   Uint4 q_off, s_off;
1051
1086
   Uint4 max_bases_left, max_bases_right;
1052
 
   Uint4 extended_right;
1053
 
   Uint4 shift;
 
1087
   Uint4 extended_left, extended_right;
 
1088
   Uint4 extra_bases;
1054
1089
   Uint1* q, *s;
1055
1090
   Uint4 min_step = 0;
1056
 
   Boolean variable_wordsize = FALSE;
1057
1091
   Int4 hits_extended = 0;
1058
1092
   Uint1 template_length = 0;
 
1093
   Boolean hit_ready;
1059
1094
 
1060
1095
   if (lookup_wrap->lut_type == MB_LOOKUP_TABLE) {
1061
1096
      BlastMBLookupTable* lut = (BlastMBLookupTable*)lookup_wrap->lut;
1062
1097
      word_length = lut->word_length;
 
1098
      lut_word_length = lut->lut_word_length;
1063
1099
      /* When ungapped extension is not performed, the hit will be new only if
1064
1100
         it more than scan_step away from the previous hit. */
1065
1101
      if(!word_params->options->ungapped_extension)
1066
1102
         min_step = lut->scan_step;
1067
 
      variable_wordsize = lut->variable_wordsize;
1068
1103
      template_length = lut->template_length;
1069
1104
   } else {
1070
1105
      BlastLookupTable* lut = (BlastLookupTable*)lookup_wrap->lut;
1071
1106
      word_length = lut->word_length;
1072
 
      variable_wordsize = lut->variable_wordsize;
 
1107
      lut_word_length = lut->lut_word_length;
1073
1108
      if(!word_params->options->ungapped_extension)
1074
1109
         min_step = lut->scan_step;
1075
1110
   }
1076
 
 
1077
 
   for (index = 0; index < num_hits; ++index) {
1078
 
      Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
1079
 
      Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
1080
 
      /* Adjust offsets to the start of the next full byte in the
1081
 
         subject sequence */
1082
 
      shift = (COMPRESSION_RATIO - s_offset%COMPRESSION_RATIO)
1083
 
         % COMPRESSION_RATIO;
1084
 
      q_off = q_offset + shift;
1085
 
      s_off = s_offset + shift;
1086
 
      s = s_start + s_off/COMPRESSION_RATIO;
1087
 
      q = q_start + q_off;
1088
 
      
1089
 
      max_bases_left = 
1090
 
         MIN(word_length, MIN(q_off, s_off));
1091
 
      max_bases_right = MIN(word_length, 
1092
 
                            MIN(query_length-q_off, subject_length-s_off));
1093
 
      
1094
 
      if (s_BlastNaExactMatchExtend(q, s, max_bases_left, 
1095
 
                                  max_bases_right, word_length, 
1096
 
                                  (Boolean) !variable_wordsize, &extended_right)) 
1097
 
      {
1098
 
         /* Check if this diagonal has already been explored and save
1099
 
            the hit if needed. */
1100
 
         Boolean hit_ready = FALSE;
1101
 
         /* Check if this diagonal has already been explored. */
1102
 
         if (word_params->container_type == eWordStacks) {
1103
 
            hit_ready = 
1104
 
               s_BlastnStacksExtendInitialHit(query, subject, min_step, template_length,
1105
 
                  word_params, matrix, ewp->stack_table, q_offset, 
1106
 
                  s_off + extended_right, s_offset, init_hitlist);
1107
 
         } else {
1108
 
            hit_ready = 
1109
 
               s_BlastnDiagExtendInitialHit(query, subject, min_step, template_length,
1110
 
                  word_params, matrix, ewp->diag_table, q_offset, 
1111
 
                  s_off + extended_right, s_offset, init_hitlist);
 
1111
   extra_bases = word_length - lut_word_length;
 
1112
 
 
1113
   if (extra_bases == 0) {
 
1114
      /* if the lookup table is the width of a full word,
 
1115
         no extensions are needed. Immediately check if the
 
1116
         diagonal has been explored */
 
1117
 
 
1118
      for (index = 0; index < num_hits; ++index) {
 
1119
         Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
 
1120
         Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
1121
         if (word_params->container_type == eWordStacks) {
 
1122
            hit_ready = s_BlastnStacksExtendInitialHit(query, subject, min_step,
 
1123
                                              template_length, word_params, 
 
1124
                                              matrix, ewp->stack_table, 
 
1125
                                              q_offset, 
 
1126
                                              s_offset + lut_word_length,
 
1127
                                              s_offset, init_hitlist);
 
1128
         } else {
 
1129
            hit_ready = s_BlastnDiagExtendInitialHit(query, subject, min_step, 
 
1130
                                              template_length, word_params, 
 
1131
                                              matrix, ewp->diag_table, 
 
1132
                                              q_offset, 
 
1133
                                              s_offset + lut_word_length,
 
1134
                                              s_offset, init_hitlist);
 
1135
         }
 
1136
         if (hit_ready)
 
1137
            ++hits_extended;
 
1138
      }
 
1139
   }
 
1140
   else {
 
1141
      /* The initial lookup table hit must be extended. We
 
1142
         trust that the bases of the hit itself are exact matches,
 
1143
         and look only for exact matches before and after the hit.
 
1144
       
 
1145
         Most of the time, the lookup table width is close to the
 
1146
         word size so only a few bases need examining. Also, most of
 
1147
         the time (for random sequences) extensions will fail 
 
1148
         almost immediately (the first base examined will not
 
1149
         match about 3/4 of the time). Thus it is critical to reduce
 
1150
         as much as possible all work that is not the actual 
 
1151
         examination of sequence data */
 
1152
 
 
1153
      for (index = 0; index < num_hits; ++index) {
 
1154
         Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
 
1155
         Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
1156
         
 
1157
         /* begin with the left extension; the initialization
 
1158
            is slightly faster. Point to the first base of the
 
1159
            lookup table hit and work backwards */
 
1160
 
 
1161
         max_bases_left = MIN(extra_bases, MIN(q_offset, s_offset));
 
1162
         q = q_start + q_offset;
 
1163
         s = s_start + s_offset / COMPRESSION_RATIO;
 
1164
         s_off = s_offset;
 
1165
 
 
1166
         for (extended_left = 0; extended_left < max_bases_left; 
 
1167
                                        extended_left++) {
 
1168
            s_off--; q--;
 
1169
            if (s_off % COMPRESSION_RATIO == 3)
 
1170
               s--;
 
1171
            if (((Uint1)(*s << (2*(s_off % COMPRESSION_RATIO))) >> 6) != *q)
 
1172
               break;
 
1173
         }
 
1174
 
 
1175
         /* do the right extension if the left extension did not
 
1176
            find all the bases required. Begin at the first base
 
1177
            beyond the lookup table hit and move forwards */
 
1178
 
 
1179
         s_off = s_offset + lut_word_length;
 
1180
 
 
1181
         if (extended_left < extra_bases) {
 
1182
            q_off = q_offset + lut_word_length;
 
1183
            q = q_start + q_off;
 
1184
            s = s_start + s_off / COMPRESSION_RATIO;
 
1185
            max_bases_right = MIN(extra_bases - extended_left,
 
1186
                                  MIN(query_length - q_off, 
 
1187
                                      subject_length - s_off));
 
1188
 
 
1189
            for (extended_right = 0; extended_right < max_bases_right; 
 
1190
                                        extended_right++) {
 
1191
               if (((Uint1)(*s << (2*(s_off % COMPRESSION_RATIO))) >> 6) != *q)
 
1192
                  break;
 
1193
               s_off++; q++;
 
1194
               if (s_off % COMPRESSION_RATIO == 0)
 
1195
                  s++;
 
1196
            }
 
1197
 
 
1198
            /* check if enough extra matches were found */
 
1199
 
 
1200
            if (extended_left + extended_right < extra_bases)
 
1201
               continue;
 
1202
         }
 
1203
 
 
1204
         /* check the diagonal on which the hit lies. The boundaries
 
1205
            extend from the first match of the hit to one beyond the
 
1206
            last match */
 
1207
 
 
1208
         if (word_params->container_type == eWordStacks) {
 
1209
            hit_ready = s_BlastnStacksExtendInitialHit(query, subject, min_step,
 
1210
                                              template_length, word_params, 
 
1211
                                              matrix, ewp->stack_table, 
 
1212
                                              q_offset - extended_left, 
 
1213
                                              s_off,
 
1214
                                              s_offset - extended_left, 
 
1215
                                              init_hitlist);
 
1216
         } else {
 
1217
            hit_ready = s_BlastnDiagExtendInitialHit(query, subject, min_step, 
 
1218
                                            template_length, word_params, 
 
1219
                                            matrix, ewp->diag_table, 
 
1220
                                            q_offset - extended_left, 
 
1221
                                            s_off,
 
1222
                                            s_offset - extended_left, 
 
1223
                                            init_hitlist);
1112
1224
         }
1113
1225
         if (hit_ready)
1114
1226
            ++hits_extended;
1137
1249
   Int4 subject_length = subject->length;
1138
1250
   Int4 hits_extended = 0;
1139
1251
 
 
1252
   ASSERT(mb_lt->discontiguous ||
 
1253
          word_params->extension_method == eRightAndLeft);
 
1254
 
1140
1255
   start_offset = 0;
1141
1256
   if (mb_lt->discontiguous) {
1142
1257
      last_start = subject_length - mb_lt->template_length;
1143
1258
      last_end = subject_length;
1144
1259
   } else {
1145
1260
      last_end = subject_length;
1146
 
      switch (word_params->extension_method) {
1147
 
      case eRightAndLeft: case eUpdateDiag:
1148
 
         /* Look for matches all the way to the end of the sequence. */
1149
 
         last_start = 
1150
 
            last_end - COMPRESSION_RATIO*mb_lt->compressed_wordsize;
1151
 
         break;
1152
 
      case eRight:
1153
 
         /* Need to leave word_length to the end of the sequence for extension
1154
 
            to the right. */
1155
 
         if (mb_lt->variable_wordsize)
1156
 
            last_end -= last_end%COMPRESSION_RATIO;
1157
 
         last_start = last_end - mb_lt->word_length;
1158
 
         last_end = last_start + mb_lt->compressed_wordsize*COMPRESSION_RATIO;
1159
 
         break;
1160
 
      default: 
1161
 
         abort();  /* All the relevant cases should be handled above, otherwise variables may not be properly set
1162
 
                      for the rest of the funciton. */ 
1163
 
         break;
1164
 
      }
 
1261
      last_start = last_end - mb_lt->lut_word_length;
1165
1262
   }
1166
1263
 
1167
1264
   /* start_offset points to the beginning of the word */
1168
1265
   while ( start_offset <= last_start ) {
 
1266
 
1169
1267
      /* Set the last argument's value to the end of the last word,
1170
1268
         without the extra bases for the discontiguous case */
1171
1269
      next_start = last_end;
1172
1270
      if (mb_lt->discontiguous) {
1173
1271
         hitsfound = MB_DiscWordScanSubject(lookup_wrap, subject, start_offset,
1174
1272
                        offset_pairs, max_hits, &next_start);
1175
 
      } else if (word_params->extension_method == eRightAndLeft) {
 
1273
      } else {
1176
1274
         hitsfound = MB_AG_ScanSubject(lookup_wrap, subject, start_offset, 
1177
1275
                        offset_pairs, max_hits, &next_start);
1178
 
      } else {
1179
 
         hitsfound = MB_ScanSubject(lookup_wrap, subject, start_offset, 
1180
 
                             offset_pairs, max_hits, &next_start);
1181
1276
      }
1182
1277
 
1183
1278
      switch (word_params->extension_method) {
1187
1282
                                      lookup_wrap, query, subject, 
1188
1283
                                      matrix, ewp, init_hitlist);
1189
1284
         break;
1190
 
      case eRight:
1191
 
         hits_extended += 
1192
 
            BlastNaExtendRight(offset_pairs, hitsfound, word_params, 
1193
 
                               lookup_wrap, query, subject, 
1194
 
                               matrix, ewp, init_hitlist);
1195
 
         break;
1196
1285
      case eUpdateDiag:
1197
1286
          hits_extended += 
1198
1287
              DiscMB_ExtendInitialHits(offset_pairs, hitsfound, query, subject, 
1237
1326
   Int4 hits_extended = 0;
1238
1327
 
1239
1328
   start_offset = 0;
1240
 
   end_offset = subject->length - COMPRESSION_RATIO*lookup->reduced_wordsize;
 
1329
   end_offset = subject->length - lookup->lut_word_length;
1241
1330
 
1242
1331
   /* start_offset points to the beginning of the word; end_offset is the
1243
1332
      beginning of the last word */