Program Listing for File recycling.hpp

Return to documentation for file (fwdpp/simfunctions/recycling.hpp)

#ifndef FWDPP_RECYCLING
#define FWDPP_RECYCLING

#include <queue>
#include <stdexcept>
#include <type_traits>
#include <fwdpp/util/named_type.hpp>

namespace fwdpp
{
    namespace tags
    {
        struct mutation_recycling
        {
        };
        struct haploid_genome_recycling
        {
        };
    } // namespace tags

    using flagged_mutation_queue
        = strong_types::named_type<std::queue<std::size_t>, tags::mutation_recycling>;

    using flagged_haploid_genome_queue
        = strong_types::named_type<std::queue<std::size_t>,
                                   tags::haploid_genome_recycling>;

    inline flagged_mutation_queue
    empty_mutation_queue()
    {
        return flagged_mutation_queue(flagged_mutation_queue::value_type());
    }

    inline flagged_haploid_genome_queue
    empty_haploid_genome_queue()
    {
        return flagged_haploid_genome_queue(flagged_haploid_genome_queue::value_type());
    }

    template <typename mcount_vec>
    inline flagged_mutation_queue
    make_mut_queue(const mcount_vec &mcounts)
    {
        flagged_mutation_queue::value_type rv;
        const auto msize = mcounts.size();
        for (typename mcount_vec::size_type i = 0; i < msize; ++i)
            {
                if (!mcounts[i])
                    rv.push(i);
            }
        return flagged_mutation_queue(std::move(rv));
    }

    template <typename gvec_t>
    inline flagged_haploid_genome_queue
    make_haploid_genome_queue(const gvec_t &haploid_genomes)
    {
        flagged_haploid_genome_queue::value_type rv;
        const auto gsize = haploid_genomes.size();
        for (typename gvec_t::size_type i = 0; i < gsize; ++i)
            {
                if (!haploid_genomes[i].n)
                    rv.push(i);
            }
        return flagged_haploid_genome_queue(std::move(rv));
    }

    template <typename GenomeContainerType>
    inline std::size_t
    recycle_haploid_genome(
        GenomeContainerType &haploid_genomes,
        flagged_haploid_genome_queue &haploid_genome_recycling_bin,
        typename GenomeContainerType::value_type::mutation_container &neutral,
        typename GenomeContainerType::value_type::mutation_container &selected)
    {
        // Try to recycle
        auto &ref = haploid_genome_recycling_bin.get();
        if (!ref.empty())
            {
                auto idx = ref.front();
                ref.pop();
#ifndef NDEBUG
                if (haploid_genomes[idx].n)
                    {
                        throw std::runtime_error(
                            "FWDPP DEBUG: attempting to recycle an extant "
                            "haploid_genome");
                    }
#endif
                haploid_genomes[idx].mutations.swap(neutral);
                haploid_genomes[idx].smutations.swap(selected);
                return idx;
            }
        haploid_genomes.emplace_back(0u, std::move(neutral), std::move(selected));
        return (haploid_genomes.size() - 1);
    }

    template <typename MutationContainerType, class... Args>
    inline std::size_t
    recycle_mutation_helper(flagged_mutation_queue &mutation_recycling_bin,
                            MutationContainerType &mutations, Args &&... args)
    {
        auto &ref = mutation_recycling_bin.get();
        if (!ref.empty())
            {
                auto rv = ref.front();
                ref.pop();
                mutations[rv] = typename MutationContainerType::value_type(
                    std::forward<Args>(args)...);
                return rv;
            }
        mutations.emplace_back(std::forward<Args>(args)...);
        return mutations.size() - 1;
    }
} // namespace fwdpp

#endif