Program Listing for File change_neutral.hpp

Return to documentation for file (fwdpp/sugar/change_neutral.hpp)

#ifndef FWDPP_SUGAR_CHANGE_NEUTRAL_HPP
#define FWDPP_SUGAR_CHANGE_NEUTRAL_HPP

#include <algorithm>
#include <exception>
#include <fwdpp/debug.hpp>

namespace fwdpp
{
    namespace sugar
    {
        template <typename MutationContainerType, typename mut_key_cont_t>
        void
        change_neutral_details(const MutationContainerType &mutations, const double pos,
                               const std::size_t mindex, mut_key_cont_t &a,
                               mut_key_cont_t &b)
        {
            /*
              Ask if haploid_genome has this mutation.  We do a linear
              search here in case of finite-site schemes and we
              also do not expect this function to be called a whole lot.
            */
            auto i = std::find(std::begin(a), std::end(a), mindex);
            // If it exists and is mindex, erase it
            if (i == std::end(a))
                return;

            a.erase(i);

            // Add mutation key into b
            b.insert(std::upper_bound(
                         std::begin(b), std::end(b), pos,
                         [&mutations](const double &p,
                                      const typename mut_key_cont_t::value_type &vt)

                         { return p < mutations[vt].pos; }),
                     mindex);
        }
    } // namespace sugar

    template <typename poptype>
    void
    change_neutral(poptype &p, const std::size_t mindex)
    {
        if (mindex >= p.mutations.size())
            throw std::out_of_range("mindex >= p.mutations.size()");

        bool is_neutral = p.mutations[mindex].neutral;

        // Change neutral flag
        p.mutations[mindex].neutral = !p.mutations[mindex].neutral;
        const auto pos = p.mutations[mindex].pos;

        for (auto &g : p.haploid_genomes)
            {
                if (g.n)
                    {
                        if (is_neutral)
                            {
                                sugar::change_neutral_details(p.mutations, pos, mindex,
                                                              g.mutations, g.smutations);
                            }
                        else
                            {
                                sugar::change_neutral_details(p.mutations, pos, mindex,
                                                              g.smutations, g.mutations);
                            }
                        debug::haploid_genome_data_valid(g, p.mutations, p.mcounts);
                    }
            }
    }
} // namespace fwdpp

#endif