packages feed

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 ;
}