WSTester updated to work plus hopefully all the other changes that need to go into...
[jabaws.git] / binaries / src / ViennaRNA / lib / Lfold.c
diff --git a/binaries/src/ViennaRNA/lib/Lfold.c b/binaries/src/ViennaRNA/lib/Lfold.c
new file mode 100644 (file)
index 0000000..ca8c5bd
--- /dev/null
@@ -0,0 +1,1239 @@
+/* Last changed Time-stamp: <2007-09-04 11:16:01 ivo> */
+/*
+                  minimum free energy
+                  RNA secondary structure prediction
+                  with maximum distance base pairs
+
+                  c Ivo Hofacker, Peter Stadler
+
+                  Vienna RNA package
+*/
+
+#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 "pair_mat.h"
+#include "params.h"
+#include "loop_energies.h"
+#include "gquad.h"
+#include "Lfold.h"
+
+#ifdef USE_SVM
+#include "svm.h"
+#include "svm_utils.h"
+#endif
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+#define PAREN
+
+#define STACK_BULGE1      1   /* stacking energies for bulges of size 1 */
+#define NEW_NINIO         1   /* new asymetry penalty */
+/*@unused@*/
+#define MAXSECTORS        500     /* dimension for a backtrack array */
+#define LOCALITY          0.      /* locality parameter for base-pairs */
+
+/*
+#################################
+# GLOBAL VARIABLES              #
+#################################
+*/
+
+/*
+#################################
+# PRIVATE VARIABLES             #
+#################################
+*/
+PRIVATE paramT        *P = NULL;
+PRIVATE int           **c = NULL;        /* energy array, given that i-j pair */
+PRIVATE int           *cc = NULL;        /* linear array for calculating canonical structures */
+PRIVATE int           *cc1 = NULL;       /*   "     "        */
+PRIVATE int           *f3 = NULL;        /* energy of 5' end */
+PRIVATE int           **fML = NULL;      /* multi-loop auxiliary energy array */
+PRIVATE int           *Fmi = NULL;       /* holds row i of fML (avoids jumps in memory) */
+PRIVATE int           *DMLi = NULL;      /* DMLi[j] holds MIN(fML[i,k]+fML[k+1,j])  */
+PRIVATE int           *DMLi1 = NULL;     /*             MIN(fML[i+1,k]+fML[k+1,j])  */
+PRIVATE int           *DMLi2 = NULL;     /*             MIN(fML[i+2,k]+fML[k+1,j])  */
+PRIVATE char          **ptype = NULL;    /* precomputed array of pair types */
+PRIVATE short         *S = NULL, *S1 = NULL;
+PRIVATE unsigned int  length;
+PRIVATE char          *prev = NULL;
+#ifdef USE_SVM
+PRIVATE struct svm_model  *avg_model = NULL;
+PRIVATE struct svm_model  *sd_model = NULL;
+#endif
+
+PRIVATE int           with_gquad  = 0;
+PRIVATE int           **ggg       = NULL;
+
+
+#ifdef _OPENMP
+
+#ifdef USE_SVM
+#pragma omp threadprivate(P, c, cc, cc1, f3, fML, Fmi, DMLi, DMLi1, DMLi2, ptype, S, S1, length, sd_model, avg_model, ggg, with_gquad)
+#else
+#pragma omp threadprivate(P, c, cc, cc1, f3, fML, Fmi, DMLi, DMLi1, DMLi2, ptype, S, S1, length, ggg, with_gquad)
+#endif
+
+#endif
+
+/*
+#################################
+# PRIVATE FUNCTION DECLARATIONS #
+#################################
+*/
+PRIVATE void  initialize_Lfold(int length, int maxdist);
+PRIVATE void  update_fold_params(void);
+PRIVATE void  get_arrays(unsigned int size, int maxdist);
+PRIVATE void  free_arrays(int maxdist);
+PRIVATE void  make_ptypes(const short *S, int i, int maxdist, int n);
+PRIVATE char  *backtrack(const char *sequence, int start, int maxdist);
+PRIVATE int   fill_arrays(const char *sequence, int maxdist, int zsc, double min_z);
+
+/*
+#################################
+# BEGIN OF FUNCTION DEFINITIONS #
+#################################
+*/
+
+/*--------------------------------------------------------------------------*/
+PRIVATE void initialize_Lfold(int length, int maxdist){
+
+  if (length<1) nrerror("initialize_Lfold: argument must be greater 0");
+  get_arrays((unsigned) length, maxdist);
+  update_fold_params();
+}
+
+/*--------------------------------------------------------------------------*/
+PRIVATE void get_arrays(unsigned int size, int maxdist){
+  int i;
+  c     = (int **)  space(sizeof(int *) *(size+1));
+  fML   = (int **)  space(sizeof(int *) *(size+1));
+  ptype = (char **) space(sizeof(char *)*(size+1));
+  f3    = (int *)   space(sizeof(int)   *(size+2));  /* has to be one longer */
+  cc    = (int *)   space(sizeof(int)   *(maxdist+5));
+  cc1   = (int *)   space(sizeof(int)   *(maxdist+5));
+  Fmi   = (int *)   space(sizeof(int)   *(maxdist+5));
+  DMLi  = (int *)   space(sizeof(int)   *(maxdist+5));
+  DMLi1 = (int *)   space(sizeof(int)   *(maxdist+5));
+  DMLi2 = (int *)   space(sizeof(int)   *(maxdist+5));
+
+  for (i=size; (i>(int)size-maxdist-5) && (i>=0); i--) {
+    c[i] = (int *) space(sizeof(int)*(maxdist+5));
+  }
+  for (i=size; (i>(int)size-maxdist-5) && (i>=0); i--) {
+    fML[i] = (int *) space(sizeof(int)*(maxdist+5));
+  }
+  for (i=size; (i>(int)size-maxdist-5) && (i>=0); i--) {
+    ptype[i] = (char *) space(sizeof(char)*(maxdist+5));
+  }
+}
+
+/*--------------------------------------------------------------------------*/
+
+PRIVATE void free_arrays(int maxdist){
+  int i;
+  for (i=0; (i<maxdist+5) && (i<=length); i++){
+    free(c[i]);
+    free(fML[i]);
+    free(ptype[i]);
+  }
+  free(c);
+  free(fML);
+  free(ptype);
+  free(f3);
+  free(cc);
+  free(cc1);
+  free(Fmi);
+  free(DMLi);
+  free(DMLi1);
+  free(DMLi2);
+
+  if(ggg){
+    for (i=0; (i<maxdist+5) && (i<=length); i++){
+      free(ggg[i]);
+    }
+    free(ggg);
+    ggg = NULL;
+  }
+
+  f3    = cc = cc1 = Fmi = DMLi = DMLi1 = DMLi2 = NULL;
+  c     = fML = NULL;
+  ptype = NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+
+PUBLIC  float Lfold(const char *string, char *structure, int maxdist){
+  return Lfoldz(string, structure, maxdist, 0, 0.0);
+}
+
+PUBLIC  float Lfoldz(const char *string, char *structure, int maxdist, int zsc, double min_z){
+  int i, energy;
+
+  length = (int) strlen(string);
+  if (maxdist>length) maxdist = length;
+  initialize_Lfold(length, maxdist);
+  if (fabs(P->temperature - temperature)>1e-6) update_fold_params();
+
+  with_gquad  = P->model_details.gquad;
+  S           = encode_sequence(string, 0);
+  S1          = encode_sequence(string, 1);
+
+  for (i=length; i>=(int)length-(int)maxdist-4 && i>0; i--)
+    make_ptypes(S, i, maxdist, length);
+
+#ifdef USE_SVM  /*svm*/
+  if(zsc){
+    avg_model = svm_load_model_string(avg_model_string);
+    sd_model  = svm_load_model_string(sd_model_string);
+  }
+#endif
+
+  energy = fill_arrays(string, maxdist, zsc, min_z);
+
+#ifdef USE_SVM  /*svm*/
+  if(zsc){
+    svm_destroy_model(avg_model);
+    svm_destroy_model(sd_model);
+  }
+#endif
+
+  free(S); free(S1);
+  free_arrays(maxdist);
+
+  return (float) energy/100.;
+}
+
+PRIVATE int fill_arrays(const char *string, int maxdist, int zsc, double min_z) {
+  /* fill "c", "fML" and "f3" arrays and return  optimal energy */
+
+  int   i, j, k, length, energy;
+  int   decomp, new_fML;
+  int   no_close, type, type_2, tt;
+  int   fij;
+  int   lind;
+
+  length = (int) strlen(string);
+  prev=NULL;
+  for (j=0; j<maxdist+5; j++)
+    Fmi[j]=DMLi[j]=DMLi1[j]=DMLi2[j]=INF;
+  for (j=length; j>length-maxdist-4; j--) {
+    for (i=(length-maxdist-4>0)?length-maxdist-4:1 ; i<j; i++)
+      c[i][j-i] = fML[i][j-i] = INF;
+  }
+
+  if(with_gquad){
+    ggg = NULL;
+    ggg = get_gquad_L_matrix(S, length - maxdist - 4, maxdist, ggg, P);
+  }
+
+  for (i = length-TURN-1; i >= 1; i--) { /* i,j in [1..length] */
+    for (j = i+TURN+1; j <= length && j <= i+maxdist; j++) {
+      int p, q;
+      type = ptype[i][j-i];
+
+      no_close = (((type==3)||(type==4))&&no_closingGU);
+
+      if (type) {   /* we have a pair */
+        int new_c=0, stackEnergy=INF;
+        /* hairpin ----------------------------------------------*/
+
+        new_c = (no_close) ? FORBIDDEN : E_Hairpin(j-i-1, type, S1[i+1], S1[j-1], string+i-1, P);
+
+        /*--------------------------------------------------------
+          check for elementary structures involving more than one
+          closing pair.
+          --------------------------------------------------------*/
+
+        for (p = i+1; p <= MIN2(j-2-TURN,i+MAXLOOP+1) ; p++){
+          int minq = j-i+p-MAXLOOP-2;
+          if (minq<p+1+TURN) minq = p+1+TURN;
+          for (q = minq; q < j; q++) {
+            type_2 = ptype[p][q-p];
+
+            if (type_2==0) continue;
+            type_2 = rtype[type_2];
+
+            if (no_closingGU)
+              if (no_close||(type_2==3)||(type_2==4))
+                if ((p>i+1)||(q<j-1)) continue;  /* continue unless stack */
+
+            energy = E_IntLoop(p-i-1, j-q-1, type, type_2, S1[i+1], S1[j-1], S1[p-1], S1[q+1],P);
+            new_c = MIN2(new_c, energy + c[p][q-p]);
+            if ((p==i+1)&&(j==q+1)) stackEnergy = energy; /* remember stack energy */
+          } /* end q-loop */
+        } /* end p-loop */
+
+        /* multi-loop decomposition ------------------------*/
+        if (!no_close) {
+          decomp  = DMLi1[j-1-(i+1)];
+          tt      = rtype[type];
+          switch(dangles){
+            /* no dangles */
+            case 0:   decomp += E_MLstem(tt, -1, -1, P);
+                      break;
+            /* double dangles */
+            case 2:   decomp += E_MLstem(tt, S1[j-1], S1[i+1], P);
+                      break;
+            /* normal dangles, aka dangles = 1 */
+            default:  decomp += E_MLstem(tt, -1, -1, P);
+                      decomp = MIN2(decomp, DMLi2[j-1-(i+2)] + E_MLstem(tt, -1, S1[i+1], P) + P->MLbase);
+                      decomp = MIN2(decomp, DMLi2[j-2-(i+2)] + E_MLstem(tt, S1[j-1], S1[i+1], P) + 2*P->MLbase);
+                      decomp = MIN2(decomp, DMLi1[j-2-(i+1)] + E_MLstem(tt, S1[j-1], -1, P) + P->MLbase);
+                      break;
+          }
+          new_c = MIN2(new_c, decomp + P->MLclosing);
+        }
+
+        /* coaxial stacking of (i.j) with (i+1.k) or (k+1.j-1) */
+
+        if (dangles==3) {
+          decomp = INF;
+          for (k = i+2+TURN; k < j-2-TURN; k++) {
+            type_2 = ptype[i+1][k-i-1]; type_2 = rtype[type_2];
+            if (type_2)
+              decomp = MIN2(decomp, c[i+1][k-i-1]+P->stack[type][type_2]+
+                            fML[k+1][j-1-k-1]);
+            type_2 = ptype[k+1][j-1-k-1]; type_2 = rtype[type_2];
+            if (type_2)
+              decomp = MIN2(decomp, c[k+1][j-1-k-1]+P->stack[type][type_2]+
+                            fML[i+1][k-i-1]);
+          }
+          /* no TermAU penalty if coax stack */
+          decomp += 2*P->MLintern[1] + P->MLclosing;
+          new_c = MIN2(new_c, decomp);
+        }
+
+        if(with_gquad){
+          /* include all cases where a g-quadruplex may be enclosed by base pair (i,j) */
+          if (!no_close) {
+            tt = rtype[type];
+            energy = E_GQuad_IntLoop_L(i, j, type, S1, ggg, maxdist, P);
+            new_c = MIN2(new_c, energy);
+          }
+        }
+
+        new_c = MIN2(new_c, cc1[j-1-(i+1)]+stackEnergy);
+        cc[j-i] = new_c;
+        if (noLonelyPairs)
+          c[i][j-i] = cc1[j-1-(i+1)]+stackEnergy;
+        else
+          c[i][j-i] = cc[j-i];
+
+      } /* end >> if (pair) << */
+
+      else c[i][j-i] = INF;
+
+      /* done with c[i,j], now compute fML[i,j] */
+      /* free ends ? -----------------------------------------*/
+      new_fML = INF;
+      switch(dangles){
+        /* no dangles */
+        case 0:   new_fML = fML[i+1][j-i-1] + P->MLbase;
+                  new_fML = MIN2(new_fML, fML[i][j-1-i] + P->MLbase);
+                  new_fML = MIN2(new_fML, c[i][j-i] + E_MLstem(type, -1, -1, P));
+                  break;
+        /* double dangles */
+        case 2:   new_fML = fML[i+1][j-i-1] + P->MLbase;
+                  new_fML = MIN2(fML[i][j-1-i] + P->MLbase, new_fML);
+                  new_fML = MIN2(new_fML,  c[i][j-i] + E_MLstem(type, (i>1) ? S1[i-1] : -1, (j<length) ? S1[j+1] : -1, P));
+                  break;
+        /* normal dangles, aka dangles = 1 */
+        default:  /* i unpaired */
+                  new_fML = fML[i+1][j-i-1] + P->MLbase;
+                  /* j unpaired */
+                  new_fML = MIN2(new_fML, fML[i][j-1-i] + P->MLbase);
+                  /* i,j */
+                  if(type) new_fML = MIN2(new_fML, c[i][j-i] + E_MLstem(type, -1, -1, P));
+                  /* i+1,j */
+                  tt = ptype[i+1][j-i-1];
+                  if(tt) new_fML = MIN2(new_fML, c[i+1][j-i-1] + E_MLstem(tt, S1[i], -1, P) + P->MLbase);
+                  /* i, j-1 */
+                  tt = ptype[i][j-1-i];
+                  if(tt) new_fML = MIN2(new_fML, c[i][j-1-i] + E_MLstem(tt, -1, S1[j], P) + P->MLbase);
+                  /* i+1,j-1 */
+                  tt = ptype[i+1][j-1-i-1];
+                  if(tt) new_fML = MIN2(new_fML, c[i+1][j-1-i-1] + E_MLstem(tt, S1[i], S1[j], P) + 2*P->MLbase);
+                  break;
+      }
+
+      if(with_gquad){
+        new_fML = MIN2(new_fML, ggg[i][j - i] + E_MLstem(0, -1, -1, P));
+      }
+
+      /* modular decomposition -------------------------------*/
+      for (decomp = INF, k = i+1+TURN; k <= j-2-TURN; k++)
+        decomp = MIN2(decomp, Fmi[k-i]+fML[k+1][j-k-1]);
+
+      DMLi[j-i] = decomp;               /* store for use in ML decompositon */
+      new_fML   = MIN2(new_fML, decomp);
+
+      /* coaxial stacking */
+      if (dangles==3) {
+        /* additional ML decomposition as two coaxially stacked helices */
+        for (decomp = INF, k = i+1+TURN; k <= j-2-TURN; k++) {
+          type = ptype[i][k-i]; type = rtype[type];
+          type_2 = ptype[k+1][j-k-1]; type_2 = rtype[type_2];
+          if (type && type_2)
+            decomp = MIN2(decomp,
+                          c[i][k-i]+c[k+1][j-k-1]+P->stack[type][type_2]);
+        }
+
+        decomp += 2*P->MLintern[1];          /* no TermAU penalty if coax stack */
+#if 0
+        /* This is needed for Y shaped ML loops with coax stacking of
+           interior pairts, but backtracking will fail if activated */
+        DMLi[j-i] = MIN2(DMLi[j-i], decomp);
+        DMLi[j-i] = MIN2(DMLi[j-i], DMLi[j-1-i]+P->MLbase);
+        DMLi[j-i] = MIN2(DMLi[j-i], DMLi1[j-(i+1)]+P->MLbase);
+        new_fML = MIN2(new_fML, DMLi[j-i]);
+#endif
+        new_fML = MIN2(new_fML, decomp);
+      }
+      fML[i][j-i] = Fmi[j-i] = new_fML;     /* substring energy */
+    } /* for (j...) */
+
+    /* calculate energies of 5' and 3' fragments */
+    {
+      static int do_backtrack = 0, prev_i=0;
+      char *ss=NULL;
+      double prevz;
+      f3[i] = f3[i+1];
+      switch(dangles){
+        /* dont use dangling end and mismatch contributions at all */
+        case 0:   for(j=i+TURN+1; j<length && j<=i+maxdist; j++){
+                    type = ptype[i][j-i];
+
+                    if(with_gquad){
+                      f3[i] = MIN2(f3[i], f3[j+1] + ggg[i][j-i]);
+                    }
+
+                    if(type)
+                      f3[i] = MIN2(f3[i], f3[j+1] + c[i][j-i] + E_ExtLoop(type, -1, -1, P));
+                  }
+                  if(length<=i+maxdist){
+                    j=length;
+
+                    if(with_gquad){
+                      f3[i] = MIN2(f3[i], ggg[i][j-i]);
+                    }
+
+                    type = ptype[i][j-i];
+                    if(type)
+                      f3[i] = MIN2(f3[i], c[i][j-i] + E_ExtLoop(type, -1, -1, P));
+                  }
+                  break;
+        /* always use dangles on both sides */
+        case 2:   for(j=i+TURN+1; j<length && j<=i+maxdist; j++){
+                    type = ptype[i][j-i];
+
+                    if(with_gquad){
+                      if(ggg[i][j-i] != INF)
+                        f3[i] = MIN2(f3[i], f3[j+1] + ggg[i][j-i]);
+                    }
+
+                    if(type)
+                      f3[i] = MIN2(f3[i], f3[j+1] + c[i][j-i] + E_ExtLoop(type, (i>1) ? S1[i-1] : -1, S1[j+1], P));
+                  }
+                  if(length<=i+maxdist){
+                    j=length;
+
+                    if(with_gquad){
+                      f3[i] = MIN2(f3[i], ggg[i][j-i]);
+                    }
+
+                    type = ptype[i][j-i];
+                    if(type)
+                      f3[i] = MIN2(f3[i], c[i][j-i] + E_ExtLoop(type, (i>1) ? S1[i-1] : -1, -1, P));
+                  }
+                  break;
+        /* normal dangles, aka dangles = 1 */
+        default:  for(j=i+TURN+1; j<length && j<=i+maxdist; j++){
+                    type = ptype[i][j-i];
+
+                    if(with_gquad){
+                      f3[i] = MIN2(f3[i], f3[j+1] + ggg[i][j-i]);
+                    }
+
+                    if(type){
+                      f3[i] = MIN2(f3[i], f3[j+1] + c[i][j-i] + E_ExtLoop(type, -1, -1, P));
+                      f3[i] = MIN2(f3[i], ((j+2<=length) ? f3[j+2] : 0) + c[i][j-i] + E_ExtLoop(type, -1, S1[j+1], P));
+                    }
+                    type = ptype[i+1][j-i-1];
+                    if(type){
+                      f3[i] = MIN2(f3[i], f3[j+1] + c[i+1][j-i-1] + E_ExtLoop(type, S1[i], -1, P));
+                      f3[i] = MIN2(f3[i], ((j + 1 < length) ? f3[j+2] : 0) + c[i+1][j-i-1] + E_ExtLoop(type, S1[i], S1[j+1], P));
+                    }
+                  }
+                  if(length<=i+maxdist){
+                    j     = length;
+
+                    if(with_gquad){
+                      f3[i] = MIN2(f3[i], ggg[i][j-i]);
+                    }
+
+                    type  = ptype[i][j-i];
+                    if(type)
+                      f3[i] = MIN2(f3[i], c[i][j-i] + E_ExtLoop(type, -1, -1, P));
+                    type  = ptype[i+1][j-i-1];
+                    if(type)
+                      f3[i] = MIN2(f3[i], c[i+1][j-i-1] + E_ExtLoop(type, S1[i], -1, P));
+                  }
+                  break;
+      } /* switch(dangles)... */
+
+      /* backtrack partial structure */
+      if (f3[i] < f3[i+1]) do_backtrack=1;
+      else if (do_backtrack) {
+        int pairpartner; /*i+1?? is paired with pairpartner*/
+        int cc;
+        int traced2=0;
+        fij = f3[i+1];
+        lind=i+1;
+
+        /*start "short" backtrack*/
+
+        /*get paired base*/
+        while(fij==f3[lind+1]) lind++;
+
+        /*get pairpartner*/
+        for (pairpartner = lind + TURN; pairpartner <= lind + maxdist; pairpartner++){
+          type = ptype[lind][pairpartner-lind];
+          switch(dangles){
+            case 0:   if(type){
+                        cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, -1, P);
+                        if(fij == cc + f3[pairpartner + 1])
+                          traced2 = 1;
+                      }
+                      else if(with_gquad) {
+                        cc = ggg[lind][pairpartner-lind];
+                        if(fij == cc + f3[pairpartner + 1])
+                          traced2 = 1;
+                      }
+
+                      break;
+            case 2:   if(type){
+                        cc = c[lind][pairpartner-lind] + E_ExtLoop(type, (lind > 1) ? S1[lind-1] : -1, (pairpartner < length) ? S1[pairpartner+1] : -1, P);
+                        if(fij == cc + f3[pairpartner + 1])
+                          traced2 = 1;
+                      }
+                      else if(with_gquad){
+                        cc = ggg[lind][pairpartner-lind];
+                        if(fij == cc + f3[pairpartner + 1])
+                          traced2 = 1;
+                      }
+
+                      break;
+            default:  if(type){
+                        cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, -1, P);
+                        if(fij == cc + f3[pairpartner + 1]){
+                          traced2 = 1;
+                          break;
+                        }
+                        else if(pairpartner < length){
+                          cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, S1[pairpartner+1], P);
+                          if(fij == cc + f3[pairpartner + 2]){
+                            traced2 = 1;
+                            break;
+                          }
+                        }
+                      }
+                      else if(with_gquad){
+                        cc = ggg[lind][pairpartner-lind];
+                        if(fij == cc + f3[pairpartner + 1])
+                          traced2 = 1;
+                      }
+
+                      type = ptype[lind+1][pairpartner-lind-1];
+                      if(type){
+                        cc = c[lind+1][pairpartner-(lind+1)] + E_ExtLoop(type, S1[lind], -1, P);
+                        if(fij == cc + f3[pairpartner+1]){
+                          traced2 = 1;
+                          break;
+                        }
+                        else if(pairpartner < length){
+                          cc = c[lind+1][pairpartner-(lind+1)] + E_ExtLoop(type, S1[lind], S1[pairpartner+1], P);
+                          if(fij == cc + f3[pairpartner+2])
+                            traced2 = 1;
+                        }
+                      }
+                      break;
+          }
+          if(traced2) break;
+        }
+        if (!traced2) nrerror("backtrack failed in short backtrack 1");
+        if (zsc){
+#ifdef USE_SVM
+          int info_avg;
+          double average_free_energy;
+          double sd_free_energy;
+          double my_z;
+          int *AUGC = get_seq_composition(S, lind-1, MIN2((pairpartner+1),length));
+          /*\svm*/
+          average_free_energy = avg_regression(AUGC[0], AUGC[1], AUGC[2], AUGC[3], AUGC[4], avg_model, &info_avg);
+          if (info_avg == 0)  {
+            double difference;
+            double min_sd = minimal_sd(AUGC[0],AUGC[1],AUGC[2],AUGC[3],AUGC[4]);
+            difference=(fij-f3[pairpartner+1])/100.-average_free_energy;
+            if ( difference - ( min_z * min_sd ) <= 0.0001 ) {
+              sd_free_energy = sd_regression(AUGC[0],AUGC[1],AUGC[2],AUGC[3],AUGC[4],sd_model);
+              my_z=difference/sd_free_energy;
+              if (my_z<=min_z){
+                ss =  backtrack(string, lind , pairpartner+1);
+                if (prev) {
+                  if ((i+strlen(ss)<prev_i+strlen(prev)) ||
+                      strncmp(ss+prev_i-i,prev,strlen(prev))) { /* ss does not contain prev */
+                    if (dangles==2)
+                      printf(".%s (%6.2f) %4d z= %.3f\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)-1])/100., prev_i-1, prevz);
+                    else
+                      printf("%s (%6.2f) %4d z=%.3f\n ", prev, (f3[prev_i]-f3[prev_i+strlen(prev)])/100., prev_i, prevz);
+                  }
+                  free(prev);
+                }
+                prev=ss; prev_i = lind; prevz=my_z;
+              }
+            }
+
+          }
+          free(AUGC);
+          do_backtrack=0;
+#endif
+        }
+        else {
+          /* original code for Lfold*/
+          ss =  backtrack(string, lind , pairpartner+1);
+          if (prev) {
+            if ((i+strlen(ss)<prev_i+strlen(prev)) || strncmp(ss+prev_i-i,prev,strlen(prev))){
+              /* ss does not contain prev */
+              if (dangles==2)
+                printf(".%s (%6.2f) %4d\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)-1])/100., prev_i-1);
+              else
+                printf("%s (%6.2f) %4d\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)])/100., prev_i);
+            }
+            free(prev);
+          }
+          prev=ss;
+          prev_i = lind;
+          do_backtrack=0;
+        }
+      }
+      if (i==1) {
+        if (prev) {
+          if(zsc) {
+            if (dangles==2)
+              printf(".%s (%6.2f) %4d z= %.2f\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)-1])/100., prev_i-1, prevz);
+           else
+              printf("%s (%6.2f) %4dz= %.2f \n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)])/100., prev_i, prevz);
+            free(prev); prev=NULL;
+          }
+          else {
+            if (dangles==2)
+              printf(".%s (%6.2f) %4d\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)-1])/100., prev_i-1);
+            else
+              printf("%s (%6.2f) %4d\n", prev, (f3[prev_i]-f3[prev_i+strlen(prev)])/100., prev_i);
+          }
+        } else if (f3[i]<0)do_backtrack=1;
+
+        if (do_backtrack) {
+          int pairpartner; /*i+1?? is paired with pairpartner*/
+          int cc;
+          double average_free_energy;
+          double sd_free_energy;
+          int info_avg;
+          double my_z;
+          int traced2 = 0;
+          fij = f3[i];
+          lind=i;
+          while(fij==f3[lind+1]) lind++;
+          /*get pairpartner*/
+          for(pairpartner = lind + TURN; pairpartner <= lind + maxdist; pairpartner++){
+            type = ptype[lind][pairpartner-lind];
+            switch(dangles){
+              case 0:   if(type){
+                          cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, -1, P);
+                          if(fij == cc + f3[pairpartner + 1])
+                            traced2 = 1;
+                        }
+                        else if(with_gquad){
+                          cc = ggg[lind][pairpartner-lind];
+                          if(fij == cc + f3[pairpartner + 1])
+                            traced2 = 1;
+                        }
+
+                        break;
+              case 2:   if(type){
+                          cc = c[lind][pairpartner-lind] + E_ExtLoop(type, (lind > 1) ? S1[lind-1] : -1, (pairpartner < length) ? S1[pairpartner+1] : -1, P);
+                          if(fij == cc + f3[pairpartner + 1])
+                            traced2 = 1;
+                        }
+                        else if(with_gquad){
+                          cc = ggg[lind][pairpartner-lind];
+                          if(fij == cc + f3[pairpartner + 1])
+                            traced2 = 1;
+                        }
+
+                        break;
+              default:  if(type){
+                          cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, -1, P);
+                          if(fij == cc + f3[pairpartner + 1]){
+                            traced2 = 1;
+                            break;
+                          }
+                          else if(pairpartner < length){
+                            cc = c[lind][pairpartner-lind] + E_ExtLoop(type, -1, S1[pairpartner + 1], P);
+                            if(fij == cc + f3[pairpartner + 1]){
+                              traced2 = 1;
+                              break;
+                            }
+                          }
+                        }
+                        else if(with_gquad){
+                          cc = ggg[lind][pairpartner-lind];
+                          if(fij == cc + f3[pairpartner + 1])
+                            traced2 = 1;
+                        }
+
+                        type = ptype[lind+1][pairpartner-lind-1];
+                        if(type){
+                          cc = c[lind+1][pairpartner-(lind+1)] + E_ExtLoop(type, S1[lind], -1, P);
+                          if(fij == cc + f3[pairpartner+1]){
+                            traced2 = 1;
+                            break;
+                          }
+                          else if (pairpartner < length){
+                            cc = c[lind+1][pairpartner-(lind+1)] + E_ExtLoop(type, S1[lind], S1[pairpartner+1], P);
+                            if(fij == cc + f3[pairpartner + 2]){
+                              traced2 =1;
+                              break;
+                            }
+                          }
+                        }
+            }
+            if(traced2) break;
+          }
+          if (!traced2) nrerror("backtrack failed in short backtrack 2");
+
+          if(zsc){
+#ifdef USE_SVM
+            int *AUGC = get_seq_composition(S, lind-1, MIN2((pairpartner+1),length));
+            average_free_energy = avg_regression(AUGC[0],AUGC[1],AUGC[2],AUGC[3],AUGC[4],avg_model,&info_avg);
+            if (info_avg == 0)  {
+              double difference;
+              double min_sd = minimal_sd(AUGC[0],AUGC[1],AUGC[2],AUGC[3],AUGC[4]);
+              difference=(fij-f3[pairpartner+1])/100.-average_free_energy;
+              if ( difference - ( min_z * min_sd ) <= 0.0001 ) {
+                sd_free_energy = sd_regression(AUGC[0],AUGC[1],AUGC[2],AUGC[3],AUGC[4],sd_model);
+                my_z=difference/sd_free_energy;
+                if (my_z<=min_z){
+                  ss =  backtrack(string, lind , pairpartner+1);
+                  printf("%s (%6.2f) %4d z= %.2f\n", ss, (f3[lind]-f3[lind+strlen(ss)-1])/100., lind, my_z);
+                }
+              }
+            }
+            free(AUGC);
+#endif
+          }
+          else {
+            ss =  backtrack(string, lind , pairpartner+1);
+            if (dangles==2)
+              printf("%s (%6.2f) %4d\n", ss, (f3[lind]-f3[lind+strlen(ss)-1])/100., 1);
+            else
+              printf("%s (%6.2f) %4d\n", ss, (f3[lind]-f3[lind+strlen(ss)])/100., 1);
+            free(ss);
+          }
+        }
+        do_backtrack=0;
+      }
+    }
+    {
+      int ii, *FF; /* rotate the auxilliary arrays */
+      FF = DMLi2; DMLi2 = DMLi1; DMLi1 = DMLi; DMLi = FF;
+      FF = cc1; cc1=cc; cc=FF;
+      for (j=0; j< maxdist+5; j++) {cc[j]=Fmi[j]=DMLi[j]=INF; }
+      if (i+maxdist+4<=length) {
+        c[i-1] = c[i+maxdist+4]; c[i+maxdist+4] = NULL;
+        fML[i-1] = fML[i+maxdist+4]; fML[i+maxdist+4]=NULL;
+        ptype[i-1] = ptype[i+maxdist+4]; ptype[i+maxdist+4] = NULL;
+        if (i>1){
+          make_ptypes(S, i-1, maxdist, length);
+
+          if(with_gquad){
+            ggg = get_gquad_L_matrix(S, i - 1, maxdist, ggg, P);
+          }
+        }
+        for (ii=0; ii<maxdist+5; ii++) {
+          c[i-1][ii] = INF;
+          fML[i-1][ii] = INF;
+        }
+      }
+    }
+  }
+
+  return f3[1];
+}
+
+PRIVATE char *backtrack(const char *string, int start, int maxdist){
+  /*------------------------------------------------------------------
+    trace back through the "c", "f3" and "fML" arrays to get the
+    base pairing list. No search for equivalent structures is done.
+    This is fast, since only few structure elements are recalculated.
+    ------------------------------------------------------------------*/
+  sect  sector[MAXSECTORS];   /* backtracking sectors */
+  int   i, j, k, energy, new, no_close, type, type_2, tt, s=0;
+  char  *structure;
+
+  /* length = strlen(string); */
+  sector[++s].i = start;
+  sector[s].j   = MIN2(length, maxdist+1);
+  sector[s].ml  = (backtrack_type=='M') ? 1 : ((backtrack_type=='C')?2:0);
+
+  structure = (char *) space((MIN2(length-start, maxdist)+3)*sizeof(char));
+  for (i=0; i<=MIN2(length-start, maxdist); i++) structure[i] = '-';
+
+  while (s>0) {
+    int ml, fij, cij, traced, i1, j1, d3, d5, mm, mm5, mm3, mm53, p, q, jj=0, gq=0;
+    int canonical = 1;     /* (i,j) closes a canonical structure */
+    i  = sector[s].i;
+    j  = sector[s].j;
+    ml = sector[s--].ml;   /* ml is a flag indicating if backtracking is to
+                              occur in the fML- (1) or in the f-array (0) */
+    if (ml==2) {
+      structure[i-start] = '(';
+      structure[j-start] = ')';
+      goto repeat1;
+    }
+
+    if (j < i+TURN+1) continue; /* no more pairs in this interval */
+
+    fij = (ml)? fML[i][j-i] : f3[i];
+
+    if (ml == 0) { /* backtrack in f3 */
+
+      if (fij == f3[i+1]) {
+        sector[++s].i = i+1;
+        sector[s].j   = j;
+        sector[s].ml  = ml;
+        continue;
+      }
+      /* i or i+1 is paired. Find pairing partner */
+      switch(dangles){
+        case 0:   for(traced = 0, k=j; k>i+TURN; k--){
+
+                    if(with_gquad){
+                      if(fij == ggg[i][k-i] + f3[k+1]){
+                        /* found the decomposition */
+                        traced = i; jj = k + 1; gq = 1;
+                        break;
+                      }
+                    }
+
+                    jj    = k+1;
+                    type  = ptype[i][k-i];
+                    if(type)
+                      if(fij == c[i][k-i] + E_ExtLoop(type, -1, -1, P) + f3[k+1]){
+                        traced = i;
+                        break;
+                      }
+                  }
+                  break;
+        case 2:   for(traced = 0, k=j; k>i+TURN; k--){
+
+                    if(with_gquad){
+                      if(fij == ggg[i][k-i] + f3[k+1]){
+                        /* found the decomposition */
+                        traced = i; jj = k + 1; gq = 1;
+                        break;
+                      }
+                    }
+
+                    jj    = k+1;
+                    type  = ptype[i][k-i];
+                    if(type)
+                      if(fij == c[i][k-i] + E_ExtLoop(type, (i>1) ? S1[i-1] : -1, (k<length) ? S1[k+1] : -1, P) + f3[k+1]){
+                        traced = i;
+                        break;
+                      }
+                  }
+                  break;
+        default:  for(traced = 0,k=j; k>i+TURN; k--){
+
+                    if(with_gquad){
+                      if(fij == ggg[i][k-i] + f3[k+1]){
+                        /* found the decomposition */
+                        traced = i; jj = k + 1; gq = 1;
+                        break;
+                      }
+                    }
+
+                    jj = k+1;
+                    type = ptype[i+1][k-(i+1)];
+                    if(type){
+                      if(fij == c[i+1][k-(i+1)] + E_ExtLoop(type, S1[i], -1, P) + f3[k+1]){
+                        traced=i+1;
+                      }
+                      if(k < length){
+                        if(fij == c[i+1][k-(i+1)] + E_ExtLoop(type, S1[i], S1[k+1], P) + f3[k+2]){
+                          traced  = i+1;
+                          jj      = k+2;
+                        }
+                      }
+                    }
+                    type = ptype[i][k-i];
+                    if(type){
+                      if(fij == c[i][k-i] + E_ExtLoop(type, -1, -1, P) + f3[k+1]){
+                        traced = i;
+                      }
+                      if(k<length){
+                        if(fij == c[i][k-i] + E_ExtLoop(type, -1, S1[k+1], P) + f3[k+2]){
+                          traced  = i;
+                          jj      = k+2;
+                        }
+                      }
+                    }
+                    if(traced) break;
+                  }
+                  break;
+      } /* switch(dangles)...*/
+
+      if (!traced) nrerror("backtrack failed in f3");
+      if (j==length) { /* backtrack only one component, unless j==length */
+        sector[++s].i = jj;
+        sector[s].j   = j;
+        sector[s].ml  = ml;
+      }
+      i=traced; j=k;
+
+      if(with_gquad && gq){
+        /* goto backtrace of gquadruplex */
+        goto repeat_gquad;
+      }
+
+      structure[i-start] = '('; structure[j-start] = ')';
+      if (((jj==j+2) || (dangles==2)) && (j < length)) structure[j+1-start] = '.';
+      goto repeat1;
+    }
+    else { /* trace back in fML array */
+      if (fML[i][j-1-i]+P->MLbase == fij) {  /* 3' end is unpaired */
+        sector[++s].i = i;
+        sector[s].j   = j-1;
+        sector[s].ml  = ml;
+        continue;
+      }
+      if (fML[i+1][j-(i+1)]+P->MLbase == fij) { /* 5' end is unpaired */
+        sector[++s].i = i+1;
+        sector[s].j   = j;
+        sector[s].ml  = ml;
+        continue;
+      }
+
+      if(with_gquad){
+        if(fij == ggg[i][j-i] + E_MLstem(0, -1, -1, P)){
+          /* go to backtracing of quadruplex */
+          goto repeat_gquad;
+        }
+      }
+
+      switch(dangles){
+        case 0:   tt = ptype[i][j-i];
+                  if(fij == c[i][j-i] + E_MLstem(tt, -1, -1, P)){
+                    structure[i-start] = '(';
+                    structure[j-start] = ')';
+                    goto repeat1;
+                  }
+                  break;
+        case 2:   tt = ptype[i][j-i];
+                  if(fij == c[i][j-i] + E_MLstem(tt, (i>1) ? S1[i-1] : -1, (j < length) ? S1[j+1] : -1, P)){
+                    structure[i-start] = '(';
+                    structure[j-start] = ')';
+                    goto repeat1;
+                  }
+                  break;
+        default:  tt = ptype[i][j-i];
+                  if(fij == c[i][j-i] + E_MLstem(tt, -1, -1, P)){
+                    structure[i-start] = '(';
+                    structure[j-start] = ')';
+                    goto repeat1;
+                  }
+                  tt = ptype[i+1][j-(i+1)];
+                  if(fij == c[i+1][j-(i+1)] + E_MLstem(tt, S1[i], -1, P) + P->MLbase){
+                    structure[++i-start] = '(';
+                    structure[j-start] = ')';
+                    goto repeat1;
+                  }
+                  tt = ptype[i][j-1-i];
+                  if(fij == c[i][j-1-i] + E_MLstem(tt, -1, S1[j], P) + P->MLbase){
+                    structure[i-start] = '(';
+                    structure[--j-start] = ')';
+                    goto repeat1;
+                  }
+                  tt = ptype[i+1][j-1-(i+1)];
+                  if(fij == c[i+1][j-1-(i+1)] + E_MLstem(tt, S1[i], S1[j], P) + 2*P->MLbase){
+                    structure[++i-start] = '(';
+                    structure[--j-start] = ')';
+                    goto repeat1;
+                  }
+                  break;
+      } /* switch(dangles)... */
+
+      /* modular decomposition */
+      for (k = i+1+TURN; k <= j-2-TURN; k++)
+        if (fij == (fML[i][k-i]+fML[k+1][j-(k+1)]))
+          break;
+
+      if ((dangles==3)&&(k>j-2-TURN)) { /* must be coax stack */
+        ml = 2;
+        for (k = i+1+TURN; k <= j-2-TURN; k++) {
+          type = ptype[i][k-i];  type= rtype[type];
+          type_2 = ptype[k+1][j-(k+1)]; type_2= rtype[type_2];
+          if (type && type_2)
+            if (fij == c[i][k-i]+c[k+1][j-(k+1)]+P->stack[type][type_2]+
+                       2*P->MLintern[1])
+              break;
+        }
+      }
+
+      sector[++s].i = i;
+      sector[s].j   = k;
+      sector[s].ml  = ml;
+      sector[++s].i = k+1;
+      sector[s].j   = j;
+      sector[s].ml  = ml;
+
+      if (k>j-2-TURN) nrerror("backtrack failed in fML");
+      continue;
+    }
+
+  repeat1:
+
+    /*----- begin of "repeat:" -----*/
+    if (canonical)  cij = c[i][j-i];
+
+    type = ptype[i][j-i];
+
+
+    if (noLonelyPairs)
+      if (cij == c[i][j-i]) {
+        /* (i.j) closes canonical structures, thus
+           (i+1.j-1) must be a pair                */
+        type_2 = ptype[i+1][j-1-(i+1)]; type_2 = rtype[type_2];
+        cij -= P->stack[type][type_2];
+        structure[i+1-start] = '('; structure[j-1-start] = ')';
+        i++; j--;
+        canonical=0;
+        goto repeat1;
+      }
+    canonical = 1;
+
+
+    no_close = (((type==3)||(type==4))&&no_closingGU);
+    if (no_close) {
+      if (cij == FORBIDDEN) continue;
+    } else
+      if (cij == E_Hairpin(j-i-1, type, S1[i+1], S1[j-1],string+i-1, P))
+        continue;
+
+    for (p = i+1; p <= MIN2(j-2-TURN,i+MAXLOOP+1); p++) {
+      int minq;
+      minq = j-i+p-MAXLOOP-2;
+      if (minq<p+1+TURN) minq = p+1+TURN;
+      for (q = j-1; q >= minq; q--) {
+
+        type_2 = ptype[p][q-p];
+        if (type_2==0) continue;
+        type_2 = rtype[type_2];
+        if (no_closingGU)
+          if (no_close||(type_2==3)||(type_2==4))
+            if ((p>i+1)||(q<j-1)) continue;  /* continue unless stack */
+
+        /* energy = oldLoopEnergy(i, j, p, q, type, type_2); */
+        energy = E_IntLoop(p-i-1, j-q-1, type, type_2, S1[i+1], S1[j-1], S1[p-1], S1[q+1],P);
+
+        new = energy+c[p][q-p];
+        traced = (cij == new);
+        if (traced) {
+          structure[p-start] = '(';
+          structure[q-start] = ')';
+          i = p, j = q;
+          goto repeat1;
+        }
+      }
+    }
+
+    /* end of repeat: --------------------------------------------------*/
+
+    /* (i.j) must close a multi-loop */
+    tt = rtype[type];
+    i1 = i+1; j1 = j-1;
+
+    if(with_gquad){
+      /*
+        The case that is handled here actually resembles something like
+        an interior loop where the enclosing base pair is of regular
+        kind and the enclosed pair is not a canonical one but a g-quadruplex
+        that should then be decomposed further...
+      */
+      if(backtrack_GQuad_IntLoop_L(cij, i, j, type, S, ggg, maxdist, &p, &q, P)){
+        i = p; j = q;
+        goto repeat_gquad;
+      }
+    }
+
+    sector[s+1].ml  = sector[s+2].ml = 1;
+
+    switch(dangles){
+      case 0:   mm = P->MLclosing + E_MLstem(tt, -1, -1, P);
+                for(k = i+2+TURN; k < j-2-TURN; k++){
+                  if(cij == fML[i+1][k-(i+1)] + fML[k+1][j-1-(k+1)] + mm)
+                    break;
+                }
+                break;
+      case 2:   mm = P->MLclosing + E_MLstem(tt, S1[j-1], S1[i+1], P);
+                for(k = i+2+TURN; k < j-2-TURN; k++){
+                  if(cij == fML[i+1][k-(i+1)] + fML[k+1][j-1-(k+1)] + mm)
+                    break;
+                }
+                break;
+      default:  mm    = P->MLclosing + E_MLstem(tt, -1, -1, P);
+                mm5   = P->MLclosing + E_MLstem(tt, S1[j-1], -1, P) + P->MLbase;
+                mm3   = P->MLclosing + E_MLstem(tt, -1, S1[i+1], P) + P->MLbase;
+                mm53  = P->MLclosing + E_MLstem(tt, S1[j-1], S1[i+1], P) + 2*P->MLbase;
+                for(k = i+2+TURN; k < j-2-TURN; k++){
+                  if(cij == fML[i+1][k-(i+1)] + fML[k+1][j-1-(k+1)] + mm)
+                    break;
+                  else if(cij == fML[i+2][k-(i+2)] + fML[k+1][j-1-(k+1)] + mm3){
+                    i1 = i+2;
+                    break;
+                  }
+                  else if(cij == fML[i+1][k-(i+1)] + fML[k+1][j-2-(k+1)] + mm5){
+                    j1 = j-2;
+                    break;
+                  }
+                  else if(cij == fML[i+2][k-(i+2)] + fML[k+1][j-2-(k+1)] + mm53){
+                    i1 = i+2;
+                    j1 = j-2;
+                    break;
+                  }
+                  /* coaxial stacking of (i.j) with (i+1.k) or (k.j-1) */
+                  /* use MLintern[1] since coax stacked pairs don't get TerminalAU */
+                  if (dangles==3) {
+                    int en;
+                    type_2 = ptype[i+1][k-(i+1)]; type_2 = rtype[type_2];
+                    if (type_2) {
+                      en = c[i+1][k-(i+1)]+P->stack[type][type_2]+fML[k+1][j-1-(k+1)];
+                      if (cij == en+2*P->MLintern[1]+P->MLclosing) {
+                        ml = 2;
+                        sector[s+1].ml  = 2;
+                        break;
+                      }
+                    }
+                    type_2 = ptype[k+1][j-1-(k+1)]; type_2 = rtype[type_2];
+                    if (type_2) {
+                      en = c[k+1][j-1-(k+1)]+P->stack[type][type_2]+fML[i+1][k-(i+1)];
+                      if (cij == en+2*P->MLintern[1]+P->MLclosing) {
+                        sector[s+2].ml = 2;
+                        break;
+                      }
+                    }
+                  }
+                }
+                break;
+    } /* switch(dangles)... */
+
+    if (k<=j-3-TURN) { /* found the decomposition */
+      sector[++s].i = i1;
+      sector[s].j   = k;
+      sector[++s].i = k+1;
+      sector[s].j   = j1;
+    } else {
+#if 0
+      /* Y shaped ML loops fon't work yet */
+      if (dangles==3) {
+        /* (i,j) must close a Y shaped ML loop with coax stacking */
+        if (cij ==  fML[i+1][j-2-(i+2)] + mm + d3 + d5 + P->MLbase + P->MLbase) {
+          i1 = i+2;
+          j1 = j-2;
+        } else if (cij ==  fML[i+1][j-2-(i+1)] + mm + d5 + P->MLbase)
+          j1 = j-2;
+        else if (cij ==  fML[i+2][j-1-(i+2)] + mm + d3 + P->MLbase)
+          i1 = i+2;
+        else /* last chance */
+          if (cij != fML[i+1][j-1-(i+1)] + mm + P->MLbase)
+            fprintf(stderr,  "backtracking failed in repeat");
+        /* if we arrive here we can express cij via fML[i1,j1]+dangles */
+        sector[++s].i = i1;
+        sector[s].j   = j1;
+      }
+      else
+#endif
+        nrerror("backtracking failed in repeat");
+    }
+
+    continue; /* this is a workarround to not accidentally proceed in the following block */
+
+  repeat_gquad:
+    /*
+      now we do some fancy stuff to backtrace the stacksize and linker lengths
+      of the g-quadruplex that should reside within position i,j
+    */
+    {
+      int l[3], L, a;
+      L = -1;
+      
+      get_gquad_pattern_mfe(S, i, j, P, &L, l);
+      if(L != -1){
+        /* fill the G's of the quadruplex into the structure string */
+        for(a=0;a<L;a++){
+          structure[i+a-start] = '+';
+          structure[i+L+l[0]+a-start] = '+';
+          structure[i+L+l[0]+L+l[1]+a-start] = '+';
+          structure[i+L+l[0]+L+l[1]+L+l[2]+a-start] = '+';
+        }
+        goto repeat_gquad_exit;
+      }
+      nrerror("backtracking failed in repeat_gquad");
+    }
+  repeat_gquad_exit:
+    asm("nop");
+
+  }
+
+  for (i=strlen(structure)-1; i>0 && structure[i] == '-'; i--)
+    structure[i] = '\0';
+  for (;i>=0; i--)
+   if (structure[i]=='-') structure[i]='.';
+
+  return structure;
+}
+
+
+PRIVATE void update_fold_params(void){
+  if(P) free(P);
+  P = scale_parameters();
+  make_pair_matrix();
+}
+
+/*---------------------------------------------------------------------------*/
+
+PRIVATE void make_ptypes(const short *S, int i, int maxdist, int n) {
+  int j,k, type;
+
+  for (k=TURN+1; k<maxdist; k++) {
+    j = i+k;
+    if (j>n) continue;
+    type = pair[S[i]][S[j]];
+    if (noLonelyPairs && type) {
+      if (!ptype[i+1][j-1-i-1])
+        if (j==n || i==1 || (!pair[S[i-1]][S[j+1]])) type=0;
+    }
+    ptype[i][j-i]=type;
+  }
+}