/* Last changed Time-stamp: <2007-05-09 16:11:21 ivo> */ /* partiton function for RNA secondary structures Ivo L Hofacker Stephan Bernhart Vienna RNA package */ /* $Log: part_func_co.c,v $ Revision 1.10 2007/05/10 17:27:01 ivo make sure the relative error eps is positive in newton iteration Revision 1.9 2006/05/10 15:12:11 ivo some compiler choked on double semicolon after declaration Revision 1.8 2006/04/05 12:52:31 ivo Fix performance bug (O(n^4) loop) Revision 1.7 2006/01/19 11:30:04 ivo compute_probabilities should only look at one dimer at a time Revision 1.6 2006/01/18 12:55:40 ivo major cleanup of berni code fix bugs related to confusing which free energy is returned by co_pf_fold() Revision 1.5 2006/01/16 11:32:25 ivo small bug in multiloop pair probs Revision 1.4 2006/01/05 18:13:40 ivo update Revision 1.3 2006/01/04 15:14:29 ivo fix bug in concentration calculations Revision 1.2 2004/12/23 12:14:41 berni *** empty log message *** Revision 1.1 2004/12/22 10:46:17 berni Partition function Cofolding 0.9, Computation of concentrations. Revision 1.16 2003/08/04 09:14:09 ivo finish up stochastic backtracking Revision 1.15 2002/03/19 16:51:12 ivo more on stochastic backtracking (still incomplete) Revision 1.13 2001/11/16 17:30:04 ivo add stochastic backtracking (still incomplete) */ #include #include #include #include #include #include /* #defines FLT_MAX ... */ #include #include "utils.h" #include "energy_par.h" #include "fold_vars.h" #include "pair_mat.h" #include "PS_dot.h" #include "params.h" #include "loop_energies.h" #include "part_func.h" #include "part_func_co.h" #ifdef _OPENMP #include #endif /*@unused@*/ PRIVATE char rcsid[] UNUSED = "$Id: part_func_co.c,v 1.10 2007/05/10 17:27:01 ivo Exp $"; #define ISOLATED 256.0 #undef TURN #define TURN 0 #define SAME_STRAND(I,J) (((I)>=cut_point)||((J)=cut_point2)||(((I)>=cut_point)&&((J)0) free_co_pf_arrays(); /* free previous allocation */ #endif #ifdef SUN4 nonstandard_arithmetic(); #else #ifdef HP9 fpsetfastmode(1); #endif #endif make_pair_matrix(); get_arrays((unsigned) length); scale_pf_params((unsigned) length, parameters); init_length = length; } PRIVATE void get_arrays(unsigned int length){ unsigned int size; if((length +1) >= (unsigned int)sqrt((double)INT_MAX)) nrerror("get_arrays@part_func_co.c: sequence length exceeds addressable range"); size = sizeof(FLT_OR_DBL) * ((length+1)*(length+2)/2); q = (FLT_OR_DBL *) space(size); qb = (FLT_OR_DBL *) space(size); qm = (FLT_OR_DBL *) space(size); probs = (FLT_OR_DBL *) space(size); qm1 = (FLT_OR_DBL *) space(size); q1k = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1)); qln = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); qq = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); qq1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); qqm = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); qqm1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); prm_l = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); prm_l1 = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); prml = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+2)); expMLbase = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1)); scale = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL)*(length+1)); ptype = (char *) space(sizeof(char)*((length+1)*(length+2)/2)); my_iindx = get_iindx(length); iindx = get_iindx(length); /* for backward compatibility and Perl wrapper */ jindx = get_indx(length); } PUBLIC void free_co_pf_arrays(void){ if(q) free(q); if(qb) free(qb); if(qm) free(qm); if(qm1) free(qm1); if(ptype) free(ptype); if(qq) free(qq); if(qq1) free(qq1); if(qqm) free(qqm); if(qqm1) free(qqm1); if(q1k) free(q1k); if(qln) free(qln); if(prm_l) free(prm_l); if(prm_l1) free(prm_l1); if(prml) free(prml); if(probs) free(probs); if(expMLbase) free(expMLbase); if(scale) free(scale); if(my_iindx) free(my_iindx); if(iindx) free(iindx); /* for backward compatibility and Perl wrapper */ if(jindx) free(jindx); if(S) free(S); if(S1) free(S1); init_length=0; q = qb = qm = qm1 = qq = qq1 = qqm = qqm1 = q1k = qln = prm_l = prm_l1 = prml = expMLbase = scale = probs = NULL; ptype = NULL; S = S1 = NULL; my_iindx = jindx = iindx = NULL; #ifdef SUN4 standard_arithmetic(); #else #ifdef HP9 fpsetfastmode(0); #endif #endif } /*-----------------------------------------------------------------*/ PUBLIC cofoldF co_pf_fold(char *sequence, char *structure){ return co_pf_fold_par(sequence, structure, NULL, do_backtrack, fold_constrained); } PUBLIC cofoldF co_pf_fold_par(char *sequence, char *structure, pf_paramT *parameters, int calculate_bppm, int is_constrained){ int n; FLT_OR_DBL Q; cofoldF X; double free_energy; n = (int) strlen(sequence); do_bppm = calculate_bppm; struct_constrained = is_constrained; #ifdef _OPENMP /* always init everything since all global static variables are uninitialized when entering a thread */ init_partfunc_co(n, parameters); #else if(parameters) init_partfunc_co(n, parameters); else if (n > init_length) init_partfunc_co(n, parameters); else if (fabs(pf_params->temperature - temperature)>1e-6) update_co_pf_params_par(n, parameters); #endif /* printf("mirnatog=%d\n",mirnatog); */ if(S) free(S); S = encode_sequence(sequence, 0); if(S1) free(S1); S1 = encode_sequence(sequence, 1); make_ptypes(S, structure); pf_co(sequence); if (backtrack_type=='C') Q = qb[my_iindx[1]-n]; else if (backtrack_type=='M') Q = qm[my_iindx[1]-n]; else Q = q[my_iindx[1]-n]; /* ensemble free energy in Kcal/mol */ if (Q<=FLT_MIN) fprintf(stderr, "pf_scale too large\n"); free_energy = (-log(Q)-n*log(pf_params->pf_scale))*pf_params->kT/1000.0; /* in case we abort because of floating point errors */ if (n>1600) fprintf(stderr, "free energy = %8.2f\n", free_energy); /*probability of molecules being bound together*/ /*Computation of "real" Partition function*/ /*Need that for concentrations*/ if (cut_point>0){ double kT, pbound, QAB, QToT, Qzero; kT = pf_params->kT/1000.0; Qzero=q[my_iindx[1]-n]; QAB=(q[my_iindx[1]-n]-q[my_iindx[1]-(cut_point-1)]*q[my_iindx[cut_point]-n])*pf_params->expDuplexInit; /*correction for symmetry*/ if((n-(cut_point-1)*2)==0) { if ((strncmp(sequence, sequence+cut_point-1, cut_point-1))==0) { QAB/=2; }} QToT=q[my_iindx[1]-(cut_point-1)]*q[my_iindx[cut_point]-n]+QAB; pbound=1-(q[my_iindx[1]-(cut_point-1)]*q[my_iindx[cut_point]-n]/QToT); X.FAB = -kT*(log(QToT)+n*log(pf_params->pf_scale)); X.F0AB = -kT*(log(Qzero)+n*log(pf_params->pf_scale)); X.FcAB = (QAB>1e-17) ? -kT*(log(QAB)+n*log(pf_params->pf_scale)) : 999; X.FA = -kT*(log(q[my_iindx[1]-(cut_point-1)]) + (cut_point-1)*log(pf_params->pf_scale)); X.FB = -kT*(log(q[my_iindx[cut_point]-n]) + (n-cut_point+1)*log(pf_params->pf_scale)); /* printf("QAB=%.9f\tQtot=%.9f\n",QAB/scale[n],QToT/scale[n]);*/ } else { X.FA = X.FB = X.FAB = X.F0AB = free_energy; X.FcAB = 0; } /* backtracking to construct binding probabilities of pairs*/ if(do_bppm){ pf_co_bppm(sequence, structure); /* * Backward compatibility: * This block may be removed if deprecated functions * relying on the global variable "pr" vanish from within the package! */ pr = probs; /* { if(pr) free(pr); pr = (FLT_OR_DBL *) space(sizeof(FLT_OR_DBL) * ((n+1)*(n+2)/2)); memcpy(pr, probs, sizeof(FLT_OR_DBL) * ((n+1)*(n+2)/2)); } */ } return X; } /* forward recursion of pf cofolding */ PRIVATE void pf_co(const char *sequence){ int n, i,j,k,l, ij, u,u1,ii, type, type_2, tt; FLT_OR_DBL temp, Qmax=0; FLT_OR_DBL qbt1, *tmp; FLT_OR_DBL expMLclosing; double max_real; int noGUclosure = pf_params->model_details.noGUclosure; max_real = (sizeof(FLT_OR_DBL) == sizeof(float)) ? FLT_MAX : DBL_MAX; n = (int) strlen(sequence); expMLclosing = pf_params->expMLclosing; /*array initialization ; qb,qm,q qb,qm,q (i,j) are stored as ((n+1-i)*(n-i) div 2 + n+1-j */ /* for (d=0; d<=TURN; d++) */ for (i=1; i<=n/*-d*/; i++) { ij = my_iindx[i]-i; q[ij]=scale[1]; qb[ij]=qm[ij]=0.0; } for (i=0; i<=n; i++) qq[i]=qq1[i]=qqm[i]=qqm1[i]=prm_l[i]=prm_l1[i]=prml[i]=0; for (j=TURN+2;j<=n; j++) { for (i=j-TURN-1; i>=1; i--) { /* construction of partition function of segment i,j*/ /*firstly that given i bound to j : qb(i,j) */ u = j-i-1; ij = my_iindx[i]-j; type = ptype[ij]; qbt1=0; if (type!=0) { /*hairpin contribution*/ if SAME_STRAND(i,j){ if (((type==3)||(type==4))&&noGUclosure) qbt1 = 0; else qbt1 = exp_E_Hairpin(u, type, S1[i+1], S1[j-1], sequence+i-1, pf_params)*scale[u+2]; } /* interior loops with interior pair k,l */ for (k=i+1; k<=MIN2(i+MAXLOOP+1,j-TURN-2); k++) { u1 = k-i-1; for (l=MAX2(k+TURN+1,j-1-MAXLOOP+u1); lcut_point) temp*=scale[1]; if (i1) ? S1[i-1] : -1, (j1)&&(SAME_STRAND(i-1,i))) ? S1[i-1] : -1, ((jQmax) { Qmax = temp; if (Qmax>max_real/10.) fprintf(stderr, "Q close to overflow: %d %d %g\n", i,j,temp); } if (temp>=max_real) { PRIVATE char msg[128]; snprintf(msg, 127, "overflow in co_pf_fold while calculating q[%d,%d]\n" "use larger pf_scale", i,j); nrerror(msg); } } tmp = qq1; qq1 =qq; qq =tmp; tmp = qqm1; qqm1=qqm; qqm=tmp; } } /* backward recursion of pf cofolding */ PRIVATE void pf_co_bppm(const char *sequence, char *structure){ int n, i,j,k,l, ij, kl, ii, ll, type, type_2, tt, ov=0; FLT_OR_DBL temp, Qmax=0, prm_MLb; FLT_OR_DBL prmt,prmt1; FLT_OR_DBL *tmp; FLT_OR_DBL expMLclosing; double max_real; max_real = (sizeof(FLT_OR_DBL) == sizeof(float)) ? FLT_MAX : DBL_MAX; n = (int) strlen(sequence); expMLclosing = pf_params->expMLclosing; /* backtracking to construct binding probabilities of pairs*/ if ((S != NULL) && (S1 != NULL)) { FLT_OR_DBL *Qlout, *Qrout; Qmax=0; Qrout=(FLT_OR_DBL *)space(sizeof(FLT_OR_DBL) * (n+2)); Qlout=(FLT_OR_DBL *)space(sizeof(FLT_OR_DBL) * (cut_point+2)); for (k=1; k<=n; k++) { q1k[k] = q[my_iindx[1] - k]; qln[k] = q[my_iindx[k] -n]; } q1k[0] = 1.0; qln[n+1] = 1.0; /* pr = q; / * recycling */ /* 1. exterior pair i,j and initialization of pr array */ for (i=1; i<=n; i++) { for (j=i; j<=MIN2(i+TURN,n); j++) probs[my_iindx[i]-j] = 0; for (j=i+TURN+1; j<=n; j++) { ij = my_iindx[i]-j; type = ptype[ij]; if (type&&(qb[ij]>0.)) { probs[ij] = q1k[i-1]*qln[j+1]/q1k[n]; probs[ij] *= exp_E_ExtLoop(type, ((i>1)&&(SAME_STRAND(i-1,i))) ? S1[i-1] : -1, ((jTURN+1; l--) { /* 2. bonding k,l as substem of 2:loop enclosed by i,j */ for (k=1; k0)) { probs[kl] += probs[ij]*exp_E_IntLoop(k-i-1, j-l-1, type, type_2, S1[i+1], S1[j-1], S1[k-1], S1[l+1], pf_params)*scale[k-i+j-l]; } } } } /* 3. bonding k,l as substem of multi-loop enclosed by i,j */ prm_MLb = 0.; if ((l1)&&SAME_STRAND(k-1,k)) ? S1[k-1] : -1, ((lQmax) { Qmax = probs[kl]; if (Qmax>max_real/10.) fprintf(stderr, "P close to overflow: %d %d %g %g\n", i, j, probs[kl], qb[kl]); } if (probs[kl]>=max_real) { ov++; probs[kl]=FLT_MAX; } } /* end for (k=..) multloop*/ else /* set prm_l to 0 to get prm_l1 to be 0 */ for (i=0; i<=n; i++) prm_l[i]=0; tmp = prm_l1; prm_l1=prm_l; prm_l=tmp; /*computation of .(..(...)..&..). type features?*/ if (cut_point<=0) continue; /* no .(..(...)..&..). type features*/ if ((l==n)||(l<=2)) continue; /* no .(..(...)..&..). type features*/ /*new version with O(n^3)??*/ if (l>cut_point) { if (ll; t--) { for (k=1; k=cut_point; k--) { if (qb[my_iindx[k]-l]) { kl=my_iindx[k]-l; type=ptype[kl]; temp = Qrout[l]; temp *= exp_E_ExtLoop(type, (k>cut_point) ? S1[k-1] : -1, (l < n) ? S1[l+1] : -1, pf_params); if (k>cut_point) temp*=q[my_iindx[cut_point]-(k-1)]; probs[kl]+=temp; } } } else if (l==cut_point ) { int t, sk,s; for (t=2; t1) ? S1[k-1] : -1, (l<(cut_point-1)) ? S1[l+1] : -1, pf_params); if (l+10) fprintf(stderr, "%d overflows occurred while backtracking;\n" "you might try a smaller pf_scale than %g\n", ov, pf_params->pf_scale); } PRIVATE void scale_pf_params(unsigned int length, pf_paramT *parameters){ unsigned int i; double kT, scaling_factor; if(pf_params) free(pf_params); if(parameters){ pf_params = get_boltzmann_factor_copy(parameters); } else { model_detailsT md; set_model_details(&md); pf_params = get_boltzmann_factors(temperature, alpha, md, pf_scale); } scaling_factor = pf_params->pf_scale; kT = pf_params->kT; /* kT in cal/mol */ /* scaling factors (to avoid overflows) */ if (scaling_factor == -1) { /* mean energy for random sequences: 184.3*length cal */ scaling_factor = exp(-(-185+(pf_params->temperature-37.)*7.27)/kT); if (scaling_factor<1) scaling_factor=1; pf_params->pf_scale = scaling_factor; } scale[0] = 1.; scale[1] = 1./scaling_factor; expMLbase[0] = 1; expMLbase[1] = pf_params->expMLbase/scaling_factor; for (i=2; i<=length; i++) { scale[i] = scale[i/2]*scale[i-(i/2)]; expMLbase[i] = pow(pf_params->expMLbase, (double)i) * scale[i]; } } /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ PUBLIC void update_co_pf_params(int length){ update_co_pf_params_par(length, NULL); } PUBLIC void update_co_pf_params_par(int length, pf_paramT *parameters){ make_pair_matrix(); scale_pf_params((unsigned) length, parameters); } /*---------------------------------------------------------------------------*/ PRIVATE void make_ptypes(const short *S, const char *structure) { int n,i,j,k,l; int noLP = pf_params->model_details.noLP; n=S[0]; for (k=1; k<=n-TURN-1; k++) for (l=1; l<=2; l++) { int type,ntype=0,otype=0; i=k; j = i+TURN+l; if (j>n) continue; type = pair[S[i]][S[j]]; while ((i>=1)&&(j<=n)) { if ((i>1)&&(j=r) break; } if (l>j) nrerror("backtrack failed in qm1"); backtrack(i,l); } PRIVATE void backtrack(int i, int j) { int noGUclosure = pf_params->model_details.noGUclosure; do { double r, qbt1; int k, l, type, u, u1; pstruc[i-1] = '('; pstruc[j-1] = ')'; r = urn() * qb[my_iindx[i]-j]; type = ptype[my_iindx[i]-j]; u = j-i-1; /*hairpin contribution*/ if (((type==3)||(type==4))&&noGUclosure) qbt1 = 0; else qbt1 = exp_E_Hairpin(u, type, S1[i+1], S1[j-1], sequence+i-1, pf_params)*scale[u+2]; if (qbt1>r) return; /* found the hairpin we're done */ for (k=i+1; k<=MIN2(i+MAXLOOP+1,j-TURN-2); k++) { u1 = k-i-1; for (l=MAX2(k+TURN+1,j-1-MAXLOOP+u1); l r) break; } if (qbt1 > r) break; } if (l=r) break; } if (k>=j) nrerror("backtrack failed, can't find split index "); backtrack_qm1(k, j); j = k-1; while (j>i) { /* now backtrack [i ... j] in qm[] */ jj = jindx[j]; ii = my_iindx[i]; r = urn() * qm[ii - j]; qt = qm1[jj+i]; k=i; if (qt= r) break; } if (k>j) nrerror("backtrack failed in qm"); backtrack_qm1(k,j); if (k= r) break; /* no more pairs */ j = k-1; } } } PUBLIC void compute_probabilities(double FAB, double FA,double FB, struct plist *prAB, struct plist *prA, struct plist *prB, int Alength) { /*computes binding probabilities and dimer free energies*/ int i, j; double pAB; double mykT; struct plist *lp1, *lp2; int offset; mykT=pf_params->kT/1000.; /* pair probabilities in pr are relative to the null model (without DuplexInit) */ /*Compute probabilities pAB, pAA, pBB*/ pAB=1.-exp((1/mykT)*(FAB-FA-FB)); /* compute pair probabilities given that it is a dimer */ /* AB dimer */ offset=0; lp2=prA; if (pAB>0) for (lp1=prAB; lp1->j>0; lp1++) { float pp=0; i=lp1->i; j=lp1->j; while (offset+lp2->i < i && lp2->i>0) lp2++; if (offset+lp2->i == i) while ((offset+lp2->j) < j && (lp2->j>0)) lp2++; if (lp2->j == 0) {lp2=prB; offset=Alength;}/* jump to next list */ if ((offset+lp2->i==i) && (offset+lp2->j ==j)) { pp = lp2->p; lp2++; } lp1->p=(lp1->p-(1-pAB)*pp)/pAB; if(lp1->p < 0.){ warn_user("part_func_co: numeric instability detected, probability below zero!"); lp1->p = 0.; } } return; } PRIVATE double *Newton_Conc(double KAB, double KAA, double KBB, double concA, double concB,double* ConcVec) { double TOL, EPS, xn, yn, det, cA, cB; int i=0; /*Newton iteration for computing concentrations*/ cA=concA; cB=concB; TOL=1e-6; /*Tolerance for convergence*/ ConcVec=(double*)space(5*sizeof(double)); /* holds concentrations */ do { /* det = (4.0 * KAA * cA + KAB *cB + 1.0) * (4.0 * KBB * cB + KAB *cA + 1.0) - (KAB *cB) * (KAB *cA); */ det = 1 + 16. *KAA*KBB*cA*cB + KAB*(cA+cB) + 4.*KAA*cA + 4.*KBB*cB + 4.*KAB*(KBB*cB*cB + KAA*cA*cA); /* xn = ( (2.0 * KBB * cB*cB + KAB *cA *cB + cB - concB) * (KAB *cA) - (2.0 * KAA * cA*cA + KAB *cA *cB + cA - concA) * (4.0 * KBB * cB + KAB *cA + 1.0) ) /det; */ xn = ( (2.0 * KBB * cB*cB + cB - concB) * (KAB *cA) - KAB*cA*cB*(4. * KBB*cB + 1.) - (2.0 * KAA * cA*cA + cA - concA) * (4.0 * KBB * cB + KAB *cA + 1.0) ) /det; /* yn = ( (2.0 * KAA * cA*cA + KAB *cA *cB + cA - concA) * (KAB *cB) - (2.0 * KBB * cB*cB + KAB *cA *cB + cB - concB) * (4.0 * KAA * cA + KAB *cB + 1.0) ) /det; */ yn = ( (2.0 * KAA * cA*cA + cA - concA) * (KAB *cB) - KAB*cA*cB*(4. * KAA*cA + 1.) - (2.0 * KBB * cB*cB + cB - concB) * (4.0 * KAA * cA + KAB *cB + 1.0) ) /det; EPS = fabs(xn/cA) + fabs(yn/cB); cA += xn; cB += yn; i++; if (i>10000) { fprintf(stderr, "Newton did not converge after %d steps!!\n",i); break; } } while(EPS>TOL); ConcVec[0]= cA*cB*KAB ;/*AB concentration*/ ConcVec[1]= cA*cA*KAA ;/*AA concentration*/ ConcVec[2]= cB*cB*KBB ;/*BB concentration*/ ConcVec[3]= cA; /* A concentration*/ ConcVec[4]= cB; /* B concentration*/ return ConcVec; } PUBLIC struct ConcEnt *get_concentrations(double FcAB, double FcAA, double FcBB, double FEA, double FEB, double *startconc) { /*takes an array of start concentrations, computes equilibrium concentrations of dimers, monomers, returns array of concentrations in strucutre ConcEnt*/ double *ConcVec; int i; struct ConcEnt *Concentration; double KAA, KAB, KBB, kT; kT=pf_params->kT/1000.; Concentration=(struct ConcEnt *)space(20*sizeof(struct ConcEnt)); /* Compute equilibrium constants */ /* again note the input free energies are not from the null model (without DuplexInit) */ KAA = exp(( 2.0 * FEA - FcAA)/kT); KBB = exp(( 2.0 * FEB - FcBB)/kT); KAB = exp(( FEA + FEB - FcAB)/kT); /* printf("Kaa..%g %g %g\n", KAA, KBB, KAB); */ for (i=0; ((startconc[i]!=0)||(startconc[i+1]!=0));i+=2) { ConcVec=Newton_Conc(KAB, KAA, KBB, startconc[i], startconc[i+1], ConcVec); Concentration[i/2].A0=startconc[i]; Concentration[i/2].B0=startconc[i+1]; Concentration[i/2].ABc=ConcVec[0]; Concentration[i/2].AAc=ConcVec[1]; Concentration[i/2].BBc=ConcVec[2]; Concentration[i/2].Ac=ConcVec[3]; Concentration[i/2].Bc=ConcVec[4]; if (!(((i+2)/2)%20)) { Concentration=(struct ConcEnt *)xrealloc(Concentration,((i+2)/2+20)*sizeof(struct ConcEnt)); } free(ConcVec); } return Concentration; } PUBLIC FLT_OR_DBL *export_co_bppm(void){ return probs; } /*###########################################*/ /*# deprecated functions below #*/ /*###########################################*/ PUBLIC struct plist *get_plist(struct plist *pl, int length, double cut_off) { int i, j,n, count; /*get pair probibilities out of pr array*/ count=0; n=2; for (i=1; i??*/ pl[count++].p=0.; pl=(struct plist *)xrealloc(pl,(count)*sizeof(struct plist)); return pl; } PUBLIC void init_co_pf_fold(int length){ /* DO NOTHING */ }