WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / lib / c_plex.c
diff --git a/binaries/src/ViennaRNA/lib/c_plex.c b/binaries/src/ViennaRNA/lib/c_plex.c
new file mode 100644 (file)
index 0000000..3f93c9e
--- /dev/null
@@ -0,0 +1,1172 @@
+ /* Last changed Time-stamp: <2007-10-30 14:06:22 htafer> */
+/*                
+           compute the duplex structure of two RNA strands,
+                allowing only inter-strand base pairs.
+         see cofold() for computing hybrid structures without
+                             restriction.
+                             Ivo Hofacker
+                          Vienna RNA package
+
+*/
+
+
+/*
+  library containing the function used in rnaplex
+  the program rnaplex uses the following function
+  Lduplexfold: finds high scoring segments
+  it stores the end-position of these segments in an array 
+  and call then for each of these positions the duplexfold function 
+  which allows to make backtracking for each of the high scoring position
+  It allows to find suboptimal partially overlapping (depends on a a parameter) 
+  duplexes between a long RNA and a shorter one.
+  Contrarly to RNAduplex, the energy model is not in E~log(N), 
+  where N is the length of an interial loop but used an affine model, 
+  where the extension and begin parameter are fitted to the energy
+  parameter used by RNAduplex. This allows to check for duplex between a short RNA(20nt) 
+  and a long one at the speed of 1Mnt/s. At this speed the whole genome (3Gnt) can be analyzed for one siRNA 
+  in about 50 minutes.
+  The algorithm is based on an idea by Durbin and Eddy:when the alginment reach a value larger than a
+  given threshold this value is stored in an array. When the alignment score goes 
+  then under this threshold, the alignemnent begin from this value, in that way the backtracking allow us 
+  to find all non-overlapping high-scoring segments. 
+  For more information check "durbin, biological sequence analysis"
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <ctype.h>
+#include <string.h>
+#include "utils.h"
+#include "energy_par.h"
+#include "fold_vars.h"
+#include "fold.h"
+#include "pair_mat.h"
+#include "params.h"
+#include "plex.h"
+#include "ali_plex.h"
+#include "loop_energies.h"
+/*@unused@*/
+static char rcsid[] UNUSED = "$Id: plex.c,v 1.14 2007/06/12 12:50:16 htafer Exp $";
+/* int subopt_sorted=0; */
+
+#define PUBLIC
+#define PRIVATE static
+
+#define STACK_BULGE1  1   /* stacking energies for bulges of size 1 */
+#define NEW_NINIO     1   /* new asymetry penalty */
+#define ARRAY 32          /*array size*/
+#define UNIT 100
+#define MINPSCORE -2 * UNIT
+PRIVATE void  encode_seqs(const char *s1, const char *s2);
+PRIVATE short *encode_seq(const char *seq);
+/* PRIVATE void  my_encode_seq(const char *s1, const char *s2); */
+PRIVATE void  update_dfold_params(void);
+/* PRIVATE int   compare(const void *sub1, const void *sub2); */
+/* PRIVATE int   compare_XS(const void *sub1, const void *sub2); */
+/* PRIVATE duplexT* backtrack(int threshold, const int extension_cost); */
+/* static void  print_struct(duplexT const *dup); */
+
+/* PRIVATE int   print_struct(duplexT const *dup); */
+/* PRIVATE int   get_rescaled_energy(duplexT const *dup); */
+
+PRIVATE char * backtrack_C(int i, int j, const int extension_cost, const char * structure, int *E);
+PRIVATE void   find_max_C(const int *position, const int *position_j, const int delta, const int threshold, const int constthreshold, const int length, const char *s1, const char *s2, const int extension_cost, const int fast, const char* structure);
+PRIVATE void   plot_max_C(const int max, const int max_pos, const int max_pos_j, const int alignment_length, const char *s1, const char *s2, const int extension_cost, const int fast, const char* structure);
+
+
+PRIVATE char *   backtrack_CXS(int i, int j, const int** access_s1, const int** access_s2, const char* structure, int *E);
+PRIVATE void find_max_CXS(const int *position, const int *position_j,const int delta, const int threshold, const int constthreshold, const int alignment_length, const char *s1, const char *s2, const int **access_s1, const int **access_s2, const int fast,const char* structure);
+PRIVATE void     plot_max_CXS(const int max, const int max_pos, const int max_pos_j, const int alignment_length,const char *s1, const char *s2, const int **access_s1, const int **access_s2, const int fast, const char* structure);
+PRIVATE duplexT duplexfold_C(const char *s1, const char *s2, const int extension_cost, const char* structure);
+PRIVATE duplexT duplexfold_CXS(const char *s1, const char *s2,const int **access_s1, const int **access_s2, const int i_pos, const int j_pos, const int threshold ,const char* structure);
+
+
+/*@unused@*/
+
+#define MAXSECTORS      500     /* dimension for a backtrack array */
+#define LOCALITY        0.      /* locality parameter for base-pairs */
+
+#define MIN2(A, B)      ((A) < (B) ? (A) : (B))
+#define MAX2(A, B)      ((A) > (B) ? (A) : (B))
+
+PRIVATE paramT *P = NULL;
+PRIVATE int   **c = NULL;/*, **in, **bx, **by;*/      /* energy array used in duplexfold */
+/* PRIVATE int ****c_XS; */
+PRIVATE int  **lc = NULL, **lin = NULL, **lbx = NULL, **lby = NULL, **linx = NULL, **liny = NULL;   /* energy array used in Lduplexfold
+                                             this arrays contains only 3 columns
+                                             In this way I reduce my memory use and
+                                             I can make most of my computation and 
+                                             accession in the computer cash
+                                             which is the main performance boost*/
+                                             
+
+
+/*PRIVATE int last_cell;                    this variable is the last_cell containing
+                                            the information about the alignment
+                                            useful only if there is an alignment 
+                                            which extends till the last nucleotide of 
+                                            the long sequence*/
+
+PRIVATE short  *S1 = NULL, *SS1 = NULL, *S2 = NULL, *SS2 = NULL;/*contains the sequences*/
+PRIVATE int   n1,n2;    /* sequence lengths */
+PRIVATE int n3, n4; /*sequence length for the duplex*/;
+PRIVATE int delay_free=0;
+
+
+/*-----------------------------------------------------------------------duplexfold_XS---------------------------------------------------------------------------*/
+
+PRIVATE duplexT duplexfold_CXS(const char *s1, const char *s2, const int **access_s1, const int **access_s2, 
+                               const int i_pos, const int j_pos, const int threshold, const char* structure) {
+  int i, j,p,q,Emin=INF, l_min=0, k_min=0;
+  char *struc;
+  struc=NULL;
+  duplexT mfe;
+  int bonus=-10000;
+  n3 = (int) strlen(s1);
+  n4 = (int) strlen(s2);
+
+  int *previous_const;
+  previous_const=(int *) space(sizeof(int) * (n4+1));
+  j=0;
+  previous_const[j]=1;
+  int prev_temp = 1;
+  while(j++<n4){
+    if(structure[j-1]=='|'){
+      previous_const[j]=prev_temp;
+      prev_temp=j;
+    }
+    else{
+      previous_const[j]=prev_temp;
+    }
+  }
+  if ((!P) || (fabs(P->temperature - temperature)>1e-6)) {
+    update_fold_params();  if(P) free(P); P = scale_parameters();
+    make_pair_matrix();
+  }
+  
+  c = (int **) space(sizeof(int *) * (n3+1));
+  for (i=0; i<=n3; i++) c[i] = (int *) space(sizeof(int) * (n4+1));
+  for (i=0; i<=n3; i++){
+    for(j=0;j<=n4;j++){
+      c[i][j]=INF;
+    }
+  }
+  encode_seqs(s1, s2);
+  int type, type2, type3, E, k,l;
+  i=n3-1; j=2;
+  type = pair[S1[i]][S2[j]]; 
+  if(!type){
+    printf("Error during initialization of the duplex in duplexfold_XS\n");
+    mfe.structure=NULL;
+    mfe.energy = INF;
+    return mfe;
+  }
+  c[i][j] = P->DuplexInit + (structure[j-1]=='|' ? bonus : 0 ); /* check if first pair is constrained  */
+  if(!(structure[j-2] == '|')){
+    c[i][j]+=P->mismatchExt[rtype[type]][SS2[j-1]][SS1[i+1]];
+  }
+  else{
+    c[i][j]+=P->dangle3[rtype[type]][SS1[i+1]];
+  }
+  if (type>2) c[i][j] += P->TerminalAU;
+  for (k=i-1; k>0 ; k--) {
+    c[k+1][0]=INF;
+    for (l=j+1; l<=n4; l++) {
+      c[k][l]=INF;
+      int bonus_2 = (structure[l-1]=='|'? bonus : 0 ); /* check if position is constrained and prepare bonus accordingly */
+      type2 = pair[S1[k]][S2[l]];
+      if (!type2) continue;
+      for (p=k+1; p< n3 && p<k+MAXLOOP-1; p++){
+        for (q = l-1; q >= previous_const[l] && q > 1; q--) {
+          if (p-k+l-q-2>MAXLOOP) break;
+          type3=pair[S1[p]][S2[q]];
+          if(!type3) continue;
+          E = E_IntLoop(p-k-1, l-q-1, type2, rtype[type3],SS1[k+1], SS2[l-1], SS1[p-1], SS2[q+1],P) + bonus_2;
+          c[k][l] = MIN2(c[k][l], c[p][q]+E);
+        }
+      }
+      E = c[k][l]; 
+      if (type2>2) E += P->TerminalAU;
+      E+=access_s1[i-k+1][i_pos]+access_s2[l-1][j_pos+(l-1)-1];
+      if (k>1 && l<n4 && !(structure[l]=='|') ){
+        E+=P->mismatchExt[type2][SS1[k-1]][SS2[l+1]];
+      }
+      else if(k>1){
+        E += P->dangle5[type2][SS1[k-1]]; 
+      }
+      else if(l<n4 && !(structure[l]=='|')){
+        E += P->dangle3[type2][SS2[l+1]];
+      }
+      if (E<Emin) {
+        Emin=E; k_min=k; l_min=l;
+      } 
+    }
+  }
+  free(previous_const);
+  if(Emin  > threshold){
+    mfe.energy=INF;
+    mfe.ddG=INF;
+    mfe.structure=NULL;
+    for (i=0; i<=n3; i++) free(c[i]);
+    free(c);
+    free(S1); free(S2); free(SS1); free(SS2);
+    return mfe;
+  } else{
+    struc = backtrack_CXS(k_min, l_min, access_s1, access_s2,structure,&Emin);
+  }
+
+
+  /* lets take care of the dangles */
+  /* find best combination  */
+  int dx_5, dx_3, dy_5, dy_3,dGx,dGy,bonus_x;
+  dx_5=0; dx_3=0; dy_5=0; dy_3=0;dGx=0;dGy=0;bonus_x=0;
+  dGx = access_s1[i-k_min+1][i_pos];dx_3=0; dx_5=0;bonus_x=0; 
+  dGy = access_s2[l_min-j+1][j_pos + (l_min-1)-1]; 
+  mfe.tb=i_pos -9 - i + k_min -1 -dx_5;
+  mfe.te=i_pos -9 -1 + dx_3;
+  mfe.qb=j_pos -9 -1 - dy_5;
+  mfe.qe=j_pos + l_min -3 -9 + dy_3;
+  mfe.ddG=(double) Emin * 0.01;
+  mfe.dG1=(double) dGx*0.01 ;
+  mfe.dG2=(double) dGy*0.01 ; 
+  /* mfe.energy += bonus_y + bonus_x; */
+  mfe.energy= mfe.ddG - mfe.dG1 - mfe.dG2;
+
+  mfe.structure = struc;
+  for (i=0; i<=n3; i++) free(c[i]);
+  free(c);
+  free(S1); free(S2); free(SS1); free(SS2);
+  return mfe;
+}
+
+
+PRIVATE char *backtrack_CXS (int i, int j, const int **access_s1,const int **access_s2,const char* structure, int *Emin ) {
+  /* backtrack structure going backwards from i, and forwards from j 
+     return structure in bracket notation with & as separator */
+  int k, l, type, type2, E, traced, i0, j0;
+  char *st1, *st2, *struc;
+  int *previous_const;
+  int bonus=-10000;
+  previous_const=(int *) space(sizeof(int) * (n4+1));
+  int j_temp=0;
+  previous_const[j_temp]=1;
+  int prev_temp = 1;
+  while(j_temp++<n4){
+    if(structure[j_temp-1]=='|'){
+      previous_const[j_temp]=prev_temp;
+      prev_temp=j_temp;
+    }
+    else{
+      previous_const[j_temp]=prev_temp;
+    }
+  }
+  st1 = (char *) space(sizeof(char)*(n3+1));
+  st2 = (char *) space(sizeof(char)*(n4+1));
+  i0=i;/*MAX2(i-1,1);*/j0=j;/*MIN2(j+1,n4);*/
+  while (i<=n3-1 && j>=2) {
+    int bonus_2 = (structure[j-1]== '|'? bonus: 0);
+    E = c[i][j]; traced=0;
+    st1[i-1] = '(';
+    st2[j-1] = ')'; 
+    type = pair[S1[i]][S2[j]];
+    if (!type) nrerror("backtrack failed in fold duplex bli");
+    for (k=i+1; k<=n3 && k>i-MAXLOOP-2; k++) {
+      for (l=j-1; l >= previous_const[j] && l>=1; l--) {
+        int LE;
+        if (i-k+l-j-2>MAXLOOP) break;
+        type2 = pair[S1[k]][S2[l]];
+        if (!type2) continue;
+        LE = E_IntLoop(k-i-1, j-l-1, type, rtype[type2], SS1[i+1], SS2[j-1], SS1[k-1], SS2[l+1],P) + bonus_2;
+        if (E == c[k][l]+LE) {
+          *Emin-=bonus_2;
+          traced=1; 
+          i=k; j=l;
+          break;
+        }
+      }
+      if (traced) break;
+    }
+    if (!traced) { 
+      if(i<n3 && j>1 && !(structure[j-2]=='|')){
+        E -= P->mismatchExt[rtype[type]][SS2[j-1]][SS1[i+1]];
+      }
+      else if (i<n3){
+        E -= P->dangle3[rtype[type]][SS1[i+1]];/* +access_s1[1][i+1]; */
+      }
+      else if (j>1){
+        E -= (!(structure[j-2]=='|') ? P->dangle5[rtype[type]][SS2[j-1]] : 0);/* +access_s2[1][j+1]; */
+      }
+      if (type>2) E -= P->TerminalAU;
+
+      /* break; */
+      if (E != P->DuplexInit + bonus_2)  {
+        nrerror("backtrack failed in fold duplex bal");
+      } else {
+        *Emin-=bonus_2;
+        break;
+      }
+    }
+  }
+  /* if (i<n3)  i++; */
+  /* if (j>1)   j--; */
+  struc = (char *) space(i-i0+1+j0-j+1+2);
+  for (k=MAX2(i0,1); k<=i; k++) if (!st1[k-1]) st1[k-1] = '.';
+  for (k=j; k<=j0; k++) if (!st2[k-1]) st2[k-1] = '.';
+  strcpy(struc, st1+MAX2(i0-1,0)); strcat(struc, "&"); 
+  strcat(struc, st2+j-1);
+  free(st1); free(st2);free(previous_const);
+  return struc;
+}
+
+
+duplexT** Lduplexfold_CXS(const char *s1, const char *s2, const int **access_s1, const int **access_s2, const int threshold, const int alignment_length, const int delta, const int fast, const char* structure,const int il_a, const int il_b, const int b_a, const int b_b)/* , const int target_dead, const int query_dead) */
+{
+  
+  int i, j;
+  int bopen=b_b;
+  int bext=b_a;
+  int iopen=il_b;
+  int iext_s=2*il_a;/* iext_s 2 nt nucleotide extension of interior loop, on i and j side */
+  int iext_ass=50+il_a;/* iext_ass assymetric extension of interior loop, either on i or on j side. */
+  int min_colonne=INF; /* enthaelt das maximum einer kolonne */
+  int i_length;
+  int max_pos;/* get position of the best hit */
+  int max_pos_j;
+  /* int temp; */
+  int min_j_colonne;
+  int max=INF;
+  int bonus=-10000;
+  int constthreshold=0; /* minimal threshold corresponding to a structure complying to all constraints */
+  int maxPenalty[4];
+  i=0;
+  while(structure[i]!='\0'){
+    if(structure[i]=='|') constthreshold+=bonus;
+    i++;
+  }    
+  int *position; /* contains the position of the hits with energy > E */
+  int *position_j;
+  n1 = (int) strlen(s1);
+  n2 = (int) strlen(s2);
+  position = (int *) space ((delta+n1+3+delta) * sizeof(int));
+  position_j= (int *) space ((delta+n1+3+delta) * sizeof(int));
+
+  
+  if ((!P) || (fabs(P->temperature - temperature)>1e-6)){
+    update_dfold_params(); if(P) free(P); P = scale_parameters();
+    make_pair_matrix();
+  }
+    
+  encode_seqs(s1,s2);
+
+  maxPenalty[0]=(int) -1*P->stack[2][2]/2;
+  maxPenalty[1]=(int) -1*P->stack[2][2];
+  maxPenalty[2]=(int) -3*P->stack[2][2]/2;
+  maxPenalty[3]=(int) -2*P->stack[2][2];
+  
+  lc   = (int**) space (sizeof(int *) * 5);
+  lin  = (int**) space (sizeof(int *) * 5);
+  lbx  = (int**) space (sizeof(int *) * 5);
+  lby  = (int**) space (sizeof(int *) * 5);
+  linx = (int**) space (sizeof(int *) * 5);
+  liny = (int**) space (sizeof(int *) * 5);
+
+  for (i=0; i<=4; i++){
+    lc[i]  = (int *) space(sizeof(int) * (n2+5));  
+    lin[i] = (int *) space(sizeof(int) * (n2+5));  
+    lbx[i] = (int *) space(sizeof(int) * (n2+5));  
+    lby[i] = (int *) space(sizeof(int) * (n2+5));  
+    linx[i]= (int *) space(sizeof(int) * (n2+5));  
+    liny[i]= (int *) space(sizeof(int) * (n2+5));  
+  }
+  for(j=n2;j>=0;j--) {
+    lbx[0][j]=lbx[1][j]=lbx[2][j]=lbx[3][j]    = lbx[4][j] =INF;
+    lin[0][j]=lin[1][j]=lin[2][j]=lin[3][j]    = lin[4][j] =INF;
+    lc[0][j] =lc[1][j] =lc[2][j] = lc[3][j]    =  lc[4][j] =INF;
+    lby[0][j]=lby[1][j]=lby[2][j]=lby[3][j]    = lby[4][j] =INF;
+    liny[0][j]=liny[1][j]=liny[2][j]=liny[3][j]=liny[4][j]=INF;
+    linx[0][j]=linx[1][j]=linx[2][j]=linx[3][j]=linx[4][j]=INF;
+  }
+  
+  i=10 /*target_dead*/; /* start from 2 (        i=4) because no structure allowed to begin with a single base pair */
+  i_length= n1 - 9  /*- target_dead*/ ; 
+  while(i < i_length) {
+    int idx=i%5;
+    int idx_1=(i-1)%5;
+    int idx_2=(i-2)%5;
+    int idx_3=(i-3)%5;
+    int idx_4=(i-4)%5;
+    int di1,di2,di3,di4;
+    di1 = access_s1[5][i]   - access_s1[4][i-1];           
+    di2 = access_s1[5][i-1] - access_s1[4][i-2] + di1;
+    di3 = access_s1[5][i-2] - access_s1[4][i-3] + di2;
+    di4 = access_s1[5][i-3] - access_s1[4][i-4] + di3;
+    di1=MIN2(di1,maxPenalty[0]);
+    di2=MIN2(di2,maxPenalty[1]);
+    di3=MIN2(di3,maxPenalty[2]);
+    di4=MIN2(di4,maxPenalty[3]);
+    j=n2 - 9 /*- query_dead*/; /* start from n2-1 because no structure allow to begin with a single base pair  */
+    while (--j > 9/*query_dead - 1*/) {
+      /* ----------------------------------------------------------update lin lbx lby matrix */
+      int bonus_2 = (structure[j-1]=='|' ? bonus :0 );
+      int dj1,dj2,dj3,dj4;
+      dj1 = access_s2[5][j+4] - access_s2[4][j+4];        
+      dj2 = access_s2[5][j+5] - access_s2[4][j+5] + dj1;
+      dj3 = access_s2[5][j+6] - access_s2[4][j+6] + dj2;
+      dj4 = access_s2[5][j+7] - access_s2[4][j+7] + dj3;
+      dj1=MIN2(dj1,maxPenalty[0]);
+      dj2=MIN2(dj2,maxPenalty[1]);
+      dj3=MIN2(dj3,maxPenalty[2]);
+      dj4=MIN2(dj4,maxPenalty[3]);
+      int type2, type,temp;
+      type  = pair[S1[i]][S2[j]];
+      lc[idx][j]= type ? P->DuplexInit + access_s1[1][i] + access_s2[1][j] + bonus_2 : INF;
+      if(!bonus_2){
+        type2=pair[S2[j+1]][S1[i-1]];
+        lin[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatchI[type2][SS2[j]][SS1[i]]+di1+dj1+iopen+iext_s,lin[idx_1][j]+iext_ass + di1); 
+        lin[idx][j]=MIN2(lin[idx][j],lin[idx][j+1]+iext_ass + dj1);
+        lin[idx][j]=MIN2(lin[idx][j],lin[idx_1][j+1]+iext_s + di1 + dj1);
+        linx[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatch1nI[type2][SS2[j]][SS1[i]]+di1+dj1+iopen+iext_s,linx[idx_1][j]+iext_ass + di1);
+        liny[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatch1nI[type2][SS2[j]][SS1[i]]+di1+dj1+iopen+iext_s,liny[idx][j+1]+iext_ass + dj1); 
+        type2=pair[S2[j+1]][S1[i]];
+        lby[idx][j]=MIN2(lby[idx][j+1]+bext + dj1 , 
+                         lc[idx][j+1]+bopen+bext+(type2>2?P->TerminalAU:0)+dj1);
+      }
+      else{
+        lin[idx][j] = lby[idx][j] = linx[idx][j]= liny[idx][j]=INF; /* all loop containing "|" are rejected */
+      }
+      type2=pair[S2[j]][S1[i-1]];
+      lbx[idx][j]=MIN2(lbx[idx_1][j]+bext + di1, lc[idx_1][j]+bopen+bext+(type2>2?P->TerminalAU:0) + di1);
+      /* --------------------------------------------------------------- end update recursion */
+      if(!type){continue;} 
+      if(!(structure[j]=='|')){
+        lc[idx][j]+=P->mismatchExt[type][SS1[i-1]][SS2[j+1]];
+      }
+      else{
+        lc[idx][j]+=P->dangle5[type][SS1[i-1]];
+      }
+      lc[idx][j]+=(type>2?P->TerminalAU:0);
+      /* type > 2 -> no GC or CG pair */
+      /* ------------------------------------------------------------------update c  matrix  */
+      /*  Be careful, no lc may come from a region where a "|" is in a loop, avoided in lin = lby = INF ... jedoch fuer klein loops muss man aufpassen .. */
+      if((type2=pair[S1[i-1]][S2[j+1]]))
+        lc[idx][j]=MIN2(lc[idx_1][j+1]+E_IntLoop(0,0,type2, rtype[type],SS1[i], SS2[j], SS1[i-1], SS2[j+1], P)+di1+dj1, lc[idx][j]); /* 0x0+1x1 */
+      if((type2=pair[S1[i-2]][S2[j+1]]))
+        lc[idx][j]=MIN2(lc[idx_2][j+1]+E_IntLoop(1,0,type2, rtype[type],SS1[i-1], SS2[j], SS1[i-1], SS2[j+1], P)+di2+dj1,lc[idx][j]);/* 0x1 +1x1 */
+      /* kleine loops checks wird in den folgenden if test gemacht. */
+      if(!(structure[j]=='|')){
+        if((type2=pair[S1[i-1]][S2[j+2]]))
+          lc[idx][j]=MIN2(lc[idx_1][j+2]+E_IntLoop(0,1,type2, rtype[type],SS1[i], SS2[j+1], SS1[i-1], SS2[j+1], P)+di1+dj2,lc[idx][j]);/* 1x0 + 1x1 */
+        if((type2=pair[S1[i-2]][S2[j+2]]))
+          lc[idx][j]=MIN2(lc[idx_2][j+2]+E_IntLoop(1,1,type2, rtype[type],SS1[i-1], SS2[j+1], SS1[i-1], SS2[j+1], P)+di2+dj2, lc[idx][j]); /*  1x1 +1x1 */
+        if((type2 = pair[S1[i-3]][S2[j+2]]))
+          lc[idx][j]=MIN2(lc[idx_3][j+2]+E_IntLoop(2,1,type2, rtype[type],SS1[i-2], SS2[j+1], SS1[i-1], SS2[j+1], P)+di3+dj2, lc[idx][j]); /*  2x1 +1x1 */
+        if(!(structure[j+1]=='|')){
+          if((type2 = pair[S1[i-3]][S2[j+3]]))
+            lc[idx][j]=MIN2(lc[idx_3][j+3]+E_IntLoop(2,2,type2, rtype[type],SS1[i-2], SS2[j+2], SS1[i-1], SS2[j+1], P)+di3+dj3,lc[idx][j]);/* 2x2 + 1x1 */
+          if((type2 = pair[S1[i-2]][S2[j+3]]))
+            lc[idx][j]=MIN2(lc[idx_2][j+3]+E_IntLoop(1,2,type2, rtype[type],SS1[i-1], SS2[j+2], SS1[i-1], SS2[j+1], P)+di2+dj3, lc[idx][j]);/*  1x2 +1x1 */
+          if((type2 = pair[S1[i-4]][S2[j+3]]))
+            lc[idx][j]=MIN2(lc[idx_4][j+3]+E_IntLoop(3,2,type2, rtype[type],SS1[i-3], SS2[j+2], SS1[i-1], SS2[j+1], P)+di4+dj3, lc[idx][j]);
+          if(!(structure[j+2]=='|')){
+            if((type2 = pair[S1[i-3]][S2[j+4]]))
+              lc[idx][j]=MIN2(lc[idx_3][j+4]+E_IntLoop(2,3,type2, rtype[type],SS1[i-2], SS2[j+3], SS1[i-1], SS2[j+1], P)+di3+dj4, lc[idx][j]);
+          }
+        }
+      }
+      /* internal->stack  */
+      lc[idx][j]=MIN2(lin[idx_3][j+3]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+di3+dj3+2*iext_s, lc[idx][j]);
+      lc[idx][j]=MIN2(lin[idx_4][j+2]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_s+2*iext_ass+di4+dj2, lc[idx][j]);
+      lc[idx][j]=MIN2(lin[idx_2][j+4]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_s+2*iext_ass+di2+dj4, lc[idx][j]);
+      lc[idx][j]=MIN2(linx[idx_3][j+1]+P->mismatch1nI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_ass+iext_ass+di3+dj1, lc[idx][j]);
+      lc[idx][j]=MIN2(liny[idx_1][j+3]+P->mismatch1nI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_ass+iext_ass+dj3+di1, lc[idx][j]);
+      /* bulge -> stack */
+      int bAU;
+      bAU=(type>2?P->TerminalAU:0);
+      lc[idx][j]=MIN2(lbx[idx_2][j+1]+di2+dj1+bext+bAU, lc[idx][j]);
+      /* min2=by[i][j+1]; */
+      lc[idx][j]=MIN2(lby[idx_1][j+2]+di1+dj2+bext+bAU, lc[idx][j]);
+      lc[idx][j]+=bonus_2;
+      /* if(j<=const5end){ */
+      temp=min_colonne;
+      min_colonne=MIN2(lc[idx][j]+(type>2?P->TerminalAU:0)+
+                       (!(structure[j-2]=='|') ? 
+                        P->mismatchExt[rtype[type]][SS2[j-1]][SS1[i+1]] : P->dangle3[rtype[type]][SS1[i+1]]),
+                       min_colonne);
+      if(temp>min_colonne){
+        min_j_colonne=j;
+      }
+      /* } */
+      /* ---------------------------------------------------------------------end update */
+    }
+    if(max>=min_colonne){
+      max=min_colonne;
+      max_pos=i;
+      max_pos_j=min_j_colonne;
+    }
+    position[i+delta]=min_colonne;min_colonne=INF;
+    position_j[i+delta]=min_j_colonne;
+    i++;
+  }
+  /* printf("MAX :%d ", max); */
+  free(S1); free(S2); free(SS1); free(SS2);  
+  if(max<threshold+constthreshold){
+    find_max_CXS(position, position_j, delta, threshold+constthreshold, constthreshold, alignment_length, s1, s2, access_s1, access_s2, fast, structure);  
+  }
+  if(max<constthreshold){
+    plot_max_CXS(max, max_pos, max_pos_j,alignment_length, s1, s2, access_s1, access_s2,fast,structure);
+  }
+  for (i=0; i<=4; i++) {free(lc[i]);free(lin[i]);free(lbx[i]);free(lby[i]);free(linx[i]);free(liny[i]);}
+  /* free(lc[0]);free(lin[0]);free(lbx[0]);free(lby[0]); */
+  free(lc);free(lin);free(lbx);free(lby);free(linx);free(liny);
+  free(position);
+  free(position_j);
+  return NULL;
+}
+
+PRIVATE void find_max_CXS(const int *position, const int *position_j,const int delta, const int threshold, const int constthreshold, const int alignment_length, const char *s1, const char *s2, const int **access_s1, const int **access_s2, const int fast, const char* structure){
+  int pos=n1-9;
+  if(fast==1){
+    while(10 < pos--){
+      int temp_min=0;
+      if(position[pos+delta]<(threshold)){                                        
+        int search_range;                                                   
+        search_range=delta+1;                                               
+        while(--search_range){   
+          if(position[pos+delta-search_range]<=position[pos+delta-temp_min]){
+            temp_min=search_range;                                          
+          }                                                                 
+        }                                                                   
+        pos-=temp_min;                                                      
+        int max_pos_j;                                                      
+        max_pos_j=position_j[pos+delta];
+        int max;
+        max=position[pos+delta];
+        printf("target upper bound %d: query lower bound %d  (%5.2f) \n", pos-10, max_pos_j-10, ((double)max)/100);
+        pos=MAX2(10,pos-delta);
+      }
+    }
+  }
+  else{
+    pos=n1-9;
+    while( pos-- > 10 ){
+      int temp_min=0;
+      if(position[pos+delta]<(threshold)){
+        int search_range;
+        search_range=delta+1;
+        while(--search_range){
+          if(position[pos+delta-search_range]<=position[pos+delta-temp_min]){
+            temp_min=search_range;
+          }
+        }
+        pos-=temp_min; /* position on i */
+        int max_pos_j;
+        max_pos_j=position_j[pos+delta]; /* position on j */
+        /* int begin_t=MAX2(9, pos-alignment_length); */
+        /* int end_t  =MIN2(n1-10, pos); */
+        /* int begin_q=MAX2(9, max_pos_j-2); */
+        /* int end_q  =MIN2(n2-10, max_pos_j+alignment_length-2); */
+        int begin_t=MAX2(9,pos-alignment_length);
+        int end_t  =pos;
+        int begin_q=max_pos_j-2;
+        int end_q  =MIN2(n2-9,max_pos_j+alignment_length-2);
+        char *s3 = (char*) space(sizeof(char)*(end_t - begin_t +2));
+        char *s4 = (char*) space(sizeof(char)*(end_q - begin_q +2));
+        char *local_structure = (char*) space(sizeof(char) * ( end_q - begin_q +2));
+        strncpy(s3, (s1+begin_t),  end_t - begin_t+1);
+        strncpy(s4, (s2+begin_q) , end_q - begin_q+1 );
+        strncpy(local_structure, (structure+begin_q), end_q - begin_q +1);
+        s3[end_t -begin_t +1 ]='\0';
+        s4[end_q -begin_q +1 ]='\0';
+        local_structure[end_q - begin_q +1]='\0';
+        duplexT test;
+        test = duplexfold_CXS(s3,s4,access_s1,access_s2,pos, max_pos_j,threshold,local_structure);
+        if(test.energy * 100 < (threshold - constthreshold)){
+          int l1=strchr(test.structure, '&')-test.structure;
+          int dL = strrchr(structure,'|') - strchr(structure,'|');
+          dL+=1;
+          if(dL <=  strlen(test.structure)-l1-1){
+            printf("%s %3d,%-3d : %3d,%-3d (%5.2f = %5.2f + %5.2f + %5.2f)\n", test.structure, 
+                   test.tb,test.te,test.qb,test.qe, test.ddG, test.energy, test.dG1, test.dG2);
+            pos=MAX2(10,pos-delta);
+          }
+        }
+        free(s3);free(s4);
+        free(test.structure);
+        free(local_structure);
+      }
+    }
+  }
+}
+
+
+PRIVATE void plot_max_CXS(const int max, const int max_pos, const int max_pos_j, const int alignment_length, const char *s1, const char *s2, const int ** access_s1, const int ** access_s2, const int fast, const char* structure)
+{
+  if(fast==1){ 
+    printf("target upper bound %d: query lower bound %d (%5.2f)\n", max_pos-3, max_pos_j, ((double)max)/100); 
+  } 
+  else{ 
+    int begin_t=MAX2(9,max_pos-alignment_length);
+    int end_t  =max_pos;
+    int begin_q=max_pos_j-2;
+    int end_q  =MIN2(n2-9,max_pos_j+alignment_length-2);
+    char *s3 = (char*) space(sizeof(char)*(end_t - begin_t +2));
+    char *s4 = (char*) space(sizeof(char)*(end_q - begin_q +2));
+    char *local_structure = (char*) space(sizeof(char)*(end_q - begin_q +2));
+    strncpy(s3, (s1+begin_t),  end_t - begin_t+1);
+    strncpy(s4, (s2+begin_q) , end_q - begin_q+1 );
+    strncpy(local_structure, (structure+begin_q) , end_q - begin_q +1 );
+    s3[end_t -begin_t +1 ]='\0';
+    s4[end_q -begin_q +1 ]='\0';
+    local_structure[end_q - begin_q +1]='\0';
+    duplexT test;
+    test = duplexfold_CXS(s3,s4,access_s1,access_s2,max_pos, max_pos_j,INF,local_structure);
+    int l1=  strchr(test.structure, '&')-test.structure;
+    int dL = strrchr(structure,'|') - strchr(structure,'|');
+    dL+=1;
+    if(dL<=strlen(test.structure)-l1-1){
+      printf("%s %3d,%-3d : %3d,%-3d (%5.2f = %5.2f + %5.2f + %5.2f)\n", test.structure, 
+             test.tb,test.te,test.qb,test.qe, test.ddG, test.energy, test.dG1, test.dG2);
+    }
+    free(s3);free(s4);free(test.structure);free(local_structure);
+    
+  }
+}
+
+
+/*---------------------------------------------------------duplexfold----------------------------------------------------------------------------------*/
+
+
+PRIVATE duplexT duplexfold_C(const char *s1, const char *s2, const int extension_cost, const char* structure ) {
+  int i, j, l1, Emin=INF, i_min=0, j_min=0;
+  char *struc;
+  duplexT mfe;
+  int bonus=-10000;
+  int *previous_const; /* for each "|" constraint returns the position of the next "|" constraint */
+  
+  n3 = (int) strlen(s1);
+  n4 = (int) strlen(s2);
+  
+  if ((!P) || (fabs(P->temperature - temperature)>1e-6)) {
+    update_fold_params();  if(P) free(P); P = scale_parameters();
+    make_pair_matrix();
+  }
+  previous_const=(int *) space(sizeof(int) * (n4+1));
+  j=n4+1;
+  previous_const[j-1]=n4;
+  int prev_temp = n4;
+  while(--j){
+    if(structure[j-1]=='|'){
+      previous_const[j-1]=prev_temp;
+      prev_temp=j;
+    }
+    else{
+      previous_const[j-1]=prev_temp;
+    }
+  }
+  c = (int **) space(sizeof(int *) * (n3+1));
+  for (i=0; i<=n3; i++) c[i] = (int *) space(sizeof(int) * (n4+1));
+  encode_seqs(s1, s2);  
+  for (i=1; i<=n3; i++) {
+    for (j=n4; j>0; j--) {
+      int type, type2, E, k,l;
+      int bonus_2 = (structure[j-1]=='|'? bonus: 0);
+      type = pair[S1[i]][S2[j]];
+      c[i][j] = type ? P->DuplexInit +2 * extension_cost + bonus_2: INF;
+      if(!type){ continue;}
+      if(j<n4 && i>1 && !(structure[j]=='|') ) {
+        c[i][j]+=P->mismatchExt[type][SS1[i-1]][SS2[j+1]]+2*extension_cost;
+      }
+      else if(i>1){
+        c[i][j] += P->dangle5[type][SS1[i-1]]+ extension_cost;
+      }
+      else if(j<n4 && !(structure[j]=='|')){
+        c[i][j] += P->dangle3[type][SS2[j+1]]+ extension_cost;
+      }
+      if (type>2) c[i][j] += P->TerminalAU;
+      for (k=i-1; k>0 && k>i-MAXLOOP-2; k--) {
+        for (l=j+1; l<=previous_const[j]; l++) {
+          if (i-k+l-j-2>MAXLOOP) break;
+          type2 = pair[S1[k]][S2[l]];
+          if (!type2) continue;
+          E = E_IntLoop(i-k-1, l-j-1, type2, rtype[type],
+                        SS1[k+1], SS2[l-1], SS1[i-1], SS2[j+1],P)+(i-k+l-j)*extension_cost + bonus_2;
+          c[i][j] = MIN2(c[i][j], c[k][l]+E);
+        }
+      }
+      E = c[i][j]; 
+      if(i<n3 && j>1 && !(structure[j-2]=='|')){
+        E+= P->mismatchExt[rtype[type]][SS2[j-1]][SS1[i+1]]+2*extension_cost;
+      }
+      else if (i<n3){
+        E += P->dangle3[rtype[type]][SS1[i+1]]+extension_cost;
+      }
+      else if (j>1 && !(structure[j-2]=='|')){
+        E += P->dangle5[rtype[type]][SS2[j-1]]+extension_cost;
+      }
+      if (type>2) E += P->TerminalAU;
+
+      if (E<Emin) {
+        Emin=E; i_min=i; j_min=j;
+      } 
+    }
+  }  
+  struc = backtrack_C(i_min, j_min, extension_cost,structure,&Emin);
+  if (i_min<n3) i_min++;
+  if (j_min>1 ) j_min--;
+  l1 = strchr(struc, '&')-struc;
+  int size;
+  size=strlen(struc)-1;
+  Emin-= size * (extension_cost);  
+  mfe.i = i_min;
+  mfe.j = j_min;
+  mfe.energy = (double) Emin/100.;
+  mfe.structure = struc;
+  free(previous_const); 
+  if (!delay_free) {
+    for (i=0; i<=n3; i++) free(c[i]);
+    
+    free(c);
+    free(S1); free(S2); free(SS1); free(SS2);
+  }
+  return mfe;
+}
+
+PRIVATE char *backtrack_C(int i, int j, const int extension_cost, const char* structure, int *Emin) {
+  /* backtrack structure going backwards from i, and forwards from j 
+     return structure in bracket notation with & as separator */
+  int k, l, type, type2, E, traced, i0, j0, *previous_const;
+  char *st1, *st2, *struc;
+  int bonus=-10000;
+  previous_const=(int *) space(sizeof(int) * (n4+1)); /* encodes the position of the constraints */
+  int j_temp=n4+1;
+  previous_const[j_temp-1]=n4;
+  int prev_temp = n4;
+  while(--j_temp){
+    if(structure[j_temp-1]=='|'){
+      previous_const[j_temp-1]=prev_temp;
+      prev_temp=j_temp;
+    }
+    else{
+      previous_const[j_temp-1]=prev_temp;
+    }
+  }
+  st1 = (char *) space(sizeof(char)*(n3+1));
+  st2 = (char *) space(sizeof(char)*(n4+1));
+  i0=MIN2(i+1,n3); j0=MAX2(j-1,1);
+  while (i>0 && j<=n4) {
+    int bonus_2 = (structure[j-1]== '|'? bonus: 0);
+    E = c[i][j]; traced=0;
+    st1[i-1] = '(';
+    st2[j-1] = ')'; 
+    type = pair[S1[i]][S2[j]];
+    if (!type) nrerror("backtrack failed in fold duplex a");
+    for (k=i-1; k>0 && k>i-MAXLOOP-2; k--) {
+      for (l=j+1; l<=previous_const[j]; l++) {
+        int LE;
+        if (i-k+l-j-2>MAXLOOP) break;
+        type2 = pair[S1[k]][S2[l]];
+        if (!type2) continue;
+        LE = E_IntLoop(i-k-1, l-j-1, type2, rtype[type],
+                       SS1[k+1], SS2[l-1], SS1[i-1], SS2[j+1],P)+(i-k+l-j)*extension_cost + bonus_2;
+        if (E == c[k][l]+LE) { 
+          *Emin-=bonus_2;
+          traced=1; 
+          i=k; j=l;
+          break;
+        }
+      }
+      if (traced) break;
+    }
+    if (!traced) { 
+      
+      if (i>1 && j<n4 && !(structure[j]=='|')){
+        E -=P->mismatchExt[type][SS1[i-1]][SS2[j+1]]+2*extension_cost;
+      }
+      else if(i>1){
+        E -= P->dangle5[type][SS1[i-1]]+extension_cost;
+      }
+      else if (j<n4 && !(structure[j]=='|')){
+        E -= P->dangle3[type][SS2[j+1]]+ extension_cost;
+      }
+      /* if (j<n4) E -= P->dangle3[type][SS2[j+1]]+extension_cost; */
+      if (type>2) E -= P->TerminalAU;
+      if (E != P->DuplexInit+2*extension_cost + bonus_2) {
+        nrerror("backtrack failed in fold duplex b");
+      } else {
+        *Emin-=bonus_2;
+        break;
+      }
+    }
+  }
+  if (i>1)  i--;
+  if (j<n4) j++;
+  
+  struc = (char *) space(i0-i+1+j-j0+1+2);
+  for (k=MAX2(i,1); k<=i0; k++) if (!st1[k-1]) st1[k-1] = '.';
+  for (k=j0; k<=j; k++) if (!st2[k-1]) st2[k-1] = '.';
+  strcpy(struc, st1+MAX2(i-1,0)); strcat(struc, "&"); 
+  strcat(struc, st2+j0-1);
+  
+  /* printf("%s %3d,%-3d : %3d,%-3d\n", struc, i,i0,j0,j);  */
+  free(st1); free(st2);
+  free(previous_const);
+  return struc;
+}
+
+
+
+
+duplexT ** Lduplexfold_C(const char *s1, const char *s2, const int threshold, const int extension_cost, const int alignment_length, const int delta, const int fast, const char* structure, const int il_a, const int il_b, const int b_a, const int b_b)
+{
+  /* duplexT test = duplexfold_C(s1, s2, extension_cost,structure); */
+  
+  int i, j;
+  int bopen=b_b;
+  int bext=b_a+extension_cost;
+  int iopen=il_b;
+  int iext_s=2*(il_a+extension_cost);/* iext_s 2 nt nucleotide extension of interior loop, on i and j side */
+  int iext_ass=50+il_a+extension_cost;/* iext_ass assymetric extension of interior loop, either on i or on j side. */
+  int min_colonne=INF; /* enthaelt das maximum einer kolonne */
+  int i_length;
+  int max_pos;/* get position of the best hit */
+  int max_pos_j=10;
+  int temp;
+  int min_j_colonne=11;
+  int max=INF;
+  int bonus = -10000;
+  int constthreshold=0; /* minimal threshold corresponding to a structure complying to all constraints */
+  i=0;
+  while(structure[i]!='\0'){
+    if(structure[i]=='|') constthreshold+=bonus;
+    i++;
+  }    
+  /* FOLLOWING NEXT 4 LINE DEFINES AN ARRAY CONTAINING POSITION OF THE SUBOPT IN S1 */
+  /* int nsubopt=10;  */ /* total number of subopt */
+  int *position; /* contains the position of the hits with energy > E */
+  int *position_j;
+  /*   int const5end; */ /* position of the 5'most constraint. Only interaction reaching this position are taken into account. */
+  /* const5end = strchr(structure,'|') - structure; */
+  /* const5end++; */
+  n1 = (int) strlen(s1);
+  n2 = (int) strlen(s2);
+  /* delta_check is the minimal distance allowed for two hits to be accepted */
+  /* if both hits are closer, reject the smaller ( in term of position)  hits  */
+  position = (int *) space ((delta+n1+3+delta) * sizeof(int));
+  position_j= (int *) space ((delta+n1+3+delta) * sizeof(int));
+  /* i want to implement a function that, given a position in a long sequence and a small sequence, */
+  /* duplexfold them at this position and report the result at the command line */
+  /* for this i first need to rewrite backtrack in order to remove the printf functio */
+  /* END OF DEFINITION FOR NEEDED SUBOPT DATA  */
+  
+  if ((!P) || (fabs(P->temperature - temperature)>1e-6))
+  update_dfold_params();
+
+  lc   = (int**) space (sizeof(int *) * 5);
+  lin  = (int**) space (sizeof(int *) * 5);
+  lbx  = (int**) space (sizeof(int *) * 5);
+  lby  = (int**) space (sizeof(int *) * 5);
+  linx = (int**) space (sizeof(int *) * 5);
+  liny = (int**) space (sizeof(int *) * 5);
+
+  for (i=0; i<=4; i++){
+    lc[i]  = (int *) space(sizeof(int) * (n2+5));  
+    lin[i] = (int *) space(sizeof(int) * (n2+5));  
+    lbx[i] = (int *) space(sizeof(int) * (n2+5));  
+    lby[i] = (int *) space(sizeof(int) * (n2+5));  
+    linx[i]= (int *) space(sizeof(int) * (n2+5));  
+    liny[i]= (int *) space(sizeof(int) * (n2+5));  
+  }
+  for(j=n2;j>=0;j--) {
+    lbx[0][j]=lbx[1][j]=lbx[2][j]=lbx[3][j]    = lbx[4][j] =INF;
+    lin[0][j]=lin[1][j]=lin[2][j]=lin[3][j]    = lin[4][j] =INF;
+    lc[0][j] =lc[1][j] =lc[2][j] = lc[3][j]    =  lc[4][j] =INF;
+    lby[0][j]=lby[1][j]=lby[2][j]=lby[3][j]    = lby[4][j] =INF;
+    liny[0][j]=liny[1][j]=liny[2][j]=liny[3][j]=liny[4][j]=INF;
+    linx[0][j]=linx[1][j]=linx[2][j]=linx[3][j]=linx[4][j]=INF;
+  }
+  encode_seqs(s1,s2);
+  i=10;
+  i_length= n1 - 9 ;
+  while(i < i_length) {
+    int idx=i%5;
+    int idx_1=(i-1)%5;
+    int idx_2=(i-2)%5;
+    int idx_3=(i-3)%5;
+    int idx_4=(i-4)%5;
+    j=n2-9;
+    while (9 < --j) {
+      int bonus_2 = (structure[j-1]=='|' ? bonus : 0) ;
+      int type, type2; 
+      type = pair[S1[i]][S2[j]];
+      lc[idx][j]=type ? P->DuplexInit + 2*extension_cost + bonus_2 : INF; /* to avoid that previous value influence result should actually not be erforderlich */
+      if(!bonus_2){
+        type2=pair[S2[j+1]][S1[i-1]];
+        lin[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatchI[type2][SS2[j]][SS1[i]]+iopen+iext_s, lin[idx_1][j]+iext_ass);
+        lin[idx][j]=MIN2(lin[idx][j],lin[idx][j+1]+iext_ass);
+        lin[idx][j]=MIN2(lin[idx][j],lin[idx_1][j+1]+iext_s);
+        linx[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatch1nI[type2][SS2[j]][SS1[i]]+iopen+iext_s,linx[idx_1][j]+iext_ass);
+        liny[idx][j]=MIN2(lc[idx_1][j+1]+P->mismatch1nI[type2][SS2[j]][SS1[i]]+iopen+iext_s,liny[idx][j+1]+iext_ass); 
+        type2=pair[S2[j+1]][S1[i]];
+        lby[idx][j]=MIN2(lby[idx][j+1]+bext, lc[idx][j+1]+bopen+bext+(type2>2?P->TerminalAU:0));
+      }
+      else{
+        lin[idx][j] = lby[idx][j] = linx[idx][j]= liny[idx][j]=INF;
+      }
+      type2=pair[S2[j]][S1[i-1]];
+      lbx[idx][j]=MIN2(lbx[idx_1][j]+bext, lc[idx_1][j]+bopen+bext+(type2>2?P->TerminalAU:0));
+      /* --------------------------------------------------------------- end update recursion */
+      if(!type){continue;}
+      if(!(structure[j]=='|')){
+        lc[idx][j]+=P->mismatchExt[type][SS1[i-1]][SS2[j+1]]+2*extension_cost;
+      }
+      else{
+        lc[idx][j]+=P->dangle5[type][SS1[i-1]]+extension_cost;
+      }
+      lc[idx][j]+=(type>2?P->TerminalAU:0);
+      /* type > 2 -> no GC or CG pair */
+      /* ------------------------------------------------------------------update c  matrix  */
+      /*  Be careful, no lc may come from a region where a "|" is in a loop, avoided in lin = lby = INF ... jedoch fuer klein loops muss man aufpassen .. */
+      type2=pair[S1[i-1]][S2[j+1]];
+      lc[idx][j]=MIN2(lc[idx_1][j+1]+E_IntLoop(0,0,type2, rtype[type],SS1[i], SS2[j], SS1[i-1], SS2[j+1], P)+2*extension_cost, lc[idx][j]);
+      type2=pair[S1[i-2]][S2[j+1]];
+      lc[idx][j]=MIN2(lc[idx_2][j+1]+E_IntLoop(1,0,type2, rtype[type],SS1[i-1], SS2[j], SS1[i-1], SS2[j+1], P)+3*extension_cost,lc[idx][j]);
+      /* kleine loops checks wird in den folgenden if test gemacht. */
+      if(!(structure[j]=='|')){
+        type2=pair[S1[i-1]][S2[j+2]];
+        lc[idx][j]=MIN2(lc[idx_1][j+2]+E_IntLoop(0,1,type2, rtype[type],SS1[i], SS2[j+1], SS1[i-1], SS2[j+1], P)+3*extension_cost,lc[idx][j]);
+        type2=pair[S1[i-2]][S2[j+2]];
+        lc[idx][j]=MIN2(lc[idx_2][j+2]+E_IntLoop(1,1,type2, rtype[type],SS1[i-1], SS2[j+1], SS1[i-1], SS2[j+1], P)+4*extension_cost, lc[idx][j]);
+        type2 = pair[S1[i-3]][S2[j+2]];
+        lc[idx][j]=MIN2(lc[idx_3][j+2]+E_IntLoop(2,1,type2, rtype[type],SS1[i-2], SS2[j+1], SS1[i-1], SS2[j+1], P)+5*extension_cost, lc[idx][j]);
+        if(!(structure[j+1]=='|')){
+          type2 = pair[S1[i-3]][S2[j+3]];
+          lc[idx][j]=MIN2(lc[idx_3][j+3]+E_IntLoop(2,2,type2, rtype[type],SS1[i-2], SS2[j+2], SS1[i-1], SS2[j+1], P)+6*extension_cost,lc[idx][j]);
+          type2 = pair[S1[i-2]][S2[j+3]];
+          lc[idx][j]=MIN2(lc[idx_2][j+3]+E_IntLoop(1,2,type2, rtype[type],SS1[i-1], SS2[j+2], SS1[i-1], SS2[j+1], P)+5*extension_cost, lc[idx][j]);
+          type2 = pair[S1[i-4]][S2[j+3]];
+          lc[idx][j]=MIN2(lc[idx_4][j+3]+E_IntLoop(3,2,type2, rtype[type],SS1[i-3], SS2[j+2], SS1[i-1], SS2[j+1], P)+7*extension_cost, lc[idx][j]);
+          if(!(structure[j+2]=='|')){
+            type2 = pair[S1[i-3]][S2[j+4]];
+            lc[idx][j]=MIN2(lc[idx_3][j+4]+E_IntLoop(2,3,type2, rtype[type],SS1[i-2], SS2[j+3], SS1[i-1], SS2[j+1], P)+7*extension_cost, lc[idx][j]);
+          }
+        }
+      }
+      /* internal->stack  */
+      lc[idx][j]=MIN2(lin[idx_3][j+3]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+2*extension_cost+2*iext_s, lc[idx][j]);
+      lc[idx][j]=MIN2(lin[idx_4][j+2]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_s+2*iext_ass+2*extension_cost, lc[idx][j]);
+      lc[idx][j]=MIN2(lin[idx_2][j+4]+P->mismatchI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_s+2*iext_ass+2*extension_cost, lc[idx][j]);
+      lc[idx][j]=MIN2(linx[idx_3][j+1]+P->mismatch1nI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_ass+iext_ass+2*extension_cost, lc[idx][j]);
+      lc[idx][j]=MIN2(liny[idx_1][j+3]+P->mismatch1nI[rtype[type]][SS1[i-1]][SS2[j+1]]+iext_ass+iext_ass+2*extension_cost, lc[idx][j]);
+      /* bulge -> stack */
+      int bAU;
+      bAU=(type>2?P->TerminalAU:0);
+      lc[idx][j]=MIN2(lbx[idx_2][j+1]+2*extension_cost+bext+bAU, lc[idx][j]);
+      /* min2=by[i][j+1]; */
+      lc[idx][j]=MIN2(lby[idx_1][j+2]+2*extension_cost+bext+bAU, lc[idx][j]);
+      lc[idx][j]+=bonus_2;
+      /*       if(j<=const5end){ */
+      temp=min_colonne;        
+      min_colonne=MIN2(lc[idx][j]+(type>2?P->TerminalAU:0)+
+                       (!(structure[j-2]=='|') ? 
+                        P->mismatchExt[rtype[type]][SS2[j-1]][SS1[i+1]]+2*extension_cost : 
+                        P->dangle3[rtype[type]][SS1[i+1]]+extension_cost),
+                       min_colonne);
+      if(temp>min_colonne){
+        min_j_colonne=j;
+        /*         } */
+      }
+      /* ---------------------------------------------------------------------end update       */
+    }
+    if(max>=min_colonne){
+      max=min_colonne;
+      max_pos=i;
+      max_pos_j=min_j_colonne;
+    } 
+    position[i+delta]=min_colonne;min_colonne=INF;
+    position_j[i+delta]=min_j_colonne;
+    i++;
+  }  
+  free(S1); free(S2); free(SS1); free(SS2);  
+  /* printf("MAX: %d",max); */
+  if(max<threshold+constthreshold){
+    find_max_C(position, position_j, delta, threshold+constthreshold, constthreshold, alignment_length, s1, s2, extension_cost, fast, structure);
+  }
+  if(max<constthreshold){
+    plot_max_C(max, max_pos, max_pos_j,alignment_length, s1, s2, extension_cost,fast,structure);
+  }
+  for (i=0; i<=4; i++) {free(lc[i]);free(lin[i]);free(lbx[i]);free(lby[i]);free(linx[i]);free(liny[i]);}
+  /*  free(lc[0]);free(lin[0]);free(lbx[0]);free(lby[0]); */
+  free(lc);free(lin);free(lbx);free(lby);free(linx);free(liny);
+  free(position);
+  free(position_j);
+  return NULL;
+}
+
+
+PRIVATE void find_max_C(const int *position, const int *position_j,const int delta, const int threshold, const int constthreshold, const int alignment_length, const char *s1, const char *s2, const int extension_cost, const int fast,const char* structure){
+  int pos=n1-9;
+  if(fast==1){
+    while(10 < pos--){
+      int temp_min=0;                                                               
+      if(position[pos+delta]<(threshold)){                                          
+        int search_range;                                                           
+        search_range=delta+1;                                                       
+        while(--search_range){                                                      
+          if(position[pos+delta-search_range]<=position[pos+delta-temp_min]){                
+            temp_min=search_range;                                                  
+          }                                                                         
+        }                                                                           
+        pos-=temp_min;                                                              
+        int max_pos_j;                                                              
+        max_pos_j=position_j[pos+delta];
+        int max;
+        max=position[pos+delta];
+        printf("target upper bound %d: query lower bound %d  (%5.2f) \n", pos-10, max_pos_j-10, ((double)max)/100);
+        pos=MAX2(10,pos-delta);
+      }
+    }
+  }
+  else{
+    pos=n1-9;
+    while(10 < pos--){
+      int temp_min=0;
+      if(position[pos+delta]<(threshold)){
+        int search_range;
+        search_range=delta+1;
+        while(--search_range){
+          if(position[pos+delta-search_range]<=position[pos+delta-temp_min]){
+            temp_min=search_range;
+          }
+        }
+        pos-=temp_min;
+        int max_pos_j;
+        max_pos_j=position_j[pos+delta];
+        /* max_pos_j und pos entsprechen die realen position
+           in der erweiterten sequenz. 
+           pos=1 -> position 1 in the sequence (and not 0 like in C)
+           max_pos_j -> position 1 in the sequence ( not 0 like in C)
+        */
+        int begin_t=MAX2(11, pos-alignment_length+1);
+        int end_t  =MIN2(n1-10, pos+1);
+        int begin_q=MAX2(11, max_pos_j-1);
+        int end_q  =MIN2(n2-10, max_pos_j+alignment_length-2);
+        char *s3 = (char*) space(sizeof(char)*(end_t - begin_t +2));
+        char *s4 = (char*) space(sizeof(char)*(end_q - begin_q +2));
+        char *local_structure = (char*) space(sizeof(char)*(end_q - begin_q +2));
+        strncpy(s3, (s1+begin_t-1),  end_t - begin_t +1);
+        strncpy(s4, (s2+begin_q-1) , end_q - begin_q +1);
+        strncpy(local_structure, (structure+begin_q-1) , end_q - begin_q +1 );
+        s3[end_t -begin_t +1 ]='\0';
+        s4[end_q -begin_q +1 ]='\0';
+        local_structure[end_q - begin_q +1]='\0';
+        duplexT test;
+        test = duplexfold_C(s3, s4, extension_cost,local_structure);
+        if(test.energy * 100 < (threshold-constthreshold)){
+          int l1=strchr(test.structure, '&')-test.structure;
+          int dL = strrchr(structure,'|') - strchr(structure,'|');
+          dL+=1;
+          if(dL <=  strlen(test.structure)-l1-1){
+            printf("%s %3d,%-3d : %3d,%-3d (%5.2f)\n", test.structure, 
+                   begin_t-10+test.i-l1, 
+                   begin_t-10+test.i-1, 
+                   begin_q-10 + test.j-1 , 
+                   (begin_q -11) + test.j + strlen(test.structure)-l1-2, 
+                   test.energy);
+            pos=MAX2(10,pos-delta);
+          }
+        }
+        free(s3);free(s4);
+        free(test.structure);
+        free(local_structure);
+      }
+    }
+  }
+}
+PRIVATE void plot_max_C(const int max, const int max_pos, const int max_pos_j, const int alignment_length, const char *s1, const char *s2, const int extension_cost, const int fast,const char* structure)
+{
+  if(fast==1){
+    printf("target upper bound %d: query lower bound %d (%5.2f)\n", max_pos-10, max_pos_j-10, ((double)max)/100);
+  }
+  else{
+    duplexT test;
+    int begin_t=MAX2(11, max_pos-alignment_length+1);
+    int end_t  =MIN2(n1-10, max_pos+1);
+    int begin_q=MAX2(11, max_pos_j-1);
+    int end_q  =MIN2(n2-10, max_pos_j+alignment_length-2);
+    char *s3 = (char*) space(sizeof(char)*(end_t - begin_t +2));
+    char *s4 = (char*) space(sizeof(char)*(end_q - begin_q +2));
+    char *local_structure = (char*) space(sizeof(char)*(end_q - begin_q +2));
+    strncpy(s3, (s1+begin_t-1),  end_t - begin_t + 1);
+    strncpy(s4, (s2+begin_q-1) , end_q - begin_q +1 );
+    strncpy(local_structure, (structure+begin_q-1) , end_q - begin_q +1 );
+    s3[end_t -begin_t +1 ]='\0';
+    s4[end_q -begin_q +1 ]='\0';
+    local_structure[end_q - begin_q +1]='\0';
+    test = duplexfold_C(s3, s4, extension_cost,local_structure);
+    int l1=strchr(test.structure, '&')-test.structure;
+    int dL = strrchr(structure,'|') - strchr(structure,'|');
+    dL+=1;
+    if(dL <=  strlen(test.structure)-l1-1){
+      printf("%s %3d,%-3d : %3d,%-3d (%5.2f)\n", test.structure, 
+             begin_t-10+test.i-l1, begin_t-10+test.i-1, begin_q-10 +test.j-1 , 
+             (begin_q -11) + test.j + strlen(test.structure)-l1-2  , test.energy);
+      free(s3);free(s4);free(test.structure);
+    }
+    free(local_structure);
+  }
+}
+
+
+PRIVATE void update_dfold_params(void)
+{
+  if(P) free(P);
+  P = scale_parameters();
+  make_pair_matrix();
+}
+
+/*---------------------------------------------------------------------------*/
+
+
+PRIVATE void encode_seqs(const char *s1, const char *s2) {
+  unsigned int i,l;
+
+  l = strlen(s1);
+  S1 = encode_seq(s1);
+  SS1= (short *) space(sizeof(short)*(l+1));
+  /* SS1 exists only for the special X K and I bases and energy_set!=0 */
+  
+  for (i=1; i<=l; i++) { /* make numerical encoding of sequence */
+    SS1[i] = alias[S1[i]];   /* for mismatches of nostandard bases */
+  }
+
+  l = strlen(s2);
+  S2 = encode_seq(s2);
+  SS2= (short *) space(sizeof(short)*(l+1));
+  /* SS2 exists only for the special X K and I bases and energy_set!=0 */
+  
+  for (i=1; i<=l; i++) { /* make numerical encoding of sequence */
+    SS2[i] = alias[S2[i]];   /* for mismatches of nostandard bases */
+  }
+}
+
+
+PRIVATE short * encode_seq(const char *sequence) {
+  unsigned int i,l;
+  short *S;
+  l = strlen(sequence);
+  S = (short *) space(sizeof(short)*(l+2));
+  S[0] = (short) l;
+
+  /* make numerical encoding of sequence */
+  for (i=1; i<=l; i++)
+    S[i]= (short) encode_char(toupper(sequence[i-1]));
+
+  /* for circular folding add first base at position n+1 */
+  S[l+1] = S[1];
+
+  return S;
+}
+
+