greedy_align.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:25k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: greedy_align.c,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:08:02  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.19
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: greedy_align.c,v 1000.2 2004/06/01 18:08:02 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Webb Miller and Co. Adopted for NCBI libraries by Sergey Shavirin
  35.  *
  36.  * Initial Creation Date: 10/27/1999
  37.  *
  38.  */
  39. /** @file greedy_align.c
  40.  * Greedy gapped alignment functions
  41.  */
  42. static char const rcsid[] = 
  43.     "$Id: greedy_align.c,v 1000.2 2004/06/01 18:08:02 gouriano Exp $";
  44. #include <algo/blast/core/greedy_align.h>
  45. #include <algo/blast/core/blast_util.h> /* for NCBI2NA_UNPACK_BASE macros */
  46. enum {
  47.     EDIT_OP_MASK = 0x3,
  48.     EDIT_OP_ERR  = 0x0,
  49.     EDIT_OP_INS  = 0x1,
  50.     EDIT_OP_DEL  = 0x2,
  51.     EDIT_OP_REP  = 0x3
  52. };
  53. enum {         /* half of the (fixed) match score */
  54.     ERROR_FRACTION=2,  /* 1/this */
  55.     MAX_SPACE=1000000,
  56.     sC = 0, sI = 1, sD = 2, LARGE=100000000
  57. };
  58. /* -------- From original file edit.c ------------- */
  59. static Uint4 edit_val_get(edit_op_t op)
  60. {
  61.     return op >> 2;
  62. }
  63. static Uint4 edit_opc_get(edit_op_t op)
  64. {
  65.     return op & EDIT_OP_MASK;
  66. }
  67. static edit_op_t edit_op_cons(Uint4 op, Uint4 val)
  68. {
  69.     return (val << 2) | (op & EDIT_OP_MASK);
  70. }
  71. static edit_op_t edit_op_inc(edit_op_t op, Uint4 n)
  72. {
  73.     return edit_op_cons(edit_opc_get(op), edit_val_get(op) + n);
  74. }
  75. static edit_op_t edit_op_inc_last(MBGapEditScript *es, Uint4 n)
  76. {
  77.     edit_op_t *last;
  78.     ASSERT (es->num > 0);
  79.     last = &(es->op[es->num-1]);
  80.     *last = edit_op_inc(*last, n);
  81.     return *last;
  82. }
  83. static Int4 edit_script_ready(MBGapEditScript *es, Uint4 n)
  84. {
  85.     edit_op_t *p;
  86.     Uint4 m = n + n/2;
  87.     
  88.     if (es->size <= n) {
  89.         p = realloc(es->op, m*sizeof(edit_op_t));
  90.         if (p == 0) {
  91.             return 0;
  92.         } else {
  93.             es->op = p;
  94.             es->size = m;
  95.         }
  96.     }
  97.     return 1;
  98. }
  99. static Int4 edit_script_readyplus(MBGapEditScript *es, Uint4 n)
  100. {
  101.     if (es->size - es->num <= n)
  102.         return edit_script_ready(es, n + es->num);
  103.     return 1;
  104. }
  105. static Int4 edit_script_put(MBGapEditScript *es, Uint4 op, Uint4 n)
  106. {
  107.     if (!edit_script_readyplus(es, 2))
  108.         return 0;
  109.     es->last = op;
  110.     ASSERT(op != 0);
  111.     es->op[es->num] = edit_op_cons(op, n);
  112.     es->num += 1;
  113.     es->op[es->num] = 0; /* sentinal */
  114.     return 1;
  115. }
  116. static MBGapEditScript *edit_script_init(MBGapEditScript *es)
  117. {
  118. es->op = 0;
  119. es->size = es->num = 0;
  120. es->last = 0;
  121. edit_script_ready(es, 8);
  122. return es;
  123. }
  124. static edit_op_t *edit_script_first(MBGapEditScript *es)
  125. {
  126.     return es->num > 0 ? &es->op[0] : 0;
  127. }
  128. static edit_op_t *edit_script_next(MBGapEditScript *es, edit_op_t *op)
  129. {
  130.     /* XXX - assumes flat address space */
  131.     if (&es->op[0] <= op && op < &es->op[es->num-1])
  132.         return op+1;
  133.     else
  134.         return 0;
  135. }
  136. static Int4 edit_script_more(MBGapEditScript *data, Uint4 op, Uint4 k)
  137. {
  138.     if (op == EDIT_OP_ERR) {
  139. #ifdef ERR_POST_EX_DEFINED
  140.         ErrPostEx(SEV_FATAL, 1, 0, 
  141.                   "edit_script_more: bad opcode %d:%d", op, k);
  142. #endif
  143.         return -1;
  144.     }
  145.     
  146.     if (edit_opc_get(data->last) == op)
  147.         edit_op_inc_last(data, k);
  148.     else
  149.         edit_script_put(data, op, k);
  150.     return 0;
  151. }
  152. MBGapEditScript *MBGapEditScriptAppend(MBGapEditScript *es, MBGapEditScript *et)
  153. {
  154.     edit_op_t *op;
  155.     
  156.     for (op = edit_script_first(et); op; op = edit_script_next(et, op))
  157.         edit_script_more(es, edit_opc_get(*op), edit_val_get(*op));
  158.     return es;
  159. }
  160. MBGapEditScript *MBGapEditScriptNew(void)
  161. {
  162.     MBGapEditScript *es = calloc(1, sizeof(*es));
  163.     if (!es)
  164.         return 0;
  165.     return edit_script_init(es);
  166. }
  167. MBGapEditScript *MBGapEditScriptFree(MBGapEditScript *es)
  168. {
  169.     if (es) {
  170.         if (es->op)
  171.             sfree(es->op);
  172.         memset(es, 0, sizeof(*es));
  173.         sfree(es);
  174.     }
  175.     return 0;
  176. }
  177. static Int4 edit_script_del(MBGapEditScript *data, Uint4 k)
  178. {
  179.     return edit_script_more(data, EDIT_OP_DEL, k);
  180. }
  181. static Int4 edit_script_ins(MBGapEditScript *data, Uint4 k)
  182. {
  183.     return edit_script_more(data, EDIT_OP_INS, k);
  184. }
  185. static Int4 edit_script_rep(MBGapEditScript *data, Uint4 k)
  186. {
  187.     return edit_script_more(data, EDIT_OP_REP, k);
  188. }
  189. static MBGapEditScript *edit_script_reverse_inplace(MBGapEditScript *es)
  190. {
  191.     Uint4 i;
  192.     const Uint4 num = es->num;
  193.     const Uint4 mid = num/2;
  194.     const Uint4 end = num-1;
  195.     
  196.     for (i = 0; i < mid; ++i) {
  197.         const edit_op_t t = es->op[i];
  198.         es->op[i] = es->op[end-i];
  199.         es->op[end-i] = t;
  200.     }
  201.     return es;
  202. }
  203. SMBSpace* MBSpaceNew()
  204. {
  205.     SMBSpace* p;
  206.     Int4 amount;
  207.     
  208.     p = (SMBSpace*) malloc(sizeof(SMBSpace));
  209.     amount = MAX_SPACE;
  210.     p->space_array = (SThreeVal*) malloc(sizeof(SThreeVal)*amount);
  211.     if (p->space_array == NULL) {
  212.        sfree(p);
  213.        return NULL;
  214.     }
  215.     p->used = 0; 
  216.     p->size = amount;
  217.     p->next = NULL;
  218.     return p;
  219. }
  220. static void refresh_mb_space(SMBSpace* sp)
  221. {
  222.    while (sp) {
  223.       sp->used = 0;
  224.       sp = sp->next;
  225.    }
  226. }
  227. void MBSpaceFree(SMBSpace* sp)
  228. {
  229.    SMBSpace* next_sp;
  230.    while (sp) {
  231.       next_sp = sp->next;
  232.       sfree(sp->space_array);
  233.       sfree(sp);
  234.       sp = next_sp;
  235.    }
  236. }
  237. static SThreeVal* get_mb_space(SMBSpace* S, Int4 amount)
  238. {
  239.     SThreeVal* s;
  240.     if (amount < 0) 
  241.         return NULL;  
  242.     
  243.     while (S->used+amount > S->size) {
  244.        if (S->next == NULL)
  245.           if ((S->next = MBSpaceNew()) == NULL) {
  246. #ifdef ERR_POST_EX_DEFINED
  247.      ErrPostEx(SEV_WARNING, 0, 0, "Cannot get new space for greedy extension");
  248. #endif
  249.      return NULL;
  250.           }
  251.        S = S->next;
  252.     }
  253.     s = S->space_array+S->used;
  254.     S->used += amount;
  255.     
  256.     return s;
  257. }
  258. /* ----- */
  259. static Int4 gcd(Int4 a, Int4 b)
  260. {
  261.     Int4 c;
  262.     if (a < b) {
  263.         c = a;
  264.         a = b; b = c;
  265.     }
  266.     while ((c = a % b) != 0) {
  267.         a = b; b = c;
  268.     }
  269.     return b;
  270. }
  271. static Int4 gdb3(Int4* a, Int4* b, Int4* c)
  272. {
  273.     Int4 g;
  274.     if (*b == 0) g = gcd(*a, *c);
  275.     else g = gcd(*a, gcd(*b, *c));
  276.     if (g > 1) {
  277.         *a /= g;
  278.         *b /= g;
  279.         *c /= g;
  280.     }
  281.     return g;
  282. }
  283. static Int4 get_lastC(SThreeVal** flast_d, Int4* lower, Int4* upper, 
  284.                       Int4* d, Int4 diag, Int4 Mis_cost, Int4* row1)
  285. {
  286.     Int4 row;
  287.     
  288.     if (diag >= lower[(*d)-Mis_cost] && diag <= upper[(*d)-Mis_cost]) {
  289.         row = flast_d[(*d)-Mis_cost][diag].C;
  290.         if (row >= MAX(flast_d[*d][diag].I, flast_d[*d][diag].D)) {
  291.             *d = *d-Mis_cost;
  292.             *row1 = row;
  293.             return sC;
  294.         }
  295.     }
  296.     if (flast_d[*d][diag].I > flast_d[*d][diag].D) {
  297.         *row1 = flast_d[*d][diag].I;
  298.         return sI;
  299.     } else {
  300.         *row1 = flast_d[*d][diag].D;
  301.         return sD;
  302.     }
  303. }
  304. static Int4 get_last_ID(SThreeVal** flast_d, Int4* lower, Int4* upper, 
  305.                         Int4* d, Int4 diag, Int4 GO_cost, 
  306.                         Int4 GE_cost, Int4 IorD)
  307. {
  308.     Int4 ndiag; 
  309.     Int4 row;
  310.     if (IorD == sI) { ndiag = diag -1;} else ndiag = diag+1;
  311.     if (ndiag >= lower[(*d)-GE_cost] && ndiag <=upper[(*d)-GE_cost]) 
  312.         row = (IorD == sI)? flast_d[(*d)-GE_cost][ndiag].I: flast_d[(*d)-GE_cost][ndiag].D;
  313.     else row = -100;
  314.     if (ndiag >= lower[(*d)-GO_cost-GE_cost] && ndiag <= upper[(*d)-GO_cost-GE_cost] && row < flast_d[(*d)-GO_cost-GE_cost][ndiag].C) {
  315.         *d = (*d)-GO_cost-GE_cost;
  316.         return sC;
  317.     }
  318.     *d = (*d)-GE_cost;
  319.     return IorD;
  320. }
  321. static Int4 get_lastI(SThreeVal** flast_d, Int4* lower, Int4* upper, 
  322.                       Int4* d, Int4 diag, Int4 GO_cost, Int4 GE_cost)
  323. {
  324.     return get_last_ID(flast_d, lower, upper, d, diag, GO_cost, GE_cost, sI);
  325. }
  326. static int get_lastD(SThreeVal** flast_d, Int4* lower, Int4* upper, 
  327.                      Int4* d, Int4 diag, Int4 GO_cost, Int4 GE_cost)
  328. {
  329.     return get_last_ID(flast_d, lower, upper, d, diag, GO_cost, GE_cost, sD);
  330. }
  331. /* --- From file align.c --- */
  332. /* ----- */
  333. static Int4 get_last(Int4 **flast_d, Int4 d, Int4 diag, Int4 *row1)
  334. {
  335.     if (flast_d[d-1][diag-1] > MAX(flast_d[d-1][diag], flast_d[d-1][diag+1])) {
  336.         *row1 = flast_d[d-1][diag-1];
  337.         return diag-1;
  338.     } 
  339.     if (flast_d[d-1][diag] > flast_d[d-1][diag+1]) {
  340.         *row1 = flast_d[d-1][diag];
  341.         return diag;
  342.     }
  343.     *row1 = flast_d[d-1][diag+1];
  344.     return diag+1;
  345. }
  346. /*
  347. Version to search a (possibly) packed nucl. sequence against
  348. an unpacked sequence.  s2 is the packed nucl. sequence.
  349. s1 can be packed or unpacked. If rem == 4, then s1 is unpacked.
  350. len2 corresponds to the unpacked (true) length.
  351.  * Basic O(ND) time, O(N) space, alignment function. 
  352.  * Parameters:
  353.  *   s1, len1        - first sequence and its length
  354.  *   s2, len2        - second sequence and its length
  355.  *   reverse         - direction of alignment
  356.  *   xdrop_threshold - 
  357.  *   mismatch_cost   -
  358.  *   e1, e2          - endpoint of the computed alignment
  359.  *   edit_script     -
  360.  *   rem             - offset shift within a packed sequence
  361.  */
  362. Int4 BLAST_GreedyAlign(const Uint1* s1, Int4 len1,
  363.   const Uint1* s2, Int4 len2,
  364.   Boolean reverse, Int4 xdrop_threshold, 
  365.   Int4 match_cost, Int4 mismatch_cost,
  366.   Int4* e1, Int4* e2, 
  367.   SGreedyAlignMem* gamp, MBGapEditScript *S,
  368.                           Uint1 rem)
  369. {
  370. #define ICEIL(x,y) ((((x)-1)/(y))+1)
  371.     Int4 col, /* column number */
  372.         d, /* current distance */
  373.         k, /* current diagonal */
  374.         flower, fupper,            /* boundaries for searching diagonals */
  375.         row,         /* row number */
  376.         MAX_D,  /* maximum cost */
  377.         ORIGIN,
  378.         return_val = 0;
  379.     Int4** flast_d = gamp->flast_d; /* rows containing the last d */
  380.     Int4* max_row; /* reached for cost d=0, ... len1.  */
  381.     
  382.     Int4 X_pen = xdrop_threshold;
  383.     Int4 M_half = match_cost/2;
  384.     Int4 Op_cost = mismatch_cost + M_half*2;
  385.     Int4 D_diff = ICEIL(X_pen+M_half, Op_cost);
  386.     
  387.     Int4 x, cur_max, b_diag = 0, best_diag = INT4_MAX/2;
  388.     Int4* max_row_free = gamp->max_row_free;
  389.     char nlower = 0, nupper = 0;
  390.     SMBSpace* space = gamp->space;
  391.     Int4 max_len = len2;
  392.  
  393.     MAX_D = (Int4) (len1/ERROR_FRACTION + 1);
  394.     ORIGIN = MAX_D + 2;
  395.     *e1 = *e2 = 0;
  396.     
  397.     if (reverse) {
  398.        if (!(rem & 4)) {
  399.           for (row = 0; row < len2 && row < len1 && 
  400.                   (s2[len2-1-row] ==
  401.                    NCBI2NA_UNPACK_BASE(s1[(len1-1-row)/4], 
  402.                                         3-(len1-1-row)%4)); 
  403.                row++)
  404.              /*empty*/ ;
  405.        } else {
  406.           for (row = 0; row < len2 && row < len1 && (s2[len2-1-row] == s1[len1-1-row]); row++)
  407.              /*empty*/ ;
  408.        }
  409.     } else {
  410.        if (!(rem & 4)) {
  411.           for (row = 0; row < len2 && row < len1 && 
  412.                   (s2[row] == 
  413.                    NCBI2NA_UNPACK_BASE(s1[(row+rem)/4], 
  414.                                         3-(row+rem)%4)); 
  415.                row++)
  416.              /*empty*/ ;
  417.        } else {
  418.           for (row = 0; row < len2 && row < len1 && (s2[row] == s1[row]); row++)
  419.              /*empty*/ ;
  420.        }
  421.     }
  422.     *e1 = row;
  423.     *e2 = row;
  424.     if (row == len1) {
  425.         if (S != NULL)
  426.             edit_script_rep(S, row);
  427. /* hit last row; stop search */
  428. return 0;
  429.     }
  430.     if (S==NULL) {
  431.        space = 0;
  432.     } else if (!space) {
  433.        gamp->space = space = MBSpaceNew();
  434.     } else { 
  435.         refresh_mb_space(space);
  436.     }
  437.     
  438.     max_row = max_row_free + D_diff;
  439.     for (k = 0; k < D_diff; k++)
  440. max_row_free[k] = 0;
  441.     
  442.     flast_d[0][ORIGIN] = row;
  443.     max_row[0] = (row + row)*M_half;
  444.     
  445.     flower = ORIGIN - 1;
  446.     fupper = ORIGIN + 1;
  447.     d = 1;
  448.     while (d <= MAX_D) {
  449. Int4 fl0, fu0;
  450. flast_d[d - 1][flower - 1] = flast_d[d - 1][flower] = -1;
  451. flast_d[d - 1][fupper] = flast_d[d - 1][fupper + 1] = -1;
  452. x = max_row[d - D_diff] + Op_cost * d - X_pen;
  453. x = ICEIL(x, M_half);
  454. cur_max = 0;
  455. fl0 = flower;
  456. fu0 = fupper;
  457. for (k = fl0; k <= fu0; k++) {
  458.     row = MAX(flast_d[d - 1][k + 1], flast_d[d - 1][k]) + 1;
  459.     row = MAX(row, flast_d[d - 1][k - 1]);
  460.     col = row + k - ORIGIN;
  461.     if (row + col >= x)
  462. fupper = k;
  463.     else {
  464. if (k == flower)
  465.     flower++;
  466. else
  467.     flast_d[d][k] = -1;
  468. continue;
  469.     }
  470.             
  471.             if (row > max_len || row < 0) {
  472.                   flower = k+1; nlower = 1;
  473.             } else {
  474.                /* Slide down the diagonal. */
  475.                if (reverse) {
  476.                   if (!(rem & 4)) {
  477.                      while (row < len2 && col < len1 && s2[len2-1-row] == 
  478.                             NCBI2NA_UNPACK_BASE(s1[(len1-1-col)/4],
  479.                                                  3-(len1-1-col)%4)) {
  480.                         ++row;
  481.                         ++col;
  482.                      }
  483.                   } else {
  484.                      while (row < len2 && col < len1 && 
  485.                             s2[len2-1-row] == s1[len1-1-col]) {
  486.                         ++row;
  487.                         ++col;
  488.                      }
  489.                   }
  490.                } else {
  491.                   if (!(rem & 4)) {
  492.                      while (row < len2 && col < len1 && s2[row] == 
  493.                             NCBI2NA_UNPACK_BASE(s1[(col+rem)/4],
  494.                                                  3-(col+rem)%4)) {
  495.                         ++row;
  496.                         ++col;
  497.                      }
  498.                   } else {
  499.                      while (row < len2 && col < len1 && s2[row] == s1[col]) {
  500.                         ++row;
  501.                         ++col;
  502.                      }
  503.                   }
  504.                }
  505.             }
  506.     flast_d[d][k] = row;
  507.     if (row + col > cur_max) {
  508. cur_max = row + col;
  509. b_diag = k;
  510.     }
  511.     if (row == len2) {
  512. flower = k+1; nlower = 1;
  513.     }
  514.     if (col == len1) {
  515. fupper = k-1; nupper = 1;
  516.     }
  517. }
  518. k = cur_max*M_half - d * Op_cost;
  519. if (max_row[d - 1] < k) {
  520.     max_row[d] = k;
  521.     return_val = d;
  522.     best_diag = b_diag;
  523.     *e2 = flast_d[d][b_diag];
  524.     *e1 = (*e2)+b_diag-ORIGIN;
  525. } else {
  526.     max_row[d] = max_row[d - 1];
  527. }
  528. if (flower > fupper)
  529.     break;
  530. d++;
  531. if (!nlower) flower--; 
  532. if (!nupper) fupper++;
  533. if (S==NULL)
  534.    flast_d[d] = flast_d[d - 2];
  535. else {
  536.            /* space array consists of SThreeVal structures which are 
  537.               3 times larger than Int4, so divide requested amount by 3
  538.            */
  539.    flast_d[d] = (Int4*) get_mb_space(space, (fupper-flower+7)/3);
  540.    if (flast_d[d] != NULL)
  541.               flast_d[d] = flast_d[d] - flower + 2;
  542.            else
  543.       return return_val;
  544.         }
  545.     }
  546.     
  547.     if (S!=NULL) { /*trace back*/
  548.         Int4 row1, col1, diag1, diag;
  549.         d = return_val; diag = best_diag;
  550.         row = *e2; col = *e1;
  551.         while (d > 0) {
  552.             diag1 = get_last(flast_d, d, diag, &row1);
  553.             col1 = row1+diag1-ORIGIN;
  554.             if (diag1 == diag) {
  555.                 if (row-row1 > 0) edit_script_rep(S, row-row1);
  556.             } else if (diag1 < diag) {
  557.                 if (row-row1 > 0) edit_script_rep(S, row-row1);
  558.                 edit_script_ins(S,1);
  559.             } else {
  560.                 if (row-row1-1> 0) edit_script_rep(S, row-row1-1);
  561.                 edit_script_del(S, 1);
  562.             }
  563.             d--; diag = diag1; col = col1; row = row1;
  564.         }
  565.         edit_script_rep(S, flast_d[0][ORIGIN]);
  566.         if (!reverse) 
  567.             edit_script_reverse_inplace(S);
  568.     }
  569.     return return_val;
  570. }
  571. Int4 BLAST_AffineGreedyAlign (const Uint1* s1, Int4 len1, 
  572.  const Uint1* s2, Int4 len2,
  573.  Boolean reverse, Int4 xdrop_threshold, 
  574.  Int4 match_score, Int4 mismatch_score, 
  575.  Int4 gap_open, Int4 gap_extend,
  576.  Int4* e1, Int4* e2, 
  577.  SGreedyAlignMem* gamp, MBGapEditScript *S,
  578.                                  Uint1 rem)
  579. {
  580.     Int4 col, /* column number */
  581.         d, /* current distance */
  582.         k, /* current diagonal */
  583.         flower, fupper,         /* boundaries for searching diagonals */
  584.         row,         /* row number */
  585.         MAX_D,  /* maximum cost */
  586.         ORIGIN,
  587.         return_val = 0;
  588.     SThreeVal** flast_d; /* rows containing the last d */
  589.     Int4* max_row_free = gamp->max_row_free;
  590.     Int4* max_row; /* reached for cost d=0, ... len1.  */
  591.     Int4 Mis_cost, GO_cost, GE_cost;
  592.     Int4 D_diff, gd;
  593.     Int4 M_half;
  594.     Int4 max_cost;
  595.     Int4 *lower, *upper;
  596.     
  597.     Int4 x, cur_max, b_diag = 0, best_diag = INT4_MAX/2;
  598.     char nlower = 0, nupper = 0;
  599.     SMBSpace* space = gamp->space;
  600.     Int4 stop_condition;
  601.     Int4 max_d;
  602.     Int4* uplow_free;
  603.     Int4 max_len = len2;
  604.  
  605.     if (match_score % 2 == 1) {
  606.         match_score *= 2;
  607.         mismatch_score *= 2;
  608.         xdrop_threshold *= 2;
  609.         gap_open *= 2;
  610. gap_extend *= 2;
  611.     }
  612.     M_half = match_score/2;
  613.     if (gap_open == 0 && gap_extend == 0) {
  614.        return BLAST_GreedyAlign(s1, len1, s2, len2, reverse, 
  615.                                    xdrop_threshold, match_score, 
  616.                                    mismatch_score, e1, e2, gamp, S, rem);
  617.     }
  618.     
  619.     Mis_cost = mismatch_score + match_score;
  620.     GO_cost = gap_open;
  621.     GE_cost = gap_extend+M_half;
  622.     gd = gdb3(&Mis_cost, &GO_cost, &GE_cost);
  623.     D_diff = ICEIL(xdrop_threshold+M_half, gd);
  624.     
  625.     
  626.     MAX_D = (Int4) (len1/ERROR_FRACTION + 1);
  627.     max_d = MAX_D*GE_cost;
  628.     ORIGIN = MAX_D + 2;
  629.     max_cost = MAX(Mis_cost, GO_cost+GE_cost);
  630.     *e1 = *e2 = 0;
  631.     
  632.     if (reverse) {
  633.        if (!(rem & 4)) {
  634.           for (row = 0; row < len2 && row < len1 && 
  635.                   (s2[len2-1-row] ==
  636.                    NCBI2NA_UNPACK_BASE(s1[(len1-1-row)/4], 
  637.                                         3-(len1-1-row)%4)); 
  638.                row++)
  639.              /*empty*/ ;
  640.        } else {
  641.           for (row = 0; row < len2 && row < len1 && (s2[len2-1-row] == s1[len1-1-row]); row++)
  642.              /*empty*/ ;
  643.        }
  644.     } else {
  645.        if (!(rem & 4)) {
  646.           for (row = 0; row < len2 && row < len1 && 
  647.                   (s2[row] == 
  648.                    NCBI2NA_UNPACK_BASE(s1[(row+rem)/4], 
  649.                                         3-(row+rem)%4)); 
  650.                row++)
  651.              /*empty*/ ;
  652.        } else {
  653.           for (row = 0; row < len2 && row < len1 && (s2[row] == s1[row]); row++)
  654.              /*empty*/ ;
  655.        }
  656.     }
  657.     *e1 = row;
  658.     *e2 = row;
  659.     if (row == len1 || row == len2) {
  660.         if (S != NULL)
  661.             edit_script_rep(S, row);
  662. /* hit last row; stop search */
  663. return row*match_score;
  664.     }
  665.     flast_d = gamp->flast_d_affine;
  666.     if (S==NULL) {
  667.         space = 0;
  668.     } else if (!space) {
  669.        gamp->space = space = MBSpaceNew();
  670.     } else { 
  671.         refresh_mb_space(space);
  672.     }
  673.     max_row = max_row_free + D_diff;
  674.     for (k = 0; k < D_diff; k++)
  675. max_row_free[k] = 0;
  676.     uplow_free = gamp->uplow_free;
  677.     lower = uplow_free;
  678.     upper = uplow_free+max_d+1+max_cost;
  679.     /* next 3 lines set boundary for -1,-2,...,-max_cost+1*/
  680.     for (k = 0; k < max_cost; k++) {lower[k] =LARGE;  upper[k] = -LARGE;}
  681.     lower += max_cost;
  682.     upper += max_cost; 
  683.     
  684.     flast_d[0][ORIGIN].C = row;
  685.     flast_d[0][ORIGIN].I = flast_d[0][ORIGIN].D = -2;
  686.     max_row[0] = (row + row)*M_half;
  687.     lower[0] = upper[0] = ORIGIN;
  688.     
  689.     flower = ORIGIN - 1;
  690.     fupper = ORIGIN + 1;
  691.     
  692.     d = 1;
  693.     stop_condition = 1;
  694.     while (d <= max_d) {
  695. Int4 fl0, fu0;
  696. x = max_row[d - D_diff] + gd * d - xdrop_threshold;
  697. x = ICEIL(x, M_half);
  698. if (x < 0) x=0;
  699. cur_max = 0;
  700. fl0 = flower;
  701. fu0 = fupper;
  702. for (k = fl0; k <= fu0; k++) {
  703.     row = -2;
  704.     if (k+1 <= upper[d-GO_cost-GE_cost] && k+1 >= lower[d-GO_cost-GE_cost]) 
  705.                 row = flast_d[d-GO_cost-GE_cost][k+1].C;
  706.     if (k+1  <= upper[d-GE_cost] && k+1 >= lower[d-GE_cost] &&
  707. row < flast_d[d-GE_cost][k+1].D) 
  708.                 row = flast_d[d-GE_cost][k+1].D;
  709.     row++;
  710.     if (row+row+k-ORIGIN >= x) 
  711.       flast_d[d][k].D = row;
  712.     else flast_d[d][k].D = -2;
  713.     row = -1; 
  714.     if (k-1 <= upper[d-GO_cost-GE_cost] && k-1 >= lower[d-GO_cost-GE_cost]) 
  715.                 row = flast_d[d-GO_cost-GE_cost][k-1].C;
  716.     if (k-1  <= upper[d-GE_cost] && k-1 >= lower[d-GE_cost] &&
  717. row < flast_d[d-GE_cost][k-1].I) 
  718.                 row = flast_d[d-GE_cost][k-1].I;
  719.     if (row+row+k-ORIGIN >= x) 
  720.                 flast_d[d][k].I = row;
  721.     else flast_d[d][k].I = -2;
  722.             
  723.     row = MAX(flast_d[d][k].I, flast_d[d][k].D);
  724.     if (k <= upper[d-Mis_cost] && k >= lower[d-Mis_cost]) 
  725.                 row = MAX(flast_d[d-Mis_cost][k].C+1,row);
  726.             
  727.     col = row + k - ORIGIN;
  728.     if (row + col >= x)
  729. fupper = k;
  730.     else {
  731. if (k == flower)
  732.     flower++;
  733. else
  734.     flast_d[d][k].C = -2;
  735. continue;
  736.     }
  737.             if (row > max_len || row < -2) {
  738.                flower = k; nlower = k+1; 
  739.             } else {
  740.                /* slide down the diagonal */
  741.                if (reverse) {
  742.                   if (!(rem & 4)) {
  743.                      while (row < len2 && col < len1 && s2[len2-1-row] == 
  744.                             NCBI2NA_UNPACK_BASE(s1[(len1-1-col)/4],
  745.                                                  3-(len1-1-col)%4)) {
  746.                         ++row;
  747.                         ++col;
  748.                      }
  749.                   } else {
  750.                      while (row < len2 && col < len1 && s2[len2-1-row] ==
  751.                             s1[len1-1-col]) {
  752.                         ++row;
  753.                         ++col;
  754.                      }
  755.                   }
  756.                } else {
  757.                   if (!(rem & 4)) {
  758.                      while (row < len2 && col < len1 && s2[row] == 
  759.                             NCBI2NA_UNPACK_BASE(s1[(col+rem)/4],
  760.                                                  3-(col+rem)%4)) {
  761.                         ++row;
  762.                         ++col;
  763.                      }
  764.                   } else {
  765.                      while (row < len2 && col < len1 && s2[row] == s1[col]) {
  766.                         ++row;
  767.                         ++col;
  768.                      }
  769.                   }
  770.                }
  771.             }
  772.             flast_d[d][k].C = row;
  773.             if (row + col > cur_max) {
  774.                cur_max = row + col;
  775.                b_diag = k;
  776.             }
  777.             if (row == len2) {
  778.                flower = k; nlower = k+1;
  779.             }
  780.             if (col == len1) {
  781.                fupper = k; nupper = k-1;
  782.             }
  783. }
  784. k = cur_max*M_half - d * gd;
  785. if (max_row[d - 1] < k) {
  786.     max_row[d] = k;
  787.     return_val = d;
  788.     best_diag = b_diag;
  789.     *e2 = flast_d[d][b_diag].C;
  790.     *e1 = (*e2)+b_diag-ORIGIN;
  791. } else {
  792.     max_row[d] = max_row[d - 1];
  793. }
  794. if (flower <= fupper) {
  795.             stop_condition++;
  796.             lower[d] = flower; upper[d] = fupper;
  797. } else {
  798.             lower[d] = LARGE; upper[d] = -LARGE;
  799. }
  800. if (lower[d-max_cost] <= upper[d-max_cost]) stop_condition--;
  801. if (stop_condition == 0) break;
  802. d++;
  803. flower = MIN(lower[d-Mis_cost], MIN(lower[d-GO_cost-GE_cost], lower[d-GE_cost])-1);
  804. if (nlower) flower = MAX(flower, nlower);
  805. fupper = MAX(upper[d-Mis_cost], MAX(upper[d-GO_cost-GE_cost], upper[d-GE_cost])+1);
  806. if (nupper) fupper = MIN(fupper, nupper);
  807. if (d > max_cost) {
  808.    if (S==NULL) {
  809.       /*if (d > max_cost)*/
  810.       flast_d[d] = flast_d[d - max_cost-1];
  811.    } else {
  812.       flast_d[d] = get_mb_space(space, fupper-flower+1)-flower;
  813.       if (flast_d[d] == NULL)
  814.  return return_val;
  815.            }
  816. }
  817.     }
  818.     
  819.     if (S!=NULL) { /*trace back*/
  820.         Int4 row1, diag, state;
  821.         d = return_val; diag = best_diag;
  822.         row = *e2; state = sC;
  823.         while (d > 0) {
  824.             if (state == sC) {
  825.                 /* diag will not be changed*/
  826.                 state = get_lastC(flast_d, lower, upper, &d, diag, Mis_cost, &row1);
  827.                 if (row-row1 > 0) edit_script_rep(S, row-row1);
  828.                 row = row1;
  829.             } else {
  830.                 if (state == sI) {
  831.                     /*row unchanged */
  832.                     state = get_lastI(flast_d, lower, upper, &d, diag, GO_cost, GE_cost);
  833.                     diag--;
  834.                     edit_script_ins(S,1);
  835.                 } else {
  836.                     edit_script_del(S,1);
  837.                     state = get_lastD(flast_d, lower, upper, &d, diag, GO_cost, GE_cost);
  838.                     diag++;
  839.                     row--;
  840.                 }
  841.             }
  842.         }
  843.         edit_script_rep(S, flast_d[0][ORIGIN].C);
  844.         if (!reverse) 
  845.             edit_script_reverse_inplace(S);
  846.     }
  847.     return_val = max_row[return_val];
  848.     return return_val;
  849. }