LCOV - code coverage report
Current view: top level - src - SmithWaterman.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2 240 0.8 %
Date: 2010-12-13 Functions: 2 23 8.7 %
Branches: 2 148 1.4 %

           Branch data     Line data    Source code
       1                 :            : // $Id: SmithWaterman.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <algorithm>
       8                 :            : #include <ctype.h>
       9                 :            : 
      10                 :            : #include "SmithWaterman.h"
      11                 :            : #include "Var.h"
      12                 :            : #include "util.h"
      13                 :            : 
      14                 :          0 : BroSubstring::BroSubstring(const BroSubstring& bst)
      15                 :          0 : : BroString((const BroString&) bst), _new(bst._new)
      16                 :            :         {
      17 [ #  # ][ #  # ]:          0 :         for ( BSSAlignVecCIt it = bst._aligns.begin(); it != bst._aligns.end(); ++it )
      18                 :          0 :                 _aligns.push_back(*it);
      19                 :          0 :         }
      20                 :            : 
      21                 :          0 : const BroSubstring& BroSubstring::operator=(const BroSubstring& bst)
      22                 :            :         {
      23                 :          0 :         BroString::operator=(bst);
      24                 :            : 
      25                 :          0 :         _aligns.clear();
      26                 :            : 
      27         [ #  # ]:          0 :         for ( BSSAlignVecCIt it = bst._aligns.begin(); it != bst._aligns.end(); ++it )
      28                 :          0 :                 _aligns.push_back(*it);
      29                 :            : 
      30                 :          0 :         _new = bst._new;
      31                 :            : 
      32                 :          0 :         return *this;
      33                 :            :         }
      34                 :            : 
      35                 :          0 : void BroSubstring::AddAlignment(const BroString* str, int index)
      36                 :            :         {
      37                 :          0 :         _aligns.push_back(BSSAlign(str, index));
      38                 :          0 :         }
      39                 :            : 
      40                 :          0 : bool BroSubstring::DoesCover(const BroSubstring* bst) const
      41                 :            :         {
      42         [ #  # ]:          0 :         if ( _aligns.size() != bst->_aligns.size() )
      43                 :          0 :                 return false;
      44                 :            : 
      45                 :          0 :         BSSAlignVecCIt it_bst = bst->_aligns.begin();
      46                 :            : 
      47         [ #  # ]:          0 :         for ( BSSAlignVecCIt it = _aligns.begin(); it != _aligns.end(); ++it, ++it_bst )
      48                 :            :                 {
      49                 :          0 :                 const BSSAlign& a = *it;
      50                 :          0 :                 const BSSAlign& a_bst = *it_bst;
      51                 :            : 
      52   [ #  #  #  # ]:          0 :                 if (a.index > a_bst.index || a.index + Len() < a_bst.index + bst->Len())
                 [ #  # ]
      53                 :          0 :                         return false;
      54                 :            :                 }
      55                 :            : 
      56                 :          0 :         return true;
      57                 :            :         }
      58                 :            : 
      59                 :          0 : VectorVal* BroSubstring::VecToPolicy(Vec* vec)
      60                 :            :         {
      61                 :            :         RecordType* sw_substring_type =
      62                 :          0 :                 internal_type("sw_substring")->AsRecordType();
      63         [ #  # ]:          0 :         if ( ! sw_substring_type )
      64                 :          0 :                 return 0;
      65                 :            : 
      66                 :            :         RecordType* sw_align_type =
      67                 :          0 :                 internal_type("sw_align")->AsRecordType();
      68         [ #  # ]:          0 :         if ( ! sw_align_type )
      69                 :          0 :                 return 0;
      70                 :            : 
      71                 :            :         VectorType* sw_align_vec_type =
      72                 :          0 :                 internal_type("sw_align_vec")->AsVectorType();
      73         [ #  # ]:          0 :         if ( ! sw_align_vec_type )
      74                 :          0 :                 return 0;
      75                 :            : 
      76                 :            :         VectorVal* result =
      77                 :          0 :                 new VectorVal(internal_type("sw_substring_vec")->AsVectorType());
      78         [ #  # ]:          0 :         if ( ! result )
      79                 :          0 :                 return 0;
      80                 :            : 
      81         [ #  # ]:          0 :         if ( vec )
      82                 :            :                 {
      83         [ #  # ]:          0 :                 for ( unsigned int i = 0; i < vec->size(); ++i )
      84                 :            :                         {
      85                 :          0 :                         BroSubstring* bst = (*vec)[i];
      86                 :            : 
      87                 :          0 :                         RecordVal* st_val = new RecordVal(sw_substring_type);
      88                 :          0 :                         st_val->Assign(0, new StringVal(new BroString(*bst)));
      89                 :            : 
      90                 :          0 :                         VectorVal* aligns = new VectorVal(sw_align_vec_type);
      91                 :            : 
      92         [ #  # ]:          0 :                         for ( unsigned int j = 0; j < bst->GetNumAlignments(); ++j )
      93                 :            :                                 {
      94                 :          0 :                                 const BSSAlign& align = (bst->GetAlignments())[j];
      95                 :            : 
      96                 :          0 :                                 RecordVal* align_val = new RecordVal(sw_align_type);
      97                 :          0 :                                 align_val->Assign(0, new StringVal(new BroString(*align.string)));
      98                 :          0 :                                 align_val->Assign(1, new Val(align.index, TYPE_COUNT));
      99                 :            : 
     100                 :          0 :                                 aligns->Assign(j+1, align_val, 0);
     101                 :            :                                 }
     102                 :            : 
     103                 :          0 :                         st_val->Assign(1, aligns);
     104                 :          0 :                         st_val->Assign(2, new Val(bst->IsNewAlignment(), TYPE_BOOL));
     105                 :          0 :                         result->Assign(i+1, st_val, 0);
     106                 :            :                         }
     107                 :            :                 }
     108                 :            : 
     109                 :          0 :         return result;
     110                 :            :         }
     111                 :            : 
     112                 :          0 : BroSubstring::Vec* BroSubstring::VecFromPolicy(VectorVal* vec)
     113                 :            :         {
     114                 :          0 :         Vec* result = new Vec();
     115                 :            : 
     116                 :            :         // VectorVals start at index 1!
     117         [ #  # ]:          0 :         for ( unsigned int i = 1; i <= vec->Size(); ++i )
     118                 :            :                 {
     119                 :          0 :                 Val* v = vec->Lookup(i);     // get the RecordVal
     120         [ #  # ]:          0 :                 if ( ! v )
     121                 :          0 :                         continue;
     122                 :            : 
     123                 :          0 :                 const BroString* str = v->AsRecordVal()->Lookup(0)->AsString();
     124                 :          0 :                 BroSubstring* substr = new BroSubstring(*str);
     125                 :            : 
     126                 :          0 :                 const VectorVal* aligns = v->AsRecordVal()->Lookup(1)->AsVectorVal();
     127         [ #  # ]:          0 :                 for ( unsigned int j = 1; j <= aligns->Size(); ++j )
     128                 :            :                         {
     129                 :          0 :                         const RecordVal* align = aligns->AsVectorVal()->Lookup(j)->AsRecordVal();
     130                 :          0 :                         const BroString* str = align->Lookup(0)->AsString();
     131                 :          0 :                         int index = align->Lookup(1)->AsCount();
     132                 :          0 :                         substr->AddAlignment(str, index);
     133                 :            :                         }
     134                 :            : 
     135                 :          0 :                 bool new_alignment = v->AsRecordVal()->Lookup(2)->AsBool();
     136                 :          0 :                 substr->MarkNewAlignment(new_alignment);
     137                 :            : 
     138                 :          0 :                 result->push_back(substr);
     139                 :            :                 }
     140                 :            : 
     141                 :          0 :         return result;
     142                 :            :         }
     143                 :            : 
     144                 :          0 : char* BroSubstring::VecToString(Vec* vec)
     145                 :            :         {
     146                 :          0 :         string result("[");
     147                 :            : 
     148         [ #  # ]:          0 :         for ( BroSubstring::VecIt it = vec->begin(); it != vec->end(); ++it )
     149                 :            :                 {
     150                 :          0 :                 result += (*it)->CheckString();
     151                 :          0 :                 result += ",";
     152                 :            :                 }
     153                 :            : 
     154                 :          0 :         result += "]";
     155                 :          0 :         return strdup(result.c_str());
     156                 :            :         }
     157                 :            : 
     158                 :          0 : BroString::IdxVec* BroSubstring::GetOffsetsVec(const Vec* vec, unsigned int index)
     159                 :            :         {
     160                 :          0 :         BroString::IdxVec* result = new BroString::IdxVec();
     161                 :            : 
     162         [ #  # ]:          0 :         for ( VecCIt it = vec->begin(); it != vec->end(); ++it )
     163                 :            :                 {
     164                 :            :                 int start, end;
     165                 :          0 :                 const BroSubstring* bst = (*it);
     166                 :            : 
     167         [ #  # ]:          0 :                 if ( bst->_aligns.size() <= index )
     168                 :          0 :                         continue;
     169                 :            : 
     170                 :          0 :                 const BSSAlign& align = bst->_aligns[index];
     171                 :          0 :                 start = align.index;
     172                 :          0 :                 end = start + bst->Len();
     173                 :            : 
     174                 :          0 :                 result->push_back(start);
     175                 :          0 :                 result->push_back(end);
     176                 :            :                 }
     177                 :            : 
     178                 :          0 :         return result;
     179                 :            :         }
     180                 :            : 
     181                 :            : 
     182                 :            : bool BroSubstringCmp::operator()(const BroSubstring* bst1,
     183                 :          0 :                                  const BroSubstring* bst2) const
     184                 :            :         {
     185 [ #  # ][ #  # ]:          0 :         if ( _index >= bst1->GetNumAlignments() ||
                 [ #  # ]
     186                 :            :              _index >= bst2->GetNumAlignments() )
     187                 :            :                 {
     188                 :          0 :                 warn("BroSubstringCmp::operator(): invalid index for input strings.\n");
     189                 :          0 :                 return false;
     190                 :            :                 }
     191                 :            : 
     192         [ #  # ]:          0 :         if ( bst1->GetAlignments()[_index].index <=
     193                 :            :              bst2->GetAlignments()[_index].index )
     194                 :          0 :                 return true;
     195                 :            : 
     196                 :          0 :         return false;
     197                 :            :         }
     198                 :            : 
     199                 :            : // A node in Smith-Waterman's dynamic programming matrix.  Each node
     200                 :            : // contains the byte it represents in the case of a match, the score
     201                 :            : // at this point, and a pointer to the previous cell. Previous means
     202                 :            : // one up and left in case of a match, or a jump somewhere above and
     203                 :            : // left in case of a gap.
     204                 :            : //
     205                 :            : struct SWNode {
     206                 :            :         // ID field for the cell, for debugging purposes.
     207                 :            :         int id;
     208                 :            : 
     209                 :            :         u_char swn_byte;
     210                 :            :         bool swn_byte_assigned;
     211                 :            :         bool swn_visited;
     212                 :            : 
     213                 :            :         // The score in this cell. The cell with the globally best score
     214                 :            :         // marks the end of the alignment.
     215                 :            :         int swn_score;
     216                 :            : 
     217                 :            :         // Pointer to previous match, walking back yields subsequence.
     218                 :            :         SWNode* swn_prev;
     219                 :            : };
     220                 :            : 
     221                 :            : // A matrix of Smith-Waterman nodes.
     222                 :            : //
     223                 :            : class SWNodeMatrix {
     224                 :            : public:
     225                 :          0 :         SWNodeMatrix(const BroString* s1, const BroString* s2)
     226                 :          0 :         : _s1(s1), _s2(s2), _rows(s1->Len() + 1), _cols(s2->Len() + 1)
     227                 :            :                 {
     228                 :          0 :                 _nodes = new SWNode[_cols * _rows];
     229                 :          0 :                 memset(_nodes, 0, sizeof(SWNode) * _cols * _rows);
     230                 :          0 :                 }
     231                 :            : 
     232         [ #  # ]:          0 :         ~SWNodeMatrix() { delete [] _nodes; }
     233                 :            : 
     234                 :          0 :         SWNode* operator()(int row, int col)
     235                 :            :                 {
     236                 :            :                 // Make sure access is in allowed range.
     237 [ #  # ][ #  # ]:          0 :                 if ( row < 0 || row >= _rows )
     238                 :          0 :                         return 0;
     239 [ #  # ][ #  # ]:          0 :                 if ( col < 0 || col >= _cols )
     240                 :          0 :                         return 0;
     241                 :            : 
     242                 :          0 :                 return &(_nodes[row * _cols + col]);
     243                 :            :                 }
     244                 :            : 
     245                 :          0 :         const BroString* GetRowsString() const  { return _s1; }
     246                 :          0 :         const BroString* GetColsString() const  { return _s2; }
     247                 :            : 
     248                 :          0 :         int GetHeight() const   { return _rows; }
     249                 :          0 :         int GetWidth() const    { return _cols; }
     250                 :            : 
     251                 :            :         // Quick helper function that calculates the coordinates of a
     252                 :            :         // node in the matrix via pointer arithmetic.
     253                 :            :         //
     254                 :          0 :         void GetNodeIndices(SWNode* node, int& row, int& col)
     255                 :            :                 {
     256                 :          0 :                 SWNode* base = &_nodes[0];
     257                 :          0 :                 int offset = (node - base);
     258                 :          0 :                 col = (offset % _cols);
     259                 :          0 :                 row = (offset / _cols);
     260                 :          0 :                 }
     261                 :            : 
     262                 :            : private:
     263                 :            :         const BroString* _s1;
     264                 :            :         const BroString* _s2;
     265                 :            : 
     266                 :            :         int _rows, _cols;
     267                 :            :         SWNode* _nodes;
     268                 :            : };
     269                 :            : 
     270                 :            : // Returns the common subsequence starting from a given node.
     271                 :            : // @result: vector holding results on return.
     272                 :            : // @matrix: SW matrix.
     273                 :            : // @node: starting node.
     274                 :            : // @params: SW parameters.
     275                 :            : //
     276                 :            : static void sw_collect_single(BroSubstring::Vec* result, SWNodeMatrix& matrix,
     277                 :          0 :                               SWNode* node, SWParams& params)
     278                 :            :         {
     279                 :          0 :         string substring("");
     280                 :          0 :         int row = 0, col = 0;
     281                 :            : 
     282         [ #  # ]:          0 :         while ( node )
     283                 :            :                 {
     284                 :            : //              printf("NODE: %i\n", node->id);
     285                 :          0 :                 node->swn_visited = true;
     286                 :            : 
     287                 :            :                 // Once we hit a gap, terminate the string and prepend
     288                 :            :                 // it to our result vector, IF it has at least the length
     289                 :            :                 // requested through the params._min_toklen parameter.
     290                 :            :                 //
     291         [ #  # ]:          0 :                 if ( node->swn_byte_assigned )
     292                 :            :                         {
     293                 :          0 :                         matrix.GetNodeIndices(node, row, col);
     294                 :          0 :                         substring += node->swn_byte;
     295                 :            : //                      printf("SUBSTRING: %s\n", substring.c_str());
     296                 :            :                         }
     297                 :            :                 else
     298                 :            :                         {
     299                 :            : //                      printf("GAP\n");
     300         [ #  # ]:          0 :                         if ( substring.size() >= params._min_toklen )
     301                 :            :                                 {
     302                 :          0 :                                 reverse(substring.begin(), substring.end());
     303                 :          0 :                                 BroSubstring* bst = new BroSubstring(substring);
     304                 :          0 :                                 bst->AddAlignment(matrix.GetRowsString(), row-1);
     305                 :          0 :                                 bst->AddAlignment(matrix.GetColsString(), col-1);
     306                 :          0 :                                 result->push_back(bst);
     307                 :            :                                 }
     308                 :            : 
     309                 :          0 :                         substring = "";
     310                 :            :                         }
     311                 :            : 
     312                 :          0 :                 node = node->swn_prev;
     313                 :            :                 }
     314                 :            : 
     315                 :            :         // Anything left over now is the first string of an alignment and is
     316                 :            :         // manually added and marked as the beginning of a new alignment.
     317                 :            :         //
     318         [ #  # ]:          0 :         if ( substring.size() > 0 )
     319                 :            :                 {
     320                 :          0 :                 reverse(substring.begin(), substring.end());
     321                 :          0 :                 BroSubstring* bst = new BroSubstring(substring);
     322                 :          0 :                 bst->AddAlignment(matrix.GetRowsString(), row-1);
     323                 :          0 :                 bst->AddAlignment(matrix.GetColsString(), col-1);
     324                 :          0 :                 result->push_back(bst);
     325                 :            :                 }
     326                 :            : 
     327         [ #  # ]:          0 :         if ( result->size() > 0 )
     328                 :          0 :                 result->back()->MarkNewAlignment(true);
     329                 :          0 :         }
     330                 :            : 
     331                 :            : // Returns repeated common-subsequence alignments.
     332                 :            : // @result: vector holding results on return.
     333                 :            : // @matrix: SW matrix.
     334                 :            : // @params: SW parameters.
     335                 :            : //
     336                 :            : // The approach taken is to essentially follow back from all starting points of
     337                 :            : // common subsequences while tracking which nodes were visited earlier and which
     338                 :            : // substrings are redundant (i.e., fully covered by a larger common substring).
     339                 :            : //
     340                 :            : static void sw_collect_multiple(BroSubstring::Vec* result,
     341                 :          0 :                                 SWNodeMatrix& matrix, SWParams& params)
     342                 :            :         {
     343                 :          0 :         vector<BroSubstring::Vec*> als;
     344                 :            : 
     345         [ #  # ]:          0 :         for ( int i = matrix.GetHeight() - 1; i > 0; --i )
     346                 :            :                 {
     347         [ #  # ]:          0 :                 for ( int j = matrix.GetWidth() - 1; j > 0; --j )
     348                 :            :                         {
     349                 :          0 :                         SWNode* node = matrix(i, j);
     350                 :            : 
     351   [ #  #  #  # ]:          0 :                         if ( ! (node->swn_byte_assigned && ! node->swn_visited) )
     352                 :          0 :                                 continue;
     353                 :            : 
     354                 :          0 :                         BroSubstring::Vec* new_al = new BroSubstring::Vec();
     355                 :          0 :                         sw_collect_single(new_al, matrix, node, params);
     356                 :            : 
     357         [ #  # ]:          0 :                         for ( vector<BroSubstring::Vec*>::iterator it = als.begin();
     358                 :            :                               it != als.end(); ++it )
     359                 :            :                                 {
     360                 :          0 :                                 BroSubstring::Vec* old_al = *it;
     361                 :            : 
     362         [ #  # ]:          0 :                                 if ( old_al == 0 )
     363                 :          0 :                                         continue;
     364                 :            : 
     365         [ #  # ]:          0 :                                 for ( BroSubstring::VecIt it2 = old_al->begin();
     366                 :            :                                       it2 != old_al->end(); ++it2 )
     367                 :            :                                         {
     368         [ #  # ]:          0 :                                         for ( BroSubstring::VecIt it3 = new_al->begin();
     369                 :            :                                               it3 != new_al->end(); ++it3 )
     370                 :            :                                                 {
     371         [ #  # ]:          0 :                                                 if ( (*it2)->DoesCover(*it3) )
     372                 :            :                                                         {
     373                 :          0 :                                                         delete_each(new_al);
     374         [ #  # ]:          0 :                                                         delete new_al;
     375                 :          0 :                                                         new_al = 0;
     376                 :          0 :                                                         goto end_loop;
     377                 :            :                                                         }
     378                 :            : 
     379         [ #  # ]:          0 :                                                 if ( (*it3)->DoesCover(*it2) )
     380                 :            :                                                         {
     381                 :          0 :                                                         delete_each(old_al);
     382         [ #  # ]:          0 :                                                         delete old_al;
     383                 :          0 :                                                         *it = 0;
     384                 :          0 :                                                         goto end_loop;
     385                 :            :                                                         }
     386                 :            :                                                 }
     387                 :            :                                         }
     388                 :            :                                 }
     389                 :            : 
     390                 :          0 : end_loop:
     391         [ #  # ]:          0 :                         if ( new_al )
     392                 :          0 :                                 als.push_back(new_al);
     393                 :            :                         }
     394                 :            :                 }
     395                 :            : 
     396         [ #  # ]:          0 :         for ( vector<BroSubstring::Vec*>::iterator it = als.begin();
     397                 :            :               it != als.end(); ++it )
     398                 :            :                 {
     399                 :          0 :                 BroSubstring::Vec* al = *it;
     400                 :            : 
     401         [ #  # ]:          0 :                 if ( al == 0 )
     402                 :          0 :                         continue;
     403                 :            : 
     404         [ #  # ]:          0 :                 for ( BroSubstring::VecIt it2 = al->begin();
     405                 :            :                       it2 != al->end(); ++it2 )
     406                 :          0 :                         result->push_back(*it2);
     407                 :            : 
     408         [ #  # ]:          0 :                 delete al;
     409                 :          0 :                 }
     410                 :          0 :         }
     411                 :            : 
     412                 :            : // The main Smith-Waterman algorithm.
     413                 :            : //
     414                 :            : BroSubstring::Vec* smith_waterman(const BroString* s1, const BroString* s2,
     415                 :          0 :                                         SWParams& params)
     416                 :            :         {
     417                 :          0 :         BroSubstring::Vec* result = new BroSubstring::Vec();
     418                 :            : 
     419   [ #  #  #  # ]:          0 :         if ( ! s1 || s1->Len() < int(params._min_toklen) ||
         [ #  # ][ #  # ]
                 [ #  # ]
     420                 :            :              ! s2 || s2->Len() < int(params._min_toklen) )
     421                 :          0 :                 return result;
     422                 :            : 
     423                 :            :         // Length of both strings, plus one because SW needs
     424                 :            :         // an extra row and column.
     425                 :            :         //
     426                 :          0 :         int i, len1 = s1->Len() + 1;
     427                 :          0 :         int j, len2 = s2->Len() + 1;
     428                 :            : 
     429                 :          0 :         int row = 0, col = 0;
     430                 :            : 
     431                 :          0 :         byte_vec string1 = s1->Bytes();
     432                 :          0 :         byte_vec string2 = s2->Bytes();
     433                 :            : 
     434                 :          0 :         SWNodeMatrix matrix(s1, s2);    // dynamic programming matrix.
     435                 :          0 :         SWNode* node_max = 0;   // pointer to the best score's node
     436                 :          0 :         SWNode* node_br_max = 0;        // pointer to lowest-right matching node
     437                 :            : 
     438                 :            :         // The highest score in the matrix, globally.  We initialize to 1
     439                 :            :         // because we are only interested in real scores (initializing to
     440                 :            :         // -infty would mean 0 is larger, and would complicate the link
     441                 :            :         // structure in the matrix).
     442                 :            :         //
     443                 :          0 :         int matrix_max = 1;
     444                 :          0 :         int br_max_r = 0;
     445                 :          0 :         int br_max_b = 0;
     446                 :            : 
     447                 :            : 
     448                 :            :         // Matrix initialization ----------------------------------------------
     449                 :            : 
     450                 :            :         // Assign IDs to each cell -- this is only for debugging purposes
     451                 :            :         // and can go later.
     452                 :            : 
     453                 :          0 :         int counter = 1;
     454                 :            : 
     455         [ #  # ]:          0 :         for ( i = 1; i < len1; ++i )
     456         [ #  # ]:          0 :                 for ( j = 1; j < len2; ++j )
     457                 :          0 :                         matrix(i, j)->id = counter++;
     458                 :            : 
     459                 :            :         // Subsequence calculation --------------------------------------------
     460                 :            : 
     461         [ #  # ]:          0 :         for ( i = 1; i < len1; ++i )
     462                 :            :                 {
     463         [ #  # ]:          0 :                 for ( j = 1; j < len2; ++j )
     464                 :            :                         {
     465                 :            :                         // Current node, top/left neighbours.
     466                 :            :                         //
     467                 :          0 :                         SWNode* current = matrix(i, j);
     468                 :          0 :                         SWNode* node_tl = matrix(i-1, j-1);
     469                 :          0 :                         SWNode* node_l  = matrix(i, j-1);
     470                 :          0 :                         SWNode* node_t  = matrix(i-1, j);
     471                 :            : 
     472                 :            :                         // Scores of neighbouring nodes.
     473                 :            :                         //
     474                 :          0 :                         int score_t = node_t->swn_score;
     475                 :          0 :                         int score_l = node_l->swn_score;
     476                 :          0 :                         int score_tl = node_tl->swn_score;
     477                 :            : 
     478                 :            :                         // If strings at current indices match, assign new
     479                 :            :                         // score to current node.  Minus-one adjustments
     480                 :            :                         // are necessary since matrix has one extra
     481                 :            :                         // row + column.
     482                 :            :                         //
     483         [ #  # ]:          0 :                         if ( string1[i-1] == string2[j-1] )
     484                 :            :                                 {
     485                 :            :                                 // We have a match: improve previous score.
     486                 :            :                                 //
     487                 :          0 :                                 score_tl += 1;
     488                 :            : 
     489                 :            :                                 // If we're continuing a chain of matches, rate
     490                 :            :                                 // higher.  This favours longer consecutive
     491                 :            :                                 // substrings.
     492                 :            :                                 //
     493         [ #  # ]:          0 :                                 if ( node_tl->swn_byte_assigned )
     494                 :          0 :                                         score_tl += 99;
     495                 :            : 
     496                 :            :                                 // Store the byte we've matched in the node for
     497                 :            :                                 // easier access.
     498                 :            :                                 //
     499                 :          0 :                                 current->swn_byte = string1[i-1];
     500                 :          0 :                                 current->swn_byte_assigned = true;
     501                 :            :                                 }
     502                 :            : 
     503                 :            :                         // Pick the score among the neighbours that is now highest.
     504                 :            :                         // This is the core of Smith-Waterman.
     505                 :            :                         //
     506         [ #  # ]:          0 :                         if ( current->swn_byte_assigned )
     507                 :          0 :                                 current->swn_score = score_tl;
     508                 :            :                         else
     509                 :          0 :                                 current->swn_score = max(max(score_t, score_l), score_tl);
     510                 :            : 
     511                 :            :                         // Establish predecessor chain according to neighbor
     512                 :            :                         // with best score.
     513                 :            :                         //
     514 [ #  # ][ #  # ]:          0 :                         if ( current->swn_score == score_tl &&
     515                 :            :                              current->swn_byte_assigned )
     516                 :            :                                 {
     517                 :            :                                 // If we had matched bytes (*and* it's the
     518                 :            :                                 // best neighbor), marke the node accordingly
     519                 :            :                                 //
     520 [ #  # ][ #  # ]:          0 :                                 if ( i >= br_max_b && j >= br_max_r )
     521                 :            :                                         {
     522                 :          0 :                                         node_br_max = current;
     523                 :          0 :                                         br_max_b = i;
     524                 :          0 :                                         br_max_r = j;
     525                 :            :                                         }
     526                 :            : 
     527                 :          0 :                                 current->swn_prev = node_tl;
     528                 :            :                                 }
     529         [ #  # ]:          0 :                         else if ( current->swn_score == score_t )
     530                 :          0 :                                 current->swn_prev = node_t;
     531                 :            :                         else
     532                 :          0 :                                 current->swn_prev = node_l;
     533                 :            : 
     534                 :            :                         // Check if we have a new global maximum -- we
     535                 :            :                         // specifically track the node that is the global
     536                 :            :                         // maximum so we now from where to backtrack at
     537                 :            :                         // the end of the matrix iteration.
     538                 :            :                         //
     539         [ #  # ]:          0 :                         if ( current->swn_score > matrix_max )
     540                 :            :                                 {
     541                 :          0 :                                 node_max = current;
     542                 :          0 :                                 matrix_max = current->swn_score;
     543                 :            :                                 }
     544                 :            : 
     545                 :            : #if 0
     546                 :            :                         printf("%4i/%.5i%c/%.5i[%c%c] ",
     547                 :            :                                 current->swn_score,
     548                 :            :                                 current->id,
     549                 :            :                                 current->swn_byte_assigned ? '*' : ' ',
     550                 :            :                                 current->swn_prev ? current->swn_prev->id : 0,
     551                 :            :                                string1[i-1], string2[j-1]);
     552                 :            : #endif
     553                 :            :                         //printf("%.5i ", current->swn_score); 
     554                 :            :                         }
     555                 :            : 
     556                 :            : #if 0
     557                 :            :                 printf("\n");
     558                 :            : #endif
     559                 :            :                 }
     560                 :            : 
     561                 :            :         // Result generation.
     562                 :            : 
     563                 :            :         // How we do this depends on the mode we operate in.  In SW_SINGLE, we
     564                 :            :         // follow the path from the best node until there is no predecessor
     565                 :            :         // (that is, when we hit a node in row 0), and stop.  In SW_MULTIPLE,
     566                 :            :         // we collect all non-redundant common subsequences.
     567                 :            : 
     568         [ #  # ]:          0 :         if ( params._sw_variant == SW_MULTIPLE )
     569                 :          0 :                 sw_collect_multiple(result, matrix, params);
     570                 :            :         else
     571                 :          0 :                 sw_collect_single(result, matrix, node_max, params);
     572                 :            : 
     573         [ #  # ]:          0 :         if ( len1 > len2 )
     574                 :          0 :                 sort(result->begin(), result->end(), BroSubstringCmp(0));
     575                 :            :         else
     576                 :          0 :                 sort(result->begin(), result->end(), BroSubstringCmp(1));
     577                 :            : 
     578                 :          0 :         return result;
     579 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8