sumalibs first commit

This commit is contained in:
Celine Mercier
2015-07-16 14:00:12 +02:00
commit 049129488e
41 changed files with 7796 additions and 0 deletions

BIN
liblcs/.DS_Store vendored Normal file

Binary file not shown.

25
liblcs/Makefile Normal file
View File

@ -0,0 +1,25 @@
SOURCES = sse_banded_LCS_alignment.c \
upperband.c
SRCS=$(SOURCES)
OBJECTS= $(patsubst %.c,%.o,$(SOURCES))
LIBFILE= liblcs.a
RANLIB=ranlib
include ../global.mk
all: $(LIBFILE)
clean:
rm -rf $(OBJECTS) $(LIBFILE)
rm -f *.P
rm -f *.a
$(LIBFILE): $(OBJECTS)
ar -cr $@ $?
$(RANLIB) $@

168
liblcs/_lcs.ext.1.c Normal file
View File

@ -0,0 +1,168 @@
#include "_lcs.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
// Allocate a band allowing to align sequences of length : 'length'
column_t* allocateColumn(int length,column_t *column, bool mode8bits)
{
int size;
bool newc = false;
// The band length should be equal to the length
// of the sequence + 7 for taking into account its
// shape
size = (length+1) * ((mode8bits) ? sizeof(int8_t):sizeof(int16_t));
// If the pointer to the old column is NULL we allocate
// a new column
if (column==NULL)
{
column = malloc(sizeof(column_t));
if (!column)
return NULL;
column->size = 0;
column->data.shrt=NULL;
column->score.shrt=NULL;
newc = true;
}
// Otherwise we check if its size is sufficient
// or if it should be extended
if (size > column->size)
{
int16_t *old = column->data.shrt;
int16_t *olds= column->score.shrt;
column->data.shrt = malloc(size);
column->score.shrt= malloc(size);
if (column->data.shrt==NULL || column->score.shrt==NULL)
{
fprintf(stderr,"Allocation Error on column for a size of %d\n" , size);
column->data.shrt = old;
column->score.shrt= olds;
if (newc)
{
free(column);
column=NULL;
return NULL;
}
return NULL;
}
else
column->size = size;
}
return column;
}
void freeColumn(column_p column)
{
if (column)
{
if (column->data.shrt)
free(column->data.shrt);
if (column->score.shrt)
free(column->score.shrt);
free(column);
}
}
int fastLCSScore(const char* seq1, const char* seq2,column_pp column,int32_t* lpath)
{
return fastLCSScore16(seq1,seq2,column,lpath);
}
int simpleLCS(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath)
{
int lseq1,lseq2; // length of the both sequences
int lcs;
int itmp; // tmp variables for swap
const char* stmp; //
int32_t *score;
int32_t *path;
column_t *column;
int32_t i,j;
int32_t sl,su,sd;
int32_t pl,pu,pd;
// Made seq1 the longest sequences
lseq1=strlen(seq1);
lseq2=strlen(seq2);
if (lseq1 < lseq2)
{
itmp=lseq1;
lseq1=lseq2;
lseq2=itmp;
stmp=seq1;
seq1=seq2;
seq2=stmp;
}
lseq1++;
lseq2++;
// a band sized to the smallest sequence is allocated
if (ppcolumn)
column = *ppcolumn;
else
column=NULL;
column = allocateColumn(lseq1*2,column,0);
score = (int32_t*) column->score.shrt;
path = (int32_t*) column->data.shrt;
memset(score,0,lseq1 * sizeof(int32_t));
for (j=0; j < lseq1; j++)
path[j]=j;
for (i=1; i< lseq2; i++)
{
sl=0;
pl=i;
for (j=1; j < lseq1; j++)
{
sd=score[j-1] + (seq2[i-1]==seq1[j-1] ? 1:0);
pd=path[j-1] + 1;
su=score[j];
pu=path[j] + 1;
score[j-1]=sl;
if (su > sl) sl=su, pl=pu;
if (sd > sl) sl=sd, pl=pd;
}
}
lcs = sl;
if(lpath) *lpath=pl;
if (ppcolumn)
*ppcolumn=column;
else
freeColumn(column);
return lcs;
}

34
liblcs/_lcs.ext.2.c Normal file
View File

@ -0,0 +1,34 @@
#include "_lcs.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#define VSIZE (8)
#define VTYPE vInt16
#define STYPE int16_t
#define CMENB shrt
#define VMODE false
#define FASTLCSSCORE fastLCSScore16
#define INSERT_REG _MM_INSERT_EPI16
#define EXTRACT_REG _MM_EXTRACT_EPI16
#define EQUAL_REG _MM_CMPEQ_EPI16
#define GREATER_REG _MM_CMPGT_EPI16
#define SMALLER_REG _MM_CMPLT_EPI16
#define ADD_REG _MM_ADD_EPI16
#define SUB_REG _MM_SUB_EPI16
#define AND_REG _MM_AND_SI128
#define ANDNOT_REG _MM_ANDNOT_SI128
#define OR_REG _MM_OR_SI128
#define SET_CONST _MM_SET1_EPI16
#define GET_MAX _MM_MAX_EPI16
#define GET_MIN _MM_MIN_EPI16
#define MIN_SCORE INT16_MIN
#define MAX_SCORE 32000
#include "_lcs_fast.h"

34
liblcs/_lcs.ext.3.c Normal file
View File

@ -0,0 +1,34 @@
#include "_lcs.h"
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#define VSIZE (16)
#define VTYPE vInt8
#define STYPE int8_t
#define CMENB byte
#define VMODE true
#define FASTLCSSCORE fastLCSScore8
#define INSERT_REG _MM_INSERT_EPI8
#define EXTRACT_REG _MM_EXTRACT_EPI8
#define EQUAL_REG _MM_CMPEQ_EPI8
#define GREATER_REG _MM_CMPGT_EPI8
#define SMALLER_REG _MM_CMPLT_EPI8
#define ADD_REG _MM_ADD_EPI8
#define SUB_REG _MM_SUB_EPI8
#define AND_REG _MM_AND_SI128
#define ANDNOT_REG _MM_ANDNOT_SI128
#define OR_REG _MM_OR_SI128
#define SET_CONST _MM_SET1_EPI8
#define GET_MAX _MM_MAX_EPI8
#define GET_MIN _MM_MIN_EPI8
#define MIN_SCORE INT8_MIN
#define MAX_SCORE 127
#include "_lcs_fast.h"

29
liblcs/_lcs.h Normal file
View File

@ -0,0 +1,29 @@
#include "../libsse/_sse.h"
#define bool char
#define false (1==0)
#define true (1==1)
typedef struct {
int16_t size;
union { int16_t *shrt;
int8_t *byte;
} data;
union { int16_t *shrt;
int8_t *byte;
} score;
} column_t, **column_pp, *column_p;
column_p allocateColumn(int length,column_t *column, bool mode8bits);
void freeColumn(column_p column);
int fastLCSScore16(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath);
int fastLCSScore8(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath);
int simpleLCS(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath);
int fastLCSScore(const char* seq1, const char* seq2,column_pp column,int32_t* lpath);

597
liblcs/_lcs_fast.h Normal file
View File

