#include <stdint.h>
#include <limits.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
/* This version receives the second sequence reverse-complemented and
* the second quality vector reversed. Allows for a forward loop,
* doesn't need the lookup table. */
int prim_match_reads( int i1 // matches from i2
, int i2 // ???
, int r // length to match
, const uint8_t *rd1
, const uint8_t *qs1
, const uint8_t *rc_rd2
, const uint8_t *rv_qs2 )
{
int acc = 0 ;
while( r != 0 )
{
uint8_t n1 = rd1[ i1 ] ;
uint8_t n2 = rc_rd2[ i2 ] ;
uint8_t q1 = qs1[ i1 ] ;
uint8_t q2 = rv_qs2[ i2 ] ;
acc += (n1 & 0xF) == (n2 & 0xF) ? 0 : 5 + (q1 < q2 ? q1 : q2) ;
++i1 ;
++i2 ;
--r ;
}
return acc ;
}
int prim_match_ad( int off
, int i
, const uint8_t *rd
, const uint8_t *qs
, const uint8_t *ad )
{
int acc = 0 ;
while( i > 0 )
{
--i;
acc += rd[ i+off ] == ad[ i ] ? 0 : 5 +
(qs[ i+off ] < 25 ? qs[ i+off ] : 25) ;
}
return acc ;
}
// return the length that minimizes the score
int prim_merge_score (
uint8_t **p_fwd_ads,
int *p_fwd_lns,
int n_fwd_adapters,
uint8_t **p_rev_ads,
int *p_rev_lns,
int n_rev_adapters,
uint8_t *p_rd1,
uint8_t *p_qs1,
int l1,
uint8_t *p_rd2,
uint8_t *p_qs2,
int l2,
uint8_t *p_rrd2,
uint8_t *p_rqs2,
int *scores )
{
int minl = -1 ;
int min0 = 6 * (l1+l2) ;
int min1= INT_MAX ;
for( int l = 0 ; l <= l1+l2 ; ++l )
{
int ff = INT_MAX ;
for( int i = 0 ; i != n_fwd_adapters ; ++i )
{
int efflength = MIN(l1 - l, p_fwd_lns[i]) ;
int x = prim_match_ad( l, efflength, p_rd1, p_qs1, p_fwd_ads[i] ) ;
ff = MIN(ff, x + 6 * MAX( 0, l1 - p_fwd_lns[i] - l)) ;
}
int rr = INT_MAX ;
for( int i = 0 ; i != n_rev_adapters ; ++i )
{
int efflength = MIN(l2 - l,p_rev_lns[i]) ;
int x = prim_match_ad( l, efflength, p_rd2, p_qs2, p_rev_ads[i] ) ;
rr = MIN(rr, x + 6 * MAX( 0, l1 - p_rev_lns[i] - l)) ;
}
int minidx1 = MAX(l - l2, 0) ; // vec1, forward
int minidx2 = MAX(l2 - l, 0) ; // vec2, forward-on-reverse
int efflength = MIN(l1 + l2 - l, l) ; // effective length
int mm = efflength <= 0 ? 0 : prim_match_reads( minidx1, minidx2, efflength, p_rd1, p_qs1, p_rrd2, p_rqs2 ) ;
int z = 6 * l + ff + rr + mm ;
if( z < min0 ) {
min1 = min0 ;
min0 = z ;
minl = l ;
} else if( z < min1 ) {
min1 = z ;
}
}
scores[0] = min1 - min0 ;
scores[1] = 6*(l1+l2) - min0 ;
return minl ;
}