Project: s41467-024-51468-6 | Function: get_gene_similarity (cpp)

system: You are an expert C++ programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow C++ best practices and maintain consistent code style.
Return **only** the complete C++ function code.

user: Complete this C++ function:

**DESCRIPTION:** Calculates similarity between two var genes to determine survival probability of recombinant offspring based on epitope divergence

**KEY TERMS:** {
  "p_div": "total divergence between parent genes",
  "child_div": "divergence in offspring before breakpoint",
  "avg_mutation": "average mutations per epitope (5)",
  "RHO": "base survival probability parameter",
  "breakpoint": "recombination crossover point",
  "N_LOCI": "number of epitope loci"
}

**CONTEXT CODE:**     RETURN();
}

void retain_strain(Strain * strain) {
    BEGIN();
    
    strain->refcount++;
    
    RETURN();
}

void release_strain(Strain * strain) {
    BEGIN();
    
    assert(strain->refcount > 0);
    strain->refcount--;
    
    if(strain->refcount == 0)  {
        destroy_strain(strain);
    }
    
    RETURN();
}

Strain * generate_random_strain() {
    BEGIN();
    
    Strain * strain = strain_manager.create();
    auto & genes =  strain->genes;
    
    //    std::array<Gene *, N_GENES_PER_STRAIN> genes;
    
    // Old genes
    for(uint64_t i = 0; i < N_GENES_PER_STRAIN; i++) {
        genes[i] = draw_random_gene();
    }
    
    if(OUTPUT_STRAINS) {
        write_strain(strain, strain_stmt, NULL, NULL);
    }
    
    RETURN(strain);
}

Strain * recombine_strains(Strain * s1, Strain * s2) {
    fprintf(stderr, "Function recombine_strains has been masked\n");
    abort();
    return NULL;
}

double get_gene_similarity(Gene * gene1, Gene * gene2, uint64_t breakpoint) {
    fprintf(stderr, "Function get_gene_similarity has been masked\n");
    abort();
    return 0.0;
}

double get_gene_similarity(Gene * gene1, Gene * gene2, double breakpoint) {
    fprintf(stderr, "Function get_gene_similarity has been masked\n");
    abort();
    return 0.0;
}


Strain * mutate_strain(Strain * strain) {
    BEGIN();
    uint64_t index = draw_uniform_index(N_GENES_PER_STRAIN);
    Strain * mutated_strain = create_strain();
    mutated_strain->genes = strain->genes;
    mutated_strain->genes[index] = mutate_gene(strain->genes[index], SOURCE_MUTATION, false);
    
    if(OUTPUT_STRAINS) {
        write_strain(strain, strain_stmt, NULL, NULL);
    }
    
    RETURN(mutated_strain);
}

Gene * mutate_gene(Gene * gene, GeneSource source, bool in_pool) {
    BEGIN();
    auto alleles = gene->alleles;
    uint64_t locus = draw_uniform_index(N_LOCI); 
    alleles[locus] = n_alleles[locus];
    n_alleles[locus]++;
    
    // Add new AlleleRef for this allele
    AlleleRef * allele_ref = allele_ref_manager.create();
    allele_ref->locus = locus;
    allele_ref->allele = n_alleles[locus] - 1;
    allele_refs[locus].push_back(allele_ref);
    
    //keep the global pool size the same
    if(in_pool){
        gene->in_pool = false;
    }
    mut_count += 1;
    RETURN(get_or_create_gene(alleles, source, gene->is_functional, in_pool));
}


void recombine_infection(Infection * infection, bool recombLoad) {
    BEGIN();
    
    if(N_GENES_PER_STRAIN == 1) {
        RETURN();
    }
    
    Gene * new_gene_1;
    Gene * new_gene_2;
    
    // Choose random expression order indices
    uint64_t exp_index_1;
    uint64_t exp_index_2;
    do {
        exp_index_1 = draw_uniform_index(N_GENES_PER_STRAIN);
        exp_index_2 = draw_uniform_index_except(N_GENES_PER_STRAIN, exp_index_1);
    } while(exp_index_1 == exp_index_2);
    
    Gene * src_gene_1 = infection->expression_order[exp_index_1];
    Gene * src_gene_2 = infection->expression_order[exp_index_2];
    if(src_gene_1 == src_gene_2) {
        RETURN();
    }
    
    bool is_conversion = draw_bernoulli(P_ECTOPIC_RECOMBINATION_IS_CONVERSION);
    
    if (ECTOPIC_RECOMBINATION_CREATE_NEW_ALLELE) {
        double breakpoint;
        breakpoint = draw_uniform_real(0, double(N_LOCI));
        
        //similarity takes into account the functionality of the source genes
        double similarity = get_gene_similarity(src_gene_1, src_gene_2, breakpoint);
        
        bool create_new_allele = draw_bernoulli(P_ECTOPIC_RECOMBINATION_CREATE_NEW_ALLELE);
        new_gene_1 = recombine_alleles(src_gene_1, src_gene_2, breakpoint, similarity, create_new_allele);
        
        // Under conversion, the second gene remains unchanged
        if(is_conversion) {
            new_gene_2 = src_gene_2;
        }
        // Under normal combination, both genes have material swapped
        else {
            new_gene_2 = recombine_alleles(src_gene_2, src_gene_1, breakpoint, similarity, create_new_allele);
        }
    } else {
        uint64_t breakpoint = draw_uniform_index(N_LOCI);
        
        // If breakpoint == 0, very little to do
        if(breakpoint == 0) {
            if(is_conversion) {
                new_gene_1 = src_gene_1;


Complete the function implementation replacing "throw std::runtime_error("Not implemented");".