@ -0,0 +1,597 @@
/*
* Print a SSE register for debug purpose
*/
#ifdef __SSE2__
static void printreg(VTYPE r)
{
STYPE a0,a1,a2,a3,a4,a5,a6,a7;
#if VMODE
STYPE a8,a9,a10,a11,a12,a13,a14,a15;
#endif
a0= EXTRACT_REG(r,0);
a1= EXTRACT_REG(r,1);
a2= EXTRACT_REG(r,2);
a3= EXTRACT_REG(r,3);
a4= EXTRACT_REG(r,4);
a5= EXTRACT_REG(r,5);
a6= EXTRACT_REG(r,6);
a7= EXTRACT_REG(r,7);
#if VMODE
a8= EXTRACT_REG(r,8);
a9= EXTRACT_REG(r,9);
a10= EXTRACT_REG(r,10);
a11= EXTRACT_REG(r,11);
a12= EXTRACT_REG(r,12);
a13= EXTRACT_REG(r,13);
a14= EXTRACT_REG(r,14);
a15= EXTRACT_REG(r,15);
#endif
printf( "a00 :-> %7d %7d %7d %7d "
" %7d %7d %7d %7d "
#if VMODE
"%7d %7d %7d %7d "
" %7d %7d %7d %7d "
#endif
"\n"
, a0,a1,a2,a3,a4,a5,a6,a7
#if VMODE
, a8,a9,a10,a11,a12,a13,a14,a15
#endif
);
}
/*
* set position p of a SSE register with the value v
*/
static inline VTYPE insert_reg(VTYPE r, STYPE v, int p)
{
switch (p) {
case 0: return INSERT_REG(r,v,0);
case 1: return INSERT_REG(r,v,1);
case 2: return INSERT_REG(r,v,2);
case 3: return INSERT_REG(r,v,3);
case 4: return INSERT_REG(r,v,4);
case 5: return INSERT_REG(r,v,5);
case 6: return INSERT_REG(r,v,6);
case 7: return INSERT_REG(r,v,7);
#if VMODE
case 8: return INSERT_REG(r,v,8);
case 9: return INSERT_REG(r,v,9);
case 10: return INSERT_REG(r,v,10);
case 11: return INSERT_REG(r,v,11);
case 12: return INSERT_REG(r,v,12);
case 13: return INSERT_REG(r,v,13);
case 14: return INSERT_REG(r,v,14);
case 15: return INSERT_REG(r,v,15);
#endif
}
return _MM_SETZERO_SI128();
}
static inline STYPE extract_reg(VTYPE r, int p)
{
switch (p) {
case 0: return EXTRACT_REG(r,0);
case 1: return EXTRACT_REG(r,1);
case 2: return EXTRACT_REG(r,2);
case 3: return EXTRACT_REG(r,3);
case 4: return EXTRACT_REG(r,4);
case 5: return EXTRACT_REG(r,5);
case 6: return EXTRACT_REG(r,6);
case 7: return EXTRACT_REG(r,7);
#if VMODE
case 8: return EXTRACT_REG(r,8);
case 9: return EXTRACT_REG(r,9);
case 10: return EXTRACT_REG(r,10);
case 11: return EXTRACT_REG(r,11);
case 12: return EXTRACT_REG(r,12);
case 13: return EXTRACT_REG(r,13);
case 14: return EXTRACT_REG(r,14);
case 15: return EXTRACT_REG(r,15);
#endif
}
return 0;
}
#define GET_H_SYMBOLE(s,p) ((p && p < lseq1) ? (s)[(p)-1]:255)
#define GET_V_SYMBOLE(s,p) ((p && p < lseq2) ? (s)[(p)-1]:0)
#define LSHIFT_SCORE(r) { r = _MM_SLLI_SI128((r),sizeof(STYPE)); }
#define SET_H_SYMBOLE(r,p,s) { r = insert_reg((r),(STYPE)GET_H_SYMBOLE(seq1,(s)),(p)); }
#define PUSH_V_SYMBOLE(r,s) { r = insert_reg(_MM_SLLI_SI128((r),sizeof(STYPE)),(STYPE)GET_V_SYMBOLE(seq2,(s)),0); }
#define EQUAL(f1,f2) _MM_AND_SI128(EQUAL_REG((f1),(f2)),SET_CONST(1))
int FASTLCSSCORE(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath)
{
int lseq1,lseq2; // length of the both sequences
int itmp; // tmp variables for swap
const char* stmp; //
int nbands; // Number of bands of width eight in the score matrix
int lastband; // width of the last band
// Register for scanning the score matrix
VTYPE minus1;
VTYPE minus2;
VTYPE current;
VTYPE left;
VTYPE top;
VTYPE diag;
VTYPE sminus1;
VTYPE sminus2;
VTYPE scurrent;
VTYPE sleft;
VTYPE stop;
VTYPE sdiag;
VTYPE way;
VTYPE onevect;
VTYPE maxvect;
VTYPE fhseq; // The fragment of the horizontal sequence
// to consider for aligment
VTYPE fvseq; // The fragment of the horizontal sequence
// to consider for aligment
VTYPE match;
int band;
int line;
int limit;
int lcs;
int h;
int i;
column_t *column;
// Made seq1 the longest sequences
lseq1=strlen(seq1);
lseq2=strlen(seq2);
if (lseq1 < 10 || lseq2 < 10)
return simpleLCS(seq1,seq2,ppcolumn,lpath);
if (lseq1 < lseq2)
{
itmp=lseq1;
lseq1=lseq2;
lseq2=itmp;
stmp=seq1;
seq1=seq2;
seq2=stmp;
}
// we add one to both lengths for taking into
// account the extra line and column in the score
// matrix
lseq1++;
lseq2++;
// a band sized to the smallest sequence is allocated
if (ppcolumn)
column = *ppcolumn;
else
column=NULL;
column = allocateColumn(lseq2,column,VMODE);
// Check memory allocation
if (column == NULL)
return -1;
for (i=0; i<lseq2;i++)
{
column->data.CMENB[i]=MIN_SCORE;
column->score.CMENB[i]=-1;
}
nbands = lseq1 / VSIZE; // You have VSIZE element in one SSE register
// Alignment will be realized in nbands
lastband = lseq1 - (nbands * VSIZE); // plus one of width lastband except if
// lastband==0
if (lastband) nbands++;
else lastband=VSIZE;
lastband--;
// printf("seq1 : %s seq2 : %s\n",seq1,seq2);
minus2 = SET_CONST(MIN_SCORE);
minus1 = _MM_SETZERO_SI128();
sminus1= _MM_SETZERO_SI128();
sminus2= _MM_SETZERO_SI128();
onevect= SET_CONST(1);
maxvect= SET_CONST(MAX_SCORE);
h=0;
fhseq = _MM_SETZERO_SI128();
fvseq = _MM_SETZERO_SI128();
//
// Beginning of the first band
//
for (line = 0; line < VSIZE; line++,h++) // avant VSIZE - 1
{
// printf("line= %4d h= %4d\n",line,h);
SET_H_SYMBOLE(fhseq,line,h)
PUSH_V_SYMBOLE(fvseq,line)
minus2 = insert_reg(minus2,0,h);
minus1 = insert_reg(minus1,MIN_SCORE,line); // 0 avant
match = EQUAL(fhseq,fvseq);
if (lpath)
{
sminus2 = insert_reg(sminus2,line-1,line); // Je ne suis pas certain de l'initialisation
sminus1 = insert_reg(sminus1,0,line);
}
// printreg(fvseq);
// printreg(fhseq);
// printreg(match);
// printf("================================\n");
current = minus1; // The best score is the upper one
// It cannot be the best as set to MIN_SCORE
left = minus1;
// printf("Vert = "); printreg(current);
LSHIFT_SCORE(minus1) // I shift minus1 so now I'll compare with the left position
minus1=insert_reg(minus1,(column)->data.CMENB[line],0);
top=minus1;
if (lpath)
{
sleft=sminus1; // I store the path length corresponding to the upper path
LSHIFT_SCORE(sminus1) // I shift to prepare the score coming from the left side
sminus1=insert_reg(sminus1,(column)->score.CMENB[line],0);
stop=sminus1;
sdiag=sminus2;
}
// printf("Horz = "); printreg(minus1);
current = GET_MAX(current,minus1); // Look for the best between upper and left
// printf("BstHV= "); printreg(current);
//
// printf("Diag = "); printreg(ADD_REG(minus2,match));
diag=minus2;
// minus2 = ; // Minus2 contains the diagonal score, so I add the match reward
// Diag score are setup to 0 so this one will win on the first iteration
current = GET_MAX(current,ADD_REG(minus2,match));
if (lpath)
{
// printf("\n");
// printf("current: ");
// printreg(current);
// printf("current: ");
// printreg(SUB_REG(current,match));
// printf("diag : ");
// printreg(diag);
// printf("left : ");
// printreg(left);
// printf("top : ");
// printreg(top);
way = EQUAL_REG(SUB_REG(current,match),diag);
scurrent= OR_REG(AND_REG(way,sdiag),
ANDNOT_REG(way,maxvect));
// printf("sdiag : ");
// printreg(scurrent);
way = EQUAL_REG(current,left);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,sleft),
ANDNOT_REG(way,maxvect)));
// printf("sleft : ");
// printreg(scurrent);
way = EQUAL_REG(current,top);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,stop),
ANDNOT_REG(way,maxvect)));
// printf("stop : ");
// printreg(scurrent);
scurrent= ADD_REG(scurrent,onevect);
sminus2=sminus1;
sminus1=scurrent;
}
// printf("line %d :Best = ",line); printreg(current);
//
// printf("================================\n");
minus2=minus1;
minus1=current;
// printf("min2 = "); printreg(minus2);
// printf("min1 = "); printreg(minus1);
// printf("================================\n");
// printf("\n");
// printf("sdiag : ");
// printreg(sminus2);
// printf("scur : ");
// printreg(scurrent);
// printf("current: ");
// printreg(current);
// printf("%8s\n",seq1);
// printf("%8s\n",seq2);
// printf("================================\n");
} ///// <<<<<<<<------- Fin du debut de la premiere bande
// printf("================================\n");
(column)->data.CMENB[lseq2-VSIZE+line]=EXTRACT_REG(current,VSIZE-1);
if (lpath)
(column)->score.CMENB[lseq2-VSIZE+line]=EXTRACT_REG(scurrent,VSIZE-1);
for (band=0; band < nbands; band++)
{
// SET_H_SYMBOLE(fhseq,line,h)
// minus2 = insert_reg(minus2,0,line);
// minus1 = insert_reg(minus1,MIN_SCORE,line); // 0 avant
// h++;
for (; line < lseq2; line++)
{
// printf("Je tourne avec line= %d \n",line);
PUSH_V_SYMBOLE(fvseq,line)
match = EQUAL(fhseq,fvseq);
// printreg(fvseq);
// printreg(fhseq);
// printreg(match);
// printf("================================\n");
current = minus1;
left = minus1;
// Store the last current score in extra column
(column)->data.CMENB[line-VSIZE]=EXTRACT_REG(current,VSIZE-1);
LSHIFT_SCORE(minus1)
minus1=insert_reg(minus1,(column)->data.CMENB[line],0);
top = minus1;
// printf("Vert = "); printreg(current);
if (lpath)
{
sleft= sminus1;
(column)->score.CMENB[line-VSIZE]=EXTRACT_REG(scurrent,VSIZE-1);
LSHIFT_SCORE(sminus1)
sminus1=insert_reg(sminus1,(column)->score.CMENB[line],0);
stop=sminus1;
sdiag=sminus2;
}
// printf("line = %d --> get = %d\n",line,(column)->data.CMENB[line]);
// printf("Horz = "); printreg(minus1);
current = GET_MAX(current,minus1);
diag=minus2;
current = GET_MAX(current,ADD_REG(minus2,match));
if (lpath)
{
// printf("\n");
// printf("current: ");
// printreg(current);
// printf("current: ");
// printreg(SUB_REG(current,match));
// printf("diag : ");
// printreg(diag);
// printf("left : ");
// printreg(left);
// printf("top : ");
// printreg(top);
way = EQUAL_REG(SUB_REG(current,match),diag);
scurrent= OR_REG(AND_REG(way,sdiag),
ANDNOT_REG(way,maxvect));
// printf("sdiag : ");
// printreg(scurrent);
way = EQUAL_REG(current,left);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,sleft),
ANDNOT_REG(way,maxvect)));
// printf("sleft : ");
// printreg(scurrent);
way = EQUAL_REG(current,top);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,stop),
ANDNOT_REG(way,maxvect)));
// printf("stop : ");
// printreg(scurrent);
scurrent= ADD_REG(scurrent,onevect);
sminus2=sminus1;
sminus1=scurrent;
}
minus2=minus1;
minus1=current;
// printf("\n");
// printf("sdiag : ");
// printreg(sminus2);
// printf("scur : ");
// printreg(scurrent);
// printf("current: ");
// printreg(current);
// printf("%8s\n",seq1);
// printf("%8s\n",seq2);
}
// printf("================================\n");
// end of the band and beginnig of the next one
limit=(band==(nbands-1)) ? lastband:VSIZE;
for (line = 0; line < limit; line++,h++)
{
// printf("Je fini avec line= %d \n",line);
SET_H_SYMBOLE(fhseq,line,h)
PUSH_V_SYMBOLE(fvseq,line)
minus2 = insert_reg(minus2,MIN_SCORE,line);
minus1 = insert_reg(minus1,MIN_SCORE,line);
current = minus1;
left=minus1;
match = EQUAL(fhseq,fvseq);
if (lpath)
{
sminus2 = insert_reg(sminus2,lseq2-VSIZE+line,line);
sminus1 = insert_reg(sminus1,h,line);
sleft= sminus1;
}
// printf("\n");
// printf("fhseq = "); printreg(fhseq);
// printf("fvseq = "); printreg(fvseq);
// printf("----------------------------------------------------------------\n");
// printf("match = "); printreg(match);
(column)->data.CMENB[lseq2-VSIZE+line]=EXTRACT_REG(current,VSIZE-1);
LSHIFT_SCORE(minus1)
minus1=insert_reg(minus1,(column)->data.CMENB[line],0);
top=minus1;
current = GET_MAX(current,minus1);
if (lpath)
{
(column)->score.CMENB[lseq2-VSIZE+line]=EXTRACT_REG(scurrent,VSIZE-1);
LSHIFT_SCORE(sminus1)
sminus1=insert_reg(sminus1,(column)->score.CMENB[line],0);
stop=sminus1;
sdiag=sminus2;
way = EQUAL_REG(current,minus1);
scurrent= OR_REG(AND_REG(way,sminus1),
ANDNOT_REG(way,scurrent));
}
diag=minus2;
current = GET_MAX(current,ADD_REG(minus2,match));
if (lpath)
{
way = EQUAL_REG(SUB_REG(current,match),diag);
scurrent= OR_REG(AND_REG(way,sdiag),
ANDNOT_REG(way,maxvect));
way = EQUAL_REG(current,left);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,sleft),
ANDNOT_REG(way,maxvect)));
way = EQUAL_REG(current,top);
scurrent= GET_MIN(scurrent,OR_REG(AND_REG(way,stop),
ANDNOT_REG(way,maxvect)));
scurrent= ADD_REG(scurrent,onevect);
sminus2=sminus1;
sminus1=scurrent;
}
// printf("currt = "); printreg(current);
minus2=minus1;
minus1=current;
// printf("\n");
// printf("sdiag : ");
// printreg(sminus2);
// printf("scur : ");
// printreg(scurrent);
// printf("current: ");
// printreg(current);
// printf("%8s\n",seq1);
// printf("%8s\n",seq2);
// printf("Je stocke line= %d la valeur %d\n",lseq2-VSIZE+line,(column)->data.CMENB[lseq2-VSIZE+line]);
}
}
// printf("\n");
// printf("line = %d, h= %d, lastband = %d\n",line,h,lastband);
// printf("currt = "); printreg(current);
lcs = extract_reg(current,lastband);
if(lpath)
*lpath= extract_reg(scurrent,lastband);
// printf("lastband = %d (%d) lcs = %d\n",lastband,lseq2,lcs);
if (ppcolumn)
*ppcolumn=column;
else
freeColumn(column);
return lcs;
}
#else
int FASTLCSSCORE(const char* seq1, const char* seq2,column_pp ppcolumn,int32_t* lpath)
{
return simpleLCS(seq1,seq2,ppcolumn,lpath);
}
#endif /* __SSE2__ */

