biohazard-0.6.1: src/cbits/jive.c
/** Computes likelihoods for each pair of indices, given matching
* probabilities for each and a matrix of prior probabilities. Return
* the index pair that yields the maximum likelihood and the total
* likelihood. (The length of p5_ must be a multiple of 32 to make
* vectorization easier.)
*
* @param v_ matrix of dimension (n7,n5_*32) containing the prior
* @param p7_ vector of length n7 containing matching probabilities for
* the first index
* @param n7 length of vector p7_
* @param p5_ vector of length (n5_*32) containing matching
* probabilities for the second index
* @param n5 length of vector p5_ divided by 32
* @param pi7 pointer to location that receives index of the first index
* that yields the maximum likelihood (ignored if null)
* @param pi5 pointer to location that receives index of the second index
* that yields the maximum likelihood (ignored if null)
* @return the total likelihood
*/
double c_unmix_total( const double *restrict v_
, const double *restrict p7_, unsigned n7
, const double *restrict p5_, unsigned n5_
, unsigned *pi7, unsigned *pi5 )
{
unsigned n5 = n5_ * 32 ;
const double *restrict v = v_ ; // __builtin_assume_aligned( v_, 16 ) ;
const double *restrict p5 = p5_ ; // __builtin_assume_aligned( p5_, 16 ) ;
const double *restrict p7 = p7_ ; // __builtin_assume_aligned( p7_, 16 ) ;
double acc = 0 ;
double max = 0 ;
unsigned mi7 = 0 ;
unsigned mi5 = 0 ;
for( unsigned i = 0, k = 0 ; i != n7 ; ++i, k += n5 ) {
double p7i = p7[i] ;
for( unsigned j = 0 ; j != n5 ; ++j ) {
double p = v[k+j] * p7i * p5[j] ;
acc += p ;
if( p > max ) {
max = p ;
mi7 = i ;
mi5 = j ;
}
}
}
if( pi7 ) *pi7 = mi7 ;
if( pi5 ) *pi5 = mi5 ;
return acc ;
}
/** Computes posterior probabilities for each pair of indices, given
* matching probabilities for each and a matrix of prior probabilities,
* the total likelihood and the index pair that yields the maximum
* likelihood. The posterior is added to an accumulator, and a quality
* score is returned. (The length of p5_ must be a multiple of 32 to
* make vectorization easier.)
*
* @param w_ matrix of dimension (n7,n5_*32) to which the posterior is added (ignored if null)
* @param v_ matrix of dimension (n7,n5_*32) containing the prior
* @param p7_ vector of length n7 containing matching probabilities for the first index
* @param n7 length of vector p7_
* @param p5_ vector of length (n5_*32) containing matching probabilities for the second index
* @param n5 length of vector p5_ divided by 32
* @param total the total likelihood
* @param mi7 index of the first index that yields the maximum likelihood
* @param mi5 index of the second index that yields the maximum likelihood
* @return the posterior probability for any other than the most likely assignment
*/
double c_unmix_qual( double *restrict w_
, const double *restrict v_
, const double *restrict p7_, unsigned n7
, const double *restrict p5_, unsigned n5_
, double total, unsigned mi7, unsigned mi5 )
{
unsigned n5 = n5_ * 32 ;
double *restrict w = w_ ; // __builtin_assume_aligned( w_, 16 ) ;
const double *restrict v = v_ ; // __builtin_assume_aligned( v_, 16 ) ;
const double *restrict p5 = p5_ ; // __builtin_assume_aligned( p5_, 16 ) ;
const double *restrict p7 = p7_ ; // __builtin_assume_aligned( p7_, 16 ) ;
double acc = 0 ;
total = 1.0 / total ;
for( unsigned i = 0, k = 0 ; i != n7 ; ++i ) {
double p7i = p7[i] ;
for( unsigned j = 0 ; j != n5 ; ++j, ++k ) {
double p = total * v[k] * p7i * p5[j] ;
if( w ) w[k] += p ;
if( mi7 != i || mi5 != j ) acc += p ;
}
}
return acc ;
}