From 249ab048324b35379fc2fe4c29c18a6869173ede Mon Sep 17 00:00:00 2001 From: Ben Haller Date: Sun, 6 Oct 2024 20:13:26 -0400 Subject: [PATCH] shift to a vector of haplosomes --- QtSLiM/QtSLiMGraphView.cpp | 24 +- QtSLiM/QtSLiMGraphView_1DSampleSFS.cpp | 12 +- QtSLiM/QtSLiMGraphView_2DSampleSFS.cpp | 24 +- QtSLiM/QtSLiMHaplotypeManager.cpp | 7 +- .../GraphView_MutationFrequencyTrajectory.mm | 10 +- SLiMgui/SLiMHaplotypeManager.mm | 8 +- core/chromosome.cpp | 4 +- core/haplosome.cpp | 21 +- core/individual.cpp | 94 ++-- core/individual.h | 14 +- core/population.cpp | 401 ++++++++---------- core/species.cpp | 115 ++--- core/species_eidos.cpp | 7 +- core/subpopulation.cpp | 72 ++-- 14 files changed, 355 insertions(+), 458 deletions(-) diff --git a/QtSLiM/QtSLiMGraphView.cpp b/QtSLiM/QtSLiMGraphView.cpp index 59686a5c..0acf1e81 100644 --- a/QtSLiM/QtSLiMGraphView.cpp +++ b/QtSLiM/QtSLiMGraphView.cpp @@ -1693,15 +1693,15 @@ void QtSLiMGraphView::contextMenuEvent(QContextMenuEvent *p_event) void QtSLiMGraphView::setXAxisRangeFromTick(void) { - Community *community = controller_->community; + Community *community = controller_->community; // We can't get the estimated last tick until tick ranges are known if (!community || (community->Tick() < 1)) return; - slim_tick_t lastTick = community->EstimatedLastTick(); - - // The last tick could be just about anything, so we need some smart axis setup code here – a problem we neglect elsewhere + slim_tick_t lastTick = community->EstimatedLastTick(); + + // The last tick could be just about anything, so we need some smart axis setup code here – a problem we neglect elsewhere // since we use hard-coded axis setups in other places. The goal is to (1) have the axis max be >= lastTick, (2) have the axis // max be == lastTick if lastTick is a reasonably round number (a single-digit multiple of a power of 10, say), (3) have just a few // other major tick intervals drawn, so labels don't collide or look crowded, and (4) have a few minor tick intervals in between @@ -2434,20 +2434,17 @@ size_t QtSLiMGraphView::tallyGUIMutationReferences(slim_objectid_t subpop_id, in if (subpop) // tally only within our chosen subpop { - slim_popsize_t subpop_haplosome_count = 2 * subpop->parent_subpop_size_; - std::vector &subpop_haplosome = subpop->parent_haplosomes_; - - for (int i = 0; i < subpop_haplosome_count; i++) + for (Individual *ind : subpop->parent_individuals_) { - Haplosome &haplosome = *subpop_haplosome[static_cast(i)]; - - if (!haplosome.IsNull()) + for (Haplosome *haplosome : ind->haplosomes_) + { + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -2463,6 +2460,7 @@ size_t QtSLiMGraphView::tallyGUIMutationReferences(slim_objectid_t subpop_id, in subpop_total_haplosome_count++; } } + } } return subpop_total_haplosome_count; diff --git a/QtSLiM/QtSLiMGraphView_1DSampleSFS.cpp b/QtSLiM/QtSLiMGraphView_1DSampleSFS.cpp index 95e2ee7b..6f6b7de1 100644 --- a/QtSLiM/QtSLiMGraphView_1DSampleSFS.cpp +++ b/QtSLiM/QtSLiMGraphView_1DSampleSFS.cpp @@ -275,12 +275,18 @@ uint64_t *QtSLiMGraphView_1DSampleSFS::mutation1DSFS(void) // Get frequencies for a sample taken (with replacement) from subpop1 { std::vector sampleHaplosomes; - std::vector &subpopHaplosomes = subpop1->parent_haplosomes_; - size_t subpopHaplosomeCount = subpopHaplosomes.size(); + std::vector &subpopIndividuals = subpop1->parent_individuals_; + size_t subpopHaplosomeCount = subpopIndividuals.size() * 2; if (subpopHaplosomeCount) for (int i = 0; i < histogramBinCount_ - 1; ++i) - sampleHaplosomes.emplace_back(subpopHaplosomes[random() % subpopHaplosomeCount]); + { + slim_popsize_t haplosome_index = random() % subpopHaplosomeCount; + slim_popsize_t individual_index = haplosome_index >> 1; + Haplosome *haplosome = subpopIndividuals[individual_index]->haplosomes_[haplosome_index & 0x01]; + + sampleHaplosomes.emplace_back(haplosome); + } tallyGUIMutationReferences(sampleHaplosomes, selectedMutationTypeIndex_); } diff --git a/QtSLiM/QtSLiMGraphView_2DSampleSFS.cpp b/QtSLiM/QtSLiMGraphView_2DSampleSFS.cpp index 13533392..dc7be37d 100644 --- a/QtSLiM/QtSLiMGraphView_2DSampleSFS.cpp +++ b/QtSLiM/QtSLiMGraphView_2DSampleSFS.cpp @@ -352,12 +352,18 @@ uint64_t *QtSLiMGraphView_2DSampleSFS::mutation2DSFS(void) // Get frequencies for a sample taken from subpop1 { std::vector sample1Haplosomes; - std::vector &subpopHaplosomes = subpop1->parent_haplosomes_; - size_t subpopHaplosomeCount = subpopHaplosomes.size(); + std::vector &subpopIndividuals = subpop1->parent_individuals_; + size_t subpopHaplosomeCount = subpopIndividuals.size() * 2; if (subpopHaplosomeCount) for (int i = 0; i < histogramBinCount_ - 1; ++i) - sample1Haplosomes.emplace_back(subpopHaplosomes[random() % subpopHaplosomeCount]); + { + slim_popsize_t haplosome_index = random() % subpopHaplosomeCount; + slim_popsize_t individual_index = haplosome_index >> 1; + Haplosome *haplosome = subpopIndividuals[individual_index]->haplosomes_[haplosome_index & 0x01]; + + sample1Haplosomes.emplace_back(haplosome); + } tallyGUIMutationReferences(sample1Haplosomes, selectedMutationTypeIndex_); } @@ -374,12 +380,18 @@ uint64_t *QtSLiMGraphView_2DSampleSFS::mutation2DSFS(void) // Get frequencies for a sample taken from subpop2 { std::vector sample2Haplosomes; - std::vector &subpopHaplosomes = subpop2->parent_haplosomes_; - size_t subpopHaplosomeCount = subpopHaplosomes.size(); + std::vector &subpopIndividuals = subpop2->parent_individuals_; + size_t subpopHaplosomeCount = subpopIndividuals.size() * 2; if (subpopHaplosomeCount) for (int i = 0; i < histogramBinCount_ - 1; ++i) - sample2Haplosomes.emplace_back(subpopHaplosomes[random() % subpopHaplosomeCount]); + { + slim_popsize_t haplosome_index = random() % subpopHaplosomeCount; + slim_popsize_t individual_index = haplosome_index >> 1; + Haplosome *haplosome = subpopIndividuals[individual_index]->haplosomes_[haplosome_index & 0x01]; + + sample2Haplosomes.emplace_back(haplosome); + } tallyGUIMutationReferences(sample2Haplosomes, selectedMutationTypeIndex_); } diff --git a/QtSLiM/QtSLiMHaplotypeManager.cpp b/QtSLiM/QtSLiMHaplotypeManager.cpp index 60d16258..c149f6ed 100644 --- a/QtSLiM/QtSLiMHaplotypeManager.cpp +++ b/QtSLiM/QtSLiMHaplotypeManager.cpp @@ -217,9 +217,10 @@ QtSLiMHaplotypeManager::QtSLiMHaplotypeManager(QObject *p_parent, ClusteringMeth // Fetch haplosomes and figure out what we're going to plot; note that we plot only non-null haplosomes for (Subpopulation *subpop : selected_subpops) - for (Haplosome *haplosome : subpop->parent_haplosomes_) - if (!haplosome->IsNull()) - haplosomes.emplace_back(haplosome); + for (Individual *ind : subpop->parent_individuals_) + for (Haplosome *haplosome : ind->haplosomes_) + if (!haplosome->IsNull()) + haplosomes.emplace_back(haplosome); // If a sample is requested, select that now; sampleSize <= 0 means no sampling if ((sampleSize > 0) && (haplosomes.size() > sampleSize)) diff --git a/SLiMgui/GraphView_MutationFrequencyTrajectory.mm b/SLiMgui/GraphView_MutationFrequencyTrajectory.mm index f66ac2ba..b8c23a22 100644 --- a/SLiMgui/GraphView_MutationFrequencyTrajectory.mm +++ b/SLiMgui/GraphView_MutationFrequencyTrajectory.mm @@ -318,17 +318,15 @@ - (void)fetchDataForFinishedTick for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); diff --git a/SLiMgui/SLiMHaplotypeManager.mm b/SLiMgui/SLiMHaplotypeManager.mm index 524818f3..a6a36e57 100644 --- a/SLiMgui/SLiMHaplotypeManager.mm +++ b/SLiMgui/SLiMHaplotypeManager.mm @@ -112,15 +112,9 @@ - (instancetype)initWithClusteringMethod:(SLiMHaplotypeClusteringMethod)clusteri for (Subpopulation *subpop : selected_subpops) { for (Individual *ind : subpop->parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - + for (Haplosome *haplosome : ind->haplosomes_) if (!haplosome->IsNull()) haplosomes.emplace_back(haplosome); - } - } } // If a sample is requested, select that now; sampleSize <= 0 means no sampling diff --git a/core/chromosome.cpp b/core/chromosome.cpp index 0c6aec2b..f2a76a05 100644 --- a/core/chromosome.cpp +++ b/core/chromosome.cpp @@ -2831,7 +2831,7 @@ EidosValue_SP Chromosome::ExecuteMethod_drawBreakpoints(EidosGlobalStringID p_me if (parent && recombination_callbacks.size()) { // a non-zero number of breakpoints, with recombination callbacks - species_.population_.ApplyRecombinationCallbacks(parent->index_, parent->haplosome1_, parent->haplosome2_, parent_subpop, all_breakpoints, recombination_callbacks); + species_.population_.ApplyRecombinationCallbacks(parent->index_, parent->haplosomes_[0], parent->haplosomes_[1], parent_subpop, all_breakpoints, recombination_callbacks); if (all_breakpoints.size() > 1) { @@ -2843,7 +2843,7 @@ EidosValue_SP Chromosome::ExecuteMethod_drawBreakpoints(EidosGlobalStringID p_me else if (parent && recombination_callbacks.size()) { // zero breakpoints from the SLiM core, but we have recombination() callbacks - species_.population_.ApplyRecombinationCallbacks(parent->index_, parent->haplosome1_, parent->haplosome2_, parent_subpop, all_breakpoints, recombination_callbacks); + species_.population_.ApplyRecombinationCallbacks(parent->index_, parent->haplosomes_[0], parent->haplosomes_[1], parent_subpop, all_breakpoints, recombination_callbacks); if (all_breakpoints.size() > 1) { diff --git a/core/haplosome.cpp b/core/haplosome.cpp index 202d8e77..ba5b8933 100644 --- a/core/haplosome.cpp +++ b/core/haplosome.cpp @@ -2186,7 +2186,8 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_addMutations(EidosGlobalStringID p_ if (focal_modification_child) { - Haplosome *focal_haplosome_1 = focal_modification_child->haplosome1_, *focal_haplosome_2 = focal_modification_child->haplosome2_; + Haplosome *focal_haplosome_1 = focal_modification_child->haplosomes_[0]; + Haplosome *focal_haplosome_2 = focal_modification_child->haplosomes_[1]; for (int haplosome_index = 0; haplosome_index < target_size; ++haplosome_index) { @@ -2486,7 +2487,8 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_addNewMutation(EidosGlobalStringID if (focal_modification_child) { - Haplosome *focal_haplosome_1 = focal_modification_child->haplosome1_, *focal_haplosome_2 = focal_modification_child->haplosome2_; + Haplosome *focal_haplosome_1 = focal_modification_child->haplosomes_[0]; + Haplosome *focal_haplosome_2 = focal_modification_child->haplosomes_[1]; for (int haplosome_index = 0; haplosome_index < target_size; ++haplosome_index) { @@ -3900,7 +3902,8 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_removeMutations(EidosGlobalStringID if (focal_modification_child) { - Haplosome *focal_haplosome_1 = focal_modification_child->haplosome1_, *focal_haplosome_2 = focal_modification_child->haplosome2_; + Haplosome *focal_haplosome_1 = focal_modification_child->haplosomes_[0]; + Haplosome *focal_haplosome_2 = focal_modification_child->haplosomes_[1]; for (int haplosome_index = 0; haplosome_index < target_size; ++haplosome_index) { @@ -4142,14 +4145,8 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_removeMutations(EidosGlobalStringID Subpopulation *subpop = subpop_pair.second; for (Individual *ind : subpop->parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - + for (Haplosome *haplosome : ind->haplosomes_) haplosome->scratch_ = (haplosome->IsNull() ? 0 : 1); - } - } } for (int haplosome_index = 0; haplosome_index < target_size; ++haplosome_index) @@ -4177,10 +4174,8 @@ EidosValue_SP Haplosome_Class::ExecuteMethod_removeMutations(EidosGlobalStringID for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - if (haplosome->scratch_ == 1) { for (slim_position_t position : unique_positions) diff --git a/core/individual.cpp b/core/individual.cpp index 414e0fee..456ee87d 100644 --- a/core/individual.cpp +++ b/core/individual.cpp @@ -55,13 +55,18 @@ Individual::Individual(Subpopulation *p_subpopulation, slim_popsize_t p_individu #ifdef SLIMGUI cached_unscaled_fitness_(p_fitness), #endif - haplosome1_(p_haplosome1), haplosome2_(p_haplosome2), age_(p_age), index_(p_individual_index), subpopulation_(p_subpopulation) + age_(p_age), index_(p_individual_index), subpopulation_(p_subpopulation) { #if DEBUG if (!p_haplosome1 || !p_haplosome2) EIDOS_TERMINATION << "ERROR (Individual::Individual): (internal error) nullptr passed for haplosome." << EidosTerminate(); #endif + // Set up our haplosomes vector + haplosomes_.resize(2); + haplosomes_[0] = p_haplosome1; + haplosomes_[1] = p_haplosome2; + // Set up the pointers from our haplosomes to us p_haplosome1->individual_ = this; p_haplosome2->individual_ = this; @@ -89,9 +94,8 @@ Individual::Individual(Subpopulation *p_subpopulation, slim_popsize_t p_individu Individual::~Individual(void) { // BCH 10/6/2024: Individual now owns the haplosomes inside it (a policy change for multichrom) - // This means the subpopulation_ pointer must be valid at this point! - subpopulation_->FreeSubpopHaplosome(haplosome1_); - subpopulation_->FreeSubpopHaplosome(haplosome2_); + for (Haplosome *haplosome : haplosomes_) + subpopulation_->FreeSubpopHaplosome(haplosome); } static inline bool _InPedigree(slim_pedigreeid_t A, slim_pedigreeid_t A_P1, slim_pedigreeid_t A_P2, slim_pedigreeid_t A_G1, slim_pedigreeid_t A_G2, slim_pedigreeid_t A_G3, slim_pedigreeid_t A_G4, slim_pedigreeid_t B) @@ -361,47 +365,31 @@ EidosValue_SP Individual::GetProperty(EidosGlobalStringID p_property_id) } case gID_haplosomes: { - EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->resize_no_initialize(2); + size_t haplosomes_count = haplosomes_.size(); + EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->resize_no_initialize(haplosomes_count); - vec->set_object_element_no_check_NORR(haplosome1_, 0); - vec->set_object_element_no_check_NORR(haplosome2_, 1); + for (size_t haplosome_index = 0; haplosome_index < haplosomes_count; haplosome_index++) + vec->set_object_element_no_check_NORR(haplosomes_[haplosome_index], haplosome_index); return EidosValue_SP(vec); } case gID_haplosomesNonNull: { - bool haplosome1null = haplosome1_->IsNull(); - bool haplosome2null = haplosome2_->IsNull(); + EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->reserve(haplosomes_.size()); - if (haplosome1null) - { - if (haplosome2null) - return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class)); - else - return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosome2_, gSLiM_Haplosome_Class)); - } - else - { - if (haplosome2null) - return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosome1_, gSLiM_Haplosome_Class)); - else - { - EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->resize_no_initialize(2); - - vec->set_object_element_no_check_NORR(haplosome1_, 0); - vec->set_object_element_no_check_NORR(haplosome2_, 1); - - return EidosValue_SP(vec); - } - } + for (Haplosome *haplosome : haplosomes_) + if (!haplosome->IsNull()) + vec->push_object_element_no_check_NORR(haplosome); + + return EidosValue_SP(vec); } case gID_haplosomesFromParent1: // ACCELERATED { - return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosome1_, gSLiM_Haplosome_Class)); + return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosomes_[0], gSLiM_Haplosome_Class)); } case gID_haplosomesFromParent2: // ACCELERATED { - return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosome2_, gSLiM_Haplosome_Class)); + return EidosValue_SP(new (gEidosValuePool->AllocateChunk()) EidosValue_Object(haplosomes_[1], gSLiM_Haplosome_Class)); } case gID_sex: { @@ -503,12 +491,12 @@ EidosValue_SP Individual::GetProperty(EidosGlobalStringID p_property_id) } case gID_uniqueMutations: { - if (haplosome1_->IsDeferred() || haplosome2_->IsDeferred()) + if (haplosomes_[0]->IsDeferred() || haplosomes_[1]->IsDeferred()) EIDOS_TERMINATION << "ERROR (Individual::GetProperty): the mutations of deferred haplosomes cannot be accessed." << EidosTerminate(); // We reserve a vector large enough to hold all the mutations from both haplosomes; probably usually overkill, but it does little harm - int haplosome1_size = (haplosome1_->IsNull() ? 0 : haplosome1_->mutation_count()); - int haplosome2_size = (haplosome2_->IsNull() ? 0 : haplosome2_->mutation_count()); + int haplosome1_size = (haplosomes_[0]->IsNull() ? 0 : haplosomes_[0]->mutation_count()); + int haplosome2_size = (haplosomes_[1]->IsNull() ? 0 : haplosomes_[1]->mutation_count()); EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Mutation_Class)); EidosValue_SP result_SP = EidosValue_SP(vec); @@ -518,14 +506,14 @@ EidosValue_SP Individual::GetProperty(EidosGlobalStringID p_property_id) vec->reserve(haplosome1_size + haplosome2_size); Mutation *mut_block_ptr = gSLiM_Mutation_Block; - int mutrun_count = (haplosome1_size ? haplosome1_->mutrun_count_ : haplosome2_->mutrun_count_); + int mutrun_count = (haplosome1_size ? haplosomes_[0]->mutrun_count_ : haplosomes_[1]->mutrun_count_); for (int run_index = 0; run_index < mutrun_count; ++run_index) { // We want to interleave mutations from the two haplosomes, keeping only the uniqued mutations. For a given position, we take mutations // from g1 first, and then look at the mutations in g2 at the same position and add them if they are not in g1. - const MutationRun *mutrun1 = (haplosome1_size ? haplosome1_->mutruns_[run_index] : nullptr); - const MutationRun *mutrun2 = (haplosome2_size ? haplosome2_->mutruns_[run_index] : nullptr); + const MutationRun *mutrun1 = (haplosome1_size ? haplosomes_[0]->mutruns_[run_index] : nullptr); + const MutationRun *mutrun2 = (haplosome2_size ? haplosomes_[1]->mutruns_[run_index] : nullptr); int g1_size = (mutrun1 ? mutrun1->size() : 0); int g2_size = (mutrun2 ? mutrun2->size() : 0); int g1_index = 0, g2_index = 0; @@ -1105,7 +1093,7 @@ EidosValue *Individual::GetProperty_Accelerated_haplosomesFromParent1(EidosObjec { Individual *value = (Individual *)(p_values[value_index]); - object_result->set_object_element_no_check_NORR(value->haplosome1_, value_index); + object_result->set_object_element_no_check_NORR(value->haplosomes_[0], value_index); } return object_result; @@ -1119,7 +1107,7 @@ EidosValue *Individual::GetProperty_Accelerated_haplosomesFromParent2(EidosObjec { Individual *value = (Individual *)(p_values[value_index]); - object_result->set_object_element_no_check_NORR(value->haplosome2_, value_index); + object_result->set_object_element_no_check_NORR(value->haplosomes_[1], value_index); } return object_result; @@ -1655,7 +1643,7 @@ EidosValue_SP Individual::ExecuteInstanceMethod(EidosGlobalStringID p_method_id, EidosValue_SP Individual::ExecuteMethod_containsMutations(EidosGlobalStringID p_method_id, const std::vector &p_arguments, EidosInterpreter &p_interpreter) { #pragma unused (p_method_id, p_arguments, p_interpreter) - if (haplosome1_->IsDeferred() || haplosome2_->IsDeferred()) + if (haplosomes_[0]->IsDeferred() || haplosomes_[1]->IsDeferred()) EIDOS_TERMINATION << "ERROR (Individual::ExecuteMethod_containsMutations): the mutations of deferred haplosomes cannot be accessed." << EidosTerminate(); EidosValue *mutations_value = p_arguments[0].get(); @@ -1675,7 +1663,7 @@ EidosValue_SP Individual::ExecuteMethod_containsMutations(EidosGlobalStringID p_ // treat the singleton case separately to return gStaticEidosValue_LogicalT / gStaticEidosValue_LogicalF MutationIndex mut = ((Mutation *)(mutations_value->ObjectElementAtIndex_NOCAST(0, nullptr)))->BlockIndex(); - if ((!haplosome1_->IsNull() && haplosome1_->contains_mutation(mut)) || (!haplosome2_->IsNull() && haplosome2_->contains_mutation(mut))) + if ((!haplosomes_[0]->IsNull() && haplosomes_[0]->contains_mutation(mut)) || (!haplosomes_[1]->IsNull() && haplosomes_[1]->contains_mutation(mut))) return gStaticEidosValue_LogicalT; else return gStaticEidosValue_LogicalF; @@ -1688,7 +1676,7 @@ EidosValue_SP Individual::ExecuteMethod_containsMutations(EidosGlobalStringID p_ for (int value_index = 0; value_index < mutations_count; ++value_index) { MutationIndex mut = mutations[value_index]->BlockIndex(); - bool contains_mut = ((!haplosome1_->IsNull() && haplosome1_->contains_mutation(mut)) || (!haplosome2_->IsNull() && haplosome2_->contains_mutation(mut))); + bool contains_mut = ((!haplosomes_[0]->IsNull() && haplosomes_[0]->contains_mutation(mut)) || (!haplosomes_[1]->IsNull() && haplosomes_[1]->contains_mutation(mut))); logical_result->set_logical_no_check(contains_mut, value_index); } @@ -1727,8 +1715,8 @@ EidosValue_SP Individual::ExecuteMethod_Accelerated_countOfMutationsOfType(Eidos for (size_t element_index = 0; element_index < p_elements_size; ++element_index) { Individual *element = (Individual *)(p_elements[element_index]); - Haplosome *haplosome1 = element->haplosome1_; - Haplosome *haplosome2 = element->haplosome2_; + Haplosome *haplosome1 = element->haplosomes_[0]; + Haplosome *haplosome2 = element->haplosomes_[1]; int match_count = 0; if (!haplosome1->IsNull()) @@ -1891,8 +1879,8 @@ EidosValue_SP Individual::ExecuteMethod_Accelerated_sumOfMutationsOfType(EidosOb for (size_t element_index = 0; element_index < p_elements_size; ++element_index) { Individual *element = (Individual *)(p_elements[element_index]); - Haplosome *haplosome1 = element->haplosome1_; - Haplosome *haplosome2 = element->haplosome2_; + Haplosome *haplosome1 = element->haplosomes_[0]; + Haplosome *haplosome2 = element->haplosomes_[1]; double selcoeff_sum = 0.0; if (!haplosome1->IsNull()) @@ -1945,7 +1933,7 @@ EidosValue_SP Individual::ExecuteMethod_Accelerated_sumOfMutationsOfType(EidosOb EidosValue_SP Individual::ExecuteMethod_uniqueMutationsOfType(EidosGlobalStringID p_method_id, const std::vector &p_arguments, EidosInterpreter &p_interpreter) { #pragma unused (p_method_id, p_arguments, p_interpreter) - if (haplosome1_->IsDeferred() || haplosome2_->IsDeferred()) + if (haplosomes_[0]->IsDeferred() || haplosomes_[1]->IsDeferred()) EIDOS_TERMINATION << "ERROR (Individual::ExecuteMethod_uniqueMutationsOfType): the mutations of deferred haplosomes cannot be accessed." << EidosTerminate(); EidosValue *mutType_value = p_arguments[0].get(); @@ -1956,8 +1944,8 @@ EidosValue_SP Individual::ExecuteMethod_uniqueMutationsOfType(EidosGlobalStringI // This code is adapted from uniqueMutations and follows its logic closely // We try to reserve a vector large enough to hold all the mutations; probably usually overkill, but it does little harm - int haplosome1_size = (haplosome1_->IsNull() ? 0 : haplosome1_->mutation_count()); - int haplosome2_size = (haplosome2_->IsNull() ? 0 : haplosome2_->mutation_count()); + int haplosome1_size = (haplosomes_[0]->IsNull() ? 0 : haplosomes_[0]->mutation_count()); + int haplosome2_size = (haplosomes_[1]->IsNull() ? 0 : haplosomes_[1]->mutation_count()); EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Mutation_Class)); EidosValue_SP result_SP = EidosValue_SP(vec); @@ -1968,14 +1956,14 @@ EidosValue_SP Individual::ExecuteMethod_uniqueMutationsOfType(EidosGlobalStringI vec->reserve(haplosome1_size + haplosome2_size); // since we do not always reserve, we have to use push_object_element() below to check Mutation *mut_block_ptr = gSLiM_Mutation_Block; - int mutrun_count = (haplosome1_size ? haplosome1_->mutrun_count_ : haplosome2_->mutrun_count_); + int mutrun_count = (haplosome1_size ? haplosomes_[0]->mutrun_count_ : haplosomes_[1]->mutrun_count_); for (int run_index = 0; run_index < mutrun_count; ++run_index) { // We want to interleave mutations from the two haplosomes, keeping only the uniqued mutations. For a given position, we take mutations // from g1 first, and then look at the mutations in g2 at the same position and add them if they are not in g1. - const MutationRun *mutrun1 = (haplosome1_size ? haplosome1_->mutruns_[run_index] : nullptr); - const MutationRun *mutrun2 = (haplosome2_size ? haplosome2_->mutruns_[run_index] : nullptr); + const MutationRun *mutrun1 = (haplosome1_size ? haplosomes_[0]->mutruns_[run_index] : nullptr); + const MutationRun *mutrun2 = (haplosome2_size ? haplosomes_[1]->mutruns_[run_index] : nullptr); int g1_size = (mutrun1 ? mutrun1->size() : 0); int g2_size = (mutrun2 ? mutrun2->size() : 0); int g1_index = 0, g2_index = 0; diff --git a/core/individual.h b/core/individual.h index 2c720d91..d878bad9 100644 --- a/core/individual.h +++ b/core/individual.h @@ -132,7 +132,7 @@ class Individual : public EidosDictionaryUnretained // that confuses interpretation; note that individual_cached_fitness_OVERRIDE_ is not relevant to this #endif - Haplosome *haplosome1_, *haplosome2_; // OWNED; must correspond to the entries in the Subpopulation we live in + std::vector haplosomes_; // OWNED (this is a policy change made for multichrom) slim_age_t age_; // nonWF only: the age of the individual, in cycles; -1 in WF models slim_popsize_t index_; // the individual index in that subpop (0-based, and not multiplied by 2) @@ -160,8 +160,8 @@ class Individual : public EidosDictionaryUnretained { pedigree_id_ = p_pedigree_id; - haplosome1_->haplosome_id_ = p_pedigree_id * 2; - haplosome2_->haplosome_id_ = p_pedigree_id * 2 + 1; + haplosomes_[0]->haplosome_id_ = p_pedigree_id * 2; + haplosomes_[1]->haplosome_id_ = p_pedigree_id * 2 + 1; pedigree_p1_ = p_parent1.pedigree_id_; pedigree_p2_ = p_parent2.pedigree_id_; @@ -190,8 +190,8 @@ class Individual : public EidosDictionaryUnretained { pedigree_id_ = p_pedigree_id; - haplosome1_->haplosome_id_ = p_pedigree_id * 2; - haplosome2_->haplosome_id_ = p_pedigree_id * 2 + 1; + haplosomes_[0]->haplosome_id_ = p_pedigree_id * 2; + haplosomes_[1]->haplosome_id_ = p_pedigree_id * 2 + 1; pedigree_p1_ = p_parent.pedigree_id_; pedigree_p2_ = p_parent.pedigree_id_; @@ -220,8 +220,8 @@ class Individual : public EidosDictionaryUnretained { pedigree_id_ = p_pedigree_id; - haplosome1_->haplosome_id_ = p_pedigree_id * 2; - haplosome2_->haplosome_id_ = p_pedigree_id * 2 + 1; + haplosomes_[0]->haplosome_id_ = p_pedigree_id * 2; + haplosomes_[1]->haplosome_id_ = p_pedigree_id * 2 + 1; } inline __attribute__((always_inline)) void RevokeParentage_Parentless() diff --git a/core/population.cpp b/core/population.cpp index d64b5033..d849ea64 100644 --- a/core/population.cpp +++ b/core/population.cpp @@ -306,11 +306,11 @@ Subpopulation *Population::AddSubpopulationSplit(slim_objectid_t p_subpop_id, Su migrant_index = p_source_subpop.DrawParentUsingFitness(rng); } - Haplosome *source_haplosome1 = p_source_subpop.parent_individuals_[migrant_index]->haplosome1_; - Haplosome *source_haplosome2 = p_source_subpop.parent_individuals_[migrant_index]->haplosome2_; + Haplosome *source_haplosome1 = p_source_subpop.parent_individuals_[migrant_index]->haplosomes_[0]; + Haplosome *source_haplosome2 = p_source_subpop.parent_individuals_[migrant_index]->haplosomes_[1]; - Haplosome *dest_haplosome1 = subpop.parent_individuals_[parent_index]->haplosome1_; - Haplosome *dest_haplosome2 = subpop.parent_individuals_[parent_index]->haplosome2_; + Haplosome *dest_haplosome1 = subpop.parent_individuals_[parent_index]->haplosomes_[0]; + Haplosome *dest_haplosome2 = subpop.parent_individuals_[parent_index]->haplosomes_[1]; dest_haplosome1->copy_from_haplosome(*source_haplosome1); dest_haplosome2->copy_from_haplosome(*source_haplosome2); @@ -550,11 +550,10 @@ void Population::CheckForDeferralInIndividualsVector(Individual **p_individuals, for (size_t element_index = 0; element_index < p_elements_size; ++element_index) { Individual *element = p_individuals[element_index]; - Haplosome *haplosome1 = element->haplosome1_; - Haplosome *haplosome2 = element->haplosome2_; - if (haplosome1->IsDeferred() || haplosome2->IsDeferred()) - EIDOS_TERMINATION << "ERROR (" << p_caller << "): the mutations of deferred haplosomes cannot be accessed." << EidosTerminate(); + for (Haplosome *haplosome : element->haplosomes_) + if (haplosome->IsDeferred()) + EIDOS_TERMINATION << "ERROR (" << p_caller << "): the mutations of deferred haplosomes cannot be accessed." << EidosTerminate(); } } } @@ -611,9 +610,9 @@ void Population::DoDeferredReproduction(void) } else if (deferred_rec.type_ == SLiM_DeferredReproductionType::kClonal) { - DoClonalMutation(deferred_rec.parent1_->subpopulation_, *deferred_rec.child_haplosome_1_, *deferred_rec.parent1_->haplosome1_, deferred_rec.child_sex_, nullptr); + DoClonalMutation(deferred_rec.parent1_->subpopulation_, *deferred_rec.child_haplosome_1_, *deferred_rec.parent1_->haplosomes_[0], deferred_rec.child_sex_, nullptr); - DoClonalMutation(deferred_rec.parent1_->subpopulation_, *deferred_rec.child_haplosome_2_, *deferred_rec.parent1_->haplosome2_, deferred_rec.child_sex_, nullptr); + DoClonalMutation(deferred_rec.parent1_->subpopulation_, *deferred_rec.child_haplosome_2_, *deferred_rec.parent1_->haplosomes_[1], deferred_rec.child_sex_, nullptr); } } @@ -1445,10 +1444,10 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice parent2 = parent1; - Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[child_index]->haplosome1_; - Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[child_index]->haplosome2_; - Haplosome &parent_haplosome_1 = *source_subpop.parent_individuals_[parent1]->haplosome1_; - Haplosome &parent_haplosome_2 = *source_subpop.parent_individuals_[parent1]->haplosome2_; + Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[child_index]->haplosomes_[0]; + Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[child_index]->haplosomes_[1]; + Haplosome &parent_haplosome_1 = *source_subpop.parent_individuals_[parent1]->haplosomes_[0]; + Haplosome &parent_haplosome_2 = *source_subpop.parent_individuals_[parent1]->haplosomes_[1]; Individual *new_child = p_subpop.child_individuals_[child_index]; new_child->migrant_ = false; @@ -1541,15 +1540,15 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop.parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_index]->haplosome1_, parent1, child_sex, parent1_sex, recombination_callbacks, mutation_callbacks); - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_index]->haplosome2_, parent2, child_sex, parent2_sex, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_index]->haplosomes_[0], parent1, child_sex, parent1_sex, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_index]->haplosomes_[1], parent2, child_sex, parent2_sex, recombination_callbacks, mutation_callbacks); } if (modify_child_callbacks) { Individual *child = p_subpop.child_individuals_[child_index]; - Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_index]->haplosome1_; - Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_index]->haplosome2_; + Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_index]->haplosomes_[0]; + Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_index]->haplosomes_[1]; Individual *parent1_ind = source_subpop.parent_individuals_[parent1]; Individual *parent2_ind = source_subpop.parent_individuals_[parent2]; @@ -1631,14 +1630,14 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop.parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_count]->haplosome1_, parent1, IndividualSex::kHermaphrodite, IndividualSex::kHermaphrodite, recombination_callbacks, mutation_callbacks); - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_count]->haplosome2_, parent2, IndividualSex::kHermaphrodite, IndividualSex::kHermaphrodite, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_count]->haplosomes_[0], parent1, IndividualSex::kHermaphrodite, IndividualSex::kHermaphrodite, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[child_count]->haplosomes_[1], parent2, IndividualSex::kHermaphrodite, IndividualSex::kHermaphrodite, recombination_callbacks, mutation_callbacks); if (modify_child_callbacks) { Individual *child = p_subpop.child_individuals_[child_count]; - Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_count]->haplosome1_; - Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_count]->haplosome2_; + Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_count]->haplosomes_[0]; + Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_count]->haplosomes_[1]; Individual *parent1_ind = source_subpop.parent_individuals_[parent1]; Individual *parent2_ind = source_subpop.parent_individuals_[parent2]; @@ -1903,10 +1902,10 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice parent2 = parent1; - Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[child_index]->haplosome1_; - Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[child_index]->haplosome2_; - Haplosome &parent_haplosome_1 = *source_subpop->parent_individuals_[parent1]->haplosome1_; - Haplosome &parent_haplosome_2 = *source_subpop->parent_individuals_[parent1]->haplosome2_; + Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[child_index]->haplosomes_[0]; + Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[child_index]->haplosomes_[1]; + Haplosome &parent_haplosome_1 = *source_subpop->parent_individuals_[parent1]->haplosomes_[0]; + Haplosome &parent_haplosome_2 = *source_subpop->parent_individuals_[parent1]->haplosomes_[1]; Individual *new_child = p_subpop.child_individuals_[child_index]; new_child->migrant_ = (source_subpop != &p_subpop); @@ -1999,15 +1998,15 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop->parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(source_subpop, *p_subpop.child_individuals_[child_index]->haplosome1_, parent1, child_sex, parent1_sex, recombination_callbacks, mutation_callbacks); - DoCrossoverMutation(source_subpop, *p_subpop.child_individuals_[child_index]->haplosome2_, parent2, child_sex, parent2_sex, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(source_subpop, *p_subpop.child_individuals_[child_index]->haplosomes_[0], parent1, child_sex, parent1_sex, recombination_callbacks, mutation_callbacks); + DoCrossoverMutation(source_subpop, *p_subpop.child_individuals_[child_index]->haplosomes_[1], parent2, child_sex, parent2_sex, recombination_callbacks, mutation_callbacks); } if (modify_child_callbacks) { Individual *child = p_subpop.child_individuals_[child_index]; - Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_index]->haplosome1_; - Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_index]->haplosome2_; + Haplosome *child_haplosome1 = p_subpop.child_individuals_[child_index]->haplosomes_[0]; + Haplosome *child_haplosome2 = p_subpop.child_individuals_[child_index]->haplosomes_[1]; Individual *parent1_ind = source_subpop->parent_individuals_[parent1]; Individual *parent2_ind = source_subpop->parent_individuals_[parent2]; @@ -2199,8 +2198,8 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop.parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome1_, parent1, child_sex, IndividualSex::kFemale, nullptr, nullptr); - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome2_, parent2, child_sex, IndividualSex::kMale, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[0], parent1, child_sex, IndividualSex::kFemale, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[1], parent2, child_sex, IndividualSex::kMale, nullptr, nullptr); } } EIDOS_BENCHMARK_END(EidosBenchmarkType::k_WF_REPRO); @@ -2240,8 +2239,8 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop.parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome1_, parent1, child_sex, IndividualSex::kHermaphrodite, nullptr, nullptr); - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome2_, parent2, child_sex, IndividualSex::kHermaphrodite, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[0], parent1, child_sex, IndividualSex::kHermaphrodite, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[1], parent2, child_sex, IndividualSex::kHermaphrodite, nullptr, nullptr); } } EIDOS_BENCHMARK_END(EidosBenchmarkType::k_WF_REPRO); @@ -2274,10 +2273,10 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice (void)parent2; // tell the static analyzer that we know we just did a dead store slim_popsize_t this_child_index = base_child_count + migrant_count; - Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[this_child_index]->haplosome1_; - Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[this_child_index]->haplosome2_; - Haplosome &parent_haplosome_1 = *source_subpop.parent_individuals_[parent1]->haplosome1_; - Haplosome &parent_haplosome_2 = *source_subpop.parent_individuals_[parent1]->haplosome2_; + Haplosome &child_haplosome_1 = *p_subpop.child_individuals_[this_child_index]->haplosomes_[0]; + Haplosome &child_haplosome_2 = *p_subpop.child_individuals_[this_child_index]->haplosomes_[1]; + Haplosome &parent_haplosome_1 = *source_subpop.parent_individuals_[parent1]->haplosomes_[0]; + Haplosome &parent_haplosome_2 = *source_subpop.parent_individuals_[parent1]->haplosomes_[1]; Individual *new_child = p_subpop.child_individuals_[this_child_index]; new_child->migrant_ = (&source_subpop != &p_subpop); @@ -2357,8 +2356,8 @@ void Population::EvolveSubpopulation(Subpopulation &p_subpop, bool p_mate_choice new_child->InheritSpatialPosition(species_.SpatialDimensionality(), source_subpop.parent_individuals_[parent1]); // recombination, gene-conversion, mutation - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome1_, parent1, child_sex, parent1_sex, nullptr, nullptr); - DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosome2_, parent2, child_sex, parent2_sex, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[0], parent1, child_sex, parent1_sex, nullptr, nullptr); + DoCrossoverMutation(&source_subpop, *p_subpop.child_individuals_[this_child_index]->haplosomes_[1], parent2, child_sex, parent2_sex, nullptr, nullptr); } } } @@ -2564,8 +2563,8 @@ void Population::DoCrossoverMutation(Subpopulation *p_source_subpop, Haplosome & ChromosomeType chromosome_type = p_child_haplosome.AssociatedChromosome()->Type(); // FIXME MULTICHROM this should maybe get passed in? bool child_haplosome_null = p_child_haplosome.IsNull(); - Haplosome *parent_haplosome_1 = p_source_subpop->parent_individuals_[p_parent_index]->haplosome1_; - Haplosome *parent_haplosome_2 = p_source_subpop->parent_individuals_[p_parent_index]->haplosome2_; + Haplosome *parent_haplosome_1 = p_source_subpop->parent_individuals_[p_parent_index]->haplosomes_[0]; + Haplosome *parent_haplosome_2 = p_source_subpop->parent_individuals_[p_parent_index]->haplosomes_[1]; #if DEBUG { @@ -5314,10 +5313,8 @@ void Population::ClearParentalHaplosomes(void) #pragma omp for schedule(static) for (Individual *ind : subpop->parent_individuals_) - { - ind->haplosome1_->clear_to_nullptr(); - ind->haplosome2_->clear_to_nullptr(); - } + for (Haplosome *haplosome : ind->haplosomes_) + haplosome->clear_to_nullptr(); } // We have to clear out removed subpops, too, for as long as they stick around @@ -5325,16 +5322,13 @@ void Population::ClearParentalHaplosomes(void) { #pragma omp for schedule(static) for (Individual *ind : subpop->parent_individuals_) - { - ind->haplosome1_->clear_to_nullptr(); - ind->haplosome2_->clear_to_nullptr(); - } + for (Haplosome *haplosome : ind->haplosomes_) + haplosome->clear_to_nullptr(); + #pragma omp for schedule(static) for (Individual *ind : subpop->child_individuals_) - { - ind->haplosome1_->clear_to_nullptr(); - ind->haplosome2_->clear_to_nullptr(); - } + for (Haplosome *haplosome : ind->haplosomes_) + haplosome->clear_to_nullptr(); } } EIDOS_BENCHMARK_END(EidosBenchmarkType::k_PARENTS_CLEAR); @@ -5379,14 +5373,12 @@ void Population::UniqueMutationRuns(void) for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (haplosome.IsNull()) + if (haplosome->IsNull()) continue; - const MutationRun *mut_run = haplosome.mutruns_[mutrun_index]; + const MutationRun *mut_run = haplosome->mutruns_[mutrun_index]; if (mut_run) { @@ -5437,7 +5429,7 @@ void Population::UniqueMutationRuns(void) if (mut_run->Identical(*hash_run)) { - haplosome.mutruns_[mutrun_index] = hash_run; + haplosome->mutruns_[mutrun_index] = hash_run; count_identical++; // We will unique away all references to this mutrun, but we only want to count it once @@ -5505,36 +5497,34 @@ void Population::SplitMutationRunsForChromosome(int32_t p_new_mutrun_count, Chro for (Individual *ind : subpop->child_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int32_t old_mutrun_count = haplosome.mutrun_count_; - slim_position_t old_mutrun_length = haplosome.mutrun_length_; + int32_t old_mutrun_count = haplosome->mutrun_count_; + slim_position_t old_mutrun_length = haplosome->mutrun_length_; int32_t new_mutrun_count = old_mutrun_count << 1; slim_position_t new_mutrun_length = old_mutrun_length >> 1; - if (haplosome.mutruns_ != haplosome.run_buffer_) - free(haplosome.mutruns_); - haplosome.mutruns_ = nullptr; + if (haplosome->mutruns_ != haplosome->run_buffer_) + free(haplosome->mutruns_); + haplosome->mutruns_ = nullptr; - haplosome.mutrun_count_ = new_mutrun_count; - haplosome.mutrun_length_ = new_mutrun_length; + haplosome->mutrun_count_ = new_mutrun_count; + haplosome->mutrun_length_ = new_mutrun_length; if (new_mutrun_count <= SLIM_HAPLOSOME_MUTRUN_BUFSIZE) { - haplosome.mutruns_ = haplosome.run_buffer_; - EIDOS_BZERO(haplosome.run_buffer_, SLIM_HAPLOSOME_MUTRUN_BUFSIZE * sizeof(const MutationRun *)); + haplosome->mutruns_ = haplosome->run_buffer_; + EIDOS_BZERO(haplosome->run_buffer_, SLIM_HAPLOSOME_MUTRUN_BUFSIZE * sizeof(const MutationRun *)); } else - haplosome.mutruns_ = (const MutationRun **)calloc(new_mutrun_count, sizeof(const MutationRun *)); + haplosome->mutruns_ = (const MutationRun **)calloc(new_mutrun_count, sizeof(const MutationRun *)); // Install empty MutationRun objects; I think this is not necessary, since this is the // child generation, which will not be accessed by anybody until crossover-mutation //for (int run_index = 0; run_index < new_mutrun_count; ++run_index) - // haplosome.mutruns_[run_index] = MutationRun::NewMutationRun(); + // haplosome->mutruns_[run_index] = MutationRun::NewMutationRun(); } } } @@ -5567,14 +5557,12 @@ void Population::SplitMutationRunsForChromosome(int32_t p_new_mutrun_count, Chro for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int32_t old_mutrun_count = haplosome.mutrun_count_; - slim_position_t old_mutrun_length = haplosome.mutrun_length_; + int32_t old_mutrun_count = haplosome->mutrun_count_; + slim_position_t old_mutrun_length = haplosome->mutrun_length_; int32_t new_mutrun_count = old_mutrun_count << 1; slim_position_t new_mutrun_length = old_mutrun_length >> 1; @@ -5583,7 +5571,7 @@ void Population::SplitMutationRunsForChromosome(int32_t p_new_mutrun_count, Chro for (int run_index = 0; run_index < old_mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; MutationRunContext &mutrun_context = chromosome.ChromosomeMutationRunContextForMutationRunIndex(run_index); if (mutrun->use_count() == 1) @@ -5628,20 +5616,20 @@ void Population::SplitMutationRunsForChromosome(int32_t p_new_mutrun_count, Chro } // now replace the runs in the haplosome with those in mutrun_buf - if (haplosome.mutruns_ != haplosome.run_buffer_) - free(haplosome.mutruns_); - haplosome.mutruns_ = nullptr; + if (haplosome->mutruns_ != haplosome->run_buffer_) + free(haplosome->mutruns_); + haplosome->mutruns_ = nullptr; - haplosome.mutrun_count_ = new_mutrun_count; - haplosome.mutrun_length_ = new_mutrun_length; + haplosome->mutrun_count_ = new_mutrun_count; + haplosome->mutrun_length_ = new_mutrun_length; if (new_mutrun_count <= SLIM_HAPLOSOME_MUTRUN_BUFSIZE) - haplosome.mutruns_ = haplosome.run_buffer_; + haplosome->mutruns_ = haplosome->run_buffer_; else - haplosome.mutruns_ = (const MutationRun **)malloc(new_mutrun_count * sizeof(const MutationRun *)); // not calloc() because overwritten below + haplosome->mutruns_ = (const MutationRun **)malloc(new_mutrun_count * sizeof(const MutationRun *)); // not calloc() because overwritten below for (int run_index = 0; run_index < new_mutrun_count; ++run_index) - haplosome.mutruns_[run_index] = mutruns_buf[run_index]; + haplosome->mutruns_[run_index] = mutruns_buf[run_index]; } } } @@ -5706,36 +5694,34 @@ void Population::JoinMutationRunsForChromosome(int32_t p_new_mutrun_count, Chrom for (Individual *ind : subpop->child_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int32_t old_mutrun_count = haplosome.mutrun_count_; - slim_position_t old_mutrun_length = haplosome.mutrun_length_; + int32_t old_mutrun_count = haplosome->mutrun_count_; + slim_position_t old_mutrun_length = haplosome->mutrun_length_; int32_t new_mutrun_count = old_mutrun_count >> 1; slim_position_t new_mutrun_length = old_mutrun_length << 1; - if (haplosome.mutruns_ != haplosome.run_buffer_) - free(haplosome.mutruns_); - haplosome.mutruns_ = nullptr; + if (haplosome->mutruns_ != haplosome->run_buffer_) + free(haplosome->mutruns_); + haplosome->mutruns_ = nullptr; - haplosome.mutrun_count_ = new_mutrun_count; - haplosome.mutrun_length_ = new_mutrun_length; + haplosome->mutrun_count_ = new_mutrun_count; + haplosome->mutrun_length_ = new_mutrun_length; if (new_mutrun_count <= SLIM_HAPLOSOME_MUTRUN_BUFSIZE) { - haplosome.mutruns_ = haplosome.run_buffer_; - EIDOS_BZERO(haplosome.run_buffer_, SLIM_HAPLOSOME_MUTRUN_BUFSIZE * sizeof(const MutationRun *)); + haplosome->mutruns_ = haplosome->run_buffer_; + EIDOS_BZERO(haplosome->run_buffer_, SLIM_HAPLOSOME_MUTRUN_BUFSIZE * sizeof(const MutationRun *)); } else - haplosome.mutruns_ = (const MutationRun **)calloc(new_mutrun_count, sizeof(const MutationRun *)); + haplosome->mutruns_ = (const MutationRun **)calloc(new_mutrun_count, sizeof(const MutationRun *)); // Install empty MutationRun objects; I think this is not necessary, since this is the // child generation, which will not be accessed by anybody until crossover-mutation //for (int run_index = 0; run_index < new_mutrun_count; ++run_index) - // haplosome.mutruns_[run_index] = MutationRun::NewMutationRun(); + // haplosome->mutruns_[run_index] = MutationRun::NewMutationRun(); } } } @@ -5767,14 +5753,12 @@ void Population::JoinMutationRunsForChromosome(int32_t p_new_mutrun_count, Chrom for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int32_t old_mutrun_count = haplosome.mutrun_count_; - slim_position_t old_mutrun_length = haplosome.mutrun_length_; + int32_t old_mutrun_count = haplosome->mutrun_count_; + slim_position_t old_mutrun_length = haplosome->mutrun_length_; int32_t new_mutrun_count = old_mutrun_count >> 1; slim_position_t new_mutrun_length = old_mutrun_length << 1; @@ -5783,8 +5767,8 @@ void Population::JoinMutationRunsForChromosome(int32_t p_new_mutrun_count, Chrom for (int run_index = 0; run_index < old_mutrun_count; run_index += 2) { - const MutationRun *mutrun1 = haplosome.mutruns_[run_index]; - const MutationRun *mutrun2 = haplosome.mutruns_[run_index + 1]; + const MutationRun *mutrun1 = haplosome->mutruns_[run_index]; + const MutationRun *mutrun2 = haplosome->mutruns_[run_index + 1]; MutationRunContext &mutrun_context = chromosome.ChromosomeMutationRunContextForMutationRunIndex(run_index); if ((mutrun1->use_count() == 1) || (mutrun2->use_count() == 1)) @@ -5826,20 +5810,20 @@ void Population::JoinMutationRunsForChromosome(int32_t p_new_mutrun_count, Chrom } // now replace the runs in the haplosome with those in mutrun_buf - if (haplosome.mutruns_ != haplosome.run_buffer_) - free(haplosome.mutruns_); - haplosome.mutruns_ = nullptr; + if (haplosome->mutruns_ != haplosome->run_buffer_) + free(haplosome->mutruns_); + haplosome->mutruns_ = nullptr; - haplosome.mutrun_count_ = new_mutrun_count; - haplosome.mutrun_length_ = new_mutrun_length; + haplosome->mutrun_count_ = new_mutrun_count; + haplosome->mutrun_length_ = new_mutrun_length; if (new_mutrun_count <= SLIM_HAPLOSOME_MUTRUN_BUFSIZE) - haplosome.mutruns_ = haplosome.run_buffer_; + haplosome->mutruns_ = haplosome->run_buffer_; else - haplosome.mutruns_ = (const MutationRun **)malloc(new_mutrun_count * sizeof(const MutationRun *)); // not calloc() because overwritten below + haplosome->mutruns_ = (const MutationRun **)malloc(new_mutrun_count * sizeof(const MutationRun *)); // not calloc() because overwritten below for (int run_index = 0; run_index < new_mutrun_count; ++run_index) - haplosome.mutruns_[run_index] = mutruns_buf[run_index]; + haplosome->mutruns_[run_index] = mutruns_buf[run_index]; } } } @@ -5932,18 +5916,16 @@ void Population::AssessMutationRuns(void) for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - mutrun_count = haplosome.mutrun_count_; - mutrun_length = haplosome.mutrun_length_; + mutrun_count = haplosome->mutrun_count_; + mutrun_length = haplosome->mutrun_length_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mutrun_size = mutrun->size(); total_mutrun_count++; @@ -6058,14 +6040,12 @@ slim_refcount_t Population::TallyMutationRunReferencesForPopulation(void) { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { for (int run_index = first_mutrun_index; run_index <= last_mutrun_index; ++run_index) - haplosome.mutruns_[run_index]->increment_use_count(); + haplosome->mutruns_[run_index]->increment_use_count(); total_haplosome_count++; } @@ -6077,12 +6057,10 @@ slim_refcount_t Population::TallyMutationRunReferencesForPopulation(void) // optimized case when null haplosomes do not exist in this subpop for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - for (int run_index = first_mutrun_index; run_index <= last_mutrun_index; ++run_index) - haplosome.mutruns_[run_index]->increment_use_count(); + haplosome->mutruns_[run_index]->increment_use_count(); } } @@ -6112,16 +6090,14 @@ slim_refcount_t Population::TallyMutationRunReferencesForPopulation(void) for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) - haplosome.mutruns_[run_index]->use_count_CHECK_++; + haplosome->mutruns_[run_index]->use_count_CHECK_++; total_haplosome_count_CHECK++; } @@ -6207,14 +6183,12 @@ slim_refcount_t Population::TallyMutationRunReferencesForSubpops(std::vectorparent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { for (int run_index = first_mutrun_index; run_index <= last_mutrun_index; ++run_index) - haplosome.mutruns_[run_index]->increment_use_count(); + haplosome->mutruns_[run_index]->increment_use_count(); total_haplosome_count++; } @@ -6226,12 +6200,10 @@ slim_refcount_t Population::TallyMutationRunReferencesForSubpops(std::vectorparent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - for (int run_index = first_mutrun_index; run_index <= last_mutrun_index; ++run_index) - haplosome.mutruns_[run_index]->increment_use_count(); + haplosome->mutruns_[run_index]->increment_use_count(); } } @@ -6364,11 +6336,9 @@ slim_refcount_t Population::_CountNonNullHaplosomes(void) { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) total_haplosome_count++; } } @@ -6476,10 +6446,8 @@ slim_refcount_t Population::TallyMutationReferencesAcrossPopulation(bool p_force for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - if (!haplosome->IsNull()) haplosomes.push_back(haplosome); } @@ -6535,17 +6503,15 @@ slim_refcount_t Population::TallyMutationReferencesAcrossPopulation(bool p_force { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -6572,17 +6538,15 @@ slim_refcount_t Population::TallyMutationReferencesAcrossPopulation(bool p_force { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -6635,11 +6599,9 @@ slim_refcount_t Population::TallyMutationReferencesAcrossSubpopulations(std::vec { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) total_haplosome_count++; } } @@ -6684,10 +6646,8 @@ slim_refcount_t Population::TallyMutationReferencesAcrossSubpopulations(std::vec { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - if (!haplosome->IsNull()) haplosomes.push_back(haplosome); } @@ -6707,17 +6667,15 @@ slim_refcount_t Population::TallyMutationReferencesAcrossSubpopulations(std::vec { for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -6776,15 +6734,15 @@ slim_refcount_t Population::TallyMutationReferencesAcrossHaplosomes(const Haplos for (slim_popsize_t i = 0; i < haplosomes_count; i++) { - const Haplosome &haplosome = *haplosomes_ptr[i]; + const Haplosome *haplosome = haplosomes_ptr[i]; - if (!haplosome.IsNull()) + if (!haplosome->IsNull()) { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -7236,10 +7194,8 @@ void Population::RemoveAllFixedMutations(void) Subpopulation *subpop = subpop_pair.second; for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - if (!haplosome->IsNull()) { // Loop over the mutations to remove, and take advantage of our mutation runs by scanning @@ -7360,14 +7316,13 @@ void Population::CheckMutationRegistry(bool p_check_haplosomes) Subpopulation *subpop = subpop_pair.second; for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; const MutationIndex *haplosome_iter = mutrun->begin_pointer_const(); const MutationIndex *haplosome_end_iter = mutrun->end_pointer_const(); @@ -7481,14 +7436,13 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions, for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); @@ -7610,23 +7564,21 @@ void Population::PrintAll(std::ostream &p_out, bool p_output_spatial_positions, for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); + p_out << "p" << subpop_id << ":" << i << " " << haplosome->AssociatedChromosome()->Type(); - p_out << "p" << subpop_id << ":" << i << " " << haplosome.AssociatedChromosome()->Type(); - - if (haplosome.IsNull()) + if (haplosome->IsNull()) { p_out << " "; } else { - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); @@ -7818,14 +7770,13 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); @@ -7896,12 +7847,10 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - // Write out the haplosome header; start with the haplosome type to guarantee that the first 32 bits are != section_end_tag - int32_t chromosome_type = (int32_t)(haplosome.AssociatedChromosome()->Type()); + int32_t chromosome_type = (int32_t)(haplosome->AssociatedChromosome()->Type()); p_out.write(reinterpret_cast(&chromosome_type), sizeof chromosome_type); p_out.write(reinterpret_cast(&subpop_id), sizeof subpop_id); @@ -7941,7 +7890,7 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit } // Write out the mutation list - if (haplosome.IsNull()) + if (haplosome->IsNull()) { // null haplosomes get a 32-bit flag value written instead of a mutation count int32_t null_haplosome_tag = 0xFFFF1000; @@ -7952,7 +7901,7 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit { // write a 32-bit mutation count { - int32_t total_mutations = haplosome.mutation_count(); + int32_t total_mutations = haplosome->mutation_count(); p_out.write(reinterpret_cast(&total_mutations), sizeof total_mutations); } @@ -7960,11 +7909,11 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit if (use_16_bit) { // Write out 16-bit mutation tags - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); @@ -7991,11 +7940,11 @@ void Population::PrintAllBinary(std::ostream &p_out, bool p_output_spatial_posit else { // Write out 32-bit mutation tags - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); @@ -8044,8 +7993,8 @@ void Population::PrintSample_SLiM(std::ostream &p_out, Subpopulation &p_subpop, if (p_subpop.sex_enabled_ && (p_requested_sex != IndividualSex::kUnspecified) && (ind->sex_ != p_requested_sex)) continue; - Haplosome *haplosome1 = ind->haplosome1_; - Haplosome *haplosome2 = ind->haplosome2_; + Haplosome *haplosome1 = ind->haplosomes_[0]; + Haplosome *haplosome2 = ind->haplosomes_[1]; if (!haplosome1->IsNull()) candidates.push_back(haplosome1); @@ -8095,8 +8044,8 @@ void Population::PrintSample_MS(std::ostream &p_out, Subpopulation &p_subpop, sl if (p_subpop.sex_enabled_ && (p_requested_sex != IndividualSex::kUnspecified) && (ind->sex_ != p_requested_sex)) continue; - Haplosome *haplosome1 = ind->haplosome1_; - Haplosome *haplosome2 = ind->haplosome2_; + Haplosome *haplosome1 = ind->haplosomes_[0]; + Haplosome *haplosome2 = ind->haplosomes_[1]; if (!haplosome1->IsNull()) candidates.push_back(haplosome1); @@ -8163,8 +8112,8 @@ void Population::PrintSample_VCF(std::ostream &p_out, Subpopulation &p_subpop, s // select a random individual (not a random haplosome) by selecting a random candidate entry int candidate_index = static_cast(Eidos_rng_uniform_int(rng, (uint32_t)candidates.size())); - sample.emplace_back(candidates[candidate_index]->haplosome1_); - sample.emplace_back(candidates[candidate_index]->haplosome2_); + sample.emplace_back(candidates[candidate_index]->haplosomes_[0]); + sample.emplace_back(candidates[candidate_index]->haplosomes_[1]); // If we're sampling without replacement, remove the index we have just taken; either we will use it or it is invalid if (!p_replace) diff --git a/core/species.cpp b/core/species.cpp index 4c2fadc2..29a7e578 100644 --- a/core/species.cpp +++ b/core/species.cpp @@ -770,8 +770,8 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos if (PedigreesEnabled()) { individual.SetPedigreeID(pedigree_id); - individual.haplosome1_->SetHaplosomeID(pedigree_id * 2); - individual.haplosome2_->SetHaplosomeID(pedigree_id * 2 + 1); + individual.haplosomes_[0]->SetHaplosomeID(pedigree_id * 2); + individual.haplosomes_[1]->SetHaplosomeID(pedigree_id * 2 + 1); gSLiM_next_pedigree_id = std::max(gSLiM_next_pedigree_id, pedigree_id + 1); } } @@ -864,7 +864,7 @@ slim_tick_t Species::_InitializePopulationFromTextFile(const char *p_file, Eidos int64_t individual_index = haplosome_index >> 1; Individual *ind = subpop->parent_individuals_[individual_index]; - Haplosome &haplosome = *((haplosome_index & 0x01) ? ind->haplosome1_ : ind->haplosome2_); + Haplosome &haplosome = *(ind->haplosomes_[haplosome_index & 0x01]); // Now we might have [A|X|Y] (SLiM 2.0), or we might have the first mutation id - or we might have nothing at all if (iss >> sub) @@ -1538,8 +1538,8 @@ slim_tick_t Species::_InitializePopulationFromBinaryFile(const char *p_file, Eid memcpy(&pedigree_id, p, sizeof(pedigree_id)); individual.SetPedigreeID(pedigree_id); - individual.haplosome1_->SetHaplosomeID(pedigree_id * 2); - individual.haplosome2_->SetHaplosomeID(pedigree_id * 2 + 1); + individual.haplosomes_[0]->SetHaplosomeID(pedigree_id * 2); + individual.haplosomes_[1]->SetHaplosomeID(pedigree_id * 2 + 1); gSLiM_next_pedigree_id = std::max(gSLiM_next_pedigree_id, pedigree_id + 1); } @@ -1569,7 +1569,7 @@ slim_tick_t Species::_InitializePopulationFromBinaryFile(const char *p_file, Eid int64_t individual_index = haplosome_index >> 1; Individual *ind = subpop->parent_individuals_[individual_index]; - Haplosome &haplosome = *((haplosome_index & 0x01) ? ind->haplosome1_ : ind->haplosome2_); + Haplosome &haplosome = *(ind->haplosomes_[haplosome_index & 0x01]); // Error-check the haplosome type if (haplosome_type != (int32_t)haplosome.AssociatedChromosome()->Type()) @@ -2744,20 +2744,17 @@ void Species::TabulateSLiMMemoryUsage_Species(SLiMMemoryUsage_Species *p_usage) Subpopulation &subpop = *iter.second; for (Individual *ind : subpop.parent_individuals_) - { - all_haplosomes_in_use.push_back(ind->haplosome1_); - all_haplosomes_in_use.push_back(ind->haplosome2_); - } + for (Haplosome *haplosome : ind->haplosomes_) + all_haplosomes_in_use.push_back(haplosome); + for (Individual *ind : subpop.child_individuals_) - { - all_haplosomes_in_use.push_back(ind->haplosome1_); - all_haplosomes_in_use.push_back(ind->haplosome2_); - } + for (Haplosome *haplosome : ind->haplosomes_) + all_haplosomes_in_use.push_back(haplosome); + for (Individual *ind : subpop.nonWF_offspring_individuals_) - { - all_haplosomes_in_use.push_back(ind->haplosome1_); - all_haplosomes_in_use.push_back(ind->haplosome2_); - } + for (Haplosome *haplosome : ind->haplosomes_) + all_haplosomes_in_use.push_back(haplosome); + } all_haplosomes_not_in_use.insert(all_haplosomes_not_in_use.end(), population_.species_haplosomes_junkyard_nonnull.begin(), population_.species_haplosomes_junkyard_nonnull.end()); @@ -3091,9 +3088,10 @@ void Species::CollectMutationProfileInfo(void) for (std::pair &subpop_pair : population_.subpops_) { Subpopulation *subpop = subpop_pair.second; - std::vector &subpop_haplosome = subpop->parent_haplosomes_; - for (Haplosome *haplosome : subpop_haplosome) + for (Individual *ind : subpop->parent_individuals_) + { + for (Haplosome *haplosome : ind->haplosomes_) { const MutationRun **mutruns = haplosome->mutruns_; int32_t mutrun_count = haplosome->mutrun_count_; @@ -3117,6 +3115,7 @@ void Species::CollectMutationProfileInfo(void) } } } + } } } #endif @@ -3533,9 +3532,8 @@ void Species::SimplifyTreeSequence(void) for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); tsk_id_t M = haplosome->tsk_node_id_; // check if this sample is already being remembered, and assign the correct tsk_node_id_ @@ -3666,14 +3664,10 @@ void Species::CheckCoalescenceAfterSimplification(void) for (auto subpop_iter : population_.subpops_) { Subpopulation *subpop = subpop_iter.second; + for (Individual *ind : subpop->parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); + for (Haplosome *haplosome : ind->haplosomes_) all_extant_nodes.emplace_back(haplosome->tsk_node_id_); - } - } } int64_t extant_node_count = (int64_t)all_extant_nodes.size(); @@ -4235,16 +4229,16 @@ void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_n p_individuals_hash->emplace(ped_id, tsk_individual); // Update node table - assert(ind->haplosome1_->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows - && ind->haplosome2_->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows); - p_tables->nodes.individual[ind->haplosome1_->tsk_node_id_] = tsk_individual; - p_tables->nodes.individual[ind->haplosome2_->tsk_node_id_] = tsk_individual; + assert(ind->haplosomes_[0]->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows + && ind->haplosomes_[1]->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows); + p_tables->nodes.individual[ind->haplosomes_[0]->tsk_node_id_] = tsk_individual; + p_tables->nodes.individual[ind->haplosomes_[1]->tsk_node_id_] = tsk_individual; // update remembered haplosomes if (p_flags & SLIM_TSK_INDIVIDUAL_REMEMBERED) { - remembered_haplosomes_.emplace_back(ind->haplosome1_->tsk_node_id_); - remembered_haplosomes_.emplace_back(ind->haplosome2_->tsk_node_id_); + remembered_haplosomes_.emplace_back(ind->haplosomes_[0]->tsk_node_id_); + remembered_haplosomes_.emplace_back(ind->haplosomes_[1]->tsk_node_id_); } } else { // This individual is already there; we need to update the information. @@ -4264,8 +4258,8 @@ void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_n if (((p_tables->individuals.flags[tsk_individual] & SLIM_TSK_INDIVIDUAL_REMEMBERED) == 0) && (p_flags & SLIM_TSK_INDIVIDUAL_REMEMBERED)) { - remembered_haplosomes_.emplace_back(ind->haplosome1_->tsk_node_id_); - remembered_haplosomes_.emplace_back(ind->haplosome2_->tsk_node_id_); + remembered_haplosomes_.emplace_back(ind->haplosomes_[0]->tsk_node_id_); + remembered_haplosomes_.emplace_back(ind->haplosomes_[1]->tsk_node_id_); } memcpy(p_tables->individuals.location @@ -4277,14 +4271,14 @@ void Species::AddIndividualsToTable(Individual * const *p_individual, size_t p_n p_tables->individuals.flags[tsk_individual] |= p_flags; // Check node table - assert(ind->haplosome1_->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows - && ind->haplosome2_->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows); + assert(ind->haplosomes_[0]->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows + && ind->haplosomes_[1]->tsk_node_id_ < (tsk_id_t) p_tables->nodes.num_rows); // BCH 4/29/2019: These asserts are, we think, not technically necessary – the code // would work even if they were violated. But they're a nice invariant to guarantee, // and right now they are always true. - assert(p_tables->nodes.individual[ind->haplosome1_->tsk_node_id_] == (tsk_id_t)tsk_individual); - assert(p_tables->nodes.individual[ind->haplosome2_->tsk_node_id_] == (tsk_id_t)tsk_individual); + assert(p_tables->nodes.individual[ind->haplosomes_[0]->tsk_node_id_] == (tsk_id_t)tsk_individual); + assert(p_tables->nodes.individual[ind->haplosomes_[1]->tsk_node_id_] == (tsk_id_t)tsk_individual); } } } @@ -5284,7 +5278,7 @@ void Species::WriteTreeSequence(std::string &p_recording_tree_path, bool p_simpl for (Individual *individual : subpop->parent_individuals_) { - tsk_id_t node_id = individual->haplosome1_->tsk_node_id_; + tsk_id_t node_id = individual->haplosomes_[0]->tsk_node_id_; tsk_id_t ind_id = output_tables.nodes.individual[node_id]; individual_map.emplace_back(ind_id); @@ -5393,8 +5387,8 @@ void Species::RecordAllDerivedStatesFromSLiM(void) for (Individual *individual : subpop->parent_individuals_) { - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; // This is done for us, at present, as a side effect of the readPopulationFile() code... //SetCurrentNewIndividual(individual); @@ -5555,13 +5549,8 @@ void Species::CrosscheckTreeSeqIntegrity(void) Subpopulation *subpop = pop_iter.second; for (Individual *ind : subpop->parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); + for (Haplosome *haplosome : ind->haplosomes_) haplosomes.emplace_back(haplosome); - } - } } // if we have no haplosomes to check, we return; we could check that the tree sequences are also empty, but we don't @@ -5611,13 +5600,8 @@ void Species::CrosscheckTreeSeqIntegrity(void) Subpopulation *subpop = iter.second; for (Individual *ind : subpop->parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); + for (Haplosome *haplosome : ind->haplosomes_) samples.emplace_back(haplosome->tsk_node_id_); - } - } } tsk_flags_t flags = TSK_NO_CHECK_INTEGRITY; @@ -6749,11 +6733,11 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_maphaplosome1_->tsk_node_id_ = node_id_0; - individual->haplosome2_->tsk_node_id_ = node_id_1; + individual->haplosomes_[0]->tsk_node_id_ = node_id_0; + individual->haplosomes_[1]->tsk_node_id_ = node_id_1; - p_nodeToHaplosomeMap.emplace(node_id_0, individual->haplosome1_); - p_nodeToHaplosomeMap.emplace(node_id_1, individual->haplosome2_); + p_nodeToHaplosomeMap.emplace(node_id_0, individual->haplosomes_[0]); + p_nodeToHaplosomeMap.emplace(node_id_1, individual->haplosomes_[1]); slim_pedigreeid_t pedigree_id = subpop_info.pedigreeID_[tabulation_index]; individual->SetPedigreeID(pedigree_id); @@ -6766,8 +6750,8 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_mapmigrant_ = true; - individual->haplosome1_->haplosome_id_ = pedigree_id * 2; - individual->haplosome2_->haplosome_id_ = pedigree_id * 2 + 1; + individual->haplosomes_[0]->haplosome_id_ = pedigree_id * 2; + individual->haplosomes_[1]->haplosome_id_ = pedigree_id * 2 + 1; individual->age_ = subpop_info.age_[tabulation_index]; individual->spatial_x_ = subpop_info.spatial_x_[tabulation_index]; @@ -6785,7 +6769,7 @@ void Species::__CreateSubpopulationsFromTabulation(std::unordered_maphaplosome1_, *haplosome1 = individual->haplosome2_; + Haplosome *haplosome0 = individual->haplosomes_[0], *haplosome1 = individual->haplosomes_[1]; if ((node0_metadata->haplosome_id_ != haplosome0->haplosome_id_) || (node1_metadata->haplosome_id_ != haplosome1->haplosome_id_)) EIDOS_TERMINATION << "ERROR (Species::__CreateSubpopulationsFromTabulation): node-haplosome id mismatch; this file cannot be read." << EidosTerminate(); @@ -7229,14 +7213,9 @@ void Species::__CreateMutationsFromTabulation(std::unordered_mapparent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); + for (Haplosome *haplosome : ind->haplosomes_) if (!haplosome->IsNull()) fixation_count++; - } - } } // instantiate mutations diff --git a/core/species_eidos.cpp b/core/species_eidos.cpp index 81a3bbbc..f4281d1d 100644 --- a/core/species_eidos.cpp +++ b/core/species_eidos.cpp @@ -2860,14 +2860,13 @@ EidosValue_SP Species::ExecuteMethod_outputMutations(EidosGlobalStringID p_metho for (Individual *ind : subpop->parent_individuals_) { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) + for (Haplosome *haplosome : ind->haplosomes_) { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - int mutrun_count = haplosome.mutrun_count_; + int mutrun_count = haplosome->mutrun_count_; for (int run_index = 0; run_index < mutrun_count; ++run_index) { - const MutationRun *mutrun = haplosome.mutruns_[run_index]; + const MutationRun *mutrun = haplosome->mutruns_[run_index]; int mut_count = mutrun->size(); const MutationIndex *mut_ptr = mutrun->begin_pointer_const(); diff --git a/core/subpopulation.cpp b/core/subpopulation.cpp index c667facb..70c3a705 100644 --- a/core/subpopulation.cpp +++ b/core/subpopulation.cpp @@ -102,8 +102,8 @@ void Subpopulation::WipeIndividualsAndHaplosomes(std::vector &p_in { Individual *individual = p_individuals[index]; - individual->haplosome1_->ReinitializeHaplosomeNullptr(mutrun_count, mutrun_length); - individual->haplosome2_->ReinitializeHaplosomeNullptr(mutrun_count, mutrun_length); + individual->haplosomes_[0]->ReinitializeHaplosomeNullptr(mutrun_count, mutrun_length); + individual->haplosomes_[1]->ReinitializeHaplosomeNullptr(mutrun_count, mutrun_length); } } } @@ -113,8 +113,8 @@ void Subpopulation::WipeIndividualsAndHaplosomes(std::vector &p_in for (int index = 0; index < p_individual_count; ++index) { Individual *individual = p_individuals[index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; bool is_female = (index < p_first_male); individual->sex_ = (is_female ? IndividualSex::kFemale : IndividualSex::kMale); @@ -485,8 +485,8 @@ void Subpopulation::CheckIndividualIntegrity(void) for (int ind_index = 0; ind_index < parent_subpop_size_; ++ind_index) { Individual *individual = parent_individuals_[ind_index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; bool invalid_age = false; if (!individual) @@ -649,8 +649,8 @@ void Subpopulation::CheckIndividualIntegrity(void) for (int ind_index = 0; ind_index < child_subpop_size_; ++ind_index) { Individual *individual = child_individuals_[ind_index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; if (!individual) EIDOS_TERMINATION << "ERROR (Subpopulation::CheckIndividualIntegrity): (internal error) null pointer for individual." << EidosTerminate(); @@ -1033,15 +1033,9 @@ slim_refcount_t Subpopulation::NullHaplosomeCount(void) slim_refcount_t null_haplosome_count = 0; for (Individual *ind : parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome &haplosome = *((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - - if (haplosome.IsNull()) + for (Haplosome *haplosome : ind->haplosomes_) + if (haplosome->IsNull()) null_haplosome_count++; - } - } return null_haplosome_count; } @@ -2456,8 +2450,8 @@ double Subpopulation::FitnessOfParentWithHaplosomeIndices_NoCallbacks(slim_popsi Mutation *mut_block_ptr = gSLiM_Mutation_Block; Individual *individual = parent_individuals_[p_individual_index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; bool haplosome1_null = haplosome1->IsNull(); bool haplosome2_null = haplosome2->IsNull(); @@ -2657,8 +2651,8 @@ double Subpopulation::FitnessOfParentWithHaplosomeIndices_Callbacks(slim_popsize Mutation *mut_block_ptr = gSLiM_Mutation_Block; Individual *individual = parent_individuals_[p_individual_index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; bool haplosome1_null = haplosome1->IsNull(); bool haplosome2_null = haplosome2->IsNull(); @@ -2896,8 +2890,8 @@ double Subpopulation::FitnessOfParentWithHaplosomeIndices_SingleCallback(slim_po Mutation *mut_block_ptr = gSLiM_Mutation_Block; Individual *individual = parent_individuals_[p_individual_index]; - Haplosome *haplosome1 = individual->haplosome1_; - Haplosome *haplosome2 = individual->haplosome2_; + Haplosome *haplosome1 = individual->haplosomes_[0]; + Haplosome *haplosome2 = individual->haplosomes_[1]; bool haplosome1_null = haplosome1->IsNull(); bool haplosome2_null = haplosome2->IsNull(); @@ -3296,10 +3290,8 @@ void Subpopulation::SwapChildAndParentHaplosomes(void) if (Individual::s_any_haplosome_tag_set_) { for (Individual *child : child_individuals_) - { - child->haplosome1_->tag_value_ = SLIM_TAG_UNSET_VALUE; - child->haplosome2_->tag_value_ = SLIM_TAG_UNSET_VALUE; - } + for (Haplosome *haplosome : child->haplosomes_) + haplosome->tag_value_ = SLIM_TAG_UNSET_VALUE; } if (species_.PedigreesEnabled()) @@ -3689,7 +3681,6 @@ void Subpopulation::ViabilitySurvival(std::vector &p_survival_c // Loop through our individuals and do draws based on fitness to determine who dies; dead individuals get compacted out Individual **individual_data = parent_individuals_.data(); - int survived_haplosome_index = 0; int survived_individual_index = 0; int females_deceased = 0; bool individuals_died = false; @@ -3780,7 +3771,6 @@ void Subpopulation::ViabilitySurvival(std::vector &p_survival_c individual_data[survived_individual_index]->index_ = survived_individual_index; } - survived_haplosome_index += 2; survived_individual_index++; } else @@ -3905,14 +3895,8 @@ EidosValue_SP Subpopulation::GetProperty(EidosGlobalStringID p_property_id) EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->reserve(expected_haplosome_count); for (Individual *ind : parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - + for (Haplosome *haplosome : ind->haplosomes_) vec->push_object_element_no_check_NORR(haplosome); - } - } return EidosValue_SP(vec); } @@ -3922,15 +3906,9 @@ EidosValue_SP Subpopulation::GetProperty(EidosGlobalStringID p_property_id) EidosValue_Object *vec = (new (gEidosValuePool->AllocateChunk()) EidosValue_Object(gSLiM_Haplosome_Class))->reserve(expected_haplosome_count); for (Individual *ind : parent_individuals_) - { - for (int haplosome_index = 0; haplosome_index <= 1; ++haplosome_index) - { - Haplosome *haplosome = ((haplosome_index == 0) ? ind->haplosome1_ : ind->haplosome2_); - + for (Haplosome *haplosome : ind->haplosomes_) if (!haplosome->IsNull()) vec->push_object_element_no_check_NORR(haplosome); - } - } return EidosValue_SP(vec); } @@ -4435,7 +4413,7 @@ EidosValue_SP Subpopulation::ExecuteMethod_addCloned(EidosGlobalStringID p_metho return EidosValue_SP(result); // Determine the sex of the offspring, and the consequent expected haplosome types - bool haplosome1_null = parent->haplosome1_->IsNull(), haplosome2_null = parent->haplosome2_->IsNull(); + bool haplosome1_null = parent->haplosomes_[0]->IsNull(), haplosome2_null = parent->haplosomes_[1]->IsNull(); IndividualSex child_sex = parent_sex; if (haplosome1_null || haplosome2_null) @@ -4445,8 +4423,8 @@ EidosValue_SP Subpopulation::ExecuteMethod_addCloned(EidosGlobalStringID p_metho Chromosome &chromosome = species_.TheChromosome(); int32_t mutrun_count = chromosome.mutrun_count_; slim_position_t mutrun_length = chromosome.mutrun_length_; - Haplosome &parent_haplosome_1 = *parent->haplosome1_; - Haplosome &parent_haplosome_2 = *parent->haplosome2_; + Haplosome &parent_haplosome_1 = *parent->haplosomes_[0]; + Haplosome &parent_haplosome_2 = *parent->haplosomes_[1]; std::vector *parent_mutation_callbacks = &parent_subpop.registered_mutation_callbacks_; std::vector &modify_child_callbacks_ = parent_subpop.registered_modify_child_callbacks_; @@ -5661,7 +5639,7 @@ EidosValue_SP Subpopulation::ExecuteMethod_takeMigrants(EidosGlobalStringID p_me parent_individuals_[parent_first_male_index_] = migrant; // the has_null_haplosomes_ needs to reflect the presence of null haplosomes - if (migrant->haplosome1_->IsNull() || migrant->haplosome2_->IsNull()) + if (migrant->haplosomes_[0]->IsNull() || migrant->haplosomes_[1]->IsNull()) has_null_haplosomes_ = true; migrant->subpopulation_ = this; @@ -5676,7 +5654,7 @@ EidosValue_SP Subpopulation::ExecuteMethod_takeMigrants(EidosGlobalStringID p_me parent_individuals_.emplace_back(migrant); // the has_null_haplosomes_ needs to reflect the presence of null haplosomes - if (migrant->haplosome1_->IsNull() || migrant->haplosome2_->IsNull()) + if (migrant->haplosomes_[0]->IsNull() || migrant->haplosomes_[1]->IsNull()) has_null_haplosomes_ = true; migrant->subpopulation_ = this;