View File

@ -0,0 +1,211 @@
/*
* banded_LCS_alignment.c
*
* Created on: 7 nov. 2012
* Author: merciece
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "../libutils/utilities.h"
typedef struct {
int score;
int l_path;
}infos;
int calculateScore(char nuc1, char nuc2)
{
return(nuc1 == nuc2);
}
infos** banded_align(char *seq1, char *seq2, int l1, int l2, int bandLengthRight, int bandLengthLeft)
{
int i, j;
//int c;
//double id;
int start, end;
int diag_score, delete, insert, mismatch;
int l_path, l_path_i, l_path_d;
int bestScore;
int mismatch_margin;
int stop;
int diag_index;
infos **matrix;
l1++;
l2++;
mismatch_margin = bandLengthLeft; // the biggest one
diag_index = l1-l2; // diagonal index
stop=0;
//fprintf(stderr,"\nseq1 = %s, seq2=%s, bandLengthR = %d, bandLengthL = %d", seq1, seq2, bandLengthRight, bandLengthLeft);
// Matrix initialization~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
matrix = (infos**) malloc(l1 * sizeof(infos*));
for (i = 0; i < l1; i++)
matrix[i] = (infos*) malloc(l2 * sizeof(infos));
for (i = 0; i < l1; i++)
for (j = 0; j < l2; j++)
{
matrix[i][j].score = 0;
matrix[i][j].l_path = 0;
}
for (i = 0; i < l1; i++)
matrix[i][0].l_path = i;
for (j = 0; j < l2; j++)
matrix[0][j].l_path = j;
// Matrix initialized~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for (i = 1; i < l1; i++)
{
start = i - bandLengthLeft;
if (start < 1)
start = 1;
end = i+bandLengthRight+1;
if (end > l2)
end = l2;
for (j = start; j < end; j++)
{
delete = matrix[i-1][j].score;
l_path_d = matrix[i-1][j].l_path + 1;
insert = matrix[i][j-1].score;
l_path_i = matrix[i][j-1].l_path + 1;
mismatch = 0;
diag_score = calculateScore(seq1[i-1], seq2[j-1]);
bestScore = matrix[i-1][j-1].score + diag_score;
l_path = matrix[i-1][j-1].l_path + 1;
if (diag_score == 0) // mismatch
mismatch = 1;
if ((insert > bestScore) || ((insert == bestScore) && (l_path_i < l_path)))
{
bestScore = matrix[i][j-1].score;
l_path = l_path_i;
mismatch = 0;
}
if ((delete > bestScore) || ((delete == bestScore) && (l_path_d < l_path)))
{
bestScore = delete;
l_path = l_path_d;
mismatch = 0;
}
/*if (((i-j) - diag_index == 0) && (mismatch == 1))
{
//fprintf(stderr, "\nR = %d, L = %d\n", bandLengthRight, bandLengthLeft);
if (bandLengthRight+bandLengthLeft == 0)
{
stop = 1;
//fprintf(stderr, "\nBREAKING LOOPS\n");
break;
}
if (bandLengthRight != 0)
bandLengthRight = bandLengthRight - 1;
if (bandLengthLeft != 0)
bandLengthLeft = bandLengthLeft - 1;
}*/
(matrix[i][j]).score = bestScore;
(matrix[i][j]).l_path = l_path;
}
//if ((bandLengthRight + bandLengthLeft == 0) && ((matrix[i][j].l_path - matrix[i][j].score) > mismatch_margin))
if (stop==1)
break;
}
return(matrix);
}
void calculateBandLength(int l1, int l2, double threshold, int* bandLengthRight, int* bandLengthLeft)
{
(*bandLengthLeft) = round(-l1 * threshold + l1);
(*bandLengthRight) = round(-l1 * threshold + l2);
// fprintf(stderr,"\nR=%d, L=%d", (*bandLengthRight), (*bandLengthLeft));
}
double calculateId(infos** matrix, int len1, int len2)
{
double id;
int l_ali;
int l_lcs;
l_lcs = matrix[len1][len2].score;
l_ali = matrix[len1][len2].l_path;
if (l_lcs == 0)
id = 0.0;
else
id = (double) l_lcs / (double) l_ali;
//fprintf(stderr, "\n%d, %d\n", l_lcs, l_ali);
return(id);
}
double banded_lcs_align(int16_t* seq1, int16_t* seq2, int l1, int l2, double threshold, BOOL n, int ref, BOOL lcsmode, int16_t* address)
{
double id;
int bandLengthRight, bandLengthLeft;
int i,j;
char* s1;
char* s2;
s1 = (char*) malloc(l1*sizeof(char)+1);
s2 = (char*) malloc(l2*sizeof(char)+1);
for (i=l1-1, j=0; i>=0, j<l1; i--, j++)
*(s1+i) = (char) *(seq1+j);
for (i=0; i<l2; i++)
*(s2+i) = (char) *(seq2+i);
*(s1+l1) = 0;
*(s2+l2) = 0;
//fprintf(stderr, "\nl1=%d, %s\nl2=%d, %s\n", l1, s1, l2, s2);
infos** matrix;
calculateBandLength(l1, l2, threshold, &bandLengthRight, &bandLengthLeft);
matrix = banded_align(s1, s2, l1, l2, bandLengthRight, bandLengthLeft);
/*fprintf(stderr, "\n");
for (i = 0; i <= l1; i++)
{
fprintf(stderr, "\n");
for (j = 0; j <= l2; j++)
fprintf(stderr, "%d/%d\t", matrix[i][j].score, matrix[i][j].l_path); //matrix[i][j].stop);
}
fprintf(stderr, "\n");*/
id = calculateId(matrix, l1, l2);
for (i = 0; i <= l1; i++)
free(matrix[i]);
free(matrix);
free(s1);
free(s2);
//fprintf(stderr, "\nscore = %lf\n", id);
return(id);
}

View File

@ -0,0 +1,9 @@
/*
* banded_LCS_alignment.h
*
* Created on: november 8, 2012
* Author: mercier
*/
double banded_lcs_align(int16_t* seq1, int16_t* seq2, int l1, int l2, double threshold, BOOL n, int ref, BOOL lcsmode, int16_t* address);

View File

@ -0,0 +1,724 @@
/*
* sse_banded_LCS_alignment.c
*
* Created on: 7 nov. 2012
* Author: celine mercier
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include "../libutils/utilities.h"
#include "../libsse/_sse.h"
/*static void printreg(__m128i r)
{
int16_t a0,a1,a2,a3,a4,a5,a6,a7;
a0= _MM_EXTRACT_EPI16(r,0);
a1= _MM_EXTRACT_EPI16(r,1);
a2= _MM_EXTRACT_EPI16(r,2);
a3= _MM_EXTRACT_EPI16(r,3);
a4= _MM_EXTRACT_EPI16(r,4);
a5= _MM_EXTRACT_EPI16(r,5);
a6= _MM_EXTRACT_EPI16(r,6);
a7= _MM_EXTRACT_EPI16(r,7);
fprintf(stderr, "a00 :-> %7d %7d %7d %7d "
" %7d %7d %7d %7d "
"\n"
, a0,a1,a2,a3,a4,a5,a6,a7
);
}
*/
static inline int extract_reg(__m128i r, int p)
{
switch (p) {
case 0: return(_MM_EXTRACT_EPI16(r,0));
case 1: return(_MM_EXTRACT_EPI16(r,1));
case 2: return(_MM_EXTRACT_EPI16(r,2));
case 3: return(_MM_EXTRACT_EPI16(r,3));
case 4: return(_MM_EXTRACT_EPI16(r,4));
case 5: return(_MM_EXTRACT_EPI16(r,5));
case 6: return(_MM_EXTRACT_EPI16(r,6));
case 7: return(_MM_EXTRACT_EPI16(r,7));
}
return(0);
}
void sse_banded_align_lcs_and_ali_len(int16_t* seq1, int16_t* seq2, int l1, int l2, int bandLengthLeft, int bandLengthTotal, int16_t* address, double* lcs_length, int* ali_length)
{
register int j;
int k1, k2;
int max, diff;
int l_reg, l_loc;
int line;
int numberOfRegistersPerLine;
int numberOfRegistersFor3Lines;
BOOL even_line;
BOOL odd_line;
BOOL even_BLL;
BOOL odd_BLL;
um128* SSEregisters;
um128* p_diag;
um128* p_gap1;
um128* p_gap2;
um128* p_diag_j;
um128* p_gap1_j;
um128* p_gap2_j;
um128 current;
um128* l_ali_SSEregisters;
um128* p_l_ali_diag;
um128* p_l_ali_gap1;
um128* p_l_ali_gap2;
um128* p_l_ali_diag_j;
um128* p_l_ali_gap1_j;
um128* p_l_ali_gap2_j;
um128 l_ali_current;
um128 nucs1;
um128 nucs2;
um128 scores;
um128 boolean_reg;
// Initialisations
odd_BLL = bandLengthLeft & 1;
even_BLL = !odd_BLL;
max = INT16_MAX - l1;
numberOfRegistersPerLine = bandLengthTotal / 8;
numberOfRegistersFor3Lines = 3 * numberOfRegistersPerLine;
SSEregisters = (um128*) calloc(numberOfRegistersFor3Lines * 2, sizeof(um128));
l_ali_SSEregisters = SSEregisters + numberOfRegistersFor3Lines;
// preparer registres SSE
for (j=0; j<numberOfRegistersFor3Lines; j++)
l_ali_SSEregisters[j].i = _MM_LOAD_SI128(address+j*8);
p_diag = SSEregisters;
p_gap1 = SSEregisters+numberOfRegistersPerLine;
p_gap2 = SSEregisters+2*numberOfRegistersPerLine;
p_l_ali_diag = l_ali_SSEregisters;
p_l_ali_gap1 = l_ali_SSEregisters+numberOfRegistersPerLine;
p_l_ali_gap2 = l_ali_SSEregisters+2*numberOfRegistersPerLine;
// Loop on diagonals = 'lines' :
for (line=2; line <= l1+l2; line++)
{
odd_line = line & 1;
even_line = !odd_line;
// loop on the registers of a line :
for (j=0; j < numberOfRegistersPerLine; j++)
{
p_diag_j = p_diag+j;
p_gap1_j = p_gap1+j;
p_gap2_j = p_gap2+j;
p_l_ali_diag_j = p_l_ali_diag+j;
p_l_ali_gap1_j = p_l_ali_gap1+j;
p_l_ali_gap2_j = p_l_ali_gap2+j;
// comparing nucleotides for diagonal scores :
// k1 = position of the 1st nucleotide to align for seq1 and k2 = position of the 1st nucleotide to align for seq2
if (odd_line && odd_BLL)
k1 = (line / 2) + ((bandLengthLeft+1) / 2) - j*8;
else
k1 = (line / 2) + (bandLengthLeft/2) - j*8;
k2 = line - k1 - 1;
nucs1.i = _MM_LOADU_SI128(seq1+l1-k1);
nucs2.i = _MM_LOADU_SI128(seq2+k2);
/* fprintf(stderr, "\nnucs, r %d, k1 = %d, k2 = %d\n", j, k1, k2);
printreg(nucs1.i);
printreg(nucs2.i);
*/
// computing diagonal score :
scores.i = _MM_AND_SI128(_MM_CMPEQ_EPI16(nucs1.i, nucs2.i), _MM_SET1_EPI16(1));
current.i = _MM_ADDS_EPU16(p_diag_j->i, scores.i);
// Computing alignment length
l_ali_current.i = p_l_ali_diag_j->i;
boolean_reg.i = _MM_CMPGT_EPI16(p_gap1_j->i, current.i);
l_ali_current.i = _MM_OR_SI128(
_MM_AND_SI128(p_l_ali_gap1_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, l_ali_current.i));
current.i = _MM_OR_SI128(
_MM_AND_SI128(p_gap1_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, current.i));
boolean_reg.i = _MM_AND_SI128(
_MM_CMPEQ_EPI16(p_gap1_j->i, current.i),
_MM_CMPLT_EPI16(p_l_ali_gap1_j->i, l_ali_current.i));
l_ali_current.i = _MM_OR_SI128(
_MM_AND_SI128(p_l_ali_gap1_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, l_ali_current.i));
current.i = _MM_OR_SI128(
_MM_AND_SI128(p_gap1_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, current.i));
boolean_reg.i = _MM_CMPGT_EPI16(p_gap2_j->i, current.i);
l_ali_current.i = _MM_OR_SI128(
_MM_AND_SI128(p_l_ali_gap2_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, l_ali_current.i));
current.i = _MM_OR_SI128(
_MM_AND_SI128(p_gap2_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, current.i));
boolean_reg.i = _MM_AND_SI128(
_MM_CMPEQ_EPI16(p_gap2_j->i, current.i),
_MM_CMPLT_EPI16(p_l_ali_gap2_j->i, l_ali_current.i));
l_ali_current.i = _MM_OR_SI128(
_MM_AND_SI128(p_l_ali_gap2_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, l_ali_current.i));
current.i = _MM_OR_SI128(
_MM_AND_SI128(p_gap2_j->i, boolean_reg.i),
_MM_ANDNOT_SI128(boolean_reg.i, current.i));
/* fprintf(stderr, "\nline = %d", line);
fprintf(stderr, "\nDiag, r %d : ", j);
printreg((*(p_diag_j)).i);
fprintf(stderr, "Gap1 : ");
printreg((*(p_gap1_j)).i);
fprintf(stderr, "Gap2 : ");
printreg((*(p_gap2_j)).i);
fprintf(stderr, "current : ");
printreg(current.i);
fprintf(stderr, "L ALI\nDiag r %d : ", j);
printreg((*(p_l_ali_diag_j)).i);
fprintf(stderr, "Gap1 : ");
printreg((*(p_l_ali_gap1_j)).i);
fprintf(stderr, "Gap2 : ");
printreg((*(p_l_ali_gap2_j)).i);
fprintf(stderr, "current : ");
printreg(l_ali_current.i);
*/
// diag = gap1 and gap1 = current
p_diag_j->i = p_gap1_j->i;
p_gap1_j->i = current.i;
// l_ali_diag = l_ali_gap1 and l_ali_gap1 = l_ali_current+1
p_l_ali_diag_j->i = p_l_ali_gap1_j->i;
p_l_ali_gap1_j->i = _MM_ADD_EPI16(l_ali_current.i, _MM_SET1_EPI16(1));
}
// shifts for gap2, to do only once all the registers of a line have been computed Copier gap2 puis le charger depuis la copie?
for (j=0; j < numberOfRegistersPerLine; j++)
{
if ((odd_line && even_BLL) || (even_line && odd_BLL))
{
p_gap2[j].i = _MM_LOADU_SI128((p_gap1[j].s16)-1);
p_l_ali_gap2[j].i = _MM_LOADU_SI128((p_l_ali_gap1[j].s16)-1);
if (j == 0)
{
p_gap2[j].i = _MM_INSERT_EPI16(p_gap2[j].i, 0, 0);
p_l_ali_gap2[j].i = _MM_INSERT_EPI16(p_l_ali_gap2[j].i, max, 0);
}
}
else
{
p_gap2[j].i = _MM_LOADU_SI128(p_gap1[j].s16+1);
p_l_ali_gap2[j].i = _MM_LOADU_SI128(p_l_ali_gap1[j].s16+1);
if (j == numberOfRegistersPerLine - 1)
{
p_gap2[j].i = _MM_INSERT_EPI16(p_gap2[j].i, 0, 7);
p_l_ali_gap2[j].i = _MM_INSERT_EPI16(p_l_ali_gap2[j].i, max, 7);
}
}
}
// end shifts for gap2
}
/* /// Recovering LCS and alignment lengths \\\ */
// finding the location of the results in the registers :
diff = l1-l2;
if ((diff & 1) && odd_BLL)
l_loc = (int) floor((double)(bandLengthLeft) / (double)2) - floor((double)(diff) / (double)2);
else
l_loc = (int) floor((double)(bandLengthLeft) / (double)2) - ceil((double)(diff) / (double)2);
l_reg = (int)floor((double)l_loc/(double)8.0);
//fprintf(stderr, "\nl_reg = %d, l_loc = %d\n", l_reg, l_loc);
l_loc = l_loc - l_reg*8;
// extracting the results from the registers :
*lcs_length = extract_reg(p_gap1[l_reg].i, l_loc);
*ali_length = extract_reg(p_l_ali_gap1[l_reg].i, l_loc) - 1;
// freeing the registers
free(SSEregisters);
}
double sse_banded_align_just_lcs(int16_t* seq1, int16_t* seq2, int l1, int l2, int bandLengthLeft, int bandLengthTotal)
{
register int j;
int k1, k2;
int diff;
int l_reg, l_loc;
int16_t l_lcs;
int line;
int numberOfRegistersPerLine;
int numberOfRegistersFor3Lines;
BOOL even_line;
BOOL odd_line;
BOOL even_BLL;
BOOL odd_BLL;
um128* SSEregisters;
um128* p_diag;
um128* p_gap1;
um128* p_gap2;
um128* p_diag_j;
um128* p_gap1_j;
um128* p_gap2_j;
um128 current;
um128 nucs1;
um128 nucs2;
um128 scores;
// Initialisations
odd_BLL = bandLengthLeft & 1;
even_BLL = !odd_BLL;
numberOfRegistersPerLine = bandLengthTotal / 8;
numberOfRegistersFor3Lines = 3 * numberOfRegistersPerLine;
SSEregisters = malloc(numberOfRegistersFor3Lines * sizeof(um128));
// preparer registres SSE
for (j=0; j<numberOfRegistersFor3Lines; j++)
(*(SSEregisters+j)).i = _MM_SETZERO_SI128();
p_diag = SSEregisters;
p_gap1 = SSEregisters+numberOfRegistersPerLine;
p_gap2 = SSEregisters+2*numberOfRegistersPerLine;
// Loop on diagonals = 'lines' :
for (line=2; line <= l1+l2; line++)
{
odd_line = line & 1;
even_line = !odd_line;
// loop on the registers of a line :
for (j=0; j < numberOfRegistersPerLine; j++)
{
p_diag_j = p_diag+j;
p_gap1_j = p_gap1+j;
p_gap2_j = p_gap2+j;
// comparing nucleotides for diagonal scores :
// k1 = position of the 1st nucleotide to align for seq1 and k2 = position of the 1st nucleotide to align for seq2
if (odd_line && odd_BLL)
k1 = (line / 2) + ((bandLengthLeft+1) / 2) - j*8;
else
k1 = (line / 2) + (bandLengthLeft/2) - j*8;
k2 = line - k1 - 1;
nucs1.i = _MM_LOADU_SI128(seq1+l1-k1);
nucs2.i = _MM_LOADU_SI128(seq2+k2);
// computing diagonal score :
scores.i = _MM_AND_SI128(_MM_CMPEQ_EPI16(nucs1.i, nucs2.i), _MM_SET1_EPI16(1));
current.i = _MM_ADDS_EPU16((*(p_diag_j)).i, scores.i);
// current = max(gap1, current)
current.i = _MM_MAX_EPI16((*(p_gap1_j)).i, current.i);
// current = max(gap2, current)
current.i = _MM_MAX_EPI16((*(p_gap2_j)).i, current.i);
// diag = gap1 and gap1 = current
(*(p_diag_j)).i = (*(p_gap1_j)).i;
(*(p_gap1_j)).i = current.i;
}
// shifts for gap2, to do only once all the registers of a line have been computed
for (j=0; j < numberOfRegistersPerLine; j++)
{
if ((odd_line && even_BLL) || (even_line && odd_BLL))
{
(*(p_gap2+j)).i = _MM_LOADU_SI128(((*(p_gap1+j)).s16)-1);
if (j == 0)
{
(*(p_gap2+j)).i = _MM_INSERT_EPI16((*(p_gap2+j)).i, 0, 0);
}
}
else
{
(*(p_gap2+j)).i = _MM_LOADU_SI128(((*(p_gap1+j)).s16)+1);
if (j == numberOfRegistersPerLine - 1)
{
(*(p_gap2+j)).i = _MM_INSERT_EPI16((*(p_gap2+j)).i, 0, 7);
}
}
}
// end shifts for gap2
}
/* /// Recovering LCS and alignment lengths \\\ */
// finding the location of the results in the registers :
diff = l1-l2;
if ((diff & 1) && odd_BLL)
l_loc = (int) floor((double)(bandLengthLeft) / (double)2) - floor((double)(diff) / (double)2);
else
l_loc = (int) floor((double)(bandLengthLeft) / (double)2) - ceil((double)(diff) / (double)2);
l_reg = (int)floor((double)l_loc/(double)8.0);
//fprintf(stderr, "\nl_reg = %d, l_loc = %d\n", l_reg, l_loc);
l_loc = l_loc - l_reg*8;
// extracting LCS from the registers :
l_lcs = extract_reg((*(p_gap1+l_reg)).i, l_loc);
// freeing the registers
free(SSEregisters);
return((double) l_lcs);
}
inline void calculateBandLengths(int l1, int l2, int* bandLengthRight, int* bandLengthLeft, int LCSmin)
{
(*bandLengthLeft) = l1 - LCSmin;
(*bandLengthRight) = l2 - LCSmin;
}
int calculateLCSmin(int l1, int l2, double threshold, BOOL normalize, int reference, BOOL lcsmode)
{
int LCSmin;
if (threshold > 0)
{
if (normalize)
{
if (reference == MINLEN)
LCSmin = threshold*l2;
else // ref = maxlen or alilen
LCSmin = threshold*l1;
}
else if (lcsmode)
LCSmin = threshold;
else if ((reference == MINLEN)) // not lcsmode
LCSmin = l2 - threshold;
else // not lcsmode and ref = maxlen or alilen
LCSmin = l1 - threshold;
}
else
LCSmin = 0;
return(LCSmin);
}
int calculateSSEBandLength(int bandLengthRight, int bandLengthLeft)
{
// *bandLengthTotal= (double) floor(bandLengthRight + bandLengthLeft) / 2.0 + 1;
int bandLengthTotal= (double)(bandLengthRight + bandLengthLeft) / 2.0 + 1.0;
return (bandLengthTotal & (~ (int)7)) + (( bandLengthTotal & (int)7) ? 8:0); // Calcule le multiple de 8 superieur
}
int calculateSizeToAllocate(int maxLen, int minLen, int LCSmin)
{
int size;
int notUsed;
calculateBandLengths(maxLen, minLen, &notUsed, &size, LCSmin); // max size = max left band length * 2
//fprintf(stderr, "\nsize for address before %8 = %d", size);
size*= 2;
size = (size & (~ (int)7)) + (( size & (int)7) ? 8:0); // Calcule le multiple de 8 superieur
size*= 3;
size+= 16;
//fprintf(stderr, "\nsize for address = %d", size);
return(size*sizeof(int16_t));
}
void iniSeq(int16_t* seq, int size, int16_t iniValue)
{
int16_t *target=seq;
int16_t *end = target + (size_t)size;
for (; target < end; target++)
*target = iniValue;
}
void putSeqInSeq(int16_t* seq, char* s, int l, BOOL reverse)
{
int16_t *target=seq;
int16_t *end = target + (size_t)l;
char *source=s;
if (reverse)
for (source=s + (size_t)l-1; target < end; target++, source--)
*target=*source;
else
for (; target < end; source++,target++)
*target=*source;
}
void initializeAddressWithGaps(int16_t* address, int bandLengthTotal, int bandLengthLeft, int l1)
{
int i;
int address_00, x_address_10, address_01, address_01_shifted;
int numberOfRegistersPerLine;
int bm;
int value=INT16_MAX-l1;
numberOfRegistersPerLine = bandLengthTotal / 8;
bm = bandLengthLeft%2;
for (i=0; i < (3*numberOfRegistersPerLine*8); i++)
address[i] = value;
// 0,0 set to 1 and 0,1 and 1,0 set to 2
address_00 = bandLengthLeft / 2;
x_address_10 = address_00 + bm - 1;
address_01 = numberOfRegistersPerLine*8 + x_address_10;
address_01_shifted = numberOfRegistersPerLine*16 + address_00 - bm;
// fill address_00, address_01,+1, address_01_shifted,+1
address[address_00] = 1;
address[address_01] = 2;
address[address_01+1] = 2;
address[address_01_shifted] = 2;
address[address_01_shifted+1] = 2;
}
double sse_banded_lcs_align(int16_t* seq1, int16_t* seq2, int l1, int l2, BOOL normalize, int reference, BOOL lcsmode, int16_t* address, int LCSmin)
{
double id;
int bandLengthRight, bandLengthLeft, bandLengthTotal;
int ali_length;
//fprintf(stderr, "\nl1 = %d, l2 = %d\n", l1, l2);
calculateBandLengths(l1, l2, &bandLengthRight, &bandLengthLeft, LCSmin);
//fprintf(stderr, "\nBLL = %d, BLR = %d, LCSmin = %d\n", bandLengthLeft, bandLengthRight, LCSmin);
bandLengthTotal = calculateSSEBandLength(bandLengthRight, bandLengthLeft);
//fprintf(stderr, "\nBLT = %d\n", bandLengthTotal);
if ((reference == ALILEN) && (normalize || !lcsmode))
{
initializeAddressWithGaps(address, bandLengthTotal, bandLengthLeft, l1);
sse_banded_align_lcs_and_ali_len(seq1, seq2, l1, l2, bandLengthLeft, bandLengthTotal, address, &id, &ali_length);
}
else
id = sse_banded_align_just_lcs(seq1, seq2, l1, l2, bandLengthLeft, bandLengthTotal);
//fprintf(stderr, "\nid before normalizations = %f", id);
//fprintf(stderr, "\nlcs = %f, ali = %d\n", id, ali_length);
if (!lcsmode && !normalize)
switch(reference) {
case ALILEN: id = ali_length - id;
break;
case MAXLEN: id = l1 - id;
break;
case MINLEN: id = l2 - id;
}
//fprintf(stderr, "\n2>>> %f, %d\n", id, ali_length);
if (normalize)
switch(reference) {
case ALILEN: id = id / (double) ali_length;
break;
case MAXLEN: id = id / (double) l1;
break;
case MINLEN: id = id / (double) l2;
}
//fprintf(stderr, "\nid = %f\n", id);
return(id);
}
double generic_sse_banded_lcs_align(char* seq1, char* seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, int16_t** address, int* buffer_size, int16_t** iseq1,
int16_t** iseq2, int* buffer_sizeS)
{
double id;
int l1;
int l2;
int lmax, lmin;
int sizeToAllocateForBand;
int maxBLL, notUsed;
int sizeToAllocateForSeqs;
int LCSmin;
l1 = strlen(seq1);
l2 = strlen(seq2);
if (l2 > l1)
{
lmax = l1;
lmin = l2;
}
else
{
lmax = l2;
lmin = l1;
}
if (!lcsmode && (normalize==TRUE))
{
threshold = 1.0 - threshold;
}
LCSmin = calculateLCSmin(lmax, lmin, threshold, normalize, reference, lcsmode);
// Allocating space for matrix band if the alignment must be computed
if ((reference == ALILEN) && ((lcsmode && normalize) || (!lcsmode))) // checking if alignment must be computed
{
sizeToAllocateForBand = calculateSizeToAllocate(lmax, lmin, LCSmin);
if (sizeToAllocateForBand > (*buffer_size))
{
// reallocating if needed
address = reallocA16Address(*address, sizeToAllocateForBand);
}
}
// Allocating space for the int16_t arrays representing the sequences
calculateBandLengths(lmax, lmin, &notUsed, &maxBLL, LCSmin);
sizeToAllocateForSeqs = 2*maxBLL+lmax;
if (sizeToAllocateForSeqs > *buffer_sizeS)
{
(*(iseq1)) = realloc((*(iseq1)), sizeToAllocateForSeqs*sizeof(int16_t));
(*(iseq2)) = realloc((*(iseq2)), sizeToAllocateForSeqs*sizeof(int16_t));
}
iniSeq(*(iseq1), maxBLL, 0);
iniSeq(*(iseq2), maxBLL, 255);
*(iseq1) = *(iseq1)+maxBLL;
*(iseq2) = *(iseq2)+maxBLL;
// longest seq must be first argument of sse_align function
if (l2 > l1)
{
putSeqInSeq((*(iseq1)), seq2, l2, TRUE);
putSeqInSeq((*(iseq2)), seq1, l1, FALSE);
id = sse_banded_lcs_align(*(iseq1), *(iseq2), l2, l1, normalize, reference, lcsmode, *address, LCSmin);
}
else
{
putSeqInSeq((*(iseq1)), seq1, l1, TRUE);
putSeqInSeq((*(iseq2)), seq2, l2, FALSE);
id = sse_banded_lcs_align(*(iseq1), *(iseq2), l1, l2, normalize, reference, lcsmode, *address, LCSmin);
}
return(id);
}
int prepareTablesForSumathings(int lmax, int lmin, double threshold, BOOL normalize, int reference, BOOL lcsmode,
int16_t** address, int16_t** iseq1, int16_t** iseq2)
{
int sizeToAllocateForBand;
int maxBLL;
int notUsed;
int sizeToAllocateForSeqs;
int LCSmin;
LCSmin = calculateLCSmin(lmax, lmin, threshold, normalize, reference, lcsmode);
// Allocating space for matrix band if the alignment must be computed
if ((reference == ALILEN) && (normalize || !lcsmode)) // checking if alignment must be computed
{
sizeToAllocateForBand = calculateSizeToAllocate(lmax, lmin, LCSmin);
(*(address)) = getA16Address(sizeToAllocateForBand);
}
// Allocating space for the int16_t arrays representing the sequences
calculateBandLengths(lmax, lmin, &notUsed, &maxBLL, LCSmin);
sizeToAllocateForSeqs = 2*maxBLL+lmax;
(*(iseq1)) = malloc(sizeToAllocateForSeqs*sizeof(int16_t));
(*(iseq2)) = malloc(sizeToAllocateForSeqs*sizeof(int16_t));
iniSeq(*(iseq1), maxBLL, 0);
iniSeq(*(iseq2), maxBLL, 255);
*(iseq1) = *(iseq1)+maxBLL;
*(iseq2) = *(iseq2)+maxBLL;
return(maxBLL+lmax);
}
double alignForSumathings(char* seq1, int16_t* iseq1, char* seq2, int16_t* iseq2, int l1, int l2,
BOOL normalize, int reference, BOOL lcsmode, int16_t* address, int sizeForSeqs, int LCSmin)
{
double id;
iniSeq(iseq1, sizeForSeqs, 0);
iniSeq(iseq2, sizeForSeqs, 255);
if (l2 > l1)
{
putSeqInSeq(iseq1, seq2, l2, TRUE);
putSeqInSeq(iseq2, seq1, l1, FALSE);
id = sse_banded_lcs_align(iseq1, iseq2, l2, l1, normalize, reference, lcsmode, address, LCSmin);
}
else
{
putSeqInSeq(iseq1, seq1, l1, TRUE);
putSeqInSeq(iseq2, seq2, l2, FALSE);
id = sse_banded_lcs_align(iseq1, iseq2, l1, l2, normalize, reference, lcsmode, address, LCSmin);
}
return(id);
}

View File

@ -0,0 +1,24 @@
/*
* sse_banded_LCS_alignment.h
*
* Created on: november 29, 2012
* Author: mercier
*/
#ifndef SSE_BANDED_LCS_ALIGNMENT_H_
#define SSE_BANDED_LCS_ALIGNMENT_H_
#include <stdint.h>
double sse_banded_lcs_align(int16_t* seq1, int16_t* seq2, int l1, int l2, BOOL normalize, int reference, BOOL lcsmode, int16_t* address, int LCSmin);
int calculateSizeToAllocate(int maxLen, int minLen, int LCSmin);
void calculateThresholdFromErrorNumber(int error, int length, double* threshold);
void iniSeq(int16_t* seq, int size, int16_t iniValue);
void putSeqInSeq(int16_t* seq, char* s, int l, BOOL reverse);
double generic_sse_banded_lcs_align(char* seq1, char* seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, int16_t** address, int* buffer_size, int16_t** iseq1,
int16_t** iseq2, int* buffer_sizeS);
int prepareTablesForSumathings(int lmax, int lmin, double threshold, BOOL normalize, int reference, BOOL lcsmode,
int16_t** address, int16_t** iseq1, int16_t** iseq2);
double alignForSumathings(char* seq1, int16_t* iseq1, char* seq2, int16_t* iseq2, int l1, int l2, BOOL normalize,
int reference, BOOL lcsmode, int16_t* address, int sizeForSeqs, int LCSmin);
int calculateLCSmin(int l1, int l2, double threshold, BOOL normalize, int reference, BOOL lcsmode);
#endif

382
liblcs/upperband.c Normal file
View File

@ -0,0 +1,382 @@
#include "../libsse/_sse.h"
#include <stdio.h>
#include <math.h>
#include "../libutils/utilities.h"
#include "../libfasta/sequence.h"
#include "sse_banded_LCS_alignment.h"
inline static uchar_v hash4m128(uchar_v frag)
{
uchar_v words;
vUInt8 mask_03= _MM_SET1_EPI8(0x03); // charge le registre avec 16x le meme octet
vUInt8 mask_FC= _MM_SET1_EPI8(0xFC);
frag.m = _MM_SRLI_EPI64(frag.m,1); // shift logic a droite sur 2 x 64 bits
frag.m = _MM_AND_SI128(frag.m,mask_03); // and sur les 128 bits
words.m= _MM_SLLI_EPI64(frag.m,2);
words.m= _MM_AND_SI128(words.m,mask_FC);
frag.m = _MM_SRLI_SI128(frag.m,1);
words.m= _MM_OR_SI128(words.m,frag.m);
words.m= _MM_SLLI_EPI64(words.m,2);
words.m= _MM_AND_SI128(words.m,mask_FC);
frag.m = _MM_SRLI_SI128(frag.m,1);
words.m= _MM_OR_SI128(words.m,frag.m);
words.m= _MM_SLLI_EPI64(words.m,2);
words.m= _MM_AND_SI128(words.m,mask_FC);
frag.m = _MM_SRLI_SI128(frag.m,1);
words.m= _MM_OR_SI128(words.m,frag.m);
return words;
}
#ifdef __SSE2__
inline static int anyzerom128(vUInt8 data)
{
vUInt8 mask_00= _MM_SETZERO_SI128();
uint64_v tmp;
tmp.m = _MM_CMPEQ_EPI8(data,mask_00);
return (int)(tmp.c[0]!=0 || tmp.c[1]!=0);
}
#else
inline static int anyzerom128(vUInt8 data)
{
int i;
um128 tmp;
tmp.i = data;
for (i=0;i<8;i++)
if (tmp.s8[i]==0)
return 1;
return 0;
}
#endif
inline static void dumpm128(unsigned short *table,vUInt8 data)
{
memcpy(table,&data,16);
}
/**
* Compute 4mer occurrence table from a DNA sequence
*
* sequence : a pointer to the null terminated nuc sequence
* table : a pointer to a 256 cells unisgned char table for
* storing the occurrence table
* count : pointer to an int value used as a return value
* containing the global word counted
*
* returns the number of words observed in the sequence with a
* count greater than 255.
*/
int buildTable(const char* sequence, unsigned char *table, int *count)
{
int overflow = 0;
int wc=0;
int i;
vUInt8 mask_00= _MM_SETZERO_SI128();
uchar_v frag;
uchar_v words;
uchar_v zero;
char* s;
s=(char*)sequence;
memset(table,0,256*sizeof(unsigned char));
// encode ascii sequence with A : 00 C : 01 T: 10 G : 11
for(frag.m=_MM_LOADU_SI128((vUInt8*)s);
! anyzerom128(frag.m);
s+=12,frag.m=_MM_LOADU_SI128((vUInt8*)s))
{
words= hash4m128(frag);
// printf("%d %d %d %d\n",words.c[0],words.c[1],words.c[2],words.c[3]);
if (table[words.c[0]]<255) table[words.c[0]]++; else overflow++;
if (table[words.c[1]]<255) table[words.c[1]]++; else overflow++;
if (table[words.c[2]]<255) table[words.c[2]]++; else overflow++;
if (table[words.c[3]]<255) table[words.c[3]]++; else overflow++;
if (table[words.c[4]]<255) table[words.c[4]]++; else overflow++;
if (table[words.c[5]]<255) table[words.c[5]]++; else overflow++;
if (table[words.c[6]]<255) table[words.c[6]]++; else overflow++;
if (table[words.c[7]]<255) table[words.c[7]]++; else overflow++;
if (table[words.c[8]]<255) table[words.c[8]]++; else overflow++;
if (table[words.c[9]]<255) table[words.c[9]]++; else overflow++;
if (table[words.c[10]]<255) table[words.c[10]]++; else overflow++;
if (table[words.c[11]]<255) table[words.c[11]]++; else overflow++;
wc+=12;
}
zero.m=_MM_CMPEQ_EPI8(frag.m,mask_00);
//printf("frag=%d %d %d %d\n",frag.c[0],frag.c[1],frag.c[2],frag.c[3]);
//printf("zero=%d %d %d %d\n",zero.c[0],zero.c[1],zero.c[2],zero.c[3]);
words = hash4m128(frag);
if (zero.c[0]+zero.c[1]+zero.c[2]+zero.c[3]==0)
for(i=0;zero.c[i+3]==0;i++,wc++)
if (table[words.c[i]]<255) table[words.c[i]]++; else overflow++;
if (count) *count=wc;
return overflow;
}
static inline vUInt16 partialminsum(vUInt8 ft1,vUInt8 ft2)
{
vUInt8 mini;
vUInt16 minilo;
vUInt16 minihi;
vUInt8 mask_00= _MM_SETZERO_SI128();
mini = _MM_MIN_EPU8(ft1,ft2);
minilo = _MM_UNPACKLO_EPI8(mini,mask_00);
minihi = _MM_UNPACKHI_EPI8(mini,mask_00);
return _MM_ADDS_EPU16(minilo,minihi);
}
int compareTable(unsigned char *t1, int over1, unsigned char* t2, int over2)
{
vUInt8 ft1;
vUInt8 ft2;
vUInt8 *table1=(vUInt8*)t1;
vUInt8 *table2=(vUInt8*)t2;
ushort_v summini;
int i;
int total;
ft1 = _MM_LOADU_SI128(table1);
ft2 = _MM_LOADU_SI128(table2);
summini.m = partialminsum(ft1,ft2);
table1++;
table2++;
for (i=1;i<16;i++,table1++,table2++)
{
ft1 = _MM_LOADU_SI128(table1);
ft2 = _MM_LOADU_SI128(table2);
summini.m = _MM_ADDS_EPU16(summini.m,partialminsum(ft1,ft2));
}
// Finishing the sum process
summini.m = _MM_ADDS_EPU16(summini.m,_MM_SRLI_SI128(summini.m,8)); // sum the 4 firsts with the 4 lasts
summini.m = _MM_ADDS_EPU16(summini.m,_MM_SRLI_SI128(summini.m,4));
total = summini.c[0]+summini.c[1];
total+= (over1 < over2) ? over1:over2;
return total;
}
int threshold4(int wordcount,double identity)
{
int error;
int lmax;
wordcount+=3;
error = (int)floor((double)wordcount * ((double)1.0-identity));
lmax = (wordcount - error) / (error + 1);
if (lmax < 4)
return 0;
return (lmax - 3) \
* (error + 1) \
+ ((wordcount - error) % (error + 1));
}
int thresholdLCS4(int32_t reflen,int32_t lcs)
{
int nbfrag;
int smin;
int R;
int common;
nbfrag = (reflen - lcs)*2 + 1;
smin = lcs/nbfrag;
R = lcs - smin * nbfrag;
common = MAX(smin - 2,0) * R + MAX(smin - 3,0) * (nbfrag - R);
return common;
}
int hashDB(fastaSeqCount db)
{
int32_t i;
int32_t count;
fprintf(stderr,"Indexing dataset...");
for (i=0; i < db.count;i++)
{
db.fastaSeqs[i].table = util_malloc((256)*sizeof(unsigned char), __FILE__, __LINE__);
db.fastaSeqs[i].over = buildTable((const char*)(db.fastaSeqs[i].sequence),
db.fastaSeqs[i].table,
&count);
}
fprintf(stderr," : Done\n");
return db.count;
}
BOOL isPossible(fastaSeqPtr seq1, fastaSeqPtr seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode)
{
int32_t reflen;
int32_t maxlen;
int32_t lcs;
int32_t mincount;
if (seq1->length < 12 || seq2->length < 12)
return TRUE;
maxlen = MAX(seq1->length,seq2->length);
if (reference==ALILEN || reference==MAXLEN)
reflen = maxlen;
else
reflen = MIN(seq1->length,seq2->length);
if (normalize)
{
if (! lcsmode)
threshold = 1. - threshold;
lcs = (int32_t)ceil((double)reflen * threshold);
}
else
{
if (! lcsmode)
threshold = reflen - threshold;
lcs = (int32_t) threshold;
}
if (lcs > MIN(seq1->length,seq2->length))
return FALSE;
mincount = thresholdLCS4(maxlen,lcs);
return compareTable(seq1->table,seq1->over,seq2->table,seq2->over) >=mincount;
}
BOOL isPossibleSumathings(fastaSeqPtr seq1, fastaSeqPtr seq2, int l1, int l2, double threshold, BOOL normalize, int reference, BOOL lcsmode)
{ // optimized version of the filter for sumaclust and sumatra
int32_t reflen;
int32_t lcs;
int32_t mincount;
if (l1 < 12 || l2 < 12)
return TRUE;
if (reference==ALILEN || reference==MAXLEN)
reflen = l1;
else
reflen = l2;
if (normalize)
lcs = (int32_t)ceil((double)reflen * threshold);
else
{
if (! lcsmode)
threshold = reflen - threshold;
lcs = (int32_t) threshold;
}
mincount = thresholdLCS4(l1,lcs);
return compareTable(seq1->table,seq1->over,seq2->table,seq2->over) >=mincount;
}
void filters(fastaSeqPtr seq1, fastaSeqPtr seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, double* score, int* LCSmin)
{ // score takes value -1 if filters are passed. score must be initialized in calling function.
int l1;
int l2;
l1 = seq1->length;
l2 = seq2->length;
if (l1 >= l2)
{
*LCSmin = calculateLCSmin(l1, l2, threshold, normalize, reference, lcsmode);
if (l2 >= *LCSmin)
{
if (isPossibleSumathings(seq1, seq2, l1, l2, threshold, normalize, reference, lcsmode)) // 4-mers filter
*score = -1.0;
}
}
else
{
*LCSmin = calculateLCSmin(l2, l1, threshold, normalize, reference, lcsmode);
if (l1 >= *LCSmin)
{
if (isPossibleSumathings(seq2, seq1, l2, l1, threshold, normalize, reference, lcsmode)) // 4-mers filter
*score = -1.0;
}
}
}
void filtersSumatra(fastaSeqPtr seq1, fastaSeqPtr seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, double* score, int* LCSmin)
{ // score takes value -2 if filters are not passed, -1 if filters are passed and >= 0 with max score if the 2 sequences are identical.
int l1;
int l2;
l1 = seq1->length;
*score = -2.0;
if (strcmp(seq1->sequence, seq2->sequence) == 0) // the 2 sequences are identical
{
if (lcsmode && normalize)
*score = 1.0;
else if (!lcsmode)
*score = 0.0;
else
*score = l1;
}
else if (threshold != 0)
{
l2 = seq2->length;
if (l1 >= l2)
{
*LCSmin = calculateLCSmin(l1, l2, threshold, normalize, reference, lcsmode);
if (l2 >= *LCSmin)
{
if (isPossibleSumathings(seq1, seq2, l1, l2, threshold, normalize, reference, lcsmode)) // 4-mers filter
*score = -1.0;
}
}
else
{
*LCSmin = calculateLCSmin(l2, l1, threshold, normalize, reference, lcsmode);
if (l1 >= *LCSmin)
{
if (isPossibleSumathings(seq2, seq1, l2, l1, threshold, normalize, reference, lcsmode)) // 4-mers filter
*score = -1.0;
}
}
}
else
*LCSmin = 0;
}

18
liblcs/upperband.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef UPPERBAND_H_
#define UPPERBAND_H_
int buildTable(const char *sequence, unsigned char *table, int *count);
int compareTable(unsigned char *t1, int over1, unsigned char* t2, int over2);
int threshold4(int wordcount,double identity);
int thresholdLCS4(int32_t reflen,int32_t lcs);
int hashDB(fastaSeqCount);
BOOL isPossible(fastaSeqPtr, fastaSeqPtr, BOOL, int, double, BOOL);
BOOL isPossibleSumathings(fastaSeqPtr seq1, fastaSeqPtr seq2, int l1, int l2, double threshold, BOOL normalize, int reference, BOOL lcsmode);
void filters(fastaSeqPtr seq1, fastaSeqPtr seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, double* score, int* LCSmin);
void filtersSumatra(fastaSeqPtr seq1, fastaSeqPtr seq2, double threshold, BOOL normalize, int reference, BOOL lcsmode, double* score, int* LCSmin);
#endif