From c76560be17873389fa9e7ea8c335377ebca5cccc Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Fri, 13 May 2022 04:56:03 +0000 Subject: [PATCH 01/21] Untested impl of more robust index sampling --- necsim/core/src/cogs/rng.rs | 133 ++++++++++++------ .../alias/sampler/indexed/mod.rs | 5 +- .../alias/sampler/indexed/tests.rs | 7 - .../alias/sampler/stack/mod.rs | 5 +- .../alias/sampler/stack/tests.rs | 7 - 5 files changed, 97 insertions(+), 60 deletions(-) diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index b9145f0fc..f08ae55c1 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -41,6 +41,7 @@ pub trait SeedableRng: RngCore { const INC: u64 = 11_634_580_027_462_260_723_u64; let mut seed = Self::Seed::default(); + for chunk in seed.as_mut().chunks_mut(4) { // We advance the state first (to get away from the input value, // in case it has low Hamming Weight). @@ -96,68 +97,112 @@ pub trait RngSampler: RngCore { #[inline] #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] fn sample_index(&mut self, length: NonZeroUsize) -> usize { - // attributes on expressions are experimental - // see https://github.com/rust-lang/rust/issues/15701 - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = - M::floor(self.sample_uniform_closed_open().get() * (length.get() as f64)) as usize; - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + #[cfg(target_pointer_width = "32")] + #[allow(clippy::cast_possible_truncation)] + { + self.sample_index_u32(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }) + as usize + } + #[cfg(target_pointer_width = "64")] + #[allow(clippy::cast_possible_truncation)] + { + self.sample_index_u64(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }) + as usize + } } #[must_use] #[inline] #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] fn sample_index_u32(&mut self, length: NonZeroU32) -> u32 { - // attributes on expressions are experimental - // see https://github.com/rust-lang/rust/issues/15701 - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = - M::floor(self.sample_uniform_closed_open().get() * f64::from(length.get())) as u32; - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + // TODO: Check if delegation to `sample_index_u64` is faster + + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u64 = !0 >> 32; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = self.sample_u64(); + + let sample_check_lo = (raw & LOWER_MASK) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_lo as u32) <= acceptance_zone { + return (sample_check_lo >> 32) as u32; + } + + let sample_check_hi = (raw >> 32) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_hi as u32) <= acceptance_zone { + return (sample_check_hi >> 32) as u32; + } + } } #[must_use] #[inline] #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] fn sample_index_u64(&mut self, length: NonZeroU64) -> u64 { - // attributes on expressions are experimental - // see https://github.com/rust-lang/rust/issues/15701 - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = - M::floor(self.sample_uniform_closed_open().get() * (length.get() as f64)) as u64; - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = self.sample_u64(); + + let sample_check = u128::from(raw) * u128::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check as u64) <= acceptance_zone { + return (sample_check >> 64) as u64; + } + } } #[must_use] #[inline] #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] fn sample_index_u128(&mut self, length: NonZeroU128) -> u128 { - // attributes on expressions are experimental - // see https://github.com/rust-lang/rust/issues/15701 - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = - M::floor(self.sample_uniform_closed_open().get() * (length.get() as f64)) as u128; - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u128 = !0 >> 64; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw_hi = u128::from(self.sample_u64()); + let raw_lo = u128::from(self.sample_u64()); + + // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length + let mut low = raw_lo * (length.get() & LOWER_MASK); + let mut t = low >> 64; + low &= LOWER_MASK; + t += raw_hi * (length.get() & LOWER_MASK); + low += (t & LOWER_MASK) << 64; + let mut high = t >> 64; + t = low >> 64; + low &= LOWER_MASK; + t += (length.get() >> 64) * raw_lo; + low += (t & LOWER_MASK) << 64; + high += t >> 64; + high += raw_hi * (length.get() >> 64); + + let sample = high; + let check = low; + + if check <= acceptance_zone { + return sample; + } + } } #[must_use] diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 857a81824..df51351c9 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -1,9 +1,10 @@ use alloc::{vec, vec::Vec}; use core::{ cmp::Ordering, + convert::TryFrom, fmt, hash::Hash, - num::{NonZeroU128, NonZeroUsize}, + num::{NonZeroU128, NonZeroU64, NonZeroUsize}, }; use fnv::FnvBuildHasher; @@ -190,6 +191,8 @@ impl DynamicAliasMethodIndexedSampler { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 + } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { + u128::from(rng.sample_index_u64(total_weight)) } else { rng.sample_index_u128(total_weight) }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 00e8d33a5..5f8310137 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1100,11 +1100,4 @@ impl RngCore for DummyRng { self.0.pop().unwrap() } } - -#[contract_trait] -impl Backup for DummyRng { - unsafe fn backup_unchecked(&self) -> Self { - Self(self.0.clone()) - } -} // GRCOV_EXCL_STOP diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index a0af49b8e..237653a8f 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -1,9 +1,10 @@ use alloc::{vec, vec::Vec}; use core::{ cmp::Ordering, + convert::TryFrom, fmt, hash::Hash, - num::{NonZeroU128, NonZeroUsize}, + num::{NonZeroU128, NonZeroU64, NonZeroUsize}, }; use necsim_core::cogs::{Backup, MathsCore, RngCore, RngSampler}; @@ -124,6 +125,8 @@ impl DynamicAliasMethodStackSampler { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 + } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { + u128::from(rng.sample_index_u64(total_weight)) } else { rng.sample_index_u128(total_weight) }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 461fe6904..b2e6739c1 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -598,11 +598,4 @@ impl RngCore for DummyRng { self.0.pop().unwrap() } } - -#[contract_trait] -impl Backup for DummyRng { - unsafe fn backup_unchecked(&self) -> Self { - Self(self.0.clone()) - } -} // GRCOV_EXCL_STOP From 8b1da043a86cd42c847822a7ec7aab89b7b169d3 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Mon, 16 May 2022 10:15:02 +0000 Subject: [PATCH 02/21] Start of modular RNG generator+sampler redesign experiment --- .../core/src/cogs/active_lineage_sampler.rs | 4 +- necsim/core/src/cogs/coalescence_sampler.rs | 16 +- necsim/core/src/cogs/dispersal_sampler.rs | 6 +- necsim/core/src/cogs/emigration_exit.rs | 4 +- necsim/core/src/cogs/event_sampler.rs | 6 +- necsim/core/src/cogs/habitat.rs | 4 +- necsim/core/src/cogs/mod.rs | 5 +- necsim/core/src/cogs/rng.rs | 314 +++++++++++++++--- necsim/core/src/simulation/backup.rs | 6 +- necsim/core/src/simulation/builder.rs | 11 +- necsim/core/src/simulation/mod.rs | 4 +- .../partial/active_lineage_sampler.rs | 6 +- .../src/simulation/partial/emigration_exit.rs | 4 +- .../src/simulation/partial/event_sampler.rs | 8 +- .../src/simulation/process/immigration.rs | 4 +- necsim/core/src/simulation/process/local.rs | 4 +- 16 files changed, 324 insertions(+), 82 deletions(-) diff --git a/necsim/core/src/cogs/active_lineage_sampler.rs b/necsim/core/src/cogs/active_lineage_sampler.rs index 98df0a19e..bb8b2cc76 100644 --- a/necsim/core/src/cogs/active_lineage_sampler.rs +++ b/necsim/core/src/cogs/active_lineage_sampler.rs @@ -4,7 +4,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use super::{ CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, ImmigrationEntry, - LineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }; use crate::{lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation}; @@ -15,7 +15,7 @@ use crate::{lineage::Lineage, simulation::partial::active_lineage_sampler::Parti pub trait ActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/cogs/coalescence_sampler.rs b/necsim/core/src/cogs/coalescence_sampler.rs index 93af7bc92..526d64cf7 100644 --- a/necsim/core/src/cogs/coalescence_sampler.rs +++ b/necsim/core/src/cogs/coalescence_sampler.rs @@ -5,13 +5,14 @@ use necsim_core_bond::ClosedOpenUnitF64; use serde::{Deserialize, Serialize}; use crate::{ - cogs::{Backup, MathsCore, RngCore}, + cogs::{ + rng::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, LineageStore, MathsCore, + Rng, + }, landscape::{IndexedLocation, Location}, lineage::LineageInteraction, }; -use super::{Habitat, LineageStore}; - #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] pub trait CoalescenceSampler, S: LineageStore>: @@ -57,10 +58,11 @@ impl Eq for CoalescenceRngSample {} impl CoalescenceRngSample { #[must_use] #[inline] - pub fn new>(rng: &mut G) -> Self { - use crate::cogs::RngSampler; - - Self(rng.sample_uniform_closed_open()) + pub fn new>(rng: &mut G) -> Self + where + G::Sampler: DistributionSampler, + { + Self(rng.sample::()) } #[must_use] diff --git a/necsim/core/src/cogs/dispersal_sampler.rs b/necsim/core/src/cogs/dispersal_sampler.rs index 00f7e01ed..5d6a817e7 100644 --- a/necsim/core/src/cogs/dispersal_sampler.rs +++ b/necsim/core/src/cogs/dispersal_sampler.rs @@ -1,7 +1,7 @@ use necsim_core_bond::ClosedUnitF64; use crate::{ - cogs::{MathsCore, RngCore}, + cogs::{MathsCore, Rng}, landscape::Location, }; @@ -11,7 +11,7 @@ use super::Habitat; #[allow(clippy::no_effect_underscore_binding)] #[allow(clippy::module_name_repetitions)] #[contract_trait] -pub trait DispersalSampler, G: RngCore>: +pub trait DispersalSampler, G: Rng>: crate::cogs::Backup + core::fmt::Debug { #[must_use] @@ -29,7 +29,7 @@ pub trait DispersalSampler, G: RngCore>: #[allow(clippy::no_effect_underscore_binding)] #[allow(clippy::module_name_repetitions)] #[contract_trait] -pub trait SeparableDispersalSampler, G: RngCore>: +pub trait SeparableDispersalSampler, G: Rng>: DispersalSampler { #[must_use] diff --git a/necsim/core/src/cogs/emigration_exit.rs b/necsim/core/src/cogs/emigration_exit.rs index 45c6d37c3..3812eee63 100644 --- a/necsim/core/src/cogs/emigration_exit.rs +++ b/necsim/core/src/cogs/emigration_exit.rs @@ -1,7 +1,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use crate::{ - cogs::{Habitat, LineageStore, MathsCore, RngCore}, + cogs::{Habitat, LineageStore, MathsCore, Rng}, landscape::{IndexedLocation, Location}, lineage::GlobalLineageReference, simulation::partial::emigration_exit::PartialSimulation, @@ -14,7 +14,7 @@ use crate::{ )] #[allow(clippy::no_effect_underscore_binding)] #[contract_trait] -pub trait EmigrationExit, G: RngCore, S: LineageStore>: +pub trait EmigrationExit, G: Rng, S: LineageStore>: crate::cogs::Backup + core::fmt::Debug { #[must_use] diff --git a/necsim/core/src/cogs/event_sampler.rs b/necsim/core/src/cogs/event_sampler.rs index 1a619935f..7aecda59f 100644 --- a/necsim/core/src/cogs/event_sampler.rs +++ b/necsim/core/src/cogs/event_sampler.rs @@ -1,8 +1,8 @@ use necsim_core_bond::PositiveF64; use super::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, - RngCore, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }; use crate::{ event::{DispersalEvent, SpeciationEvent}, @@ -21,7 +21,7 @@ pub struct EventHandler { pub trait EventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/cogs/habitat.rs b/necsim/core/src/cogs/habitat.rs index 105ed41b6..1442637ad 100644 --- a/necsim/core/src/cogs/habitat.rs +++ b/necsim/core/src/cogs/habitat.rs @@ -2,7 +2,7 @@ use necsim_core_bond::OffByOneU64; use crate::landscape::{IndexedLocation, LandscapeExtent, Location}; -use super::{MathsCore, RngCore}; +use super::{MathsCore, Rng}; #[allow( clippy::inline_always, @@ -67,7 +67,7 @@ pub trait Habitat: crate::cogs::Backup + core::fmt::Debug + Sized clippy::no_effect_underscore_binding )] #[contract_trait] -pub trait UniformlySampleableHabitat>: Habitat { +pub trait UniformlySampleableHabitat>: Habitat { #[debug_ensures( old(self).get_extent().contains(ret.location()) && ret.index() < old(self).get_habitat_at_location(ret.location()), diff --git a/necsim/core/src/cogs/mod.rs b/necsim/core/src/cogs/mod.rs index 97233e2f6..7fa38cfc1 100644 --- a/necsim/core/src/cogs/mod.rs +++ b/necsim/core/src/cogs/mod.rs @@ -10,7 +10,10 @@ pub mod speciation_probability; pub use speciation_probability::SpeciationProbability; pub mod rng; -pub use rng::{HabitatPrimeableRng, PrimeableRng, RngCore, RngSampler, SeedableRng, SplittableRng}; +pub use rng::{ + Distribution, DistributionSampler, HabitatPrimeableRng, PrimeableRng, Rng, RngCore, + SeedableRng, SplittableRng, +}; pub mod dispersal_sampler; pub use dispersal_sampler::{DispersalSampler, SeparableDispersalSampler}; diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index f08ae55c1..616853c26 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -1,11 +1,12 @@ use core::{ convert::AsMut, default::Default, + marker::PhantomData, num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, ptr::copy_nonoverlapping, }; -use serde::{de::DeserializeOwned, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; use necsim_core_bond::{ ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64, PositiveF64, @@ -17,7 +18,7 @@ use crate::{ }; #[allow(clippy::module_name_repetitions)] -pub trait RngCore: +pub trait RngCore: crate::cogs::Backup + Sized + Clone + core::fmt::Debug + Serialize + DeserializeOwned { type Seed: AsMut<[u8]> + Default + Sized; @@ -30,7 +31,7 @@ pub trait RngCore: } #[allow(clippy::module_name_repetitions)] -pub trait SeedableRng: RngCore { +pub trait SeedableRng: RngCore { #[must_use] fn seed_from_u64(mut state: u64) -> Self { // Implementation from: @@ -64,9 +65,278 @@ pub trait SeedableRng: RngCore { } } -impl> SeedableRng for R {} +impl SeedableRng for R {} -#[allow(clippy::inline_always, clippy::inline_fn_without_body)] +#[allow(clippy::module_name_repetitions)] +pub trait PrimeableRng: RngCore { + fn prime_with(&mut self, location_index: u64, time_index: u64); +} + +#[allow(clippy::module_name_repetitions)] +pub trait HabitatPrimeableRng>: PrimeableRng { + #[inline] + fn prime_with_habitat( + &mut self, + habitat: &H, + indexed_location: &IndexedLocation, + time_index: u64, + ) { + self.prime_with( + habitat.map_indexed_location_to_u64_injective(indexed_location), + time_index, + ); + } +} + +impl, R: PrimeableRng> HabitatPrimeableRng for R {} + +#[allow(clippy::module_name_repetitions)] +pub trait SplittableRng: RngCore { + #[must_use] + fn split(self) -> (Self, Self); + + #[must_use] + fn split_to_stream(self, stream: u64) -> Self; +} + +pub trait Distribution { + type Parameters; + type Sample; +} + +pub trait Rng: RngCore { + type Generator: RngCore; + type Sampler; + + #[must_use] + fn generator(&mut self) -> &mut Self::Generator; + + #[must_use] + fn sample_with(&mut self, params: D::Parameters) -> D::Sample + where + Self::Sampler: DistributionSampler; + + #[must_use] + fn sample>(&mut self) -> D::Sample + where + Self::Sampler: DistributionSampler, + { + self.sample_with(()) + } +} + +#[allow(clippy::module_name_repetitions)] +pub trait DistributionSampler { + type ConcreteSampler: DistributionSampler; + + #[must_use] + fn concrete(&self) -> &Self::ConcreteSampler; + + #[must_use] + fn sample_with(&self, rng: &mut R, samplers: &S, params: D::Parameters) -> D::Sample; + + #[must_use] + fn sample(&self, rng: &mut R, samplers: &S) -> D::Sample + where + D: Distribution, + { + self.sample_with(rng, samplers, ()) + } +} + +pub enum UniformClosedOpenUnit {} + +impl Distribution for UniformClosedOpenUnit { + type Parameters = (); + type Sample = ClosedOpenUnitF64; +} + +pub enum UniformOpenClosedUnit {} + +impl Distribution for UniformOpenClosedUnit { + type Parameters = (); + type Sample = OpenClosedUnitF64; +} + +pub enum IndexUsize {} + +pub struct Length(pub T); + +impl Distribution for IndexUsize { + type Parameters = Length; + type Sample = usize; +} + +pub enum IndexU32 {} + +impl Distribution for IndexU32 { + type Parameters = Length; + type Sample = u32; +} + +pub enum IndexU64 {} + +impl Distribution for IndexU64 { + type Parameters = Length; + type Sample = u64; +} + +pub enum IndexU128 {} + +impl Distribution for IndexU128 { + type Parameters = Length; + type Sample = u128; +} + +pub enum Exponential {} + +pub struct Lambda(pub PositiveF64); + +impl Distribution for Exponential { + type Parameters = Lambda; + type Sample = NonNegativeF64; +} + +pub enum Event {} + +impl Distribution for Event { + type Parameters = ClosedUnitF64; + type Sample = bool; +} + +pub enum StandardNormal2D {} + +impl Distribution for StandardNormal2D { + type Parameters = (); + type Sample = (f64, f64); +} + +pub enum Normal2D {} + +pub struct Normal { + pub mu: f64, + pub sigma: NonNegativeF64, +} + +impl Distribution for Normal2D { + type Parameters = Normal; + type Sample = (f64, f64); +} + +#[derive(Clone, Debug)] +#[allow(clippy::module_name_repetitions)] +pub struct SimpleRng { + inner: R, + _marker: PhantomData, +} + +impl Serialize for SimpleRng { + fn serialize(&self, serializer: S) -> Result { + self.inner.serialize(serializer) + } +} + +impl<'de, M: MathsCore, R: RngCore> Deserialize<'de> for SimpleRng { + fn deserialize>(deserializer: D) -> Result { + let inner = R::deserialize(deserializer)?; + + Ok(Self { + inner, + _marker: PhantomData::, + }) + } +} + +#[contract_trait] +impl crate::cogs::Backup for SimpleRng { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: self.inner.backup_unchecked(), + _marker: PhantomData::, + } + } +} + +impl RngCore for SimpleRng { + type Seed = R::Seed; + + #[must_use] + fn from_seed(seed: Self::Seed) -> Self { + Self { + inner: R::from_seed(seed), + _marker: PhantomData::, + } + } + + #[must_use] + fn sample_u64(&mut self) -> u64 { + self.inner.sample_u64() + } +} + +impl Rng for SimpleRng { + type Generator = R; + type Sampler = SimplerDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + &mut self.inner + } + + fn sample_with(&mut self, params: D::Parameters) -> D::Sample + where + Self::Sampler: DistributionSampler, + { + let samplers = SimplerDistributionSamplers { + _marker: PhantomData::<(M, R)>, + }; + + samplers.sample_with(&mut self.inner, &samplers, params) + } +} + +#[allow(clippy::module_name_repetitions)] +pub struct SimplerDistributionSamplers { + _marker: PhantomData<(M, R)>, +} + +impl DistributionSampler + for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = + (((rng.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } +} + +/*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[allow(clippy::module_name_repetitions)] #[contract_trait] pub trait RngSampler: RngCore { @@ -242,36 +512,4 @@ pub trait RngSampler: RngCore { } } -impl> RngSampler for R {} - -#[allow(clippy::module_name_repetitions)] -pub trait PrimeableRng: RngCore { - fn prime_with(&mut self, location_index: u64, time_index: u64); -} - -#[allow(clippy::module_name_repetitions)] -pub trait HabitatPrimeableRng>: PrimeableRng { - #[inline] - fn prime_with_habitat( - &mut self, - habitat: &H, - indexed_location: &IndexedLocation, - time_index: u64, - ) { - self.prime_with( - habitat.map_indexed_location_to_u64_injective(indexed_location), - time_index, - ); - } -} - -impl, H: Habitat> HabitatPrimeableRng for R {} - -#[allow(clippy::module_name_repetitions)] -pub trait SplittableRng: RngCore { - #[must_use] - fn split(self) -> (Self, Self); - - #[must_use] - fn split_to_stream(self, stream: u64) -> Self; -} +impl> RngSampler for R {}*/ diff --git a/necsim/core/src/simulation/backup.rs b/necsim/core/src/simulation/backup.rs index 455d78e27..1ec3bf0ad 100644 --- a/necsim/core/src/simulation/backup.rs +++ b/necsim/core/src/simulation/backup.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use crate::cogs::{ backup::BackedUp, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, - EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, + EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }; @@ -12,7 +12,7 @@ use super::Simulation; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -46,7 +46,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/builder.rs b/necsim/core/src/simulation/builder.rs index c73c112cb..4c8111f89 100644 --- a/necsim/core/src/simulation/builder.rs +++ b/necsim/core/src/simulation/builder.rs @@ -2,8 +2,7 @@ use core::{marker::PhantomData, num::Wrapping}; use crate::cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability, - TurnoverRate, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }; #[derive(Debug)] @@ -11,7 +10,7 @@ use crate::cogs::{ pub struct SimulationBuilder< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -39,7 +38,7 @@ pub struct SimulationBuilder< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -92,7 +91,7 @@ impl< pub struct Simulation< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -132,7 +131,7 @@ pub struct Simulation< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/mod.rs b/necsim/core/src/simulation/mod.rs index c5356f1a2..f5318eea3 100644 --- a/necsim/core/src/simulation/mod.rs +++ b/necsim/core/src/simulation/mod.rs @@ -11,7 +11,7 @@ use core::num::Wrapping; use crate::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::TieBreaker, @@ -25,7 +25,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/partial/active_lineage_sampler.rs b/necsim/core/src/simulation/partial/active_lineage_sampler.rs index 846d0be89..36e5cc67f 100644 --- a/necsim/core/src/simulation/partial/active_lineage_sampler.rs +++ b/necsim/core/src/simulation/partial/active_lineage_sampler.rs @@ -2,14 +2,14 @@ use core::marker::PhantomData; use crate::cogs::{ CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore, - MathsCore, RngCore, SpeciationProbability, TurnoverRate, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }; #[repr(C)] pub struct PartialSimulation< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -34,7 +34,7 @@ pub struct PartialSimulation< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/partial/emigration_exit.rs b/necsim/core/src/simulation/partial/emigration_exit.rs index ebac274f8..968e24f82 100644 --- a/necsim/core/src/simulation/partial/emigration_exit.rs +++ b/necsim/core/src/simulation/partial/emigration_exit.rs @@ -1,9 +1,9 @@ use core::marker::PhantomData; -use crate::cogs::{Habitat, LineageStore, MathsCore, RngCore}; +use crate::cogs::{Habitat, LineageStore, MathsCore, Rng}; #[repr(C)] -pub struct PartialSimulation, G: RngCore, S: LineageStore> { +pub struct PartialSimulation, G: Rng, S: LineageStore> { pub maths: PhantomData, pub habitat: H, pub lineage_store: S, diff --git a/necsim/core/src/simulation/partial/event_sampler.rs b/necsim/core/src/simulation/partial/event_sampler.rs index 8e56b884f..2cd68c655 100644 --- a/necsim/core/src/simulation/partial/event_sampler.rs +++ b/necsim/core/src/simulation/partial/event_sampler.rs @@ -1,15 +1,15 @@ use core::marker::PhantomData; use crate::cogs::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, - RngCore, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }; #[repr(C)] pub struct PartialSimulation< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -32,7 +32,7 @@ pub struct PartialSimulation< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/process/immigration.rs b/necsim/core/src/simulation/process/immigration.rs index aa1c49b3c..64e7eeccb 100644 --- a/necsim/core/src/simulation/process/immigration.rs +++ b/necsim/core/src/simulation/process/immigration.rs @@ -3,7 +3,7 @@ use core::num::Wrapping; use crate::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, event::DispersalEvent, @@ -15,7 +15,7 @@ use crate::{ impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/core/src/simulation/process/local.rs b/necsim/core/src/simulation/process/local.rs index 2aad2fb89..01a681ffb 100644 --- a/necsim/core/src/simulation/process/local.rs +++ b/necsim/core/src/simulation/process/local.rs @@ -5,7 +5,7 @@ use necsim_core_bond::PositiveF64; use crate::{ cogs::{ event_sampler::EventHandler, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, - EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, + EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, @@ -17,7 +17,7 @@ use crate::{ impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, From fde14671d54fc7c74c804ac9e16f80514c22bf89 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Tue, 17 May 2022 07:42:29 +0000 Subject: [PATCH 03/21] Some further progress in the exploration --- necsim/core/src/cogs/rng.rs | 100 +++++++++++++ necsim/impls/cuda/src/cogs/rng.rs | 37 +++-- necsim/impls/no-std/src/alias/mod.rs | 35 ++--- necsim/impls/no-std/src/alias/packed.rs | 33 ++--- .../alias/individual/mod.rs | 24 ++- .../alias/individual/sampler.rs | 15 +- .../alias/location/mod.rs | 28 +++- .../alias/location/sampler.rs | 23 +-- .../alias/sampler/indexed/mod.rs | 33 +++-- .../alias/sampler/indexed/tests.rs | 140 ++++++++++++++++-- .../alias/sampler/stack/mod.rs | 8 +- .../alias/sampler/stack/tests.rs | 2 +- .../active_lineage_sampler/classical/mod.rs | 8 +- .../classical/sampler.rs | 6 +- .../independent/event_time_sampler/const.rs | 18 ++- .../independent/event_time_sampler/exp.rs | 21 ++- .../independent/event_time_sampler/fixed.rs | 7 +- .../event_time_sampler/geometric.rs | 7 +- .../independent/event_time_sampler/mod.rs | 10 +- .../independent/event_time_sampler/poisson.rs | 4 +- .../active_lineage_sampler/independent/mod.rs | 8 +- .../independent/sampler.rs | 4 +- .../independent/singular.rs | 4 +- .../active_lineage_sampler/resuming/mod.rs | 8 +- .../resuming/sampler.rs | 6 +- .../cogs/active_lineage_sampler/singular.rs | 6 +- .../almost_infinite_normal.rs | 14 +- .../in_memory/alias/dispersal.rs | 4 +- .../dispersal_sampler/in_memory/alias/mod.rs | 8 +- .../in_memory/cumulative/dispersal.rs | 6 +- .../in_memory/cumulative/mod.rs | 4 +- .../cogs/dispersal_sampler/in_memory/mod.rs | 4 +- .../in_memory/packed_alias/dispersal.rs | 4 +- .../in_memory/packed_alias/mod.rs | 10 +- .../in_memory/separable_alias/dispersal.rs | 8 +- .../in_memory/separable_alias/mod.rs | 8 +- .../src/cogs/dispersal_sampler/non_spatial.rs | 16 +- .../dispersal_sampler/spatially_implicit.rs | 16 +- .../cogs/dispersal_sampler/trespassing/mod.rs | 14 +- .../dispersal_sampler/trespassing/uniform.rs | 10 +- .../cogs/dispersal_sampler/wrapping_noise.rs | 12 +- .../no-std/src/cogs/emigration_exit/domain.rs | 4 +- .../cogs/emigration_exit/independent/mod.rs | 12 +- .../no-std/src/cogs/emigration_exit/never.rs | 10 +- .../gillespie/conditional/mod.rs | 12 +- .../gillespie/conditional/probability.rs | 6 +- .../src/cogs/event_sampler/gillespie/mod.rs | 6 +- .../event_sampler/gillespie/unconditional.rs | 16 +- .../src/cogs/event_sampler/independent.rs | 14 +- .../no-std/src/cogs/event_sampler/tracking.rs | 6 +- .../src/cogs/event_sampler/unconditional.rs | 13 +- .../src/cogs/habitat/almost_infinite.rs | 4 +- .../no-std/src/cogs/habitat/in_memory.rs | 6 +- .../no-std/src/cogs/habitat/non_spatial.rs | 6 +- .../src/cogs/habitat/spatially_implicit.rs | 4 +- .../src/cogs/habitat/wrapping_noise/mod.rs | 8 +- necsim/impls/no-std/src/cogs/rng/rand.rs | 59 +++----- necsim/impls/no-std/src/cogs/rng/seahash.rs | 16 +- necsim/impls/no-std/src/cogs/rng/wyhash.rs | 21 +-- necsim/impls/no-std/src/lib.rs | 1 + .../independent/individuals.rs | 5 +- .../parallelisation/independent/landscape.rs | 5 +- .../independent/monolithic/mod.rs | 5 +- .../parallelisation/monolithic/averaging.rs | 5 +- .../parallelisation/monolithic/lockstep.rs | 5 +- .../parallelisation/monolithic/monolithic.rs | 5 +- .../parallelisation/monolithic/optimistic.rs | 4 +- .../monolithic/optimistic_lockstep.rs | 5 +- 68 files changed, 613 insertions(+), 383 deletions(-) diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index 616853c26..3a0130ea9 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -336,6 +336,106 @@ impl DistributionSampler> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> usize { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as usize; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u32 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let index = M::floor(u01.get() * f64::from(length.get())) as u32; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as u64; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as u128; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + /*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[allow(clippy::module_name_repetitions)] #[contract_trait] diff --git a/necsim/impls/cuda/src/cogs/rng.rs b/necsim/impls/cuda/src/cogs/rng.rs index 63073c126..af411f60e 100644 --- a/necsim/impls/cuda/src/cogs/rng.rs +++ b/necsim/impls/cuda/src/cogs/rng.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use necsim_core::cogs::{MathsCore, PrimeableRng, RngCore}; +use necsim_core::cogs::{Distribution, DistributionSampler, MathsCore, Rng, RngCore}; use const_type_layout::TypeGraphLayout; use rust_cuda::safety::StackOnly; @@ -12,13 +12,13 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cuda(free = "M", free = "R")] pub struct CudaRng where - R: RngCore + StackOnly + ~const TypeGraphLayout, + R: Rng + StackOnly + ~const TypeGraphLayout, { inner: R, marker: PhantomData, } -impl + StackOnly + ~const TypeGraphLayout> Clone for CudaRng { +impl + StackOnly + ~const TypeGraphLayout> Clone for CudaRng { fn clone(&self) -> Self { Self { inner: self.inner.clone(), @@ -27,7 +27,7 @@ impl + StackOnly + ~const TypeGraphLayout> Clone for } } -impl + StackOnly + ~const TypeGraphLayout> From for CudaRng { +impl + StackOnly + ~const TypeGraphLayout> From for CudaRng { #[must_use] #[inline] fn from(rng: R) -> Self { @@ -38,10 +38,10 @@ impl + StackOnly + ~const TypeGraphLayout> From f } } -impl + StackOnly + ~const TypeGraphLayout> RngCore +impl + StackOnly + ~const TypeGraphLayout> RngCore for CudaRng { - type Seed = >::Seed; + type Seed = ::Seed; #[must_use] #[inline] @@ -59,24 +59,29 @@ impl + StackOnly + ~const TypeGraphLayout> RngCore + StackOnly + ~const TypeGraphLayout> PrimeableRng - for CudaRng -{ - #[inline] - fn prime_with(&mut self, location_index: u64, time_index: u64) { - self.inner.prime_with(location_index, time_index); +impl + StackOnly + ~const TypeGraphLayout> Rng for CudaRng { + type Generator = R::Generator; + type Sampler = R::Sampler; + + fn generator(&mut self) -> &mut Self::Generator { + self.inner.generator() + } + + fn sample_with(&mut self, params: D::Parameters) -> D::Sample + where + Self::Sampler: DistributionSampler, + { + self.inner.sample_with(params) } } -impl + StackOnly + ~const TypeGraphLayout> Serialize for CudaRng { +impl + StackOnly + ~const TypeGraphLayout> Serialize for CudaRng { fn serialize(&self, serializer: S) -> Result { self.inner.serialize(serializer) } } -impl<'de, M: MathsCore, R: RngCore + StackOnly + ~const TypeGraphLayout> Deserialize<'de> - for CudaRng -{ +impl<'de, M: MathsCore, R: Rng + StackOnly + ~const TypeGraphLayout> Deserialize<'de> for CudaRng { fn deserialize>(deserializer: D) -> Result { let inner = R::deserialize(deserializer)?; diff --git a/necsim/impls/no-std/src/alias/mod.rs b/necsim/impls/no-std/src/alias/mod.rs index 2eec4ef53..f916d83d8 100644 --- a/necsim/impls/no-std/src/alias/mod.rs +++ b/necsim/impls/no-std/src/alias/mod.rs @@ -1,6 +1,11 @@ +use core::num::NonZeroUsize; + use alloc::vec::Vec; -use necsim_core::cogs::{MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::{Event, IndexUsize, Length}, + DistributionSampler, MathsCore, Rng, +}; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; pub mod packed; @@ -89,22 +94,18 @@ impl AliasMethodSampler { } #[debug_ensures(self.Es.contains(&ret), "returns one of the weighted events")] - pub fn sample_event>(&self, rng: &mut G) -> E { - use necsim_core::cogs::RngSampler; - - let x = rng.sample_uniform_closed_open(); - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let i = M::floor(x.get() * (self.Es.len() as f64)) as usize; // index into events - - #[allow(clippy::cast_precision_loss)] - let y = x.get() * (self.Es.len() as f64) - (i as f64); // U(0,1) to compare against U[i] - - if y < self.Us[i].get() { + pub fn sample_event>(&self, rng: &mut G) -> E + where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + { + // Safety: Es is non-empty by the precondition on construction + let length = unsafe { NonZeroUsize::new_unchecked(self.Es.len()) }; + + let i = rng.sample_with::(Length(length)); // index into events + + // Select Es[i] over Ks[i] according to its bucket percentage Us[i] + if rng.sample_with::(self.Us[i]) { self.Es[i] } else { self.Ks[i] diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index fcce6f9af..bca820be3 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -1,8 +1,11 @@ -use core::cmp::Ordering; +use core::{cmp::Ordering, num::NonZeroUsize}; use alloc::vec::Vec; -use necsim_core::cogs::{MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::{Event, IndexUsize, Length}, + DistributionSampler, MathsCore, Rng, +}; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; #[allow(clippy::module_name_repetitions)] @@ -108,27 +111,23 @@ impl AliasMethodSamplerAtom { old(alias_samplers).iter().map(|s| s.e).any(|e| e == ret), "returns one of the weighted events" )] - pub fn sample_event>( + pub fn sample_event>( alias_samplers: &[AliasMethodSamplerAtom], rng: &mut G, - ) -> E { - use necsim_core::cogs::RngSampler; + ) -> E + where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + { + // Safety: alias_samplers is non-empty by the precondition + let length = unsafe { NonZeroUsize::new_unchecked(alias_samplers.len()) }; - let x = rng.sample_uniform_closed_open(); - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let i = M::floor(x.get() * (alias_samplers.len() as f64)) as usize; // index into events - - #[allow(clippy::cast_precision_loss)] - let y = x.get() * (alias_samplers.len() as f64) - (i as f64); // U(0,1) to compare against U[i] + let i = rng.sample_with::(Length(length)); // index into events let sample = &alias_samplers[i]; - if y < sample.u.get() { + // Select E over K according to its bucket percentage U + if rng.sample_with::(sample.u) { sample.e } else { sample.k diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index 94049419d..f128a9fc8 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -4,9 +4,9 @@ use core::{fmt, marker::PhantomData}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::cogs::{ - Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, - TurnoverRate, + rng::Exponential, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, + EmigrationExit, EventSampler, Habitat, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }; use crate::cogs::{ @@ -22,7 +22,7 @@ mod sampler; pub struct IndividualAliasActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -31,7 +31,9 @@ pub struct IndividualAliasActiveLineageSampler< N: SpeciationProbability, E: EventSampler, I: ImmigrationEntry, -> { +> where + G::Sampler: DistributionSampler, +{ alias_sampler: DynamicAliasMethodStackSampler, number_active_lineages: usize, last_event_time: NonNegativeF64, @@ -42,7 +44,7 @@ pub struct IndividualAliasActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -52,6 +54,8 @@ impl< E: EventSampler, I: ImmigrationEntry, > IndividualAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -149,7 +153,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -159,6 +163,8 @@ impl< E: EventSampler, I: ImmigrationEntry, > fmt::Debug for IndividualAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("IndividualAliasActiveLineageSampler") @@ -172,7 +178,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -182,6 +188,8 @@ impl< E: EventSampler, I: ImmigrationEntry, > Backup for IndividualAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index fc5440e6e..b0130ead7 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -2,9 +2,10 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore, - SpeciationProbability, TurnoverRate, + rng::{Exponential, Lambda}, + ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, + EmigrationExit, EventSampler, Habitat, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -18,7 +19,7 @@ use super::IndividualAliasActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -29,6 +30,8 @@ impl< I: ImmigrationEntry, > ActiveLineageSampler for IndividualAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; @@ -60,12 +63,10 @@ impl< rng: &mut G, early_peek_stop: F, ) -> Option<(Lineage, PositiveF64)> { - use necsim_core::cogs::RngSampler; - let total_rate = self.alias_sampler.total_weight(); if let Ok(lambda) = PositiveF64::new(total_rate.get()) { - let event_time = self.last_event_time + rng.sample_exponential(lambda); + let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index b8c4e29fc..206db19e6 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -5,8 +5,10 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, GloballyCoherentLineageStore, - Habitat, ImmigrationEntry, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + rng::{Exponential, IndexUsize}, + Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, + GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, landscape::Location, }; @@ -25,7 +27,7 @@ mod sampler; pub struct LocationAliasActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -34,7 +36,10 @@ pub struct LocationAliasActiveLineageSampler< N: SpeciationProbability, E: GillespieEventSampler, I: ImmigrationEntry, -> { +> where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ alias_sampler: DynamicAliasMethodIndexedSampler, number_active_lineages: usize, last_event_time: NonNegativeF64, @@ -45,7 +50,7 @@ pub struct LocationAliasActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -55,6 +60,9 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > LocationAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -199,7 +207,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -209,6 +217,9 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > core::fmt::Debug for LocationAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("LocationAliasActiveLineageSampler") @@ -222,7 +233,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -232,6 +243,9 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > Backup for LocationAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index 0ccbe5a34..cdf70e474 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -2,9 +2,10 @@ use core::{num::NonZeroUsize, ops::ControlFlow}; use necsim_core::{ cogs::{ - ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, - GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, RngCore, - SpeciationProbability, TurnoverRate, + rng::{Exponential, IndexUsize, Lambda, Length}, + ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, + EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -20,7 +21,7 @@ use super::LocationAliasActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -31,6 +32,9 @@ impl< I: ImmigrationEntry, > ActiveLineageSampler for LocationAliasActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; @@ -67,12 +71,10 @@ impl< rng: &mut G, early_peek_stop: F, ) -> Option<(Lineage, PositiveF64)> { - use necsim_core::cogs::RngSampler; - let total_rate = self.alias_sampler.total_weight(); if let Ok(lambda) = PositiveF64::new(total_rate.get()) { - let event_time = self.last_event_time + rng.sample_exponential(lambda); + let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); @@ -95,10 +97,11 @@ impl< // Safety: `lineages_at_location` must be >0 since // `chosen_active_location` can only be selected in that case - let chosen_lineage_index_at_location = rng - .sample_index(unsafe { NonZeroUsize::new_unchecked(lineages_at_location.len()) }); + let chosen_lineage_index_at_location = rng.sample_with::(Length(unsafe { + NonZeroUsize::new_unchecked(lineages_at_location.len()) + })); // Safety: reference clone is only used to then remove the lineage, which is - // owned + // owned let chosen_lineage_reference = unsafe { lineages_at_location[chosen_lineage_index_at_location].backup_unchecked() }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index df51351c9..3eacfaafc 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -10,7 +10,10 @@ use core::{ use fnv::FnvBuildHasher; use hashbrown::HashMap; -use necsim_core::cogs::{Backup, MathsCore, RngCore, RngSampler}; +use necsim_core::cogs::{ + rng::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, MathsCore, Rng, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; #[cfg(test)] @@ -46,11 +49,14 @@ impl RejectionSamplingGroup { self.events.iter() } - unsafe fn sample_pop_inplace>( + unsafe fn sample_pop_inplace>( &mut self, lookup: &mut HashMap, rng: &mut G, - ) -> (Option<&mut Self>, E) { + ) -> (Option<&mut Self>, E) + where + G::Sampler: DistributionSampler, + { if let [event] = &self.events[..] { lookup.remove(event); @@ -60,7 +66,8 @@ impl RejectionSamplingGroup { loop { // Safety: By construction, the group never contains zero elements - let index = rng.sample_index(NonZeroUsize::new_unchecked(self.weights.len())); + let index = rng + .sample_with::(Length(NonZeroUsize::new_unchecked(self.weights.len()))); let height = rng.sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% @@ -85,11 +92,14 @@ impl RejectionSamplingGroup { } #[cfg(test)] - fn sample_pop>( + fn sample_pop>( mut self, lookup: &mut HashMap, rng: &mut G, - ) -> (Option, E) { + ) -> (Option, E) + where + G::Sampler: DistributionSampler, + { match unsafe { self.sample_pop_inplace(lookup, rng) } { (Some(_), event) => (Some(self), event), (None, event) => (None, event), @@ -187,14 +197,19 @@ impl DynamicAliasMethodIndexedSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } - pub fn sample_pop>(&mut self, rng: &mut G) -> Option { + pub fn sample_pop>(&mut self, rng: &mut G) -> Option + where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { - u128::from(rng.sample_index_u64(total_weight)) + u128::from(rng.sample_with::(Length(total_weight))) } else { - rng.sample_index_u128(total_weight) + rng.sample_with::(Length(total_weight)) }; let mut cdf_acc = 0_u128; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 5f8310137..94ecebc74 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1,9 +1,14 @@ use alloc::{vec, vec::Vec}; +use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; use hashbrown::HashMap; -use necsim_core::cogs::{Backup, RngCore, SeedableRng}; +use necsim_core::cogs::{ + rng::{IndexU128, IndexU64, IndexUsize, Length, SimpleRng}, + Backup, Distribution, DistributionSampler, Rng, RngCore, SeedableRng, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; +use necsim_core_maths::MathsCore; use crate::cogs::{maths::intrinsics::IntrinsicsMathsCore, rng::wyhash::WyHash}; @@ -183,7 +188,7 @@ fn sample_single_group() { let mut tally = [0_u64; 6]; - let mut rng = WyHash::::seed_from_u64(24897); + let mut rng = SimpleRng::::seed_from_u64(24897); for _ in 0..N { let (maybe_group, sample) = group.sample_pop(&mut lookup, &mut rng); @@ -898,7 +903,7 @@ fn add_update_event_full() { fn sample_single_group_full() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(471_093); + let mut rng = SimpleRng::::seed_from_u64(471_093); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -947,7 +952,7 @@ fn sample_single_group_full() { fn sample_three_groups_full() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(739_139); + let mut rng = SimpleRng::::seed_from_u64(739_139); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -993,7 +998,7 @@ fn sample_three_groups_full() { fn sample_three_groups_full_reverse() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(248_971); + let mut rng = SimpleRng::::seed_from_u64(248_971); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -1072,22 +1077,21 @@ fn debug_display_sampler() { // GRCOV_EXCL_START #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -struct DummyRng(Vec); +struct DummyRng(Vec); impl DummyRng { fn new(mut vec: Vec) -> Self { vec.reverse(); - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - Self( - vec.into_iter() - .map(|u01| ((u01 / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11) - .collect(), - ) + Self(vec) + } + + fn sample_f64(&mut self) -> f64 { + self.0.pop().unwrap() } } -impl RngCore for DummyRng { +impl RngCore for DummyRng { type Seed = [u8; 0]; #[must_use] @@ -1097,7 +1101,115 @@ impl RngCore for DummyRng { #[must_use] fn sample_u64(&mut self) -> u64 { - self.0.pop().unwrap() + // #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + } +} + +impl Rng for DummyRng { + type Generator = Self; + type Sampler = DummyDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + self + } + + fn sample_with(&mut self, params: D::Parameters) -> D::Sample + where + Self::Sampler: DistributionSampler, + { + let samplers = DummyDistributionSamplers; + + samplers.sample_with(self, &samplers, params) + } +} + +struct DummyDistributionSamplers; + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> usize { + let length = params.0; + + /*#[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )]*/ + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as usize; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> u64 { + let length = params.0; + + /*#[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )]*/ + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u64; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> u128 { + let length = params.0; + + /*#[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )]*/ + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u128; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) } } // GRCOV_EXCL_STOP diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 237653a8f..48c4e3f23 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -7,7 +7,7 @@ use core::{ num::{NonZeroU128, NonZeroU64, NonZeroUsize}, }; -use necsim_core::cogs::{Backup, MathsCore, RngCore, RngSampler}; +use necsim_core::cogs::{Backup, MathsCore, Rng, RngCore}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; #[cfg(test)] @@ -42,7 +42,7 @@ impl RejectionSamplingGroup { self.events.iter() } - unsafe fn sample_pop_inplace>( + unsafe fn sample_pop_inplace>( &mut self, rng: &mut G, ) -> (Option<&mut Self>, E) { @@ -70,7 +70,7 @@ impl RejectionSamplingGroup { } #[cfg(test)] - fn sample_pop>(mut self, rng: &mut G) -> (Option, E) { + fn sample_pop>(mut self, rng: &mut G) -> (Option, E) { match unsafe { self.sample_pop_inplace(rng) } { (Some(_), event) => (Some(self), event), (None, event) => (None, event), @@ -121,7 +121,7 @@ impl DynamicAliasMethodStackSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } - pub fn sample_pop>(&mut self, rng: &mut G) -> Option { + pub fn sample_pop>(&mut self, rng: &mut G) -> Option { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index b2e6739c1..9cc9b547c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -585,7 +585,7 @@ impl DummyRng { } } -impl RngCore for DummyRng { +impl RngCore for DummyRng { type Seed = [u8; 0]; #[must_use] diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index 2bd683d45..b1e89e4f7 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use necsim_core::cogs::{ Backup, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }; use necsim_core_bond::NonNegativeF64; @@ -19,7 +19,7 @@ mod sampler; pub struct ClassicalActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -35,7 +35,7 @@ pub struct ClassicalActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -126,7 +126,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index b8aa51b46..3e1ec7f1a 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -6,7 +6,7 @@ use core::{ use necsim_core::{ cogs::{ ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -25,7 +25,7 @@ use super::ClassicalActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -106,8 +106,6 @@ impl< rng: &mut G, early_peek_stop: F, ) -> Option<(Lineage, PositiveF64)> { - use necsim_core::cogs::RngSampler; - if let Some(number_active_lineages) = NonZeroU64::new(self.number_active_lineages() as u64) { let lambda = simulation.turnover_rate.get_uniform_turnover_rate() diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs index b69bc20c0..c8f230dc9 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, MathsCore, PrimeableRng, TurnoverRate}, + cogs::{Habitat, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -21,18 +21,26 @@ impl ConstEventTimeSampler { } #[contract_trait] -impl, G: PrimeableRng, T: TurnoverRate> +impl, G: Rng, T: TurnoverRate> EventTimeSampler for ConstEventTimeSampler { #[inline] fn next_event_time_at_indexed_location_weakly_after( &self, - _indexed_location: &IndexedLocation, + indexed_location: &IndexedLocation, _time: NonNegativeF64, - _habitat: &H, - _rng: &mut G, + habitat: &H, + rng: &mut G, _turnover_rate: &T, ) -> NonNegativeF64 { + // Note: Since the constant event time is not controlled by the RNG, + // feeding it directly into it should not cause a feedback loop + rng.generator().prime_with_habitat( + habitat, + indexed_location, + self.event_time.get().to_bits(), + ); + self.event_time.into() } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index 8b6bdc9c4..73c36935d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, RngSampler, TurnoverRate}, + cogs::{ + rng::{Exponential, Lambda}, + Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate, + }, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -24,7 +27,7 @@ impl ExpEventTimeSampler { } #[contract_trait] -impl, G: PrimeableRng, T: TurnoverRate> +impl, G: Rng, T: TurnoverRate> EventTimeSampler for ExpEventTimeSampler { #[inline] @@ -55,12 +58,13 @@ impl, G: PrimeableRng, T: TurnoverRate> let mut time_slice_end = NonNegativeF64::from(time_step + 1) * self.delta_t; #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - rng.prime_with_habitat(habitat, indexed_location, time_step); + rng.generator() + .prime_with_habitat(habitat, indexed_location, time_step); let mut sub_index: u64 = 0; loop { - event_time += rng.sample_exponential(lambda); + event_time += rng.sample_with::(Lambda(lambda)); sub_index = sub_index.wrapping_add(INV_PHI); @@ -72,13 +76,18 @@ impl, G: PrimeableRng, T: TurnoverRate> event_time = time_slice_end; time_slice_end = NonNegativeF64::from(time_step + 1) * self.delta_t; - rng.prime_with_habitat(habitat, indexed_location, time_step); + rng.generator() + .prime_with_habitat(habitat, indexed_location, time_step); } else if event_time > time { break; } } - rng.prime_with_habitat(habitat, indexed_location, time_step.wrapping_add(sub_index)); + rng.generator().prime_with_habitat( + habitat, + indexed_location, + time_step.wrapping_add(sub_index), + ); event_time } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs index 5685d57fe..386738869 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, TurnoverRate}, + cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::NonNegativeF64; @@ -12,7 +12,7 @@ use super::EventTimeSampler; pub struct FixedEventTimeSampler([u8; 0]); #[contract_trait] -impl, G: PrimeableRng, T: TurnoverRate> +impl, G: Rng, T: TurnoverRate> EventTimeSampler for FixedEventTimeSampler { #[inline] @@ -31,7 +31,8 @@ impl, G: PrimeableRng, T: TurnoverRate> #[allow(clippy::cast_sign_loss)] let time_step = M::floor(time.get() * lambda.get()) as u64 + 1; - rng.prime_with_habitat(habitat, indexed_location, time_step); + rng.generator() + .prime_with_habitat(habitat, indexed_location, time_step); NonNegativeF64::from(time_step) / lambda } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index be31a8a60..3f6c8b0bf 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, RngSampler, TurnoverRate}, + cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -21,7 +21,7 @@ impl GeometricEventTimeSampler { } #[contract_trait] -impl, G: PrimeableRng, T: TurnoverRate> +impl, G: Rng, T: TurnoverRate> EventTimeSampler for GeometricEventTimeSampler { #[inline] @@ -44,7 +44,8 @@ impl, G: PrimeableRng, T: TurnoverRate> let mut time_step = M::floor(time.get() / self.delta_t.get()) as u64 + 1; loop { - rng.prime_with_habitat(habitat, indexed_location, time_step); + rng.generator() + .prime_with_habitat(habitat, indexed_location, time_step); if rng.sample_event(event_probability_per_step) { break; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/mod.rs index 19c8f2e58..d5aaf6bb1 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, MathsCore, PrimeableRng, TurnoverRate}, + cogs::{Habitat, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::NonNegativeF64; @@ -13,8 +13,12 @@ pub mod poisson; #[allow(clippy::module_name_repetitions)] #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait EventTimeSampler, G: PrimeableRng, T: TurnoverRate>: - Clone + core::fmt::Debug +pub trait EventTimeSampler< + M: MathsCore, + H: Habitat, + G: Rng, + T: TurnoverRate, +>: Clone + core::fmt::Debug { #[debug_requires( habitat.get_habitat_at_location(indexed_location.location()) > 0, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index fcd1355ab..381362042 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, RngSampler, TurnoverRate}, + cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -24,7 +24,7 @@ impl PoissonEventTimeSampler { } #[contract_trait] -impl, G: PrimeableRng, T: TurnoverRate> +impl, G: Rng, T: TurnoverRate> EventTimeSampler for PoissonEventTimeSampler { #[inline] diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs index 1aafbee33..ecf692a1d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - Backup, DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, + Backup, DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, @@ -30,7 +30,7 @@ use event_time_sampler::EventTimeSampler; pub struct IndependentActiveLineageSampler< M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -52,7 +52,7 @@ pub struct IndependentActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -138,7 +138,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs index 9625dbe3f..013b1a994 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs @@ -3,7 +3,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, - SpeciationProbability, TurnoverRate, + Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -23,7 +23,7 @@ use super::{EventTimeSampler, IndependentActiveLineageSampler}; impl< M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs index 5a045befb..95f102ee6 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs @@ -1,5 +1,5 @@ use necsim_core::cogs::{ - DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, SpeciationProbability, + DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }; @@ -19,7 +19,7 @@ use super::{EventTimeSampler, IndependentActiveLineageSampler}; impl< M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/mod.rs index 2489c5f62..de2475df0 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/mod.rs @@ -4,7 +4,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, - EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, + EventSampler, Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, @@ -19,7 +19,7 @@ pub mod lineage; pub struct RestartFixUpActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -40,7 +40,7 @@ pub struct RestartFixUpActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, @@ -71,7 +71,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs index 4520f67e6..65d718f77 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability, - TurnoverRate, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -16,7 +16,7 @@ use super::RestartFixUpActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs index f595c9808..fd0526d4d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, RngCore, SpeciationProbability, - TurnoverRate, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, lineage::Lineage, }; @@ -11,7 +11,7 @@ use necsim_core::{ pub trait SingularActiveLineageSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index 7b71b472b..8100b5656 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use necsim_core::{ - cogs::{Backup, DispersalSampler, MathsCore, RngCore, SeparableDispersalSampler}, + cogs::{Backup, DispersalSampler, MathsCore, Rng, SeparableDispersalSampler}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -12,13 +12,13 @@ use crate::cogs::habitat::almost_infinite::AlmostInfiniteHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct AlmostInfiniteNormalDispersalSampler> { +pub struct AlmostInfiniteNormalDispersalSampler> { sigma: NonNegativeF64, self_dispersal: ClosedUnitF64, marker: PhantomData<(M, G)>, } -impl> AlmostInfiniteNormalDispersalSampler { +impl> AlmostInfiniteNormalDispersalSampler { #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { let self_dispersal_1d = if sigma > 0.0_f64 { @@ -40,7 +40,7 @@ impl> AlmostInfiniteNormalDispersalSampler { } #[contract_trait] -impl> Backup for AlmostInfiniteNormalDispersalSampler { +impl> Backup for AlmostInfiniteNormalDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { sigma: self.sigma, @@ -51,7 +51,7 @@ impl> Backup for AlmostInfiniteNormalDispersalSample } #[contract_trait] -impl> DispersalSampler, G> +impl> DispersalSampler, G> for AlmostInfiniteNormalDispersalSampler { #[must_use] @@ -61,8 +61,6 @@ impl> DispersalSampler, _habitat: &AlmostInfiniteHabitat, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - const WRAP: i64 = 1 << 32; let (dx, dy): (f64, f64) = rng.sample_2d_normal(0.0_f64, self.sigma); @@ -85,7 +83,7 @@ impl> DispersalSampler, } #[contract_trait] -impl> SeparableDispersalSampler, G> +impl> SeparableDispersalSampler, G> for AlmostInfiniteNormalDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs index 08730e87a..88827eece 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs @@ -1,12 +1,12 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, RngCore}, + cogs::{DispersalSampler, Habitat, MathsCore, Rng}, landscape::Location, }; use super::InMemoryAliasDispersalSampler; #[contract_trait] -impl, G: RngCore> DispersalSampler +impl, G: Rng> DispersalSampler for InMemoryAliasDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs index e063db091..a4b19842f 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use alloc::vec::Vec; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore}, + cogs::{Backup, Habitat, MathsCore, Rng}, landscape::Location, }; use necsim_core_bond::NonNegativeF64; @@ -17,13 +17,13 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemoryAliasDispersalSampler, G: RngCore> { +pub struct InMemoryAliasDispersalSampler, G: Rng> { alias_dispersal: Array2D>>, marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: RngCore> InMemoryDispersalSampler +impl, G: Rng> InMemoryDispersalSampler for InMemoryAliasDispersalSampler { /// Creates a new `InMemoryAliasDispersalSampler` from the @@ -77,7 +77,7 @@ impl, G: RngCore> InMemoryDispersalSampler, G: RngCore> Backup for InMemoryAliasDispersalSampler { +impl, G: Rng> Backup for InMemoryAliasDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { alias_dispersal: self.alias_dispersal.clone(), diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs index d5495b774..4b34d84c9 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs @@ -1,12 +1,12 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, RngCore}, + cogs::{DispersalSampler, Habitat, MathsCore, Rng}, landscape::Location, }; use super::InMemoryCumulativeDispersalSampler; #[contract_trait] -impl, G: RngCore> DispersalSampler +impl, G: Rng> DispersalSampler for InMemoryCumulativeDispersalSampler { #[must_use] @@ -16,8 +16,6 @@ impl, G: RngCore> DispersalSampler habitat: &H, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - let location_index = (location.y().wrapping_sub(habitat.get_extent().y()) as usize) * usize::from(habitat.get_extent().width()) + (location.x().wrapping_sub(habitat.get_extent().x()) as usize); diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs index 956ffd211..fe030a331 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs @@ -1,7 +1,7 @@ use alloc::{boxed::Box, vec}; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore}, + cogs::{Backup, Habitat, MathsCore, Rng}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -19,7 +19,7 @@ pub struct InMemoryCumulativeDispersalSampler { } #[contract_trait] -impl, G: RngCore> InMemoryDispersalSampler +impl, G: Rng> InMemoryDispersalSampler for InMemoryCumulativeDispersalSampler { /// Creates a new `InMemoryCumulativeDispersalSampler` from the diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/mod.rs index e046c4daa..1d32de4a0 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/mod.rs @@ -1,4 +1,4 @@ -use necsim_core::cogs::{DispersalSampler, Habitat, MathsCore, RngCore}; +use necsim_core::cogs::{DispersalSampler, Habitat, MathsCore, Rng}; use crate::array2d::Array2D; @@ -15,7 +15,7 @@ use necsim_core_bond::NonNegativeF64; #[allow(clippy::module_name_repetitions)] #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait InMemoryDispersalSampler, G: RngCore>: +pub trait InMemoryDispersalSampler, G: Rng>: DispersalSampler + Sized { #[debug_requires(( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs index 107405bcd..16722013d 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs @@ -1,7 +1,7 @@ use core::ops::Range; use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, RngCore}, + cogs::{DispersalSampler, Habitat, MathsCore, Rng}, landscape::Location, }; @@ -10,7 +10,7 @@ use crate::alias::packed::AliasMethodSamplerAtom; use super::InMemoryPackedAliasDispersalSampler; #[contract_trait] -impl, G: RngCore> DispersalSampler +impl, G: Rng> DispersalSampler for InMemoryPackedAliasDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs index f3c191fdf..59bc188d3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs @@ -5,7 +5,7 @@ use necsim_core_bond::NonNegativeF64; use r#final::Final; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore}, + cogs::{Backup, Habitat, MathsCore, Rng}, landscape::Location, }; @@ -42,7 +42,7 @@ impl From for Range { #[allow(clippy::module_name_repetitions)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "H", free = "G"))] -pub struct InMemoryPackedAliasDispersalSampler, G: RngCore> { +pub struct InMemoryPackedAliasDispersalSampler, G: Rng> { #[cfg_attr(feature = "cuda", cuda(embed))] alias_dispersal_ranges: Final>, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -51,7 +51,7 @@ pub struct InMemoryPackedAliasDispersalSampler, G: R } #[contract_trait] -impl, G: RngCore> InMemoryDispersalSampler +impl, G: Rng> InMemoryDispersalSampler for InMemoryPackedAliasDispersalSampler { /// Creates a new `InMemoryPackedAliasDispersalSampler` from the @@ -112,7 +112,7 @@ impl, G: RngCore> InMemoryDispersalSampler, G: RngCore> core::fmt::Debug +impl, G: Rng> core::fmt::Debug for InMemoryPackedAliasDispersalSampler { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { @@ -131,7 +131,7 @@ impl, G: RngCore> core::fmt::Debug } #[contract_trait] -impl, G: RngCore> Backup +impl, G: Rng> Backup for InMemoryPackedAliasDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index 84bf3f84c..1c7c37e99 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, RngCore, SeparableDispersalSampler}, + cogs::{DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, landscape::Location, }; use necsim_core_bond::ClosedUnitF64; @@ -7,7 +7,7 @@ use necsim_core_bond::ClosedUnitF64; use super::InMemorySeparableAliasDispersalSampler; #[contract_trait] -impl, G: RngCore> DispersalSampler +impl, G: Rng> DispersalSampler for InMemorySeparableAliasDispersalSampler { #[must_use] @@ -17,8 +17,6 @@ impl, G: RngCore> DispersalSampler habitat: &H, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - let self_dispersal_at_location = self.get_self_dispersal_probability_at_location(location, habitat); @@ -35,7 +33,7 @@ impl, G: RngCore> DispersalSampler } #[contract_trait] -impl, G: RngCore> SeparableDispersalSampler +impl, G: Rng> SeparableDispersalSampler for InMemorySeparableAliasDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs index 57c81986b..70cda163e 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use alloc::vec::Vec; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore}, + cogs::{Backup, Habitat, MathsCore, Rng}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -17,14 +17,14 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemorySeparableAliasDispersalSampler, G: RngCore> { +pub struct InMemorySeparableAliasDispersalSampler, G: Rng> { alias_dispersal: Array2D>>, self_dispersal: Array2D, _marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: RngCore> InMemoryDispersalSampler +impl, G: Rng> InMemoryDispersalSampler for InMemorySeparableAliasDispersalSampler { /// Creates a new `InMemorySeparableAliasDispersalSampler` from the @@ -112,7 +112,7 @@ impl, G: RngCore> InMemoryDispersalSampler, G: RngCore> Backup +impl, G: Rng> Backup for InMemorySeparableAliasDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs index 23fbe2a0e..929521c05 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs @@ -1,7 +1,7 @@ use core::{marker::PhantomData, num::NonZeroU64}; use necsim_core::{ - cogs::{Backup, DispersalSampler, Habitat, MathsCore, RngCore, SeparableDispersalSampler}, + cogs::{Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, landscape::Location, }; use necsim_core_bond::ClosedUnitF64; @@ -12,11 +12,11 @@ use crate::cogs::habitat::non_spatial::NonSpatialHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct NonSpatialDispersalSampler> { +pub struct NonSpatialDispersalSampler> { marker: PhantomData<(M, G)>, } -impl> Default for NonSpatialDispersalSampler { +impl> Default for NonSpatialDispersalSampler { #[must_use] fn default() -> Self { Self { @@ -26,7 +26,7 @@ impl> Default for NonSpatialDispersalSampler { } #[contract_trait] -impl> Backup for NonSpatialDispersalSampler { +impl> Backup for NonSpatialDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { marker: PhantomData::<(M, G)>, @@ -35,7 +35,7 @@ impl> Backup for NonSpatialDispersalSampler { } #[contract_trait] -impl> DispersalSampler, G> +impl> DispersalSampler, G> for NonSpatialDispersalSampler { #[must_use] @@ -46,8 +46,6 @@ impl> DispersalSampler, G> habitat: &NonSpatialHabitat, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - let habitat_index_max = habitat.get_extent().width().get() * habitat.get_extent().height().get(); @@ -70,7 +68,7 @@ impl> DispersalSampler, G> } #[contract_trait] -impl> SeparableDispersalSampler, G> +impl> SeparableDispersalSampler, G> for NonSpatialDispersalSampler { #[must_use] @@ -83,8 +81,6 @@ impl> SeparableDispersalSampler, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - let habitat_index_max = habitat.get_extent().width().get() * habitat.get_extent().height().get(); let current_location_index = diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index 9664e50bb..3451bc9bb 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Backup, DispersalSampler, Habitat, MathsCore, RngCore, SeparableDispersalSampler}, + cogs::{Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, OpenClosedUnitF64 as PositiveUnitF64}; @@ -13,7 +13,7 @@ use crate::cogs::{ #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M"))] -pub struct SpatiallyImplicitDispersalSampler> { +pub struct SpatiallyImplicitDispersalSampler> { #[cfg_attr(feature = "cuda", cuda(embed))] local: NonSpatialDispersalSampler, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -21,7 +21,7 @@ pub struct SpatiallyImplicitDispersalSampler> { local_migration_probability_per_generation: PositiveUnitF64, } -impl> SpatiallyImplicitDispersalSampler { +impl> SpatiallyImplicitDispersalSampler { #[must_use] pub fn new(local_migration_probability_per_generation: PositiveUnitF64) -> Self { Self { @@ -33,7 +33,7 @@ impl> SpatiallyImplicitDispersalSampler { } #[contract_trait] -impl> Backup for SpatiallyImplicitDispersalSampler { +impl> Backup for SpatiallyImplicitDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { local: self.local.backup_unchecked(), @@ -45,7 +45,7 @@ impl> Backup for SpatiallyImplicitDispersalSampler> DispersalSampler, G> +impl> DispersalSampler, G> for SpatiallyImplicitDispersalSampler { #[must_use] @@ -62,8 +62,6 @@ impl> DispersalSampler, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - // By PRE, location must be habitable, i.e. either in the local or the meta // habitat if habitat.local().get_extent().contains(location) { @@ -89,7 +87,7 @@ impl> DispersalSampler> SeparableDispersalSampler, G> +impl> SeparableDispersalSampler, G> for SpatiallyImplicitDispersalSampler { #[must_use] @@ -106,8 +104,6 @@ impl> SeparableDispersalSampler, rng: &mut G, ) -> Location { - use necsim_core::cogs::RngSampler; - // By PRE, location must be habitable, i.e. either in the local or the meta // habitat if habitat.local().get_extent().contains(location) { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/mod.rs index 996dc2684..e91e6e088 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/mod.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use necsim_core::{ - cogs::{Backup, DispersalSampler, Habitat, MathsCore, RngCore, SeparableDispersalSampler}, + cogs::{Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, landscape::Location, }; use necsim_core_bond::ClosedUnitF64; @@ -12,7 +12,7 @@ pub mod uniform; #[allow(clippy::no_effect_underscore_binding)] #[allow(clippy::module_name_repetitions)] #[contract_trait] -pub trait AntiTrespassingDispersalSampler, G: RngCore>: +pub trait AntiTrespassingDispersalSampler, G: Rng>: Backup + core::fmt::Debug { #[must_use] @@ -33,7 +33,7 @@ pub trait AntiTrespassingDispersalSampler, G: RngCor pub struct TrespassingDispersalSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, D: DispersalSampler, T: AntiTrespassingDispersalSampler, > { @@ -47,7 +47,7 @@ pub struct TrespassingDispersalSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, D: DispersalSampler, T: AntiTrespassingDispersalSampler, > TrespassingDispersalSampler @@ -66,7 +66,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, D: DispersalSampler, T: AntiTrespassingDispersalSampler, > Backup for TrespassingDispersalSampler @@ -83,7 +83,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, D: DispersalSampler, T: AntiTrespassingDispersalSampler, > DispersalSampler for TrespassingDispersalSampler @@ -126,7 +126,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, D: SeparableDispersalSampler, T: AntiTrespassingDispersalSampler, > SeparableDispersalSampler for TrespassingDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/uniform.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/uniform.rs index 22e3216d2..6902e935d 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/uniform.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/trespassing/uniform.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use necsim_core::{ - cogs::{Backup, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, MathsCore, Rng, UniformlySampleableHabitat}, landscape::Location, }; @@ -14,12 +14,12 @@ use super::AntiTrespassingDispersalSampler; pub struct UniformAntiTrespassingDispersalSampler< M: MathsCore, H: UniformlySampleableHabitat, - G: RngCore, + G: Rng, > { marker: PhantomData<(M, H, G)>, } -impl, G: RngCore> Default +impl, G: Rng> Default for UniformAntiTrespassingDispersalSampler { #[must_use] @@ -31,7 +31,7 @@ impl, G: RngCore> Default } #[contract_trait] -impl, G: RngCore> Backup +impl, G: Rng> Backup for UniformAntiTrespassingDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { @@ -42,7 +42,7 @@ impl, G: RngCore> Backup } #[contract_trait] -impl, G: RngCore> +impl, G: Rng> AntiTrespassingDispersalSampler for UniformAntiTrespassingDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs index 5f38306db..e423248d3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - Backup, DispersalSampler, Habitat, MathsCore, RngCore, RngSampler, + Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler, }, landscape::Location, @@ -16,12 +16,12 @@ use crate::cogs::{ #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M"))] -pub struct WrappingNoiseApproximateNormalDispersalSampler> { +pub struct WrappingNoiseApproximateNormalDispersalSampler> { #[cfg_attr(feature = "cuda", cuda(embed))] inner: AlmostInfiniteNormalDispersalSampler, } -impl> WrappingNoiseApproximateNormalDispersalSampler { +impl> WrappingNoiseApproximateNormalDispersalSampler { #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { Self { @@ -31,7 +31,7 @@ impl> WrappingNoiseApproximateNormalDispersalSampler } #[contract_trait] -impl> Backup for WrappingNoiseApproximateNormalDispersalSampler { +impl> Backup for WrappingNoiseApproximateNormalDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { inner: self.inner.backup_unchecked(), @@ -40,7 +40,7 @@ impl> Backup for WrappingNoiseApproximateNormalDispe } #[contract_trait] -impl> DispersalSampler, G> +impl> DispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler { #[must_use] @@ -65,7 +65,7 @@ impl> DispersalSampler, G } #[contract_trait] -impl> SeparableDispersalSampler, G> +impl> SeparableDispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs index dca13451b..4fbc4873c 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs @@ -6,7 +6,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, Backup, EmigrationExit, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, + LocallyCoherentLineageStore, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -45,7 +45,7 @@ impl< M: MathsCore, H: Habitat, C: Decomposition, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, > EmigrationExit for DomainEmigrationExit { diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs index 5720aca3a..42a6a868a 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs @@ -2,8 +2,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, Backup, EmigrationExit, Habitat, MathsCore, - RngCore, + coalescence_sampler::CoalescenceRngSample, Backup, EmigrationExit, Habitat, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -52,13 +51,8 @@ impl, C: Decomposition, E: EmigrationChoice, - C: Decomposition, - E: EmigrationChoice, - G: RngCore, - > EmigrationExit> +impl, C: Decomposition, E: EmigrationChoice, G: Rng> + EmigrationExit> for IndependentEmigrationExit { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/never.rs b/necsim/impls/no-std/src/cogs/emigration_exit/never.rs index 74a68fdda..d24934c67 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/never.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/never.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Backup, EmigrationExit, Habitat, LineageStore, MathsCore, RngCore}, + cogs::{Backup, EmigrationExit, Habitat, LineageStore, MathsCore, Rng}, landscape::{IndexedLocation, Location}, lineage::GlobalLineageReference, simulation::partial::emigration_exit::PartialSimulation, @@ -19,8 +19,12 @@ impl Backup for NeverEmigrationExit { } #[contract_trait] -impl, G: RngCore, S: LineageStore> EmigrationExit - for NeverEmigrationExit +impl< + M: MathsCore, + H: Habitat, + G: Rng, + S: LineageStore, + > EmigrationExit for NeverEmigrationExit { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs index 2775ad348..dab070974 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs @@ -4,7 +4,7 @@ use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, CoalescenceSampler, EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, - MathsCore, RngCore, RngSampler, SeparableDispersalSampler, SpeciationProbability, + MathsCore, Rng, SeparableDispersalSampler, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, @@ -28,7 +28,7 @@ use probability::ProbabilityAtLocation; pub struct ConditionalGillespieEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -42,7 +42,7 @@ pub struct ConditionalGillespieEventSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -61,7 +61,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -80,7 +80,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -232,7 +232,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs index 8d7ccaba2..18e191eae 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - GloballyCoherentLineageStore, Habitat, MathsCore, RngCore, SeparableDispersalSampler, - SpeciationProbability, + GloballyCoherentLineageStore, Habitat, MathsCore, Rng, + SeparableDispersalSampler, SpeciationProbability, }, landscape::Location, }; @@ -20,7 +20,7 @@ impl ProbabilityAtLocation { pub fn new< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, D: SeparableDispersalSampler, N: SpeciationProbability, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs index f0c8b72cb..5a79a1626 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore, - MathsCore, RngCore, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, + LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, landscape::Location, }; @@ -16,7 +16,7 @@ pub mod unconditional; pub trait GillespieEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index b1864186d..60f73d73e 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -4,8 +4,8 @@ use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - GloballyCoherentLineageStore, Habitat, MathsCore, RngCore, SpeciationProbability, - TurnoverRate, + GloballyCoherentLineageStore, Habitat, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -21,7 +21,7 @@ use super::GillespieEventSampler; pub struct UnconditionalGillespieEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -36,7 +36,7 @@ pub struct UnconditionalGillespieEventSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -56,7 +56,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -76,7 +76,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -110,8 +110,6 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - use necsim_core::cogs::RngSampler; - if rng.sample_event( simulation .speciation_probability @@ -185,7 +183,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs index baeb01622..b70a5ea73 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs @@ -4,7 +4,7 @@ use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, MathsCore, - RngCore, SpeciationProbability, TurnoverRate, + Rng, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -37,7 +37,7 @@ use super::tracking::{MinSpeciationTrackingEventSampler, SpeciationSample}; pub struct IndependentEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -56,7 +56,7 @@ pub struct IndependentEventSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -75,7 +75,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -94,7 +94,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -147,8 +147,6 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - use necsim_core::cogs::RngSampler; - let speciation_sample = rng.sample_uniform_closed_open(); SpeciationSample::update_min( @@ -230,7 +228,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs b/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs index 8b5c1cccd..5b825f178 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs @@ -4,8 +4,8 @@ use necsim_core_bond::{ClosedOpenUnitF64, PositiveF64}; use necsim_core::{ cogs::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore, - MathsCore, RngCore, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, + LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, landscape::IndexedLocation, }; @@ -13,7 +13,7 @@ use necsim_core::{ pub trait MinSpeciationTrackingEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index b20c476e7..7c97b3423 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -4,7 +4,8 @@ use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -17,7 +18,7 @@ use necsim_core_bond::PositiveF64; pub struct UnconditionalEventSampler< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -32,7 +33,7 @@ pub struct UnconditionalEventSampler< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -52,7 +53,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -72,7 +73,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -106,8 +107,6 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - use necsim_core::cogs::RngSampler; - if rng.sample_event( simulation .speciation_probability diff --git a/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs b/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs index 914672dbc..84c668f9d 100644 --- a/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs +++ b/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs @@ -1,7 +1,7 @@ use core::{fmt, marker::PhantomData}; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -78,7 +78,7 @@ impl Habitat for AlmostInfiniteHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for AlmostInfiniteHabitat { +impl> UniformlySampleableHabitat for AlmostInfiniteHabitat { #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { diff --git a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs index 7ee8a1cd4..f611f629a 100644 --- a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs +++ b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs @@ -5,7 +5,7 @@ use alloc::{boxed::Box, vec::Vec}; use r#final::Final; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -106,12 +106,10 @@ impl Habitat for InMemoryHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for InMemoryHabitat { +impl> UniformlySampleableHabitat for InMemoryHabitat { #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { - use necsim_core::cogs::RngSampler; - let indexed_location_index = rng.sample_index_u64(self.get_total_habitat().into()); let location_index = match self.u64_injection.binary_search(&indexed_location_index) { diff --git a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs index bbba06e66..5a7189ff4 100644 --- a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs @@ -4,7 +4,7 @@ use core::{ }; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -116,12 +116,10 @@ impl Habitat for NonSpatialHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for NonSpatialHabitat { +impl> UniformlySampleableHabitat for NonSpatialHabitat { #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { - use necsim_core::cogs::RngSampler; - let habitat_index_max = self.extent.width().get() * self.extent.height().get() * u64::from(self.deme.get()); diff --git a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs index 5f78012e9..80f7812da 100644 --- a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs @@ -1,7 +1,7 @@ use core::num::NonZeroU32; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -128,7 +128,7 @@ impl Habitat for SpatiallyImplicitHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for SpatiallyImplicitHabitat { +impl> UniformlySampleableHabitat for SpatiallyImplicitHabitat { #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { diff --git a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs index e86345216..3604aa8a7 100644 --- a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs +++ b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs @@ -1,14 +1,16 @@ use alloc::boxed::Box; use core::{fmt, num::NonZeroUsize}; -use necsim_core_bond::{ClosedUnitF64, OffByOneU64, OpenClosedUnitF64 as PositiveUnitF64}; + use r#final::Final; +use necsim_core_bond::{ClosedUnitF64, OffByOneU64, OpenClosedUnitF64 as PositiveUnitF64}; + mod opensimplex_noise; use opensimplex_noise::OpenSimplexNoise; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, RngCore, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -189,7 +191,7 @@ impl Habitat for WrappingNoiseHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for WrappingNoiseHabitat { +impl> UniformlySampleableHabitat for WrappingNoiseHabitat { #[must_use] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { // Rejection sample until a habitable location is found diff --git a/necsim/impls/no-std/src/cogs/rng/rand.rs b/necsim/impls/no-std/src/cogs/rng/rand.rs index 8e979e343..bd09e7755 100644 --- a/necsim/impls/no-std/src/cogs/rng/rand.rs +++ b/necsim/impls/no-std/src/cogs/rng/rand.rs @@ -1,44 +1,34 @@ -use core::{fmt, marker::PhantomData}; +use core::fmt; -use necsim_core::cogs::{Backup, MathsCore, RngCore}; +use necsim_core::cogs::{Backup, RngCore}; use rand_core::{RngCore as RandRngCore, SeedableRng as RandSeedableRng}; use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; #[allow(clippy::module_name_repetitions)] #[derive(Clone, TypeLayout)] -#[layout(free = "M")] #[repr(transparent)] -pub struct RandRng< - M: MathsCore, - G: RandRngCore + RandSeedableRng + Clone + Serialize + DeserializeOwned, -> { +pub struct RandRng { inner: G, - marker: PhantomData, } -impl From - for RandRng +impl From + for RandRng { fn from(inner: G) -> Self { - Self { - inner, - marker: PhantomData::, - } + Self { inner } } } -impl - RandRng -{ +impl RandRng { #[must_use] pub fn into_inner(self) -> G { self.inner } } -impl - fmt::Debug for RandRng +impl fmt::Debug + for RandRng { default fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct InnerRng(&'static str); @@ -55,10 +45,8 @@ impl fmt::Debug for RandRng +impl + fmt::Debug for RandRng { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_tuple("RandRng").field(&self.inner).finish() @@ -66,40 +54,34 @@ impl< } #[contract_trait] -impl Backup - for RandRng +impl Backup + for RandRng { unsafe fn backup_unchecked(&self) -> Self { self.clone() } } -impl - Serialize for RandRng +impl Serialize + for RandRng { fn serialize(&self, serializer: S) -> Result { self.inner.serialize(serializer) } } -impl< - 'de, - M: MathsCore, - G: RandRngCore + RandSeedableRng + Clone + Serialize + DeserializeOwned, - > Deserialize<'de> for RandRng +impl<'de, G: RandRngCore + RandSeedableRng + Clone + Serialize + DeserializeOwned> Deserialize<'de> + for RandRng { fn deserialize>(deserializer: D) -> Result { let inner = G::deserialize(deserializer)?; - Ok(Self { - inner, - marker: PhantomData::, - }) + Ok(Self { inner }) } } -impl - RngCore for RandRng +impl RngCore + for RandRng { type Seed = G::Seed; @@ -108,7 +90,6 @@ impl Self { Self { inner: G::from_seed(seed), - marker: PhantomData::, } } diff --git a/necsim/impls/no-std/src/cogs/rng/seahash.rs b/necsim/impls/no-std/src/cogs/rng/seahash.rs index 93cc87ecd..ea316ce72 100644 --- a/necsim/impls/no-std/src/cogs/rng/seahash.rs +++ b/necsim/impls/no-std/src/cogs/rng/seahash.rs @@ -1,30 +1,25 @@ -use core::marker::PhantomData; - -use necsim_core::cogs::{Backup, MathsCore, PrimeableRng, RngCore}; +use necsim_core::cogs::{Backup, PrimeableRng, RngCore}; use serde::{Deserialize, Serialize}; #[allow(clippy::module_name_repetitions, clippy::unsafe_derive_deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, TypeLayout)] #[serde(deny_unknown_fields)] -#[layout(free = "M")] -pub struct SeaHash { +pub struct SeaHash { seed: u64, location: u64, time: u64, offset: u64, - #[serde(skip)] - marker: PhantomData, } #[contract_trait] -impl Backup for SeaHash { +impl Backup for SeaHash { unsafe fn backup_unchecked(&self) -> Self { self.clone() } } -impl RngCore for SeaHash { +impl RngCore for SeaHash { type Seed = [u8; 8]; #[must_use] @@ -37,7 +32,6 @@ impl RngCore for SeaHash { location: 0_u64, time: 0_u64, offset: 0_u64, - marker: PhantomData::, } } @@ -53,7 +47,7 @@ impl RngCore for SeaHash { } } -impl PrimeableRng for SeaHash { +impl PrimeableRng for SeaHash { fn prime_with(&mut self, location_index: u64, time_index: u64) { self.location = location_index; self.time = time_index; diff --git a/necsim/impls/no-std/src/cogs/rng/wyhash.rs b/necsim/impls/no-std/src/cogs/rng/wyhash.rs index c4fdeed68..d1fa184fa 100644 --- a/necsim/impls/no-std/src/cogs/rng/wyhash.rs +++ b/necsim/impls/no-std/src/cogs/rng/wyhash.rs @@ -1,6 +1,4 @@ -use core::marker::PhantomData; - -use necsim_core::cogs::{Backup, MathsCore, PrimeableRng, RngCore}; +use necsim_core::cogs::{Backup, PrimeableRng, RngCore}; use serde::{Deserialize, Serialize}; @@ -13,24 +11,21 @@ const P5: u64 = 0xeb44_acca_b455_d165; #[allow(clippy::module_name_repetitions, clippy::unsafe_derive_deserialize)] #[derive(Clone, Debug, Serialize, Deserialize, TypeLayout)] -#[layout(free = "M")] #[serde(deny_unknown_fields)] #[repr(C)] -pub struct WyHash { +pub struct WyHash { seed: u64, state: u64, - #[serde(skip)] - marker: PhantomData, } #[contract_trait] -impl Backup for WyHash { +impl Backup for WyHash { unsafe fn backup_unchecked(&self) -> Self { self.clone() } } -impl RngCore for WyHash { +impl RngCore for WyHash { type Seed = [u8; 8]; #[must_use] @@ -38,11 +33,7 @@ impl RngCore for WyHash { fn from_seed(seed: Self::Seed) -> Self { let seed = u64::from_le_bytes(seed); - Self { - seed, - state: seed, - marker: PhantomData::, - } + Self { seed, state: seed } } #[must_use] @@ -60,7 +51,7 @@ impl RngCore for WyHash { } } -impl PrimeableRng for WyHash { +impl PrimeableRng for WyHash { #[inline] fn prime_with(&mut self, location_index: u64, time_index: u64) { let location_index = seahash_diffuse(location_index); diff --git a/necsim/impls/no-std/src/lib.rs b/necsim/impls/no-std/src/lib.rs index 8e8c88d8a..fda8c949f 100644 --- a/necsim/impls/no-std/src/lib.rs +++ b/necsim/impls/no-std/src/lib.rs @@ -10,6 +10,7 @@ #![feature(control_flow_enum)] #![feature(negative_impls)] #![feature(impl_trait_in_assoc_type)] +#![feature(associated_type_bounds)] #![allow(incomplete_features)] #![feature(specialization)] diff --git a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs index 93fbe37f0..9498a714c 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs @@ -9,7 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, + TurnoverRate, }, lineage::Lineage, reporter::Reporter, @@ -39,7 +40,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index 75c83085d..ff7d0808a 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -9,7 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, + TurnoverRate, }, event::DispersalEvent, landscape::IndexedLocation, @@ -44,7 +45,7 @@ pub fn simulate< H: Habitat, C: Decomposition, E: EmigrationChoice, - G: PrimeableRng, + G: Rng, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs index b3ac9a64c..e543487a6 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs @@ -8,7 +8,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, + TurnoverRate, }, lineage::Lineage, reporter::{boolean::Boolean, Reporter}, @@ -44,7 +45,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: PrimeableRng, + G: Rng, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs index 187ee4038..b9149241e 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs @@ -3,7 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, reporter::Reporter, simulation::Simulation, @@ -26,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs index 174c2c358..0fac89dfe 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs @@ -3,7 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -26,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs index 895344836..feffe1fef 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs @@ -3,7 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, reporter::Reporter, simulation::Simulation, @@ -25,7 +26,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs index bb5109217..553fcb735 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs @@ -4,7 +4,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ backup::BackedUp, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, - EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, RngCore, + EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::MigratingLineage, @@ -31,7 +31,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs index 767e5cbb9..0930e18f7 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs @@ -3,7 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -26,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: RngCore, + G: Rng, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, From 7d9c29571eb7a3fdb0b16fc328366d52265c38ab Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Wed, 18 May 2022 07:03:31 +0000 Subject: [PATCH 04/21] Some more progress --- .../alias/individual/mod.rs | 16 +- .../alias/individual/sampler.rs | 5 +- .../alias/location/mod.rs | 10 +- .../alias/location/sampler.rs | 4 +- .../alias/sampler/indexed/tests.rs | 12 +- .../alias/sampler/stack/mod.rs | 29 +++- .../alias/sampler/stack/tests.rs | 139 ++++++++++++++++-- .../active_lineage_sampler/classical/mod.rs | 14 +- .../classical/sampler.rs | 15 +- .../independent/event_time_sampler/const.rs | 2 +- .../independent/event_time_sampler/exp.rs | 5 +- .../event_time_sampler/geometric.rs | 9 +- .../independent/event_time_sampler/poisson.rs | 23 ++- .../almost_infinite_normal.rs | 29 +++- .../src/cogs/dispersal_sampler/non_spatial.rs | 35 ++++- .../dispersal_sampler/spatially_implicit.rs | 34 ++++- .../cogs/dispersal_sampler/wrapping_noise.rs | 28 +++- .../src/cogs/habitat/wrapping_noise/mod.rs | 4 +- 18 files changed, 338 insertions(+), 75 deletions(-) diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index f128a9fc8..7a85d9e6c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -4,9 +4,10 @@ use core::{fmt, marker::PhantomData}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::cogs::{ - rng::Exponential, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, - EmigrationExit, EventSampler, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + rng::{Exponential, IndexU128, IndexU64, IndexUsize}, + Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, + EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }; use crate::cogs::{ @@ -56,6 +57,9 @@ impl< > IndividualAliasActiveLineageSampler where G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -165,6 +169,9 @@ impl< > fmt::Debug for IndividualAliasActiveLineageSampler where G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("IndividualAliasActiveLineageSampler") @@ -190,6 +197,9 @@ impl< > Backup for IndividualAliasActiveLineageSampler where G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index b0130ead7..35e0c0028 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -2,7 +2,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::{Exponential, Lambda}, + rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, @@ -32,6 +32,9 @@ impl< for IndividualAliasActiveLineageSampler where G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index 206db19e6..f2b195cf0 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -5,7 +5,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - rng::{Exponential, IndexUsize}, + rng::{Exponential, IndexU128, IndexU64, IndexUsize}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, SpeciationProbability, TurnoverRate, @@ -39,6 +39,8 @@ pub struct LocationAliasActiveLineageSampler< > where G::Sampler: DistributionSampler, G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { alias_sampler: DynamicAliasMethodIndexedSampler, number_active_lineages: usize, @@ -63,6 +65,8 @@ impl< where G::Sampler: DistributionSampler, G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -220,6 +224,8 @@ impl< where G::Sampler: DistributionSampler, G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("LocationAliasActiveLineageSampler") @@ -246,6 +252,8 @@ impl< where G::Sampler: DistributionSampler, G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index cdf70e474..6b8c627f5 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -2,7 +2,7 @@ use core::{num::NonZeroUsize, ops::ControlFlow}; use necsim_core::{ cogs::{ - rng::{Exponential, IndexUsize, Lambda, Length}, + rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, SpeciationProbability, TurnoverRate, @@ -35,6 +35,8 @@ impl< where G::Sampler: DistributionSampler, G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 94ecebc74..3e2b341b4 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1143,11 +1143,11 @@ impl DistributionSampler usize { let length = params.0; - /*#[allow( + #[allow( clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss - )]*/ + )] let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as usize; // Safety in case of f64 rounding errors @@ -1172,11 +1172,11 @@ impl DistributionSampler u64 { let length = params.0; - /*#[allow( + #[allow( clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss - )]*/ + )] let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u64; // Safety in case of f64 rounding errors @@ -1201,11 +1201,11 @@ impl DistributionSampler u128 { let length = params.0; - /*#[allow( + #[allow( clippy::cast_precision_loss, clippy::cast_possible_truncation, clippy::cast_sign_loss - )]*/ + )] let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u128; // Safety in case of f64 rounding errors diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 48c4e3f23..bc3ecb692 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -7,7 +7,10 @@ use core::{ num::{NonZeroU128, NonZeroU64, NonZeroUsize}, }; -use necsim_core::cogs::{Backup, MathsCore, Rng, RngCore}; +use necsim_core::cogs::{ + rng::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, MathsCore, Rng, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; #[cfg(test)] @@ -45,7 +48,10 @@ impl RejectionSamplingGroup { unsafe fn sample_pop_inplace>( &mut self, rng: &mut G, - ) -> (Option<&mut Self>, E) { + ) -> (Option<&mut Self>, E) + where + G::Sampler: DistributionSampler, + { if let [_event] = &self.events[..] { // Safety: If there is only one event, the pop must succeed return (None, self.events.pop().unwrap_unchecked()); @@ -53,7 +59,8 @@ impl RejectionSamplingGroup { loop { // Safety: By construction, the group never contains zero elements - let index = rng.sample_index(NonZeroUsize::new_unchecked(self.weights.len())); + let index = rng + .sample_with::(Length(NonZeroUsize::new_unchecked(self.weights.len()))); let height = rng.sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% @@ -70,7 +77,10 @@ impl RejectionSamplingGroup { } #[cfg(test)] - fn sample_pop>(mut self, rng: &mut G) -> (Option, E) { + fn sample_pop>(mut self, rng: &mut G) -> (Option, E) + where + G::Sampler: DistributionSampler, + { match unsafe { self.sample_pop_inplace(rng) } { (Some(_), event) => (Some(self), event), (None, event) => (None, event), @@ -121,14 +131,19 @@ impl DynamicAliasMethodStackSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } - pub fn sample_pop>(&mut self, rng: &mut G) -> Option { + pub fn sample_pop>(&mut self, rng: &mut G) -> Option + where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, + { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { - u128::from(rng.sample_index_u64(total_weight)) + u128::from(rng.sample_with::(Length(total_weight))) } else { - rng.sample_index_u128(total_weight) + rng.sample_with::(Length(total_weight)) }; let mut cdf_acc = 0_u128; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 9cc9b547c..5fb69cc0d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -1,7 +1,13 @@ +use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; + use alloc::{vec, vec::Vec}; -use necsim_core::cogs::{Backup, RngCore, SeedableRng}; +use necsim_core::cogs::{ + rng::{IndexU128, IndexU64, IndexUsize, Length, SimpleRng}, + Backup, Distribution, DistributionSampler, Rng, RngCore, SeedableRng, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; +use necsim_core_maths::MathsCore; use crate::cogs::{maths::intrinsics::IntrinsicsMathsCore, rng::wyhash::WyHash}; @@ -96,7 +102,7 @@ fn sample_single_group() { let mut tally = [0_u64; 6]; - let mut rng = WyHash::::seed_from_u64(24897); + let mut rng = SimpleRng::::seed_from_u64(24897); for _ in 0..N { let (maybe_group, sample) = group.sample_pop(&mut rng); @@ -396,7 +402,7 @@ fn add_remove_event_full() { fn sample_single_group_full() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(471_093); + let mut rng = SimpleRng::::seed_from_u64(471_093); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -445,7 +451,7 @@ fn sample_single_group_full() { fn sample_three_groups_full() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(739_139); + let mut rng = SimpleRng::::seed_from_u64(739_139); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -491,7 +497,7 @@ fn sample_three_groups_full() { fn sample_three_groups_full_reverse() { const N: usize = 10_000_000; - let mut rng = WyHash::::seed_from_u64(248_971); + let mut rng = SimpleRng::::seed_from_u64(248_971); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -570,18 +576,17 @@ fn debug_display_sampler() { // GRCOV_EXCL_START #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -struct DummyRng(Vec); +struct DummyRng(Vec); impl DummyRng { fn new(mut vec: Vec) -> Self { vec.reverse(); - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - Self( - vec.into_iter() - .map(|u01| ((u01 / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11) - .collect(), - ) + Self(vec) + } + + fn sample_f64(&mut self) -> f64 { + self.0.pop().unwrap() } } @@ -595,7 +600,115 @@ impl RngCore for DummyRng { #[must_use] fn sample_u64(&mut self) -> u64 { - self.0.pop().unwrap() + // #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + } +} + +impl Rng for DummyRng { + type Generator = Self; + type Sampler = DummyDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + self + } + + fn sample_with(&mut self, params: D::Parameters) -> D::Sample + where + Self::Sampler: DistributionSampler, + { + let samplers = DummyDistributionSamplers; + + samplers.sample_with(self, &samplers, params) + } +} + +struct DummyDistributionSamplers; + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> usize { + let length = params.0; + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as usize; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> u64 { + let length = params.0; + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u64; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with( + &self, + rng: &mut DummyRng, + samplers: &DummyDistributionSamplers, + params: Length, + ) -> u128 { + let length = params.0; + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u128; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) } } // GRCOV_EXCL_STOP diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index b1e89e4f7..721b46387 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -2,7 +2,8 @@ use alloc::vec::Vec; use core::marker::PhantomData; use necsim_core::cogs::{ - Backup, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, + rng::{Exponential, IndexUsize}, + Backup, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }; use necsim_core_bond::NonNegativeF64; @@ -25,7 +26,10 @@ pub struct ClassicalActiveLineageSampler< D: DispersalSampler, N: SpeciationProbability, I: ImmigrationEntry, -> { +> where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ active_lineage_references: Vec, last_event_time: NonNegativeF64, #[allow(clippy::type_complexity)] @@ -42,6 +46,9 @@ impl< N: SpeciationProbability, I: ImmigrationEntry, > ClassicalActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -133,6 +140,9 @@ impl< N: SpeciationProbability, I: ImmigrationEntry, > Backup for ClassicalActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 3e1ec7f1a..75364840a 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -5,8 +5,10 @@ use core::{ use necsim_core::{ cogs::{ - ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + rng::{Exponential, IndexUsize, Lambda, Length}, + ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, + SpeciationProbability, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -55,6 +57,9 @@ impl< >, I, > for ClassicalActiveLineageSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, N: 'a, I: 'a; @@ -111,7 +116,7 @@ impl< let lambda = simulation.turnover_rate.get_uniform_turnover_rate() * PositiveF64::from(number_active_lineages); - let event_time = self.last_event_time + rng.sample_exponential(lambda); + let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); @@ -123,9 +128,9 @@ impl< // Safety: The outer if statement has already shown that the number // of remaining lineages is non-zero - let chosen_lineage_index = rng.sample_index(unsafe { + let chosen_lineage_index = rng.sample_with::(Length(unsafe { NonZeroUsize::new_unchecked(self.active_lineage_references.len()) - }); + })); let chosen_lineage_reference = self .active_lineage_references .swap_remove(chosen_lineage_index); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs index c8f230dc9..312603e7d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, MathsCore, PrimeableRng, Rng, TurnoverRate}, + cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index 73c36935d..002de74bb 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ rng::{Exponential, Lambda}, - Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate, + DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, + TurnoverRate, }, landscape::IndexedLocation, }; @@ -29,6 +30,8 @@ impl ExpEventTimeSampler { #[contract_trait] impl, G: Rng, T: TurnoverRate> EventTimeSampler for ExpEventTimeSampler +where + G::Sampler: DistributionSampler, { #[inline] fn next_event_time_at_indexed_location_weakly_after( diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index 3f6c8b0bf..e7e635446 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, + cogs::{ + rng::Event, DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, + Rng, TurnoverRate, + }, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -23,6 +26,8 @@ impl GeometricEventTimeSampler { #[contract_trait] impl, G: Rng, T: TurnoverRate> EventTimeSampler for GeometricEventTimeSampler +where + G::Sampler: DistributionSampler, { #[inline] fn next_event_time_at_indexed_location_weakly_after( @@ -47,7 +52,7 @@ impl, G: Rng, T: Turnove rng.generator() .prime_with_habitat(habitat, indexed_location, time_step); - if rng.sample_event(event_probability_per_step) { + if rng.sample_with::(event_probability_per_step) { break; } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index 381362042..cafdbe373 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -1,5 +1,9 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, + cogs::{ + rng::{Normal, Normal2D, UniformClosedOpenUnit}, + DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, + TurnoverRate, + }, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -26,6 +30,9 @@ impl PoissonEventTimeSampler { #[contract_trait] impl, G: Rng, T: TurnoverRate> EventTimeSampler for PoissonEventTimeSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[inline] fn next_event_time_at_indexed_location_weakly_after( @@ -46,7 +53,8 @@ impl, G: Rng, T: Turnove let mut time_step = M::floor(time.get() / self.delta_t.get()) as u64; let (event_time, event_index) = loop { - rng.prime_with_habitat(habitat, indexed_location, time_step); + rng.generator() + .prime_with_habitat(habitat, indexed_location, time_step); let number_events_at_time_steps = if no_event_probability_per_step > 0.0_f64 { // https://en.wikipedia.org/wiki/Poisson_distribution#cite_ref-Devroye1986_54-0 @@ -54,7 +62,7 @@ impl, G: Rng, T: Turnove let mut prod = no_event_probability_per_step; let mut acc = no_event_probability_per_step; - let u = rng.sample_uniform_closed_open(); + let u = rng.sample::(); while u > acc && prod > 0.0_f64 { poisson += 1; @@ -67,7 +75,10 @@ impl, G: Rng, T: Turnove // Fallback in case no_event_probability_per_step underflows #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let normal_as_poisson = rng - .sample_2d_normal(lambda_per_step.get(), lambda_per_step.sqrt::()) + .sample_with::(Normal { + mu: lambda_per_step.get(), + sigma: lambda_per_step.sqrt::(), + }) .0 .max(0.0_f64) as u32; @@ -79,7 +90,7 @@ impl, G: Rng, T: Turnove for event_index in 0..number_events_at_time_steps { #[allow(clippy::cast_precision_loss)] let event_time = (NonNegativeF64::from(time_step) - + NonNegativeF64::from(rng.sample_uniform_closed_open())) + + NonNegativeF64::from(rng.sample::())) * self.delta_t; if event_time > time { @@ -99,7 +110,7 @@ impl, G: Rng, T: Turnove } }; - rng.prime_with_habitat( + rng.generator().prime_with_habitat( habitat, indexed_location, time_step + INV_PHI.wrapping_mul(u64::from(event_index + 1)), diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index 8100b5656..cb1242313 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -1,7 +1,10 @@ use core::marker::PhantomData; use necsim_core::{ - cogs::{Backup, DispersalSampler, MathsCore, Rng, SeparableDispersalSampler}, + cogs::{ + rng::{Normal, Normal2D}, + Backup, DispersalSampler, DistributionSampler, MathsCore, Rng, SeparableDispersalSampler, + }, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -12,13 +15,19 @@ use crate::cogs::habitat::almost_infinite::AlmostInfiniteHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct AlmostInfiniteNormalDispersalSampler> { +pub struct AlmostInfiniteNormalDispersalSampler> +where + G::Sampler: DistributionSampler, +{ sigma: NonNegativeF64, self_dispersal: ClosedUnitF64, marker: PhantomData<(M, G)>, } -impl> AlmostInfiniteNormalDispersalSampler { +impl> AlmostInfiniteNormalDispersalSampler +where + G::Sampler: DistributionSampler, +{ #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { let self_dispersal_1d = if sigma > 0.0_f64 { @@ -40,7 +49,10 @@ impl> AlmostInfiniteNormalDispersalSampler { } #[contract_trait] -impl> Backup for AlmostInfiniteNormalDispersalSampler { +impl> Backup for AlmostInfiniteNormalDispersalSampler +where + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { sigma: self.sigma, @@ -53,6 +65,8 @@ impl> Backup for AlmostInfiniteNormalDispersalSampler> DispersalSampler, G> for AlmostInfiniteNormalDispersalSampler +where + G::Sampler: DistributionSampler, { #[must_use] fn sample_dispersal_from_location( @@ -63,7 +77,10 @@ impl> DispersalSampler, G> ) -> Location { const WRAP: i64 = 1 << 32; - let (dx, dy): (f64, f64) = rng.sample_2d_normal(0.0_f64, self.sigma); + let (dx, dy): (f64, f64) = rng.sample_with::(Normal { + mu: 0.0_f64, + sigma: self.sigma, + }); // Discrete dispersal assumes lineage positions are centred on (0.5, 0.5), // i.e. |dispersal| >= 0.5 changes the cell @@ -85,6 +102,8 @@ impl> DispersalSampler, G> #[contract_trait] impl> SeparableDispersalSampler, G> for AlmostInfiniteNormalDispersalSampler +where + G::Sampler: DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs index 929521c05..7be0ddfd3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs @@ -1,7 +1,11 @@ use core::{marker::PhantomData, num::NonZeroU64}; use necsim_core::{ - cogs::{Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, + cogs::{ + rng::{IndexU64, Length}, + Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + SeparableDispersalSampler, + }, landscape::Location, }; use necsim_core_bond::ClosedUnitF64; @@ -12,11 +16,17 @@ use crate::cogs::habitat::non_spatial::NonSpatialHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct NonSpatialDispersalSampler> { +pub struct NonSpatialDispersalSampler> +where + G::Sampler: DistributionSampler, +{ marker: PhantomData<(M, G)>, } -impl> Default for NonSpatialDispersalSampler { +impl> Default for NonSpatialDispersalSampler +where + G::Sampler: DistributionSampler, +{ #[must_use] fn default() -> Self { Self { @@ -26,7 +36,10 @@ impl> Default for NonSpatialDispersalSampler { } #[contract_trait] -impl> Backup for NonSpatialDispersalSampler { +impl> Backup for NonSpatialDispersalSampler +where + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { marker: PhantomData::<(M, G)>, @@ -37,6 +50,8 @@ impl> Backup for NonSpatialDispersalSampler { #[contract_trait] impl> DispersalSampler, G> for NonSpatialDispersalSampler +where + G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -50,8 +65,9 @@ impl> DispersalSampler, G> habitat.get_extent().width().get() * habitat.get_extent().height().get(); // Safety: habitat width and height are both > 0 - let dispersal_target_index = - rng.sample_index_u64(unsafe { NonZeroU64::new_unchecked(habitat_index_max) }); + let dispersal_target_index = rng.sample_with::(Length(unsafe { + NonZeroU64::new_unchecked(habitat_index_max) + })); #[allow(clippy::cast_possible_truncation)] Location::new( @@ -70,6 +86,8 @@ impl> DispersalSampler, G> #[contract_trait] impl> SeparableDispersalSampler, G> for NonSpatialDispersalSampler +where + G::Sampler: DistributionSampler, { #[must_use] #[debug_requires(( @@ -88,8 +106,9 @@ impl> SeparableDispersalSampler, let dispersal_target_index = { // Safety: by PRE, `habitat_index_max` > 1 - let dispersal_target_index = - rng.sample_index_u64(unsafe { NonZeroU64::new_unchecked(habitat_index_max - 1) }); + let dispersal_target_index = rng.sample_with::(Length(unsafe { + NonZeroU64::new_unchecked(habitat_index_max - 1) + })); if dispersal_target_index >= current_location_index { dispersal_target_index + 1 diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index 3451bc9bb..6f20be60a 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,5 +1,9 @@ use necsim_core::{ - cogs::{Backup, DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, + cogs::{ + rng::{Event, IndexU64}, + Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + SeparableDispersalSampler, + }, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, OpenClosedUnitF64 as PositiveUnitF64}; @@ -13,7 +17,11 @@ use crate::cogs::{ #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M"))] -pub struct SpatiallyImplicitDispersalSampler> { +pub struct SpatiallyImplicitDispersalSampler> +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ #[cfg_attr(feature = "cuda", cuda(embed))] local: NonSpatialDispersalSampler, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -21,7 +29,11 @@ pub struct SpatiallyImplicitDispersalSampler> { local_migration_probability_per_generation: PositiveUnitF64, } -impl> SpatiallyImplicitDispersalSampler { +impl> SpatiallyImplicitDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ #[must_use] pub fn new(local_migration_probability_per_generation: PositiveUnitF64) -> Self { Self { @@ -33,7 +45,11 @@ impl> SpatiallyImplicitDispersalSampler { } #[contract_trait] -impl> Backup for SpatiallyImplicitDispersalSampler { +impl> Backup for SpatiallyImplicitDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { local: self.local.backup_unchecked(), @@ -47,6 +63,9 @@ impl> Backup for SpatiallyImplicitDispersalSampler #[contract_trait] impl> DispersalSampler, G> for SpatiallyImplicitDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -65,7 +84,7 @@ impl> DispersalSampler, G // By PRE, location must be habitable, i.e. either in the local or the meta // habitat if habitat.local().get_extent().contains(location) { - if rng.sample_event(self.local_migration_probability_per_generation.into()) { + if rng.sample_with::(self.local_migration_probability_per_generation.into()) { // Provide a dummpy Location in the meta community to disperse from self.meta.sample_dispersal_from_location( &Location::new( @@ -89,6 +108,9 @@ impl> DispersalSampler, G #[contract_trait] impl> SeparableDispersalSampler, G> for SpatiallyImplicitDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -107,7 +129,7 @@ impl> SeparableDispersalSampler(self.local_migration_probability_per_generation.into()) { // Provide a dummpy Location in the meta community to disperse from // As the individual is dispersing to a different community, // we can use standard dispersal in the meta community diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs index e423248d3..22c70b7eb 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ Backup, DispersalSampler, Habitat, MathsCore, Rng, - SeparableDispersalSampler, + SeparableDispersalSampler, DistributionSampler, rng::{Normal2D, Event}, }, landscape::Location, }; @@ -16,12 +16,20 @@ use crate::cogs::{ #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M"))] -pub struct WrappingNoiseApproximateNormalDispersalSampler> { +pub struct WrappingNoiseApproximateNormalDispersalSampler> +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ #[cfg_attr(feature = "cuda", cuda(embed))] inner: AlmostInfiniteNormalDispersalSampler, } -impl> WrappingNoiseApproximateNormalDispersalSampler { +impl> WrappingNoiseApproximateNormalDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { Self { @@ -31,7 +39,11 @@ impl> WrappingNoiseApproximateNormalDispersalSampler> Backup for WrappingNoiseApproximateNormalDispersalSampler { +impl> Backup for WrappingNoiseApproximateNormalDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { inner: self.inner.backup_unchecked(), @@ -42,6 +54,9 @@ impl> Backup for WrappingNoiseApproximateNormalDispersal #[contract_trait] impl> DispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -56,7 +71,7 @@ impl> DispersalSampler, G> // targets are rejected. // If seperable dispersal is not required, this can be implemented as a // direct rejection sampling loop instead. - if rng.sample_event(self.get_self_dispersal_probability_at_location(location, habitat)) { + if rng.sample_with::(self.get_self_dispersal_probability_at_location(location, habitat)) { location.clone() } else { self.sample_non_self_dispersal_from_location(location, habitat, rng) @@ -67,6 +82,9 @@ impl> DispersalSampler, G> #[contract_trait] impl> SeparableDispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler +where + G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs index 3604aa8a7..5d87ec583 100644 --- a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs +++ b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs @@ -10,7 +10,7 @@ mod opensimplex_noise; use opensimplex_noise::OpenSimplexNoise; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat, RngCore}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -62,7 +62,7 @@ impl WrappingNoiseHabitat { // Utilise a PRNG to avoid sampling degeneracies for finding the // threshold which would poison the entire sampler - let mut rng: WyHash = WyHash::from_seed(seed.to_le_bytes()); + let mut rng = WyHash::from_seed(seed.to_le_bytes()); for _ in 0..(1_usize << 16) { let location = rng.sample_u64(); From ba9bc808774002f09faa0b77a11a8f3e6e2aea4a Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Wed, 18 May 2022 08:13:50 +0000 Subject: [PATCH 05/21] Finished refactoring of necsim-impls --- necsim/impls/no-std/src/alias/mod.rs | 4 +- necsim/impls/no-std/src/alias/packed.rs | 4 +- .../alias/individual/mod.rs | 28 +++++++------- .../alias/individual/sampler.rs | 12 +++--- .../alias/location/mod.rs | 32 ++++++++-------- .../alias/location/sampler.rs | 12 +++--- .../alias/sampler/indexed/mod.rs | 6 +-- .../alias/sampler/indexed/tests.rs | 12 +++--- .../alias/sampler/stack/mod.rs | 6 +-- .../alias/sampler/stack/tests.rs | 12 +++--- .../active_lineage_sampler/classical/mod.rs | 20 ++++++---- .../classical/sampler.rs | 11 +++--- .../independent/event_time_sampler/poisson.rs | 4 +- .../active_lineage_sampler/independent/mod.rs | 12 ++++-- .../independent/sampler.rs | 6 ++- .../independent/singular.rs | 6 ++- .../resuming/sampler.rs | 4 +- .../cogs/active_lineage_sampler/singular.rs | 4 +- .../in_memory/alias/dispersal.rs | 8 +++- .../dispersal_sampler/in_memory/alias/mod.rs | 20 ++++++++-- .../in_memory/cumulative/contract.rs | 12 +++--- .../in_memory/cumulative/dispersal.rs | 10 +++-- .../in_memory/cumulative/mod.rs | 21 +++++++++-- .../in_memory/packed_alias/dispersal.rs | 8 +++- .../in_memory/packed_alias/mod.rs | 23 ++++++++++-- .../in_memory/separable_alias/dispersal.rs | 15 +++++++- .../in_memory/separable_alias/mod.rs | 17 ++++++++- .../dispersal_sampler/spatially_implicit.rs | 20 +++++----- .../no-std/src/cogs/emigration_exit/domain.rs | 37 +++++++++++++------ .../cogs/emigration_exit/independent/mod.rs | 32 ++++++++++------ .../no-std/src/cogs/emigration_exit/never.rs | 8 +--- .../gillespie/conditional/mod.rs | 22 ++++++++--- .../gillespie/conditional/probability.rs | 4 +- .../src/cogs/event_sampler/gillespie/mod.rs | 4 +- .../event_sampler/gillespie/unconditional.rs | 29 ++++++++++++--- .../src/cogs/event_sampler/independent.rs | 21 ++++++++--- .../no-std/src/cogs/event_sampler/tracking.rs | 4 +- .../src/cogs/event_sampler/unconditional.rs | 24 +++++++++--- .../no-std/src/cogs/habitat/in_memory.rs | 13 +++++-- .../no-std/src/cogs/habitat/non_spatial.rs | 15 ++++++-- .../src/cogs/habitat/spatially_implicit.rs | 10 ++++- .../independent/individuals.rs | 9 +++-- .../parallelisation/independent/landscape.rs | 17 +++++---- .../independent/monolithic/mod.rs | 9 +++-- .../parallelisation/monolithic/averaging.rs | 17 +++++---- .../parallelisation/monolithic/lockstep.rs | 17 +++++---- .../parallelisation/monolithic/monolithic.rs | 3 +- .../parallelisation/monolithic/optimistic.rs | 17 +++++---- .../monolithic/optimistic_lockstep.rs | 17 +++++---- .../cogs/dispersal_sampler/in_memory/mod.rs | 6 +-- necsim/impls/std/src/cogs/rng/pcg.rs | 27 +++++--------- 51 files changed, 460 insertions(+), 251 deletions(-) diff --git a/necsim/impls/no-std/src/alias/mod.rs b/necsim/impls/no-std/src/alias/mod.rs index f916d83d8..cbabed87c 100644 --- a/necsim/impls/no-std/src/alias/mod.rs +++ b/necsim/impls/no-std/src/alias/mod.rs @@ -96,8 +96,8 @@ impl AliasMethodSampler { #[debug_ensures(self.Es.contains(&ret), "returns one of the weighted events")] pub fn sample_event>(&self, rng: &mut G) -> E where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { // Safety: Es is non-empty by the precondition on construction let length = unsafe { NonZeroUsize::new_unchecked(self.Es.len()) }; diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index bca820be3..fcc0aab9a 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -116,8 +116,8 @@ impl AliasMethodSamplerAtom { rng: &mut G, ) -> E where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { // Safety: alias_samplers is non-empty by the precondition let length = unsafe { NonZeroUsize::new_unchecked(alias_samplers.len()) }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index 7a85d9e6c..490784d5c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -6,8 +6,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::cogs::{ rng::{Exponential, IndexU128, IndexU64, IndexUsize}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }; use crate::cogs::{ @@ -56,10 +56,10 @@ impl< I: ImmigrationEntry, > IndividualAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -168,10 +168,10 @@ impl< I: ImmigrationEntry, > fmt::Debug for IndividualAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("IndividualAliasActiveLineageSampler") @@ -196,10 +196,10 @@ impl< I: ImmigrationEntry, > Backup for IndividualAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index 35e0c0028..cf56e5058 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -4,8 +4,8 @@ use necsim_core::{ cogs::{ rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, - EmigrationExit, EventSampler, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -31,10 +31,10 @@ impl< > ActiveLineageSampler for IndividualAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index f2b195cf0..34ed04bd0 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -37,10 +37,10 @@ pub struct LocationAliasActiveLineageSampler< E: GillespieEventSampler, I: ImmigrationEntry, > where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { alias_sampler: DynamicAliasMethodIndexedSampler, number_active_lineages: usize, @@ -63,10 +63,10 @@ impl< I: ImmigrationEntry, > LocationAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -222,10 +222,10 @@ impl< I: ImmigrationEntry, > core::fmt::Debug for LocationAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("LocationAliasActiveLineageSampler") @@ -250,10 +250,10 @@ impl< I: ImmigrationEntry, > Backup for LocationAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index 6b8c627f5..ca1717dad 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -4,8 +4,8 @@ use necsim_core::{ cogs::{ rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, - EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -33,10 +33,10 @@ impl< > ActiveLineageSampler for LocationAliasActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 3eacfaafc..6c5416b89 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -199,9 +199,9 @@ impl DynamicAliasMethodIndexedSampler { pub fn sample_pop>(&mut self, rng: &mut G) -> Option where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 3e2b341b4..c866a6886 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1101,8 +1101,10 @@ impl RngCore for DummyRng { #[must_use] fn sample_u64(&mut self) -> u64 { - // #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + { + ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + } } } @@ -1138,7 +1140,7 @@ impl DistributionSampler, ) -> usize { let length = params.0; @@ -1167,7 +1169,7 @@ impl DistributionSampler, ) -> u64 { let length = params.0; @@ -1196,7 +1198,7 @@ impl DistributionSampler, ) -> u128 { let length = params.0; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index bc3ecb692..5ce8675bb 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -133,9 +133,9 @@ impl DynamicAliasMethodStackSampler { pub fn sample_pop>(&mut self, rng: &mut G) -> Option where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 5fb69cc0d..06ff6339c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -600,8 +600,10 @@ impl RngCore for DummyRng { #[must_use] fn sample_u64(&mut self) -> u64 { - // #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + { + ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + } } } @@ -637,7 +639,7 @@ impl DistributionSampler, ) -> usize { let length = params.0; @@ -666,7 +668,7 @@ impl DistributionSampler, ) -> u64 { let length = params.0; @@ -695,7 +697,7 @@ impl DistributionSampler, ) -> u128 { let length = params.0; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index 721b46387..339fa1036 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::marker::PhantomData; use necsim_core::cogs::{ - rng::{Exponential, IndexUsize}, + rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, Backup, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }; @@ -27,8 +27,10 @@ pub struct ClassicalActiveLineageSampler< N: SpeciationProbability, I: ImmigrationEntry, > where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { active_lineage_references: Vec, last_event_time: NonNegativeF64, @@ -47,8 +49,10 @@ impl< I: ImmigrationEntry, > ClassicalActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -141,8 +145,10 @@ impl< I: ImmigrationEntry, > Backup for ClassicalActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 75364840a..3512b9ca3 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -5,10 +5,9 @@ use core::{ use necsim_core::{ cogs::{ - rng::{Exponential, IndexUsize, Lambda, Length}, + rng::{Event, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, - SpeciationProbability, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -58,8 +57,10 @@ impl< I, > for ClassicalActiveLineageSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, N: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index cafdbe373..0eb959300 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -31,8 +31,8 @@ impl PoissonEventTimeSampler { impl, G: Rng, T: TurnoverRate> EventTimeSampler for PoissonEventTimeSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[inline] fn next_event_time_at_indexed_location_weakly_after( diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs index ecf692a1d..9642d7979 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - Backup, DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, - SpeciationProbability, TurnoverRate, + rng::UniformClosedOpenUnit, Backup, DispersalSampler, DistributionSampler, EmigrationExit, + Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, }; @@ -36,7 +36,9 @@ pub struct IndependentActiveLineageSampler< T: TurnoverRate, N: SpeciationProbability, J: EventTimeSampler, -> { +> where + G::Sampler: DistributionSampler, +{ #[cfg_attr( feature = "cuda", cuda(embed = "Option>") @@ -59,6 +61,8 @@ impl< N: SpeciationProbability, J: EventTimeSampler, > IndependentActiveLineageSampler +where + G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store_and_lineages<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -145,6 +149,8 @@ impl< N: SpeciationProbability, J: EventTimeSampler, > Backup for IndependentActiveLineageSampler +where + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs index 013b1a994..fb951a52a 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs @@ -2,8 +2,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, - Rng, SpeciationProbability, TurnoverRate, + rng::UniformClosedOpenUnit, ActiveLineageSampler, DispersalSampler, DistributionSampler, + EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -43,6 +43,8 @@ impl< IndependentEventSampler, NeverImmigrationEntry, > for IndependentActiveLineageSampler +where + G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, X: 'a, D: 'a, T: 'a, N: 'a, J: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs index 95f102ee6..1e197de68 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs @@ -1,6 +1,6 @@ use necsim_core::cogs::{ - DispersalSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, + MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }; use necsim_core::lineage::Lineage; @@ -39,6 +39,8 @@ impl< IndependentEventSampler, NeverImmigrationEntry, > for IndependentActiveLineageSampler +where + G::Sampler: DistributionSampler, { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs index 65d718f77..fe94a105b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/resuming/sampler.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs index fd0526d4d..2cc096afc 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/singular.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + Habitat, ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, lineage::Lineage, }; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs index 88827eece..302921b3e 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, Rng}, + cogs::{ + rng::{Event, IndexUsize}, + DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; @@ -8,6 +11,9 @@ use super::InMemoryAliasDispersalSampler; #[contract_trait] impl, G: Rng> DispersalSampler for InMemoryAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs index a4b19842f..87dda5998 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs @@ -3,7 +3,10 @@ use core::marker::PhantomData; use alloc::vec::Vec; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng}, + cogs::{ + rng::{Event, IndexUsize}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; use necsim_core_bond::NonNegativeF64; @@ -17,7 +20,11 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemoryAliasDispersalSampler, G: Rng> { +pub struct InMemoryAliasDispersalSampler, G: Rng> +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ alias_dispersal: Array2D>>, marker: PhantomData<(M, H, G)>, } @@ -25,6 +32,9 @@ pub struct InMemoryAliasDispersalSampler, G: Rng> #[contract_trait] impl, G: Rng> InMemoryDispersalSampler for InMemoryAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { /// Creates a new `InMemoryAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -77,7 +87,11 @@ impl, G: Rng> InMemoryDispersalSampler } #[contract_trait] -impl, G: Rng> Backup for InMemoryAliasDispersalSampler { +impl, G: Rng> Backup for InMemoryAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { alias_dispersal: self.alias_dispersal.clone(), diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs index 44f099a80..cc0f41401 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs @@ -1,15 +1,15 @@ use necsim_core::{ - cogs::{Habitat, MathsCore}, + cogs::{rng::UniformClosedOpenUnit, DistributionSampler, Habitat, MathsCore, Rng}, landscape::Location, }; use super::InMemoryCumulativeDispersalSampler; -impl InMemoryCumulativeDispersalSampler { - pub(super) fn explicit_only_valid_targets_dispersal_contract>( - &self, - habitat: &H, - ) -> bool { +impl, G: Rng> InMemoryCumulativeDispersalSampler +where + G::Sampler: DistributionSampler, +{ + pub(super) fn explicit_only_valid_targets_dispersal_contract(&self, habitat: &H) -> bool { let habitat_width = habitat.get_extent().width(); for target_index in self.valid_dispersal_targets.iter().filter_map(|x| *x) { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs index 4b34d84c9..9ca1dadec 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs @@ -1,5 +1,7 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, Rng}, + cogs::{ + rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; @@ -7,7 +9,9 @@ use super::InMemoryCumulativeDispersalSampler; #[contract_trait] impl, G: Rng> DispersalSampler - for InMemoryCumulativeDispersalSampler + for InMemoryCumulativeDispersalSampler +where + G::Sampler: DistributionSampler, { #[must_use] fn sample_dispersal_from_location( @@ -26,7 +30,7 @@ impl, G: Rng> DispersalSampler let cumulative_dispersals_at_location = &self.cumulative_dispersal [location_index * habitat_area..(location_index + 1) * habitat_area]; - let cumulative_percentage_sample = rng.sample_uniform_closed_open().into(); + let cumulative_percentage_sample = rng.sample::().into(); let dispersal_target_index = usize::min( match cumulative_dispersals_at_location.binary_search(&cumulative_percentage_sample) { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs index fe030a331..7a658eb1b 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs @@ -1,7 +1,9 @@ +use core::marker::PhantomData; + use alloc::{boxed::Box, vec}; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng}, + cogs::{rng::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, MathsCore, Rng}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -13,14 +15,20 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemoryCumulativeDispersalSampler { +pub struct InMemoryCumulativeDispersalSampler, G: Rng> +where + G::Sampler: DistributionSampler, +{ cumulative_dispersal: Box<[ClosedUnitF64]>, valid_dispersal_targets: Box<[Option]>, + marker: PhantomData<(M, H, G)>, } #[contract_trait] impl, G: Rng> InMemoryDispersalSampler - for InMemoryCumulativeDispersalSampler + for InMemoryCumulativeDispersalSampler +where + G::Sampler: DistributionSampler, { /// Creates a new `InMemoryCumulativeDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -96,16 +104,21 @@ impl, G: Rng> InMemoryDispersalSampler InMemoryCumulativeDispersalSampler { cumulative_dispersal, valid_dispersal_targets, + marker: PhantomData::<(M, H, G)>, } } } #[contract_trait] -impl Backup for InMemoryCumulativeDispersalSampler { +impl, G: Rng> Backup for InMemoryCumulativeDispersalSampler +where + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { cumulative_dispersal: self.cumulative_dispersal.clone(), valid_dispersal_targets: self.valid_dispersal_targets.clone(), + marker: PhantomData::<(M, H, G)>, } } } diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs index 16722013d..06189f91a 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs @@ -1,7 +1,10 @@ use core::ops::Range; use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, Rng}, + cogs::{ + rng::{Event, IndexUsize}, + DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; @@ -12,6 +15,9 @@ use super::InMemoryPackedAliasDispersalSampler; #[contract_trait] impl, G: Rng> DispersalSampler for InMemoryPackedAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs index 59bc188d3..ec27a0fa1 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs @@ -5,7 +5,10 @@ use necsim_core_bond::NonNegativeF64; use r#final::Final; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng}, + cogs::{ + rng::{Event, IndexUsize}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; @@ -42,7 +45,11 @@ impl From for Range { #[allow(clippy::module_name_repetitions)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "H", free = "G"))] -pub struct InMemoryPackedAliasDispersalSampler, G: Rng> { +pub struct InMemoryPackedAliasDispersalSampler, G: Rng> +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ #[cfg_attr(feature = "cuda", cuda(embed))] alias_dispersal_ranges: Final>, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -53,6 +60,9 @@ pub struct InMemoryPackedAliasDispersalSampler, G: R #[contract_trait] impl, G: Rng> InMemoryDispersalSampler for InMemoryPackedAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { /// Creates a new `InMemoryPackedAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -114,6 +124,9 @@ impl, G: Rng> InMemoryDispersalSampler impl, G: Rng> core::fmt::Debug for InMemoryPackedAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct(stringify!(InMemoryPackedAliasDispersalSampler)) @@ -131,8 +144,10 @@ impl, G: Rng> core::fmt::Debug } #[contract_trait] -impl, G: Rng> Backup - for InMemoryPackedAliasDispersalSampler +impl, G: Rng> Backup for InMemoryPackedAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index 1c7c37e99..437ec6bb2 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{DispersalSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler}, + cogs::{ + rng::{Event, IndexUsize}, + DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler, + }, landscape::Location, }; use necsim_core_bond::ClosedUnitF64; @@ -9,6 +12,9 @@ use super::InMemorySeparableAliasDispersalSampler; #[contract_trait] impl, G: Rng> DispersalSampler for InMemorySeparableAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( @@ -24,7 +30,9 @@ impl, G: Rng> DispersalSampler return location.clone(); } - if self_dispersal_at_location > 0.0_f64 && rng.sample_event(self_dispersal_at_location) { + if self_dispersal_at_location > 0.0_f64 + && rng.sample_with::(self_dispersal_at_location) + { return location.clone(); } @@ -35,6 +43,9 @@ impl, G: Rng> DispersalSampler #[contract_trait] impl, G: Rng> SeparableDispersalSampler for InMemorySeparableAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs index 70cda163e..0d6604292 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs @@ -3,7 +3,10 @@ use core::marker::PhantomData; use alloc::vec::Vec; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng}, + cogs::{ + rng::{Event, IndexUsize}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -17,7 +20,11 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemorySeparableAliasDispersalSampler, G: Rng> { +pub struct InMemorySeparableAliasDispersalSampler, G: Rng> +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ alias_dispersal: Array2D>>, self_dispersal: Array2D, _marker: PhantomData<(M, H, G)>, @@ -26,6 +33,9 @@ pub struct InMemorySeparableAliasDispersalSampler, G #[contract_trait] impl, G: Rng> InMemoryDispersalSampler for InMemorySeparableAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { /// Creates a new `InMemorySeparableAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -114,6 +124,9 @@ impl, G: Rng> InMemoryDispersalSampler #[contract_trait] impl, G: Rng> Backup for InMemorySeparableAliasDispersalSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index 6f20be60a..f8c442481 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -19,8 +19,8 @@ use crate::cogs::{ #[cfg_attr(feature = "cuda", cuda(free = "M"))] pub struct SpatiallyImplicitDispersalSampler> where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[cfg_attr(feature = "cuda", cuda(embed))] local: NonSpatialDispersalSampler, @@ -31,8 +31,8 @@ where impl> SpatiallyImplicitDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] pub fn new(local_migration_probability_per_generation: PositiveUnitF64) -> Self { @@ -47,8 +47,8 @@ where #[contract_trait] impl> Backup for SpatiallyImplicitDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -64,8 +64,8 @@ where impl> DispersalSampler, G> for SpatiallyImplicitDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -109,8 +109,8 @@ where impl> SeparableDispersalSampler, G> for SpatiallyImplicitDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs index 4fbc4873c..969a16cd7 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs @@ -5,8 +5,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, Backup, EmigrationExit, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, + coalescence_sampler::CoalescenceRngSample, rng::UniformClosedOpenUnit, Backup, + DistributionSampler, EmigrationExit, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -17,14 +17,21 @@ use crate::decomposition::Decomposition; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct DomainEmigrationExit, C: Decomposition> { +pub struct DomainEmigrationExit, G: Rng, C: Decomposition> +where + G::Sampler: DistributionSampler, +{ decomposition: C, emigrants: Vec<(u32, MigratingLineage)>, - _marker: PhantomData<(M, H)>, + _marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, C: Decomposition> Backup for DomainEmigrationExit { +impl, G: Rng, C: Decomposition> Backup + for DomainEmigrationExit +where + G::Sampler: DistributionSampler, +{ unsafe fn backup_unchecked(&self) -> Self { Self { decomposition: self.decomposition.backup_unchecked(), @@ -35,7 +42,7 @@ impl, C: Decomposition> Backup for DomainEmigr (*partition, migrating_lineage.backup_unchecked()) }) .collect(), - _marker: PhantomData::<(M, H)>, + _marker: PhantomData::<(M, H, G)>, } } } @@ -47,7 +54,9 @@ impl< C: Decomposition, G: Rng, S: LocallyCoherentLineageStore, - > EmigrationExit for DomainEmigrationExit + > EmigrationExit for DomainEmigrationExit +where + G::Sampler: DistributionSampler, { #[must_use] #[debug_ensures(ret.is_some() == ( @@ -106,13 +115,17 @@ impl< } } -impl, C: Decomposition> DomainEmigrationExit { +impl, G: Rng, C: Decomposition> + DomainEmigrationExit +where + G::Sampler: DistributionSampler, +{ #[must_use] pub fn new(decomposition: C) -> Self { Self { decomposition, emigrants: Vec::new(), - _marker: PhantomData::<(M, H)>, + _marker: PhantomData::<(M, H, G)>, } } @@ -125,8 +138,10 @@ impl, C: Decomposition> DomainEmigrationExit, C: Decomposition> Iterator - for DomainEmigrationExit +impl, G: Rng, C: Decomposition> Iterator + for DomainEmigrationExit +where + G::Sampler: DistributionSampler, { type Item = (u32, MigratingLineage); diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs index 42a6a868a..661d30b8b 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs @@ -2,7 +2,8 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, Backup, EmigrationExit, Habitat, MathsCore, Rng, + coalescence_sampler::CoalescenceRngSample, rng::UniformClosedOpenUnit, Backup, + DistributionSampler, EmigrationExit, Habitat, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -22,18 +23,23 @@ use choice::EmigrationChoice; pub struct IndependentEmigrationExit< M: MathsCore, H: Habitat, + G: Rng, C: Decomposition, E: EmigrationChoice, -> { +> where + G::Sampler: DistributionSampler, +{ decomposition: C, choice: E, emigrant: Option<(u32, MigratingLineage)>, - _marker: PhantomData<(M, H)>, + _marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, C: Decomposition, E: EmigrationChoice> Backup - for IndependentEmigrationExit +impl, G: Rng, C: Decomposition, E: EmigrationChoice> + Backup for IndependentEmigrationExit +where + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -45,15 +51,17 @@ impl, C: Decomposition, E: EmigrationChoice, + _marker: PhantomData::<(M, H, G)>, } } } #[contract_trait] -impl, C: Decomposition, E: EmigrationChoice, G: Rng> +impl, G: Rng, C: Decomposition, E: EmigrationChoice> EmigrationExit> - for IndependentEmigrationExit + for IndependentEmigrationExit +where + G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -126,8 +134,10 @@ impl, C: Decomposition, E: EmigrationChoice, C: Decomposition, E: EmigrationChoice> - IndependentEmigrationExit +impl, G: Rng, C: Decomposition, E: EmigrationChoice> + IndependentEmigrationExit +where + G::Sampler: DistributionSampler, { #[must_use] pub fn new(decomposition: C, choice: E) -> Self { @@ -135,7 +145,7 @@ impl, C: Decomposition, E: EmigrationChoice, + _marker: PhantomData::<(M, H, G)>, } } diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/never.rs b/necsim/impls/no-std/src/cogs/emigration_exit/never.rs index d24934c67..0e5f2e7ec 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/never.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/never.rs @@ -19,12 +19,8 @@ impl Backup for NeverEmigrationExit { } #[contract_trait] -impl< - M: MathsCore, - H: Habitat, - G: Rng, - S: LineageStore, - > EmigrationExit for NeverEmigrationExit +impl, G: Rng, S: LineageStore> EmigrationExit + for NeverEmigrationExit { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs index dab070974..39c5d85db 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs @@ -2,10 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, - CoalescenceSampler, EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, - MathsCore, Rng, SeparableDispersalSampler, SpeciationProbability, - TurnoverRate, + coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, + rng::UniformClosedOpenUnit, Backup, CoalescenceSampler, DistributionSampler, + EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, + SeparableDispersalSampler, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -34,7 +34,9 @@ pub struct ConditionalGillespieEventSampler< D: SeparableDispersalSampler, T: TurnoverRate, N: SpeciationProbability, -> { +> where + G::Sampler: DistributionSampler, +{ #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, T, N)>, } @@ -49,6 +51,8 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for ConditionalGillespieEventSampler +where + G::Sampler: DistributionSampler, { fn default() -> Self { Self { @@ -68,6 +72,8 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for ConditionalGillespieEventSampler +where + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -88,6 +94,8 @@ impl< N: SpeciationProbability, > EventSampler, T, N> for ConditionalGillespieEventSampler +where + G::Sampler: DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< @@ -135,7 +143,7 @@ impl< false, ); - let event_sample = probability_at_location.total() * rng.sample_uniform_closed_open(); + let event_sample = probability_at_location.total() * rng.sample::(); if event_sample < probability_at_location.speciation() { // Speciation Event @@ -240,6 +248,8 @@ impl< N: SpeciationProbability, > GillespieEventSampler, T, N> for ConditionalGillespieEventSampler +where + G::Sampler: DistributionSampler, { #[must_use] fn get_event_rate_at_location( diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs index 18e191eae..ae82c49b9 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/probability.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - GloballyCoherentLineageStore, Habitat, MathsCore, Rng, - SeparableDispersalSampler, SpeciationProbability, + GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SeparableDispersalSampler, + SpeciationProbability, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs index 5a79a1626..577e068d5 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/mod.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index 60f73d73e..07eb9c646 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -2,10 +2,12 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - GloballyCoherentLineageStore, Habitat, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + coalescence_sampler::CoalescenceRngSample, + event_sampler::EventHandler, + rng::{Event, UniformClosedOpenUnit}, + Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, + EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SpeciationProbability, + TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -28,7 +30,10 @@ pub struct UnconditionalGillespieEventSampler< C: CoalescenceSampler, T: TurnoverRate, N: SpeciationProbability, -> { +> where + G::Sampler: DistributionSampler + + DistributionSampler, +{ #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, C, T, N)>, } @@ -44,6 +49,9 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for UnconditionalGillespieEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { fn default() -> Self { Self { @@ -64,6 +72,9 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for UnconditionalGillespieEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -85,6 +96,9 @@ impl< N: SpeciationProbability, > EventSampler for UnconditionalGillespieEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< @@ -110,7 +124,7 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - if rng.sample_event( + if rng.sample_with::( simulation .speciation_probability .get_speciation_probability_at_location( @@ -192,6 +206,9 @@ impl< N: SpeciationProbability, > GillespieEventSampler for UnconditionalGillespieEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn get_event_rate_at_location( diff --git a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs index b70a5ea73..6592ebdf8 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs @@ -2,9 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, MathsCore, - Rng, SpeciationProbability, TurnoverRate, + coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, + rng::UniformClosedOpenUnit, Backup, CoalescenceSampler, DispersalSampler, + DistributionSampler, EmigrationExit, EventSampler, Habitat, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -42,7 +43,9 @@ pub struct IndependentEventSampler< D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, -> { +> where + G::Sampler: DistributionSampler, +{ #[cfg_attr( feature = "cuda", cuda( @@ -62,6 +65,8 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for IndependentEventSampler +where + G::Sampler: DistributionSampler, { fn default() -> Self { Self { @@ -81,6 +86,8 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for IndependentEventSampler +where + G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -111,6 +118,8 @@ impl< T, N, > for IndependentEventSampler +where + G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -147,7 +156,7 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - let speciation_sample = rng.sample_uniform_closed_open(); + let speciation_sample = rng.sample::(); SpeciationSample::update_min( &mut self.min_spec_sample, @@ -245,6 +254,8 @@ impl< T, N, > for IndependentEventSampler +where + G::Sampler: DistributionSampler, { fn replace_min_speciation( &mut self, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs b/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs index 5b825f178..2ab61dd71 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/tracking.rs @@ -4,8 +4,8 @@ use necsim_core_bond::{ClosedOpenUnitF64, PositiveF64}; use necsim_core::{ cogs::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, landscape::IndexedLocation, }; diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index 7c97b3423..2b6da1505 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -2,9 +2,11 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, Backup, - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + coalescence_sampler::CoalescenceRngSample, + event_sampler::EventHandler, + rng::{Event, UniformClosedOpenUnit}, + Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, + EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, @@ -25,7 +27,10 @@ pub struct UnconditionalEventSampler< C: CoalescenceSampler, T: TurnoverRate, N: SpeciationProbability, -> { +> where + G::Sampler: DistributionSampler + + DistributionSampler, +{ #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, C, T, N)>, } @@ -41,6 +46,9 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for UnconditionalEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { fn default() -> Self { Self { @@ -61,6 +69,9 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for UnconditionalEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -82,6 +93,9 @@ impl< N: SpeciationProbability, > EventSampler for UnconditionalEventSampler +where + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< @@ -107,7 +121,7 @@ impl< }: EventHandler, auxiliary: Aux, ) -> Q { - if rng.sample_event( + if rng.sample_with::( simulation .speciation_probability .get_speciation_probability_at_location( diff --git a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs index f611f629a..146b8ed81 100644 --- a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs +++ b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs @@ -5,7 +5,10 @@ use alloc::{boxed::Box, vec::Vec}; use r#final::Final; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, + cogs::{ + rng::{IndexU64, Length}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, UniformlySampleableHabitat, + }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -106,11 +109,15 @@ impl Habitat for InMemoryHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for InMemoryHabitat { +impl> UniformlySampleableHabitat for InMemoryHabitat +where + G::Sampler: DistributionSampler, +{ #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { - let indexed_location_index = rng.sample_index_u64(self.get_total_habitat().into()); + let indexed_location_index = + rng.sample_with::(Length(self.get_total_habitat().into())); let location_index = match self.u64_injection.binary_search(&indexed_location_index) { Ok(index) => index, diff --git a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs index 5a7189ff4..03d421a42 100644 --- a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs @@ -4,7 +4,10 @@ use core::{ }; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, + cogs::{ + rng::{IndexU64, Length}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, UniformlySampleableHabitat, + }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -116,7 +119,10 @@ impl Habitat for NonSpatialHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for NonSpatialHabitat { +impl> UniformlySampleableHabitat for NonSpatialHabitat +where + G::Sampler: DistributionSampler, +{ #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { @@ -124,8 +130,9 @@ impl> UniformlySampleableHabitat for NonSpatialHab self.extent.width().get() * self.extent.height().get() * u64::from(self.deme.get()); // Safety: habitat width, height, and deme are all > 0 - let mut dispersal_target_index = - rng.sample_index_u64(unsafe { NonZeroU64::new_unchecked(habitat_index_max) }); + let mut dispersal_target_index = rng.sample_with::(Length(unsafe { + NonZeroU64::new_unchecked(habitat_index_max) + })); #[allow(clippy::cast_possible_truncation)] let index = (dispersal_target_index % u64::from(self.deme.get())) as u32; dispersal_target_index /= u64::from(self.deme.get()); diff --git a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs index 80f7812da..e029edf6c 100644 --- a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs @@ -1,7 +1,10 @@ use core::num::NonZeroU32; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, + cogs::{ + rng::IndexU64, Backup, DistributionSampler, Habitat, MathsCore, Rng, + UniformlySampleableHabitat, + }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -128,7 +131,10 @@ impl Habitat for SpatiallyImplicitHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for SpatiallyImplicitHabitat { +impl> UniformlySampleableHabitat for SpatiallyImplicitHabitat +where + G::Sampler: DistributionSampler, +{ #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { diff --git a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs index 9498a714c..a442883df 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, + PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::Reporter, @@ -84,7 +84,10 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) { +) +where + G::Sampler: DistributionSampler, +{ let mut lineages = VecDeque::from_iter(lineages); let mut proxy = IgnoreProgressReporterProxy::from(local_partition); let mut min_spec_samples = dedup_cache.construct(lineages.len()); diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index ff7d0808a..292e6f78f 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, + PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, event::DispersalEvent, landscape::IndexedLocation, @@ -54,12 +54,12 @@ pub fn simulate< H, G, IndependentLineageStore, - IndependentEmigrationExit, + IndependentEmigrationExit, D, IndependentCoalescenceSampler, T, N, - IndependentEventSampler, D, T, N>, + IndependentEventSampler, D, T, N>, NeverImmigrationEntry, >, R: Reporter, @@ -71,12 +71,12 @@ pub fn simulate< H, G, IndependentLineageStore, - IndependentEmigrationExit, + IndependentEmigrationExit, D, IndependentCoalescenceSampler, T, N, - IndependentEventSampler, D, T, N>, + IndependentEventSampler, D, T, N>, NeverImmigrationEntry, A, >, @@ -89,7 +89,10 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) { +) +where + G::Sampler: DistributionSampler, +{ let mut lineages = VecDeque::from_iter(lineages); let mut proxy = IgnoreProgressReporterProxy::from(local_partition); let mut min_spec_samples = dedup_cache.construct(lineages.len()); diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs index e543487a6..b7508aaf1 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs @@ -8,8 +8,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - DispersalSampler, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, + PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::{boolean::Boolean, Reporter}, @@ -91,7 +91,10 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) { +) +where + G::Sampler: DistributionSampler, +{ let mut slow_lineages = lineages .into_iter() .map(|lineage| { diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs index b9149241e..c535f74b9 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs @@ -2,9 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, + DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, reporter::Reporter, simulation::Simulation, @@ -34,13 +34,13 @@ pub fn simulate< T: TurnoverRate, N: SpeciationProbability, O: Decomposition, - E: EventSampler, D, C, T, N>, + E: EventSampler, D, C, T, N>, A: ActiveLineageSampler< M, H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -56,7 +56,7 @@ pub fn simulate< H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -67,7 +67,10 @@ pub fn simulate< >, independent_time_slice: PositiveF64, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) { +) -> (Status, NonNegativeF64, u64) +where + G::Sampler: DistributionSampler, +{ // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs index 0fac89dfe..deebee9a9 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs @@ -2,9 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, + DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + SpeciationProbability, TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -34,13 +34,13 @@ pub fn simulate< T: TurnoverRate, N: SpeciationProbability, O: Decomposition, - E: EventSampler, D, C, T, N>, + E: EventSampler, D, C, T, N>, A: ActiveLineageSampler< M, H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -56,7 +56,7 @@ pub fn simulate< H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -66,7 +66,10 @@ pub fn simulate< A, >, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) { +) -> (Status, NonNegativeF64, u64) +where + G::Sampler: DistributionSampler, +{ // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs index feffe1fef..38df79c17 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/monolithic.rs @@ -3,8 +3,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, reporter::Reporter, simulation::Simulation, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs index 553fcb735..3924e6ffd 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs @@ -3,9 +3,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - backup::BackedUp, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, - EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + backup::BackedUp, rng::UniformClosedOpenUnit, ActiveLineageSampler, Backup, + CoalescenceSampler, DispersalSampler, DistributionSampler, EventSampler, Habitat, + LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, lineage::MigratingLineage, reporter::Reporter, @@ -38,13 +38,13 @@ pub fn simulate< T: TurnoverRate, N: SpeciationProbability, O: Decomposition, - E: EventSampler, D, C, T, N>, + E: EventSampler, D, C, T, N>, A: ActiveLineageSampler< M, H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -60,7 +60,7 @@ pub fn simulate< H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -71,7 +71,10 @@ pub fn simulate< >, independent_time_slice: PositiveF64, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) { +) -> (Status, NonNegativeF64, u64) +where + G::Sampler: DistributionSampler, +{ // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs index 0930e18f7..acc862bf6 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs @@ -2,9 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + rng::UniformClosedOpenUnit, ActiveLineageSampler, Backup, CoalescenceSampler, + DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -34,13 +34,13 @@ pub fn simulate< T: TurnoverRate, N: SpeciationProbability, O: Decomposition, - E: EventSampler, D, C, T, N>, + E: EventSampler, D, C, T, N>, A: ActiveLineageSampler< M, H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -56,7 +56,7 @@ pub fn simulate< H, G, S, - DomainEmigrationExit, + DomainEmigrationExit, D, C, T, @@ -66,7 +66,10 @@ pub fn simulate< A, >, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) { +) -> (Status, NonNegativeF64, u64) +where + G::Sampler: DistributionSampler, +{ // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/std/src/cogs/dispersal_sampler/in_memory/mod.rs b/necsim/impls/std/src/cogs/dispersal_sampler/in_memory/mod.rs index e58acd679..3ebb85ce8 100644 --- a/necsim/impls/std/src/cogs/dispersal_sampler/in_memory/mod.rs +++ b/necsim/impls/std/src/cogs/dispersal_sampler/in_memory/mod.rs @@ -1,4 +1,4 @@ -use necsim_core::cogs::{Habitat, MathsCore, RngCore}; +use necsim_core::cogs::{Habitat, MathsCore, Rng}; use necsim_impls_no_std::array2d::Array2D; pub mod error; @@ -13,7 +13,7 @@ use necsim_impls_no_std::cogs::dispersal_sampler::in_memory::{ #[allow(clippy::module_name_repetitions)] #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait InMemoryDispersalSampler, G: RngCore>: +pub trait InMemoryDispersalSampler, G: Rng>: InMemoryDispersalSamplerNoError + Sized { #[debug_ensures( @@ -40,7 +40,7 @@ pub trait InMemoryDispersalSampler, G: RngCore>: } #[contract_trait] -impl, G: RngCore, T: InMemoryDispersalSamplerNoError> +impl, G: Rng, T: InMemoryDispersalSamplerNoError> InMemoryDispersalSampler for T { /// Creates a new `T` from the `dispersal` map and extent of the habitat diff --git a/necsim/impls/std/src/cogs/rng/pcg.rs b/necsim/impls/std/src/cogs/rng/pcg.rs index 23f5d3d68..81664a89f 100644 --- a/necsim/impls/std/src/cogs/rng/pcg.rs +++ b/necsim/impls/std/src/cogs/rng/pcg.rs @@ -1,29 +1,27 @@ -use std::{fmt, marker::PhantomData}; +use std::fmt; use pcg_rand::{seeds::PcgSeeder, PCGStateInfo, Pcg64}; use rand_core::{RngCore as _, SeedableRng}; use serde::{Deserialize, Serialize}; -use necsim_core::cogs::{MathsCore, RngCore, SplittableRng}; +use necsim_core::cogs::{RngCore, SplittableRng}; #[allow(clippy::module_name_repetitions)] #[derive(Serialize, Deserialize)] #[serde(from = "PcgState", into = "PcgState")] -pub struct Pcg { +pub struct Pcg { inner: Pcg64, - marker: PhantomData, } -impl Clone for Pcg { +impl Clone for Pcg { fn clone(&self) -> Self { Self { inner: Pcg64::restore_state_with_no_verification(self.inner.get_state()), - marker: PhantomData::, } } } -impl fmt::Debug for Pcg { +impl fmt::Debug for Pcg { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let state = self.inner.get_state(); @@ -34,7 +32,7 @@ impl fmt::Debug for Pcg { } } -impl RngCore for Pcg { +impl RngCore for Pcg { type Seed = [u8; 16]; #[must_use] @@ -45,7 +43,6 @@ impl RngCore for Pcg { u128::from_le_bytes(seed), 0_u128, )), - marker: PhantomData::, } } @@ -56,7 +53,7 @@ impl RngCore for Pcg { } } -impl SplittableRng for Pcg { +impl SplittableRng for Pcg { #[allow(clippy::identity_op)] fn split(self) -> (Self, Self) { let mut left_state = self.inner.get_state(); @@ -67,11 +64,9 @@ impl SplittableRng for Pcg { let left = Self { inner: Pcg64::restore_state_with_no_verification(left_state), - marker: PhantomData::, }; let right = Self { inner: Pcg64::restore_state_with_no_verification(right_state), - marker: PhantomData::, }; (left, right) @@ -83,7 +78,6 @@ impl SplittableRng for Pcg { Self { inner: Pcg64::restore_state_with_no_verification(state), - marker: PhantomData::, } } } @@ -96,8 +90,8 @@ struct PcgState { increment: u128, } -impl From> for PcgState { - fn from(rng: Pcg) -> Self { +impl From for PcgState { + fn from(rng: Pcg) -> Self { let state_info = rng.inner.get_state(); Self { @@ -107,7 +101,7 @@ impl From> for PcgState { } } -impl From for Pcg { +impl From for Pcg { fn from(state: PcgState) -> Self { use pcg_rand::{ multiplier::{DefaultMultiplier, Multiplier}, @@ -125,7 +119,6 @@ impl From for Pcg { Self { inner: Pcg64::restore_state_with_no_verification(state_info), - marker: PhantomData::, } } } From 0f40f71f8188b0021613974494e409225f148880 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Wed, 18 May 2022 12:55:02 +0000 Subject: [PATCH 06/21] It compiles? --- necsim/core/src/cogs/rng.rs | 109 ++++++++++++- necsim/impls/cuda/src/cogs/rng.rs | 9 ++ .../alias/sampler/indexed/tests.rs | 4 + .../alias/sampler/stack/tests.rs | 4 + .../algorithms/cuda/cpu-kernel/src/lib.rs | 9 +- .../algorithms/cuda/cpu-kernel/src/link.rs | 81 ++++++---- .../algorithms/cuda/cpu-kernel/src/patch.rs | 4 +- .../algorithms/cuda/gpu-kernel/src/lib.rs | 5 +- .../algorithms/cuda/src/initialiser/fixup.rs | 10 +- .../cuda/src/initialiser/genesis.rs | 10 +- .../algorithms/cuda/src/initialiser/mod.rs | 10 +- .../algorithms/cuda/src/initialiser/resume.rs | 10 +- rustcoalescence/algorithms/cuda/src/launch.rs | 36 +++-- rustcoalescence/algorithms/cuda/src/lib.rs | 144 +++++++++++++----- .../cuda/src/parallelisation/monolithic.rs | 4 +- .../src/event_skipping/initialiser/fixup.rs | 13 +- .../src/event_skipping/initialiser/genesis.rs | 13 +- .../src/event_skipping/initialiser/mod.rs | 10 +- .../src/event_skipping/initialiser/resume.rs | 14 +- .../gillespie/src/event_skipping/launch.rs | 14 +- .../gillespie/src/event_skipping/mod.rs | 17 ++- .../gillespie/classical/initialiser/fixup.rs | 13 +- .../classical/initialiser/genesis.rs | 15 +- .../gillespie/classical/initialiser/mod.rs | 16 +- .../gillespie/classical/initialiser/resume.rs | 13 +- .../src/gillespie/classical/launch.rs | 15 +- .../gillespie/src/gillespie/classical/mod.rs | 4 +- .../gillespie/turnover/initialiser/fixup.rs | 13 +- .../gillespie/turnover/initialiser/genesis.rs | 15 +- .../src/gillespie/turnover/initialiser/mod.rs | 16 +- .../gillespie/turnover/initialiser/resume.rs | 13 +- .../src/gillespie/turnover/launch.rs | 15 +- .../gillespie/src/gillespie/turnover/mod.rs | 13 +- .../algorithms/gillespie/src/lib.rs | 1 + .../independent/src/initialiser/fixup.rs | 17 ++- .../independent/src/initialiser/genesis.rs | 11 +- .../independent/src/initialiser/mod.rs | 12 +- .../independent/src/initialiser/resume.rs | 17 ++- .../algorithms/independent/src/launch.rs | 15 +- .../algorithms/independent/src/lib.rs | 18 ++- rustcoalescence/algorithms/src/lib.rs | 4 +- rustcoalescence/algorithms/src/result.rs | 4 +- .../scenarios/src/almost_infinite.rs | 19 ++- rustcoalescence/scenarios/src/lib.rs | 4 +- rustcoalescence/scenarios/src/non_spatial.rs | 19 ++- .../src/spatially_explicit/turnover/map.rs | 19 ++- .../spatially_explicit/turnover/uniform.rs | 19 ++- .../scenarios/src/spatially_implicit.rs | 23 ++- rustcoalescence/src/args/config/rng/mod.rs | 22 +-- .../src/cli/simulate/dispatch/valid/rng.rs | 12 +- rustcoalescence/src/cli/simulate/parse/rng.rs | 12 +- 51 files changed, 693 insertions(+), 246 deletions(-) diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index 3a0130ea9..ce282cc5c 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -111,6 +111,9 @@ pub trait Rng: RngCore { #[must_use] fn generator(&mut self) -> &mut Self::Generator; + #[must_use] + fn map_generator Self::Generator>(self, map: F) -> Self; + #[must_use] fn sample_with(&mut self, params: D::Parameters) -> D::Sample where @@ -223,11 +226,12 @@ impl Distribution for Normal2D { type Sample = (f64, f64); } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, TypeLayout)] +#[layout(free = "M")] #[allow(clippy::module_name_repetitions)] pub struct SimpleRng { inner: R, - _marker: PhantomData, + marker: PhantomData, } impl Serialize for SimpleRng { @@ -242,7 +246,7 @@ impl<'de, M: MathsCore, R: RngCore> Deserialize<'de> for SimpleRng { Ok(Self { inner, - _marker: PhantomData::, + marker: PhantomData::, }) } } @@ -252,7 +256,7 @@ impl crate::cogs::Backup for SimpleRng { unsafe fn backup_unchecked(&self) -> Self { Self { inner: self.inner.backup_unchecked(), - _marker: PhantomData::, + marker: PhantomData::, } } } @@ -264,7 +268,7 @@ impl RngCore for SimpleRng { fn from_seed(seed: Self::Seed) -> Self { Self { inner: R::from_seed(seed), - _marker: PhantomData::, + marker: PhantomData::, } } @@ -282,6 +286,15 @@ impl Rng for SimpleRng { &mut self.inner } + fn map_generator Self::Generator>(self, map: F) -> Self { + let SimpleRng { inner, marker } = self; + + SimpleRng { + inner: map(inner), + marker, + } + } + fn sample_with(&mut self, params: D::Parameters) -> D::Sample where Self::Sampler: DistributionSampler, @@ -436,6 +449,92 @@ impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> NonNegativeF64 { + let lambda = params.0; + + let u01: OpenClosedUnitF64 = samplers.sample(rng, samplers); + + // Inverse transform sample: X = -ln(U(0,1]) / lambda + -u01.ln::() / lambda + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: ClosedUnitF64) -> bool { + let probability = params; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + // if probability == 1, then U[0, 1) always < 1.0 + // if probability == 0, then U[0, 1) never < 0.0 + u01 < probability + } +} + +#[allow(clippy::trait_duplication_in_bounds)] +impl< + M: MathsCore, + R: RngCore, + S: DistributionSampler + + DistributionSampler, + > DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { + // Basic Box-Muller transform + let u0 = + DistributionSampler::::sample(samplers, rng, samplers); + let u1 = + DistributionSampler::::sample(samplers, rng, samplers); + + let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); + let theta = -core::f64::consts::TAU * u1.get(); + + (r * M::sin(theta), r * M::cos(theta)) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { + let (z0, z1) = samplers.sample(rng, samplers); + + ( + z0 * params.sigma.get() + params.mu, + z1 * params.sigma.get() + params.mu, + ) + } +} + /*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[allow(clippy::module_name_repetitions)] #[contract_trait] diff --git a/necsim/impls/cuda/src/cogs/rng.rs b/necsim/impls/cuda/src/cogs/rng.rs index af411f60e..6f04b14e2 100644 --- a/necsim/impls/cuda/src/cogs/rng.rs +++ b/necsim/impls/cuda/src/cogs/rng.rs @@ -67,6 +67,15 @@ impl + StackOnly + ~const TypeGraphLayout> Rng for Cu self.inner.generator() } + fn map_generator Self::Generator>(self, map: F) -> Self { + let CudaRng { inner, marker } = self; + + CudaRng { + inner: inner.map_generator(map), + marker, + } + } + fn sample_with(&mut self, params: D::Parameters) -> D::Sample where Self::Sampler: DistributionSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index c866a6886..81bd218de 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1116,6 +1116,10 @@ impl Rng for DummyRng { self } + fn map_generator Self::Generator>(self, map: F) -> Self { + map(self) + } + fn sample_with(&mut self, params: D::Parameters) -> D::Sample where Self::Sampler: DistributionSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 06ff6339c..f9486183d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -615,6 +615,10 @@ impl Rng for DummyRng { self } + fn map_generator Self::Generator>(self, map: F) -> Self { + map(self) + } + fn sample_with(&mut self, params: D::Parameters) -> D::Sample where Self::Sampler: DistributionSampler, diff --git a/rustcoalescence/algorithms/cuda/cpu-kernel/src/lib.rs b/rustcoalescence/algorithms/cuda/cpu-kernel/src/lib.rs index 5436bea05..1caa2d456 100644 --- a/rustcoalescence/algorithms/cuda/cpu-kernel/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/cpu-kernel/src/lib.rs @@ -1,13 +1,14 @@ #![deny(clippy::pedantic)] #![feature(const_eval_limit)] #![const_eval_limit = "1000000000000"] +#![feature(associated_type_bounds)] #![allow(incomplete_features)] #![feature(specialization)] use necsim_core::{ cogs::{ CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LineageStore, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + LineageStore, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, reporter::boolean::Boolean, }; @@ -38,7 +39,7 @@ pub type KernelCompilationCallback = dyn FnMut(&Function) -> CudaResult<()>; pub struct SimulationKernel< M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, @@ -80,7 +81,7 @@ pub struct SimulationKernel< impl< M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, @@ -139,7 +140,7 @@ impl< impl< M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs index 98f3b0819..255da478e 100644 --- a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs +++ b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs @@ -34,8 +34,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::lineage_store::independent::IndependentLineageStore< @@ -55,9 +56,10 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore, - >, + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, + >, >, necsim_impls_no_std::cogs::emigration_exit::never::NeverEmigrationExit, $dispersal, @@ -70,8 +72,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< + necsim_core::cogs::rng::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::emigration_exit::never::NeverEmigrationExit, @@ -89,8 +92,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::lineage_store::independent::IndependentLineageStore< @@ -103,8 +107,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, $dispersal, @@ -113,8 +118,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -130,8 +136,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< + necsim_core::cogs::rng::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::emigration_exit::never::NeverEmigrationExit, @@ -140,8 +147,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, $dispersal, @@ -150,8 +158,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -165,8 +174,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< + necsim_core::cogs::rng::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::emigration_exit::never::NeverEmigrationExit, @@ -175,8 +185,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, $dispersal, @@ -185,8 +196,9 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -209,8 +221,9 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -226,8 +239,9 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -243,8 +257,9 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -263,8 +278,9 @@ link_kernel!( >, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, @@ -283,8 +299,9 @@ link_kernel!( >, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore + necsim_core::cogs::rng::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, >, diff --git a/rustcoalescence/algorithms/cuda/cpu-kernel/src/patch.rs b/rustcoalescence/algorithms/cuda/cpu-kernel/src/patch.rs index 129565624..f0d63342c 100644 --- a/rustcoalescence/algorithms/cuda/cpu-kernel/src/patch.rs +++ b/rustcoalescence/algorithms/cuda/cpu-kernel/src/patch.rs @@ -3,7 +3,7 @@ use std::sync::atomic::AtomicU64; use necsim_core::{ cogs::{ CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LineageStore, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + LineageStore, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::boolean::{Boolean, False, True}, @@ -40,7 +40,7 @@ extern "C" { unsafe impl< M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/gpu-kernel/src/lib.rs b/rustcoalescence/algorithms/cuda/gpu-kernel/src/lib.rs index 53299dc7b..24cf141e0 100644 --- a/rustcoalescence/algorithms/cuda/gpu-kernel/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/gpu-kernel/src/lib.rs @@ -2,6 +2,7 @@ #![no_std] #![feature(const_eval_limit)] #![const_eval_limit = "1000000000000"] +#![feature(associated_type_bounds)] #![cfg_attr(target_os = "cuda", feature(abi_ptx))] #![cfg_attr(target_os = "cuda", feature(alloc_error_handler))] #![cfg_attr(target_os = "cuda", feature(panic_info_message))] @@ -18,7 +19,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LineageStore, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + LineageStore, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, reporter::boolean::Boolean, }; @@ -38,7 +39,7 @@ use rust_cuda::common::RustToCuda; pub fn simulate< M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs index 4e91831cc..ab03e1758 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -43,7 +46,7 @@ pub struct FixUpInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, O: Scenario, > CudaLineageStoreSampleInitialiser> for FixUpInitialiser where @@ -51,6 +54,9 @@ where O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs index 5f851c286..499f2d0f4 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; @@ -23,13 +26,16 @@ use super::CudaLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl + RustToCuda, O: Scenario> +impl + RustToCuda, O: Scenario> CudaLineageStoreSampleInitialiser for GenesisInitialiser where O::Habitat: RustToCuda, O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs index a1a39e87e..09f931146 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{DispersalSampler, EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; @@ -28,7 +31,7 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait CudaLineageStoreSampleInitialiser< M: MathsCore, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, O: Scenario, Error: From, > where @@ -36,6 +39,9 @@ pub trait CudaLineageStoreSampleInitialiser< O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type DispersalSampler: DispersalSampler + RustToCuda; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs index 2cba7640b..417bbb08e 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; use necsim_core_bond::NonNegativeF64; @@ -32,7 +35,7 @@ pub struct ResumeInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, O: Scenario, > CudaLineageStoreSampleInitialiser> for ResumeInitialiser where @@ -40,6 +43,9 @@ where O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index 40fd18f7b..90cbc9350 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -1,6 +1,10 @@ use std::marker::PhantomData; -use necsim_core::{cogs::MathsCore, reporter::Reporter, simulation::SimulationBuilder}; +use necsim_core::{ + cogs::{rng::SimpleRng, MathsCore}, + reporter::Reporter, + simulation::SimulationBuilder, +}; use necsim_core_bond::NonNegativeF64; use necsim_impls_cuda::cogs::rng::CudaRng; @@ -46,35 +50,36 @@ use crate::{ parallelisation, }; -#[allow(clippy::too_many_lines)] +#[allow(clippy::too_many_lines, clippy::type_complexity)] pub fn initialise_and_simulate< 'p, M: MathsCore, - O: Scenario>>, + O: Scenario>>, R: Reporter, P: LocalPartition<'p, R>, I: Iterator, - L: CudaLineageStoreSampleInitialiser>, O, Error>, + L: CudaLineageStoreSampleInitialiser>, O, Error>, Error: From, >( args: &CudaArguments, - rng: CudaRng>, + rng: CudaRng>, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result>>, Error> +) -> Result>>, Error> where O::Habitat: RustToCuda, - O::DispersalSampler>>>: - RustToCuda, + O::DispersalSampler< + InMemoryPackedAliasDispersalSampler>>, + >: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, SimulationKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, L::DispersalSampler, @@ -84,7 +89,7 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, L::DispersalSampler, O::TurnoverRate, @@ -97,7 +102,7 @@ where >: SimulatableKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, L::DispersalSampler, @@ -107,7 +112,7 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, L::DispersalSampler, O::TurnoverRate, @@ -126,8 +131,11 @@ where speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario - .build::>>>(); + ) = scenario.build::>, + >>(); let coalescence_sampler = IndependentCoalescenceSampler::default(); let event_sampler = IndependentEventSampler::default(); diff --git a/rustcoalescence/algorithms/cuda/src/lib.rs b/rustcoalescence/algorithms/cuda/src/lib.rs index e2c221dca..a88d58a51 100644 --- a/rustcoalescence/algorithms/cuda/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/src/lib.rs @@ -1,11 +1,16 @@ #![deny(clippy::pedantic)] +#![feature(associated_type_bounds)] #![allow(incomplete_features)] #![feature(inline_const_pat)] #[macro_use] extern crate serde_derive_state; -use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; +use necsim_core::{ + cogs::{rng::SimpleRng, MathsCore}, + lineage::Lineage, + reporter::Reporter, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_cuda::cogs::{maths::NvptxMathsCore, rng::CudaRng}; @@ -74,24 +79,25 @@ impl AlgorithmDefaults for CudaAlgorithm { impl< 'p, M: MathsCore, - O: Scenario>>, + O: Scenario>>, R: Reporter, P: LocalPartition<'p, R>, > Algorithm<'p, M, O, R, P> for CudaAlgorithm where O::Habitat: RustToCuda, - O::DispersalSampler>>>: - RustToCuda, + O::DispersalSampler< + InMemoryPackedAliasDispersalSampler>>, + >: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, SimulationKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler>>, >, IndependentCoalescenceSampler, O::TurnoverRate, @@ -99,10 +105,14 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, O::TurnoverRate, O::SpeciationProbability, @@ -111,10 +121,14 @@ where IndependentActiveLineageSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, O::TurnoverRate, O::SpeciationProbability, @@ -125,11 +139,11 @@ where >: SimulatableKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler>>, >, IndependentCoalescenceSampler, O::TurnoverRate, @@ -137,10 +151,14 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, O::TurnoverRate, O::SpeciationProbability, @@ -149,10 +167,14 @@ where IndependentActiveLineageSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, O::TurnoverRate, O::SpeciationProbability, @@ -164,17 +186,21 @@ where SimulationKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, - UniformAntiTrespassingDispersalSampler>>, + UniformAntiTrespassingDispersalSampler>>, >, IndependentCoalescenceSampler, O::TurnoverRate, @@ -182,16 +208,24 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, + >, + UniformAntiTrespassingDispersalSampler< + M, + O::Habitat, + CudaRng>, >, - UniformAntiTrespassingDispersalSampler>>, >, O::TurnoverRate, O::SpeciationProbability, @@ -200,16 +234,24 @@ where IndependentActiveLineageSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, + >, + UniformAntiTrespassingDispersalSampler< + M, + O::Habitat, + CudaRng>, >, - UniformAntiTrespassingDispersalSampler>>, >, O::TurnoverRate, O::SpeciationProbability, @@ -220,17 +262,21 @@ where >: SimulatableKernel< M, O::Habitat, - CudaRng>, + CudaRng>, IndependentLineageStore, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, >, - UniformAntiTrespassingDispersalSampler>>, + UniformAntiTrespassingDispersalSampler>>, >, IndependentCoalescenceSampler, O::TurnoverRate, @@ -238,16 +284,24 @@ where IndependentEventSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, + >, + UniformAntiTrespassingDispersalSampler< + M, + O::Habitat, + CudaRng>, >, - UniformAntiTrespassingDispersalSampler>>, >, O::TurnoverRate, O::SpeciationProbability, @@ -256,16 +310,24 @@ where IndependentActiveLineageSampler< M, O::Habitat, - CudaRng>, + CudaRng>, NeverEmigrationExit, TrespassingDispersalSampler< M, O::Habitat, - CudaRng>, + CudaRng>, O::DispersalSampler< - InMemoryPackedAliasDispersalSampler>>, + InMemoryPackedAliasDispersalSampler< + M, + O::Habitat, + CudaRng>, + >, + >, + UniformAntiTrespassingDispersalSampler< + M, + O::Habitat, + CudaRng>, >, - UniformAntiTrespassingDispersalSampler>>, >, O::TurnoverRate, O::SpeciationProbability, @@ -276,7 +338,7 @@ where >, { type LineageStore = IndependentLineageStore; - type Rng = CudaRng>; + type Rng = CudaRng>; fn get_logical_partition(args: &Self::Arguments, _local_partition: &P) -> Partition { match &args.parallelism_mode { diff --git a/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs b/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs index 66e1ff479..7b55fcb89 100644 --- a/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs +++ b/rustcoalescence/algorithms/cuda/src/parallelisation/monolithic.rs @@ -10,7 +10,7 @@ use rust_cuda::{ use necsim_core::{ cogs::{ CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LineageStore, MathsCore, PrimeableRng, SpeciationProbability, TurnoverRate, + LineageStore, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::{boolean::Boolean, Reporter}, @@ -50,7 +50,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat + RustToCuda, - G: PrimeableRng + RustToCuda, + G: Rng + RustToCuda, S: LineageStore + RustToCuda, X: EmigrationExit + RustToCuda, D: DispersalSampler + RustToCuda, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs index fcd0f20a2..1b05a8d52 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, RngCore, - SeparableDispersalSampler, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, + MathsCore, Rng, SeparableDispersalSampler, }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, @@ -45,11 +46,17 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: RngCore, O: Scenario> +impl, M: MathsCore, G: Rng, O: Scenario> EventSkippingLineageStoreSampleInitialiser> for FixUpInitialiser where O::DispersalSampler>: SeparableDispersalSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs index 079a47cd3..8229dd02c 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, RngCore, - SeparableDispersalSampler, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, + MathsCore, Rng, SeparableDispersalSampler, }, reporter::Reporter, }; @@ -22,11 +23,17 @@ use super::EventSkippingLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> +impl, O: Scenario> EventSkippingLineageStoreSampleInitialiser for GenesisInitialiser where O::DispersalSampler>: SeparableDispersalSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs index 2b14b98f9..537dc8e76 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - ActiveLineageSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, - MathsCore, RngCore, SeparableDispersalSampler, + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + ActiveLineageSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, + ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, }, reporter::Reporter, }; @@ -23,12 +24,15 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait EventSkippingLineageStoreSampleInitialiser< M: MathsCore, - G: RngCore, + G: Rng, O: Scenario, Error, > where O::DispersalSampler>: SeparableDispersalSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type DispersalSampler: SeparableDispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs index 5ae570961..a2ba351e6 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, RngCore, - SeparableDispersalSampler, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, + MathsCore, Rng, SeparableDispersalSampler, }, lineage::Lineage, reporter::Reporter, @@ -28,11 +29,18 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } -impl, M: MathsCore, G: RngCore, O: Scenario> +#[allow(clippy::type_complexity)] +impl, M: MathsCore, G: Rng, O: Scenario> EventSkippingLineageStoreSampleInitialiser> for ResumeInitialiser where O::DispersalSampler>: SeparableDispersalSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index 5fa1e4391..a8dc76277 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -2,8 +2,9 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ - ActiveLineageSampler, GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler, - SplittableRng, + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + ActiveLineageSampler, DistributionSampler, GloballyCoherentLineageStore, MathsCore, Rng, + SeparableDispersalSampler, SplittableRng, }, reporter::Reporter, simulation::SimulationBuilder, @@ -37,7 +38,7 @@ use crate::arguments::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: SplittableRng, + G: Rng, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -58,6 +59,9 @@ where GloballyCoherentLineageStore, O::DispersalSampler>: SeparableDispersalSampler, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { @@ -129,7 +133,9 @@ where } }, non_monolithic_parallelism_mode => { - let rng = rng.split_to_stream(u64::from(local_partition.get_partition().rank())); + let rng = rng.map_generator(|rng| { + rng.split_to_stream(u64::from(local_partition.get_partition().rank())) + }); let ( habitat, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs index 4dc2bfa4e..f67f83e60 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler}, + cogs::{rng::SimpleRng, GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler}, lineage::Lineage, reporter::Reporter, }; @@ -41,16 +41,21 @@ impl AlgorithmDefaults for EventSkippingAlgorithm { type MathsCore = IntrinsicsMathsCore; } -impl<'p, O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, M: MathsCore> - Algorithm<'p, M, O, R, P> for EventSkippingAlgorithm +impl< + 'p, + O: Scenario>, + R: Reporter, + P: LocalPartition<'p, R>, + M: MathsCore, + > Algorithm<'p, M, O, R, P> for EventSkippingAlgorithm where O::LineageStore>: GloballyCoherentLineageStore, - O::DispersalSampler>>: - SeparableDispersalSampler>, + O::DispersalSampler>>: + SeparableDispersalSampler>, { type LineageStore = O::LineageStore>; - type Rng = Pcg; + type Rng = SimpleRng; fn get_logical_partition(args: &Self::Arguments, local_partition: &P) -> Partition { get_gillespie_logical_partition(args, local_partition) diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index 5e6f21e03..16121c022 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -1,5 +1,9 @@ use necsim_core::{ - cogs::{EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore}, + cogs::{ + rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, + MathsCore, Rng, + }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, reporter::Reporter, @@ -43,8 +47,13 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: RngCore, O: Scenario> +impl, M: MathsCore, G: Rng, O: Scenario> ClassicalLineageStoreSampleInitialiser> for FixUpInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index 4d8529154..f6ba30fdc 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -1,5 +1,9 @@ use necsim_core::{ - cogs::{EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore}, + cogs::{ + rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, + MathsCore, Rng, + }, reporter::Reporter, }; @@ -17,8 +21,13 @@ use super::ClassicalLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> - ClassicalLineageStoreSampleInitialiser for GenesisInitialiser +impl, O: Scenario> ClassicalLineageStoreSampleInitialiser + for GenesisInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index f03b13e2a..f5226dbe3 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - ActiveLineageSampler, DispersalSampler, EmigrationExit, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, reporter::Reporter, }; @@ -21,12 +22,11 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] -pub trait ClassicalLineageStoreSampleInitialiser< - M: MathsCore, - G: RngCore, - O: Scenario, - Error, -> +pub trait ClassicalLineageStoreSampleInitialiser, O: Scenario, Error> +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type DispersalSampler: DispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index a2c313ccd..72254ed31 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -1,5 +1,9 @@ use necsim_core::{ - cogs::{EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore}, + cogs::{ + rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, + MathsCore, Rng, + }, lineage::Lineage, reporter::Reporter, }; @@ -23,8 +27,13 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } -impl, M: MathsCore, G: RngCore, O: Scenario> +impl, M: MathsCore, G: Rng, O: Scenario> ClassicalLineageStoreSampleInitialiser> for ResumeInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index e770d1d3e..5321faaa8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -1,7 +1,11 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ - cogs::{ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, SplittableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, + SplittableRng, + }, reporter::Reporter, simulation::SimulationBuilder, }; @@ -37,7 +41,7 @@ use super::initialiser::ClassicalLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: SplittableRng, + G: Rng, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -56,6 +60,9 @@ pub fn initialise_and_simulate< where O::LineageStore>: LocallyCoherentLineageStore, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { @@ -124,7 +131,9 @@ where } }, non_monolithic_parallelism_mode => { - let rng = rng.split_to_stream(u64::from(local_partition.get_partition().rank())); + let rng = rng.map_generator(|rng| { + rng.split_to_stream(u64::from(local_partition.get_partition().rank())) + }); let ( habitat, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs index 06114bca7..a2fbf3f77 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{LocallyCoherentLineageStore, MathsCore}, + cogs::{rng::SimpleRng, LocallyCoherentLineageStore, MathsCore}, lineage::Lineage, reporter::Reporter, }; @@ -31,7 +31,7 @@ use initialiser::{ // Optimised 'Classical' implementation for the `UniformTurnoverSampler` impl< 'p, - O: Scenario, TurnoverRate = UniformTurnoverRate>, + O: Scenario, TurnoverRate = UniformTurnoverRate>, R: Reporter, P: LocalPartition<'p, R>, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs index 66243468d..ed4797930 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, @@ -43,8 +44,14 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: RngCore, O: Scenario> +impl, M: MathsCore, G: Rng, O: Scenario> GillespieLineageStoreSampleInitialiser> for FixUpInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs index b3a4f8430..40704a80d 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, }, reporter::Reporter, }; @@ -20,8 +21,14 @@ use super::GillespieLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> - GillespieLineageStoreSampleInitialiser for GenesisInitialiser +impl, O: Scenario> GillespieLineageStoreSampleInitialiser + for GenesisInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs index cee39068f..eadba6dc8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs @@ -1,7 +1,9 @@ use necsim_core::{ cogs::{ - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, RngCore, + rng::{Event, IndexUsize}, + ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, + EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, + Rng, }, reporter::Reporter, }; @@ -19,12 +21,10 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] -pub trait GillespieLineageStoreSampleInitialiser< - M: MathsCore, - G: RngCore, - O: Scenario, - Error, -> +pub trait GillespieLineageStoreSampleInitialiser, O: Scenario, Error> +where + G::Sampler: DistributionSampler + + DistributionSampler, { type DispersalSampler: DispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs index 2e1264ef5..060ae98a8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, RngCore, + rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, }, lineage::Lineage, reporter::Reporter, @@ -26,8 +27,14 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } -impl, M: MathsCore, G: RngCore, O: Scenario> +impl, M: MathsCore, G: Rng, O: Scenario> GillespieLineageStoreSampleInitialiser> for ResumeInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index 4f23dea77..b106364b8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -1,7 +1,11 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ - cogs::{ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, SplittableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, + SplittableRng, + }, reporter::Reporter, simulation::SimulationBuilder, }; @@ -36,7 +40,7 @@ use super::initialiser::GillespieLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: SplittableRng, + G: Rng, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -55,6 +59,9 @@ pub fn initialise_and_simulate< where O::LineageStore>: LocallyCoherentLineageStore, + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { @@ -124,7 +131,9 @@ where } }, non_monolithic_parallelism_mode => { - let rng = rng.split_to_stream(u64::from(local_partition.get_partition().rank())); + let rng = rng.map_generator(|rng| { + rng.split_to_stream(u64::from(local_partition.get_partition().rank())) + }); let ( habitat, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs index 7f44e6280..3aac781a1 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{LocallyCoherentLineageStore, MathsCore}, + cogs::{rng::SimpleRng, LocallyCoherentLineageStore, MathsCore}, lineage::Lineage, reporter::Reporter, }; @@ -31,14 +31,19 @@ use initialiser::{ }; // Default 'Gillespie' implementation for any turnover sampler -impl<'p, O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, M: MathsCore> - Algorithm<'p, M, O, R, P> for GillespieAlgorithm +impl< + 'p, + O: Scenario>, + R: Reporter, + P: LocalPartition<'p, R>, + M: MathsCore, + > Algorithm<'p, M, O, R, P> for GillespieAlgorithm where O::LineageStore>: LocallyCoherentLineageStore, { type LineageStore = O::LineageStore>; - type Rng = Pcg; + type Rng = SimpleRng; default fn get_logical_partition(args: &Self::Arguments, local_partition: &P) -> Partition { get_gillespie_logical_partition(args, local_partition) diff --git a/rustcoalescence/algorithms/gillespie/src/lib.rs b/rustcoalescence/algorithms/gillespie/src/lib.rs index 2cb62f1b1..82ba4c5ed 100644 --- a/rustcoalescence/algorithms/gillespie/src/lib.rs +++ b/rustcoalescence/algorithms/gillespie/src/lib.rs @@ -1,5 +1,6 @@ #![deny(clippy::pedantic)] #![feature(never_type)] +#![feature(associated_type_bounds)] #![allow(incomplete_features)] #![feature(specialization)] diff --git a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs index 8ed395c40..ddca78463 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -36,8 +39,16 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: PrimeableRng, O: Scenario> - IndependentLineageStoreSampleInitialiser> for FixUpInitialiser +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng, + O: Scenario, + > IndependentLineageStoreSampleInitialiser> for FixUpInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs index 6d960f0e5..f00285217 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; @@ -19,8 +22,12 @@ use super::IndependentLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> +impl, O: Scenario> IndependentLineageStoreSampleInitialiser for GenesisInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs index d62dc31d6..f54da064d 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs @@ -1,5 +1,8 @@ use necsim_core::{ - cogs::{DispersalSampler, EmigrationExit, MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, UniformClosedOpenUnit}, + DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + }, lineage::Lineage, }; @@ -24,10 +27,13 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait IndependentLineageStoreSampleInitialiser< M: MathsCore, - G: PrimeableRng, + G: Rng, O: Scenario, Error, -> +> where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type DispersalSampler: DispersalSampler; type ActiveLineageSampler> { pub resume_after: Option, } -impl, M: MathsCore, G: PrimeableRng, O: Scenario> - IndependentLineageStoreSampleInitialiser> for ResumeInitialiser +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng, + O: Scenario, + > IndependentLineageStoreSampleInitialiser> for ResumeInitialiser +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index a16586f88..bd0f88e53 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -1,7 +1,10 @@ use std::marker::PhantomData; use necsim_core::{ - cogs::{MathsCore, PrimeableRng}, + cogs::{ + rng::{Event, IndexUsize, Normal2D, UniformClosedOpenUnit}, + DistributionSampler, MathsCore, PrimeableRng, Rng, + }, reporter::Reporter, simulation::SimulationBuilder, }; @@ -46,7 +49,7 @@ use crate::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: PrimeableRng, + G: Rng, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -61,7 +64,13 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> { +) -> Result, Error> +where + G::Sampler: DistributionSampler + + DistributionSampler + + DistributionSampler + + DistributionSampler, +{ match args.parallelism_mode { ParallelismMode::Monolithic(MonolithicParallelismMode { event_slice }) | ParallelismMode::IsolatedIndividuals(IsolatedParallelismMode { event_slice, .. }) diff --git a/rustcoalescence/algorithms/independent/src/lib.rs b/rustcoalescence/algorithms/independent/src/lib.rs index 8a7d0473d..faa502de1 100644 --- a/rustcoalescence/algorithms/independent/src/lib.rs +++ b/rustcoalescence/algorithms/independent/src/lib.rs @@ -1,10 +1,15 @@ #![deny(clippy::pedantic)] #![feature(never_type)] +#![feature(associated_type_bounds)] #[macro_use] extern crate serde_derive_state; -use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; +use necsim_core::{ + cogs::{rng::SimpleRng, MathsCore}, + lineage::Lineage, + reporter::Reporter, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::{ @@ -41,11 +46,16 @@ impl AlgorithmDefaults for IndependentAlgorithm { type MathsCore = IntrinsicsMathsCore; } -impl<'p, O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, M: MathsCore> - Algorithm<'p, M, O, R, P> for IndependentAlgorithm +impl< + 'p, + O: Scenario>, + R: Reporter, + P: LocalPartition<'p, R>, + M: MathsCore, + > Algorithm<'p, M, O, R, P> for IndependentAlgorithm { type LineageStore = IndependentLineageStore; - type Rng = WyHash; + type Rng = SimpleRng; fn get_logical_partition(args: &Self::Arguments, local_partition: &P) -> Partition { match &args.parallelism_mode { diff --git a/rustcoalescence/algorithms/src/lib.rs b/rustcoalescence/algorithms/src/lib.rs index 7ed7ce88a..2c1138524 100644 --- a/rustcoalescence/algorithms/src/lib.rs +++ b/rustcoalescence/algorithms/src/lib.rs @@ -3,7 +3,7 @@ use std::error::Error as StdError; use necsim_core::{ - cogs::{LineageStore, MathsCore, RngCore}, + cogs::{LineageStore, MathsCore, Rng}, lineage::Lineage, reporter::Reporter, }; @@ -37,7 +37,7 @@ pub trait Algorithm< P: LocalPartition<'p, R>, >: Sized + AlgorithmParamters + AlgorithmDefaults { - type Rng: RngCore; + type Rng: Rng; type LineageStore: LineageStore; fn get_logical_partition(args: &Self::Arguments, local_partition: &P) -> Partition; diff --git a/rustcoalescence/algorithms/src/result.rs b/rustcoalescence/algorithms/src/result.rs index 6fa2d4b4d..cf1c7c98d 100644 --- a/rustcoalescence/algorithms/src/result.rs +++ b/rustcoalescence/algorithms/src/result.rs @@ -1,14 +1,14 @@ use std::{error::Error as StdError, fmt, marker::PhantomData}; use necsim_core::{ - cogs::{MathsCore, RngCore}, + cogs::{MathsCore, Rng}, lineage::Lineage, }; use necsim_core_bond::NonNegativeF64; use necsim_impls_no_std::cogs::active_lineage_sampler::resuming::lineage::ExceptionalLineage; -pub enum SimulationOutcome> { +pub enum SimulationOutcome> { Done { time: NonNegativeF64, steps: u64, diff --git a/rustcoalescence/scenarios/src/almost_infinite.rs b/rustcoalescence/scenarios/src/almost_infinite.rs index 7b0e7c805..8d645589c 100644 --- a/rustcoalescence/scenarios/src/almost_infinite.rs +++ b/rustcoalescence/scenarios/src/almost_infinite.rs @@ -1,6 +1,8 @@ use serde::{Deserialize, Serialize}; -use necsim_core::cogs::{DispersalSampler, LineageStore, MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::Normal2D, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, +}; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -21,7 +23,10 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct AlmostInfiniteScenario> { +pub struct AlmostInfiniteScenario> +where + G::Sampler: DistributionSampler, +{ radius: u16, habitat: AlmostInfiniteHabitat, @@ -38,12 +43,18 @@ pub struct AlmostInfiniteArguments { pub sigma: NonNegativeF64, } -impl> ScenarioParameters for AlmostInfiniteScenario { +impl> ScenarioParameters for AlmostInfiniteScenario +where + G::Sampler: DistributionSampler, +{ type Arguments = AlmostInfiniteArguments; type Error = !; } -impl> Scenario for AlmostInfiniteScenario { +impl> Scenario for AlmostInfiniteScenario +where + G::Sampler: DistributionSampler, +{ type Decomposition = RadialDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = diff --git a/rustcoalescence/scenarios/src/lib.rs b/rustcoalescence/scenarios/src/lib.rs index 8f8dfc13a..05bd7a7ac 100644 --- a/rustcoalescence/scenarios/src/lib.rs +++ b/rustcoalescence/scenarios/src/lib.rs @@ -6,7 +6,7 @@ extern crate log; use necsim_core::cogs::{ - DispersalSampler, LineageStore, MathsCore, RngCore, SpeciationProbability, TurnoverRate, + DispersalSampler, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, UniformlySampleableHabitat, }; use necsim_core_bond::OpenClosedUnitF64 as PositiveUnitF64; @@ -31,7 +31,7 @@ pub trait ScenarioParameters { type Error; } -pub trait Scenario>: Sized + ScenarioParameters { +pub trait Scenario>: Sized + ScenarioParameters { type Habitat: UniformlySampleableHabitat; type OriginSampler<'h, I: Iterator>: TrustedOriginSampler< 'h, diff --git a/rustcoalescence/scenarios/src/non_spatial.rs b/rustcoalescence/scenarios/src/non_spatial.rs index 9e5d15b94..7bb043702 100644 --- a/rustcoalescence/scenarios/src/non_spatial.rs +++ b/rustcoalescence/scenarios/src/non_spatial.rs @@ -2,7 +2,9 @@ use std::num::NonZeroU32; use serde::{Deserialize, Serialize}; -use necsim_core::cogs::{DispersalSampler, LineageStore, MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::IndexU64, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, +}; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -20,7 +22,10 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct NonSpatialScenario> { +pub struct NonSpatialScenario> +where + G::Sampler: DistributionSampler, +{ habitat: NonSpatialHabitat, dispersal_sampler: NonSpatialDispersalSampler, turnover_rate: UniformTurnoverRate, @@ -34,12 +39,18 @@ pub struct NonSpatialArguments { pub deme: NonZeroU32, } -impl> ScenarioParameters for NonSpatialScenario { +impl> ScenarioParameters for NonSpatialScenario +where + G::Sampler: DistributionSampler, +{ type Arguments = NonSpatialArguments; type Error = !; } -impl> Scenario for NonSpatialScenario { +impl> Scenario for NonSpatialScenario +where + G::Sampler: DistributionSampler, +{ type Decomposition = ModuloDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs index 34786cd4c..973f888ab 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs @@ -2,7 +2,9 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; -use necsim_core::cogs::{DispersalSampler, Habitat, LineageStore, MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, MathsCore, Rng, +}; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -38,7 +40,10 @@ pub enum SpatiallyExplicitTurnoverMapScenarioError { } #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyExplicitTurnoverMapScenario> { +pub struct SpatiallyExplicitTurnoverMapScenario> +where + G::Sampler: DistributionSampler, +{ habitat: InMemoryHabitat, dispersal_map: Array2D, turnover_rate: InMemoryTurnoverRate, @@ -46,14 +51,18 @@ pub struct SpatiallyExplicitTurnoverMapScenario> { _marker: PhantomData, } -impl> ScenarioParameters - for SpatiallyExplicitTurnoverMapScenario +impl> ScenarioParameters for SpatiallyExplicitTurnoverMapScenario +where + G::Sampler: DistributionSampler, { type Arguments = SpatiallyExplicitTurnoverMapArguments; type Error = SpatiallyExplicitTurnoverMapScenarioError; } -impl> Scenario for SpatiallyExplicitTurnoverMapScenario { +impl> Scenario for SpatiallyExplicitTurnoverMapScenario +where + G::Sampler: DistributionSampler, +{ type Decomposition = EqualDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = D; diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs index f87f41e40..fed318aa6 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs @@ -2,7 +2,9 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; -use necsim_core::cogs::{DispersalSampler, Habitat, LineageStore, MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, MathsCore, Rng, +}; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64, PositiveF64}; use necsim_partitioning_core::partition::Partition; @@ -36,7 +38,10 @@ pub enum SpatiallyExplicitUniformTurnoverScenarioError { } #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyExplicitUniformTurnoverScenario> { +pub struct SpatiallyExplicitUniformTurnoverScenario> +where + G::Sampler: DistributionSampler, +{ habitat: InMemoryHabitat, dispersal_map: Array2D, turnover_rate: UniformTurnoverRate, @@ -44,15 +49,17 @@ pub struct SpatiallyExplicitUniformTurnoverScenario> _marker: PhantomData, } -impl> ScenarioParameters - for SpatiallyExplicitUniformTurnoverScenario +impl> ScenarioParameters for SpatiallyExplicitUniformTurnoverScenario +where + G::Sampler: DistributionSampler, { type Arguments = SpatiallyExplicitUniformTurnoverArguments; type Error = SpatiallyExplicitUniformTurnoverScenarioError; } -impl> Scenario - for SpatiallyExplicitUniformTurnoverScenario +impl> Scenario for SpatiallyExplicitUniformTurnoverScenario +where + G::Sampler: DistributionSampler, { type Decomposition = EqualDecomposition; type DecompositionAuxiliary = (); diff --git a/rustcoalescence/scenarios/src/spatially_implicit.rs b/rustcoalescence/scenarios/src/spatially_implicit.rs index 8c6ed774f..37a64f123 100644 --- a/rustcoalescence/scenarios/src/spatially_implicit.rs +++ b/rustcoalescence/scenarios/src/spatially_implicit.rs @@ -2,7 +2,10 @@ use std::num::NonZeroU32; use serde::{Deserialize, Serialize}; -use necsim_core::cogs::{DispersalSampler, LineageStore, MathsCore, RngCore}; +use necsim_core::cogs::{ + rng::{Event, IndexU64}, + DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, +}; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -22,7 +25,11 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyImplicitScenario> { +pub struct SpatiallyImplicitScenario> +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ habitat: SpatiallyImplicitHabitat, dispersal_sampler: SpatiallyImplicitDispersalSampler, turnover_rate: UniformTurnoverRate, @@ -41,12 +48,20 @@ pub struct SpatiallyImplicitArguments { pub migration_probability_per_generation: PositiveUnitF64, } -impl> ScenarioParameters for SpatiallyImplicitScenario { +impl> ScenarioParameters for SpatiallyImplicitScenario +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ type Arguments = SpatiallyImplicitArguments; type Error = !; } -impl> Scenario for SpatiallyImplicitScenario { +impl> Scenario for SpatiallyImplicitScenario +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ type Decomposition = ModuloDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = diff --git a/rustcoalescence/src/args/config/rng/mod.rs b/rustcoalescence/src/args/config/rng/mod.rs index 6899a848a..406800030 100644 --- a/rustcoalescence/src/args/config/rng/mod.rs +++ b/rustcoalescence/src/args/config/rng/mod.rs @@ -3,7 +3,7 @@ use std::{fmt, marker::PhantomData}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_state::DeserializeState; -use necsim_core::cogs::{MathsCore, RngCore}; +use necsim_core::cogs::{MathsCore, Rng}; use necsim_partitioning_core::partition::Partition; mod base32; @@ -12,19 +12,21 @@ use self::base32::Base32String; #[derive(Debug, Serialize)] #[serde(bound = "")] -pub enum Rng> { +#[serde(rename = "Rng")] +#[allow(clippy::module_name_repetitions)] +pub enum RngConfig> { Seed(u64), Sponge(Base32String), State(Base32RngState), } #[allow(dead_code)] -pub struct Base32RngState> { +pub struct Base32RngState> { rng: G, marker: PhantomData, } -impl<'de, M: MathsCore, G: RngCore> DeserializeState<'de, Partition> for Rng { +impl<'de, M: MathsCore, G: Rng> DeserializeState<'de, Partition> for RngConfig { fn deserialize_state>( partition: &mut Partition, deserializer: D, @@ -73,7 +75,7 @@ impl<'de, M: MathsCore, G: RngCore> DeserializeState<'de, Partition> for Rng< } } -impl> From for Base32RngState { +impl> From for Base32RngState { fn from(rng: G) -> Self { Self { rng, @@ -82,7 +84,7 @@ impl> From for Base32RngState { } } -impl> Base32RngState { +impl> Base32RngState { #[must_use] #[allow(dead_code)] pub fn into(self) -> G { @@ -90,7 +92,7 @@ impl> Base32RngState { } } -impl> fmt::Debug for Base32RngState { +impl> fmt::Debug for Base32RngState { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match ProtectedState::serialize(&self.rng) { Ok(state) => Base32String::new(&state).fmt(fmt), @@ -99,7 +101,7 @@ impl> fmt::Debug for Base32RngState { } } -impl> Serialize for Base32RngState { +impl> Serialize for Base32RngState { fn serialize(&self, serializer: S) -> Result { let state = ProtectedState::serialize(&self.rng).map_err(serde::ser::Error::custom)?; @@ -107,7 +109,7 @@ impl> Serialize for Base32RngState { } } -impl<'de, M: MathsCore, G: RngCore> Deserialize<'de> for Base32RngState { +impl<'de, M: MathsCore, G: Rng> Deserialize<'de> for Base32RngState { fn deserialize>(deserializer: D) -> Result { let state = Base32String::deserialize(deserializer)?; @@ -129,7 +131,7 @@ impl<'de, M: MathsCore, G: RngCore> Deserialize<'de> for Base32RngState #[derive(Debug, Deserialize)] #[serde(bound = "")] #[serde(rename = "Rng")] -enum RngRaw> { +enum RngRaw> { Entropy, Seed(u64), #[serde(deserialize_with = "deserialize_rng_sponge")] diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs index 929556339..542611cb9 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs @@ -13,7 +13,7 @@ use rustcoalescence_scenarios::Scenario; use crate::{ args::config::{ - rng::{Base32RngState, Rng as RngArgs}, + rng::{Base32RngState, RngConfig}, sample::Sample, }, cli::simulate::parse, @@ -51,9 +51,9 @@ where normalised_args, &mut A::get_logical_partition(&algorithm_args, &local_partition), )? { - RngArgs::Seed(seed) => SeedableRng::seed_from_u64(seed), - RngArgs::Sponge(bytes) => { - let mut seed = >::Seed::default(); + RngConfig::Seed(seed) => SeedableRng::seed_from_u64(seed), + RngConfig::Sponge(bytes) => { + let mut seed = ::Seed::default(); let mut sponge = Keccak::v256(); sponge.update(&bytes); @@ -61,7 +61,7 @@ where RngCore::from_seed(seed) }, - RngArgs::State(state) => state.into(), + RngConfig::State(state) => state.into(), }; let result = info::dispatch::( @@ -83,7 +83,7 @@ where rng: paused_rng, .. } => { - normalised_args.rng(&RngArgs::State(Base32RngState::from(paused_rng))); + normalised_args.rng(&RngConfig::State(Base32RngState::from(paused_rng))); Ok(SimulationOutcome::Paused { time, diff --git a/rustcoalescence/src/cli/simulate/parse/rng.rs b/rustcoalescence/src/cli/simulate/parse/rng.rs index 2c463d296..b059a2223 100644 --- a/rustcoalescence/src/cli/simulate/parse/rng.rs +++ b/rustcoalescence/src/cli/simulate/parse/rng.rs @@ -1,16 +1,16 @@ -use necsim_core::cogs::{MathsCore, RngCore}; +use necsim_core::cogs::{MathsCore, Rng}; use necsim_partitioning_core::partition::Partition; -use crate::args::{config::rng::Rng, utils::parse::try_parse_state}; +use crate::args::{config::rng::RngConfig, utils::parse::try_parse_state}; use super::super::BufferingSimulateArgsBuilder; #[allow(dead_code)] -pub(in super::super) fn parse_and_normalise>( +pub(in super::super) fn parse_and_normalise>( ron_args: &str, normalised_args: &mut BufferingSimulateArgsBuilder, partition: &mut Partition, -) -> anyhow::Result> { +) -> anyhow::Result> { let SimulateArgsRngOnly { rng } = try_parse_state("simulate", ron_args, partition)?; normalised_args.rng(&rng); @@ -22,8 +22,8 @@ pub(in super::super) fn parse_and_normalise>( #[serde(bound = "")] #[serde(rename = "Simulate")] #[serde(deserialize_state = "Partition")] -struct SimulateArgsRngOnly> { +struct SimulateArgsRngOnly> { #[serde(alias = "randomness")] #[serde(deserialize_state)] - rng: Rng, + rng: RngConfig, } From 4575112f58b83727b2e44821ec7d48e1a06f3822 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Wed, 18 May 2022 13:18:24 +0000 Subject: [PATCH 07/21] Make SimpleRNG FFI safe --- necsim/core/src/cogs/rng.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index ce282cc5c..d1c78bec4 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -229,6 +229,7 @@ impl Distribution for Normal2D { #[derive(Clone, Debug, TypeLayout)] #[layout(free = "M")] #[allow(clippy::module_name_repetitions)] +#[repr(transparent)] pub struct SimpleRng { inner: R, marker: PhantomData, From 6a8fd3d092a78133a81c9c53019d8247d72e32ef Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Thu, 19 May 2022 10:05:11 +0000 Subject: [PATCH 08/21] Some first refactoring --- necsim/core/src/cogs/coalescence_sampler.rs | 11 +- necsim/core/src/cogs/distribution.rs | 141 ++++ necsim/core/src/cogs/mod.rs | 8 +- necsim/core/src/cogs/rng.rs | 639 +----------------- necsim/impls/cuda/src/cogs/rng.rs | 17 +- necsim/impls/no-std/src/alias/mod.rs | 20 +- necsim/impls/no-std/src/alias/packed.rs | 10 +- .../alias/individual/mod.rs | 2 +- .../alias/individual/sampler.rs | 6 +- .../alias/location/mod.rs | 2 +- .../alias/location/sampler.rs | 13 +- .../alias/sampler/indexed/mod.rs | 14 +- .../alias/sampler/indexed/tests.rs | 16 +- .../alias/sampler/stack/mod.rs | 14 +- .../alias/sampler/stack/tests.rs | 16 +- .../active_lineage_sampler/classical/mod.rs | 8 +- .../classical/sampler.rs | 18 +- .../independent/event_time_sampler/const.rs | 2 +- .../independent/event_time_sampler/exp.rs | 7 +- .../independent/event_time_sampler/fixed.rs | 2 +- .../event_time_sampler/geometric.rs | 8 +- .../independent/event_time_sampler/poisson.rs | 21 +- .../active_lineage_sampler/independent/mod.rs | 4 +- .../independent/sampler.rs | 5 +- .../independent/singular.rs | 4 +- .../almost_infinite_normal.rs | 16 +- .../in_memory/alias/dispersal.rs | 4 +- .../dispersal_sampler/in_memory/alias/mod.rs | 8 +- .../in_memory/cumulative/contract.rs | 2 +- .../in_memory/cumulative/dispersal.rs | 5 +- .../in_memory/cumulative/mod.rs | 4 +- .../in_memory/packed_alias/dispersal.rs | 4 +- .../in_memory/packed_alias/mod.rs | 10 +- .../in_memory/separable_alias/dispersal.rs | 11 +- .../in_memory/separable_alias/mod.rs | 8 +- .../src/cogs/dispersal_sampler/non_spatial.rs | 18 +- .../dispersal_sampler/spatially_implicit.rs | 18 +- .../cogs/dispersal_sampler/wrapping_noise.rs | 30 +- .../no-std/src/cogs/emigration_exit/domain.rs | 2 +- .../cogs/emigration_exit/independent/mod.rs | 2 +- .../gillespie/conditional/mod.rs | 8 +- .../event_sampler/gillespie/unconditional.rs | 19 +- .../src/cogs/event_sampler/independent.rs | 8 +- .../src/cogs/event_sampler/unconditional.rs | 17 +- .../no-std/src/cogs/habitat/in_memory.rs | 7 +- .../no-std/src/cogs/habitat/non_spatial.rs | 12 +- .../src/cogs/habitat/spatially_implicit.rs | 2 +- .../src/cogs/habitat/wrapping_noise/mod.rs | 2 +- necsim/impls/no-std/src/cogs/rng/mod.rs | 1 + necsim/impls/no-std/src/cogs/rng/simple.rs | 553 +++++++++++++++ .../independent/individuals.rs | 4 +- .../parallelisation/independent/landscape.rs | 4 +- .../independent/monolithic/mod.rs | 4 +- .../parallelisation/monolithic/averaging.rs | 6 +- .../parallelisation/monolithic/lockstep.rs | 6 +- .../parallelisation/monolithic/optimistic.rs | 2 +- .../monolithic/optimistic_lockstep.rs | 2 +- .../algorithms/cuda/cpu-kernel/src/link.rs | 38 +- .../algorithms/cuda/src/initialiser/fixup.rs | 4 +- .../cuda/src/initialiser/genesis.rs | 4 +- .../algorithms/cuda/src/initialiser/mod.rs | 4 +- .../algorithms/cuda/src/initialiser/resume.rs | 4 +- rustcoalescence/algorithms/cuda/src/launch.rs | 8 +- rustcoalescence/algorithms/cuda/src/lib.rs | 8 +- .../src/event_skipping/initialiser/fixup.rs | 6 +- .../src/event_skipping/initialiser/genesis.rs | 6 +- .../src/event_skipping/initialiser/mod.rs | 4 +- .../src/event_skipping/initialiser/resume.rs | 6 +- .../gillespie/src/event_skipping/launch.rs | 4 +- .../gillespie/src/event_skipping/mod.rs | 3 +- .../gillespie/classical/initialiser/fixup.rs | 4 +- .../classical/initialiser/genesis.rs | 4 +- .../gillespie/classical/initialiser/mod.rs | 4 +- .../gillespie/classical/initialiser/resume.rs | 4 +- .../src/gillespie/classical/launch.rs | 4 +- .../gillespie/src/gillespie/classical/mod.rs | 5 +- .../gillespie/turnover/initialiser/fixup.rs | 4 +- .../gillespie/turnover/initialiser/genesis.rs | 4 +- .../src/gillespie/turnover/initialiser/mod.rs | 4 +- .../gillespie/turnover/initialiser/resume.rs | 4 +- .../src/gillespie/turnover/launch.rs | 4 +- .../gillespie/src/gillespie/turnover/mod.rs | 4 +- .../independent/src/initialiser/fixup.rs | 4 +- .../independent/src/initialiser/genesis.rs | 4 +- .../independent/src/initialiser/mod.rs | 4 +- .../independent/src/initialiser/resume.rs | 4 +- .../algorithms/independent/src/launch.rs | 4 +- .../algorithms/independent/src/lib.rs | 12 +- .../scenarios/src/almost_infinite.rs | 2 +- rustcoalescence/scenarios/src/non_spatial.rs | 2 +- .../src/spatially_explicit/turnover/map.rs | 3 +- .../spatially_explicit/turnover/uniform.rs | 3 +- .../scenarios/src/spatially_implicit.rs | 8 +- .../scenarios/src/wrapping_noise.rs | 23 +- 94 files changed, 1088 insertions(+), 940 deletions(-) create mode 100644 necsim/core/src/cogs/distribution.rs create mode 100644 necsim/impls/no-std/src/cogs/rng/simple.rs diff --git a/necsim/core/src/cogs/coalescence_sampler.rs b/necsim/core/src/cogs/coalescence_sampler.rs index 526d64cf7..6af72afa7 100644 --- a/necsim/core/src/cogs/coalescence_sampler.rs +++ b/necsim/core/src/cogs/coalescence_sampler.rs @@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize}; use crate::{ cogs::{ - rng::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, LineageStore, MathsCore, - Rng, + distribution::UniformClosedOpenUnit, Backup, Habitat, LineageStore, MathsCore, Rng, + SampledDistribution, Samples, }, landscape::{IndexedLocation, Location}, lineage::LineageInteraction, @@ -58,11 +58,8 @@ impl Eq for CoalescenceRngSample {} impl CoalescenceRngSample { #[must_use] #[inline] - pub fn new>(rng: &mut G) -> Self - where - G::Sampler: DistributionSampler, - { - Self(rng.sample::()) + pub fn new + Samples>(rng: &mut G) -> Self { + Self(UniformClosedOpenUnit::sample(rng)) } #[must_use] diff --git a/necsim/core/src/cogs/distribution.rs b/necsim/core/src/cogs/distribution.rs new file mode 100644 index 000000000..f59cdf509 --- /dev/null +++ b/necsim/core/src/cogs/distribution.rs @@ -0,0 +1,141 @@ +use core::num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}; + +use necsim_core_bond::{ + ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64, PositiveF64, +}; + +use crate::cogs::{MathsCore, RngCore, Samples}; + +pub trait Distribution { + type Parameters; + type Sample; +} + +#[allow(clippy::module_name_repetitions)] +pub trait SampledDistribution: Distribution { + fn sample_with>( + rng: &mut R, + params: Self::Parameters, + ) -> Self::Sample; + + fn sample>(rng: &mut R) -> Self::Sample + where + Self: Distribution, + { + Self::sample_with(rng, ()) + } +} + +impl SampledDistribution for D { + fn sample_with>( + rng: &mut R, + params: Self::Parameters, + ) -> Self::Sample { + rng.sample_with(params) + } +} + +#[allow(clippy::module_name_repetitions)] +pub trait DistributionSampler { + type ConcreteSampler: DistributionSampler; + + #[must_use] + fn concrete(&self) -> &Self::ConcreteSampler; + + #[must_use] + fn sample_with(&self, rng: &mut R, samplers: &S, params: D::Parameters) -> D::Sample; + + #[must_use] + fn sample(&self, rng: &mut R, samplers: &S) -> D::Sample + where + D: Distribution, + { + self.sample_with(rng, samplers, ()) + } +} + +pub enum UniformClosedOpenUnit {} + +impl Distribution for UniformClosedOpenUnit { + type Parameters = (); + type Sample = ClosedOpenUnitF64; +} + +pub enum UniformOpenClosedUnit {} + +impl Distribution for UniformOpenClosedUnit { + type Parameters = (); + type Sample = OpenClosedUnitF64; +} + +pub enum IndexUsize {} + +pub struct Length(pub T); + +impl Distribution for IndexUsize { + type Parameters = Length; + type Sample = usize; +} + +pub enum IndexU32 {} + +impl Distribution for IndexU32 { + type Parameters = Length; + type Sample = u32; +} + +pub enum IndexU64 {} + +impl Distribution for IndexU64 { + type Parameters = Length; + type Sample = u64; +} + +pub enum IndexU128 {} + +impl Distribution for IndexU128 { + type Parameters = Length; + type Sample = u128; +} + +pub struct Lambda(pub PositiveF64); + +pub enum Exponential {} + +impl Distribution for Exponential { + type Parameters = Lambda; + type Sample = NonNegativeF64; +} + +pub enum Poisson {} + +impl Distribution for Poisson { + type Parameters = Lambda; + type Sample = usize; +} + +pub enum Bernoulli {} + +impl Distribution for Bernoulli { + type Parameters = ClosedUnitF64; + type Sample = bool; +} + +pub enum StandardNormal2D {} + +impl Distribution for StandardNormal2D { + type Parameters = (); + type Sample = (f64, f64); +} + +pub struct Normal { + pub mu: f64, + pub sigma: NonNegativeF64, +} + +pub enum Normal2D {} + +impl Distribution for Normal2D { + type Parameters = Normal; + type Sample = (f64, f64); +} diff --git a/necsim/core/src/cogs/mod.rs b/necsim/core/src/cogs/mod.rs index 7fa38cfc1..80324d2f8 100644 --- a/necsim/core/src/cogs/mod.rs +++ b/necsim/core/src/cogs/mod.rs @@ -10,10 +10,10 @@ pub mod speciation_probability; pub use speciation_probability::SpeciationProbability; pub mod rng; -pub use rng::{ - Distribution, DistributionSampler, HabitatPrimeableRng, PrimeableRng, Rng, RngCore, - SeedableRng, SplittableRng, -}; +pub use rng::{PrimeableRng, Rng, RngCore, Samples, SeedableRng, SplittableRng}; + +pub mod distribution; +pub use distribution::{Distribution, DistributionSampler, SampledDistribution}; pub mod dispersal_sampler; pub use dispersal_sampler::{DispersalSampler, SeparableDispersalSampler}; diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index d1c78bec4..3075e6424 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -1,22 +1,25 @@ -use core::{ - convert::AsMut, - default::Default, - marker::PhantomData, - num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, - ptr::copy_nonoverlapping, -}; - -use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; +use core::{convert::AsMut, ptr::copy_nonoverlapping}; -use necsim_core_bond::{ - ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64, PositiveF64, -}; +use serde::{de::DeserializeOwned, Serialize}; use crate::{ - cogs::{Habitat, MathsCore}, + cogs::{Distribution, DistributionSampler, Habitat, MathsCore}, landscape::IndexedLocation, }; +pub trait Rng: RngCore { + type Generator: RngCore; + type Sampler; + + #[must_use] + fn generator(&mut self) -> &mut Self::Generator; + + #[must_use] + fn map_generator Self::Generator>(self, map: F) -> Self; + + fn with_rng Q, Q>(&mut self, inner: F) -> Q; +} + #[allow(clippy::module_name_repetitions)] pub trait RngCore: crate::cogs::Backup + Sized + Clone + core::fmt::Debug + Serialize + DeserializeOwned @@ -99,617 +102,25 @@ pub trait SplittableRng: RngCore { fn split_to_stream(self, stream: u64) -> Self; } -pub trait Distribution { - type Parameters; - type Sample; -} - -pub trait Rng: RngCore { - type Generator: RngCore; - type Sampler; - - #[must_use] - fn generator(&mut self) -> &mut Self::Generator; - - #[must_use] - fn map_generator Self::Generator>(self, map: F) -> Self; - - #[must_use] - fn sample_with(&mut self, params: D::Parameters) -> D::Sample - where - Self::Sampler: DistributionSampler; - - #[must_use] - fn sample>(&mut self) -> D::Sample - where - Self::Sampler: DistributionSampler, - { - self.sample_with(()) - } -} - -#[allow(clippy::module_name_repetitions)] -pub trait DistributionSampler { - type ConcreteSampler: DistributionSampler; - +pub trait Samples: Rng { #[must_use] - fn concrete(&self) -> &Self::ConcreteSampler; + fn sample_with(&mut self, params: D::Parameters) -> D::Sample; #[must_use] - fn sample_with(&self, rng: &mut R, samplers: &S, params: D::Parameters) -> D::Sample; - - #[must_use] - fn sample(&self, rng: &mut R, samplers: &S) -> D::Sample + fn sample(&mut self) -> D::Sample where D: Distribution, { - self.sample_with(rng, samplers, ()) - } -} - -pub enum UniformClosedOpenUnit {} - -impl Distribution for UniformClosedOpenUnit { - type Parameters = (); - type Sample = ClosedOpenUnitF64; -} - -pub enum UniformOpenClosedUnit {} - -impl Distribution for UniformOpenClosedUnit { - type Parameters = (); - type Sample = OpenClosedUnitF64; -} - -pub enum IndexUsize {} - -pub struct Length(pub T); - -impl Distribution for IndexUsize { - type Parameters = Length; - type Sample = usize; -} - -pub enum IndexU32 {} - -impl Distribution for IndexU32 { - type Parameters = Length; - type Sample = u32; -} - -pub enum IndexU64 {} - -impl Distribution for IndexU64 { - type Parameters = Length; - type Sample = u64; -} - -pub enum IndexU128 {} - -impl Distribution for IndexU128 { - type Parameters = Length; - type Sample = u128; -} - -pub enum Exponential {} - -pub struct Lambda(pub PositiveF64); - -impl Distribution for Exponential { - type Parameters = Lambda; - type Sample = NonNegativeF64; -} - -pub enum Event {} - -impl Distribution for Event { - type Parameters = ClosedUnitF64; - type Sample = bool; -} - -pub enum StandardNormal2D {} - -impl Distribution for StandardNormal2D { - type Parameters = (); - type Sample = (f64, f64); -} - -pub enum Normal2D {} - -pub struct Normal { - pub mu: f64, - pub sigma: NonNegativeF64, -} - -impl Distribution for Normal2D { - type Parameters = Normal; - type Sample = (f64, f64); -} - -#[derive(Clone, Debug, TypeLayout)] -#[layout(free = "M")] -#[allow(clippy::module_name_repetitions)] -#[repr(transparent)] -pub struct SimpleRng { - inner: R, - marker: PhantomData, -} - -impl Serialize for SimpleRng { - fn serialize(&self, serializer: S) -> Result { - self.inner.serialize(serializer) - } -} - -impl<'de, M: MathsCore, R: RngCore> Deserialize<'de> for SimpleRng { - fn deserialize>(deserializer: D) -> Result { - let inner = R::deserialize(deserializer)?; - - Ok(Self { - inner, - marker: PhantomData::, - }) - } -} - -#[contract_trait] -impl crate::cogs::Backup for SimpleRng { - unsafe fn backup_unchecked(&self) -> Self { - Self { - inner: self.inner.backup_unchecked(), - marker: PhantomData::, - } - } -} - -impl RngCore for SimpleRng { - type Seed = R::Seed; - - #[must_use] - fn from_seed(seed: Self::Seed) -> Self { - Self { - inner: R::from_seed(seed), - marker: PhantomData::, - } - } - - #[must_use] - fn sample_u64(&mut self) -> u64 { - self.inner.sample_u64() - } -} - -impl Rng for SimpleRng { - type Generator = R; - type Sampler = SimplerDistributionSamplers; - - fn generator(&mut self) -> &mut Self::Generator { - &mut self.inner - } - - fn map_generator Self::Generator>(self, map: F) -> Self { - let SimpleRng { inner, marker } = self; - - SimpleRng { - inner: map(inner), - marker, - } - } - - fn sample_with(&mut self, params: D::Parameters) -> D::Sample - where - Self::Sampler: DistributionSampler, - { - let samplers = SimplerDistributionSamplers { - _marker: PhantomData::<(M, R)>, - }; - - samplers.sample_with(&mut self.inner, &samplers, params) - } -} - -#[allow(clippy::module_name_repetitions)] -pub struct SimplerDistributionSamplers { - _marker: PhantomData<(M, R)>, -} - -impl DistributionSampler - for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { ClosedOpenUnitF64::new_unchecked(u01) } - } -} - -impl DistributionSampler - for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = - (((rng.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { OpenClosedUnitF64::new_unchecked(u01) } - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> usize { - let length = params.0; - - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as usize; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u32 { - let length = params.0; - - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); - - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let index = M::floor(u01.get() * f64::from(length.get())) as u32; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { - let length = params.0; - - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as u64; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { - let length = params.0; - - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as u128; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> NonNegativeF64 { - let lambda = params.0; - - let u01: OpenClosedUnitF64 = samplers.sample(rng, samplers); - - // Inverse transform sample: X = -ln(U(0,1]) / lambda - -u01.ln::() / lambda - } -} - -impl> - DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: ClosedUnitF64) -> bool { - let probability = params; - - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); - - // if probability == 1, then U[0, 1) always < 1.0 - // if probability == 0, then U[0, 1) never < 0.0 - u01 < probability - } -} - -#[allow(clippy::trait_duplication_in_bounds)] -impl< - M: MathsCore, - R: RngCore, - S: DistributionSampler - + DistributionSampler, - > DistributionSampler for SimplerDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { - // Basic Box-Muller transform - let u0 = - DistributionSampler::::sample(samplers, rng, samplers); - let u1 = - DistributionSampler::::sample(samplers, rng, samplers); - - let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); - let theta = -core::f64::consts::TAU * u1.get(); - - (r * M::sin(theta), r * M::cos(theta)) + self.sample_with(()) } } -impl> - DistributionSampler for SimplerDistributionSamplers +impl> Samples for R +where + R::Sampler: DistributionSampler, { - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_with(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { - let (z0, z1) = samplers.sample(rng, samplers); - - ( - z0 * params.sigma.get() + params.mu, - z1 * params.sigma.get() + params.mu, - ) - } -} - -/*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] -#[allow(clippy::module_name_repetitions)] -#[contract_trait] -pub trait RngSampler: RngCore { #[must_use] - #[inline] - /// Samples a uniform sample within `[0.0, 1.0)`, i.e. `0.0 <= X < 1.0` - fn sample_uniform_closed_open(&mut self) -> ClosedOpenUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = ((self.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { ClosedOpenUnitF64::new_unchecked(u01) } - } - - #[must_use] - #[inline] - /// Samples a uniform sample within `(0.0, 1.0]`, i.e. `0.0 < X <= 1.0` - fn sample_uniform_open_closed(&mut self) -> OpenClosedUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = - (((self.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { OpenClosedUnitF64::new_unchecked(u01) } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index(&mut self, length: NonZeroUsize) -> usize { - #[cfg(target_pointer_width = "32")] - #[allow(clippy::cast_possible_truncation)] - { - self.sample_index_u32(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }) - as usize - } - #[cfg(target_pointer_width = "64")] - #[allow(clippy::cast_possible_truncation)] - { - self.sample_index_u64(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }) - as usize - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u32(&mut self, length: NonZeroU32) -> u32 { - // TODO: Check if delegation to `sample_index_u64` is faster - - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - const LOWER_MASK: u64 = !0 >> 32; - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw = self.sample_u64(); - - let sample_check_lo = (raw & LOWER_MASK) * u64::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check_lo as u32) <= acceptance_zone { - return (sample_check_lo >> 32) as u32; - } - - let sample_check_hi = (raw >> 32) * u64::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check_hi as u32) <= acceptance_zone { - return (sample_check_hi >> 32) as u32; - } - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u64(&mut self, length: NonZeroU64) -> u64 { - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw = self.sample_u64(); - - let sample_check = u128::from(raw) * u128::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check as u64) <= acceptance_zone { - return (sample_check >> 64) as u64; - } - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u128(&mut self, length: NonZeroU128) -> u128 { - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - const LOWER_MASK: u128 = !0 >> 64; - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw_hi = u128::from(self.sample_u64()); - let raw_lo = u128::from(self.sample_u64()); - - // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length - let mut low = raw_lo * (length.get() & LOWER_MASK); - let mut t = low >> 64; - low &= LOWER_MASK; - t += raw_hi * (length.get() & LOWER_MASK); - low += (t & LOWER_MASK) << 64; - let mut high = t >> 64; - t = low >> 64; - low &= LOWER_MASK; - t += (length.get() >> 64) * raw_lo; - low += (t & LOWER_MASK) << 64; - high += t >> 64; - high += raw_hi * (length.get() >> 64); - - let sample = high; - let check = low; - - if check <= acceptance_zone { - return sample; - } - } - } - - #[must_use] - #[inline] - fn sample_exponential(&mut self, lambda: PositiveF64) -> NonNegativeF64 { - // Inverse transform sample: X = -ln(U(0,1]) / lambda - -self.sample_uniform_open_closed().ln::() / lambda - } - - #[must_use] - #[inline] - fn sample_event(&mut self, probability: ClosedUnitF64) -> bool { - // if probability == 1, then U[0, 1) always < 1.0 - // if probability == 0, then U[0, 1) never < 0.0 - self.sample_uniform_closed_open() < probability - } - - #[must_use] - #[inline] - fn sample_2d_standard_normal(&mut self) -> (f64, f64) { - // Basic Box-Muller transform - let u0 = self.sample_uniform_open_closed(); - let u1 = self.sample_uniform_closed_open(); - - let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); - let theta = -core::f64::consts::TAU * u1.get(); - - (r * M::sin(theta), r * M::cos(theta)) - } - - #[must_use] - #[inline] - fn sample_2d_normal(&mut self, mu: f64, sigma: NonNegativeF64) -> (f64, f64) { - let (z0, z1) = self.sample_2d_standard_normal(); - - (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + fn sample_with(&mut self, params: D::Parameters) -> D::Sample { + self.with_rng(|rng, samplers| samplers.sample_with(rng, samplers, params)) } } - -impl> RngSampler for R {}*/ diff --git a/necsim/impls/cuda/src/cogs/rng.rs b/necsim/impls/cuda/src/cogs/rng.rs index 6f04b14e2..8c29ba2b7 100644 --- a/necsim/impls/cuda/src/cogs/rng.rs +++ b/necsim/impls/cuda/src/cogs/rng.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use necsim_core::cogs::{Distribution, DistributionSampler, MathsCore, Rng, RngCore}; +use necsim_core::cogs::{MathsCore, Rng, RngCore}; use const_type_layout::TypeGraphLayout; use rust_cuda::safety::StackOnly; @@ -38,9 +38,7 @@ impl + StackOnly + ~const TypeGraphLayout> From for C } } -impl + StackOnly + ~const TypeGraphLayout> RngCore - for CudaRng -{ +impl + StackOnly + ~const TypeGraphLayout> RngCore for CudaRng { type Seed = ::Seed; #[must_use] @@ -76,11 +74,8 @@ impl + StackOnly + ~const TypeGraphLayout> Rng for Cu } } - fn sample_with(&mut self, params: D::Parameters) -> D::Sample - where - Self::Sampler: DistributionSampler, - { - self.inner.sample_with(params) + fn with_rng Q, Q>(&mut self, inner: F) -> Q { + self.inner.with_rng(inner) } } @@ -90,7 +85,9 @@ impl + StackOnly + ~const TypeGraphLayout> Serialize for } } -impl<'de, M: MathsCore, R: Rng + StackOnly + ~const TypeGraphLayout> Deserialize<'de> for CudaRng { +impl<'de, M: MathsCore, R: Rng + StackOnly + ~const TypeGraphLayout> Deserialize<'de> + for CudaRng +{ fn deserialize>(deserializer: D) -> Result { let inner = R::deserialize(deserializer)?; diff --git a/necsim/impls/no-std/src/alias/mod.rs b/necsim/impls/no-std/src/alias/mod.rs index cbabed87c..1dca499f4 100644 --- a/necsim/impls/no-std/src/alias/mod.rs +++ b/necsim/impls/no-std/src/alias/mod.rs @@ -3,8 +3,8 @@ use core::num::NonZeroUsize; use alloc::vec::Vec; use necsim_core::cogs::{ - rng::{Event, IndexUsize, Length}, - DistributionSampler, MathsCore, Rng, + distribution::{Bernoulli, IndexUsize, Length}, + MathsCore, Rng, SampledDistribution, Samples, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -94,18 +94,20 @@ impl AliasMethodSampler { } #[debug_ensures(self.Es.contains(&ret), "returns one of the weighted events")] - pub fn sample_event>(&self, rng: &mut G) -> E - where - G::Sampler: DistributionSampler - + DistributionSampler, - { + pub fn sample_event< + M: MathsCore, + G: Rng + Samples + Samples, + >( + &self, + rng: &mut G, + ) -> E { // Safety: Es is non-empty by the precondition on construction let length = unsafe { NonZeroUsize::new_unchecked(self.Es.len()) }; - let i = rng.sample_with::(Length(length)); // index into events + let i = IndexUsize::sample_with(rng, Length(length)); // index into events // Select Es[i] over Ks[i] according to its bucket percentage Us[i] - if rng.sample_with::(self.Us[i]) { + if Bernoulli::sample_with(rng, self.Us[i]) { self.Es[i] } else { self.Ks[i] diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index fcc0aab9a..fe1a797f1 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -3,8 +3,8 @@ use core::{cmp::Ordering, num::NonZeroUsize}; use alloc::vec::Vec; use necsim_core::cogs::{ - rng::{Event, IndexUsize, Length}, - DistributionSampler, MathsCore, Rng, + distribution::{Bernoulli, IndexUsize, Length}, + DistributionSampler, MathsCore, Rng, SampledDistribution, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -117,17 +117,17 @@ impl AliasMethodSamplerAtom { ) -> E where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { // Safety: alias_samplers is non-empty by the precondition let length = unsafe { NonZeroUsize::new_unchecked(alias_samplers.len()) }; - let i = rng.sample_with::(Length(length)); // index into events + let i = IndexUsize::sample_with(rng, Length(length)); // index into events let sample = &alias_samplers[i]; // Select E over K according to its bucket percentage U - if rng.sample_with::(sample.u) { + if Bernoulli::sample_with(rng, sample.u) { sample.e } else { sample.k diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index 490784d5c..4e3eeca67 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -4,7 +4,7 @@ use core::{fmt, marker::PhantomData}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::cogs::{ - rng::{Exponential, IndexU128, IndexU64, IndexUsize}, + distribution::{Exponential, IndexU128, IndexU64, IndexUsize}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index cf56e5058..004b09ddc 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -2,10 +2,10 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, + distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + MathsCore, Rng, SampledDistribution, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -69,7 +69,7 @@ where let total_rate = self.alias_sampler.total_weight(); if let Ok(lambda) = PositiveF64::new(total_rate.get()) { - let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); + let event_time = self.last_event_time + Exponential::sample_with(rng, Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index 34ed04bd0..5ab2d9e69 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -5,7 +5,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - rng::{Exponential, IndexU128, IndexU64, IndexUsize}, + distribution::{Exponential, IndexU128, IndexU64, IndexUsize}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, SpeciationProbability, TurnoverRate, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index ca1717dad..cc67138de 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -2,10 +2,10 @@ use core::{num::NonZeroUsize, ops::ControlFlow}; use necsim_core::{ cogs::{ - rng::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, + distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + SampledDistribution, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -76,7 +76,7 @@ where let total_rate = self.alias_sampler.total_weight(); if let Ok(lambda) = PositiveF64::new(total_rate.get()) { - let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); + let event_time = self.last_event_time + Exponential::sample_with(rng, Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); @@ -99,9 +99,10 @@ where // Safety: `lineages_at_location` must be >0 since // `chosen_active_location` can only be selected in that case - let chosen_lineage_index_at_location = rng.sample_with::(Length(unsafe { - NonZeroUsize::new_unchecked(lineages_at_location.len()) - })); + let chosen_lineage_index_at_location = IndexUsize::sample_with( + rng, + Length(unsafe { NonZeroUsize::new_unchecked(lineages_at_location.len()) }), + ); // Safety: reference clone is only used to then remove the lineage, which is // owned let chosen_lineage_reference = unsafe { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 6c5416b89..f1f24d996 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -11,8 +11,8 @@ use fnv::FnvBuildHasher; use hashbrown::HashMap; use necsim_core::cogs::{ - rng::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, MathsCore, Rng, + distribution::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, MathsCore, Rng, SampledDistribution, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -66,8 +66,10 @@ impl RejectionSamplingGroup { loop { // Safety: By construction, the group never contains zero elements - let index = rng - .sample_with::(Length(NonZeroUsize::new_unchecked(self.weights.len()))); + let index = IndexUsize::sample_with( + rng, + Length(NonZeroUsize::new_unchecked(self.weights.len())), + ); let height = rng.sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% @@ -207,9 +209,9 @@ impl DynamicAliasMethodIndexedSampler { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { - u128::from(rng.sample_with::(Length(total_weight))) + u128::from(IndexU64::sample_with(rng, Length(total_weight))) } else { - rng.sample_with::(Length(total_weight)) + IndexU128::sample_with(rng, Length(total_weight)) }; let mut cdf_acc = 0_u128; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 81bd218de..1d1e0872e 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -4,13 +4,16 @@ use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; use hashbrown::HashMap; use necsim_core::cogs::{ - rng::{IndexU128, IndexU64, IndexUsize, Length, SimpleRng}, - Backup, Distribution, DistributionSampler, Rng, RngCore, SeedableRng, + distribution::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, Rng, RngCore, SeedableRng, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core_maths::MathsCore; -use crate::cogs::{maths::intrinsics::IntrinsicsMathsCore, rng::wyhash::WyHash}; +use crate::cogs::{ + maths::intrinsics::IntrinsicsMathsCore, + rng::{simple::SimpleRng, wyhash::WyHash}, +}; use super::{ super::decompose_weight, DynamicAliasMethodIndexedSampler, EventLocation, @@ -1120,13 +1123,10 @@ impl Rng for DummyRng { map(self) } - fn sample_with(&mut self, params: D::Parameters) -> D::Sample - where - Self::Sampler: DistributionSampler, - { + fn with_rng Q, Q>(&mut self, inner: F) -> Q { let samplers = DummyDistributionSamplers; - samplers.sample_with(self, &samplers, params) + inner(self, &samplers) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 5ce8675bb..9760fcc69 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -8,8 +8,8 @@ use core::{ }; use necsim_core::cogs::{ - rng::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, MathsCore, Rng, + distribution::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, MathsCore, Rng, SampledDistribution, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -59,8 +59,10 @@ impl RejectionSamplingGroup { loop { // Safety: By construction, the group never contains zero elements - let index = rng - .sample_with::(Length(NonZeroUsize::new_unchecked(self.weights.len()))); + let index = IndexUsize::sample_with( + rng, + Length(NonZeroUsize::new_unchecked(self.weights.len())), + ); let height = rng.sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% @@ -141,9 +143,9 @@ impl DynamicAliasMethodStackSampler { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 } else if let Ok(total_weight) = NonZeroU64::try_from(total_weight) { - u128::from(rng.sample_with::(Length(total_weight))) + u128::from(IndexU64::sample_with(rng, Length(total_weight))) } else { - rng.sample_with::(Length(total_weight)) + IndexU128::sample_with(rng, Length(total_weight)) }; let mut cdf_acc = 0_u128; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index f9486183d..10715637c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -3,13 +3,16 @@ use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; use alloc::{vec, vec::Vec}; use necsim_core::cogs::{ - rng::{IndexU128, IndexU64, IndexUsize, Length, SimpleRng}, - Backup, Distribution, DistributionSampler, Rng, RngCore, SeedableRng, + distribution::{IndexU128, IndexU64, IndexUsize, Length}, + Backup, DistributionSampler, Rng, RngCore, SeedableRng, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core_maths::MathsCore; -use crate::cogs::{maths::intrinsics::IntrinsicsMathsCore, rng::wyhash::WyHash}; +use crate::cogs::{ + maths::intrinsics::IntrinsicsMathsCore, + rng::{simple::SimpleRng, wyhash::WyHash}, +}; use super::{super::decompose_weight, DynamicAliasMethodStackSampler, RejectionSamplingGroup}; @@ -619,13 +622,10 @@ impl Rng for DummyRng { map(self) } - fn sample_with(&mut self, params: D::Parameters) -> D::Sample - where - Self::Sampler: DistributionSampler, - { + fn with_rng Q, Q>(&mut self, inner: F) -> Q { let samplers = DummyDistributionSamplers; - samplers.sample_with(self, &samplers, params) + inner(self, &samplers) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index 339fa1036..50f26fc53 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::marker::PhantomData; use necsim_core::cogs::{ - rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, Backup, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, }; @@ -29,7 +29,7 @@ pub struct ClassicalActiveLineageSampler< > where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { active_lineage_references: Vec, @@ -51,7 +51,7 @@ impl< where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { #[must_use] @@ -147,7 +147,7 @@ impl< where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 3512b9ca3..24f6fbe49 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -5,9 +5,10 @@ use core::{ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, + SpeciationProbability, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -59,7 +60,7 @@ impl< where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, N: 'a, I: 'a; @@ -117,7 +118,7 @@ where let lambda = simulation.turnover_rate.get_uniform_turnover_rate() * PositiveF64::from(number_active_lineages); - let event_time = self.last_event_time + rng.sample_with::(Lambda(lambda)); + let event_time = self.last_event_time + Exponential::sample_with(rng, Lambda(lambda)); let next_event_time = PositiveF64::max_after(self.last_event_time, event_time); @@ -129,9 +130,12 @@ where // Safety: The outer if statement has already shown that the number // of remaining lineages is non-zero - let chosen_lineage_index = rng.sample_with::(Length(unsafe { - NonZeroUsize::new_unchecked(self.active_lineage_references.len()) - })); + let chosen_lineage_index = IndexUsize::sample_with( + rng, + Length(unsafe { + NonZeroUsize::new_unchecked(self.active_lineage_references.len()) + }), + ); let chosen_lineage_reference = self .active_lineage_references .swap_remove(chosen_lineage_index); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs index 312603e7d..b6db567ba 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/const.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, + cogs::{rng::HabitatPrimeableRng, Habitat, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index 002de74bb..ea48c2660 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Exponential, Lambda}, - DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, + distribution::{Exponential, Lambda}, + rng::HabitatPrimeableRng, + DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, TurnoverRate, }, landscape::IndexedLocation, @@ -67,7 +68,7 @@ where let mut sub_index: u64 = 0; loop { - event_time += rng.sample_with::(Lambda(lambda)); + event_time += Exponential::sample_with(rng, Lambda(lambda)); sub_index = sub_index.wrapping_add(INV_PHI); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs index 386738869..08844e755 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, TurnoverRate}, + cogs::{rng::HabitatPrimeableRng, Habitat, MathsCore, PrimeableRng, Rng, TurnoverRate}, landscape::IndexedLocation, }; use necsim_core_bond::NonNegativeF64; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index e7e635446..6c3996ccc 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - rng::Event, DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, - Rng, TurnoverRate, + distribution::Bernoulli, rng::HabitatPrimeableRng, DistributionSampler, Habitat, MathsCore, + PrimeableRng, Rng, SampledDistribution, TurnoverRate, }, landscape::IndexedLocation, }; @@ -27,7 +27,7 @@ impl GeometricEventTimeSampler { impl, G: Rng, T: TurnoverRate> EventTimeSampler for GeometricEventTimeSampler where - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler, { #[inline] fn next_event_time_at_indexed_location_weakly_after( @@ -52,7 +52,7 @@ where rng.generator() .prime_with_habitat(habitat, indexed_location, time_step); - if rng.sample_with::(event_probability_per_step) { + if Bernoulli::sample_with(rng, event_probability_per_step) { break; } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index 0eb959300..5efdbc631 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Normal, Normal2D, UniformClosedOpenUnit}, - DistributionSampler, Habitat, HabitatPrimeableRng, MathsCore, PrimeableRng, Rng, + distribution::{Normal, Normal2D, UniformClosedOpenUnit}, + rng::HabitatPrimeableRng, + DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, TurnoverRate, }, landscape::IndexedLocation, @@ -62,7 +63,7 @@ where let mut prod = no_event_probability_per_step; let mut acc = no_event_probability_per_step; - let u = rng.sample::(); + let u = UniformClosedOpenUnit::sample(rng); while u > acc && prod > 0.0_f64 { poisson += 1; @@ -74,13 +75,15 @@ where } else { // Fallback in case no_event_probability_per_step underflows #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let normal_as_poisson = rng - .sample_with::(Normal { + let normal_as_poisson = Normal2D::sample_with( + rng, + Normal { mu: lambda_per_step.get(), sigma: lambda_per_step.sqrt::(), - }) - .0 - .max(0.0_f64) as u32; + }, + ) + .0 + .max(0.0_f64) as u32; normal_as_poisson }; @@ -90,7 +93,7 @@ where for event_index in 0..number_events_at_time_steps { #[allow(clippy::cast_precision_loss)] let event_time = (NonNegativeF64::from(time_step) - + NonNegativeF64::from(rng.sample::())) + + NonNegativeF64::from(UniformClosedOpenUnit::sample(rng))) * self.delta_t; if event_time > time { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs index 9642d7979..739ebc498 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, Backup, DispersalSampler, DistributionSampler, EmigrationExit, - Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, Backup, DispersalSampler, DistributionSampler, + EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs index fb951a52a..b0a4beccf 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs @@ -2,8 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, ActiveLineageSampler, DispersalSampler, DistributionSampler, - EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, ActiveLineageSampler, DispersalSampler, + DistributionSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, + SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs index 1e197de68..2962f86ac 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs @@ -1,6 +1,6 @@ use necsim_core::cogs::{ - rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, - MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, EmigrationExit, + Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }; use necsim_core::lineage::Lineage; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index cb1242313..a1a939361 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -2,8 +2,9 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - rng::{Normal, Normal2D}, - Backup, DispersalSampler, DistributionSampler, MathsCore, Rng, SeparableDispersalSampler, + distribution::{Normal, Normal2D}, + Backup, DispersalSampler, DistributionSampler, MathsCore, Rng, SampledDistribution, + SeparableDispersalSampler, }, landscape::Location, }; @@ -77,10 +78,13 @@ where ) -> Location { const WRAP: i64 = 1 << 32; - let (dx, dy): (f64, f64) = rng.sample_with::(Normal { - mu: 0.0_f64, - sigma: self.sigma, - }); + let (dx, dy): (f64, f64) = Normal2D::sample_with( + rng, + Normal { + mu: 0.0_f64, + sigma: self.sigma, + }, + ); // Discrete dispersal assumes lineage positions are centred on (0.5, 0.5), // i.e. |dispersal| >= 0.5 changes the cell diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs index 302921b3e..c7302f79d 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, }, landscape::Location, @@ -13,7 +13,7 @@ impl, G: Rng> DispersalSampler for InMemoryAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs index 87dda5998..494bb6735 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, Backup, DistributionSampler, Habitat, MathsCore, Rng, }, landscape::Location, @@ -23,7 +23,7 @@ mod dispersal; pub struct InMemoryAliasDispersalSampler, G: Rng> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { alias_dispersal: Array2D>>, marker: PhantomData<(M, H, G)>, @@ -34,7 +34,7 @@ impl, G: Rng> InMemoryDispersalSampler for InMemoryAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { /// Creates a new `InMemoryAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -90,7 +90,7 @@ where impl, G: Rng> Backup for InMemoryAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs index cc0f41401..36ceb64bd 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{rng::UniformClosedOpenUnit, DistributionSampler, Habitat, MathsCore, Rng}, + cogs::{distribution::UniformClosedOpenUnit, DistributionSampler, Habitat, MathsCore, Rng}, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs index 9ca1dadec..7cfacdd37 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs @@ -1,6 +1,7 @@ use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, + MathsCore, Rng, SampledDistribution, }, landscape::Location, }; @@ -30,7 +31,7 @@ where let cumulative_dispersals_at_location = &self.cumulative_dispersal [location_index * habitat_area..(location_index + 1) * habitat_area]; - let cumulative_percentage_sample = rng.sample::().into(); + let cumulative_percentage_sample = UniformClosedOpenUnit::sample(rng).into(); let dispersal_target_index = usize::min( match cumulative_dispersals_at_location.binary_search(&cumulative_percentage_sample) { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs index 7a658eb1b..47f0fd148 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs @@ -3,7 +3,9 @@ use core::marker::PhantomData; use alloc::{boxed::Box, vec}; use necsim_core::{ - cogs::{rng::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, MathsCore, Rng}, + cogs::{ + distribution::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, MathsCore, Rng, + }, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs index 06189f91a..6c3892329 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs @@ -2,7 +2,7 @@ use core::ops::Range; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, }, landscape::Location, @@ -17,7 +17,7 @@ impl, G: Rng> DispersalSampler for InMemoryPackedAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs index ec27a0fa1..0c2c079dc 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs @@ -6,7 +6,7 @@ use r#final::Final; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, Backup, DistributionSampler, Habitat, MathsCore, Rng, }, landscape::Location, @@ -48,7 +48,7 @@ impl From for Range { pub struct InMemoryPackedAliasDispersalSampler, G: Rng> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[cfg_attr(feature = "cuda", cuda(embed))] alias_dispersal_ranges: Final>, @@ -62,7 +62,7 @@ impl, G: Rng> InMemoryDispersalSampler for InMemoryPackedAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { /// Creates a new `InMemoryPackedAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -126,7 +126,7 @@ impl, G: Rng> core::fmt::Debug for InMemoryPackedAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct(stringify!(InMemoryPackedAliasDispersalSampler)) @@ -147,7 +147,7 @@ where impl, G: Rng> Backup for InMemoryPackedAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index 437ec6bb2..7e254f244 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, - DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, SeparableDispersalSampler, + distribution::{Bernoulli, IndexUsize}, + DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, + SeparableDispersalSampler, }, landscape::Location, }; @@ -14,7 +15,7 @@ impl, G: Rng> DispersalSampler for InMemorySeparableAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] fn sample_dispersal_from_location( @@ -31,7 +32,7 @@ where } if self_dispersal_at_location > 0.0_f64 - && rng.sample_with::(self_dispersal_at_location) + && Bernoulli::sample_with(rng, self_dispersal_at_location) { return location.clone(); } @@ -45,7 +46,7 @@ impl, G: Rng> SeparableDispersalSampler for InMemorySeparableAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs index 0d6604292..f5c313d8d 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, Backup, DistributionSampler, Habitat, MathsCore, Rng, }, landscape::Location, @@ -23,7 +23,7 @@ mod dispersal; pub struct InMemorySeparableAliasDispersalSampler, G: Rng> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { alias_dispersal: Array2D>>, self_dispersal: Array2D, @@ -35,7 +35,7 @@ impl, G: Rng> InMemoryDispersalSampler for InMemorySeparableAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { /// Creates a new `InMemorySeparableAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -126,7 +126,7 @@ impl, G: Rng> Backup for InMemorySeparableAliasDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs index 7be0ddfd3..90d300035 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs @@ -2,9 +2,9 @@ use core::{marker::PhantomData, num::NonZeroU64}; use necsim_core::{ cogs::{ - rng::{IndexU64, Length}, + distribution::{IndexU64, Length}, Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - SeparableDispersalSampler, + SampledDistribution, SeparableDispersalSampler, }, landscape::Location, }; @@ -65,9 +65,10 @@ where habitat.get_extent().width().get() * habitat.get_extent().height().get(); // Safety: habitat width and height are both > 0 - let dispersal_target_index = rng.sample_with::(Length(unsafe { - NonZeroU64::new_unchecked(habitat_index_max) - })); + let dispersal_target_index = IndexU64::sample_with( + rng, + Length(unsafe { NonZeroU64::new_unchecked(habitat_index_max) }), + ); #[allow(clippy::cast_possible_truncation)] Location::new( @@ -106,9 +107,10 @@ where let dispersal_target_index = { // Safety: by PRE, `habitat_index_max` > 1 - let dispersal_target_index = rng.sample_with::(Length(unsafe { - NonZeroU64::new_unchecked(habitat_index_max - 1) - })); + let dispersal_target_index = IndexU64::sample_with( + rng, + Length(unsafe { NonZeroU64::new_unchecked(habitat_index_max - 1) }), + ); if dispersal_target_index >= current_location_index { dispersal_target_index + 1 diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index f8c442481..df10d55bd 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexU64}, + distribution::{Bernoulli, IndexU64}, Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - SeparableDispersalSampler, + SampledDistribution, SeparableDispersalSampler, }, landscape::Location, }; @@ -20,7 +20,7 @@ use crate::cogs::{ pub struct SpatiallyImplicitDispersalSampler> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[cfg_attr(feature = "cuda", cuda(embed))] local: NonSpatialDispersalSampler, @@ -32,7 +32,7 @@ where impl> SpatiallyImplicitDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] pub fn new(local_migration_probability_per_generation: PositiveUnitF64) -> Self { @@ -48,7 +48,7 @@ where impl> Backup for SpatiallyImplicitDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -65,7 +65,7 @@ impl> DispersalSampler, G for SpatiallyImplicitDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -84,7 +84,7 @@ where // By PRE, location must be habitable, i.e. either in the local or the meta // habitat if habitat.local().get_extent().contains(location) { - if rng.sample_with::(self.local_migration_probability_per_generation.into()) { + if Bernoulli::sample_with(rng, self.local_migration_probability_per_generation.into()) { // Provide a dummpy Location in the meta community to disperse from self.meta.sample_dispersal_from_location( &Location::new( @@ -110,7 +110,7 @@ impl> SeparableDispersalSampler where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -129,7 +129,7 @@ where // By PRE, location must be habitable, i.e. either in the local or the meta // habitat if habitat.local().get_extent().contains(location) { - if rng.sample_with::(self.local_migration_probability_per_generation.into()) { + if Bernoulli::sample_with(rng, self.local_migration_probability_per_generation.into()) { // Provide a dummpy Location in the meta community to disperse from // As the individual is dispersing to a different community, // we can use standard dispersal in the meta community diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs index 22c70b7eb..e34611409 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs @@ -1,7 +1,8 @@ use necsim_core::{ cogs::{ - Backup, DispersalSampler, Habitat, MathsCore, Rng, - SeparableDispersalSampler, DistributionSampler, rng::{Normal2D, Event}, + distribution::{Bernoulli, Normal2D}, + Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + SampledDistribution, SeparableDispersalSampler, }, landscape::Location, }; @@ -18,8 +19,8 @@ use crate::cogs::{ #[cfg_attr(feature = "cuda", cuda(free = "M"))] pub struct WrappingNoiseApproximateNormalDispersalSampler> where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[cfg_attr(feature = "cuda", cuda(embed))] inner: AlmostInfiniteNormalDispersalSampler, @@ -27,8 +28,8 @@ where impl> WrappingNoiseApproximateNormalDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { @@ -41,8 +42,8 @@ where #[contract_trait] impl> Backup for WrappingNoiseApproximateNormalDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -55,8 +56,8 @@ where impl> DispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] #[inline] @@ -71,7 +72,10 @@ where // targets are rejected. // If seperable dispersal is not required, this can be implemented as a // direct rejection sampling loop instead. - if rng.sample_with::(self.get_self_dispersal_probability_at_location(location, habitat)) { + if Bernoulli::sample_with( + rng, + self.get_self_dispersal_probability_at_location(location, habitat), + ) { location.clone() } else { self.sample_non_self_dispersal_from_location(location, habitat, rng) @@ -83,8 +87,8 @@ where impl> SeparableDispersalSampler, G> for WrappingNoiseApproximateNormalDispersalSampler where - G::Sampler: DistributionSampler, - G::Sampler: DistributionSampler, + G::Sampler: DistributionSampler + + DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs index 969a16cd7..4ad3d10ba 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs @@ -5,7 +5,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, rng::UniformClosedOpenUnit, Backup, + coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, Backup, DistributionSampler, EmigrationExit, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs index 661d30b8b..ed5a2c8b6 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, rng::UniformClosedOpenUnit, Backup, + coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, Backup, DistributionSampler, EmigrationExit, Habitat, MathsCore, Rng, }, landscape::{IndexedLocation, Location}, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs index 39c5d85db..4249a52ca 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs @@ -2,10 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, - rng::UniformClosedOpenUnit, Backup, CoalescenceSampler, DistributionSampler, + coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, + event_sampler::EventHandler, Backup, CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, - SeparableDispersalSampler, SpeciationProbability, TurnoverRate, + SampledDistribution, SeparableDispersalSampler, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -143,7 +143,7 @@ where false, ); - let event_sample = probability_at_location.total() * rng.sample::(); + let event_sample = probability_at_location.total() * UniformClosedOpenUnit::sample(rng); if event_sample < probability_at_location.speciation() { // Speciation Event diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index 07eb9c646..8877a9ffe 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -3,11 +3,11 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, + distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - rng::{Event, UniformClosedOpenUnit}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SampledDistribution, + SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -31,7 +31,7 @@ pub struct UnconditionalGillespieEventSampler< T: TurnoverRate, N: SpeciationProbability, > where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { #[allow(clippy::type_complexity)] @@ -50,7 +50,7 @@ impl< N: SpeciationProbability, > Default for UnconditionalGillespieEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { fn default() -> Self { @@ -73,7 +73,7 @@ impl< N: SpeciationProbability, > Backup for UnconditionalGillespieEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { @@ -97,7 +97,7 @@ impl< > EventSampler for UnconditionalGillespieEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { #[must_use] @@ -124,7 +124,8 @@ where }: EventHandler, auxiliary: Aux, ) -> Q { - if rng.sample_with::( + if Bernoulli::sample_with( + rng, simulation .speciation_probability .get_speciation_probability_at_location( @@ -207,7 +208,7 @@ impl< > GillespieEventSampler for UnconditionalGillespieEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { #[must_use] diff --git a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs index 6592ebdf8..9a35ff8b2 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs @@ -2,10 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, event_sampler::EventHandler, - rng::UniformClosedOpenUnit, Backup, CoalescenceSampler, DispersalSampler, + coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, + event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, EventSampler, Habitat, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + SampledDistribution, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -156,7 +156,7 @@ where }: EventHandler, auxiliary: Aux, ) -> Q { - let speciation_sample = rng.sample::(); + let speciation_sample = UniformClosedOpenUnit::sample(rng); SpeciationSample::update_min( &mut self.min_spec_sample, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index 2b6da1505..3081e0ab4 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -3,11 +3,11 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, + distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - rng::{Event, UniformClosedOpenUnit}, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, - TurnoverRate, + EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, + SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -28,7 +28,7 @@ pub struct UnconditionalEventSampler< T: TurnoverRate, N: SpeciationProbability, > where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { #[allow(clippy::type_complexity)] @@ -47,7 +47,7 @@ impl< N: SpeciationProbability, > Default for UnconditionalEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { fn default() -> Self { @@ -70,7 +70,7 @@ impl< N: SpeciationProbability, > Backup for UnconditionalEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { @@ -94,7 +94,7 @@ impl< > EventSampler for UnconditionalEventSampler where - G::Sampler: DistributionSampler + G::Sampler: DistributionSampler + DistributionSampler, { #[must_use] @@ -121,7 +121,8 @@ where }: EventHandler, auxiliary: Aux, ) -> Q { - if rng.sample_with::( + if Bernoulli::sample_with( + rng, simulation .speciation_probability .get_speciation_probability_at_location( diff --git a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs index 146b8ed81..4249f254b 100644 --- a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs +++ b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs @@ -6,8 +6,9 @@ use r#final::Final; use necsim_core::{ cogs::{ - rng::{IndexU64, Length}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, UniformlySampleableHabitat, + distribution::{IndexU64, Length}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, + UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -117,7 +118,7 @@ where #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { let indexed_location_index = - rng.sample_with::(Length(self.get_total_habitat().into())); + IndexU64::sample_with(rng, Length(self.get_total_habitat().into())); let location_index = match self.u64_injection.binary_search(&indexed_location_index) { Ok(index) => index, diff --git a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs index 03d421a42..b4a900fc8 100644 --- a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs @@ -5,8 +5,9 @@ use core::{ use necsim_core::{ cogs::{ - rng::{IndexU64, Length}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, UniformlySampleableHabitat, + distribution::{IndexU64, Length}, + Backup, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, + UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -130,9 +131,10 @@ where self.extent.width().get() * self.extent.height().get() * u64::from(self.deme.get()); // Safety: habitat width, height, and deme are all > 0 - let mut dispersal_target_index = rng.sample_with::(Length(unsafe { - NonZeroU64::new_unchecked(habitat_index_max) - })); + let mut dispersal_target_index = IndexU64::sample_with( + rng, + Length(unsafe { NonZeroU64::new_unchecked(habitat_index_max) }), + ); #[allow(clippy::cast_possible_truncation)] let index = (dispersal_target_index % u64::from(self.deme.get())) as u32; dispersal_target_index /= u64::from(self.deme.get()); diff --git a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs index e029edf6c..964eb63a4 100644 --- a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs @@ -2,7 +2,7 @@ use core::num::NonZeroU32; use necsim_core::{ cogs::{ - rng::IndexU64, Backup, DistributionSampler, Habitat, MathsCore, Rng, + distribution::IndexU64, Backup, DistributionSampler, Habitat, MathsCore, Rng, UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, diff --git a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs index 5d87ec583..a3765b19f 100644 --- a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs +++ b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs @@ -10,7 +10,7 @@ mod opensimplex_noise; use opensimplex_noise::OpenSimplexNoise; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat, RngCore}, + cogs::{Backup, Habitat, MathsCore, Rng, RngCore, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; diff --git a/necsim/impls/no-std/src/cogs/rng/mod.rs b/necsim/impls/no-std/src/cogs/rng/mod.rs index 43c2bf6e6..62fe40a87 100644 --- a/necsim/impls/no-std/src/cogs/rng/mod.rs +++ b/necsim/impls/no-std/src/cogs/rng/mod.rs @@ -1,3 +1,4 @@ pub mod rand; pub mod seahash; +pub mod simple; pub mod wyhash; diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs new file mode 100644 index 000000000..010aa98af --- /dev/null +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -0,0 +1,553 @@ +use core::{ + marker::PhantomData, + num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, +}; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use necsim_core::cogs::{ + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, + Normal2D, Poisson, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, + }, + Backup, DistributionSampler, MathsCore, Rng, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; + +#[derive(Clone, Debug, TypeLayout)] +#[allow(clippy::module_name_repetitions)] +#[layout(free = "M")] +#[repr(transparent)] +pub struct SimpleRng { + inner: R, + marker: PhantomData, +} + +impl Serialize for SimpleRng { + fn serialize(&self, serializer: S) -> Result { + self.inner.serialize(serializer) + } +} + +impl<'de, M: MathsCore, R: RngCore> Deserialize<'de> for SimpleRng { + fn deserialize>(deserializer: D) -> Result { + let inner = R::deserialize(deserializer)?; + + Ok(Self { + inner, + marker: PhantomData::, + }) + } +} + +#[contract_trait] +impl Backup for SimpleRng { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: self.inner.backup_unchecked(), + marker: PhantomData::, + } + } +} + +impl RngCore for SimpleRng { + type Seed = R::Seed; + + #[must_use] + fn from_seed(seed: Self::Seed) -> Self { + Self { + inner: R::from_seed(seed), + marker: PhantomData::, + } + } + + #[must_use] + fn sample_u64(&mut self) -> u64 { + self.inner.sample_u64() + } +} + +impl Rng for SimpleRng { + type Generator = R; + type Sampler = SimplerDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + &mut self.inner + } + + fn map_generator Self::Generator>(self, map: F) -> Self { + let SimpleRng { inner, marker } = self; + + SimpleRng { + inner: map(inner), + marker, + } + } + + fn with_rng Q, Q>(&mut self, inner: F) -> Q { + let samplers = SimplerDistributionSamplers { + _marker: PhantomData::<(M, R)>, + }; + + inner(&mut self.inner, &samplers) + } +} + +#[allow(clippy::module_name_repetitions)] +pub struct SimplerDistributionSamplers { + _marker: PhantomData<(M, R)>, +} + +impl DistributionSampler + for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = + (((rng.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> usize { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as usize; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u32 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let index = M::floor(u01.get() * f64::from(length.get())) as u32; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as u64; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { + let length = params.0; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + #[allow( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss + )] + let index = M::floor(u01.get() * (length.get() as f64)) as u128; + + // Safety in case of f64 rounding errors + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> NonNegativeF64 { + let lambda = params.0; + + let u01: OpenClosedUnitF64 = samplers.sample(rng, samplers); + + // Inverse transform sample: X = -ln(U(0,1]) / lambda + -u01.ln::() / lambda + } +} + +impl< + M: MathsCore, + R: RngCore, + S: DistributionSampler + + DistributionSampler, + > DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> usize { + let lambda = params.0; + let no_event_probability = M::exp(-lambda.get()); + + if no_event_probability <= 0.0_f64 { + // Fallback in case no_event_probability_per_step underflows + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let normal_as_poisson = DistributionSampler::::sample_with( + samplers, + rng, + samplers, + Normal { + mu: lambda.get(), + sigma: NonNegativeF64::from(lambda).sqrt::(), + }, + ) + .0 + .max(0.0_f64) as usize; + + return normal_as_poisson; + } + + // https://en.wikipedia.org/wiki/Poisson_distribution#cite_ref-Devroye1986_54-0 + let mut poisson = 0_usize; + let mut prod = no_event_probability; + let mut acc = no_event_probability; + + let u = + DistributionSampler::::sample(samplers, rng, samplers); + + #[allow(clippy::cast_precision_loss)] + while u > acc && prod > 0.0_f64 { + poisson += 1; + prod *= lambda.get() / (poisson as f64); + acc += prod; + } + + poisson + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: ClosedUnitF64) -> bool { + let probability = params; + + let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + + // if probability == 1, then U[0, 1) always < 1.0 + // if probability == 0, then U[0, 1) never < 0.0 + u01 < probability + } +} + +impl< + M: MathsCore, + R: RngCore, + S: DistributionSampler + + DistributionSampler, + > DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { + // Basic Box-Muller transform + let u0 = + DistributionSampler::::sample(samplers, rng, samplers); + let u1 = + DistributionSampler::::sample(samplers, rng, samplers); + + let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); + let theta = -core::f64::consts::TAU * u1.get(); + + (r * M::sin(theta), r * M::cos(theta)) + } +} + +impl> + DistributionSampler for SimplerDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_with(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { + let (z0, z1) = samplers.sample(rng, samplers); + + ( + z0 * params.sigma.get() + params.mu, + z1 * params.sigma.get() + params.mu, + ) + } +} + +/*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] +#[allow(clippy::module_name_repetitions)] +#[contract_trait] +pub trait RngSampler: RngCore { + #[must_use] + #[inline] + /// Samples a uniform sample within `[0.0, 1.0)`, i.e. `0.0 <= X < 1.0` + fn sample_uniform_closed_open(&mut self) -> ClosedOpenUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = ((self.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } + + #[must_use] + #[inline] + /// Samples a uniform sample within `(0.0, 1.0]`, i.e. `0.0 < X <= 1.0` + fn sample_uniform_open_closed(&mut self) -> OpenClosedUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + #[allow(clippy::cast_precision_loss)] + let u01 = + (((self.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } + + #[must_use] + #[inline] + #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] + fn sample_index(&mut self, length: NonZeroUsize) -> usize { + #[cfg(target_pointer_width = "32")] + #[allow(clippy::cast_possible_truncation)] + { + self.sample_index_u32(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }) + as usize + } + #[cfg(target_pointer_width = "64")] + #[allow(clippy::cast_possible_truncation)] + { + self.sample_index_u64(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }) + as usize + } + } + + #[must_use] + #[inline] + #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] + fn sample_index_u32(&mut self, length: NonZeroU32) -> u32 { + // TODO: Check if delegation to `sample_index_u64` is faster + + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u64 = !0 >> 32; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = self.sample_u64(); + + let sample_check_lo = (raw & LOWER_MASK) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_lo as u32) <= acceptance_zone { + return (sample_check_lo >> 32) as u32; + } + + let sample_check_hi = (raw >> 32) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_hi as u32) <= acceptance_zone { + return (sample_check_hi >> 32) as u32; + } + } + } + + #[must_use] + #[inline] + #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] + fn sample_index_u64(&mut self, length: NonZeroU64) -> u64 { + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = self.sample_u64(); + + let sample_check = u128::from(raw) * u128::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check as u64) <= acceptance_zone { + return (sample_check >> 64) as u64; + } + } + } + + #[must_use] + #[inline] + #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] + fn sample_index_u128(&mut self, length: NonZeroU128) -> u128 { + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u128 = !0 >> 64; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw_hi = u128::from(self.sample_u64()); + let raw_lo = u128::from(self.sample_u64()); + + // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length + let mut low = raw_lo * (length.get() & LOWER_MASK); + let mut t = low >> 64; + low &= LOWER_MASK; + t += raw_hi * (length.get() & LOWER_MASK); + low += (t & LOWER_MASK) << 64; + let mut high = t >> 64; + t = low >> 64; + low &= LOWER_MASK; + t += (length.get() >> 64) * raw_lo; + low += (t & LOWER_MASK) << 64; + high += t >> 64; + high += raw_hi * (length.get() >> 64); + + let sample = high; + let check = low; + + if check <= acceptance_zone { + return sample; + } + } + } + + #[must_use] + #[inline] + fn sample_exponential(&mut self, lambda: PositiveF64) -> NonNegativeF64 { + // Inverse transform sample: X = -ln(U(0,1]) / lambda + -self.sample_uniform_open_closed().ln::() / lambda + } + + #[must_use] + #[inline] + fn sample_event(&mut self, probability: ClosedUnitF64) -> bool { + // if probability == 1, then U[0, 1) always < 1.0 + // if probability == 0, then U[0, 1) never < 0.0 + self.sample_uniform_closed_open() < probability + } + + #[must_use] + #[inline] + fn sample_2d_standard_normal(&mut self) -> (f64, f64) { + // Basic Box-Muller transform + let u0 = self.sample_uniform_open_closed(); + let u1 = self.sample_uniform_closed_open(); + + let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); + let theta = -core::f64::consts::TAU * u1.get(); + + (r * M::sin(theta), r * M::cos(theta)) + } + + #[must_use] + #[inline] + fn sample_2d_normal(&mut self, mu: f64, sigma: NonNegativeF64) -> (f64, f64) { + let (z0, z1) = self.sample_2d_standard_normal(); + + (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + } +} + +impl> RngSampler for R {}*/ diff --git a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs index a442883df..f01b3032f 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, - PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, + MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::Reporter, diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index 292e6f78f..63eab7f35 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, - PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, + MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, event::DispersalEvent, landscape::IndexedLocation, diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs index b7508aaf1..a2e753bc3 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs @@ -8,8 +8,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, MathsCore, - PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, + MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::{boolean::Boolean, Reporter}, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs index c535f74b9..58e69d69e 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs @@ -2,9 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, - DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, + DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, reporter::Reporter, simulation::Simulation, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs index deebee9a9..3450fc1d7 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs @@ -2,9 +2,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, - DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, + DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, + MathsCore, Rng, SpeciationProbability, TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs index 3924e6ffd..a0b6838cd 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs @@ -3,7 +3,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - backup::BackedUp, rng::UniformClosedOpenUnit, ActiveLineageSampler, Backup, + backup::BackedUp, distribution::UniformClosedOpenUnit, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs index acc862bf6..789568ab4 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs @@ -2,7 +2,7 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ - rng::UniformClosedOpenUnit, ActiveLineageSampler, Backup, CoalescenceSampler, + distribution::UniformClosedOpenUnit, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }, diff --git a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs index 255da478e..8a342b4a4 100644 --- a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs +++ b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs @@ -34,7 +34,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -56,7 +56,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -72,7 +72,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -92,7 +92,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -107,7 +107,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -118,7 +118,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -136,7 +136,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -147,7 +147,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -158,7 +158,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -174,7 +174,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -185,7 +185,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -196,7 +196,7 @@ macro_rules! link_kernel { $habitat, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -221,7 +221,7 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -239,7 +239,7 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -257,7 +257,7 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -278,7 +278,7 @@ link_kernel!( >, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -299,7 +299,7 @@ link_kernel!( >, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_core::cogs::rng::SimpleRng< + necsim_impls_no_std::cogs::rng::simple::SimpleRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, @@ -317,9 +317,7 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash< - necsim_impls_cuda::cogs::maths::NvptxMathsCore - >, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, >, >, necsim_impls_no_std::cogs::turnover_rate::uniform::UniformTurnoverRate, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs index ab03e1758..fd7620ecb 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -55,7 +55,7 @@ where O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs index 499f2d0f4..a0d5c5188 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -34,7 +34,7 @@ where O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs index 09f931146..3ebb5b28e 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -40,7 +40,7 @@ pub trait CudaLineageStoreSampleInitialiser< O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type DispersalSampler: DispersalSampler + RustToCuda; diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs index 417bbb08e..77228019f 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -44,7 +44,7 @@ where O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index 90cbc9350..e1a7fc747 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -1,10 +1,6 @@ use std::marker::PhantomData; -use necsim_core::{ - cogs::{rng::SimpleRng, MathsCore}, - reporter::Reporter, - simulation::SimulationBuilder, -}; +use necsim_core::{cogs::MathsCore, reporter::Reporter, simulation::SimulationBuilder}; use necsim_core_bond::NonNegativeF64; use necsim_impls_cuda::cogs::rng::CudaRng; @@ -20,7 +16,7 @@ use necsim_impls_no_std::{ origin_sampler::{ decomposition::DecompositionOriginSampler, pre_sampler::OriginPreSampler, }, - rng::wyhash::WyHash, + rng::{simple::SimpleRng, wyhash::WyHash}, }, parallelisation::Status, }; diff --git a/rustcoalescence/algorithms/cuda/src/lib.rs b/rustcoalescence/algorithms/cuda/src/lib.rs index a88d58a51..df9cc279f 100644 --- a/rustcoalescence/algorithms/cuda/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/src/lib.rs @@ -6,11 +6,7 @@ #[macro_use] extern crate serde_derive_state; -use necsim_core::{ - cogs::{rng::SimpleRng, MathsCore}, - lineage::Lineage, - reporter::Reporter, -}; +use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_cuda::cogs::{maths::NvptxMathsCore, rng::CudaRng}; @@ -31,7 +27,7 @@ use necsim_impls_no_std::cogs::{ immigration_entry::never::NeverImmigrationEntry, lineage_store::independent::IndependentLineageStore, origin_sampler::pre_sampler::OriginPreSampler, - rng::wyhash::WyHash, + rng::{simple::SimpleRng, wyhash::WyHash}, }; use necsim_partitioning_core::{partition::Partition, LocalPartition}; diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs index 1b05a8d52..4a4f1bf86 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs @@ -1,6 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, + }, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, }, @@ -52,7 +54,7 @@ where O::DispersalSampler>: SeparableDispersalSampler, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs index 8229dd02c..1438086de 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs @@ -1,6 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, + }, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, }, @@ -29,7 +31,7 @@ where O::DispersalSampler>: SeparableDispersalSampler, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs index 537dc8e76..4b66a3f9e 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, ActiveLineageSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, }, @@ -31,7 +31,7 @@ pub trait EventSkippingLineageStoreSampleInitialiser< O::DispersalSampler>: SeparableDispersalSampler, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type DispersalSampler: SeparableDispersalSampler; diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs index a2ba351e6..c386ab160 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs @@ -1,6 +1,8 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit}, + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, + }, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, }, @@ -36,7 +38,7 @@ where O::DispersalSampler>: SeparableDispersalSampler, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index a8dc76277..5752ee4f6 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -2,7 +2,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, ActiveLineageSampler, DistributionSampler, GloballyCoherentLineageStore, MathsCore, Rng, SeparableDispersalSampler, SplittableRng, }, @@ -60,7 +60,7 @@ where O::DispersalSampler>: SeparableDispersalSampler, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { match args.parallelism_mode { diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs index f67f83e60..457b87692 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{rng::SimpleRng, GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler}, + cogs::{GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler}, lineage::Lineage, reporter::Reporter, }; @@ -9,6 +9,7 @@ use necsim_impls_no_std::cogs::{ dispersal_sampler::in_memory::separable_alias::InMemorySeparableAliasDispersalSampler, lineage_store::coherent::globally::gillespie::GillespieLineageStore, maths::intrinsics::IntrinsicsMathsCore, origin_sampler::pre_sampler::OriginPreSampler, + rng::simple::SimpleRng, }; use necsim_impls_std::cogs::rng::pcg::Pcg; use necsim_partitioning_core::{partition::Partition, LocalPartition}; diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index 16121c022..004e71036 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -51,7 +51,7 @@ impl, M: MathsCore, G: Rng, O: Scenario< ClassicalLineageStoreSampleInitialiser> for FixUpInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler, { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index f6ba30fdc..f1c629bf1 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -25,7 +25,7 @@ impl, O: Scenario> ClassicalLineageStoreSampleInit for GenesisInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler, { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index f5226dbe3..f8459676d 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -25,7 +25,7 @@ pub mod resume; pub trait ClassicalLineageStoreSampleInitialiser, O: Scenario, Error> where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { type DispersalSampler: DispersalSampler; diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index 72254ed31..484f068a4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -31,7 +31,7 @@ impl, M: MathsCore, G: Rng, O: Scenario< ClassicalLineageStoreSampleInitialiser> for ResumeInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler, { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 5321faaa8..298e5900a 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -2,7 +2,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, SplittableRng, }, @@ -61,7 +61,7 @@ where O::LineageStore>: LocallyCoherentLineageStore, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { match args.parallelism_mode { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs index a2fbf3f77..61b3b150d 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{rng::SimpleRng, LocallyCoherentLineageStore, MathsCore}, + cogs::{LocallyCoherentLineageStore, MathsCore}, lineage::Lineage, reporter::Reporter, }; @@ -7,7 +7,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::{ lineage_store::coherent::locally::classical::ClassicalLineageStore, - origin_sampler::pre_sampler::OriginPreSampler, turnover_rate::uniform::UniformTurnoverRate, + origin_sampler::pre_sampler::OriginPreSampler, rng::simple::SimpleRng, + turnover_rate::uniform::UniformTurnoverRate, }; use necsim_impls_std::cogs::rng::pcg::Pcg; use necsim_partitioning_core::LocalPartition; diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs index ed4797930..43d853008 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -48,7 +48,7 @@ impl, M: MathsCore, G: Rng, O: Scenario< GillespieLineageStoreSampleInitialiser> for FixUpInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs index 40704a80d..a0ce35c3e 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -25,7 +25,7 @@ impl, O: Scenario> GillespieLineageStoreSampleInit for GenesisInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs index eadba6dc8..20370ee6b 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize}, + distribution::{Bernoulli, IndexUsize}, ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, @@ -24,7 +24,7 @@ pub mod resume; pub trait GillespieLineageStoreSampleInitialiser, O: Scenario, Error> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { type DispersalSampler: DispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs index 060ae98a8..8618cd4e2 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, Exponential, IndexU128, IndexU64, IndexUsize}, + distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, }, @@ -31,7 +31,7 @@ impl, M: MathsCore, G: Rng, O: Scenario< GillespieLineageStoreSampleInitialiser> for ResumeInitialiser where G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler + DistributionSampler + DistributionSampler, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index b106364b8..90c3db24d 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -2,7 +2,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, SplittableRng, }, @@ -60,7 +60,7 @@ where O::LineageStore>: LocallyCoherentLineageStore, G::Sampler: DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { match args.parallelism_mode { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs index 3aac781a1..728f34acf 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{rng::SimpleRng, LocallyCoherentLineageStore, MathsCore}, + cogs::{LocallyCoherentLineageStore, MathsCore}, lineage::Lineage, reporter::Reporter, }; @@ -7,7 +7,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::{ lineage_store::coherent::locally::classical::ClassicalLineageStore, - origin_sampler::pre_sampler::OriginPreSampler, + origin_sampler::pre_sampler::OriginPreSampler, rng::simple::SimpleRng, }; use necsim_impls_std::cogs::rng::pcg::Pcg; use necsim_partitioning_core::{partition::Partition, LocalPartition}; diff --git a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs index ddca78463..563e4adb3 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -48,7 +48,7 @@ impl< where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler, + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs index f00285217..88107b22b 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -27,7 +27,7 @@ impl, O: Scenario> where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler, + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs index f54da064d..f3de92c3d 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, }, lineage::Lineage, @@ -33,7 +33,7 @@ pub trait IndependentLineageStoreSampleInitialiser< > where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler, + + DistributionSampler, { type DispersalSampler: DispersalSampler; type ActiveLineageSampler + DistributionSampler - + DistributionSampler, + + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index bd0f88e53..fcbe5d1bd 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use necsim_core::{ cogs::{ - rng::{Event, IndexUsize, Normal2D, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize, Normal2D, UniformClosedOpenUnit}, DistributionSampler, MathsCore, PrimeableRng, Rng, }, reporter::Reporter, @@ -68,7 +68,7 @@ pub fn initialise_and_simulate< where G::Sampler: DistributionSampler + DistributionSampler - + DistributionSampler + + DistributionSampler + DistributionSampler, { match args.parallelism_mode { diff --git a/rustcoalescence/algorithms/independent/src/lib.rs b/rustcoalescence/algorithms/independent/src/lib.rs index faa502de1..dff7dde25 100644 --- a/rustcoalescence/algorithms/independent/src/lib.rs +++ b/rustcoalescence/algorithms/independent/src/lib.rs @@ -5,16 +5,14 @@ #[macro_use] extern crate serde_derive_state; -use necsim_core::{ - cogs::{rng::SimpleRng, MathsCore}, - lineage::Lineage, - reporter::Reporter, -}; +use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::{ - lineage_store::independent::IndependentLineageStore, maths::intrinsics::IntrinsicsMathsCore, - origin_sampler::pre_sampler::OriginPreSampler, rng::wyhash::WyHash, + lineage_store::independent::IndependentLineageStore, + maths::intrinsics::IntrinsicsMathsCore, + origin_sampler::pre_sampler::OriginPreSampler, + rng::{simple::SimpleRng, wyhash::WyHash}, }; use necsim_partitioning_core::{partition::Partition, LocalPartition}; diff --git a/rustcoalescence/scenarios/src/almost_infinite.rs b/rustcoalescence/scenarios/src/almost_infinite.rs index 8d645589c..6636731c9 100644 --- a/rustcoalescence/scenarios/src/almost_infinite.rs +++ b/rustcoalescence/scenarios/src/almost_infinite.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ - rng::Normal2D, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + distribution::Normal2D, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; diff --git a/rustcoalescence/scenarios/src/non_spatial.rs b/rustcoalescence/scenarios/src/non_spatial.rs index 7bb043702..571d54f6b 100644 --- a/rustcoalescence/scenarios/src/non_spatial.rs +++ b/rustcoalescence/scenarios/src/non_spatial.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ - rng::IndexU64, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + distribution::IndexU64, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, }; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs index 973f888ab..a7d6157fd 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs @@ -3,7 +3,8 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; use necsim_core::cogs::{ - rng::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, MathsCore, Rng, + distribution::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, + MathsCore, Rng, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs index fed318aa6..67c470e6c 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs @@ -3,7 +3,8 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; use necsim_core::cogs::{ - rng::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, MathsCore, Rng, + distribution::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, + MathsCore, Rng, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64, PositiveF64}; use necsim_partitioning_core::partition::Partition; diff --git a/rustcoalescence/scenarios/src/spatially_implicit.rs b/rustcoalescence/scenarios/src/spatially_implicit.rs index 37a64f123..5a29dcf51 100644 --- a/rustcoalescence/scenarios/src/spatially_implicit.rs +++ b/rustcoalescence/scenarios/src/spatially_implicit.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ - rng::{Event, IndexU64}, + distribution::{Bernoulli, IndexU64}, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, }; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; @@ -28,7 +28,7 @@ use crate::{Scenario, ScenarioParameters}; pub struct SpatiallyImplicitScenario> where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { habitat: SpatiallyImplicitHabitat, dispersal_sampler: SpatiallyImplicitDispersalSampler, @@ -51,7 +51,7 @@ pub struct SpatiallyImplicitArguments { impl> ScenarioParameters for SpatiallyImplicitScenario where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { type Arguments = SpatiallyImplicitArguments; type Error = !; @@ -60,7 +60,7 @@ where impl> Scenario for SpatiallyImplicitScenario where G::Sampler: DistributionSampler - + DistributionSampler, + + DistributionSampler, { type Decomposition = ModuloDecomposition; type DecompositionAuxiliary = (); diff --git a/rustcoalescence/scenarios/src/wrapping_noise.rs b/rustcoalescence/scenarios/src/wrapping_noise.rs index e5a954f0c..a83b1277a 100644 --- a/rustcoalescence/scenarios/src/wrapping_noise.rs +++ b/rustcoalescence/scenarios/src/wrapping_noise.rs @@ -3,7 +3,10 @@ use std::num::NonZeroUsize; use serde::{Deserialize, Serialize}; use necsim_core::{ - cogs::{DispersalSampler, LineageStore, MathsCore, RngCore}, + cogs::{ + distribution::{Bernoulli, Normal2D}, + DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + }, landscape::LandscapeExtent, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; @@ -26,7 +29,11 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct WrappingNoiseScenario> { +pub struct WrappingNoiseScenario> +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ sample: LandscapeExtent, habitat: WrappingNoiseHabitat, @@ -48,12 +55,20 @@ pub struct WrappingNoiseArguments { pub sigma: NonNegativeF64, } -impl> ScenarioParameters for WrappingNoiseScenario { +impl> ScenarioParameters for WrappingNoiseScenario +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ type Arguments = WrappingNoiseArguments; type Error = !; } -impl> Scenario for WrappingNoiseScenario { +impl> Scenario for WrappingNoiseScenario +where + G::Sampler: DistributionSampler + + DistributionSampler, +{ type Decomposition = RadialDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = From e0951e4e8b9578c05e9e4b6fd3987c4794d1829e Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Thu, 19 May 2022 11:10:41 +0000 Subject: [PATCH 09/21] Backup of refactoring progress for Rng + Samples --- necsim/impls/no-std/src/alias/packed.rs | 13 +++-- .../alias/individual/mod.rs | 49 +++++++++--------- .../alias/individual/sampler.rs | 17 +++---- .../alias/location/mod.rs | 51 +++++++++---------- .../alias/location/sampler.rs | 13 +++-- .../alias/sampler/indexed/mod.rs | 29 +++++------ .../alias/sampler/stack/mod.rs | 30 +++++------ .../active_lineage_sampler/classical/mod.rs | 39 +++++++------- .../classical/sampler.rs | 15 +++--- .../independent/event_time_sampler/exp.rs | 13 ++--- .../event_time_sampler/geometric.rs | 14 ++--- .../independent/event_time_sampler/poisson.rs | 46 ++++------------- .../active_lineage_sampler/independent/mod.rs | 18 +++---- .../independent/sampler.rs | 8 ++- .../independent/singular.rs | 8 ++- .../almost_infinite_normal.rs | 27 ++++------ .../in_memory/alias/dispersal.rs | 9 ++-- .../dispersal_sampler/in_memory/alias/mod.rs | 25 ++++----- .../in_memory/cumulative/contract.rs | 7 ++- .../in_memory/cumulative/dispersal.rs | 10 ++-- .../in_memory/cumulative/mod.rs | 24 ++++----- .../in_memory/packed_alias/dispersal.rs | 9 ++-- .../in_memory/packed_alias/mod.rs | 32 +++++------- .../in_memory/separable_alias/dispersal.rs | 16 ++---- .../in_memory/separable_alias/mod.rs | 24 ++++----- .../src/cogs/dispersal_sampler/non_spatial.rs | 29 +++-------- .../dispersal_sampler/spatially_implicit.rs | 37 +++++--------- .../no-std/src/cogs/emigration_exit/domain.rs | 46 +++++++++-------- .../cogs/emigration_exit/independent/mod.rs | 41 ++++++++------- .../event_sampler/gillespie/unconditional.rs | 31 +++-------- .../src/cogs/event_sampler/independent.rs | 28 ++++------ .../src/cogs/event_sampler/unconditional.rs | 26 +++------- 32 files changed, 318 insertions(+), 466 deletions(-) diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index fe1a797f1..69e4f404f 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use necsim_core::cogs::{ distribution::{Bernoulli, IndexUsize, Length}, - DistributionSampler, MathsCore, Rng, SampledDistribution, + MathsCore, Rng, SampledDistribution, Samples, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -111,14 +111,13 @@ impl AliasMethodSamplerAtom { old(alias_samplers).iter().map(|s| s.e).any(|e| e == ret), "returns one of the weighted events" )] - pub fn sample_event>( + pub fn sample_event< + M: MathsCore, + G: Rng + Samples + Samples, + >( alias_samplers: &[AliasMethodSamplerAtom], rng: &mut G, - ) -> E - where - G::Sampler: DistributionSampler - + DistributionSampler, - { + ) -> E { // Safety: alias_samplers is non-empty by the precondition let length = unsafe { NonZeroUsize::new_unchecked(alias_samplers.len()) }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index 4e3eeca67..81cf824af 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -5,9 +5,9 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::cogs::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize}, - Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, + TurnoverRate, }; use crate::cogs::{ @@ -23,7 +23,11 @@ mod sampler; pub struct IndividualAliasActiveLineageSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -32,9 +36,7 @@ pub struct IndividualAliasActiveLineageSampler< N: SpeciationProbability, E: EventSampler, I: ImmigrationEntry, -> where - G::Sampler: DistributionSampler, -{ +> { alias_sampler: DynamicAliasMethodStackSampler, number_active_lineages: usize, last_event_time: NonNegativeF64, @@ -45,7 +47,11 @@ pub struct IndividualAliasActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -55,11 +61,6 @@ impl< E: EventSampler, I: ImmigrationEntry, > IndividualAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -157,7 +158,11 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -167,11 +172,6 @@ impl< E: EventSampler, I: ImmigrationEntry, > fmt::Debug for IndividualAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("IndividualAliasActiveLineageSampler") @@ -185,7 +185,11 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -195,11 +199,6 @@ impl< E: EventSampler, I: ImmigrationEntry, > Backup for IndividualAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index 004b09ddc..faeab2386 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -3,9 +3,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, - EmigrationExit, EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, SampledDistribution, SpeciationProbability, TurnoverRate, + ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, + Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, + SampledDistribution, Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -19,7 +19,11 @@ use super::IndividualAliasActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -30,11 +34,6 @@ impl< I: ImmigrationEntry, > ActiveLineageSampler for IndividualAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index 5ab2d9e69..8956c2e8b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -6,9 +6,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize}, - Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, GloballyCoherentLineageStore, + Habitat, ImmigrationEntry, MathsCore, Rng, Samples, SpeciationProbability, TurnoverRate, }, landscape::Location, }; @@ -27,7 +26,11 @@ mod sampler; pub struct LocationAliasActiveLineageSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -36,12 +39,7 @@ pub struct LocationAliasActiveLineageSampler< N: SpeciationProbability, E: GillespieEventSampler, I: ImmigrationEntry, -> where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, -{ +> { alias_sampler: DynamicAliasMethodIndexedSampler, number_active_lineages: usize, last_event_time: NonNegativeF64, @@ -52,7 +50,11 @@ pub struct LocationAliasActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -62,11 +64,6 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > LocationAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -211,7 +208,11 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -221,11 +222,6 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > core::fmt::Debug for LocationAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("LocationAliasActiveLineageSampler") @@ -239,7 +235,11 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -249,11 +249,6 @@ impl< E: GillespieEventSampler, I: ImmigrationEntry, > Backup for LocationAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index cc67138de..6b09f4a40 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -5,7 +5,7 @@ use necsim_core::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, - SampledDistribution, SpeciationProbability, TurnoverRate, + SampledDistribution, Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -21,7 +21,11 @@ use super::LocationAliasActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -32,11 +36,6 @@ impl< I: ImmigrationEntry, > ActiveLineageSampler for LocationAliasActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, C: 'a, T: 'a, N: 'a, E: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index f1f24d996..29de8a550 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -12,7 +12,7 @@ use hashbrown::HashMap; use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, MathsCore, Rng, SampledDistribution, + Backup, MathsCore, Rng, SampledDistribution, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -49,14 +49,11 @@ impl RejectionSamplingGroup { self.events.iter() } - unsafe fn sample_pop_inplace>( + unsafe fn sample_pop_inplace + Samples>( &mut self, lookup: &mut HashMap, rng: &mut G, - ) -> (Option<&mut Self>, E) - where - G::Sampler: DistributionSampler, - { + ) -> (Option<&mut Self>, E) { if let [event] = &self.events[..] { lookup.remove(event); @@ -94,14 +91,11 @@ impl RejectionSamplingGroup { } #[cfg(test)] - fn sample_pop>( + fn sample_pop + Samples>( mut self, lookup: &mut HashMap, rng: &mut G, - ) -> (Option, E) - where - G::Sampler: DistributionSampler, - { + ) -> (Option, E) { match unsafe { self.sample_pop_inplace(lookup, rng) } { (Some(_), event) => (Some(self), event), (None, event) => (None, event), @@ -199,12 +193,13 @@ impl DynamicAliasMethodIndexedSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } - pub fn sample_pop>(&mut self, rng: &mut G) -> Option - where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, - { + pub fn sample_pop< + M: MathsCore, + G: Rng + Samples + Samples + Samples, + >( + &mut self, + rng: &mut G, + ) -> Option { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 9760fcc69..ef37863a8 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -9,7 +9,7 @@ use core::{ use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, MathsCore, Rng, SampledDistribution, + Backup, MathsCore, Rng, SampledDistribution, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -45,13 +45,10 @@ impl RejectionSamplingGroup { self.events.iter() } - unsafe fn sample_pop_inplace>( + unsafe fn sample_pop_inplace + Samples>( &mut self, rng: &mut G, - ) -> (Option<&mut Self>, E) - where - G::Sampler: DistributionSampler, - { + ) -> (Option<&mut Self>, E) { if let [_event] = &self.events[..] { // Safety: If there is only one event, the pop must succeed return (None, self.events.pop().unwrap_unchecked()); @@ -79,10 +76,10 @@ impl RejectionSamplingGroup { } #[cfg(test)] - fn sample_pop>(mut self, rng: &mut G) -> (Option, E) - where - G::Sampler: DistributionSampler, - { + fn sample_pop + Samples>( + mut self, + rng: &mut G, + ) -> (Option, E) { match unsafe { self.sample_pop_inplace(rng) } { (Some(_), event) => (Some(self), event), (None, event) => (None, event), @@ -133,12 +130,13 @@ impl DynamicAliasMethodStackSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } - pub fn sample_pop>(&mut self, rng: &mut G) -> Option - where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, - { + pub fn sample_pop< + M: MathsCore, + G: Rng + Samples + Samples + Samples, + >( + &mut self, + rng: &mut G, + ) -> Option { if let Some(total_weight) = NonZeroU128::new(self.total_weight) { let cdf_sample = if let [_group] = &self.groups[..] { 0_u128 diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index 50f26fc53..e207e7c11 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use necsim_core::cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, - Backup, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, + Backup, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, }; use necsim_core_bond::NonNegativeF64; @@ -20,18 +20,17 @@ mod sampler; pub struct ClassicalActiveLineageSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, N: SpeciationProbability, I: ImmigrationEntry, -> where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, -{ +> { active_lineage_references: Vec, last_event_time: NonNegativeF64, #[allow(clippy::type_complexity)] @@ -41,18 +40,17 @@ pub struct ClassicalActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, N: SpeciationProbability, I: ImmigrationEntry, > ClassicalActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { #[must_use] pub fn init_with_store<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -137,18 +135,17 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, N: SpeciationProbability, I: ImmigrationEntry, > Backup for ClassicalActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 24f6fbe49..315e2360d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -6,8 +6,8 @@ use core::{ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, - ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, Habitat, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, + ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, Samples, SpeciationProbability, }, lineage::Lineage, @@ -27,7 +27,11 @@ use super::ClassicalActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -57,11 +61,6 @@ impl< >, I, > for ClassicalActiveLineageSampler -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, S: 'a, X: 'a, D: 'a, N: 'a, I: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index ea48c2660..1c909317b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -2,8 +2,7 @@ use necsim_core::{ cogs::{ distribution::{Exponential, Lambda}, rng::HabitatPrimeableRng, - DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, - TurnoverRate, + Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, Samples, TurnoverRate, }, landscape::IndexedLocation, }; @@ -29,10 +28,12 @@ impl ExpEventTimeSampler { } #[contract_trait] -impl, G: Rng, T: TurnoverRate> - EventTimeSampler for ExpEventTimeSampler -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + T: TurnoverRate, + > EventTimeSampler for ExpEventTimeSampler { #[inline] fn next_event_time_at_indexed_location_weakly_after( diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index 6c3996ccc..aaa1ac100 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - distribution::Bernoulli, rng::HabitatPrimeableRng, DistributionSampler, Habitat, MathsCore, - PrimeableRng, Rng, SampledDistribution, TurnoverRate, + distribution::Bernoulli, rng::HabitatPrimeableRng, Habitat, MathsCore, PrimeableRng, Rng, + SampledDistribution, Samples, TurnoverRate, }, landscape::IndexedLocation, }; @@ -24,10 +24,12 @@ impl GeometricEventTimeSampler { } #[contract_trait] -impl, G: Rng, T: TurnoverRate> - EventTimeSampler for GeometricEventTimeSampler -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + T: TurnoverRate, + > EventTimeSampler for GeometricEventTimeSampler { #[inline] fn next_event_time_at_indexed_location_weakly_after( diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index 5efdbc631..d69de55d6 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ - distribution::{Normal, Normal2D, UniformClosedOpenUnit}, + distribution::{Lambda, Poisson, UniformClosedOpenUnit}, rng::HabitatPrimeableRng, - DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, + DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, Samples, TurnoverRate, }, landscape::IndexedLocation, @@ -29,11 +29,12 @@ impl PoissonEventTimeSampler { } #[contract_trait] -impl, G: Rng, T: TurnoverRate> - EventTimeSampler for PoissonEventTimeSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + T: TurnoverRate, + > EventTimeSampler for PoissonEventTimeSampler { #[inline] fn next_event_time_at_indexed_location_weakly_after( @@ -57,36 +58,7 @@ where rng.generator() .prime_with_habitat(habitat, indexed_location, time_step); - let number_events_at_time_steps = if no_event_probability_per_step > 0.0_f64 { - // https://en.wikipedia.org/wiki/Poisson_distribution#cite_ref-Devroye1986_54-0 - let mut poisson = 0_u32; - let mut prod = no_event_probability_per_step; - let mut acc = no_event_probability_per_step; - - let u = UniformClosedOpenUnit::sample(rng); - - while u > acc && prod > 0.0_f64 { - poisson += 1; - prod *= lambda_per_step.get() / f64::from(poisson); - acc += prod; - } - - poisson - } else { - // Fallback in case no_event_probability_per_step underflows - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let normal_as_poisson = Normal2D::sample_with( - rng, - Normal { - mu: lambda_per_step.get(), - sigma: lambda_per_step.sqrt::(), - }, - ) - .0 - .max(0.0_f64) as u32; - - normal_as_poisson - }; + let number_events_at_time_steps = Poisson::sample_with(rng, Lambda(lambda_per_step)); let mut next_event = None; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs index 739ebc498..931f80cab 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/mod.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, Backup, DispersalSampler, DistributionSampler, - EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, Backup, DispersalSampler, EmigrationExit, Habitat, + MathsCore, PrimeableRng, Rng, Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, }; @@ -30,15 +30,13 @@ use event_time_sampler::EventTimeSampler; pub struct IndependentActiveLineageSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, J: EventTimeSampler, -> where - G::Sampler: DistributionSampler, -{ +> { #[cfg_attr( feature = "cuda", cuda(embed = "Option>") @@ -54,15 +52,13 @@ pub struct IndependentActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, J: EventTimeSampler, > IndependentActiveLineageSampler -where - G::Sampler: DistributionSampler, { #[must_use] pub fn init_with_store_and_lineages<'h, O: TrustedOriginSampler<'h, M, Habitat = H>>( @@ -142,15 +138,13 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, J: EventTimeSampler, > Backup for IndependentActiveLineageSampler -where - G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs index b0a4beccf..786224b3c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/sampler.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::UniformClosedOpenUnit, ActiveLineageSampler, DispersalSampler, - DistributionSampler, EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, - SpeciationProbability, TurnoverRate, + EmigrationExit, Habitat, MathsCore, PrimeableRng, Rng, Samples, SpeciationProbability, + TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, @@ -24,7 +24,7 @@ use super::{EventTimeSampler, IndependentActiveLineageSampler}; impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -44,8 +44,6 @@ impl< IndependentEventSampler, NeverImmigrationEntry, > for IndependentActiveLineageSampler -where - G::Sampler: DistributionSampler, { type LineageIterator<'a> = impl Iterator where H: 'a, G: 'a, X: 'a, D: 'a, T: 'a, N: 'a, J: 'a; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs index 2962f86ac..203d7e38e 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/singular.rs @@ -1,6 +1,6 @@ use necsim_core::cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, EmigrationExit, - Habitat, MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, EmigrationExit, Habitat, MathsCore, + PrimeableRng, Rng, Samples, SpeciationProbability, TurnoverRate, }; use necsim_core::lineage::Lineage; @@ -19,7 +19,7 @@ use super::{EventTimeSampler, IndependentActiveLineageSampler}; impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -39,8 +39,6 @@ impl< IndependentEventSampler, NeverImmigrationEntry, > for IndependentActiveLineageSampler -where - G::Sampler: DistributionSampler, { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index a1a939361..344bd4a77 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ distribution::{Normal, Normal2D}, - Backup, DispersalSampler, DistributionSampler, MathsCore, Rng, SampledDistribution, + Backup, DispersalSampler, MathsCore, Rng, SampledDistribution, Samples, SeparableDispersalSampler, }, landscape::Location, @@ -16,19 +16,13 @@ use crate::cogs::habitat::almost_infinite::AlmostInfiniteHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct AlmostInfiniteNormalDispersalSampler> -where - G::Sampler: DistributionSampler, -{ +pub struct AlmostInfiniteNormalDispersalSampler + Samples> { sigma: NonNegativeF64, self_dispersal: ClosedUnitF64, marker: PhantomData<(M, G)>, } -impl> AlmostInfiniteNormalDispersalSampler -where - G::Sampler: DistributionSampler, -{ +impl + Samples> AlmostInfiniteNormalDispersalSampler { #[must_use] pub fn new(sigma: NonNegativeF64) -> Self { let self_dispersal_1d = if sigma > 0.0_f64 { @@ -50,9 +44,8 @@ where } #[contract_trait] -impl> Backup for AlmostInfiniteNormalDispersalSampler -where - G::Sampler: DistributionSampler, +impl + Samples> Backup + for AlmostInfiniteNormalDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -64,10 +57,9 @@ where } #[contract_trait] -impl> DispersalSampler, G> +impl + Samples> + DispersalSampler, G> for AlmostInfiniteNormalDispersalSampler -where - G::Sampler: DistributionSampler, { #[must_use] fn sample_dispersal_from_location( @@ -104,10 +96,9 @@ where } #[contract_trait] -impl> SeparableDispersalSampler, G> +impl + Samples> + SeparableDispersalSampler, G> for AlmostInfiniteNormalDispersalSampler -where - G::Sampler: DistributionSampler, { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs index c7302f79d..2970e3c62 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + DispersalSampler, Habitat, MathsCore, Rng, Samples, }, landscape::Location, }; @@ -9,11 +9,8 @@ use necsim_core::{ use super::InMemoryAliasDispersalSampler; #[contract_trait] -impl, G: Rng> DispersalSampler - for InMemoryAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + DispersalSampler for InMemoryAliasDispersalSampler { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs index 494bb6735..559ba2d23 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, + Backup, Habitat, MathsCore, Rng, Samples, }, landscape::Location, }; @@ -20,21 +20,18 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemoryAliasDispersalSampler, G: Rng> -where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +pub struct InMemoryAliasDispersalSampler< + M: MathsCore, + H: Habitat, + G: Rng + Samples + Samples, +> { alias_dispersal: Array2D>>, marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: Rng> InMemoryDispersalSampler - for InMemoryAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + InMemoryDispersalSampler for InMemoryAliasDispersalSampler { /// Creates a new `InMemoryAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -87,10 +84,8 @@ where } #[contract_trait] -impl, G: Rng> Backup for InMemoryAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> Backup + for InMemoryAliasDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs index 36ceb64bd..fb5115b21 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/contract.rs @@ -1,13 +1,12 @@ use necsim_core::{ - cogs::{distribution::UniformClosedOpenUnit, DistributionSampler, Habitat, MathsCore, Rng}, + cogs::{distribution::UniformClosedOpenUnit, Habitat, MathsCore, Rng, Samples}, landscape::Location, }; use super::InMemoryCumulativeDispersalSampler; -impl, G: Rng> InMemoryCumulativeDispersalSampler -where - G::Sampler: DistributionSampler, +impl, G: Rng + Samples> + InMemoryCumulativeDispersalSampler { pub(super) fn explicit_only_valid_targets_dispersal_contract(&self, habitat: &H) -> bool { let habitat_width = habitat.get_extent().width(); diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs index 7cfacdd37..5d4986abd 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, - MathsCore, Rng, SampledDistribution, + distribution::UniformClosedOpenUnit, DispersalSampler, Habitat, MathsCore, Rng, + SampledDistribution, Samples, }, landscape::Location, }; @@ -9,10 +9,8 @@ use necsim_core::{ use super::InMemoryCumulativeDispersalSampler; #[contract_trait] -impl, G: Rng> DispersalSampler - for InMemoryCumulativeDispersalSampler -where - G::Sampler: DistributionSampler, +impl, G: Rng + Samples> + DispersalSampler for InMemoryCumulativeDispersalSampler { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs index 47f0fd148..eb1d6622c 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/mod.rs @@ -3,9 +3,7 @@ use core::marker::PhantomData; use alloc::{boxed::Box, vec}; use necsim_core::{ - cogs::{ - distribution::UniformClosedOpenUnit, Backup, DistributionSampler, Habitat, MathsCore, Rng, - }, + cogs::{distribution::UniformClosedOpenUnit, Backup, Habitat, MathsCore, Rng, Samples}, landscape::Location, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; @@ -17,20 +15,19 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemoryCumulativeDispersalSampler, G: Rng> -where - G::Sampler: DistributionSampler, -{ +pub struct InMemoryCumulativeDispersalSampler< + M: MathsCore, + H: Habitat, + G: Rng + Samples, +> { cumulative_dispersal: Box<[ClosedUnitF64]>, valid_dispersal_targets: Box<[Option]>, marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: Rng> InMemoryDispersalSampler - for InMemoryCumulativeDispersalSampler -where - G::Sampler: DistributionSampler, +impl, G: Rng + Samples> + InMemoryDispersalSampler for InMemoryCumulativeDispersalSampler { /// Creates a new `InMemoryCumulativeDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -112,9 +109,8 @@ where } #[contract_trait] -impl, G: Rng> Backup for InMemoryCumulativeDispersalSampler -where - G::Sampler: DistributionSampler, +impl, G: Rng + Samples> Backup + for InMemoryCumulativeDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs index 6c3892329..47bd76cd4 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs @@ -3,7 +3,7 @@ use core::ops::Range; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, + DispersalSampler, Habitat, MathsCore, Rng, Samples, }, landscape::Location, }; @@ -13,11 +13,8 @@ use crate::alias::packed::AliasMethodSamplerAtom; use super::InMemoryPackedAliasDispersalSampler; #[contract_trait] -impl, G: Rng> DispersalSampler - for InMemoryPackedAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + DispersalSampler for InMemoryPackedAliasDispersalSampler { #[must_use] fn sample_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs index 0c2c079dc..0a07e3ad0 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs @@ -7,7 +7,7 @@ use r#final::Final; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, + Backup, Habitat, MathsCore, Rng, Samples, }, landscape::Location, }; @@ -45,11 +45,11 @@ impl From for Range { #[allow(clippy::module_name_repetitions)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "H", free = "G"))] -pub struct InMemoryPackedAliasDispersalSampler, G: Rng> -where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +pub struct InMemoryPackedAliasDispersalSampler< + M: MathsCore, + H: Habitat, + G: Rng + Samples + Samples, +> { #[cfg_attr(feature = "cuda", cuda(embed))] alias_dispersal_ranges: Final>, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -58,11 +58,8 @@ where } #[contract_trait] -impl, G: Rng> InMemoryDispersalSampler - for InMemoryPackedAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + InMemoryDispersalSampler for InMemoryPackedAliasDispersalSampler { /// Creates a new `InMemoryPackedAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -122,11 +119,8 @@ where } } -impl, G: Rng> core::fmt::Debug - for InMemoryPackedAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + core::fmt::Debug for InMemoryPackedAliasDispersalSampler { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct(stringify!(InMemoryPackedAliasDispersalSampler)) @@ -144,10 +138,8 @@ where } #[contract_trait] -impl, G: Rng> Backup for InMemoryPackedAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> Backup + for InMemoryPackedAliasDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index 7e254f244..5ec6db546 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, + DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, SeparableDispersalSampler, }, landscape::Location, @@ -11,11 +11,8 @@ use necsim_core_bond::ClosedUnitF64; use super::InMemorySeparableAliasDispersalSampler; #[contract_trait] -impl, G: Rng> DispersalSampler - for InMemorySeparableAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + DispersalSampler for InMemorySeparableAliasDispersalSampler { #[must_use] fn sample_dispersal_from_location( @@ -42,11 +39,8 @@ where } #[contract_trait] -impl, G: Rng> SeparableDispersalSampler - for InMemorySeparableAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + SeparableDispersalSampler for InMemorySeparableAliasDispersalSampler { #[must_use] fn sample_non_self_dispersal_from_location( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs index f5c313d8d..0610d8920 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs @@ -5,7 +5,7 @@ use alloc::vec::Vec; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, + Backup, Habitat, MathsCore, Rng, Samples, }, landscape::Location, }; @@ -20,22 +20,19 @@ mod dispersal; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct InMemorySeparableAliasDispersalSampler, G: Rng> -where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +pub struct InMemorySeparableAliasDispersalSampler< + M: MathsCore, + H: Habitat, + G: Rng + Samples + Samples, +> { alias_dispersal: Array2D>>, self_dispersal: Array2D, _marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: Rng> InMemoryDispersalSampler - for InMemorySeparableAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl, G: Rng + Samples + Samples> + InMemoryDispersalSampler for InMemorySeparableAliasDispersalSampler { /// Creates a new `InMemorySeparableAliasDispersalSampler` from the /// `dispersal` map and extent of the habitat map. @@ -122,11 +119,8 @@ where } #[contract_trait] -impl, G: Rng> Backup +impl, G: Rng + Samples + Samples> Backup for InMemorySeparableAliasDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs index 90d300035..f35dfa5ea 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs @@ -3,8 +3,8 @@ use core::{marker::PhantomData, num::NonZeroU64}; use necsim_core::{ cogs::{ distribution::{IndexU64, Length}, - Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - SampledDistribution, SeparableDispersalSampler, + Backup, DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, + SeparableDispersalSampler, }, landscape::Location, }; @@ -16,17 +16,11 @@ use crate::cogs::habitat::non_spatial::NonSpatialHabitat; #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M", free = "G"))] -pub struct NonSpatialDispersalSampler> -where - G::Sampler: DistributionSampler, -{ +pub struct NonSpatialDispersalSampler + Samples> { marker: PhantomData<(M, G)>, } -impl> Default for NonSpatialDispersalSampler -where - G::Sampler: DistributionSampler, -{ +impl + Samples> Default for NonSpatialDispersalSampler { #[must_use] fn default() -> Self { Self { @@ -36,10 +30,7 @@ where } #[contract_trait] -impl> Backup for NonSpatialDispersalSampler -where - G::Sampler: DistributionSampler, -{ +impl + Samples> Backup for NonSpatialDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { marker: PhantomData::<(M, G)>, @@ -48,10 +39,8 @@ where } #[contract_trait] -impl> DispersalSampler, G> +impl + Samples> DispersalSampler, G> for NonSpatialDispersalSampler -where - G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -85,10 +74,8 @@ where } #[contract_trait] -impl> SeparableDispersalSampler, G> - for NonSpatialDispersalSampler -where - G::Sampler: DistributionSampler, +impl + Samples> + SeparableDispersalSampler, G> for NonSpatialDispersalSampler { #[must_use] #[debug_requires(( diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index df10d55bd..44f2846e3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexU64}, - Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - SampledDistribution, SeparableDispersalSampler, + Backup, DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, + SeparableDispersalSampler, }, landscape::Location, }; @@ -17,11 +17,10 @@ use crate::cogs::{ #[derive(Debug)] #[cfg_attr(feature = "cuda", derive(rust_cuda::common::LendRustToCuda))] #[cfg_attr(feature = "cuda", cuda(free = "M"))] -pub struct SpatiallyImplicitDispersalSampler> -where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +pub struct SpatiallyImplicitDispersalSampler< + M: MathsCore, + G: Rng + Samples + Samples, +> { #[cfg_attr(feature = "cuda", cuda(embed))] local: NonSpatialDispersalSampler, #[cfg_attr(feature = "cuda", cuda(embed))] @@ -29,10 +28,8 @@ where local_migration_probability_per_generation: PositiveUnitF64, } -impl> SpatiallyImplicitDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl + Samples + Samples> + SpatiallyImplicitDispersalSampler { #[must_use] pub fn new(local_migration_probability_per_generation: PositiveUnitF64) -> Self { @@ -45,10 +42,8 @@ where } #[contract_trait] -impl> Backup for SpatiallyImplicitDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl + Samples + Samples> Backup + for SpatiallyImplicitDispersalSampler { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -61,11 +56,9 @@ where } #[contract_trait] -impl> DispersalSampler, G> +impl + Samples + Samples> + DispersalSampler, G> for SpatiallyImplicitDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( @@ -106,11 +99,9 @@ where } #[contract_trait] -impl> SeparableDispersalSampler, G> +impl + Samples + Samples> + SeparableDispersalSampler, G> for SpatiallyImplicitDispersalSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { #[must_use] #[debug_ensures(habitat.meta().get_extent().contains(&ret) || ( diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs index 4ad3d10ba..1be33636b 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/domain.rs @@ -6,7 +6,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, Backup, - DistributionSampler, EmigrationExit, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + EmigrationExit, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -17,20 +17,24 @@ use crate::decomposition::Decomposition; #[allow(clippy::module_name_repetitions)] #[derive(Debug)] -pub struct DomainEmigrationExit, G: Rng, C: Decomposition> -where - G::Sampler: DistributionSampler, -{ +pub struct DomainEmigrationExit< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, +> { decomposition: C, emigrants: Vec<(u32, MigratingLineage)>, _marker: PhantomData<(M, H, G)>, } #[contract_trait] -impl, G: Rng, C: Decomposition> Backup - for DomainEmigrationExit -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + > Backup for DomainEmigrationExit { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -52,11 +56,9 @@ impl< M: MathsCore, H: Habitat, C: Decomposition, - G: Rng, + G: Rng + Samples, S: LocallyCoherentLineageStore, > EmigrationExit for DomainEmigrationExit -where - G::Sampler: DistributionSampler, { #[must_use] #[debug_ensures(ret.is_some() == ( @@ -115,10 +117,12 @@ where } } -impl, G: Rng, C: Decomposition> - DomainEmigrationExit -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + > DomainEmigrationExit { #[must_use] pub fn new(decomposition: C) -> Self { @@ -138,10 +142,12 @@ where } } -impl, G: Rng, C: Decomposition> Iterator - for DomainEmigrationExit -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + > Iterator for DomainEmigrationExit { type Item = (u32, MigratingLineage); diff --git a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs index ed5a2c8b6..179ea74b0 100644 --- a/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs +++ b/necsim/impls/no-std/src/cogs/emigration_exit/independent/mod.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, Backup, - DistributionSampler, EmigrationExit, Habitat, MathsCore, Rng, + EmigrationExit, Habitat, MathsCore, Rng, Samples, }, landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, MigratingLineage, TieBreaker}, @@ -23,12 +23,10 @@ use choice::EmigrationChoice; pub struct IndependentEmigrationExit< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, C: Decomposition, E: EmigrationChoice, -> where - G::Sampler: DistributionSampler, -{ +> { decomposition: C, choice: E, emigrant: Option<(u32, MigratingLineage)>, @@ -36,10 +34,13 @@ pub struct IndependentEmigrationExit< } #[contract_trait] -impl, G: Rng, C: Decomposition, E: EmigrationChoice> - Backup for IndependentEmigrationExit -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + E: EmigrationChoice, + > Backup for IndependentEmigrationExit { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -57,11 +58,14 @@ where } #[contract_trait] -impl, G: Rng, C: Decomposition, E: EmigrationChoice> - EmigrationExit> +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + E: EmigrationChoice, + > EmigrationExit> for IndependentEmigrationExit -where - G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -134,10 +138,13 @@ where } } -impl, G: Rng, C: Decomposition, E: EmigrationChoice> - IndependentEmigrationExit -where - G::Sampler: DistributionSampler, +impl< + M: MathsCore, + H: Habitat, + G: Rng + Samples, + C: Decomposition, + E: EmigrationChoice, + > IndependentEmigrationExit { #[must_use] pub fn new(decomposition: C, choice: E) -> Self { diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index 8877a9ffe..f99db3fef 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -5,8 +5,8 @@ use necsim_core::{ coalescence_sampler::CoalescenceRngSample, distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SampledDistribution, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, + GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SampledDistribution, Samples, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, @@ -23,17 +23,14 @@ use super::GillespieEventSampler; pub struct UnconditionalGillespieEventSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, C: CoalescenceSampler, T: TurnoverRate, N: SpeciationProbability, -> where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +> { #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, C, T, N)>, } @@ -41,7 +38,7 @@ pub struct UnconditionalGillespieEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -49,9 +46,6 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for UnconditionalGillespieEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { fn default() -> Self { Self { @@ -64,7 +58,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -72,9 +66,6 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for UnconditionalGillespieEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -87,7 +78,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -96,9 +87,6 @@ impl< N: SpeciationProbability, > EventSampler for UnconditionalGillespieEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< @@ -198,7 +186,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -207,9 +195,6 @@ impl< N: SpeciationProbability, > GillespieEventSampler for UnconditionalGillespieEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { #[must_use] fn get_event_rate_at_location( diff --git a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs index 9a35ff8b2..64e8ef1cb 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs @@ -3,9 +3,9 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, - event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, - DistributionSampler, EmigrationExit, EventSampler, Habitat, MathsCore, Rng, - SampledDistribution, SpeciationProbability, TurnoverRate, + event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, + EventSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, SpeciationProbability, + TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -38,14 +38,12 @@ use super::tracking::{MinSpeciationTrackingEventSampler, SpeciationSample}; pub struct IndependentEventSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, -> where - G::Sampler: DistributionSampler, -{ +> { #[cfg_attr( feature = "cuda", cuda( @@ -59,14 +57,12 @@ pub struct IndependentEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, > Default for IndependentEventSampler -where - G::Sampler: DistributionSampler, { fn default() -> Self { Self { @@ -80,14 +76,12 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, > Backup for IndependentEventSampler -where - G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -101,7 +95,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -118,8 +112,6 @@ impl< T, N, > for IndependentEventSampler -where - G::Sampler: DistributionSampler, { #[must_use] #[inline] @@ -237,7 +229,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, X: EmigrationExit>, D: DispersalSampler, T: TurnoverRate, @@ -254,8 +246,6 @@ impl< T, N, > for IndependentEventSampler -where - G::Sampler: DistributionSampler, { fn replace_min_speciation( &mut self, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index 3081e0ab4..aca02a3c6 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -5,8 +5,8 @@ use necsim_core::{ coalescence_sampler::CoalescenceRngSample, distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, EmigrationExit, - EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, + LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, Samples, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, @@ -20,17 +20,14 @@ use necsim_core_bond::PositiveF64; pub struct UnconditionalEventSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, C: CoalescenceSampler, T: TurnoverRate, N: SpeciationProbability, -> where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +> { #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, C, T, N)>, } @@ -38,7 +35,7 @@ pub struct UnconditionalEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -46,9 +43,6 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Default for UnconditionalEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { fn default() -> Self { Self { @@ -61,7 +55,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -69,9 +63,6 @@ impl< T: TurnoverRate, N: SpeciationProbability, > Backup for UnconditionalEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -84,7 +75,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -93,9 +84,6 @@ impl< N: SpeciationProbability, > EventSampler for UnconditionalEventSampler -where - G::Sampler: DistributionSampler - + DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< From 4c36ce1212119f8e9ff77165ff5c84879ac80a52 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Thu, 19 May 2022 13:33:30 +0000 Subject: [PATCH 10/21] Finished refactoring into Rng + Samples --- necsim/core/src/cogs/coalescence_sampler.rs | 4 +- necsim/core/src/cogs/distribution.rs | 38 +++++++++---------- necsim/core/src/cogs/mod.rs | 2 +- necsim/core/src/cogs/rng.rs | 8 ++-- necsim/impls/no-std/src/alias/mod.rs | 2 +- necsim/impls/no-std/src/alias/packed.rs | 2 +- .../alias/individual/sampler.rs | 6 +-- .../alias/location/sampler.rs | 4 +- .../alias/sampler/indexed/mod.rs | 2 +- .../alias/sampler/stack/mod.rs | 2 +- .../classical/sampler.rs | 4 +- .../independent/event_time_sampler/exp.rs | 2 +- .../event_time_sampler/geometric.rs | 4 +- .../independent/event_time_sampler/poisson.rs | 12 +++--- .../almost_infinite_normal.rs | 3 +- .../in_memory/cumulative/dispersal.rs | 4 +- .../in_memory/separable_alias/dispersal.rs | 2 +- .../src/cogs/dispersal_sampler/non_spatial.rs | 2 +- .../dispersal_sampler/spatially_implicit.rs | 2 +- .../gillespie/conditional/mod.rs | 28 +++++--------- .../event_sampler/gillespie/unconditional.rs | 6 +-- .../src/cogs/event_sampler/independent.rs | 4 +- .../src/cogs/event_sampler/unconditional.rs | 6 +-- .../no-std/src/cogs/habitat/in_memory.rs | 8 ++-- .../no-std/src/cogs/habitat/non_spatial.rs | 8 ++-- .../src/cogs/habitat/spatially_implicit.rs | 7 ++-- necsim/impls/no-std/src/cogs/rng/simple.rs | 6 +-- .../independent/individuals.rs | 11 ++---- .../parallelisation/independent/landscape.rs | 11 ++---- .../independent/monolithic/mod.rs | 11 ++---- .../parallelisation/monolithic/averaging.rs | 11 ++---- .../parallelisation/monolithic/lockstep.rs | 11 ++---- .../parallelisation/monolithic/optimistic.rs | 11 ++---- .../monolithic/optimistic_lockstep.rs | 11 ++---- .../algorithms/cuda/src/initialiser/fixup.rs | 11 +++--- .../cuda/src/initialiser/genesis.rs | 16 +++++--- .../algorithms/cuda/src/initialiser/mod.rs | 11 +++--- .../algorithms/cuda/src/initialiser/resume.rs | 11 +++--- .../src/event_skipping/initialiser/fixup.rs | 24 +++++++----- .../src/event_skipping/initialiser/genesis.rs | 23 ++++++----- .../src/event_skipping/initialiser/mod.rs | 9 ++--- .../src/event_skipping/initialiser/resume.rs | 24 +++++++----- .../gillespie/src/event_skipping/launch.rs | 10 ++--- .../gillespie/classical/initialiser/fixup.rs | 20 +++++----- .../classical/initialiser/genesis.rs | 19 +++++----- .../gillespie/classical/initialiser/mod.rs | 15 ++++---- .../gillespie/classical/initialiser/resume.rs | 20 +++++----- .../src/gillespie/classical/launch.rs | 11 +++--- .../gillespie/turnover/initialiser/fixup.rs | 23 ++++++----- .../gillespie/turnover/initialiser/genesis.rs | 22 ++++++----- .../src/gillespie/turnover/initialiser/mod.rs | 15 ++++---- .../gillespie/turnover/initialiser/resume.rs | 23 ++++++----- .../src/gillespie/turnover/launch.rs | 11 +++--- .../independent/src/initialiser/fixup.rs | 11 +++--- .../independent/src/initialiser/genesis.rs | 16 ++++---- .../independent/src/initialiser/mod.rs | 12 +++--- .../independent/src/initialiser/resume.rs | 11 +++--- .../algorithms/independent/src/launch.rs | 18 ++++----- .../scenarios/src/almost_infinite.rs | 17 +++------ rustcoalescence/scenarios/src/non_spatial.rs | 17 +++------ .../src/spatially_explicit/turnover/map.rs | 18 +++------ .../spatially_explicit/turnover/uniform.rs | 17 +++------ .../scenarios/src/spatially_implicit.rs | 23 +++++------ 63 files changed, 347 insertions(+), 386 deletions(-) diff --git a/necsim/core/src/cogs/coalescence_sampler.rs b/necsim/core/src/cogs/coalescence_sampler.rs index 6af72afa7..2f2eed5b3 100644 --- a/necsim/core/src/cogs/coalescence_sampler.rs +++ b/necsim/core/src/cogs/coalescence_sampler.rs @@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize}; use crate::{ cogs::{ - distribution::UniformClosedOpenUnit, Backup, Habitat, LineageStore, MathsCore, Rng, - SampledDistribution, Samples, + distribution::UniformClosedOpenUnit, Backup, Distribution, Habitat, LineageStore, + MathsCore, Rng, Samples, }, landscape::{IndexedLocation, Location}, lineage::LineageInteraction, diff --git a/necsim/core/src/cogs/distribution.rs b/necsim/core/src/cogs/distribution.rs index f59cdf509..525f1689d 100644 --- a/necsim/core/src/cogs/distribution.rs +++ b/necsim/core/src/cogs/distribution.rs @@ -6,13 +6,13 @@ use necsim_core_bond::{ use crate::cogs::{MathsCore, RngCore, Samples}; -pub trait Distribution { +#[allow(clippy::module_name_repetitions)] +pub trait DistributionCore { type Parameters; type Sample; } -#[allow(clippy::module_name_repetitions)] -pub trait SampledDistribution: Distribution { +pub trait Distribution: DistributionCore { fn sample_with>( rng: &mut R, params: Self::Parameters, @@ -20,13 +20,13 @@ pub trait SampledDistribution: Distribution { fn sample>(rng: &mut R) -> Self::Sample where - Self: Distribution, + Self: DistributionCore, { Self::sample_with(rng, ()) } } -impl SampledDistribution for D { +impl Distribution for D { fn sample_with>( rng: &mut R, params: Self::Parameters, @@ -36,7 +36,7 @@ impl SampledDistribution for D { } #[allow(clippy::module_name_repetitions)] -pub trait DistributionSampler { +pub trait DistributionSampler { type ConcreteSampler: DistributionSampler; #[must_use] @@ -48,7 +48,7 @@ pub trait DistributionSampler { #[must_use] fn sample(&self, rng: &mut R, samplers: &S) -> D::Sample where - D: Distribution, + D: DistributionCore, { self.sample_with(rng, samplers, ()) } @@ -56,14 +56,14 @@ pub trait DistributionSampler { pub enum UniformClosedOpenUnit {} -impl Distribution for UniformClosedOpenUnit { +impl DistributionCore for UniformClosedOpenUnit { type Parameters = (); type Sample = ClosedOpenUnitF64; } pub enum UniformOpenClosedUnit {} -impl Distribution for UniformOpenClosedUnit { +impl DistributionCore for UniformOpenClosedUnit { type Parameters = (); type Sample = OpenClosedUnitF64; } @@ -72,28 +72,28 @@ pub enum IndexUsize {} pub struct Length(pub T); -impl Distribution for IndexUsize { +impl DistributionCore for IndexUsize { type Parameters = Length; type Sample = usize; } pub enum IndexU32 {} -impl Distribution for IndexU32 { +impl DistributionCore for IndexU32 { type Parameters = Length; type Sample = u32; } pub enum IndexU64 {} -impl Distribution for IndexU64 { +impl DistributionCore for IndexU64 { type Parameters = Length; type Sample = u64; } pub enum IndexU128 {} -impl Distribution for IndexU128 { +impl DistributionCore for IndexU128 { type Parameters = Length; type Sample = u128; } @@ -102,28 +102,28 @@ pub struct Lambda(pub PositiveF64); pub enum Exponential {} -impl Distribution for Exponential { +impl DistributionCore for Exponential { type Parameters = Lambda; type Sample = NonNegativeF64; } pub enum Poisson {} -impl Distribution for Poisson { +impl DistributionCore for Poisson { type Parameters = Lambda; - type Sample = usize; + type Sample = u64; } pub enum Bernoulli {} -impl Distribution for Bernoulli { +impl DistributionCore for Bernoulli { type Parameters = ClosedUnitF64; type Sample = bool; } pub enum StandardNormal2D {} -impl Distribution for StandardNormal2D { +impl DistributionCore for StandardNormal2D { type Parameters = (); type Sample = (f64, f64); } @@ -135,7 +135,7 @@ pub struct Normal { pub enum Normal2D {} -impl Distribution for Normal2D { +impl DistributionCore for Normal2D { type Parameters = Normal; type Sample = (f64, f64); } diff --git a/necsim/core/src/cogs/mod.rs b/necsim/core/src/cogs/mod.rs index 80324d2f8..125592868 100644 --- a/necsim/core/src/cogs/mod.rs +++ b/necsim/core/src/cogs/mod.rs @@ -13,7 +13,7 @@ pub mod rng; pub use rng::{PrimeableRng, Rng, RngCore, Samples, SeedableRng, SplittableRng}; pub mod distribution; -pub use distribution::{Distribution, DistributionSampler, SampledDistribution}; +pub use distribution::{Distribution, DistributionCore, DistributionSampler}; pub mod dispersal_sampler; pub use dispersal_sampler::{DispersalSampler, SeparableDispersalSampler}; diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index 3075e6424..dbdf9dd27 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -3,7 +3,7 @@ use core::{convert::AsMut, ptr::copy_nonoverlapping}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ - cogs::{Distribution, DistributionSampler, Habitat, MathsCore}, + cogs::{DistributionCore, DistributionSampler, Habitat, MathsCore}, landscape::IndexedLocation, }; @@ -102,20 +102,20 @@ pub trait SplittableRng: RngCore { fn split_to_stream(self, stream: u64) -> Self; } -pub trait Samples: Rng { +pub trait Samples: Rng { #[must_use] fn sample_with(&mut self, params: D::Parameters) -> D::Sample; #[must_use] fn sample(&mut self) -> D::Sample where - D: Distribution, + D: DistributionCore, { self.sample_with(()) } } -impl> Samples for R +impl> Samples for R where R::Sampler: DistributionSampler, { diff --git a/necsim/impls/no-std/src/alias/mod.rs b/necsim/impls/no-std/src/alias/mod.rs index 1dca499f4..437c52346 100644 --- a/necsim/impls/no-std/src/alias/mod.rs +++ b/necsim/impls/no-std/src/alias/mod.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use necsim_core::cogs::{ distribution::{Bernoulli, IndexUsize, Length}, - MathsCore, Rng, SampledDistribution, Samples, + Distribution, MathsCore, Rng, Samples, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index 69e4f404f..f7019c08d 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use necsim_core::cogs::{ distribution::{Bernoulli, IndexUsize, Length}, - MathsCore, Rng, SampledDistribution, Samples, + Distribution, MathsCore, Rng, Samples, }; use necsim_core_bond::{ClosedUnitF64, NonNegativeF64}; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index faeab2386..722a6ef81 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -3,9 +3,9 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda}, - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, - SampledDistribution, Samples, SpeciationProbability, TurnoverRate, + ActiveLineageSampler, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, + EventSampler, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index 6b09f4a40..44c958c08 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -3,9 +3,9 @@ use core::{num::NonZeroUsize, ops::ControlFlow}; use necsim_core::{ cogs::{ distribution::{Exponential, IndexU128, IndexU64, IndexUsize, Lambda, Length}, - ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, DistributionSampler, + ActiveLineageSampler, Backup, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, GloballyCoherentLineageStore, Habitat, ImmigrationEntry, MathsCore, Rng, - SampledDistribution, Samples, SpeciationProbability, TurnoverRate, + Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 29de8a550..4416760b6 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -12,7 +12,7 @@ use hashbrown::HashMap; use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, MathsCore, Rng, SampledDistribution, Samples, + Backup, Distribution, MathsCore, Rng, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index ef37863a8..857121d1b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -9,7 +9,7 @@ use core::{ use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, MathsCore, Rng, SampledDistribution, Samples, + Backup, Distribution, MathsCore, Rng, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 315e2360d..60a2c9a29 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -6,8 +6,8 @@ use core::{ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, - ActiveLineageSampler, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, Samples, + ActiveLineageSampler, DispersalSampler, Distribution, EmigrationExit, Habitat, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, }, lineage::Lineage, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index 1c909317b..d9b38f040 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -2,7 +2,7 @@ use necsim_core::{ cogs::{ distribution::{Exponential, Lambda}, rng::HabitatPrimeableRng, - Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, Samples, TurnoverRate, + Distribution, Habitat, MathsCore, PrimeableRng, Rng, Samples, TurnoverRate, }, landscape::IndexedLocation, }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index aaa1ac100..2a8355407 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - distribution::Bernoulli, rng::HabitatPrimeableRng, Habitat, MathsCore, PrimeableRng, Rng, - SampledDistribution, Samples, TurnoverRate, + distribution::Bernoulli, rng::HabitatPrimeableRng, Distribution, Habitat, MathsCore, + PrimeableRng, Rng, Samples, TurnoverRate, }, landscape::IndexedLocation, }; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index d69de55d6..457c72b52 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -2,8 +2,7 @@ use necsim_core::{ cogs::{ distribution::{Lambda, Poisson, UniformClosedOpenUnit}, rng::HabitatPrimeableRng, - DistributionSampler, Habitat, MathsCore, PrimeableRng, Rng, SampledDistribution, Samples, - TurnoverRate, + Distribution, Habitat, MathsCore, PrimeableRng, Rng, Samples, TurnoverRate, }, landscape::IndexedLocation, }; @@ -32,7 +31,7 @@ impl PoissonEventTimeSampler { impl< M: MathsCore, H: Habitat, - G: Rng + Samples, + G: Rng + Samples + Samples, T: TurnoverRate, > EventTimeSampler for PoissonEventTimeSampler { @@ -47,8 +46,9 @@ impl< ) -> NonNegativeF64 { let lambda = turnover_rate.get_turnover_rate_at_location(indexed_location.location(), habitat); - let lambda_per_step = lambda * self.delta_t; - let no_event_probability_per_step = M::exp(-lambda_per_step.get()); + // Safety: lambda is already >= 0, cannot be 0 if an event occurs at this + // location + let lambda_per_step = unsafe { PositiveF64::new_unchecked(lambda.get()) } * self.delta_t; #[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss)] @@ -88,7 +88,7 @@ impl< rng.generator().prime_with_habitat( habitat, indexed_location, - time_step + INV_PHI.wrapping_mul(u64::from(event_index + 1)), + time_step + INV_PHI.wrapping_mul(event_index + 1), ); event_time diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index 344bd4a77..8df4339f3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -3,8 +3,7 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ distribution::{Normal, Normal2D}, - Backup, DispersalSampler, MathsCore, Rng, SampledDistribution, Samples, - SeparableDispersalSampler, + Backup, DispersalSampler, Distribution, MathsCore, Rng, Samples, SeparableDispersalSampler, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs index 5d4986abd..adcc11f75 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/cumulative/dispersal.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, Habitat, MathsCore, Rng, - SampledDistribution, Samples, + distribution::UniformClosedOpenUnit, DispersalSampler, Distribution, Habitat, MathsCore, + Rng, Samples, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index 5ec6db546..e4d99a7a2 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, + DispersalSampler, Distribution, Habitat, MathsCore, Rng, Samples, SeparableDispersalSampler, }, landscape::Location, diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs index f35dfa5ea..2daf80bc2 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/non_spatial.rs @@ -3,7 +3,7 @@ use core::{marker::PhantomData, num::NonZeroU64}; use necsim_core::{ cogs::{ distribution::{IndexU64, Length}, - Backup, DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, + Backup, DispersalSampler, Distribution, Habitat, MathsCore, Rng, Samples, SeparableDispersalSampler, }, landscape::Location, diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index 44f2846e3..edfdbf4e3 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexU64}, - Backup, DispersalSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, + Backup, DispersalSampler, Distribution, Habitat, MathsCore, Rng, Samples, SeparableDispersalSampler, }, landscape::Location, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs index 4249a52ca..2d8162825 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/conditional/mod.rs @@ -3,9 +3,9 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, - event_sampler::EventHandler, Backup, CoalescenceSampler, DistributionSampler, - EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, - SampledDistribution, SeparableDispersalSampler, SpeciationProbability, TurnoverRate, + event_sampler::EventHandler, Backup, CoalescenceSampler, Distribution, EmigrationExit, + EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, Samples, + SeparableDispersalSampler, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -28,15 +28,13 @@ use probability::ProbabilityAtLocation; pub struct ConditionalGillespieEventSampler< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, T: TurnoverRate, N: SpeciationProbability, -> where - G::Sampler: DistributionSampler, -{ +> { #[allow(clippy::type_complexity)] marker: PhantomData<(M, H, G, S, X, D, T, N)>, } @@ -44,15 +42,13 @@ pub struct ConditionalGillespieEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, T: TurnoverRate, N: SpeciationProbability, > Default for ConditionalGillespieEventSampler -where - G::Sampler: DistributionSampler, { fn default() -> Self { Self { @@ -65,15 +61,13 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, T: TurnoverRate, N: SpeciationProbability, > Backup for ConditionalGillespieEventSampler -where - G::Sampler: DistributionSampler, { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -86,7 +80,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -94,8 +88,6 @@ impl< N: SpeciationProbability, > EventSampler, T, N> for ConditionalGillespieEventSampler -where - G::Sampler: DistributionSampler, { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< @@ -240,7 +232,7 @@ where impl< M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: SeparableDispersalSampler, @@ -248,8 +240,6 @@ impl< N: SpeciationProbability, > GillespieEventSampler, T, N> for ConditionalGillespieEventSampler -where - G::Sampler: DistributionSampler, { #[must_use] fn get_event_rate_at_location( diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index f99db3fef..ac7342ce6 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -5,9 +5,9 @@ use necsim_core::{ coalescence_sampler::CoalescenceRngSample, distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, - GloballyCoherentLineageStore, Habitat, MathsCore, Rng, SampledDistribution, Samples, - SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, EventSampler, + GloballyCoherentLineageStore, Habitat, MathsCore, Rng, Samples, SpeciationProbability, + TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs index 64e8ef1cb..ffca1715d 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/independent.rs @@ -3,8 +3,8 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, distribution::UniformClosedOpenUnit, - event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, - EventSampler, Habitat, MathsCore, Rng, SampledDistribution, Samples, SpeciationProbability, + event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, Distribution, + EmigrationExit, EventSampler, Habitat, MathsCore, Rng, Samples, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index aca02a3c6..e8ae14594 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -5,9 +5,9 @@ use necsim_core::{ coalescence_sampler::CoalescenceRngSample, distribution::{Bernoulli, UniformClosedOpenUnit}, event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SampledDistribution, Samples, - SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, EventSampler, + Habitat, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, + TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, diff --git a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs index 4249f254b..e7960e8bb 100644 --- a/necsim/impls/no-std/src/cogs/habitat/in_memory.rs +++ b/necsim/impls/no-std/src/cogs/habitat/in_memory.rs @@ -7,8 +7,7 @@ use r#final::Final; use necsim_core::{ cogs::{ distribution::{IndexU64, Length}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, - UniformlySampleableHabitat, + Backup, Distribution, Habitat, MathsCore, Rng, Samples, UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -110,9 +109,8 @@ impl Habitat for InMemoryHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for InMemoryHabitat -where - G::Sampler: DistributionSampler, +impl + Samples> UniformlySampleableHabitat + for InMemoryHabitat { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs index b4a900fc8..c0ec679c5 100644 --- a/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/habitat/non_spatial.rs @@ -6,8 +6,7 @@ use core::{ use necsim_core::{ cogs::{ distribution::{IndexU64, Length}, - Backup, DistributionSampler, Habitat, MathsCore, Rng, SampledDistribution, - UniformlySampleableHabitat, + Backup, Distribution, Habitat, MathsCore, Rng, Samples, UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, }; @@ -120,9 +119,8 @@ impl Habitat for NonSpatialHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for NonSpatialHabitat -where - G::Sampler: DistributionSampler, +impl + Samples> UniformlySampleableHabitat + for NonSpatialHabitat { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs index 964eb63a4..bcc3c2495 100644 --- a/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/habitat/spatially_implicit.rs @@ -2,7 +2,7 @@ use core::num::NonZeroU32; use necsim_core::{ cogs::{ - distribution::IndexU64, Backup, DistributionSampler, Habitat, MathsCore, Rng, + distribution::IndexU64, Backup, Habitat, MathsCore, Rng, Samples, UniformlySampleableHabitat, }, landscape::{IndexedLocation, LandscapeExtent, Location}, @@ -131,9 +131,8 @@ impl Habitat for SpatiallyImplicitHabitat { } #[contract_trait] -impl> UniformlySampleableHabitat for SpatiallyImplicitHabitat -where - G::Sampler: DistributionSampler, +impl + Samples> UniformlySampleableHabitat + for SpatiallyImplicitHabitat { #[must_use] #[inline] diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index 010aa98af..9604ccbfb 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -267,7 +267,7 @@ impl< self } - fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> usize { + fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> u64 { let lambda = params.0; let no_event_probability = M::exp(-lambda.get()); @@ -284,13 +284,13 @@ impl< }, ) .0 - .max(0.0_f64) as usize; + .max(0.0_f64) as u64; return normal_as_poisson; } // https://en.wikipedia.org/wiki/Poisson_distribution#cite_ref-Devroye1986_54-0 - let mut poisson = 0_usize; + let mut poisson = 0_u64; let mut prod = no_event_probability; let mut acc = no_event_probability; diff --git a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs index f01b3032f..d8c87e19b 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/individuals.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/individuals.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, - MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, Habitat, MathsCore, PrimeableRng, + Rng, Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::Reporter, @@ -40,7 +40,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, @@ -84,10 +84,7 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) -where - G::Sampler: DistributionSampler, -{ +) { let mut lineages = VecDeque::from_iter(lineages); let mut proxy = IgnoreProgressReporterProxy::from(local_partition); let mut min_spec_samples = dedup_cache.construct(lineages.len()); diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index 63eab7f35..a76569904 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -9,8 +9,8 @@ use necsim_core_bond::NonNegativeF64; use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, - MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, Habitat, MathsCore, PrimeableRng, + Rng, Samples, SpeciationProbability, TurnoverRate, }, event::DispersalEvent, landscape::IndexedLocation, @@ -45,7 +45,7 @@ pub fn simulate< H: Habitat, C: Decomposition, E: EmigrationChoice, - G: Rng, + G: Rng + Samples, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, @@ -89,10 +89,7 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) -where - G::Sampler: DistributionSampler, -{ +) { let mut lineages = VecDeque::from_iter(lineages); let mut proxy = IgnoreProgressReporterProxy::from(local_partition); let mut min_spec_samples = dedup_cache.construct(lineages.len()); diff --git a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs index a2e753bc3..db9f7b2c9 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/monolithic/mod.rs @@ -8,8 +8,8 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_core::{ cogs::{ - distribution::UniformClosedOpenUnit, DispersalSampler, DistributionSampler, Habitat, - MathsCore, PrimeableRng, Rng, SpeciationProbability, TurnoverRate, + distribution::UniformClosedOpenUnit, DispersalSampler, Habitat, MathsCore, PrimeableRng, + Rng, Samples, SpeciationProbability, TurnoverRate, }, lineage::Lineage, reporter::{boolean::Boolean, Reporter}, @@ -45,7 +45,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, D: DispersalSampler, T: TurnoverRate, N: SpeciationProbability, @@ -91,10 +91,7 @@ pub fn simulate< NonNegativeF64, u64, impl IntoIterator, -) -where - G::Sampler: DistributionSampler, -{ +) { let mut slow_lineages = lineages .into_iter() .map(|lineage| { diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs index 58e69d69e..9d049ba09 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/averaging.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, - DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + DispersalSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, reporter::Reporter, simulation::Simulation, @@ -27,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, @@ -67,10 +67,7 @@ pub fn simulate< >, independent_time_slice: PositiveF64, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) -where - G::Sampler: DistributionSampler, -{ +) -> (Status, NonNegativeF64, u64) { // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs index 3450fc1d7..96cdd81cd 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/lockstep.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::UniformClosedOpenUnit, ActiveLineageSampler, CoalescenceSampler, - DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + DispersalSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -27,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, @@ -66,10 +66,7 @@ pub fn simulate< A, >, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) -where - G::Sampler: DistributionSampler, -{ +) -> (Status, NonNegativeF64, u64) { // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs index a0b6838cd..78c5e4105 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic.rs @@ -4,8 +4,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ backup::BackedUp, distribution::UniformClosedOpenUnit, ActiveLineageSampler, Backup, - CoalescenceSampler, DispersalSampler, DistributionSampler, EventSampler, Habitat, - LocallyCoherentLineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + CoalescenceSampler, DispersalSampler, EventSampler, Habitat, LocallyCoherentLineageStore, + MathsCore, Rng, Samples, SpeciationProbability, TurnoverRate, }, lineage::MigratingLineage, reporter::Reporter, @@ -31,7 +31,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, @@ -71,10 +71,7 @@ pub fn simulate< >, independent_time_slice: PositiveF64, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) -where - G::Sampler: DistributionSampler, -{ +) -> (Status, NonNegativeF64, u64) { // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs index 789568ab4..9b51f5c26 100644 --- a/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs +++ b/necsim/impls/no-std/src/parallelisation/monolithic/optimistic_lockstep.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core::{ cogs::{ distribution::UniformClosedOpenUnit, ActiveLineageSampler, Backup, CoalescenceSampler, - DispersalSampler, DistributionSampler, EventSampler, Habitat, LocallyCoherentLineageStore, - MathsCore, Rng, SpeciationProbability, TurnoverRate, + DispersalSampler, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, reporter::{NullReporter, Reporter}, simulation::Simulation, @@ -27,7 +27,7 @@ pub fn simulate< 'p, M: MathsCore, H: Habitat, - G: Rng, + G: Rng + Samples, S: LocallyCoherentLineageStore, D: DispersalSampler, C: CoalescenceSampler, @@ -66,10 +66,7 @@ pub fn simulate< A, >, local_partition: &mut L, -) -> (Status, NonNegativeF64, u64) -where - G::Sampler: DistributionSampler, -{ +) -> (Status, NonNegativeF64, u64) { // Ensure that the progress bar starts with the expected target local_partition.report_progress_sync(simulation.get_balanced_remaining_work().0); diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs index fd7620ecb..115791b4f 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -46,7 +46,11 @@ pub struct FixUpInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng + RustToCuda, + G: Rng + + Samples + + Samples + + Samples + + RustToCuda, O: Scenario, > CudaLineageStoreSampleInitialiser> for FixUpInitialiser where @@ -54,9 +58,6 @@ where O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs index a0d5c5188..96055414b 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -26,16 +26,20 @@ use super::CudaLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl + RustToCuda, O: Scenario> - CudaLineageStoreSampleInitialiser for GenesisInitialiser +impl< + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + RustToCuda, + O: Scenario, + > CudaLineageStoreSampleInitialiser for GenesisInitialiser where O::Habitat: RustToCuda, O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs index 3ebb5b28e..7bebde14e 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + DispersalSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -31,7 +31,11 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait CudaLineageStoreSampleInitialiser< M: MathsCore, - G: Rng + RustToCuda, + G: Rng + + Samples + + Samples + + Samples + + RustToCuda, O: Scenario, Error: From, > where @@ -39,9 +43,6 @@ pub trait CudaLineageStoreSampleInitialiser< O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type DispersalSampler: DispersalSampler + RustToCuda; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs index 77228019f..936bd6d65 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -35,7 +35,11 @@ pub struct ResumeInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng + RustToCuda, + G: Rng + + Samples + + Samples + + Samples + + RustToCuda, O: Scenario, > CudaLineageStoreSampleInitialiser> for ResumeInitialiser where @@ -43,9 +47,6 @@ where O::DispersalSampler>: RustToCuda, O::TurnoverRate: RustToCuda, O::SpeciationProbability: RustToCuda, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit> + RustToCuda, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs index 4a4f1bf86..2fed583c6 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs @@ -3,8 +3,8 @@ use necsim_core::{ distribution::{ Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, }, - DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, - MathsCore, Rng, SeparableDispersalSampler, + EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, Samples, + SeparableDispersalSampler, }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, @@ -48,17 +48,21 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: Rng, O: Scenario> - EventSkippingLineageStoreSampleInitialiser> for FixUpInitialiser +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > EventSkippingLineageStoreSampleInitialiser> for FixUpInitialiser where O::DispersalSampler>: SeparableDispersalSampler, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs index 1438086de..b464810b7 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs @@ -3,8 +3,8 @@ use necsim_core::{ distribution::{ Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, }, - DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, - MathsCore, Rng, SeparableDispersalSampler, + EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, Samples, + SeparableDispersalSampler, }, reporter::Reporter, }; @@ -25,17 +25,20 @@ use super::EventSkippingLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> - EventSkippingLineageStoreSampleInitialiser for GenesisInitialiser +impl< + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > EventSkippingLineageStoreSampleInitialiser for GenesisInitialiser where O::DispersalSampler>: SeparableDispersalSampler, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs index 4b66a3f9e..61e2f386f 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, - ImmigrationEntry, MathsCore, Rng, SeparableDispersalSampler, + ActiveLineageSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, + MathsCore, Rng, Samples, SeparableDispersalSampler, }, reporter::Reporter, }; @@ -24,15 +24,12 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait EventSkippingLineageStoreSampleInitialiser< M: MathsCore, - G: Rng, + G: Rng + Samples + Samples + Samples, O: Scenario, Error, > where O::DispersalSampler>: SeparableDispersalSampler, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type DispersalSampler: SeparableDispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs index c386ab160..aa93e90d6 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs @@ -3,8 +3,8 @@ use necsim_core::{ distribution::{ Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize, UniformClosedOpenUnit, }, - DistributionSampler, EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, - MathsCore, Rng, SeparableDispersalSampler, + EmigrationExit, GloballyCoherentLineageStore, ImmigrationEntry, MathsCore, Rng, Samples, + SeparableDispersalSampler, }, lineage::Lineage, reporter::Reporter, @@ -32,17 +32,21 @@ pub struct ResumeInitialiser> { } #[allow(clippy::type_complexity)] -impl, M: MathsCore, G: Rng, O: Scenario> - EventSkippingLineageStoreSampleInitialiser> for ResumeInitialiser +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > EventSkippingLineageStoreSampleInitialiser> for ResumeInitialiser where O::DispersalSampler>: SeparableDispersalSampler, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< S: GloballyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index 5752ee4f6..22c2e794b 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -3,7 +3,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, DistributionSampler, GloballyCoherentLineageStore, MathsCore, Rng, + ActiveLineageSampler, GloballyCoherentLineageStore, MathsCore, Rng, Samples, SeparableDispersalSampler, SplittableRng, }, reporter::Reporter, @@ -38,7 +38,10 @@ use crate::arguments::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -59,9 +62,6 @@ where GloballyCoherentLineageStore, O::DispersalSampler>: SeparableDispersalSampler, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index 004e71036..ecca829c7 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -1,8 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, + EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, @@ -47,13 +46,16 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: Rng, O: Scenario> - ClassicalLineageStoreSampleInitialiser> for FixUpInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > ClassicalLineageStoreSampleInitialiser> for FixUpInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index f1c629bf1..1df6aac38 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -1,8 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, + EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, reporter::Reporter, }; @@ -21,13 +20,15 @@ use super::ClassicalLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> ClassicalLineageStoreSampleInitialiser - for GenesisInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > ClassicalLineageStoreSampleInitialiser for GenesisInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index f8459676d..6f694b803 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, DispersalSampler, DistributionSampler, EmigrationExit, - ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, + ActiveLineageSampler, DispersalSampler, EmigrationExit, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, reporter::Reporter, }; @@ -22,11 +22,12 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] -pub trait ClassicalLineageStoreSampleInitialiser, O: Scenario, Error> -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, +pub trait ClassicalLineageStoreSampleInitialiser< + M: MathsCore, + G: Rng + Samples + Samples + Samples, + O: Scenario, + Error, +> { type DispersalSampler: DispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index 484f068a4..458177523 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -1,8 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, - MathsCore, Rng, + EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, lineage::Lineage, reporter::Reporter, @@ -27,13 +26,16 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } -impl, M: MathsCore, G: Rng, O: Scenario> - ClassicalLineageStoreSampleInitialiser> for ResumeInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > ClassicalLineageStoreSampleInitialiser> for ResumeInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 298e5900a..db147badb 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -3,8 +3,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, - SplittableRng, + ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SplittableRng, }, reporter::Reporter, simulation::SimulationBuilder, @@ -41,7 +40,10 @@ use super::initialiser::ClassicalLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -60,9 +62,6 @@ pub fn initialise_and_simulate< where O::LineageStore>: LocallyCoherentLineageStore, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs index 43d853008..aa6d3d57a 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, - CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, + CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, event::DispersalEvent, lineage::{Lineage, LineageInteraction}, @@ -44,14 +44,17 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } -impl, M: MathsCore, G: Rng, O: Scenario> - GillespieLineageStoreSampleInitialiser> for FixUpInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > GillespieLineageStoreSampleInitialiser> for FixUpInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs index a0ce35c3e..6f9ae9605 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, - CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, + CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, reporter::Reporter, }; @@ -21,14 +21,16 @@ use super::GillespieLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> GillespieLineageStoreSampleInitialiser - for GenesisInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > GillespieLineageStoreSampleInitialiser for GenesisInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs index 20370ee6b..cb8fd7bc2 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs @@ -1,9 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize}, - ActiveLineageSampler, CoalescenceSampler, DispersalSampler, DistributionSampler, - EmigrationExit, EventSampler, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, - Rng, + ActiveLineageSampler, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, + ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, reporter::Reporter, }; @@ -21,10 +20,12 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] -pub trait GillespieLineageStoreSampleInitialiser, O: Scenario, Error> -where - G::Sampler: DistributionSampler - + DistributionSampler, +pub trait GillespieLineageStoreSampleInitialiser< + M: MathsCore, + G: Rng + Samples + Samples, + O: Scenario, + Error, +> { type DispersalSampler: DispersalSampler; type ActiveLineageSampler< diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs index 8618cd4e2..281635014 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Exponential, IndexU128, IndexU64, IndexUsize}, - CoalescenceSampler, DistributionSampler, EmigrationExit, EventSampler, ImmigrationEntry, - LocallyCoherentLineageStore, MathsCore, Rng, + CoalescenceSampler, EmigrationExit, EventSampler, ImmigrationEntry, + LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, lineage::Lineage, reporter::Reporter, @@ -27,14 +27,17 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } -impl, M: MathsCore, G: Rng, O: Scenario> - GillespieLineageStoreSampleInitialiser> for ResumeInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + L: ExactSizeIterator, + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples + + Samples + + Samples, + O: Scenario, + > GillespieLineageStoreSampleInitialiser> for ResumeInitialiser { type ActiveLineageSampler< S: LocallyCoherentLineageStore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index 90c3db24d..86d90adb4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -3,8 +3,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, DistributionSampler, LocallyCoherentLineageStore, MathsCore, Rng, - SplittableRng, + ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SplittableRng, }, reporter::Reporter, simulation::SimulationBuilder, @@ -40,7 +39,10 @@ use super::initialiser::GillespieLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -59,9 +61,6 @@ pub fn initialise_and_simulate< where O::LineageStore>: LocallyCoherentLineageStore, - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { match args.parallelism_mode { ParallelismMode::Monolithic => { diff --git a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs index 563e4adb3..76ecab2b0 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -42,13 +42,12 @@ pub struct FixUpInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, > IndependentLineageStoreSampleInitialiser> for FixUpInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs index 88107b22b..730c5e3ad 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -22,12 +22,14 @@ use super::IndependentLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; -impl, O: Scenario> - IndependentLineageStoreSampleInitialiser for GenesisInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, +impl< + M: MathsCore, + G: Rng + + Samples + + Samples + + Samples, + O: Scenario, + > IndependentLineageStoreSampleInitialiser for GenesisInitialiser { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs index f3de92c3d..e599e6501 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs @@ -1,7 +1,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - DispersalSampler, DistributionSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, + DispersalSampler, EmigrationExit, MathsCore, PrimeableRng, Rng, Samples, }, lineage::Lineage, }; @@ -27,13 +27,13 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait IndependentLineageStoreSampleInitialiser< M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, Error, -> where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, +> { type DispersalSampler: DispersalSampler; type ActiveLineageSampler> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples, O: Scenario, > IndependentLineageStoreSampleInitialiser> for ResumeInitialiser -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler, { type ActiveLineageSampler< X: EmigrationExit>, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index fcbe5d1bd..2d13ad2a1 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -2,8 +2,8 @@ use std::marker::PhantomData; use necsim_core::{ cogs::{ - distribution::{Bernoulli, IndexUsize, Normal2D, UniformClosedOpenUnit}, - DistributionSampler, MathsCore, PrimeableRng, Rng, + distribution::{Bernoulli, IndexUsize, Poisson, UniformClosedOpenUnit}, + MathsCore, PrimeableRng, Rng, Samples, }, reporter::Reporter, simulation::SimulationBuilder, @@ -49,7 +49,11 @@ use crate::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng, + G: Rng + + Samples + + Samples + + Samples + + Samples, O: Scenario, R: Reporter, P: LocalPartition<'p, R>, @@ -64,13 +68,7 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> -where - G::Sampler: DistributionSampler - + DistributionSampler - + DistributionSampler - + DistributionSampler, -{ +) -> Result, Error> { match args.parallelism_mode { ParallelismMode::Monolithic(MonolithicParallelismMode { event_slice }) | ParallelismMode::IsolatedIndividuals(IsolatedParallelismMode { event_slice, .. }) diff --git a/rustcoalescence/scenarios/src/almost_infinite.rs b/rustcoalescence/scenarios/src/almost_infinite.rs index 6636731c9..e908c497c 100644 --- a/rustcoalescence/scenarios/src/almost_infinite.rs +++ b/rustcoalescence/scenarios/src/almost_infinite.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ - distribution::Normal2D, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + distribution::Normal2D, DispersalSampler, LineageStore, MathsCore, Rng, Samples, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -23,10 +23,7 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct AlmostInfiniteScenario> -where - G::Sampler: DistributionSampler, -{ +pub struct AlmostInfiniteScenario + Samples> { radius: u16, habitat: AlmostInfiniteHabitat, @@ -43,17 +40,15 @@ pub struct AlmostInfiniteArguments { pub sigma: NonNegativeF64, } -impl> ScenarioParameters for AlmostInfiniteScenario -where - G::Sampler: DistributionSampler, +impl + Samples> ScenarioParameters + for AlmostInfiniteScenario { type Arguments = AlmostInfiniteArguments; type Error = !; } -impl> Scenario for AlmostInfiniteScenario -where - G::Sampler: DistributionSampler, +impl + Samples> Scenario + for AlmostInfiniteScenario { type Decomposition = RadialDecomposition; type DecompositionAuxiliary = (); diff --git a/rustcoalescence/scenarios/src/non_spatial.rs b/rustcoalescence/scenarios/src/non_spatial.rs index 571d54f6b..07df10df9 100644 --- a/rustcoalescence/scenarios/src/non_spatial.rs +++ b/rustcoalescence/scenarios/src/non_spatial.rs @@ -3,7 +3,7 @@ use std::num::NonZeroU32; use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ - distribution::IndexU64, DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + distribution::IndexU64, DispersalSampler, LineageStore, MathsCore, Rng, Samples, }; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -22,10 +22,7 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct NonSpatialScenario> -where - G::Sampler: DistributionSampler, -{ +pub struct NonSpatialScenario + Samples> { habitat: NonSpatialHabitat, dispersal_sampler: NonSpatialDispersalSampler, turnover_rate: UniformTurnoverRate, @@ -39,18 +36,14 @@ pub struct NonSpatialArguments { pub deme: NonZeroU32, } -impl> ScenarioParameters for NonSpatialScenario -where - G::Sampler: DistributionSampler, +impl + Samples> ScenarioParameters + for NonSpatialScenario { type Arguments = NonSpatialArguments; type Error = !; } -impl> Scenario for NonSpatialScenario -where - G::Sampler: DistributionSampler, -{ +impl + Samples> Scenario for NonSpatialScenario { type Decomposition = ModuloDecomposition; type DecompositionAuxiliary = (); type DispersalSampler> = diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs index a7d6157fd..f19cb079c 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs @@ -3,8 +3,7 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; use necsim_core::cogs::{ - distribution::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, - MathsCore, Rng, + distribution::IndexU64, DispersalSampler, Habitat, LineageStore, MathsCore, Rng, Samples, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -41,10 +40,7 @@ pub enum SpatiallyExplicitTurnoverMapScenarioError { } #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyExplicitTurnoverMapScenario> -where - G::Sampler: DistributionSampler, -{ +pub struct SpatiallyExplicitTurnoverMapScenario + Samples> { habitat: InMemoryHabitat, dispersal_map: Array2D, turnover_rate: InMemoryTurnoverRate, @@ -52,17 +48,15 @@ where _marker: PhantomData, } -impl> ScenarioParameters for SpatiallyExplicitTurnoverMapScenario -where - G::Sampler: DistributionSampler, +impl + Samples> ScenarioParameters + for SpatiallyExplicitTurnoverMapScenario { type Arguments = SpatiallyExplicitTurnoverMapArguments; type Error = SpatiallyExplicitTurnoverMapScenarioError; } -impl> Scenario for SpatiallyExplicitTurnoverMapScenario -where - G::Sampler: DistributionSampler, +impl + Samples> Scenario + for SpatiallyExplicitTurnoverMapScenario { type Decomposition = EqualDecomposition; type DecompositionAuxiliary = (); diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs index 67c470e6c..e19aade26 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs @@ -3,8 +3,7 @@ use std::{convert::TryFrom, marker::PhantomData, path::PathBuf}; use serde::{Deserialize, Serialize, Serializer}; use necsim_core::cogs::{ - distribution::IndexU64, DispersalSampler, DistributionSampler, Habitat, LineageStore, - MathsCore, Rng, + distribution::IndexU64, DispersalSampler, Habitat, LineageStore, MathsCore, Rng, Samples, }; use necsim_core_bond::{NonNegativeF64, OpenClosedUnitF64 as PositiveUnitF64, PositiveF64}; use necsim_partitioning_core::partition::Partition; @@ -39,9 +38,7 @@ pub enum SpatiallyExplicitUniformTurnoverScenarioError { } #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyExplicitUniformTurnoverScenario> -where - G::Sampler: DistributionSampler, +pub struct SpatiallyExplicitUniformTurnoverScenario + Samples> { habitat: InMemoryHabitat, dispersal_map: Array2D, @@ -50,17 +47,15 @@ where _marker: PhantomData, } -impl> ScenarioParameters for SpatiallyExplicitUniformTurnoverScenario -where - G::Sampler: DistributionSampler, +impl + Samples> ScenarioParameters + for SpatiallyExplicitUniformTurnoverScenario { type Arguments = SpatiallyExplicitUniformTurnoverArguments; type Error = SpatiallyExplicitUniformTurnoverScenarioError; } -impl> Scenario for SpatiallyExplicitUniformTurnoverScenario -where - G::Sampler: DistributionSampler, +impl + Samples> Scenario + for SpatiallyExplicitUniformTurnoverScenario { type Decomposition = EqualDecomposition; type DecompositionAuxiliary = (); diff --git a/rustcoalescence/scenarios/src/spatially_implicit.rs b/rustcoalescence/scenarios/src/spatially_implicit.rs index 5a29dcf51..4933bd6f7 100644 --- a/rustcoalescence/scenarios/src/spatially_implicit.rs +++ b/rustcoalescence/scenarios/src/spatially_implicit.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use necsim_core::cogs::{ distribution::{Bernoulli, IndexU64}, - DispersalSampler, DistributionSampler, LineageStore, MathsCore, Rng, + DispersalSampler, LineageStore, MathsCore, Rng, Samples, }; use necsim_core_bond::{OffByOneU32, OpenClosedUnitF64 as PositiveUnitF64}; use necsim_partitioning_core::partition::Partition; @@ -25,11 +25,10 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] -pub struct SpatiallyImplicitScenario> -where - G::Sampler: DistributionSampler - + DistributionSampler, -{ +pub struct SpatiallyImplicitScenario< + M: MathsCore, + G: Rng + Samples + Samples, +> { habitat: SpatiallyImplicitHabitat, dispersal_sampler: SpatiallyImplicitDispersalSampler, turnover_rate: UniformTurnoverRate, @@ -48,19 +47,15 @@ pub struct SpatiallyImplicitArguments { pub migration_probability_per_generation: PositiveUnitF64, } -impl> ScenarioParameters for SpatiallyImplicitScenario -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl + Samples + Samples> ScenarioParameters + for SpatiallyImplicitScenario { type Arguments = SpatiallyImplicitArguments; type Error = !; } -impl> Scenario for SpatiallyImplicitScenario -where - G::Sampler: DistributionSampler - + DistributionSampler, +impl + Samples + Samples> Scenario + for SpatiallyImplicitScenario { type Decomposition = ModuloDecomposition; type DecompositionAuxiliary = (); From 544f43db08124a62a67a14061580c503ccbcd4dd Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Thu, 19 May 2022 14:55:30 +0000 Subject: [PATCH 11/21] Backup of partial refactoring of Rng not a subtrait of RngCore --- necsim/core/src/cogs/rng.rs | 8 ++-- necsim/impls/cuda/src/cogs/rng.rs | 46 +++--------------- .../alias/sampler/indexed/mod.rs | 4 +- .../alias/sampler/indexed/tests.rs | 10 ++-- .../alias/sampler/stack/mod.rs | 4 +- .../alias/sampler/stack/tests.rs | 10 ++-- .../src/cogs/habitat/almost_infinite.rs | 4 +- necsim/impls/no-std/src/cogs/rng/simple.rs | 41 ++++------------ rustcoalescence/algorithms/cuda/src/launch.rs | 9 ++-- rustcoalescence/algorithms/cuda/src/lib.rs | 18 ++++--- .../src/gillespie/classical/launch.rs | 22 ++++----- .../gillespie/src/gillespie/classical/mod.rs | 14 +++--- .../algorithms/independent/src/launch.rs | 31 +++++------- .../algorithms/independent/src/lib.rs | 18 ++++--- rustcoalescence/algorithms/src/lib.rs | 12 ++--- rustcoalescence/algorithms/src/result.rs | 10 ++-- rustcoalescence/src/args/config/rng/mod.rs | 47 +++++++------------ .../src/cli/simulate/dispatch/valid/rng.rs | 7 ++- rustcoalescence/src/cli/simulate/parse/rng.rs | 11 ++--- 19 files changed, 127 insertions(+), 199 deletions(-) diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index dbdf9dd27..956cae27b 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -3,11 +3,11 @@ use core::{convert::AsMut, ptr::copy_nonoverlapping}; use serde::{de::DeserializeOwned, Serialize}; use crate::{ - cogs::{DistributionCore, DistributionSampler, Habitat, MathsCore}, + cogs::{Backup, DistributionCore, DistributionSampler, Habitat, MathsCore}, landscape::IndexedLocation, }; -pub trait Rng: RngCore { +pub trait Rng: Backup + Clone + core::fmt::Debug { type Generator: RngCore; type Sampler; @@ -17,7 +17,7 @@ pub trait Rng: RngCore { #[must_use] fn map_generator Self::Generator>(self, map: F) -> Self; - fn with_rng Q, Q>(&mut self, inner: F) -> Q; + fn with Q, Q>(&mut self, inner: F) -> Q; } #[allow(clippy::module_name_repetitions)] @@ -121,6 +121,6 @@ where { #[must_use] fn sample_with(&mut self, params: D::Parameters) -> D::Sample { - self.with_rng(|rng, samplers| samplers.sample_with(rng, samplers, params)) + self.with(|rng, samplers| samplers.sample_with(rng, samplers, params)) } } diff --git a/necsim/impls/cuda/src/cogs/rng.rs b/necsim/impls/cuda/src/cogs/rng.rs index 8c29ba2b7..99d7df48a 100644 --- a/necsim/impls/cuda/src/cogs/rng.rs +++ b/necsim/impls/cuda/src/cogs/rng.rs @@ -1,11 +1,9 @@ use core::marker::PhantomData; -use necsim_core::cogs::{MathsCore, Rng, RngCore}; - use const_type_layout::TypeGraphLayout; use rust_cuda::safety::StackOnly; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use necsim_core::cogs::{MathsCore, Rng}; #[allow(clippy::module_name_repetitions)] #[derive(Debug, rust_cuda::common::LendRustToCuda)] @@ -38,22 +36,9 @@ impl + StackOnly + ~const TypeGraphLayout> From for C } } -impl + StackOnly + ~const TypeGraphLayout> RngCore for CudaRng { - type Seed = ::Seed; - - #[must_use] - #[inline] - fn from_seed(seed: Self::Seed) -> Self { - Self { - inner: R::from_seed(seed), - marker: PhantomData::, - } - } - - #[must_use] - #[inline] - fn sample_u64(&mut self) -> u64 { - self.inner.sample_u64() +impl + StackOnly + ~const TypeGraphLayout> CudaRng { + pub fn into(self) -> R { + self.inner } } @@ -74,26 +59,7 @@ impl + StackOnly + ~const TypeGraphLayout> Rng for Cu } } - fn with_rng Q, Q>(&mut self, inner: F) -> Q { - self.inner.with_rng(inner) - } -} - -impl + StackOnly + ~const TypeGraphLayout> Serialize for CudaRng { - fn serialize(&self, serializer: S) -> Result { - self.inner.serialize(serializer) - } -} - -impl<'de, M: MathsCore, R: Rng + StackOnly + ~const TypeGraphLayout> Deserialize<'de> - for CudaRng -{ - fn deserialize>(deserializer: D) -> Result { - let inner = R::deserialize(deserializer)?; - - Ok(Self { - inner, - marker: PhantomData::, - }) + fn with Q, Q>(&mut self, inner: F) -> Q { + self.inner.with(inner) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 4416760b6..19d5ac095 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -12,7 +12,7 @@ use hashbrown::HashMap; use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, Distribution, MathsCore, Rng, Samples, + Backup, Distribution, MathsCore, Rng, RngCore, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -67,7 +67,7 @@ impl RejectionSamplingGroup { rng, Length(NonZeroUsize::new_unchecked(self.weights.len())), ); - let height = rng.sample_u64() >> 11; + let height = rng.generator().sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% if height < self.weights[index] { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 1d1e0872e..ae4187417 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -191,7 +191,7 @@ fn sample_single_group() { let mut tally = [0_u64; 6]; - let mut rng = SimpleRng::::seed_from_u64(24897); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(24897)); for _ in 0..N { let (maybe_group, sample) = group.sample_pop(&mut lookup, &mut rng); @@ -906,7 +906,7 @@ fn add_update_event_full() { fn sample_single_group_full() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(471_093); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(471_093)); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -955,7 +955,7 @@ fn sample_single_group_full() { fn sample_three_groups_full() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(739_139); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(739_139)); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -1001,7 +1001,7 @@ fn sample_three_groups_full() { fn sample_three_groups_full_reverse() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(248_971); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(248_971)); let mut sampler = DynamicAliasMethodIndexedSampler::with_capacity(6); @@ -1123,7 +1123,7 @@ impl Rng for DummyRng { map(self) } - fn with_rng Q, Q>(&mut self, inner: F) -> Q { + fn with Q, Q>(&mut self, inner: F) -> Q { let samplers = DummyDistributionSamplers; inner(self, &samplers) diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 857121d1b..4f7fc1475 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -9,7 +9,7 @@ use core::{ use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, Distribution, MathsCore, Rng, Samples, + Backup, Distribution, MathsCore, Rng, RngCore, Samples, }; use necsim_core_bond::{NonNegativeF64, PositiveF64}; @@ -60,7 +60,7 @@ impl RejectionSamplingGroup { rng, Length(NonZeroUsize::new_unchecked(self.weights.len())), ); - let height = rng.sample_u64() >> 11; + let height = rng.generator().sample_u64() >> 11; // 53rd bit of weight is always 1, so sampling chance >= 50% if height < self.weights[index] { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 10715637c..7a2dcc1f5 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -105,7 +105,7 @@ fn sample_single_group() { let mut tally = [0_u64; 6]; - let mut rng = SimpleRng::::seed_from_u64(24897); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(24897)); for _ in 0..N { let (maybe_group, sample) = group.sample_pop(&mut rng); @@ -405,7 +405,7 @@ fn add_remove_event_full() { fn sample_single_group_full() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(471_093); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(471_093)); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -454,7 +454,7 @@ fn sample_single_group_full() { fn sample_three_groups_full() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(739_139); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(739_139)); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -500,7 +500,7 @@ fn sample_three_groups_full() { fn sample_three_groups_full_reverse() { const N: usize = 10_000_000; - let mut rng = SimpleRng::::seed_from_u64(248_971); + let mut rng = SimpleRng::::from(WyHash::seed_from_u64(248_971)); let mut sampler = DynamicAliasMethodStackSampler::with_capacity(6); @@ -622,7 +622,7 @@ impl Rng for DummyRng { map(self) } - fn with_rng Q, Q>(&mut self, inner: F) -> Q { + fn with Q, Q>(&mut self, inner: F) -> Q { let samplers = DummyDistributionSamplers; inner(self, &samplers) diff --git a/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs b/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs index 84c668f9d..ce74e49d1 100644 --- a/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs +++ b/necsim/impls/no-std/src/cogs/habitat/almost_infinite.rs @@ -1,7 +1,7 @@ use core::{fmt, marker::PhantomData}; use necsim_core::{ - cogs::{Backup, Habitat, MathsCore, Rng, UniformlySampleableHabitat}, + cogs::{Backup, Habitat, MathsCore, Rng, RngCore, UniformlySampleableHabitat}, landscape::{IndexedLocation, LandscapeExtent, Location}, }; use necsim_core_bond::{OffByOneU32, OffByOneU64}; @@ -82,7 +82,7 @@ impl> UniformlySampleableHabitat for AlmostInfinit #[must_use] #[inline] fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { - let index = rng.sample_u64(); + let index = rng.generator().sample_u64(); IndexedLocation::new( Location::new( diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index 9604ccbfb..68656055b 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -3,8 +3,6 @@ use core::{ num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, }; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - use necsim_core::cogs::{ distribution::{ Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, @@ -23,20 +21,18 @@ pub struct SimpleRng { marker: PhantomData, } -impl Serialize for SimpleRng { - fn serialize(&self, serializer: S) -> Result { - self.inner.serialize(serializer) +impl From for SimpleRng { + fn from(inner: R) -> Self { + Self { + inner, + marker: PhantomData::, + } } } -impl<'de, M: MathsCore, R: RngCore> Deserialize<'de> for SimpleRng { - fn deserialize>(deserializer: D) -> Result { - let inner = R::deserialize(deserializer)?; - - Ok(Self { - inner, - marker: PhantomData::, - }) +impl SimpleRng { + pub fn into(self) -> R { + self.inner } } @@ -50,23 +46,6 @@ impl Backup for SimpleRng { } } -impl RngCore for SimpleRng { - type Seed = R::Seed; - - #[must_use] - fn from_seed(seed: Self::Seed) -> Self { - Self { - inner: R::from_seed(seed), - marker: PhantomData::, - } - } - - #[must_use] - fn sample_u64(&mut self) -> u64 { - self.inner.sample_u64() - } -} - impl Rng for SimpleRng { type Generator = R; type Sampler = SimplerDistributionSamplers; @@ -84,7 +63,7 @@ impl Rng for SimpleRng { } } - fn with_rng Q, Q>(&mut self, inner: F) -> Q { + fn with Q, Q>(&mut self, inner: F) -> Q { let samplers = SimplerDistributionSamplers { _marker: PhantomData::<(M, R)>, }; diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index e1a7fc747..b8bf930cc 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -58,13 +58,13 @@ pub fn initialise_and_simulate< Error: From, >( args: &CudaArguments, - rng: CudaRng>, + rng: WyHash, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result>>, Error> +) -> Result, Error> where O::Habitat: RustToCuda, O::DispersalSampler< @@ -120,6 +120,8 @@ where R::ReportDispersal, >, { + let rng = CudaRng::from(SimpleRng::from(rng)); + let ( habitat, dispersal_sampler, @@ -236,8 +238,7 @@ where .into_iter() .chain(passthrough.into_iter()) .collect(), - rng: simulation.rng_mut().clone(), - marker: PhantomData::, + rng: simulation.rng_mut().clone().into().into(), }), } } diff --git a/rustcoalescence/algorithms/cuda/src/lib.rs b/rustcoalescence/algorithms/cuda/src/lib.rs index df9cc279f..eada0dbab 100644 --- a/rustcoalescence/algorithms/cuda/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/src/lib.rs @@ -6,7 +6,11 @@ #[macro_use] extern crate serde_derive_state; -use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; +use necsim_core::{ + cogs::{MathsCore, Rng}, + lineage::Lineage, + reporter::Reporter, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_cuda::cogs::{maths::NvptxMathsCore, rng::CudaRng}; @@ -348,12 +352,12 @@ where fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error> { + ) -> Result>::Generator>, Self::Error> { launch::initialise_and_simulate( &args, rng, @@ -372,14 +376,14 @@ where #[allow(clippy::too_many_lines)] fn resume_and_simulate, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( &args, rng, @@ -401,14 +405,14 @@ where #[allow(clippy::too_many_lines)] fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( &args, rng, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index db147badb..47e68151a 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -1,10 +1,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ - cogs::{ - distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SplittableRng, - }, + cogs::{ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, SplittableRng}, reporter::Reporter, simulation::SimulationBuilder, }; @@ -21,6 +18,7 @@ use necsim_impls_no_std::{ origin_sampler::{ decomposition::DecompositionOriginSampler, pre_sampler::OriginPreSampler, }, + rng::simple::SimpleRng, turnover_rate::uniform::UniformTurnoverRate, }, parallelisation::{self, Status}, @@ -40,15 +38,12 @@ use super::initialiser::ClassicalLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples, - O: Scenario, + G: SplittableRng, + O: Scenario, TurnoverRate = UniformTurnoverRate>, R: Reporter, P: LocalPartition<'p, R>, I: Iterator, - L: ClassicalLineageStoreSampleInitialiser, + L: ClassicalLineageStoreSampleInitialiser, O, Error>, Error, >( args: GillespieArguments, @@ -58,11 +53,13 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> +) -> Result, Error> where O::LineageStore>: LocallyCoherentLineageStore, { + let rng = SimpleRng::from(rng); + match args.parallelism_mode { ParallelismMode::Monolithic => { let ( @@ -72,7 +69,7 @@ where speciation_probability, origin_sampler_auxiliary, _decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = UnconditionalCoalescenceSampler::default(); let event_sampler = UnconditionalEventSampler::default(); @@ -125,7 +122,6 @@ where .cloned() .collect(), rng: simulation.rng_mut().clone(), - marker: PhantomData::, }), } }, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs index 61b3b150d..f9c63710a 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{LocallyCoherentLineageStore, MathsCore}, + cogs::{LocallyCoherentLineageStore, MathsCore, Rng}, lineage::Lineage, reporter::Reporter, }; @@ -44,12 +44,12 @@ where #[allow(clippy::too_many_lines)] fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error> { + ) -> Result>::Generator>, Self::Error> { launch::initialise_and_simulate( args, rng, @@ -67,14 +67,14 @@ where /// simulation failed fn resume_and_simulate, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, @@ -96,14 +96,14 @@ where #[allow(clippy::too_many_lines)] fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index 2d13ad2a1..4ff08b8e5 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -1,10 +1,7 @@ use std::marker::PhantomData; use necsim_core::{ - cogs::{ - distribution::{Bernoulli, IndexUsize, Poisson, UniformClosedOpenUnit}, - MathsCore, PrimeableRng, Rng, Samples, - }, + cogs::{MathsCore, PrimeableRng}, reporter::Reporter, simulation::SimulationBuilder, }; @@ -29,6 +26,7 @@ use necsim_impls_no_std::{ origin_sampler::{ decomposition::DecompositionOriginSampler, pre_sampler::OriginPreSampler, }, + rng::simple::SimpleRng, }, parallelisation::{self, Status}, }; @@ -49,16 +47,12 @@ use crate::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples - + Samples, - O: Scenario, + G: PrimeableRng, + O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, I: Iterator, - L: IndependentLineageStoreSampleInitialiser, + L: IndependentLineageStoreSampleInitialiser, O, Error>, Error, >( args: &IndependentArguments, @@ -68,7 +62,9 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> { +) -> Result, Error> { + let rng = SimpleRng::from(rng); + match args.parallelism_mode { ParallelismMode::Monolithic(MonolithicParallelismMode { event_slice }) | ParallelismMode::IsolatedIndividuals(IsolatedParallelismMode { event_slice, .. }) @@ -80,7 +76,7 @@ pub fn initialise_and_simulate< speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = IndependentCoalescenceSampler::default(); let event_sampler = IndependentEventSampler::default(); @@ -163,8 +159,7 @@ pub fn initialise_and_simulate< .into_iter() .chain(passthrough.into_iter()) .collect(), - rng: simulation.rng_mut().clone(), - marker: PhantomData::, + rng: simulation.rng_mut().clone().into(), }), } }, @@ -176,7 +171,7 @@ pub fn initialise_and_simulate< speciation_probability, origin_sampler_auxiliary, _decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = IndependentCoalescenceSampler::default(); let event_sampler = IndependentEventSampler::default(); @@ -231,7 +226,7 @@ pub fn initialise_and_simulate< speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = IndependentCoalescenceSampler::default(); let event_sampler = IndependentEventSampler::default(); @@ -294,7 +289,7 @@ pub fn initialise_and_simulate< speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = IndependentCoalescenceSampler::default(); let event_sampler = IndependentEventSampler::default(); diff --git a/rustcoalescence/algorithms/independent/src/lib.rs b/rustcoalescence/algorithms/independent/src/lib.rs index dff7dde25..3783060ee 100644 --- a/rustcoalescence/algorithms/independent/src/lib.rs +++ b/rustcoalescence/algorithms/independent/src/lib.rs @@ -5,7 +5,11 @@ #[macro_use] extern crate serde_derive_state; -use necsim_core::{cogs::MathsCore, lineage::Lineage, reporter::Reporter}; +use necsim_core::{ + cogs::{MathsCore, Rng}, + lineage::Lineage, + reporter::Reporter, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::{ @@ -70,12 +74,12 @@ impl< fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error> { + ) -> Result>::Generator>, Self::Error> { launch::initialise_and_simulate( &args, rng, @@ -93,14 +97,14 @@ impl< /// simulation failed fn resume_and_simulate, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( &args, rng, @@ -122,14 +126,14 @@ impl< #[allow(clippy::too_many_lines)] fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( &args, rng, diff --git a/rustcoalescence/algorithms/src/lib.rs b/rustcoalescence/algorithms/src/lib.rs index 2c1138524..3298b4958 100644 --- a/rustcoalescence/algorithms/src/lib.rs +++ b/rustcoalescence/algorithms/src/lib.rs @@ -48,12 +48,12 @@ pub trait Algorithm< /// the algorithm failed fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error>; + ) -> Result>::Generator>, Self::Error>; /// # Errors /// @@ -62,14 +62,14 @@ pub trait Algorithm< #[allow(clippy::type_complexity, clippy::too_many_arguments)] fn resume_and_simulate, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError>; + ) -> Result>::Generator>, ResumeError>; /// # Errors /// @@ -78,12 +78,12 @@ pub trait Algorithm< #[allow(clippy::type_complexity, clippy::too_many_arguments)] fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError>; + ) -> Result>::Generator>, ResumeError>; } diff --git a/rustcoalescence/algorithms/src/result.rs b/rustcoalescence/algorithms/src/result.rs index cf1c7c98d..9399bc50b 100644 --- a/rustcoalescence/algorithms/src/result.rs +++ b/rustcoalescence/algorithms/src/result.rs @@ -1,14 +1,11 @@ -use std::{error::Error as StdError, fmt, marker::PhantomData}; +use std::{error::Error as StdError, fmt}; -use necsim_core::{ - cogs::{MathsCore, Rng}, - lineage::Lineage, -}; +use necsim_core::{cogs::RngCore, lineage::Lineage}; use necsim_core_bond::NonNegativeF64; use necsim_impls_no_std::cogs::active_lineage_sampler::resuming::lineage::ExceptionalLineage; -pub enum SimulationOutcome> { +pub enum SimulationOutcome { Done { time: NonNegativeF64, steps: u64, @@ -18,7 +15,6 @@ pub enum SimulationOutcome> { steps: u64, lineages: Vec, rng: G, - marker: PhantomData, }, } diff --git a/rustcoalescence/src/args/config/rng/mod.rs b/rustcoalescence/src/args/config/rng/mod.rs index 406800030..511a55826 100644 --- a/rustcoalescence/src/args/config/rng/mod.rs +++ b/rustcoalescence/src/args/config/rng/mod.rs @@ -1,9 +1,9 @@ -use std::{fmt, marker::PhantomData}; +use std::fmt; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_state::DeserializeState; -use necsim_core::cogs::{MathsCore, Rng}; +use necsim_core::cogs::RngCore; use necsim_partitioning_core::partition::Partition; mod base32; @@ -11,27 +11,25 @@ mod base32; use self::base32::Base32String; #[derive(Debug, Serialize)] -#[serde(bound = "")] #[serde(rename = "Rng")] #[allow(clippy::module_name_repetitions)] -pub enum RngConfig> { +pub enum RngConfig { Seed(u64), Sponge(Base32String), - State(Base32RngState), + State(Base32RngState), } #[allow(dead_code)] -pub struct Base32RngState> { +pub struct Base32RngState { rng: G, - marker: PhantomData, } -impl<'de, M: MathsCore, G: Rng> DeserializeState<'de, Partition> for RngConfig { +impl<'de, G: RngCore> DeserializeState<'de, Partition> for RngConfig { fn deserialize_state>( partition: &mut Partition, deserializer: D, ) -> Result { - let raw = RngRaw::::deserialize(deserializer)?; + let raw = RngRaw::::deserialize(deserializer)?; let rng = match raw { RngRaw::Entropy => { @@ -62,10 +60,7 @@ impl<'de, M: MathsCore, G: Rng> DeserializeState<'de, Partition> for RngConfi RngRaw::State(state) => Self::State(state), RngRaw::StateElseSponge(state) => { match bincode::Options::deserialize(bincode::options(), &state) { - Ok(rng) => Self::State(Base32RngState { - rng, - marker: PhantomData::, - }), + Ok(rng) => Self::State(Base32RngState { rng }), Err(_) => Self::Sponge(state), } }, @@ -75,16 +70,13 @@ impl<'de, M: MathsCore, G: Rng> DeserializeState<'de, Partition> for RngConfi } } -impl> From for Base32RngState { +impl From for Base32RngState { fn from(rng: G) -> Self { - Self { - rng, - marker: PhantomData::, - } + Self { rng } } } -impl> Base32RngState { +impl Base32RngState { #[must_use] #[allow(dead_code)] pub fn into(self) -> G { @@ -92,7 +84,7 @@ impl> Base32RngState { } } -impl> fmt::Debug for Base32RngState { +impl fmt::Debug for Base32RngState { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match ProtectedState::serialize(&self.rng) { Ok(state) => Base32String::new(&state).fmt(fmt), @@ -101,7 +93,7 @@ impl> fmt::Debug for Base32RngState { } } -impl> Serialize for Base32RngState { +impl Serialize for Base32RngState { fn serialize(&self, serializer: S) -> Result { let state = ProtectedState::serialize(&self.rng).map_err(serde::ser::Error::custom)?; @@ -109,16 +101,13 @@ impl> Serialize for Base32RngState { } } -impl<'de, M: MathsCore, G: Rng> Deserialize<'de> for Base32RngState { +impl<'de, G: RngCore> Deserialize<'de> for Base32RngState { fn deserialize>(deserializer: D) -> Result { let state = Base32String::deserialize(deserializer)?; if let Some(state) = ProtectedState::from_bytes(&state) { if let Ok(rng) = ProtectedState::deserialize(state) { - return Ok(Self { - rng, - marker: PhantomData::, - }); + return Ok(Self { rng }); } } @@ -129,14 +118,14 @@ impl<'de, M: MathsCore, G: Rng> Deserialize<'de> for Base32RngState { } #[derive(Debug, Deserialize)] -#[serde(bound = "")] #[serde(rename = "Rng")] -enum RngRaw> { +#[serde(bound = "")] +enum RngRaw { Entropy, Seed(u64), #[serde(deserialize_with = "deserialize_rng_sponge")] Sponge(Base32String), - State(Base32RngState), + State(Base32RngState), #[serde(deserialize_with = "deserialize_rng_state_else_sponge")] StateElseSponge(Base32String), } diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs index 542611cb9..ebfa386ab 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs @@ -3,7 +3,7 @@ use tiny_keccak::{Hasher, Keccak}; use rustcoalescence_algorithms::{result::SimulationOutcome as AlgorithmOutcome, Algorithm}; use necsim_core::{ - cogs::{MathsCore, RngCore, SeedableRng}, + cogs::{MathsCore, Rng, RngCore, SeedableRng}, reporter::Reporter, }; use necsim_core_bond::NonNegativeF64; @@ -46,14 +46,14 @@ where Result, A::Error>: anyhow::Context, A::Error>, { - let rng: A::Rng = match parse::rng::parse_and_normalise( + let rng: >::Generator = match parse::rng::parse_and_normalise( ron_args, normalised_args, &mut A::get_logical_partition(&algorithm_args, &local_partition), )? { RngConfig::Seed(seed) => SeedableRng::seed_from_u64(seed), RngConfig::Sponge(bytes) => { - let mut seed = ::Seed::default(); + let mut seed = <>::Generator as RngCore>::Seed::default(); let mut sponge = Keccak::v256(); sponge.update(&bytes); @@ -81,7 +81,6 @@ where steps, lineages, rng: paused_rng, - .. } => { normalised_args.rng(&RngConfig::State(Base32RngState::from(paused_rng))); diff --git a/rustcoalescence/src/cli/simulate/parse/rng.rs b/rustcoalescence/src/cli/simulate/parse/rng.rs index b059a2223..399fda49c 100644 --- a/rustcoalescence/src/cli/simulate/parse/rng.rs +++ b/rustcoalescence/src/cli/simulate/parse/rng.rs @@ -1,4 +1,4 @@ -use necsim_core::cogs::{MathsCore, Rng}; +use necsim_core::cogs::RngCore; use necsim_partitioning_core::partition::Partition; use crate::args::{config::rng::RngConfig, utils::parse::try_parse_state}; @@ -6,11 +6,11 @@ use crate::args::{config::rng::RngConfig, utils::parse::try_parse_state}; use super::super::BufferingSimulateArgsBuilder; #[allow(dead_code)] -pub(in super::super) fn parse_and_normalise>( +pub(in super::super) fn parse_and_normalise( ron_args: &str, normalised_args: &mut BufferingSimulateArgsBuilder, partition: &mut Partition, -) -> anyhow::Result> { +) -> anyhow::Result> { let SimulateArgsRngOnly { rng } = try_parse_state("simulate", ron_args, partition)?; normalised_args.rng(&rng); @@ -19,11 +19,10 @@ pub(in super::super) fn parse_and_normalise>( } #[derive(DeserializeState)] -#[serde(bound = "")] #[serde(rename = "Simulate")] #[serde(deserialize_state = "Partition")] -struct SimulateArgsRngOnly> { +struct SimulateArgsRngOnly { #[serde(alias = "randomness")] #[serde(deserialize_state)] - rng: RngConfig, + rng: RngConfig, } From 467eadc92069020a39f8e16b40a1da318a733759 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Fri, 20 May 2022 06:32:52 +0000 Subject: [PATCH 12/21] Finished refactoring of Rng not a subtrait of RngCore --- .../gillespie/src/event_skipping/launch.rs | 30 +++++++++---------- .../gillespie/src/event_skipping/mod.rs | 14 ++++----- .../src/gillespie/classical/launch.rs | 4 +-- .../src/gillespie/turnover/launch.rs | 26 +++++++--------- .../gillespie/src/gillespie/turnover/mod.rs | 14 ++++----- .../src/cli/simulate/dispatch/valid/info.rs | 10 +++---- .../src/cli/simulate/dispatch/valid/launch.rs | 9 ++++-- .../src/cli/simulate/dispatch/valid/rng.rs | 4 +-- 8 files changed, 55 insertions(+), 56 deletions(-) diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index 22c2e794b..ea9803bc8 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -2,8 +2,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ cogs::{ - distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, GloballyCoherentLineageStore, MathsCore, Rng, Samples, + ActiveLineageSampler, GloballyCoherentLineageStore, MathsCore, Rng, SeparableDispersalSampler, SplittableRng, }, reporter::Reporter, @@ -21,6 +20,7 @@ use necsim_impls_no_std::{ origin_sampler::{ decomposition::DecompositionOriginSampler, pre_sampler::OriginPreSampler, }, + rng::simple::SimpleRng, }, parallelisation::{self, Status}, }; @@ -38,15 +38,12 @@ use crate::arguments::{ pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples, - O: Scenario, + G: SplittableRng, + O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, I: Iterator, - L: EventSkippingLineageStoreSampleInitialiser, + L: EventSkippingLineageStoreSampleInitialiser, O, Error>, Error, >( args: GillespieArguments, @@ -56,13 +53,15 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> +) -> Result, Error> where O::LineageStore>: GloballyCoherentLineageStore, - O::DispersalSampler>: - SeparableDispersalSampler, + O::DispersalSampler>>: + SeparableDispersalSampler>, { + let rng = SimpleRng::from(rng); + match args.parallelism_mode { ParallelismMode::Monolithic => { let ( @@ -72,7 +71,8 @@ where speciation_probability, origin_sampler_auxiliary, _decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario + .build::>>(); let coalescence_sampler = ConditionalCoalescenceSampler::default(); let (lineage_store, dispersal_sampler, event_sampler, active_lineage_sampler): ( @@ -127,8 +127,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone(), - marker: PhantomData::, + rng: simulation.rng_mut().clone().into(), }), } }, @@ -144,7 +143,8 @@ where speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario + .build::>>(); let coalescence_sampler = ConditionalCoalescenceSampler::default(); let decomposition = O::decompose( diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs index 457b87692..2c473fa3a 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{GloballyCoherentLineageStore, MathsCore, SeparableDispersalSampler}, + cogs::{GloballyCoherentLineageStore, MathsCore, Rng, SeparableDispersalSampler}, lineage::Lineage, reporter::Reporter, }; @@ -64,12 +64,12 @@ where fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error> { + ) -> Result>::Generator>, Self::Error> { launch::initialise_and_simulate( args, rng, @@ -87,14 +87,14 @@ where /// simulation failed fn resume_and_simulate, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, @@ -115,14 +115,14 @@ where /// simulation (incl. running the algorithm) failed fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 47e68151a..8156b0203 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -121,7 +121,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone(), + rng: simulation.rng_mut().clone().into(), }), } }, @@ -137,7 +137,7 @@ where speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = UnconditionalCoalescenceSampler::default(); let event_sampler = UnconditionalEventSampler::default(); diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index 86d90adb4..ffd8fefa8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -1,10 +1,7 @@ use std::{hint::unreachable_unchecked, marker::PhantomData}; use necsim_core::{ - cogs::{ - distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, - ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SplittableRng, - }, + cogs::{ActiveLineageSampler, LocallyCoherentLineageStore, MathsCore, Rng, SplittableRng}, reporter::Reporter, simulation::SimulationBuilder, }; @@ -21,6 +18,7 @@ use necsim_impls_no_std::{ origin_sampler::{ decomposition::DecompositionOriginSampler, pre_sampler::OriginPreSampler, }, + rng::simple::SimpleRng, }, parallelisation::{self, Status}, }; @@ -39,15 +37,12 @@ use super::initialiser::GillespieLineageStoreSampleInitialiser; pub fn initialise_and_simulate< 'p, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples, - O: Scenario, + G: SplittableRng, + O: Scenario>, R: Reporter, P: LocalPartition<'p, R>, I: Iterator, - L: GillespieLineageStoreSampleInitialiser, + L: GillespieLineageStoreSampleInitialiser, O, Error>, Error, >( args: GillespieArguments, @@ -57,11 +52,13 @@ pub fn initialise_and_simulate< pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, -) -> Result, Error> +) -> Result, Error> where O::LineageStore>: LocallyCoherentLineageStore, { + let rng = SimpleRng::from(rng); + match args.parallelism_mode { ParallelismMode::Monolithic => { let ( @@ -71,7 +68,7 @@ where speciation_probability, origin_sampler_auxiliary, _decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = UnconditionalCoalescenceSampler::default(); let event_sampler = UnconditionalEventSampler::default(); @@ -124,8 +121,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone(), - marker: PhantomData::, + rng: simulation.rng_mut().clone().into(), }), } }, @@ -141,7 +137,7 @@ where speciation_probability, origin_sampler_auxiliary, decomposition_auxiliary, - ) = scenario.build::>(); + ) = scenario.build::>>(); let coalescence_sampler = UnconditionalCoalescenceSampler::default(); let event_sampler = UnconditionalEventSampler::default(); diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs index 728f34acf..e78723512 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs @@ -1,5 +1,5 @@ use necsim_core::{ - cogs::{LocallyCoherentLineageStore, MathsCore}, + cogs::{LocallyCoherentLineageStore, MathsCore, Rng}, lineage::Lineage, reporter::Reporter, }; @@ -52,12 +52,12 @@ where #[allow(clippy::shadow_unrelated, clippy::too_many_lines)] default fn initialise_and_simulate>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, - ) -> Result, Self::Error> { + ) -> Result>::Generator>, Self::Error> { launch::initialise_and_simulate( args, rng, @@ -79,14 +79,14 @@ where L: ExactSizeIterator, >( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, @@ -108,14 +108,14 @@ where #[allow(clippy::too_many_lines)] default fn fixup_for_restart, L: ExactSizeIterator>( args: Self::Arguments, - rng: Self::Rng, + rng: >::Generator, scenario: O, pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, local_partition: &mut P, - ) -> Result, ResumeError> { + ) -> Result>::Generator>, ResumeError> { launch::initialise_and_simulate( args, rng, diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs index aac4223c9..00fcc3f73 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/info.rs @@ -5,7 +5,7 @@ use anyhow::{Context, Result}; use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm}; use necsim_core::{ - cogs::MathsCore, + cogs::{MathsCore, Rng}, reporter::{boolean::Boolean, Reporter}, }; use necsim_core_bond::NonNegativeF64; @@ -31,17 +31,17 @@ pub(super) fn dispatch< P: LocalPartition<'p, R>, >( algorithm_args: A::Arguments, - rng: A::Rng, + rng: >::Generator, scenario: O, sample: Sample, pause_before: Option, mut local_partition: P, normalised_args: &BufferingSimulateArgsBuilder, -) -> anyhow::Result> +) -> anyhow::Result>::Generator>> where - Result, A::Error>: - anyhow::Context, A::Error>, + Result>::Generator>, A::Error>: + anyhow::Context>::Generator>, A::Error>, { let config_str = normalised_args .build() diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs index e070202d6..1512b8ef0 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/launch.rs @@ -2,7 +2,10 @@ use anyhow::Context; use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm}; -use necsim_core::{cogs::MathsCore, reporter::Reporter}; +use necsim_core::{ + cogs::{MathsCore, Rng}, + reporter::Reporter, +}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use necsim_impls_no_std::cogs::origin_sampler::pre_sampler::OriginPreSampler; use necsim_partitioning_core::LocalPartition; @@ -20,12 +23,12 @@ pub(super) fn simulate< P: LocalPartition<'p, R>, >( algorithm_args: A::Arguments, - rng: A::Rng, + rng: >::Generator, scenario: O, sample: Sample, pause_before: Option, local_partition: &mut P, -) -> anyhow::Result> { +) -> anyhow::Result>::Generator>> { let lineages = match sample.origin { SampleOrigin::Habitat => { return A::initialise_and_simulate( diff --git a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs index ebfa386ab..6433fc54c 100644 --- a/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs +++ b/rustcoalescence/src/cli/simulate/dispatch/valid/rng.rs @@ -43,8 +43,8 @@ pub(super) fn dispatch< normalised_args: &mut BufferingSimulateArgsBuilder, ) -> anyhow::Result where - Result, A::Error>: - anyhow::Context, A::Error>, + Result>::Generator>, A::Error>: + anyhow::Context>::Generator>, A::Error>, { let rng: >::Generator = match parse::rng::parse_and_normalise( ron_args, From ff7b4d0b73c463949465f82442defe8442ded673 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Fri, 20 May 2022 09:33:53 +0000 Subject: [PATCH 13/21] Added RawDistribution for better DistributionSampler impl self-documentation --- necsim/core/src/cogs/distribution.rs | 41 ++++++++++---- necsim/core/src/cogs/rng.rs | 2 +- .../alias/sampler/indexed/tests.rs | 6 +- .../alias/sampler/stack/tests.rs | 6 +- necsim/impls/no-std/src/cogs/rng/simple.rs | 56 ++++++++++--------- 5 files changed, 67 insertions(+), 44 deletions(-) diff --git a/necsim/core/src/cogs/distribution.rs b/necsim/core/src/cogs/distribution.rs index 525f1689d..9bbd95f68 100644 --- a/necsim/core/src/cogs/distribution.rs +++ b/necsim/core/src/cogs/distribution.rs @@ -36,22 +36,43 @@ impl Distribution for D { } #[allow(clippy::module_name_repetitions)] -pub trait DistributionSampler { +pub trait RawDistribution: DistributionCore { + fn sample_raw_with>( + rng: &mut R, + samplers: &S, + params: Self::Parameters, + ) -> Self::Sample; + + fn sample_raw>( + rng: &mut R, + samplers: &S, + ) -> Self::Sample + where + Self: DistributionCore, + { + Self::sample_raw_with(rng, samplers, ()) + } +} + +impl RawDistribution for D { + fn sample_raw_with>( + rng: &mut R, + samplers: &S, + params: Self::Parameters, + ) -> Self::Sample { + samplers.sample_distribution(rng, samplers, params) + } +} + +#[allow(clippy::module_name_repetitions)] +pub trait DistributionSampler { type ConcreteSampler: DistributionSampler; #[must_use] fn concrete(&self) -> &Self::ConcreteSampler; #[must_use] - fn sample_with(&self, rng: &mut R, samplers: &S, params: D::Parameters) -> D::Sample; - - #[must_use] - fn sample(&self, rng: &mut R, samplers: &S) -> D::Sample - where - D: DistributionCore, - { - self.sample_with(rng, samplers, ()) - } + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: D::Parameters) -> D::Sample; } pub enum UniformClosedOpenUnit {} diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index 956cae27b..1a728becc 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -121,6 +121,6 @@ where { #[must_use] fn sample_with(&mut self, params: D::Parameters) -> D::Sample { - self.with(|rng, samplers| samplers.sample_with(rng, samplers, params)) + self.with(|rng, samplers| samplers.sample_distribution(rng, samplers, params)) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index ae4187417..098ca2861 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1141,7 +1141,7 @@ impl DistributionSampler DistributionSampler ClosedOpenUnitF64 { + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval #[allow(clippy::cast_precision_loss)] let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 @@ -104,7 +105,7 @@ impl DistributionSampler OpenClosedUnitF64 { + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval #[allow(clippy::cast_precision_loss)] let u01 = @@ -123,10 +124,15 @@ impl) -> usize { + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + params: Length, + ) -> usize { let length = params.0; - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( clippy::cast_precision_loss, @@ -149,10 +155,10 @@ impl) -> u32 { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u32 { let length = params.0; - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let index = M::floor(u01.get() * f64::from(length.get())) as u32; @@ -171,10 +177,10 @@ impl) -> u64 { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { let length = params.0; - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( clippy::cast_precision_loss, @@ -197,10 +203,10 @@ impl) -> u128 { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { let length = params.0; - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( clippy::cast_precision_loss, @@ -223,10 +229,10 @@ impl NonNegativeF64 { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Lambda) -> NonNegativeF64 { let lambda = params.0; - let u01: OpenClosedUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformOpenClosedUnit::sample_raw(rng, samplers); // Inverse transform sample: X = -ln(U(0,1]) / lambda -u01.ln::() / lambda @@ -246,15 +252,14 @@ impl< self } - fn sample_with(&self, rng: &mut R, samplers: &S, params: Lambda) -> u64 { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Lambda) -> u64 { let lambda = params.0; let no_event_probability = M::exp(-lambda.get()); if no_event_probability <= 0.0_f64 { // Fallback in case no_event_probability_per_step underflows #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let normal_as_poisson = DistributionSampler::::sample_with( - samplers, + let normal_as_poisson = Normal2D::sample_raw_with( rng, samplers, Normal { @@ -273,8 +278,7 @@ impl< let mut prod = no_event_probability; let mut acc = no_event_probability; - let u = - DistributionSampler::::sample(samplers, rng, samplers); + let u = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow(clippy::cast_precision_loss)] while u > acc && prod > 0.0_f64 { @@ -296,10 +300,10 @@ impl bool { + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: ClosedUnitF64) -> bool { let probability = params; - let u01: ClosedOpenUnitF64 = samplers.sample(rng, samplers); + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); // if probability == 1, then U[0, 1) always < 1.0 // if probability == 0, then U[0, 1) never < 0.0 @@ -320,12 +324,10 @@ impl< self } - fn sample_with(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { + fn sample_distribution(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { // Basic Box-Muller transform - let u0 = - DistributionSampler::::sample(samplers, rng, samplers); - let u1 = - DistributionSampler::::sample(samplers, rng, samplers); + let u0 = UniformOpenClosedUnit::sample_raw(rng, samplers); + let u1 = UniformClosedOpenUnit::sample_raw(rng, samplers); let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); let theta = -core::f64::consts::TAU * u1.get(); @@ -343,8 +345,8 @@ impl self } - fn sample_with(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { - let (z0, z1) = samplers.sample(rng, samplers); + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { + let (z0, z1) = StandardNormal2D::sample_raw(rng, samplers); ( z0 * params.sigma.get() + params.mu, From 14285ced8f545f83ec17373c89d5b0d1cdb84033 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Sat, 21 May 2022 08:46:49 +0000 Subject: [PATCH 14/21] Refactored Rng+RngCore without Clone --- .../core/src/cogs/active_lineage_sampler.rs | 6 +- necsim/core/src/cogs/coalescence_sampler.rs | 2 +- necsim/core/src/cogs/dispersal_sampler.rs | 4 +- necsim/core/src/cogs/emigration_exit.rs | 4 +- necsim/core/src/cogs/event_sampler.rs | 6 +- necsim/core/src/cogs/habitat.rs | 4 +- necsim/core/src/cogs/immigration_entry.rs | 4 +- necsim/core/src/cogs/lineage_reference.rs | 4 +- necsim/core/src/cogs/lineage_store.rs | 6 +- necsim/core/src/cogs/rng.rs | 6 +- .../core/src/cogs/speciation_probability.rs | 6 +- necsim/core/src/cogs/turnover_rate.rs | 6 +- necsim/core/src/simulation/builder.rs | 33 +++++++ necsim/impls/cuda/src/cogs/rng.rs | 23 ++--- necsim/impls/cuda/src/lib.rs | 2 +- .../alias/sampler/indexed/tests.rs | 2 +- .../alias/sampler/stack/tests.rs | 2 +- .../no-std/src/cogs/origin_sampler/mod.rs | 6 +- necsim/impls/no-std/src/cogs/rng/rand.rs | 6 +- necsim/impls/no-std/src/cogs/rng/seahash.rs | 9 +- necsim/impls/no-std/src/cogs/rng/simple.rs | 4 +- necsim/impls/no-std/src/cogs/rng/wyhash.rs | 7 +- necsim/impls/no-std/src/decomposition/mod.rs | 2 +- necsim/impls/std/src/cogs/rng/pcg.rs | 94 ++++++++++--------- rustcoalescence/algorithms/cuda/src/launch.rs | 2 +- .../gillespie/src/event_skipping/launch.rs | 2 +- .../src/gillespie/classical/launch.rs | 2 +- .../src/gillespie/turnover/launch.rs | 2 +- .../algorithms/independent/src/launch.rs | 2 +- rustcoalescence/algorithms/src/lib.rs | 2 +- 30 files changed, 148 insertions(+), 112 deletions(-) diff --git a/necsim/core/src/cogs/active_lineage_sampler.rs b/necsim/core/src/cogs/active_lineage_sampler.rs index bb8b2cc76..218c0e3de 100644 --- a/necsim/core/src/cogs/active_lineage_sampler.rs +++ b/necsim/core/src/cogs/active_lineage_sampler.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use necsim_core_bond::{NonNegativeF64, PositiveF64}; use super::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, ImmigrationEntry, - LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, + ImmigrationEntry, LineageStore, MathsCore, Rng, SpeciationProbability, TurnoverRate, }; use crate::{lineage::Lineage, simulation::partial::active_lineage_sampler::PartialSimulation}; @@ -24,7 +24,7 @@ pub trait ActiveLineageSampler< N: SpeciationProbability, E: EventSampler, I: ImmigrationEntry, ->: crate::cogs::Backup + core::fmt::Debug +>: Backup + core::fmt::Debug { type LineageIterator<'a>: Iterator where diff --git a/necsim/core/src/cogs/coalescence_sampler.rs b/necsim/core/src/cogs/coalescence_sampler.rs index 2f2eed5b3..eae990435 100644 --- a/necsim/core/src/cogs/coalescence_sampler.rs +++ b/necsim/core/src/cogs/coalescence_sampler.rs @@ -16,7 +16,7 @@ use crate::{ #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] pub trait CoalescenceSampler, S: LineageStore>: - crate::cogs::Backup + core::fmt::Debug + Backup + core::fmt::Debug { #[must_use] #[debug_requires(habitat.get_habitat_at_location(&location) > 0, "location is habitable")] diff --git a/necsim/core/src/cogs/dispersal_sampler.rs b/necsim/core/src/cogs/dispersal_sampler.rs index 5d6a817e7..709c80c23 100644 --- a/necsim/core/src/cogs/dispersal_sampler.rs +++ b/necsim/core/src/cogs/dispersal_sampler.rs @@ -1,7 +1,7 @@ use necsim_core_bond::ClosedUnitF64; use crate::{ - cogs::{MathsCore, Rng}, + cogs::{Backup, MathsCore, Rng}, landscape::Location, }; @@ -12,7 +12,7 @@ use super::Habitat; #[allow(clippy::module_name_repetitions)] #[contract_trait] pub trait DispersalSampler, G: Rng>: - crate::cogs::Backup + core::fmt::Debug + Backup + core::fmt::Debug { #[must_use] #[debug_requires(habitat.is_location_habitable(location), "location is habitable")] diff --git a/necsim/core/src/cogs/emigration_exit.rs b/necsim/core/src/cogs/emigration_exit.rs index 3812eee63..be1b71117 100644 --- a/necsim/core/src/cogs/emigration_exit.rs +++ b/necsim/core/src/cogs/emigration_exit.rs @@ -1,7 +1,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use crate::{ - cogs::{Habitat, LineageStore, MathsCore, Rng}, + cogs::{Backup, Habitat, LineageStore, MathsCore, Rng}, landscape::{IndexedLocation, Location}, lineage::GlobalLineageReference, simulation::partial::emigration_exit::PartialSimulation, @@ -15,7 +15,7 @@ use crate::{ #[allow(clippy::no_effect_underscore_binding)] #[contract_trait] pub trait EmigrationExit, G: Rng, S: LineageStore>: - crate::cogs::Backup + core::fmt::Debug + Backup + core::fmt::Debug { #[must_use] #[debug_ensures(match &ret { diff --git a/necsim/core/src/cogs/event_sampler.rs b/necsim/core/src/cogs/event_sampler.rs index 7aecda59f..1ab2caac8 100644 --- a/necsim/core/src/cogs/event_sampler.rs +++ b/necsim/core/src/cogs/event_sampler.rs @@ -1,8 +1,8 @@ use necsim_core_bond::PositiveF64; use super::{ - CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, Rng, - SpeciationProbability, TurnoverRate, + Backup, CoalescenceSampler, DispersalSampler, EmigrationExit, Habitat, LineageStore, MathsCore, + Rng, SpeciationProbability, TurnoverRate, }; use crate::{ event::{DispersalEvent, SpeciationEvent}, @@ -28,7 +28,7 @@ pub trait EventSampler< C: CoalescenceSampler, T: TurnoverRate, N: SpeciationProbability, ->: crate::cogs::Backup + core::fmt::Debug +>: Backup + core::fmt::Debug { #[must_use] fn sample_event_for_lineage_at_event_time_or_emigrate< diff --git a/necsim/core/src/cogs/habitat.rs b/necsim/core/src/cogs/habitat.rs index 1442637ad..f9093db76 100644 --- a/necsim/core/src/cogs/habitat.rs +++ b/necsim/core/src/cogs/habitat.rs @@ -2,7 +2,7 @@ use necsim_core_bond::OffByOneU64; use crate::landscape::{IndexedLocation, LandscapeExtent, Location}; -use super::{MathsCore, Rng}; +use super::{Backup, MathsCore, Rng}; #[allow( clippy::inline_always, @@ -10,7 +10,7 @@ use super::{MathsCore, Rng}; clippy::no_effect_underscore_binding )] #[contract_trait] -pub trait Habitat: crate::cogs::Backup + core::fmt::Debug + Sized { +pub trait Habitat: Backup + core::fmt::Debug { type LocationIterator<'a>: Iterator + 'a where Self: 'a; diff --git a/necsim/core/src/cogs/immigration_entry.rs b/necsim/core/src/cogs/immigration_entry.rs index 03d4d8fbe..c900a1dcd 100644 --- a/necsim/core/src/cogs/immigration_entry.rs +++ b/necsim/core/src/cogs/immigration_entry.rs @@ -1,10 +1,10 @@ use crate::lineage::MigratingLineage; -use super::MathsCore; +use super::{Backup, MathsCore}; #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait ImmigrationEntry: crate::cogs::Backup + core::fmt::Debug { +pub trait ImmigrationEntry: Backup + core::fmt::Debug { #[must_use] fn next_optional_immigration(&mut self) -> Option; diff --git a/necsim/core/src/cogs/lineage_reference.rs b/necsim/core/src/cogs/lineage_reference.rs index 162dfe93c..eeea41e1b 100644 --- a/necsim/core/src/cogs/lineage_reference.rs +++ b/necsim/core/src/cogs/lineage_reference.rs @@ -1,9 +1,9 @@ use core::hash::Hash; -use super::{Habitat, MathsCore}; +use super::{Backup, Habitat, MathsCore}; #[allow(clippy::module_name_repetitions)] pub trait LineageReference>: - crate::cogs::Backup + PartialEq + Eq + Hash + core::fmt::Debug + Backup + PartialEq + Eq + Hash + core::fmt::Debug { } diff --git a/necsim/core/src/cogs/lineage_store.rs b/necsim/core/src/cogs/lineage_store.rs index afc0d319d..70b49cdb7 100644 --- a/necsim/core/src/cogs/lineage_store.rs +++ b/necsim/core/src/cogs/lineage_store.rs @@ -1,6 +1,6 @@ use core::ops::Index; -use super::{Habitat, LineageReference, MathsCore}; +use super::{Backup, Habitat, LineageReference, MathsCore}; use crate::{ landscape::{IndexedLocation, Location}, lineage::{GlobalLineageReference, Lineage}, @@ -8,9 +8,7 @@ use crate::{ #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait LineageStore>: - crate::cogs::Backup + Sized + core::fmt::Debug -{ +pub trait LineageStore>: Backup + Sized + core::fmt::Debug { type LocalLineageReference: LineageReference; #[must_use] diff --git a/necsim/core/src/cogs/rng.rs b/necsim/core/src/cogs/rng.rs index 1a728becc..008718dc3 100644 --- a/necsim/core/src/cogs/rng.rs +++ b/necsim/core/src/cogs/rng.rs @@ -7,7 +7,7 @@ use crate::{ landscape::IndexedLocation, }; -pub trait Rng: Backup + Clone + core::fmt::Debug { +pub trait Rng: Backup + core::fmt::Debug { type Generator: RngCore; type Sampler; @@ -21,9 +21,7 @@ pub trait Rng: Backup + Clone + core::fmt::Debug { } #[allow(clippy::module_name_repetitions)] -pub trait RngCore: - crate::cogs::Backup + Sized + Clone + core::fmt::Debug + Serialize + DeserializeOwned -{ +pub trait RngCore: Backup + Sized + core::fmt::Debug + Serialize + DeserializeOwned { type Seed: AsMut<[u8]> + Default + Sized; #[must_use] diff --git a/necsim/core/src/cogs/speciation_probability.rs b/necsim/core/src/cogs/speciation_probability.rs index 8584228d6..7800c55fa 100644 --- a/necsim/core/src/cogs/speciation_probability.rs +++ b/necsim/core/src/cogs/speciation_probability.rs @@ -1,15 +1,13 @@ use necsim_core_bond::ClosedUnitF64; use crate::{ - cogs::{Habitat, MathsCore}, + cogs::{Backup, Habitat, MathsCore}, landscape::Location, }; #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait SpeciationProbability>: - crate::cogs::Backup + core::fmt::Debug -{ +pub trait SpeciationProbability>: Backup + core::fmt::Debug { #[must_use] #[debug_requires( habitat.is_location_habitable(location), diff --git a/necsim/core/src/cogs/turnover_rate.rs b/necsim/core/src/cogs/turnover_rate.rs index fce772b01..b06081c4d 100644 --- a/necsim/core/src/cogs/turnover_rate.rs +++ b/necsim/core/src/cogs/turnover_rate.rs @@ -1,15 +1,13 @@ use necsim_core_bond::NonNegativeF64; use crate::{ - cogs::{Habitat, MathsCore}, + cogs::{Backup, Habitat, MathsCore}, landscape::Location, }; #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait TurnoverRate>: - crate::cogs::Backup + core::fmt::Debug -{ +pub trait TurnoverRate>: Backup + core::fmt::Debug { #[must_use] #[debug_requires( habitat.is_location_habitable(location), diff --git a/necsim/core/src/simulation/builder.rs b/necsim/core/src/simulation/builder.rs index 4c8111f89..4be829b0d 100644 --- a/necsim/core/src/simulation/builder.rs +++ b/necsim/core/src/simulation/builder.rs @@ -287,4 +287,37 @@ impl< pub fn immigration_entry_mut(&mut self) -> &mut I { &mut self.immigration_entry } + + pub fn deconstruct(self) -> SimulationBuilder { + let Simulation { + maths, + habitat, + lineage_store, + dispersal_sampler, + coalescence_sampler, + turnover_rate, + speciation_probability, + emigration_exit, + event_sampler, + active_lineage_sampler, + rng, + immigration_entry, + migration_balance: _, + } = self; + + SimulationBuilder { + maths, + habitat, + lineage_store, + dispersal_sampler, + coalescence_sampler, + turnover_rate, + speciation_probability, + emigration_exit, + event_sampler, + active_lineage_sampler, + rng, + immigration_entry, + } + } } diff --git a/necsim/impls/cuda/src/cogs/rng.rs b/necsim/impls/cuda/src/cogs/rng.rs index 99d7df48a..7a8b17c8e 100644 --- a/necsim/impls/cuda/src/cogs/rng.rs +++ b/necsim/impls/cuda/src/cogs/rng.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use const_type_layout::TypeGraphLayout; use rust_cuda::safety::StackOnly; -use necsim_core::cogs::{MathsCore, Rng}; +use necsim_core::cogs::{Backup, MathsCore, Rng}; #[allow(clippy::module_name_repetitions)] #[derive(Debug, rust_cuda::common::LendRustToCuda)] @@ -16,15 +16,6 @@ where marker: PhantomData, } -impl + StackOnly + ~const TypeGraphLayout> Clone for CudaRng { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - marker: PhantomData::, - } - } -} - impl + StackOnly + ~const TypeGraphLayout> From for CudaRng { #[must_use] #[inline] @@ -37,11 +28,21 @@ impl + StackOnly + ~const TypeGraphLayout> From for C } impl + StackOnly + ~const TypeGraphLayout> CudaRng { - pub fn into(self) -> R { + pub fn into_inner(self) -> R { self.inner } } +#[contract_trait] +impl + StackOnly + ~const TypeGraphLayout> Backup for CudaRng { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: self.inner.backup_unchecked(), + marker: PhantomData::, + } + } +} + impl + StackOnly + ~const TypeGraphLayout> Rng for CudaRng { type Generator = R::Generator; type Sampler = R::Sampler; diff --git a/necsim/impls/cuda/src/lib.rs b/necsim/impls/cuda/src/lib.rs index 44c4c984d..95d9711d9 100644 --- a/necsim/impls/cuda/src/lib.rs +++ b/necsim/impls/cuda/src/lib.rs @@ -16,7 +16,7 @@ extern crate alloc; #[macro_use] extern crate const_type_layout; -#[cfg_attr(target_os = "cuda", macro_use)] +#[macro_use] extern crate contracts; pub mod cogs; diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 098ca2861..ac1d8c1b9 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1079,7 +1079,7 @@ fn debug_display_sampler() { } // GRCOV_EXCL_START -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, serde::Serialize, serde::Deserialize)] struct DummyRng(Vec); impl DummyRng { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 0505a4e83..169ab8870 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -578,7 +578,7 @@ fn debug_display_sampler() { } // GRCOV_EXCL_START -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, serde::Serialize, serde::Deserialize)] struct DummyRng(Vec); impl DummyRng { diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs b/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs index 94a751d8d..a61a2a877 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs @@ -20,16 +20,14 @@ use pre_sampler::OriginPreSampler; /// `Lineage`s produced by the sampler's iterator must have /// * unique global references pub trait UntrustedOriginSampler<'h, M: MathsCore>: - core::fmt::Debug + core::iter::Iterator + Sized + core::fmt::Debug + core::iter::Iterator { type Habitat: 'h + Habitat; type PreSampler: Iterator; fn habitat(&self) -> &'h Self::Habitat; - fn into_pre_sampler(self) -> OriginPreSampler - where - Self: Sized; + fn into_pre_sampler(self) -> OriginPreSampler; fn full_upper_bound_size_hint(&self) -> u64; } diff --git a/necsim/impls/no-std/src/cogs/rng/rand.rs b/necsim/impls/no-std/src/cogs/rng/rand.rs index bd09e7755..0c2a11d59 100644 --- a/necsim/impls/no-std/src/cogs/rng/rand.rs +++ b/necsim/impls/no-std/src/cogs/rng/rand.rs @@ -6,7 +6,7 @@ use rand_core::{RngCore as RandRngCore, SeedableRng as RandSeedableRng}; use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; #[allow(clippy::module_name_repetitions)] -#[derive(Clone, TypeLayout)] +#[derive(TypeLayout)] #[repr(transparent)] pub struct RandRng { inner: G, @@ -58,7 +58,9 @@ impl Ba for RandRng { unsafe fn backup_unchecked(&self) -> Self { - self.clone() + Self { + inner: self.inner.clone(), + } } } diff --git a/necsim/impls/no-std/src/cogs/rng/seahash.rs b/necsim/impls/no-std/src/cogs/rng/seahash.rs index ea316ce72..c2f670ad1 100644 --- a/necsim/impls/no-std/src/cogs/rng/seahash.rs +++ b/necsim/impls/no-std/src/cogs/rng/seahash.rs @@ -3,7 +3,7 @@ use necsim_core::cogs::{Backup, PrimeableRng, RngCore}; use serde::{Deserialize, Serialize}; #[allow(clippy::module_name_repetitions, clippy::unsafe_derive_deserialize)] -#[derive(Clone, Debug, Serialize, Deserialize, TypeLayout)] +#[derive(Debug, Serialize, Deserialize, TypeLayout)] #[serde(deny_unknown_fields)] pub struct SeaHash { seed: u64, @@ -15,7 +15,12 @@ pub struct SeaHash { #[contract_trait] impl Backup for SeaHash { unsafe fn backup_unchecked(&self) -> Self { - self.clone() + Self { + seed: self.seed, + location: self.location, + time: self.time, + offset: self.offset, + } } } diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index dc4dfec89..e6dcb57f9 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -13,7 +13,7 @@ use necsim_core::cogs::{ }; use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; -#[derive(Clone, Debug, TypeLayout)] +#[derive(Debug, TypeLayout)] #[allow(clippy::module_name_repetitions)] #[layout(free = "M")] #[repr(transparent)] @@ -32,7 +32,7 @@ impl From for SimpleRng { } impl SimpleRng { - pub fn into(self) -> R { + pub fn into_inner(self) -> R { self.inner } } diff --git a/necsim/impls/no-std/src/cogs/rng/wyhash.rs b/necsim/impls/no-std/src/cogs/rng/wyhash.rs index d1fa184fa..e3eb997fb 100644 --- a/necsim/impls/no-std/src/cogs/rng/wyhash.rs +++ b/necsim/impls/no-std/src/cogs/rng/wyhash.rs @@ -10,7 +10,7 @@ const P2: u64 = 0x8ebc_6af0_9c88_c6e3; const P5: u64 = 0xeb44_acca_b455_d165; #[allow(clippy::module_name_repetitions, clippy::unsafe_derive_deserialize)] -#[derive(Clone, Debug, Serialize, Deserialize, TypeLayout)] +#[derive(Debug, Serialize, Deserialize, TypeLayout)] #[serde(deny_unknown_fields)] #[repr(C)] pub struct WyHash { @@ -21,7 +21,10 @@ pub struct WyHash { #[contract_trait] impl Backup for WyHash { unsafe fn backup_unchecked(&self) -> Self { - self.clone() + Self { + seed: self.seed, + state: self.state, + } } } diff --git a/necsim/impls/no-std/src/decomposition/mod.rs b/necsim/impls/no-std/src/decomposition/mod.rs index 7791d99c5..a7ad6a889 100644 --- a/necsim/impls/no-std/src/decomposition/mod.rs +++ b/necsim/impls/no-std/src/decomposition/mod.rs @@ -11,7 +11,7 @@ pub mod radial; #[allow(clippy::inline_always, clippy::inline_fn_without_body)] #[contract_trait] -pub trait Decomposition>: Backup + Sized + core::fmt::Debug { +pub trait Decomposition>: Backup + core::fmt::Debug { fn get_subdomain(&self) -> Partition; #[debug_requires(habitat.is_location_habitable(location), "location is habitable")] diff --git a/necsim/impls/std/src/cogs/rng/pcg.rs b/necsim/impls/std/src/cogs/rng/pcg.rs index 81664a89f..42f053e83 100644 --- a/necsim/impls/std/src/cogs/rng/pcg.rs +++ b/necsim/impls/std/src/cogs/rng/pcg.rs @@ -2,25 +2,14 @@ use std::fmt; use pcg_rand::{seeds::PcgSeeder, PCGStateInfo, Pcg64}; use rand_core::{RngCore as _, SeedableRng}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use necsim_core::cogs::{RngCore, SplittableRng}; +use necsim_core::cogs::{Backup, RngCore, SplittableRng}; -#[allow(clippy::module_name_repetitions)] -#[derive(Serialize, Deserialize)] -#[serde(from = "PcgState", into = "PcgState")] pub struct Pcg { inner: Pcg64, } -impl Clone for Pcg { - fn clone(&self) -> Self { - Self { - inner: Pcg64::restore_state_with_no_verification(self.inner.get_state()), - } - } -} - impl fmt::Debug for Pcg { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let state = self.inner.get_state(); @@ -32,6 +21,52 @@ impl fmt::Debug for Pcg { } } +impl Serialize for Pcg { + fn serialize(&self, serializer: S) -> Result { + let state_info = self.inner.get_state(); + + let state = PcgState { + state: state_info.state, + increment: state_info.increment, + }; + + state.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for Pcg { + fn deserialize>(deserializer: D) -> Result { + use pcg_rand::{ + multiplier::{DefaultMultiplier, Multiplier}, + outputmix::{DXsMMixin, OutputMixin}, + }; + + let state = PcgState::deserialize(deserializer)?; + + let state_info = PCGStateInfo { + state: state.state, + increment: state.increment, + multiplier: DefaultMultiplier::multiplier(), + internal_width: u128::BITS as usize, + output_width: u64::BITS as usize, + output_mixin: >::SERIALIZER_ID.into(), + }; + + Ok(Self { + inner: Pcg64::restore_state_with_no_verification(state_info), + }) + } +} + +#[contract_trait] +impl Backup for Pcg { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: Pcg64::restore_state_with_no_verification(self.inner.get_state()), + } + } +} + impl RngCore for Pcg { type Seed = [u8; 16]; @@ -89,36 +124,3 @@ struct PcgState { state: u128, increment: u128, } - -impl From for PcgState { - fn from(rng: Pcg) -> Self { - let state_info = rng.inner.get_state(); - - Self { - state: state_info.state, - increment: state_info.increment, - } - } -} - -impl From for Pcg { - fn from(state: PcgState) -> Self { - use pcg_rand::{ - multiplier::{DefaultMultiplier, Multiplier}, - outputmix::{DXsMMixin, OutputMixin}, - }; - - let state_info = PCGStateInfo { - state: state.state, - increment: state.increment, - multiplier: DefaultMultiplier::multiplier(), - internal_width: u128::BITS as usize, - output_width: u64::BITS as usize, - output_mixin: >::SERIALIZER_ID.into(), - }; - - Self { - inner: Pcg64::restore_state_with_no_verification(state_info), - } - } -} diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index b8bf930cc..352754b45 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -238,7 +238,7 @@ where .into_iter() .chain(passthrough.into_iter()) .collect(), - rng: simulation.rng_mut().clone().into().into(), + rng: simulation.deconstruct().rng.into_inner().into_inner(), }), } } diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index ea9803bc8..207e1d979 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -127,7 +127,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone().into(), + rng: simulation.deconstruct().rng.into_inner(), }), } }, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 8156b0203..0fe808f96 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -121,7 +121,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone().into(), + rng: simulation.deconstruct().rng.into_inner(), }), } }, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index ffd8fefa8..e44ad62c9 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -121,7 +121,7 @@ where ) .cloned() .collect(), - rng: simulation.rng_mut().clone().into(), + rng: simulation.deconstruct().rng.into_inner(), }), } }, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index 4ff08b8e5..4b6da3948 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -159,7 +159,7 @@ pub fn initialise_and_simulate< .into_iter() .chain(passthrough.into_iter()) .collect(), - rng: simulation.rng_mut().clone().into(), + rng: simulation.deconstruct().rng.into_inner(), }), } }, diff --git a/rustcoalescence/algorithms/src/lib.rs b/rustcoalescence/algorithms/src/lib.rs index 3298b4958..b56749b60 100644 --- a/rustcoalescence/algorithms/src/lib.rs +++ b/rustcoalescence/algorithms/src/lib.rs @@ -35,7 +35,7 @@ pub trait Algorithm< O: Scenario, R: Reporter, P: LocalPartition<'p, R>, ->: Sized + AlgorithmParamters + AlgorithmDefaults +>: AlgorithmParamters + AlgorithmDefaults { type Rng: Rng; type LineageStore: LineageStore; From fdab4c983e9aeda2a3968c7bbcd8dfb3c902eb25 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Sat, 21 May 2022 14:32:30 +0000 Subject: [PATCH 15/21] Implemented the RandRng sampler based on rand_distr --- Cargo.lock | 12 + necsim/impls/no-std/Cargo.toml | 1 + necsim/impls/no-std/src/cogs/rng/rand.rs | 445 ++++++++++++++++++++- necsim/impls/no-std/src/cogs/rng/simple.rs | 235 ++--------- 4 files changed, 477 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 981674d3b..337889ed9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1052,6 +1052,7 @@ dependencies = [ "necsim-core-maths", "necsim-partitioning-core", "rand_core", + "rand_distr", "rust-cuda", "serde", "slab", @@ -1226,6 +1227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1398,6 +1400,16 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand", +] + [[package]] name = "regex" version = "1.10.2" diff --git a/necsim/impls/no-std/Cargo.toml b/necsim/impls/no-std/Cargo.toml index d6ae51e71..19628f69b 100644 --- a/necsim/impls/no-std/Cargo.toml +++ b/necsim/impls/no-std/Cargo.toml @@ -28,6 +28,7 @@ displaydoc = { version = "0.2", default-features = false, features = [] } final = "0.1.1" fnv = { version = "1.0", default-features = false, features = [] } rand_core = "0.6" +rand_distr = { version = "0.4", default-features = false, features = [] } [target.'cfg(target_os = "cuda")'.dependencies] rust-cuda = { git = "https://github.com/juntyr/rust-cuda", rev = "5d5cd02", features = ["derive"], optional = true } diff --git a/necsim/impls/no-std/src/cogs/rng/rand.rs b/necsim/impls/no-std/src/cogs/rng/rand.rs index 0c2a11d59..c5a698844 100644 --- a/necsim/impls/no-std/src/cogs/rng/rand.rs +++ b/necsim/impls/no-std/src/cogs/rng/rand.rs @@ -1,26 +1,44 @@ -use core::fmt; +use core::{ + fmt, + marker::PhantomData, + num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, +}; -use necsim_core::cogs::{Backup, RngCore}; +use necsim_core::cogs::{ + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, + Normal2D, Poisson, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, + }, + Backup, DistributionSampler, MathsCore, Rng, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; -use rand_core::{RngCore as RandRngCore, SeedableRng as RandSeedableRng}; +use rand_core::{Error, RngCore as RandRngCore, SeedableRng as RandSeedableRng}; +use rand_distr::{ + uniform::{UniformInt, UniformSampler}, + Bernoulli as RandBernoulli, Distribution as RandDistribution, Exp1 as RandExp1, + OpenClosed01 as RandOpenClosed01, Poisson as RandPoisson, Standard as RandStandard, + StandardNormal as RandStandardNormal, +}; use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; #[allow(clippy::module_name_repetitions)] #[derive(TypeLayout)] #[repr(transparent)] -pub struct RandRng { +pub struct RandAsRng { inner: G, } impl From - for RandRng + for RandAsRng { + #[inline] fn from(inner: G) -> Self { Self { inner } } } -impl RandRng { +impl RandAsRng { #[must_use] pub fn into_inner(self) -> G { self.inner @@ -28,7 +46,7 @@ impl Ra } impl fmt::Debug - for RandRng + for RandAsRng { default fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct InnerRng(&'static str); @@ -39,23 +57,23 @@ impl fm } } - fmt.debug_tuple("RandRng") + fmt.debug_tuple("RandAsRng") .field(&InnerRng(core::any::type_name::())) .finish() } } impl - fmt::Debug for RandRng + fmt::Debug for RandAsRng { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_tuple("RandRng").field(&self.inner).finish() + fmt.debug_tuple("RandAsRng").field(&self.inner).finish() } } #[contract_trait] impl Backup - for RandRng + for RandAsRng { unsafe fn backup_unchecked(&self) -> Self { Self { @@ -65,7 +83,7 @@ impl Ba } impl Serialize - for RandRng + for RandAsRng { fn serialize(&self, serializer: S) -> Result { self.inner.serialize(serializer) @@ -73,7 +91,7 @@ impl Se } impl<'de, G: RandRngCore + RandSeedableRng + Clone + Serialize + DeserializeOwned> Deserialize<'de> - for RandRng + for RandAsRng { fn deserialize>(deserializer: D) -> Result { let inner = G::deserialize(deserializer)?; @@ -83,7 +101,7 @@ impl<'de, G: RandRngCore + RandSeedableRng + Clone + Serialize + DeserializeOwne } impl RngCore - for RandRng + for RandAsRng { type Seed = G::Seed; @@ -101,3 +119,402 @@ impl Rn self.inner.next_u64() } } + +#[allow(clippy::module_name_repetitions)] +#[derive(TypeLayout)] +#[repr(transparent)] +pub struct RngAsRand { + inner: G, +} + +impl From for RngAsRand { + #[inline] + fn from(inner: G) -> Self { + Self { inner } + } +} + +impl RngAsRand { + #[must_use] + pub fn into_inner(self) -> G { + self.inner + } +} + +impl fmt::Debug for RngAsRand { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_tuple("RngAsRand").field(&self.inner).finish() + } +} + +#[contract_trait] +impl Backup for RngAsRand { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: self.inner.backup_unchecked(), + } + } +} + +impl Serialize for RngAsRand { + fn serialize(&self, serializer: S) -> Result { + self.inner.serialize(serializer) + } +} + +impl<'de, G: RngCore> Deserialize<'de> for RngAsRand { + fn deserialize>(deserializer: D) -> Result { + let inner = G::deserialize(deserializer)?; + + Ok(Self { inner }) + } +} + +impl RngCore for RngAsRand { + type Seed = G::Seed; + + #[must_use] + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + Self { + inner: G::from_seed(seed), + } + } + + #[must_use] + #[inline] + fn sample_u64(&mut self) -> u64 { + self.inner.sample_u64() + } +} + +impl RandSeedableRng for RngAsRand { + type Seed = G::Seed; + + #[inline] + fn from_seed(seed: Self::Seed) -> Self { + Self { + inner: G::from_seed(seed), + } + } +} + +impl RandRngCore for RngAsRand { + #[inline] + default fn next_u32(&mut self) -> u32 { + // Note: The most significant bits are often a bit more random + (self.sample_u64() >> 32) as u32 + } + + #[inline] + default fn next_u64(&mut self) -> u64 { + self.sample_u64() + } + + #[inline] + default fn fill_bytes(&mut self, dest: &mut [u8]) { + rand_core::impls::fill_bytes_via_next(self, dest); + } + + #[inline] + #[allow(clippy::unit_arg)] + default fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + Ok(self.fill_bytes(dest)) + } +} + +impl RandRngCore for RngAsRand { + #[inline] + fn next_u32(&mut self) -> u32 { + self.inner.next_u32() + } + + #[inline] + fn next_u64(&mut self) -> u64 { + self.inner.next_u64() + } + + #[inline] + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.inner.fill_bytes(dest); + } + + #[inline] + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.inner.try_fill_bytes(dest) + } +} + +#[derive(Debug, TypeLayout)] +#[allow(clippy::module_name_repetitions)] +#[repr(transparent)] +pub struct RandRng { + inner: R, + marker: PhantomData, +} + +impl From for RandRng { + fn from(inner: R) -> Self { + Self { + inner, + marker: PhantomData::, + } + } +} + +impl RandRng { + pub fn into_inner(self) -> R { + self.inner + } +} + +#[contract_trait] +impl Backup for RandRng { + unsafe fn backup_unchecked(&self) -> Self { + Self { + inner: self.inner.backup_unchecked(), + marker: PhantomData::, + } + } +} + +impl Rng for RandRng { + type Generator = R; + type Sampler = RandDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + &mut self.inner + } + + fn map_generator Self::Generator>(self, map: F) -> Self { + let RandRng { inner, marker } = self; + + RandRng { + inner: map(inner), + marker, + } + } + + fn with Q, Q>(&mut self, inner: F) -> Q { + let samplers = RandDistributionSamplers { + _marker: PhantomData::<(M, R)>, + }; + + inner(&mut self.inner, &samplers) + } +} + +#[allow(clippy::module_name_repetitions)] +pub struct RandDistributionSamplers { + _marker: PhantomData<(M, R)>, +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + let u01: f64 = RandStandard.sample(rng); + + // Safety: Standard samples from [0, 1) + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + let u01: f64 = RandOpenClosed01.sample(rng); + + // Safety: OpenClosed01 samples from (0, 1] + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> usize { + UniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u32 { + UniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u64 { + UniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u128 { + UniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Lambda(lambda): Lambda, + ) -> NonNegativeF64 { + let exp1: f64 = RandExp1.sample(rng); + + // Safety: Exp1 samples from [0, +inf) + (unsafe { NonNegativeF64::new_unchecked(exp1) }) / lambda + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, Lambda(lambda): Lambda) -> u64 { + // Safety: PositiveF64 asserts that lambda > 0 + let poisson = unsafe { RandPoisson::new(lambda.get()).unwrap_unchecked() }; + + #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] + { + poisson.sample(rng) as u64 + } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { + // Safety: ClosedUnitF64 asserts that probability is in [0.0, 1.0] + let bernoulli = unsafe { RandBernoulli::new(probability.get()).unwrap_unchecked() }; + + bernoulli.sample(rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> (f64, f64) { + ( + RandStandardNormal.sample(rng), + RandStandardNormal.sample(rng), + ) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Normal { mu, sigma }: Normal, + ) -> (f64, f64) { + let (z0, z1): (f64, f64) = ( + RandStandardNormal.sample(rng), + RandStandardNormal.sample(rng), + ); + + (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + } +} diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index e6dcb57f9..0d0d609e3 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -128,10 +128,8 @@ impl, + Length(length): Length, ) -> usize { - let length = params.0; - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( @@ -155,9 +153,12 @@ impl) -> u32 { - let length = params.0; - + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u32 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] @@ -177,9 +178,12 @@ impl) -> u64 { - let length = params.0; - + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u64 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( @@ -203,9 +207,12 @@ impl) -> u128 { - let length = params.0; - + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u128 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); #[allow( @@ -229,9 +236,12 @@ impl NonNegativeF64 { - let lambda = params.0; - + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Lambda(lambda): Lambda, + ) -> NonNegativeF64 { let u01 = UniformOpenClosedUnit::sample_raw(rng, samplers); // Inverse transform sample: X = -ln(U(0,1]) / lambda @@ -252,8 +262,7 @@ impl< self } - fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Lambda) -> u64 { - let lambda = params.0; + fn sample_distribution(&self, rng: &mut R, samplers: &S, Lambda(lambda): Lambda) -> u64 { let no_event_probability = M::exp(-lambda.get()); if no_event_probability <= 0.0_f64 { @@ -300,9 +309,7 @@ impl bool { - let probability = params; - + fn sample_distribution(&self, rng: &mut R, samplers: &S, probability: ClosedUnitF64) -> bool { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); // if probability == 1, then U[0, 1) always < 1.0 @@ -345,190 +352,14 @@ impl self } - fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Normal { mu, sigma }: Normal, + ) -> (f64, f64) { let (z0, z1) = StandardNormal2D::sample_raw(rng, samplers); - ( - z0 * params.sigma.get() + params.mu, - z1 * params.sigma.get() + params.mu, - ) - } -} - -/*#[allow(clippy::inline_always, clippy::inline_fn_without_body)] -#[allow(clippy::module_name_repetitions)] -#[contract_trait] -pub trait RngSampler: RngCore { - #[must_use] - #[inline] - /// Samples a uniform sample within `[0.0, 1.0)`, i.e. `0.0 <= X < 1.0` - fn sample_uniform_closed_open(&mut self) -> ClosedOpenUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = ((self.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { ClosedOpenUnitF64::new_unchecked(u01) } - } - - #[must_use] - #[inline] - /// Samples a uniform sample within `(0.0, 1.0]`, i.e. `0.0 < X <= 1.0` - fn sample_uniform_open_closed(&mut self) -> OpenClosedUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = - (((self.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { OpenClosedUnitF64::new_unchecked(u01) } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index(&mut self, length: NonZeroUsize) -> usize { - #[cfg(target_pointer_width = "32")] - #[allow(clippy::cast_possible_truncation)] - { - self.sample_index_u32(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }) - as usize - } - #[cfg(target_pointer_width = "64")] - #[allow(clippy::cast_possible_truncation)] - { - self.sample_index_u64(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }) - as usize - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u32(&mut self, length: NonZeroU32) -> u32 { - // TODO: Check if delegation to `sample_index_u64` is faster - - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - const LOWER_MASK: u64 = !0 >> 32; - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw = self.sample_u64(); - - let sample_check_lo = (raw & LOWER_MASK) * u64::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check_lo as u32) <= acceptance_zone { - return (sample_check_lo >> 32) as u32; - } - - let sample_check_hi = (raw >> 32) * u64::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check_hi as u32) <= acceptance_zone { - return (sample_check_hi >> 32) as u32; - } - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u64(&mut self, length: NonZeroU64) -> u64 { - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw = self.sample_u64(); - - let sample_check = u128::from(raw) * u128::from(length.get()); - - #[allow(clippy::cast_possible_truncation)] - if (sample_check as u64) <= acceptance_zone { - return (sample_check >> 64) as u64; - } - } - } - - #[must_use] - #[inline] - #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] - fn sample_index_u128(&mut self, length: NonZeroU128) -> u128 { - // Adapted from: - // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single - - const LOWER_MASK: u128 = !0 >> 64; - - // Conservative approximation of the acceptance zone - let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); - - loop { - let raw_hi = u128::from(self.sample_u64()); - let raw_lo = u128::from(self.sample_u64()); - - // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length - let mut low = raw_lo * (length.get() & LOWER_MASK); - let mut t = low >> 64; - low &= LOWER_MASK; - t += raw_hi * (length.get() & LOWER_MASK); - low += (t & LOWER_MASK) << 64; - let mut high = t >> 64; - t = low >> 64; - low &= LOWER_MASK; - t += (length.get() >> 64) * raw_lo; - low += (t & LOWER_MASK) << 64; - high += t >> 64; - high += raw_hi * (length.get() >> 64); - - let sample = high; - let check = low; - - if check <= acceptance_zone { - return sample; - } - } - } - - #[must_use] - #[inline] - fn sample_exponential(&mut self, lambda: PositiveF64) -> NonNegativeF64 { - // Inverse transform sample: X = -ln(U(0,1]) / lambda - -self.sample_uniform_open_closed().ln::() / lambda - } - - #[must_use] - #[inline] - fn sample_event(&mut self, probability: ClosedUnitF64) -> bool { - // if probability == 1, then U[0, 1) always < 1.0 - // if probability == 0, then U[0, 1) never < 0.0 - self.sample_uniform_closed_open() < probability - } - - #[must_use] - #[inline] - fn sample_2d_standard_normal(&mut self) -> (f64, f64) { - // Basic Box-Muller transform - let u0 = self.sample_uniform_open_closed(); - let u1 = self.sample_uniform_closed_open(); - - let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); - let theta = -core::f64::consts::TAU * u1.get(); - - (r * M::sin(theta), r * M::cos(theta)) - } - - #[must_use] - #[inline] - fn sample_2d_normal(&mut self, mu: f64, sigma: NonNegativeF64) -> (f64, f64) { - let (z0, z1) = self.sample_2d_standard_normal(); - (z0 * sigma.get() + mu, z1 * sigma.get() + mu) } } - -impl> RngSampler for R {}*/ From 20e300d62ee9629bb12cf81bd3872945e8dc1819 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Sat, 21 May 2022 22:08:34 +0000 Subject: [PATCH 16/21] Small optimisations of rng usage --- necsim/core/src/cogs/coalescence_sampler.rs | 38 ++++---- .../alias/sampler/indexed/tests.rs | 66 +++++++------- .../alias/sampler/stack/tests.rs | 66 +++++++------- .../active_lineage_sampler/classical/mod.rs | 20 +---- .../classical/sampler.rs | 8 +- .../independent/event_time_sampler/exp.rs | 2 +- .../independent/event_time_sampler/fixed.rs | 4 +- .../event_time_sampler/geometric.rs | 4 +- .../independent/event_time_sampler/poisson.rs | 4 +- .../cogs/coalescence_sampler/conditional.rs | 8 +- .../cogs/coalescence_sampler/independent.rs | 8 +- .../optional_coalescence.rs | 10 ++- .../almost_infinite_normal.rs | 5 +- .../cogs/dispersal_sampler/wrapping_noise.rs | 2 +- .../event_sampler/gillespie/unconditional.rs | 20 ++--- .../src/cogs/event_sampler/unconditional.rs | 18 ++-- .../src/cogs/habitat/wrapping_noise/mod.rs | 2 +- necsim/impls/no-std/src/cogs/rng/rand.rs | 1 + necsim/impls/no-std/src/cogs/rng/simple.rs | 87 +++++++++++-------- .../no-std/src/decomposition/equal/mod.rs | 15 ++-- .../impls/no-std/src/decomposition/radial.rs | 12 ++- necsim/impls/no-std/src/lib.rs | 1 + .../parallelisation/independent/landscape.rs | 17 ++-- .../src/parallelisation/independent/mod.rs | 2 + .../gillespie/classical/initialiser/fixup.rs | 8 +- .../classical/initialiser/genesis.rs | 8 +- .../gillespie/classical/initialiser/mod.rs | 4 +- .../gillespie/classical/initialiser/resume.rs | 8 +- 28 files changed, 230 insertions(+), 218 deletions(-) diff --git a/necsim/core/src/cogs/coalescence_sampler.rs b/necsim/core/src/cogs/coalescence_sampler.rs index eae990435..4095e1313 100644 --- a/necsim/core/src/cogs/coalescence_sampler.rs +++ b/necsim/core/src/cogs/coalescence_sampler.rs @@ -1,14 +1,12 @@ -use core::cmp::{Ord, Ordering}; - -use necsim_core_bond::ClosedOpenUnitF64; +use core::{ + cmp::{Ord, Ordering}, + num::NonZeroU32, +}; use serde::{Deserialize, Serialize}; use crate::{ - cogs::{ - distribution::UniformClosedOpenUnit, Backup, Distribution, Habitat, LineageStore, - MathsCore, Rng, Samples, - }, + cogs::{Backup, Habitat, LineageStore, MathsCore, Rng, RngCore}, landscape::{IndexedLocation, Location}, lineage::LineageInteraction, }; @@ -32,7 +30,7 @@ pub trait CoalescenceSampler, S: LineageStore> #[allow(clippy::unsafe_derive_deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize, TypeLayout)] #[repr(transparent)] -pub struct CoalescenceRngSample(ClosedOpenUnitF64); +pub struct CoalescenceRngSample(u64); #[contract_trait] impl Backup for CoalescenceRngSample { @@ -58,22 +56,20 @@ impl Eq for CoalescenceRngSample {} impl CoalescenceRngSample { #[must_use] #[inline] - pub fn new + Samples>(rng: &mut G) -> Self { - Self(UniformClosedOpenUnit::sample(rng)) + pub fn new>(rng: &mut G) -> Self { + Self(rng.generator().sample_u64()) } #[must_use] #[inline] - #[debug_ensures(ret < length, "samples U(0, length - 1)")] - pub fn sample_coalescence_index(self, length: u32) -> u32 { - // attributes on expressions are experimental - // see https://github.com/rust-lang/rust/issues/15701 - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(self.0.get() * f64::from(length)) as u32; - index + #[debug_ensures(ret < length.get(), "samples U(0, length - 1)")] + pub fn sample_coalescence_index(self, length: NonZeroU32) -> u32 { + // Sample U(0, length - 1) using a widening multiplication + // Note: Some slight bias is traded for only needing one u64 sample + // Note: Should optimise to a single 64 bit (high-only) multiplication + #[allow(clippy::cast_possible_truncation)] + { + (((u128::from(self.0) * u128::from(length.get())) >> 64) & u128::from(!0_u32)) as u32 + } } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index ac1d8c1b9..4a95671e1 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1145,19 +1145,25 @@ impl DistributionSampler, + Length(length): Length, ) -> usize { - let length = params.0; - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as usize; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + let u01 = rng.sample_f64(); + + // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] + // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; + + if cfg!(target_pointer_width = "32") { + // Note: [0, 2^32) is losslessly represented in f64 + index + } else { + // Note: Ensure index < length despite + // usize->f64->usize precision loss + index.min(length.get() - 1) + } } } @@ -1174,18 +1180,18 @@ impl DistributionSampler, + Length(length): Length, ) -> u64 { - let length = params.0; + let u01 = rng.sample_f64(); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u64; + // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 + // since (1 - 2^-53) * 2^64 <= (2^64 - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u64->f64->u64 precision loss index.min(length.get() - 1) } } @@ -1203,18 +1209,18 @@ impl DistributionSampler, + Length(length): Length, ) -> u128 { - let length = params.0; + let u01 = rng.sample_f64(); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u128; + // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 + // since (1 - 2^-53) * 2^128 <= (2^128 - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u128->f64->u128 precision loss index.min(length.get() - 1) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index 169ab8870..aa0258506 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -644,19 +644,25 @@ impl DistributionSampler, + Length(length): Length, ) -> usize { - let length = params.0; - - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as usize; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + let u01 = rng.sample_f64(); + + // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] + // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; + + if cfg!(target_pointer_width = "32") { + // Note: [0, 2^32) is losslessly represented in f64 + index + } else { + // Note: Ensure index < length despite + // usize->f64->usize precision loss + index.min(length.get() - 1) + } } } @@ -673,18 +679,18 @@ impl DistributionSampler, + Length(length): Length, ) -> u64 { - let length = params.0; + let u01 = rng.sample_f64(); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u64; + // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 + // since (1 - 2^-53) * 2^64 <= (2^64 - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u64->f64->u64 precision loss index.min(length.get() - 1) } } @@ -702,18 +708,18 @@ impl DistributionSampler, + Length(length): Length, ) -> u128 { - let length = params.0; + let u01 = rng.sample_f64(); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = IntrinsicsMathsCore::floor(rng.sample_f64() * (length.get() as f64)) as u128; + // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 + // since (1 - 2^-53) * 2^128 <= (2^128 - 1) + #[allow(clippy::cast_precision_loss)] + let index = unsafe { + IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() + }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u128->f64->u128 precision loss index.min(length.get() - 1) } } diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index e207e7c11..a70d0b65e 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use core::marker::PhantomData; use necsim_core::cogs::{ - distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize}, Backup, DispersalSampler, EmigrationExit, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, }; @@ -20,11 +20,7 @@ mod sampler; pub struct ClassicalActiveLineageSampler< M: MathsCore, H: Habitat, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -40,11 +36,7 @@ pub struct ClassicalActiveLineageSampler< impl< M: MathsCore, H: Habitat, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -135,11 +127,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 60a2c9a29..2caa6dbea 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -5,7 +5,7 @@ use core::{ use necsim_core::{ cogs::{ - distribution::{Bernoulli, Exponential, IndexUsize, Lambda, Length, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize, Lambda, Length}, ActiveLineageSampler, DispersalSampler, Distribution, EmigrationExit, Habitat, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, @@ -27,11 +27,7 @@ use super::ClassicalActiveLineageSampler; impl< M: MathsCore, H: Habitat, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs index d9b38f040..ef89f407e 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/exp.rs @@ -56,13 +56,13 @@ impl< ) }; + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let mut time_step = M::floor(time.get() / self.delta_t.get()) as u64; let mut event_time = NonNegativeF64::from(time_step) * self.delta_t; let mut time_slice_end = NonNegativeF64::from(time_step + 1) * self.delta_t; - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] rng.generator() .prime_with_habitat(habitat, indexed_location, time_step); diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs index 08844e755..1b964412e 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/fixed.rs @@ -27,8 +27,8 @@ impl, G: Rng, T: Turnove let lambda = turnover_rate.get_turnover_rate_at_location(indexed_location.location(), habitat); - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let time_step = M::floor(time.get() * lambda.get()) as u64 + 1; rng.generator() diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs index 2a8355407..270a48016 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/geometric.rs @@ -46,8 +46,8 @@ impl< .neg_exp::() .one_minus(); - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let mut time_step = M::floor(time.get() / self.delta_t.get()) as u64 + 1; loop { diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index 457c72b52..22388e81b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -50,8 +50,8 @@ impl< // location let lambda_per_step = unsafe { PositiveF64::new_unchecked(lambda.get()) } * self.delta_t; - #[allow(clippy::cast_possible_truncation)] - #[allow(clippy::cast_sign_loss)] + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let mut time_step = M::floor(time.get() / self.delta_t.get()) as u64; let (event_time, event_index) = loop { diff --git a/necsim/impls/no-std/src/cogs/coalescence_sampler/conditional.rs b/necsim/impls/no-std/src/cogs/coalescence_sampler/conditional.rs index e1109422a..493f48c15 100644 --- a/necsim/impls/no-std/src/cogs/coalescence_sampler/conditional.rs +++ b/necsim/impls/no-std/src/cogs/coalescence_sampler/conditional.rs @@ -1,4 +1,4 @@ -use core::marker::PhantomData; +use core::{marker::PhantomData, num::NonZeroU32}; use necsim_core::{ cogs::{ @@ -73,11 +73,11 @@ impl, S: GloballyCoherentLineageStore> let lineages_at_location = lineage_store.get_local_lineage_references_at_location_unordered(&location, habitat); + // Safety: individuals can only occupy habitable locations #[allow(clippy::cast_possible_truncation)] - let population = lineages_at_location.len() as u32; + let population = unsafe { NonZeroU32::new_unchecked(lineages_at_location.len() as u32) }; - let chosen_coalescence_index = - coalescence_rng_sample.sample_coalescence_index::(population); + let chosen_coalescence_index = coalescence_rng_sample.sample_coalescence_index(population); let chosen_coalescence = &lineages_at_location[chosen_coalescence_index as usize]; let lineage = &lineage_store[chosen_coalescence]; diff --git a/necsim/impls/no-std/src/cogs/coalescence_sampler/independent.rs b/necsim/impls/no-std/src/cogs/coalescence_sampler/independent.rs index 0e9a16f6a..f387ab9a2 100644 --- a/necsim/impls/no-std/src/cogs/coalescence_sampler/independent.rs +++ b/necsim/impls/no-std/src/cogs/coalescence_sampler/independent.rs @@ -1,4 +1,4 @@ -use core::marker::PhantomData; +use core::{marker::PhantomData, num::NonZeroU32}; use necsim_core::{ cogs::{ @@ -45,10 +45,12 @@ impl> CoalescenceSampler, coalescence_rng_sample: CoalescenceRngSample, ) -> (IndexedLocation, LineageInteraction) { - let population = habitat.get_habitat_at_location(&location); + // Safety: individuals can only occupy habitable locations + let habitat_at_location = + unsafe { NonZeroU32::new_unchecked(habitat.get_habitat_at_location(&location)) }; let chosen_coalescence_index = - coalescence_rng_sample.sample_coalescence_index::(population); + coalescence_rng_sample.sample_coalescence_index(habitat_at_location); let indexed_location = IndexedLocation::new(location, chosen_coalescence_index); diff --git a/necsim/impls/no-std/src/cogs/coalescence_sampler/optional_coalescence.rs b/necsim/impls/no-std/src/cogs/coalescence_sampler/optional_coalescence.rs index 94d8190cf..247a13244 100644 --- a/necsim/impls/no-std/src/cogs/coalescence_sampler/optional_coalescence.rs +++ b/necsim/impls/no-std/src/cogs/coalescence_sampler/optional_coalescence.rs @@ -1,3 +1,5 @@ +use core::num::NonZeroU32; + use necsim_core::{ cogs::{ coalescence_sampler::CoalescenceRngSample, Habitat, LocallyCoherentLineageStore, MathsCore, @@ -17,8 +19,12 @@ pub fn sample_interaction_at_location< lineage_store: &S, coalescence_rng_sample: CoalescenceRngSample, ) -> (IndexedLocation, LineageInteraction) { - let chosen_coalescence_index = coalescence_rng_sample - .sample_coalescence_index::(habitat.get_habitat_at_location(&location)); + // Safety: individuals can only occupy habitable locations + let habitat_at_location = + unsafe { NonZeroU32::new_unchecked(habitat.get_habitat_at_location(&location)) }; + + let chosen_coalescence_index = + coalescence_rng_sample.sample_coalescence_index(habitat_at_location); let indexed_location = IndexedLocation::new(location, chosen_coalescence_index); diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs index 8df4339f3..54d0dea04 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/almost_infinite_normal.rs @@ -78,8 +78,9 @@ impl + Samples> ); // Discrete dispersal assumes lineage positions are centred on (0.5, 0.5), - // i.e. |dispersal| >= 0.5 changes the cell - // (dx and dy must be rounded to nearest int away from 0.0) + // i.e. |dispersal| >= 0.5 changes the cell + // dx and dy must be rounded to nearest int away from 0.0 + // Note: rust clamps f64 as i64 to [-2^-63, 2^63 - 1] #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let (dx, dy): (i64, i64) = (M::round(dx) as i64, M::round(dy) as i64); diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs index e34611409..09e86bd3a 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs @@ -2,7 +2,7 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Normal2D}, Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - SampledDistribution, SeparableDispersalSampler, + Distribution, SeparableDispersalSampler, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs index ac7342ce6..f1d9464ef 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/gillespie/unconditional.rs @@ -2,12 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, - distribution::{Bernoulli, UniformClosedOpenUnit}, - event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, EventSampler, - GloballyCoherentLineageStore, Habitat, MathsCore, Rng, Samples, SpeciationProbability, - TurnoverRate, + coalescence_sampler::CoalescenceRngSample, distribution::Bernoulli, + event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, Distribution, + EmigrationExit, EventSampler, GloballyCoherentLineageStore, Habitat, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, landscape::Location, @@ -23,7 +21,7 @@ use super::GillespieEventSampler; pub struct UnconditionalGillespieEventSampler< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -38,7 +36,7 @@ pub struct UnconditionalGillespieEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -58,7 +56,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -78,7 +76,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -186,7 +184,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: GloballyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs index e8ae14594..07d37bfb6 100644 --- a/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs +++ b/necsim/impls/no-std/src/cogs/event_sampler/unconditional.rs @@ -2,12 +2,10 @@ use core::marker::PhantomData; use necsim_core::{ cogs::{ - coalescence_sampler::CoalescenceRngSample, - distribution::{Bernoulli, UniformClosedOpenUnit}, - event_sampler::EventHandler, - Backup, CoalescenceSampler, DispersalSampler, Distribution, EmigrationExit, EventSampler, - Habitat, LocallyCoherentLineageStore, MathsCore, Rng, Samples, SpeciationProbability, - TurnoverRate, + coalescence_sampler::CoalescenceRngSample, distribution::Bernoulli, + event_sampler::EventHandler, Backup, CoalescenceSampler, DispersalSampler, Distribution, + EmigrationExit, EventSampler, Habitat, LocallyCoherentLineageStore, MathsCore, Rng, + Samples, SpeciationProbability, TurnoverRate, }, event::{DispersalEvent, SpeciationEvent}, lineage::Lineage, @@ -20,7 +18,7 @@ use necsim_core_bond::PositiveF64; pub struct UnconditionalEventSampler< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -35,7 +33,7 @@ pub struct UnconditionalEventSampler< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -55,7 +53,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, @@ -75,7 +73,7 @@ impl< impl< M: MathsCore, H: Habitat, - G: Rng + Samples + Samples, + G: Rng + Samples, S: LocallyCoherentLineageStore, X: EmigrationExit, D: DispersalSampler, diff --git a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs index a3765b19f..eac3ce204 100644 --- a/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs +++ b/necsim/impls/no-std/src/cogs/habitat/wrapping_noise/mod.rs @@ -196,7 +196,7 @@ impl> UniformlySampleableHabitat for WrappingNoise fn sample_habitable_indexed_location(&self, rng: &mut G) -> IndexedLocation { // Rejection sample until a habitable location is found let location = loop { - let index = rng.sample_u64(); + let index = rng.generator().sample_u64(); let location = Location::new( (index & 0xFFFF_FFFF) as u32, diff --git a/necsim/impls/no-std/src/cogs/rng/rand.rs b/necsim/impls/no-std/src/cogs/rng/rand.rs index c5a698844..bf234c255 100644 --- a/necsim/impls/no-std/src/cogs/rng/rand.rs +++ b/necsim/impls/no-std/src/cogs/rng/rand.rs @@ -454,6 +454,7 @@ impl DistributionSampler 0 let poisson = unsafe { RandPoisson::new(lambda.get()).unwrap_unchecked() }; + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] { poisson.sample(rng) as u64 diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index 0d0d609e3..521d3ac01 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -124,6 +124,7 @@ impl usize { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as usize; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] + // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; + + if cfg!(target_pointer_width = "32") { + // Note: [0, 2^32) is losslessly represented in f64 + index + } else { + // Note: Ensure index < length despite + // usize->f64->usize precision loss + index.min(length.get() - 1) + } } } @@ -161,11 +167,9 @@ impl u32 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let index = M::floor(u01.get() * f64::from(length.get())) as u32; - - // Safety in case of f64 rounding errors - index.min(length.get() - 1) + // Safety: U[0, 1) * length in [0, 2^32) is losslessly represented + // in both f64 and u32 + unsafe { M::floor(u01.get() * f64::from(length.get())).to_int_unchecked::() } } } @@ -186,14 +190,13 @@ impl u64 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as u64; + // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 + // since (1 - 2^-53) * 2^64 <= (2^64 - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u64->f64->u64 precision loss index.min(length.get() - 1) } } @@ -215,14 +218,13 @@ impl u128 { let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - #[allow( - clippy::cast_precision_loss, - clippy::cast_possible_truncation, - clippy::cast_sign_loss - )] - let index = M::floor(u01.get() * (length.get() as f64)) as u128; + // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 + // since (1 - 2^-53) * 2^128 <= (2^128 - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; - // Safety in case of f64 rounding errors + // Note: Ensure index < length despite u128->f64->u128 precision loss index.min(length.get() - 1) } } @@ -267,6 +269,7 @@ impl< if no_event_probability <= 0.0_f64 { // Fallback in case no_event_probability_per_step underflows + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] let normal_as_poisson = Normal2D::sample_raw_with( rng, @@ -276,8 +279,7 @@ impl< sigma: NonNegativeF64::from(lambda).sqrt::(), }, ) - .0 - .max(0.0_f64) as u64; + .0 as u64; return normal_as_poisson; } @@ -300,8 +302,8 @@ impl< } } -impl> - DistributionSampler for SimplerDistributionSamplers +impl DistributionSampler + for SimplerDistributionSamplers { type ConcreteSampler = Self; @@ -309,12 +311,21 @@ impl bool { - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - // if probability == 1, then U[0, 1) always < 1.0 - // if probability == 0, then U[0, 1) never < 0.0 - u01 < probability + fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { + #[allow(clippy::cast_precision_loss)] + const SCALE: f64 = 2.0 * (1u64 << 63) as f64; + + // Safety: + // (a) 0 <= probability < 1: probability * SCALE is in [0, 2^64) + // since 1 - 2^-53 is before 1.0 + // (b) probability == 1 : p_u64 is undefined + // this case is checked for in the return + let p_u64 = unsafe { (probability.get() * SCALE).to_int_unchecked::() }; + + #[allow(clippy::float_cmp)] + { + (rng.sample_u64() < p_u64) || (probability == 1.0_f64) + } } } diff --git a/necsim/impls/no-std/src/decomposition/equal/mod.rs b/necsim/impls/no-std/src/decomposition/equal/mod.rs index 885c88103..531d775ef 100644 --- a/necsim/impls/no-std/src/decomposition/equal/mod.rs +++ b/necsim/impls/no-std/src/decomposition/equal/mod.rs @@ -68,12 +68,15 @@ impl> Decomposition for EqualDecomposition> EqualDecomposition { fn next_log2(coord: OffByOneU32) -> u8 { - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - if coord.get() > 1 { - M::ceil(M::ln(f64::from(coord)) / core::f64::consts::LN_2) as u8 - } else { - 0 - } + // OffByOneU32 holds [1, 2^32] + // with leading zeros [63, 31] + // with next log2 [0, 32] + + #[allow(clippy::cast_possible_truncation)] + let log2_floor = (u64::BITS - coord.get().leading_zeros() - 1) as u8; + let round_up = (coord.get() & (coord.get() - 1)) != 0; + + log2_floor + u8::from(round_up) } fn map_x_y_to_morton(mut morton_x: u8, mut morton_y: u8, mut dx: u32, mut dy: u32) -> u64 { diff --git a/necsim/impls/no-std/src/decomposition/radial.rs b/necsim/impls/no-std/src/decomposition/radial.rs index e1786f672..5027042ff 100644 --- a/necsim/impls/no-std/src/decomposition/radial.rs +++ b/necsim/impls/no-std/src/decomposition/radial.rs @@ -37,6 +37,8 @@ impl> Decomposition for RadialDecomposition { } fn map_location_to_subdomain_rank(&self, location: &Location, habitat: &H) -> u32 { + const BELOW_ONE: f64 = f64::from_bits(0x3FEF_FFFF_FFFF_FFFF_u64); + let extent = habitat.get_extent(); let neutral_x = location.x().wrapping_sub(extent.x()); @@ -50,10 +52,12 @@ impl> Decomposition for RadialDecomposition { * 0.5_f64) + 0.5_f64; - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - { - (M::floor(f64::from(self.subdomain.size().get()) * fraction) as u32) - .min(self.subdomain.size().get() - 1) + let fraction = fraction.clamp(0.0_f64, BELOW_ONE); + + // Safety: [0, 1) * subdomain.size in [0, 2^32) is losslessly + // represented in both f64 and u32 + unsafe { + M::floor(fraction * f64::from(self.subdomain.size().get())).to_int_unchecked::() } } } diff --git a/necsim/impls/no-std/src/lib.rs b/necsim/impls/no-std/src/lib.rs index fda8c949f..8f1617714 100644 --- a/necsim/impls/no-std/src/lib.rs +++ b/necsim/impls/no-std/src/lib.rs @@ -11,6 +11,7 @@ #![feature(negative_impls)] #![feature(impl_trait_in_assoc_type)] #![feature(associated_type_bounds)] +#![feature(const_float_bits_conv)] #![allow(incomplete_features)] #![feature(specialization)] diff --git a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs index a76569904..122f7d7b7 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/landscape.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/landscape.rs @@ -1,7 +1,7 @@ use alloc::{collections::VecDeque, vec::Vec}; use core::{ iter::FromIterator, - num::{NonZeroU64, Wrapping}, + num::{NonZeroU32, NonZeroU64, Wrapping}, ops::ControlFlow, }; @@ -184,12 +184,17 @@ pub fn simulate< tie_breaker: _, } = immigrant; + // Safety: immigrant can only migrate to habitable target + let habitat_at_location = unsafe { + NonZeroU32::new_unchecked( + simulation + .habitat() + .get_habitat_at_location(&dispersal_target), + ) + }; + // Finish sampling the dispersal of the immigrating individual - let target_index = coalescence_rng_sample.sample_coalescence_index::( - simulation - .habitat() - .get_habitat_at_location(&dispersal_target), - ); + let target_index = coalescence_rng_sample.sample_coalescence_index(habitat_at_location); let dispersal_target = IndexedLocation::new(dispersal_target, target_index); // Cache the immigration event diff --git a/necsim/impls/no-std/src/parallelisation/independent/mod.rs b/necsim/impls/no-std/src/parallelisation/independent/mod.rs index 2af9e12e5..fa1db0b53 100644 --- a/necsim/impls/no-std/src/parallelisation/independent/mod.rs +++ b/necsim/impls/no-std/src/parallelisation/independent/mod.rs @@ -40,6 +40,7 @@ impl DedupCache { DirectMappedCache::with_capacity(match self { DedupCache::Absolute(AbsoluteCapacity { capacity }) => capacity.get(), DedupCache::Relative(RelativeCapacity { factor }) => { + // Note: rust clamps f64 as usize to [0, 2^[32/64] - 1] #[allow( clippy::cast_precision_loss, clippy::cast_sign_loss, @@ -67,6 +68,7 @@ impl EventSlice { match self { EventSlice::Absolute(AbsoluteCapacity { capacity }) => capacity, EventSlice::Relative(RelativeCapacity { factor }) => { + // Note: rust clamps f64 as usize to [0, 2^[32/64] - 1] #[allow( clippy::cast_precision_loss, clippy::cast_sign_loss, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index ecca829c7..7d052e903 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize}, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, event::DispersalEvent, @@ -49,11 +49,7 @@ pub struct FixUpInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, O: Scenario, > ClassicalLineageStoreSampleInitialiser> for FixUpInitialiser { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index 1df6aac38..1528cf6ba 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize}, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, reporter::Reporter, @@ -22,11 +22,7 @@ pub struct GenesisInitialiser; impl< M: MathsCore, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, O: Scenario, > ClassicalLineageStoreSampleInitialiser for GenesisInitialiser { diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index 6f694b803..6ef6014ba 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - distribution::{Bernoulli, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, IndexUsize}, ActiveLineageSampler, DispersalSampler, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, @@ -24,7 +24,7 @@ pub mod resume; #[allow(clippy::module_name_repetitions)] pub trait ClassicalLineageStoreSampleInitialiser< M: MathsCore, - G: Rng + Samples + Samples + Samples, + G: Rng + Samples + Samples, O: Scenario, Error, > diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index 458177523..d7ab6eceb 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -1,6 +1,6 @@ use necsim_core::{ cogs::{ - distribution::{Bernoulli, Exponential, IndexUsize, UniformClosedOpenUnit}, + distribution::{Bernoulli, Exponential, IndexUsize}, EmigrationExit, ImmigrationEntry, LocallyCoherentLineageStore, MathsCore, Rng, Samples, }, lineage::Lineage, @@ -29,11 +29,7 @@ pub struct ResumeInitialiser> { impl< L: ExactSizeIterator, M: MathsCore, - G: Rng - + Samples - + Samples - + Samples - + Samples, + G: Rng + Samples + Samples + Samples, O: Scenario, > ClassicalLineageStoreSampleInitialiser> for ResumeInitialiser { From 1bfa30ec15d29521740fe6db6ebceedd97f29830 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Sun, 22 May 2022 08:48:47 +0000 Subject: [PATCH 17/21] Implemented untested modular distribution samplers --- necsim/core/bond/src/closed_open_unit_f64.rs | 8 + necsim/core/bond/src/open_closed_unit_f64.rs | 10 +- .../src/cogs/distribution/bernoulli_64b.rs | 32 ++ .../cogs/distribution/bernoulli_from_unit.rs | 24 ++ .../src/cogs/distribution/exp_inversion.rs | 30 ++ .../src/cogs/distribution/index_from_unit.rs | 124 +++++++ .../src/cogs/distribution/index_from_wide.rs | 135 ++++++++ .../src/cogs/distribution/index_rejection.rs | 166 +++++++++ .../impls/no-std/src/cogs/distribution/mod.rs | 12 + .../no-std/src/cogs/distribution/normal2d.rs | 28 ++ .../cogs/distribution/poisson_inversion.rs | 59 ++++ .../no-std/src/cogs/distribution/rand.rs | 233 +++++++++++++ .../distribution/std_normal2d_box_muller.rs | 33 ++ .../src/cogs/distribution/uniform_53b_unit.rs | 47 +++ .../cogs/distribution/uniform_binexp_unit.rs | 105 ++++++ necsim/impls/no-std/src/cogs/mod.rs | 1 + necsim/impls/no-std/src/cogs/rng/rand.rs | 249 +------------ necsim/impls/no-std/src/cogs/rng/simple.rs | 326 ++++++++---------- necsim/impls/no-std/src/lib.rs | 1 + 19 files changed, 1191 insertions(+), 432 deletions(-) create mode 100644 necsim/impls/no-std/src/cogs/distribution/bernoulli_64b.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/bernoulli_from_unit.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/exp_inversion.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/index_from_unit.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/index_from_wide.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/index_rejection.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/mod.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/normal2d.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/rand.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/uniform_53b_unit.rs create mode 100644 necsim/impls/no-std/src/cogs/distribution/uniform_binexp_unit.rs diff --git a/necsim/core/bond/src/closed_open_unit_f64.rs b/necsim/core/bond/src/closed_open_unit_f64.rs index ebadc9f85..d31b90c15 100644 --- a/necsim/core/bond/src/closed_open_unit_f64.rs +++ b/necsim/core/bond/src/closed_open_unit_f64.rs @@ -45,6 +45,14 @@ impl From for f64 { } } +impl TryFrom for ClosedOpenUnitF64 { + type Error = ClosedOpenUnitF64Error; + + fn try_from(value: ClosedUnitF64) -> Result { + Self::new(value.get()) + } +} + impl fmt::Debug for ClosedOpenUnitF64 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct ClosedOpenUnitF64Range(f64); diff --git a/necsim/core/bond/src/open_closed_unit_f64.rs b/necsim/core/bond/src/open_closed_unit_f64.rs index ef151be16..b60397e26 100644 --- a/necsim/core/bond/src/open_closed_unit_f64.rs +++ b/necsim/core/bond/src/open_closed_unit_f64.rs @@ -8,7 +8,7 @@ use core::{ use necsim_core_maths::MathsCore; use serde::{Deserialize, Serialize}; -use crate::NonPositiveF64; +use crate::{ClosedUnitF64, NonPositiveF64}; #[derive(Debug)] #[allow(clippy::module_name_repetitions)] @@ -46,6 +46,14 @@ impl From for f64 { } } +impl TryFrom for OpenClosedUnitF64 { + type Error = OpenClosedUnitF64Error; + + fn try_from(value: ClosedUnitF64) -> Result { + Self::new(value.get()) + } +} + impl fmt::Debug for OpenClosedUnitF64 { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { struct OpenClosedUnitF64Range(f64); diff --git a/necsim/impls/no-std/src/cogs/distribution/bernoulli_64b.rs b/necsim/impls/no-std/src/cogs/distribution/bernoulli_64b.rs new file mode 100644 index 000000000..b4222a20e --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/bernoulli_64b.rs @@ -0,0 +1,32 @@ +use necsim_core::cogs::{distribution::Bernoulli, DistributionSampler, MathsCore, RngCore}; +use necsim_core_bond::ClosedUnitF64; + +#[allow(clippy::module_name_repetitions)] +pub struct Bernoulli64BitSampler; + +impl DistributionSampler + for Bernoulli64BitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { + #[allow(clippy::cast_precision_loss)] + const SCALE: f64 = 2.0 * (1u64 << 63) as f64; + + // Safety: + // (a) 0 <= probability < 1: probability * SCALE is in [0, 2^64) + // since 1 - 2^-53 is before 1.0 + // (b) probability == 1 : p_u64 is undefined + // this case is checked for in the return + let p_u64 = unsafe { (probability.get() * SCALE).to_int_unchecked::() }; + + #[allow(clippy::float_cmp)] + { + (rng.sample_u64() < p_u64) || (probability == 1.0_f64) + } + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/bernoulli_from_unit.rs b/necsim/impls/no-std/src/cogs/distribution/bernoulli_from_unit.rs new file mode 100644 index 000000000..df98880c0 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/bernoulli_from_unit.rs @@ -0,0 +1,24 @@ +use necsim_core::cogs::{ + distribution::{Bernoulli, RawDistribution, UniformClosedOpenUnit}, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::ClosedUnitF64; + +#[allow(clippy::module_name_repetitions)] +pub struct BernoulliFromUnitSampler; + +impl> + DistributionSampler for BernoulliFromUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, samplers: &S, probability: ClosedUnitF64) -> bool { + // if probability == 1, then U[0, 1) always < 1.0 + // if probability == 0, then U[0, 1) never < 0.0 + UniformClosedOpenUnit::sample_raw(rng, samplers) < probability + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/exp_inversion.rs b/necsim/impls/no-std/src/cogs/distribution/exp_inversion.rs new file mode 100644 index 000000000..1e076ad78 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/exp_inversion.rs @@ -0,0 +1,30 @@ +use necsim_core::cogs::{ + distribution::{Exponential, Lambda, RawDistribution, UniformOpenClosedUnit}, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::NonNegativeF64; + +#[allow(clippy::module_name_repetitions)] +pub struct ExponentialInverseTransformSampler; + +impl> + DistributionSampler for ExponentialInverseTransformSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Lambda(lambda): Lambda, + ) -> NonNegativeF64 { + let u01 = UniformOpenClosedUnit::sample_raw(rng, samplers); + + // Inverse transform sample: X = -ln(U(0,1]) / lambda + -u01.ln::() / lambda + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/index_from_unit.rs b/necsim/impls/no-std/src/cogs/distribution/index_from_unit.rs new file mode 100644 index 000000000..eac54edb9 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/index_from_unit.rs @@ -0,0 +1,124 @@ +use core::num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}; + +use necsim_core::cogs::{ + distribution::{ + IndexU128, IndexU32, IndexU64, IndexUsize, Length, RawDistribution, UniformClosedOpenUnit, + }, + DistributionSampler, MathsCore, RngCore, +}; + +#[allow(clippy::module_name_repetitions)] +pub struct IndexFromUnitSampler; + +impl> + DistributionSampler for IndexFromUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> usize { + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); + + // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] + // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; + + if cfg!(target_pointer_width = "32") { + // Note: [0, 2^32) is losslessly represented in f64 + index + } else { + // Note: Ensure index < length despite + // usize->f64->usize precision loss + index.min(length.get() - 1) + } + } +} + +impl> + DistributionSampler for IndexFromUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u32 { + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); + + // Safety: U[0, 1) * length in [0, 2^32) is losslessly represented + // in both f64 and u32 + unsafe { M::floor(u01.get() * f64::from(length.get())).to_int_unchecked::() } + } +} + +impl> + DistributionSampler for IndexFromUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u64 { + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); + + // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 + // since (1 - 2^-53) * 2^64 <= (2^64 - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; + + // Note: Ensure index < length despite u64->f64->u64 precision loss + index.min(length.get() - 1) + } +} + +impl> + DistributionSampler for IndexFromUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Length(length): Length, + ) -> u128 { + let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); + + // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 + // since (1 - 2^-53) * 2^128 <= (2^128 - 1) + #[allow(clippy::cast_precision_loss)] + let index = + unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; + + // Note: Ensure index < length despite u128->f64->u128 precision loss + index.min(length.get() - 1) + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/index_from_wide.rs b/necsim/impls/no-std/src/cogs/distribution/index_from_wide.rs new file mode 100644 index 000000000..514e5a641 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/index_from_wide.rs @@ -0,0 +1,135 @@ +use core::num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}; + +use necsim_core::cogs::{ + distribution::{IndexU128, IndexU32, IndexU64, IndexUsize, Length, RawDistribution}, + DistributionSampler, MathsCore, RngCore, +}; + +#[allow(clippy::module_name_repetitions)] +pub struct IndexFromWideMulSampler; + +impl DistributionSampler + for IndexFromWideMulSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + #[inline] + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> usize { + #[allow(clippy::cast_possible_truncation)] + if cfg!(target_pointer_width = "32") { + IndexU32::sample_raw_with::( + rng, + self, + Length(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }), + ) as usize + } else { + IndexU64::sample_raw_with::( + rng, + self, + Length(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }), + ) as usize + } + } +} + +impl DistributionSampler + for IndexFromWideMulSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u32 { + // Sample U(0, length - 1) using a widening multiplication + // Note: Some slight bias is traded for only needing one u64 sample + // Note: Should optimise to a single 64 bit (high-only) multiplication + #[allow(clippy::cast_possible_truncation)] + { + (((u128::from(rng.sample_u64()) * u128::from(length.get())) >> 64) & u128::from(!0_u32)) + as u32 + } + } +} + +impl DistributionSampler + for IndexFromWideMulSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u64 { + // Sample U(0, length - 1) using a widening multiplication + // Note: Some slight bias is traded for only needing one u64 sample + // Note: Should optimise to a single 64 bit (high-only) multiplication + #[allow(clippy::cast_possible_truncation)] + { + (((u128::from(rng.sample_u64()) * u128::from(length.get())) >> 64) & u128::from(!0_u64)) + as u64 + } + } +} + +impl DistributionSampler + for IndexFromWideMulSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u128 { + // Sample U(0, length - 1) using a widening multiplication + // Note: Some slight bias is traded for only needing one u128 sample + + const LOWER_MASK: u128 = !0 >> 64; + + let raw_hi = u128::from(rng.sample_u64()); + let raw_lo = u128::from(rng.sample_u64()); + + // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length + let mut low = raw_lo * (length.get() & LOWER_MASK); + let mut t = low >> 64; + low &= LOWER_MASK; + t += raw_hi * (length.get() & LOWER_MASK); + low += (t & LOWER_MASK) << 64; + let mut high = t >> 64; + t = low >> 64; + // low-only: low &= LOWER_MASK; + t += (length.get() >> 64) * raw_lo; + // low-only: low += (t & LOWER_MASK) << 64; + high += t >> 64; + high += raw_hi * (length.get() >> 64); + + high + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/index_rejection.rs b/necsim/impls/no-std/src/cogs/distribution/index_rejection.rs new file mode 100644 index 000000000..7d5f3cbcb --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/index_rejection.rs @@ -0,0 +1,166 @@ +use core::num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}; + +use necsim_core::cogs::{ + distribution::{IndexU128, IndexU32, IndexU64, IndexUsize, Length, RawDistribution}, + DistributionSampler, MathsCore, RngCore, +}; + +#[allow(clippy::module_name_repetitions)] +pub struct IndexRejectionSampler; + +impl DistributionSampler + for IndexRejectionSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + #[inline] + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> usize { + #[allow(clippy::cast_possible_truncation)] + if cfg!(target_pointer_width = "32") { + IndexU32::sample_raw_with::( + rng, + self, + Length(unsafe { NonZeroU32::new_unchecked(length.get() as u32) }), + ) as usize + } else { + IndexU64::sample_raw_with::( + rng, + self, + Length(unsafe { NonZeroU64::new_unchecked(length.get() as u64) }), + ) as usize + } + } +} + +impl DistributionSampler for IndexRejectionSampler { + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u32 { + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u64 = !0 >> 32; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = rng.sample_u64(); + + let sample_check_lo = (raw & LOWER_MASK) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_lo as u32) <= acceptance_zone { + return (sample_check_lo >> 32) as u32; + } + + let sample_check_hi = (raw >> 32) * u64::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check_hi as u32) <= acceptance_zone { + return (sample_check_hi >> 32) as u32; + } + } + } +} + +impl DistributionSampler for IndexRejectionSampler { + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u64 { + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw = rng.sample_u64(); + + let sample_check = u128::from(raw) * u128::from(length.get()); + + #[allow(clippy::cast_possible_truncation)] + if (sample_check as u64) <= acceptance_zone { + return (sample_check >> 64) as u64; + } + } + } +} + +impl DistributionSampler + for IndexRejectionSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u128 { + // Adapted from: + // https://docs.rs/rand/0.8.4/rand/distributions/uniform/trait.UniformSampler.html#method.sample_single + + const LOWER_MASK: u128 = !0 >> 64; + + // Conservative approximation of the acceptance zone + let acceptance_zone = (length.get() << length.leading_zeros()).wrapping_sub(1); + + loop { + let raw_hi = u128::from(rng.sample_u64()); + let raw_lo = u128::from(rng.sample_u64()); + + // 256-bit multiplication (hi, lo) = (raw_hi, raw_lo) * length + let mut low = raw_lo * (length.get() & LOWER_MASK); + let mut t = low >> 64; + low &= LOWER_MASK; + t += raw_hi * (length.get() & LOWER_MASK); + low += (t & LOWER_MASK) << 64; + let mut high = t >> 64; + t = low >> 64; + low &= LOWER_MASK; + t += (length.get() >> 64) * raw_lo; + low += (t & LOWER_MASK) << 64; + high += t >> 64; + high += raw_hi * (length.get() >> 64); + + let sample = high; + let check = low; + + if check <= acceptance_zone { + return sample; + } + } + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/mod.rs b/necsim/impls/no-std/src/cogs/distribution/mod.rs new file mode 100644 index 000000000..99ee5f380 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/mod.rs @@ -0,0 +1,12 @@ +pub mod bernoulli_64b; +pub mod bernoulli_from_unit; +pub mod exp_inversion; +pub mod index_from_unit; +pub mod index_from_wide; +pub mod index_rejection; +pub mod normal2d; +pub mod poisson_inversion; +pub mod rand; +pub mod std_normal2d_box_muller; +pub mod uniform_53b_unit; +pub mod uniform_binexp_unit; diff --git a/necsim/impls/no-std/src/cogs/distribution/normal2d.rs b/necsim/impls/no-std/src/cogs/distribution/normal2d.rs new file mode 100644 index 000000000..f8b3dd5e9 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/normal2d.rs @@ -0,0 +1,28 @@ +use necsim_core::cogs::{ + distribution::{Normal, Normal2D, RawDistribution, StandardNormal2D}, + DistributionSampler, MathsCore, RngCore, +}; + +#[allow(clippy::module_name_repetitions)] +pub struct Normal2dSampler; + +impl> + DistributionSampler for Normal2dSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + Normal { mu, sigma }: Normal, + ) -> (f64, f64) { + let (z0, z1) = StandardNormal2D::sample_raw(rng, samplers); + + (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs b/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs new file mode 100644 index 000000000..416aae8e5 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs @@ -0,0 +1,59 @@ +use necsim_core::cogs::{ + distribution::{Lambda, Normal, Normal2D, Poisson, RawDistribution, UniformClosedOpenUnit}, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::NonNegativeF64; + +#[allow(clippy::module_name_repetitions)] +pub struct PoissonInverseTransformOrNormalSampler; + +impl< + M: MathsCore, + R: RngCore, + S: DistributionSampler + + DistributionSampler, + > DistributionSampler for PoissonInverseTransformOrNormalSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, samplers: &S, Lambda(lambda): Lambda) -> u64 { + let no_event_probability = M::exp(-lambda.get()); + + if no_event_probability <= 0.0_f64 { + // Fallback in case no_event_probability_per_step underflows + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + let normal_as_poisson = Normal2D::sample_raw_with( + rng, + samplers, + Normal { + mu: lambda.get(), + sigma: NonNegativeF64::from(lambda).sqrt::(), + }, + ) + .0 as u64; + + return normal_as_poisson; + } + + // https://en.wikipedia.org/w/index.php?title=Poisson_distribution&oldid=1088559556#cite_ref-Devroye1986_61-0 + let mut poisson = 0_u64; + let mut prod = no_event_probability; + let mut acc = no_event_probability; + + let u = UniformClosedOpenUnit::sample_raw(rng, samplers); + + #[allow(clippy::cast_precision_loss)] + while u > acc && prod > 0.0_f64 { + poisson += 1; + prod *= lambda.get() / (poisson as f64); + acc += prod; + } + + poisson + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/rand.rs b/necsim/impls/no-std/src/cogs/distribution/rand.rs new file mode 100644 index 000000000..7445c4dd5 --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/rand.rs @@ -0,0 +1,233 @@ +use core::num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}; + +use necsim_core::cogs::{ + distribution::{ + Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, + Normal2D, Poisson, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, + }, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; + +use rand_core::RngCore as RandRngCore; +use rand_distr::{ + uniform::{UniformInt as RandUniformInt, UniformSampler as RandUniformSampler}, + Bernoulli as RandBernoulli, Distribution as RandDistribution, Exp1 as RandExp1, + OpenClosed01 as RandOpenClosed01, Poisson as RandPoisson, Standard as RandStandard, + StandardNormal as RandStandardNormal, +}; + +#[allow(clippy::module_name_repetitions)] +pub struct RandDistributionSamplers; + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + let u01: f64 = RandStandard.sample(rng); + + // Safety: Standard samples from [0, 1) + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + let u01: f64 = RandOpenClosed01.sample(rng); + + // Safety: OpenClosed01 samples from (0, 1] + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> usize { + RandUniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u32 { + RandUniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u64 { + RandUniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Length(length): Length, + ) -> u128 { + RandUniformInt::::sample_single(0, length.get(), rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Lambda(lambda): Lambda, + ) -> NonNegativeF64 { + let exp1: f64 = RandExp1.sample(rng); + + // Safety: Exp1 samples from [0, +inf) + (unsafe { NonNegativeF64::new_unchecked(exp1) }) / lambda + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, Lambda(lambda): Lambda) -> u64 { + // Safety: PositiveF64 asserts that lambda > 0 + let poisson = unsafe { RandPoisson::new(lambda.get()).unwrap_unchecked() }; + + // Note: rust clamps f64 as u64 to [0, 2^64 - 1] + #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] + { + poisson.sample(rng) as u64 + } + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { + // Safety: ClosedUnitF64 asserts that probability is in [0.0, 1.0] + let bernoulli = unsafe { RandBernoulli::new(probability.get()).unwrap_unchecked() }; + + bernoulli.sample(rng) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> (f64, f64) { + ( + RandStandardNormal.sample(rng), + RandStandardNormal.sample(rng), + ) + } +} + +impl DistributionSampler + for RandDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + #[inline] + fn sample_distribution( + &self, + rng: &mut R, + _samplers: &S, + Normal { mu, sigma }: Normal, + ) -> (f64, f64) { + let (z0, z1): (f64, f64) = ( + RandStandardNormal.sample(rng), + RandStandardNormal.sample(rng), + ); + + (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs b/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs new file mode 100644 index 000000000..ff8ab645f --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs @@ -0,0 +1,33 @@ +use necsim_core::cogs::{ + distribution::{ + RawDistribution, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, + }, + DistributionSampler, MathsCore, RngCore, +}; + +pub struct StandardNormal2DBoxMullerSampler; + +impl< + M: MathsCore, + R: RngCore, + S: DistributionSampler + + DistributionSampler, + > DistributionSampler for StandardNormal2DBoxMullerSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { + // Basic Box-Muller transform + let u0 = UniformOpenClosedUnit::sample_raw(rng, samplers); + let u1 = UniformClosedOpenUnit::sample_raw(rng, samplers); + + let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); + let theta = -core::f64::consts::TAU * u1.get(); + + (r * M::sin(theta), r * M::cos(theta)) + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/uniform_53b_unit.rs b/necsim/impls/no-std/src/cogs/distribution/uniform_53b_unit.rs new file mode 100644 index 000000000..5a43ba35c --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/uniform_53b_unit.rs @@ -0,0 +1,47 @@ +use necsim_core::cogs::{ + distribution::{UniformClosedOpenUnit, UniformOpenClosedUnit}, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, OpenClosedUnitF64}; + +#[allow(clippy::module_name_repetitions)] +pub struct Uniform53BitUnitSampler; + +impl DistributionSampler + for Uniform53BitUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + // Copyright (c) 2014, Taylor R Campbell + #[allow(clippy::cast_precision_loss)] + let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + } +} + +impl DistributionSampler + for Uniform53BitUnitSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval + // Copyright (c) 2014, Taylor R Campbell + #[allow(clippy::cast_precision_loss)] + let u01 = + (((rng.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 + + unsafe { OpenClosedUnitF64::new_unchecked(u01) } + } +} diff --git a/necsim/impls/no-std/src/cogs/distribution/uniform_binexp_unit.rs b/necsim/impls/no-std/src/cogs/distribution/uniform_binexp_unit.rs new file mode 100644 index 000000000..81c2100cc --- /dev/null +++ b/necsim/impls/no-std/src/cogs/distribution/uniform_binexp_unit.rs @@ -0,0 +1,105 @@ +use core::{ + convert::TryFrom, + intrinsics::{likely, unlikely}, +}; + +use necsim_core::cogs::{ + distribution::{UniformClosedOpenUnit, UniformOpenClosedUnit}, + DistributionSampler, MathsCore, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, OpenClosedUnitF64}; + +pub struct UniformUnitBinaryExpansionSampler; + +impl DistributionSampler + for UniformUnitBinaryExpansionSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { + loop { + // Rejection-sample to transform U[0, 1] -> U[0, 1) + if let Ok(u01) = ClosedOpenUnitF64::try_from(sample_closed_unit_f64(rng)) { + return u01; + } + } + } +} + +impl DistributionSampler + for UniformUnitBinaryExpansionSampler +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { + loop { + // Rejection-sample to transform U[0, 1] -> U(0, 1] + if let Ok(u01) = OpenClosedUnitF64::try_from(sample_closed_unit_f64(rng)) { + return u01; + } + } + } +} + +// https://prng.di.unimi.it/random_real.c -> random_real +// Copyright (c) 2014, Taylor R Campbell +fn sample_closed_unit_f64(rng: &mut R) -> ClosedUnitF64 { + let mut exponent = -64_i32; + let mut significand: u64; + + // Read zeros into the exponent until we hit a one; + // the rest will go into the significand. + loop { + significand = rng.sample_u64(); + + if likely(significand != 0) { + break; + } + + exponent -= 64; + + // If the exponent falls below -1074 = emin + 1 - p, + // the exponent of the smallest subnormal, we are + // guaranteed the result will be rounded to zero. + if unlikely(exponent < -1074) { + return ClosedUnitF64::zero(); + } + } + + // There is a 1 somewhere in significand, not necessarily in + // the most significant position. + // If there are leading zeros, shift them into the exponent + // and refill the less-significant bits of the significand. + #[allow(clippy::cast_possible_wrap)] + let shift = significand.leading_zeros() as i32; + + if shift != 0 { + exponent -= shift; + significand <<= shift; + significand |= rng.sample_u64() >> (64 - shift); + } + + // Set the sticky bit, since there is almost certainly another 1 + // in the bit stream. + // Otherwise, we might round what looks like a tie to even when, + // almost certainly, were we to look further in the bit stream, + // there would be a 1 breaking the tie. + significand |= 1; + + // Finally, convert to double (rounding) and scale by 2^exponent. + #[allow(clippy::cast_precision_loss)] + let u01 = libm::ldexp(significand as f64, exponent); + + // Safety: + // (a) (2^64 - 1) == 2^64 in f64 -> (2^64 - 1) / 2^64 is 1.0 + // (b) 0 / 2^64 is 0.0 + unsafe { ClosedUnitF64::new_unchecked(u01) } +} diff --git a/necsim/impls/no-std/src/cogs/mod.rs b/necsim/impls/no-std/src/cogs/mod.rs index cc94d1886..e221628ae 100644 --- a/necsim/impls/no-std/src/cogs/mod.rs +++ b/necsim/impls/no-std/src/cogs/mod.rs @@ -1,6 +1,7 @@ pub mod active_lineage_sampler; pub mod coalescence_sampler; pub mod dispersal_sampler; +pub mod distribution; pub mod emigration_exit; pub mod event_sampler; pub mod habitat; diff --git a/necsim/impls/no-std/src/cogs/rng/rand.rs b/necsim/impls/no-std/src/cogs/rng/rand.rs index bf234c255..52d828d9a 100644 --- a/necsim/impls/no-std/src/cogs/rng/rand.rs +++ b/necsim/impls/no-std/src/cogs/rng/rand.rs @@ -1,27 +1,12 @@ -use core::{ - fmt, - marker::PhantomData, - num::{NonZeroU128, NonZeroU32, NonZeroU64, NonZeroUsize}, -}; - -use necsim_core::cogs::{ - distribution::{ - Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, - Normal2D, Poisson, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, - }, - Backup, DistributionSampler, MathsCore, Rng, RngCore, -}; -use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; +use core::{fmt, marker::PhantomData}; + +use necsim_core::cogs::{Backup, MathsCore, Rng, RngCore}; use rand_core::{Error, RngCore as RandRngCore, SeedableRng as RandSeedableRng}; -use rand_distr::{ - uniform::{UniformInt, UniformSampler}, - Bernoulli as RandBernoulli, Distribution as RandDistribution, Exp1 as RandExp1, - OpenClosed01 as RandOpenClosed01, Poisson as RandPoisson, Standard as RandStandard, - StandardNormal as RandStandardNormal, -}; use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize, Serializer}; +use crate::cogs::distribution::rand::RandDistributionSamplers; + #[allow(clippy::module_name_repetitions)] #[derive(TypeLayout)] #[repr(transparent)] @@ -280,7 +265,7 @@ impl Backup for RandRng { impl Rng for RandRng { type Generator = R; - type Sampler = RandDistributionSamplers; + type Sampler = RandDistributionSamplers; fn generator(&mut self) -> &mut Self::Generator { &mut self.inner @@ -296,226 +281,6 @@ impl Rng for RandRng { } fn with Q, Q>(&mut self, inner: F) -> Q { - let samplers = RandDistributionSamplers { - _marker: PhantomData::<(M, R)>, - }; - - inner(&mut self.inner, &samplers) - } -} - -#[allow(clippy::module_name_repetitions)] -pub struct RandDistributionSamplers { - _marker: PhantomData<(M, R)>, -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { - let u01: f64 = RandStandard.sample(rng); - - // Safety: Standard samples from [0, 1) - unsafe { ClosedOpenUnitF64::new_unchecked(u01) } - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { - let u01: f64 = RandOpenClosed01.sample(rng); - - // Safety: OpenClosed01 samples from (0, 1] - unsafe { OpenClosedUnitF64::new_unchecked(u01) } - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Length(length): Length, - ) -> usize { - UniformInt::::sample_single(0, length.get(), rng) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Length(length): Length, - ) -> u32 { - UniformInt::::sample_single(0, length.get(), rng) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Length(length): Length, - ) -> u64 { - UniformInt::::sample_single(0, length.get(), rng) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Length(length): Length, - ) -> u128 { - UniformInt::::sample_single(0, length.get(), rng) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Lambda(lambda): Lambda, - ) -> NonNegativeF64 { - let exp1: f64 = RandExp1.sample(rng); - - // Safety: Exp1 samples from [0, +inf) - (unsafe { NonNegativeF64::new_unchecked(exp1) }) / lambda - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution(&self, rng: &mut R, _samplers: &S, Lambda(lambda): Lambda) -> u64 { - // Safety: PositiveF64 asserts that lambda > 0 - let poisson = unsafe { RandPoisson::new(lambda.get()).unwrap_unchecked() }; - - // Note: rust clamps f64 as u64 to [0, 2^64 - 1] - #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] - { - poisson.sample(rng) as u64 - } - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { - // Safety: ClosedUnitF64 asserts that probability is in [0.0, 1.0] - let bernoulli = unsafe { RandBernoulli::new(probability.get()).unwrap_unchecked() }; - - bernoulli.sample(rng) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> (f64, f64) { - ( - RandStandardNormal.sample(rng), - RandStandardNormal.sample(rng), - ) - } -} - -impl DistributionSampler - for RandDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut R, - _samplers: &S, - Normal { mu, sigma }: Normal, - ) -> (f64, f64) { - let (z0, z1): (f64, f64) = ( - RandStandardNormal.sample(rng), - RandStandardNormal.sample(rng), - ); - - (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + inner(&mut self.inner, &RandDistributionSamplers) } } diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index 521d3ac01..972af8c6f 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -6,13 +6,20 @@ use core::{ use necsim_core::cogs::{ distribution::{ Bernoulli, Exponential, IndexU128, IndexU32, IndexU64, IndexUsize, Lambda, Length, Normal, - Normal2D, Poisson, RawDistribution, StandardNormal2D, UniformClosedOpenUnit, - UniformOpenClosedUnit, + Normal2D, Poisson, StandardNormal2D, UniformClosedOpenUnit, UniformOpenClosedUnit, }, Backup, DistributionSampler, MathsCore, Rng, RngCore, }; use necsim_core_bond::{ClosedOpenUnitF64, ClosedUnitF64, NonNegativeF64, OpenClosedUnitF64}; +use crate::cogs::distribution::{ + bernoulli_64b::Bernoulli64BitSampler, exp_inversion::ExponentialInverseTransformSampler, + index_from_unit::IndexFromUnitSampler, normal2d::Normal2dSampler, + poisson_inversion::PoissonInverseTransformOrNormalSampler, + std_normal2d_box_muller::StandardNormal2DBoxMullerSampler, + uniform_53b_unit::Uniform53BitUnitSampler, +}; + #[derive(Debug, TypeLayout)] #[allow(clippy::module_name_repetitions)] #[layout(free = "M")] @@ -49,7 +56,7 @@ impl Backup for SimpleRng { impl Rng for SimpleRng { type Generator = R; - type Sampler = SimplerDistributionSamplers; + type Sampler = SimpleDistributionSamplers; fn generator(&mut self) -> &mut Self::Generator { &mut self.inner @@ -65,7 +72,14 @@ impl Rng for SimpleRng { } fn with Q, Q>(&mut self, inner: F) -> Q { - let samplers = SimplerDistributionSamplers { + let samplers = SimpleDistributionSamplers { + u01: Uniform53BitUnitSampler, + index: IndexFromUnitSampler, + exp: ExponentialInverseTransformSampler, + poisson: PoissonInverseTransformOrNormalSampler, + bernoulli: Bernoulli64BitSampler, + std_normal_2d: StandardNormal2DBoxMullerSampler, + normal_2d: Normal2dSampler, _marker: PhantomData::<(M, R)>, }; @@ -74,54 +88,58 @@ impl Rng for SimpleRng { } #[allow(clippy::module_name_repetitions)] -pub struct SimplerDistributionSamplers { +pub struct SimpleDistributionSamplers { + u01: Uniform53BitUnitSampler, + index: IndexFromUnitSampler, + exp: ExponentialInverseTransformSampler, + poisson: PoissonInverseTransformOrNormalSampler, + bernoulli: Bernoulli64BitSampler, + std_normal_2d: StandardNormal2DBoxMullerSampler, + normal_2d: Normal2dSampler, _marker: PhantomData<(M, R)>, } impl DistributionSampler - for SimplerDistributionSamplers + for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = Uniform53BitUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.u01 } - fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> ClosedOpenUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = ((rng.sample_u64() >> 11) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { ClosedOpenUnitF64::new_unchecked(u01) } + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: ()) -> ClosedOpenUnitF64 { + DistributionSampler::::sample_distribution( + &self.u01, rng, samplers, params, + ) } } impl DistributionSampler - for SimplerDistributionSamplers + for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = Uniform53BitUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.u01 } - fn sample_distribution(&self, rng: &mut R, _samplers: &S, _params: ()) -> OpenClosedUnitF64 { - // http://prng.di.unimi.it -> Generating uniform doubles in the unit interval - #[allow(clippy::cast_precision_loss)] - let u01 = - (((rng.sample_u64() >> 11) + 1) as f64) * f64::from_bits(0x3CA0_0000_0000_0000_u64); // 0x1.0p-53 - - unsafe { OpenClosedUnitF64::new_unchecked(u01) } + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: ()) -> OpenClosedUnitF64 { + DistributionSampler::::sample_distribution( + &self.u01, rng, samplers, params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = IndexFromUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.index } #[inline] @@ -129,125 +147,91 @@ impl, + params: Length, ) -> usize { - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] - // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) - #[allow(clippy::cast_precision_loss)] - let index = - unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; - - if cfg!(target_pointer_width = "32") { - // Note: [0, 2^32) is losslessly represented in f64 - index - } else { - // Note: Ensure index < length despite - // usize->f64->usize precision loss - index.min(length.get() - 1) - } + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = IndexFromUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.index } - fn sample_distribution( - &self, - rng: &mut R, - samplers: &S, - Length(length): Length, - ) -> u32 { - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - // Safety: U[0, 1) * length in [0, 2^32) is losslessly represented - // in both f64 and u32 - unsafe { M::floor(u01.get() * f64::from(length.get())).to_int_unchecked::() } + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u32 { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = IndexFromUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.index } - fn sample_distribution( - &self, - rng: &mut R, - samplers: &S, - Length(length): Length, - ) -> u64 { - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 - // since (1 - 2^-53) * 2^64 <= (2^64 - 1) - #[allow(clippy::cast_precision_loss)] - let index = - unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; - - // Note: Ensure index < length despite u64->f64->u64 precision loss - index.min(length.get() - 1) + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = IndexFromUnitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.index } - fn sample_distribution( - &self, - rng: &mut R, - samplers: &S, - Length(length): Length, - ) -> u128 { - let u01 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 - // since (1 - 2^-53) * 2^128 <= (2^128 - 1) - #[allow(clippy::cast_precision_loss)] - let index = - unsafe { M::floor(u01.get() * (length.get() as f64)).to_int_unchecked::() }; - - // Note: Ensure index < length despite u128->f64->u128 precision loss - index.min(length.get() - 1) + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = ExponentialInverseTransformSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.exp } - fn sample_distribution( - &self, - rng: &mut R, - samplers: &S, - Lambda(lambda): Lambda, - ) -> NonNegativeF64 { - let u01 = UniformOpenClosedUnit::sample_raw(rng, samplers); - - // Inverse transform sample: X = -ln(U(0,1]) / lambda - -u01.ln::() / lambda + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Lambda) -> NonNegativeF64 { + DistributionSampler::::sample_distribution( + &self.exp, rng, samplers, params, + ) } } @@ -256,76 +240,42 @@ impl< R: RngCore, S: DistributionSampler + DistributionSampler, - > DistributionSampler for SimplerDistributionSamplers + > DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = PoissonInverseTransformOrNormalSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.poisson } - fn sample_distribution(&self, rng: &mut R, samplers: &S, Lambda(lambda): Lambda) -> u64 { - let no_event_probability = M::exp(-lambda.get()); - - if no_event_probability <= 0.0_f64 { - // Fallback in case no_event_probability_per_step underflows - // Note: rust clamps f64 as u64 to [0, 2^64 - 1] - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let normal_as_poisson = Normal2D::sample_raw_with( - rng, - samplers, - Normal { - mu: lambda.get(), - sigma: NonNegativeF64::from(lambda).sqrt::(), - }, - ) - .0 as u64; - - return normal_as_poisson; - } - - // https://en.wikipedia.org/wiki/Poisson_distribution#cite_ref-Devroye1986_54-0 - let mut poisson = 0_u64; - let mut prod = no_event_probability; - let mut acc = no_event_probability; - - let u = UniformClosedOpenUnit::sample_raw(rng, samplers); - - #[allow(clippy::cast_precision_loss)] - while u > acc && prod > 0.0_f64 { - poisson += 1; - prod *= lambda.get() / (poisson as f64); - acc += prod; - } - - poisson + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Lambda) -> u64 { + DistributionSampler::::sample_distribution( + &self.poisson, + rng, + samplers, + params, + ) } } impl DistributionSampler - for SimplerDistributionSamplers + for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = Bernoulli64BitSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.bernoulli } - fn sample_distribution(&self, rng: &mut R, _samplers: &S, probability: ClosedUnitF64) -> bool { - #[allow(clippy::cast_precision_loss)] - const SCALE: f64 = 2.0 * (1u64 << 63) as f64; - - // Safety: - // (a) 0 <= probability < 1: probability * SCALE is in [0, 2^64) - // since 1 - 2^-53 is before 1.0 - // (b) probability == 1 : p_u64 is undefined - // this case is checked for in the return - let p_u64 = unsafe { (probability.get() * SCALE).to_int_unchecked::() }; - - #[allow(clippy::float_cmp)] - { - (rng.sample_u64() < p_u64) || (probability == 1.0_f64) - } + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: ClosedUnitF64) -> bool { + DistributionSampler::::sample_distribution( + &self.bernoulli, + rng, + samplers, + params, + ) } } @@ -334,43 +284,41 @@ impl< R: RngCore, S: DistributionSampler + DistributionSampler, - > DistributionSampler for SimplerDistributionSamplers + > DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = StandardNormal2DBoxMullerSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.std_normal_2d } - fn sample_distribution(&self, rng: &mut R, samplers: &S, _params: ()) -> (f64, f64) { - // Basic Box-Muller transform - let u0 = UniformOpenClosedUnit::sample_raw(rng, samplers); - let u1 = UniformClosedOpenUnit::sample_raw(rng, samplers); - - let r = M::sqrt(-2.0_f64 * M::ln(u0.get())); - let theta = -core::f64::consts::TAU * u1.get(); - - (r * M::sin(theta), r * M::cos(theta)) + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: ()) -> (f64, f64) { + DistributionSampler::::sample_distribution( + &self.std_normal_2d, + rng, + samplers, + params, + ) } } impl> - DistributionSampler for SimplerDistributionSamplers + DistributionSampler for SimpleDistributionSamplers { - type ConcreteSampler = Self; + type ConcreteSampler = Normal2dSampler; fn concrete(&self) -> &Self::ConcreteSampler { - self + &self.normal_2d } - fn sample_distribution( - &self, - rng: &mut R, - samplers: &S, - Normal { mu, sigma }: Normal, - ) -> (f64, f64) { - let (z0, z1) = StandardNormal2D::sample_raw(rng, samplers); - - (z0 * sigma.get() + mu, z1 * sigma.get() + mu) + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Normal) -> (f64, f64) { + DistributionSampler::::sample_distribution( + &self.normal_2d, + rng, + samplers, + params, + ) } } diff --git a/necsim/impls/no-std/src/lib.rs b/necsim/impls/no-std/src/lib.rs index 8f1617714..f74a06f61 100644 --- a/necsim/impls/no-std/src/lib.rs +++ b/necsim/impls/no-std/src/lib.rs @@ -12,6 +12,7 @@ #![feature(impl_trait_in_assoc_type)] #![feature(associated_type_bounds)] #![feature(const_float_bits_conv)] +#![feature(core_intrinsics)] #![allow(incomplete_features)] #![feature(specialization)] From fcbe9985b652f3685f833334d6d8c5bdbd708533 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Sun, 22 May 2022 09:14:17 +0000 Subject: [PATCH 18/21] Switch alias sampler tests to modular distribution sampling --- .../alias/sampler/indexed/tests.rs | 159 +---------------- .../alias/sampler/stack/tests.rs | 161 +----------------- .../alias/sampler/tests.rs | 158 ++++++++++++++++- 3 files changed, 165 insertions(+), 313 deletions(-) diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs index 4a95671e1..3186f1623 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/tests.rs @@ -1,14 +1,9 @@ use alloc::{vec, vec::Vec}; -use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; use hashbrown::HashMap; -use necsim_core::cogs::{ - distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, Rng, RngCore, SeedableRng, -}; +use necsim_core::cogs::{Backup, SeedableRng}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; -use necsim_core_maths::MathsCore; use crate::cogs::{ maths::intrinsics::IntrinsicsMathsCore, @@ -16,8 +11,8 @@ use crate::cogs::{ }; use super::{ - super::decompose_weight, DynamicAliasMethodIndexedSampler, EventLocation, - RejectionSamplingGroup, + super::{decompose_weight, tests::DummyRng}, + DynamicAliasMethodIndexedSampler, EventLocation, RejectionSamplingGroup, }; #[test] @@ -1077,151 +1072,3 @@ fn debug_display_sampler() { "DynamicAliasMethodIndexedSampler { exponents: [2, 1], total_weight: 20.0 }" ); } - -// GRCOV_EXCL_START -#[derive(Debug, serde::Serialize, serde::Deserialize)] -struct DummyRng(Vec); - -impl DummyRng { - fn new(mut vec: Vec) -> Self { - vec.reverse(); - - Self(vec) - } - - fn sample_f64(&mut self) -> f64 { - self.0.pop().unwrap() - } -} - -impl RngCore for DummyRng { - type Seed = [u8; 0]; - - #[must_use] - fn from_seed(_seed: Self::Seed) -> Self { - Self(Vec::new()) - } - - #[must_use] - fn sample_u64(&mut self) -> u64 { - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - { - ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 - } - } -} - -impl Rng for DummyRng { - type Generator = Self; - type Sampler = DummyDistributionSamplers; - - fn generator(&mut self) -> &mut Self::Generator { - self - } - - fn map_generator Self::Generator>(self, map: F) -> Self { - map(self) - } - - fn with Q, Q>(&mut self, inner: F) -> Q { - let samplers = DummyDistributionSamplers; - - inner(self, &samplers) - } -} - -struct DummyDistributionSamplers; - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> usize { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] - // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - if cfg!(target_pointer_width = "32") { - // Note: [0, 2^32) is losslessly represented in f64 - index - } else { - // Note: Ensure index < length despite - // usize->f64->usize precision loss - index.min(length.get() - 1) - } - } -} - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> u64 { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 - // since (1 - 2^-53) * 2^64 <= (2^64 - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - // Note: Ensure index < length despite u64->f64->u64 precision loss - index.min(length.get() - 1) - } -} - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> u128 { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 - // since (1 - 2^-53) * 2^128 <= (2^128 - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - // Note: Ensure index < length despite u128->f64->u128 precision loss - index.min(length.get() - 1) - } -} -// GRCOV_EXCL_STOP diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs index aa0258506..651d18053 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/tests.rs @@ -1,20 +1,17 @@ -use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; - use alloc::{vec, vec::Vec}; -use necsim_core::cogs::{ - distribution::{IndexU128, IndexU64, IndexUsize, Length}, - Backup, DistributionSampler, Rng, RngCore, SeedableRng, -}; +use necsim_core::cogs::{Backup, SeedableRng}; use necsim_core_bond::{NonNegativeF64, PositiveF64}; -use necsim_core_maths::MathsCore; use crate::cogs::{ maths::intrinsics::IntrinsicsMathsCore, rng::{simple::SimpleRng, wyhash::WyHash}, }; -use super::{super::decompose_weight, DynamicAliasMethodStackSampler, RejectionSamplingGroup}; +use super::{ + super::{decompose_weight, tests::DummyRng}, + DynamicAliasMethodStackSampler, RejectionSamplingGroup, +}; #[test] fn singular_event_group() { @@ -576,151 +573,3 @@ fn debug_display_sampler() { "DynamicAliasMethodStackSampler { exponents: [2, 1], total_weight: 20.0 }" ); } - -// GRCOV_EXCL_START -#[derive(Debug, serde::Serialize, serde::Deserialize)] -struct DummyRng(Vec); - -impl DummyRng { - fn new(mut vec: Vec) -> Self { - vec.reverse(); - - Self(vec) - } - - fn sample_f64(&mut self) -> f64 { - self.0.pop().unwrap() - } -} - -impl RngCore for DummyRng { - type Seed = [u8; 0]; - - #[must_use] - fn from_seed(_seed: Self::Seed) -> Self { - Self(Vec::new()) - } - - #[must_use] - fn sample_u64(&mut self) -> u64 { - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - { - ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 - } - } -} - -impl Rng for DummyRng { - type Generator = Self; - type Sampler = DummyDistributionSamplers; - - fn generator(&mut self) -> &mut Self::Generator { - self - } - - fn map_generator Self::Generator>(self, map: F) -> Self { - map(self) - } - - fn with Q, Q>(&mut self, inner: F) -> Q { - let samplers = DummyDistributionSamplers; - - inner(self, &samplers) - } -} - -struct DummyDistributionSamplers; - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> usize { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^[32/64]) is a valid [u32/u64] - // since (1 - 2^-53) * 2^[32/64] <= (2^[32/64] - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - if cfg!(target_pointer_width = "32") { - // Note: [0, 2^32) is losslessly represented in f64 - index - } else { - // Note: Ensure index < length despite - // usize->f64->usize precision loss - index.min(length.get() - 1) - } - } -} - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> u64 { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^64) is a valid u64 - // since (1 - 2^-53) * 2^64 <= (2^64 - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - // Note: Ensure index < length despite u64->f64->u64 precision loss - index.min(length.get() - 1) - } -} - -impl DistributionSampler - for DummyDistributionSamplers -{ - type ConcreteSampler = Self; - - fn concrete(&self) -> &Self::ConcreteSampler { - self - } - - fn sample_distribution( - &self, - rng: &mut DummyRng, - _samplers: &DummyDistributionSamplers, - Length(length): Length, - ) -> u128 { - let u01 = rng.sample_f64(); - - // Safety: U[0, 1) * length in [0, 2^128) is a valid u128 - // since (1 - 2^-53) * 2^128 <= (2^128 - 1) - #[allow(clippy::cast_precision_loss)] - let index = unsafe { - IntrinsicsMathsCore::floor(u01 * (length.get() as f64)).to_int_unchecked::() - }; - - // Note: Ensure index < length despite u128->f64->u128 precision loss - index.min(length.get() - 1) - } -} -// GRCOV_EXCL_STOP diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs index 12e94d9ce..931e7345f 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs @@ -1,4 +1,16 @@ -use necsim_core_bond::{NonNegativeF64, PositiveF64}; +use alloc::vec::Vec; +use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; + +use necsim_core::cogs::{ + distribution::{IndexU128, IndexU64, IndexUsize, Length, UniformClosedOpenUnit}, + DistributionSampler, Rng, RngCore, +}; +use necsim_core_bond::{ClosedOpenUnitF64, NonNegativeF64, PositiveF64}; +use necsim_core_maths::MathsCore; + +use crate::cogs::{ + distribution::index_from_unit::IndexFromUnitSampler, maths::intrinsics::IntrinsicsMathsCore, +}; use super::{compose_weight, decompose_weight, PositiveF64Decomposed}; @@ -143,3 +155,147 @@ fn compose_weights() { compose_weight(-1020, 0x0010_0000_0000_0000_u128) ); } + +// GRCOV_EXCL_START +#[derive(Debug, serde::Serialize, serde::Deserialize)] +pub struct DummyRng(Vec); + +impl DummyRng { + pub fn new(mut vec: Vec) -> Self { + vec.reverse(); + + Self(vec) + } + + fn sample_f64(&mut self) -> f64 { + self.0.pop().unwrap() + } +} + +impl RngCore for DummyRng { + type Seed = [u8; 0]; + + #[must_use] + fn from_seed(_seed: Self::Seed) -> Self { + Self(Vec::new()) + } + + #[must_use] + fn sample_u64(&mut self) -> u64 { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] + { + ((self.sample_f64() / f64::from_bits(0x3CA0_0000_0000_0000_u64)) as u64) << 11 + } + } +} + +impl Rng for DummyRng { + type Generator = Self; + type Sampler = DummyDistributionSamplers; + + fn generator(&mut self) -> &mut Self::Generator { + self + } + + fn map_generator Self::Generator>(self, map: F) -> Self { + map(self) + } + + fn with Q, Q>(&mut self, inner: F) -> Q { + let samplers = DummyDistributionSamplers { + index: IndexFromUnitSampler, + }; + + inner(self, &samplers) + } +} + +pub struct DummyDistributionSamplers { + index: IndexFromUnitSampler, +} + +impl DistributionSampler + for DummyDistributionSamplers +{ + type ConcreteSampler = Self; + + fn concrete(&self) -> &Self::ConcreteSampler { + self + } + + #[inline] + fn sample_distribution( + &self, + rng: &mut DummyRng, + _samplers: &S, + _params: (), + ) -> ClosedOpenUnitF64 { + ClosedOpenUnitF64::new(rng.sample_f64()).unwrap() + } +} + +impl> + DistributionSampler for DummyDistributionSamplers +{ + type ConcreteSampler = IndexFromUnitSampler; + + fn concrete(&self) -> &Self::ConcreteSampler { + &self.index + } + + #[inline] + fn sample_distribution( + &self, + rng: &mut R, + samplers: &S, + params: Length, + ) -> usize { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) + } +} + +impl> + DistributionSampler for DummyDistributionSamplers +{ + type ConcreteSampler = IndexFromUnitSampler; + + fn concrete(&self) -> &Self::ConcreteSampler { + &self.index + } + + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u64 { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) + } +} + +impl> + DistributionSampler for DummyDistributionSamplers +{ + type ConcreteSampler = IndexFromUnitSampler; + + fn concrete(&self) -> &Self::ConcreteSampler { + &self.index + } + + #[inline] + fn sample_distribution(&self, rng: &mut R, samplers: &S, params: Length) -> u128 { + DistributionSampler::::sample_distribution( + &self.index, + rng, + samplers, + params, + ) + } +} +// GRCOV_EXCL_STOP From 5447038e02273703a85fd5f6b9480960267877a6 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Mon, 23 May 2022 07:02:50 +0000 Subject: [PATCH 19/21] Removed MathsCore usage from OriginSampler --- .../alias/sampler/tests.rs | 9 ++++- .../cogs/origin_sampler/almost_infinite.rs | 19 +++++----- .../src/cogs/origin_sampler/decomposition.rs | 4 +- .../src/cogs/origin_sampler/in_memory.rs | 8 ++-- .../no-std/src/cogs/origin_sampler/mod.rs | 5 ++- .../src/cogs/origin_sampler/non_spatial.rs | 8 ++-- .../src/cogs/origin_sampler/pre_sampler.rs | 37 +++++++++---------- .../src/cogs/origin_sampler/resuming.rs | 18 +++++---- .../cogs/origin_sampler/spatially_implicit.rs | 9 ++--- .../impls/no-std/src/decomposition/radial.rs | 4 +- rustcoalescence/algorithms/cuda/src/launch.rs | 2 +- rustcoalescence/algorithms/cuda/src/lib.rs | 6 +-- .../gillespie/src/event_skipping/launch.rs | 2 +- .../gillespie/src/event_skipping/mod.rs | 6 +-- .../src/gillespie/classical/launch.rs | 2 +- .../gillespie/src/gillespie/classical/mod.rs | 6 +-- .../src/gillespie/turnover/launch.rs | 2 +- .../gillespie/src/gillespie/turnover/mod.rs | 6 +-- .../algorithms/independent/src/launch.rs | 2 +- .../algorithms/independent/src/lib.rs | 6 +-- rustcoalescence/algorithms/src/lib.rs | 6 +-- .../scenarios/src/almost_infinite.rs | 2 +- rustcoalescence/scenarios/src/lib.rs | 2 +- rustcoalescence/scenarios/src/non_spatial.rs | 2 +- .../src/spatially_explicit/turnover/map.rs | 2 +- .../spatially_explicit/turnover/uniform.rs | 2 +- .../scenarios/src/spatially_implicit.rs | 2 +- 27 files changed, 97 insertions(+), 82 deletions(-) diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs index 931e7345f..bce58597d 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/tests.rs @@ -3,7 +3,7 @@ use core::num::{NonZeroU128, NonZeroU64, NonZeroUsize}; use necsim_core::cogs::{ distribution::{IndexU128, IndexU64, IndexUsize, Length, UniformClosedOpenUnit}, - DistributionSampler, Rng, RngCore, + Backup, DistributionSampler, Rng, RngCore, }; use necsim_core_bond::{ClosedOpenUnitF64, NonNegativeF64, PositiveF64}; use necsim_core_maths::MathsCore; @@ -189,6 +189,13 @@ impl RngCore for DummyRng { } } +#[contract_trait] +impl Backup for DummyRng { + unsafe fn backup_unchecked(&self) -> Self { + Self(self.0.clone()) + } +} + impl Rng for DummyRng { type Generator = Self; type Sampler = DummyDistributionSamplers; diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/almost_infinite.rs b/necsim/impls/no-std/src/cogs/origin_sampler/almost_infinite.rs index c18c4a745..7d8c23442 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/almost_infinite.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/almost_infinite.rs @@ -15,9 +15,11 @@ use super::{TrustedOriginSampler, UntrustedOriginSampler}; const HABITAT_CENTRE: u32 = u32::MAX / 2; +// Note: The MathsCore should not be utilised in the origin sampler +// to improve compatibility #[allow(clippy::module_name_repetitions)] pub struct AlmostInfiniteOriginSampler<'h, M: MathsCore, I: Iterator> { - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, last_index: u64, location_iterator: LocationIterator, radius_squared: u64, @@ -43,7 +45,7 @@ impl<'h, M: MathsCore, I: Iterator> fmt::Debug impl<'h, M: MathsCore, I: Iterator> AlmostInfiniteOriginSampler<'h, M, I> { #[must_use] pub fn new( - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, habitat: &'h AlmostInfiniteHabitat, radius: u16, ) -> Self { @@ -60,12 +62,11 @@ impl<'h, M: MathsCore, I: Iterator> AlmostInfiniteOriginSampler<'h, ); #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - let upper_bound_size_hint = M::ceil( - f64::from(radius) - * f64::from(radius) - * core::f64::consts::PI - * pre_sampler.get_sample_proportion().get(), - ) as u64; + let upper_bound_size_hint = (f64::from(radius) + * f64::from(radius) + * core::f64::consts::PI + * pre_sampler.get_sample_proportion().get() + + 1.0_f64) as u64; Self { pre_sampler, @@ -89,7 +90,7 @@ impl<'h, M: MathsCore, I: Iterator> UntrustedOriginSampler<'h, M> self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.pre_sampler } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/decomposition.rs b/necsim/impls/no-std/src/cogs/origin_sampler/decomposition.rs index 518e26a61..103c36769 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/decomposition.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/decomposition.rs @@ -12,6 +12,8 @@ use crate::{ decomposition::Decomposition, }; +// Note: The MathsCore should not be utilised in the origin sampler +// (only in the decomposition) to improve compatibility #[allow(clippy::module_name_repetitions)] #[derive(Debug)] pub struct DecompositionOriginSampler< @@ -49,7 +51,7 @@ impl<'d, M: MathsCore, O: UntrustedOriginSampler<'d, M>, D: Decomposition OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.origin_sampler.into_pre_sampler() } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/in_memory.rs b/necsim/impls/no-std/src/cogs/origin_sampler/in_memory.rs index 4ea417586..7d24dd29d 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/in_memory.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/in_memory.rs @@ -16,9 +16,11 @@ use crate::cogs::{ use super::{TrustedOriginSampler, UntrustedOriginSampler}; +// Note: The MathsCore should not be utilised in the origin sampler +// to improve compatibility #[allow(clippy::module_name_repetitions)] pub struct InMemoryOriginSampler<'h, M: MathsCore, I: Iterator> { - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, last_index: u64, location_iterator: Peekable, next_location_index: u32, @@ -39,7 +41,7 @@ impl<'h, M: MathsCore, I: Iterator> fmt::Debug for InMemoryOriginSam impl<'h, M: MathsCore, I: Iterator> InMemoryOriginSampler<'h, M, I> { #[must_use] - pub fn new(pre_sampler: OriginPreSampler, habitat: &'h InMemoryHabitat) -> Self { + pub fn new(pre_sampler: OriginPreSampler, habitat: &'h InMemoryHabitat) -> Self { Self { pre_sampler, last_index: 0_u64, @@ -61,7 +63,7 @@ impl<'h, M: MathsCore, I: Iterator> UntrustedOriginSampler<'h, M> self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.pre_sampler } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs b/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs index a61a2a877..72b08f416 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/mod.rs @@ -19,6 +19,9 @@ use pre_sampler::OriginPreSampler; #[allow(clippy::module_name_repetitions)] /// `Lineage`s produced by the sampler's iterator must have /// * unique global references +/// +/// Note: The MathsCore should not be utilised in the origin sampler +/// to improve compatibility pub trait UntrustedOriginSampler<'h, M: MathsCore>: Sized + core::fmt::Debug + core::iter::Iterator { @@ -27,7 +30,7 @@ pub trait UntrustedOriginSampler<'h, M: MathsCore>: fn habitat(&self) -> &'h Self::Habitat; - fn into_pre_sampler(self) -> OriginPreSampler; + fn into_pre_sampler(self) -> OriginPreSampler; fn full_upper_bound_size_hint(&self) -> u64; } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/non_spatial.rs b/necsim/impls/no-std/src/cogs/origin_sampler/non_spatial.rs index 8cebb7036..a22e55ad4 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/non_spatial.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/non_spatial.rs @@ -16,9 +16,11 @@ use crate::cogs::{ use super::{TrustedOriginSampler, UntrustedOriginSampler}; +// Note: The MathsCore should not be utilised in the origin sampler +// to improve compatibility #[allow(clippy::module_name_repetitions)] pub struct NonSpatialOriginSampler<'h, M: MathsCore, I: Iterator> { - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, last_index: u64, location_iterator: Peekable, next_location_index: u32, @@ -39,7 +41,7 @@ impl<'h, M: MathsCore, I: Iterator> fmt::Debug for NonSpatialOriginS impl<'h, M: MathsCore, I: Iterator> NonSpatialOriginSampler<'h, M, I> { #[must_use] - pub fn new(pre_sampler: OriginPreSampler, habitat: &'h NonSpatialHabitat) -> Self { + pub fn new(pre_sampler: OriginPreSampler, habitat: &'h NonSpatialHabitat) -> Self { Self { pre_sampler, last_index: 0_u64, @@ -61,7 +63,7 @@ impl<'h, M: MathsCore, I: Iterator> UntrustedOriginSampler<'h, M> self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.pre_sampler } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/pre_sampler.rs b/necsim/impls/no-std/src/cogs/origin_sampler/pre_sampler.rs index d2a133e71..5594c025b 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/pre_sampler.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/pre_sampler.rs @@ -1,30 +1,27 @@ use core::{ fmt, iter::Empty, - marker::PhantomData, ops::{Deref, DerefMut, RangeFrom}, }; -use necsim_core::cogs::MathsCore; use necsim_core_bond::ClosedUnitF64; use necsim_partitioning_core::partition::Partition; const INV_PHI: f64 = 6.180_339_887_498_949e-1_f64; #[allow(clippy::module_name_repetitions)] -pub struct OriginPreSampler> { +pub struct OriginPreSampler> { inner: I, proportion: ClosedUnitF64, - _marker: PhantomData, } -impl> OriginPreSampler { +impl> OriginPreSampler { pub fn get_sample_proportion(&self) -> ClosedUnitF64 { self.proportion } } -impl> Deref for OriginPreSampler { +impl> Deref for OriginPreSampler { type Target = I; fn deref(&self) -> &Self::Target { @@ -32,13 +29,13 @@ impl> Deref for OriginPreSampler { } } -impl> DerefMut for OriginPreSampler { +impl> DerefMut for OriginPreSampler { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } -impl> fmt::Debug for OriginPreSampler { +impl> fmt::Debug for OriginPreSampler { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct(stringify!(OriginPreSampler)) .field("proportion", &self.proportion) @@ -46,35 +43,33 @@ impl> fmt::Debug for OriginPreSampler OriginPreSampler> { +impl OriginPreSampler> { #[must_use] pub fn all() -> Self { Self { inner: 0.., proportion: ClosedUnitF64::one(), - _marker: PhantomData::, } } } -impl OriginPreSampler> { +impl OriginPreSampler> { #[must_use] pub fn none() -> Self { Self { inner: core::iter::empty(), proportion: ClosedUnitF64::zero(), - _marker: PhantomData::, } } } -impl> OriginPreSampler { +impl> OriginPreSampler { #[must_use] pub fn percentage( mut self, percentage: ClosedUnitF64, - ) -> OriginPreSampler> { - let inv_geometric_sample_rate = M::ln(1.0_f64 - percentage.get()).recip(); + ) -> OriginPreSampler> { + let inv_geometric_sample_rate = libm::log(1.0_f64 - percentage.get()).recip(); OriginPreSampler { proportion: self.proportion * percentage, @@ -89,27 +84,29 @@ impl> OriginPreSampler { // q = (q + INV_PHI) % 1 where q >= 0 *quasi_random += INV_PHI; - *quasi_random -= M::floor(*quasi_random); + *quasi_random -= if *quasi_random >= 1.0_f64 { + 1.0_f64 + } else { + 0.0_f64 + }; #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] - let skip = M::floor(M::ln(*quasi_random) * inv_geometric_sample_rate) as usize; + let skip = (libm::log(*quasi_random) * inv_geometric_sample_rate) as usize; self.nth(skip) }), - _marker: PhantomData::, } } pub fn partition( mut self, partition: Partition, - ) -> OriginPreSampler> { + ) -> OriginPreSampler> { let _ = self.advance_by(partition.rank() as usize); OriginPreSampler { proportion: self.proportion / partition.size(), inner: self.inner.step_by(partition.size().get() as usize), - _marker: PhantomData::, } } } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/resuming.rs b/necsim/impls/no-std/src/cogs/origin_sampler/resuming.rs index 72e6fcf1e..7b8981a5b 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/resuming.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/resuming.rs @@ -1,4 +1,4 @@ -use core::{fmt, iter::ExactSizeIterator}; +use core::{fmt, iter::ExactSizeIterator, marker::PhantomData}; use necsim_core::{ cogs::{Habitat, MathsCore}, @@ -9,6 +9,8 @@ use crate::cogs::origin_sampler::{pre_sampler::OriginPreSampler, TrustedOriginSa use super::UntrustedOriginSampler; +// Note: The MathsCore should not be utilised in the origin sampler +// to improve compatibility #[allow(clippy::module_name_repetitions)] pub struct ResumingOriginSampler< 'h, @@ -18,9 +20,10 @@ pub struct ResumingOriginSampler< I: Iterator, > { lineage_iterator: L, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, last_index: u64, habitat: &'h H, + marker: PhantomData, } impl< @@ -49,12 +52,13 @@ impl< > ResumingOriginSampler<'h, M, H, L, I> { #[must_use] - pub fn new(habitat: &'h H, pre_sampler: OriginPreSampler, lineage_iterator: L) -> Self { + pub fn new(habitat: &'h H, pre_sampler: OriginPreSampler, lineage_iterator: L) -> Self { Self { lineage_iterator, pre_sampler, last_index: 0_u64, habitat, + marker: PhantomData::, } } } @@ -75,7 +79,7 @@ impl< self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.pre_sampler } @@ -85,9 +89,9 @@ impl< clippy::cast_possible_truncation, clippy::cast_sign_loss )] - let upper_bound_size_hint = M::ceil( - (self.lineage_iterator.len() as f64) * self.pre_sampler.get_sample_proportion().get(), - ) as u64; + let upper_bound_size_hint = ((self.lineage_iterator.len() as f64) + * self.pre_sampler.get_sample_proportion().get()) + as u64; upper_bound_size_hint } diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/origin_sampler/spatially_implicit.rs index 30fe6915b..65b69fe62 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/spatially_implicit.rs @@ -9,6 +9,8 @@ use crate::cogs::{ use super::{TrustedOriginSampler, UntrustedOriginSampler}; +// Note: The MathsCore should not be utilised in the origin sampler +// to improve compatibility #[allow(clippy::module_name_repetitions)] pub struct SpatiallyImplicitOriginSampler<'h, M: MathsCore, I: Iterator> { local_iterator: NonSpatialOriginSampler<'h, M, I>, @@ -28,10 +30,7 @@ impl<'h, M: MathsCore, I: Iterator> fmt::Debug impl<'h, M: MathsCore, I: Iterator> SpatiallyImplicitOriginSampler<'h, M, I> { #[must_use] - pub fn new( - pre_sampler: OriginPreSampler, - habitat: &'h SpatiallyImplicitHabitat, - ) -> Self { + pub fn new(pre_sampler: OriginPreSampler, habitat: &'h SpatiallyImplicitHabitat) -> Self { Self { local_iterator: NonSpatialOriginSampler::new(pre_sampler, habitat.local()), habitat, @@ -50,7 +49,7 @@ impl<'h, M: MathsCore, I: Iterator> UntrustedOriginSampler<'h, M> self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.local_iterator.into_pre_sampler() } diff --git a/necsim/impls/no-std/src/decomposition/radial.rs b/necsim/impls/no-std/src/decomposition/radial.rs index 5027042ff..13ae4d0d3 100644 --- a/necsim/impls/no-std/src/decomposition/radial.rs +++ b/necsim/impls/no-std/src/decomposition/radial.rs @@ -1,5 +1,3 @@ -use libm::atan2; - use necsim_core::{ cogs::{Backup, Habitat, MathsCore}, landscape::Location, @@ -45,7 +43,7 @@ impl> Decomposition for RadialDecomposition { let neutral_y = location.y().wrapping_sub(extent.y()); #[allow(clippy::cast_precision_loss)] - let fraction = (atan2( + let fraction = (libm::atan2( (i64::from(neutral_y) - i64::from(extent.height()) / 2) as f64, (i64::from(neutral_x) - i64::from(extent.width()) / 2) as f64, ) * core::f64::consts::FRAC_1_PI diff --git a/rustcoalescence/algorithms/cuda/src/launch.rs b/rustcoalescence/algorithms/cuda/src/launch.rs index 352754b45..22ec158a6 100644 --- a/rustcoalescence/algorithms/cuda/src/launch.rs +++ b/rustcoalescence/algorithms/cuda/src/launch.rs @@ -60,7 +60,7 @@ pub fn initialise_and_simulate< args: &CudaArguments, rng: WyHash, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, diff --git a/rustcoalescence/algorithms/cuda/src/lib.rs b/rustcoalescence/algorithms/cuda/src/lib.rs index eada0dbab..1b25d2543 100644 --- a/rustcoalescence/algorithms/cuda/src/lib.rs +++ b/rustcoalescence/algorithms/cuda/src/lib.rs @@ -354,7 +354,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error> { @@ -378,7 +378,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -407,7 +407,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs index 207e1d979..43136455f 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/launch.rs @@ -49,7 +49,7 @@ pub fn initialise_and_simulate< args: GillespieArguments, rng: G, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs index 2c473fa3a..fd4c687e2 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/mod.rs @@ -66,7 +66,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error> { @@ -89,7 +89,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -117,7 +117,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs index 0fe808f96..71f3973df 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/launch.rs @@ -49,7 +49,7 @@ pub fn initialise_and_simulate< args: GillespieArguments, rng: G, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs index f9c63710a..5d7dab641 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/mod.rs @@ -46,7 +46,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error> { @@ -69,7 +69,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -98,7 +98,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs index e44ad62c9..cf351df41 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/launch.rs @@ -48,7 +48,7 @@ pub fn initialise_and_simulate< args: GillespieArguments, rng: G, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs index e78723512..a6d83bfd4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/mod.rs @@ -54,7 +54,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error> { @@ -81,7 +81,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -110,7 +110,7 @@ where args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/algorithms/independent/src/launch.rs b/rustcoalescence/algorithms/independent/src/launch.rs index 4b6da3948..8a91f9910 100644 --- a/rustcoalescence/algorithms/independent/src/launch.rs +++ b/rustcoalescence/algorithms/independent/src/launch.rs @@ -58,7 +58,7 @@ pub fn initialise_and_simulate< args: &IndependentArguments, rng: G, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, lineage_store_sampler_initialiser: L, diff --git a/rustcoalescence/algorithms/independent/src/lib.rs b/rustcoalescence/algorithms/independent/src/lib.rs index 3783060ee..7bc961d63 100644 --- a/rustcoalescence/algorithms/independent/src/lib.rs +++ b/rustcoalescence/algorithms/independent/src/lib.rs @@ -76,7 +76,7 @@ impl< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error> { @@ -99,7 +99,7 @@ impl< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -128,7 +128,7 @@ impl< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/algorithms/src/lib.rs b/rustcoalescence/algorithms/src/lib.rs index b56749b60..c706a9f5f 100644 --- a/rustcoalescence/algorithms/src/lib.rs +++ b/rustcoalescence/algorithms/src/lib.rs @@ -50,7 +50,7 @@ pub trait Algorithm< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, pause_before: Option, local_partition: &mut P, ) -> Result>::Generator>, Self::Error>; @@ -64,7 +64,7 @@ pub trait Algorithm< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, resume_after: Option, pause_before: Option, @@ -80,7 +80,7 @@ pub trait Algorithm< args: Self::Arguments, rng: >::Generator, scenario: O, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, lineages: L, restart_at: PositiveF64, fixup_strategy: RestartFixUpStrategy, diff --git a/rustcoalescence/scenarios/src/almost_infinite.rs b/rustcoalescence/scenarios/src/almost_infinite.rs index e908c497c..7327640eb 100644 --- a/rustcoalescence/scenarios/src/almost_infinite.rs +++ b/rustcoalescence/scenarios/src/almost_infinite.rs @@ -104,7 +104,7 @@ impl + Samples> Scenario fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, (radius,): Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where diff --git a/rustcoalescence/scenarios/src/lib.rs b/rustcoalescence/scenarios/src/lib.rs index 05bd7a7ac..9d78ed422 100644 --- a/rustcoalescence/scenarios/src/lib.rs +++ b/rustcoalescence/scenarios/src/lib.rs @@ -78,7 +78,7 @@ pub trait Scenario>: Sized + ScenarioParameters { fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, auxiliary: Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where diff --git a/rustcoalescence/scenarios/src/non_spatial.rs b/rustcoalescence/scenarios/src/non_spatial.rs index 07df10df9..8e4e5a0a9 100644 --- a/rustcoalescence/scenarios/src/non_spatial.rs +++ b/rustcoalescence/scenarios/src/non_spatial.rs @@ -95,7 +95,7 @@ impl + Samples> Scenario for NonSpati fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, _auxiliary: Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs index f19cb079c..09d0ef43f 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/map.rs @@ -130,7 +130,7 @@ impl + Samples> Scenario fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, _auxiliary: Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where diff --git a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs index e19aade26..2faaa8e3c 100644 --- a/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs +++ b/rustcoalescence/scenarios/src/spatially_explicit/turnover/uniform.rs @@ -128,7 +128,7 @@ impl + Samples> Scenario fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, _auxiliary: Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where diff --git a/rustcoalescence/scenarios/src/spatially_implicit.rs b/rustcoalescence/scenarios/src/spatially_implicit.rs index 4933bd6f7..276fddea7 100644 --- a/rustcoalescence/scenarios/src/spatially_implicit.rs +++ b/rustcoalescence/scenarios/src/spatially_implicit.rs @@ -114,7 +114,7 @@ impl + Samples + Samples> Sce fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, _auxiliary: Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'h, I> where From ff8b633bc1d0945572975005e31994239effcd29 Mon Sep 17 00:00:00 2001 From: Juniper Langenstein Date: Sat, 13 Aug 2022 10:04:25 +0000 Subject: [PATCH 20/21] Fixed new 1.63 lints --- necsim/impls/no-std/src/alias/mod.rs | 1 + necsim/impls/no-std/src/alias/packed.rs | 1 + .../src/cogs/active_lineage_sampler/alias/individual/mod.rs | 4 ++++ .../cogs/active_lineage_sampler/alias/individual/sampler.rs | 1 + .../src/cogs/active_lineage_sampler/alias/location/mod.rs | 4 ++++ .../cogs/active_lineage_sampler/alias/location/sampler.rs | 1 + .../active_lineage_sampler/alias/sampler/indexed/mod.rs | 1 + .../cogs/active_lineage_sampler/alias/sampler/stack/mod.rs | 1 + .../no-std/src/cogs/active_lineage_sampler/classical/mod.rs | 3 +++ .../src/cogs/active_lineage_sampler/classical/sampler.rs | 1 + .../independent/event_time_sampler/poisson.rs | 1 + .../src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs | 1 + .../src/cogs/dispersal_sampler/in_memory/alias/mod.rs | 3 +++ .../dispersal_sampler/in_memory/packed_alias/dispersal.rs | 1 + .../cogs/dispersal_sampler/in_memory/packed_alias/mod.rs | 5 +++++ .../in_memory/separable_alias/dispersal.rs | 2 ++ .../cogs/dispersal_sampler/in_memory/separable_alias/mod.rs | 3 +++ .../no-std/src/cogs/dispersal_sampler/spatially_implicit.rs | 6 ++++++ .../impls/no-std/src/cogs/distribution/poisson_inversion.rs | 1 + .../no-std/src/cogs/distribution/std_normal2d_box_muller.rs | 1 + necsim/impls/no-std/src/cogs/rng/simple.rs | 2 ++ rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs | 1 + rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs | 1 + rustcoalescence/algorithms/cuda/src/initialiser/mod.rs | 1 + rustcoalescence/algorithms/cuda/src/initialiser/resume.rs | 1 + .../gillespie/src/event_skipping/initialiser/fixup.rs | 1 + .../gillespie/src/event_skipping/initialiser/genesis.rs | 1 + .../gillespie/src/event_skipping/initialiser/mod.rs | 1 + .../gillespie/src/event_skipping/initialiser/resume.rs | 1 + .../gillespie/src/gillespie/classical/initialiser/fixup.rs | 1 + .../src/gillespie/classical/initialiser/genesis.rs | 1 + .../gillespie/src/gillespie/classical/initialiser/mod.rs | 1 + .../gillespie/src/gillespie/classical/initialiser/resume.rs | 1 + .../gillespie/src/gillespie/turnover/initialiser/fixup.rs | 1 + .../gillespie/src/gillespie/turnover/initialiser/genesis.rs | 1 + .../gillespie/src/gillespie/turnover/initialiser/mod.rs | 1 + .../gillespie/src/gillespie/turnover/initialiser/resume.rs | 1 + .../algorithms/independent/src/initialiser/fixup.rs | 1 + .../algorithms/independent/src/initialiser/genesis.rs | 1 + .../algorithms/independent/src/initialiser/mod.rs | 1 + .../algorithms/independent/src/initialiser/resume.rs | 1 + rustcoalescence/scenarios/src/spatially_implicit.rs | 3 +++ 42 files changed, 67 insertions(+) diff --git a/necsim/impls/no-std/src/alias/mod.rs b/necsim/impls/no-std/src/alias/mod.rs index 437c52346..54707702a 100644 --- a/necsim/impls/no-std/src/alias/mod.rs +++ b/necsim/impls/no-std/src/alias/mod.rs @@ -93,6 +93,7 @@ impl AliasMethodSampler { Self { Us, Es, Ks } } + #[allow(clippy::trait_duplication_in_bounds)] #[debug_ensures(self.Es.contains(&ret), "returns one of the weighted events")] pub fn sample_event< M: MathsCore, diff --git a/necsim/impls/no-std/src/alias/packed.rs b/necsim/impls/no-std/src/alias/packed.rs index f7019c08d..d9f162d6a 100644 --- a/necsim/impls/no-std/src/alias/packed.rs +++ b/necsim/impls/no-std/src/alias/packed.rs @@ -106,6 +106,7 @@ impl AliasMethodSamplerAtom { } #[allow(clippy::no_effect_underscore_binding)] + #[allow(clippy::trait_duplication_in_bounds)] #[debug_requires(!alias_samplers.is_empty(), "alias_samplers is non-empty")] #[debug_ensures( old(alias_samplers).iter().map(|s| s.e).any(|e| e == ret), diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs index 81cf824af..f95a1f541 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/mod.rs @@ -20,6 +20,7 @@ use super::sampler::stack::DynamicAliasMethodStackSampler; mod sampler; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub struct IndividualAliasActiveLineageSampler< M: MathsCore, H: Habitat, @@ -44,6 +45,7 @@ pub struct IndividualAliasActiveLineageSampler< marker: PhantomData<(M, H, G, S, X, D, C, T, N, E, I)>, } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, H: Habitat, @@ -155,6 +157,7 @@ impl< } } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, H: Habitat, @@ -181,6 +184,7 @@ impl< } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs index 722a6ef81..c8488aac7 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/individual/sampler.rs @@ -15,6 +15,7 @@ use necsim_core_bond::{NonNegativeF64, PositiveF64}; use super::IndividualAliasActiveLineageSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs index 8956c2e8b..3b096bbba 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/mod.rs @@ -23,6 +23,7 @@ use super::sampler::indexed::DynamicAliasMethodIndexedSampler; mod sampler; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub struct LocationAliasActiveLineageSampler< M: MathsCore, H: Habitat, @@ -47,6 +48,7 @@ pub struct LocationAliasActiveLineageSampler< marker: PhantomData<(M, H, G, S, X, D, C, T, N, E, I)>, } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, H: Habitat, @@ -205,6 +207,7 @@ impl< } } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, H: Habitat, @@ -231,6 +234,7 @@ impl< } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs index 44c958c08..4e7bd0b47 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/location/sampler.rs @@ -17,6 +17,7 @@ use crate::cogs::event_sampler::gillespie::GillespieEventSampler; use super::LocationAliasActiveLineageSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs index 19d5ac095..063ec393b 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/indexed/mod.rs @@ -193,6 +193,7 @@ impl DynamicAliasMethodIndexedSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } + #[allow(clippy::trait_duplication_in_bounds)] pub fn sample_pop< M: MathsCore, G: Rng + Samples + Samples + Samples, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs index 4f7fc1475..5eec48515 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/alias/sampler/stack/mod.rs @@ -130,6 +130,7 @@ impl DynamicAliasMethodStackSampler { self.groups.iter().flat_map(RejectionSamplingGroup::iter) } + #[allow(clippy::trait_duplication_in_bounds)] pub fn sample_pop< M: MathsCore, G: Rng + Samples + Samples + Samples, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs index a70d0b65e..654d2696c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/mod.rs @@ -16,6 +16,7 @@ use crate::cogs::{ mod sampler; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] #[derive(Debug)] pub struct ClassicalActiveLineageSampler< M: MathsCore, @@ -33,6 +34,7 @@ pub struct ClassicalActiveLineageSampler< _marker: PhantomData<(M, H, G, S, X, D, N, I)>, } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, H: Habitat, @@ -123,6 +125,7 @@ impl< } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs index 2caa6dbea..188c58c3c 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/classical/sampler.rs @@ -23,6 +23,7 @@ use crate::cogs::{ use super::ClassicalActiveLineageSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs index 22388e81b..ef29cd4c7 100644 --- a/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs +++ b/necsim/impls/no-std/src/cogs/active_lineage_sampler/independent/event_time_sampler/poisson.rs @@ -27,6 +27,7 @@ impl PoissonEventTimeSampler { } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl< M: MathsCore, diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs index 2970e3c62..3441c0827 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/dispersal.rs @@ -8,6 +8,7 @@ use necsim_core::{ use super::InMemoryAliasDispersalSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> DispersalSampler for InMemoryAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs index 559ba2d23..18a65c1a4 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/alias/mod.rs @@ -19,6 +19,7 @@ use crate::{ mod dispersal; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] #[derive(Debug)] pub struct InMemoryAliasDispersalSampler< M: MathsCore, @@ -29,6 +30,7 @@ pub struct InMemoryAliasDispersalSampler< marker: PhantomData<(M, H, G)>, } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> InMemoryDispersalSampler for InMemoryAliasDispersalSampler @@ -83,6 +85,7 @@ impl, G: Rng + Samples + Samples, G: Rng + Samples + Samples> Backup for InMemoryAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs index 47bd76cd4..07eef5178 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/dispersal.rs @@ -12,6 +12,7 @@ use crate::alias::packed::AliasMethodSamplerAtom; use super::InMemoryPackedAliasDispersalSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> DispersalSampler for InMemoryPackedAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs index 0a07e3ad0..108294c73 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/packed_alias/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::trait_duplication_in_bounds)] + use alloc::{boxed::Box, vec::Vec}; use core::{marker::PhantomData, ops::Range}; use necsim_core_bond::NonNegativeF64; @@ -57,6 +59,7 @@ pub struct InMemoryPackedAliasDispersalSampler< marker: PhantomData<(M, H, G)>, } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> InMemoryDispersalSampler for InMemoryPackedAliasDispersalSampler @@ -119,6 +122,7 @@ impl, G: Rng + Samples + Samples, G: Rng + Samples + Samples> core::fmt::Debug for InMemoryPackedAliasDispersalSampler { @@ -137,6 +141,7 @@ impl, G: Rng + Samples + Samples, G: Rng + Samples + Samples> Backup for InMemoryPackedAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs index e4d99a7a2..5a6b9af31 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/dispersal.rs @@ -10,6 +10,7 @@ use necsim_core_bond::ClosedUnitF64; use super::InMemorySeparableAliasDispersalSampler; +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> DispersalSampler for InMemorySeparableAliasDispersalSampler @@ -38,6 +39,7 @@ impl, G: Rng + Samples + Samples, G: Rng + Samples + Samples> SeparableDispersalSampler for InMemorySeparableAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs index 0610d8920..d2d15b0dd 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/in_memory/separable_alias/mod.rs @@ -19,6 +19,7 @@ use crate::{ mod dispersal; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] #[derive(Debug)] pub struct InMemorySeparableAliasDispersalSampler< M: MathsCore, @@ -30,6 +31,7 @@ pub struct InMemorySeparableAliasDispersalSampler< _marker: PhantomData<(M, H, G)>, } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl, G: Rng + Samples + Samples> InMemoryDispersalSampler for InMemorySeparableAliasDispersalSampler @@ -118,6 +120,7 @@ impl, G: Rng + Samples + Samples, G: Rng + Samples + Samples> Backup for InMemorySeparableAliasDispersalSampler diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs index edfdbf4e3..e8cede3e0 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/spatially_implicit.rs @@ -1,3 +1,5 @@ +#![allow(clippy::trait_duplication_in_bounds)] + use necsim_core::{ cogs::{ distribution::{Bernoulli, IndexU64}, @@ -28,6 +30,7 @@ pub struct SpatiallyImplicitDispersalSampler< local_migration_probability_per_generation: PositiveUnitF64, } +#[allow(clippy::trait_duplication_in_bounds)] impl + Samples + Samples> SpatiallyImplicitDispersalSampler { @@ -41,6 +44,7 @@ impl + Samples + Samples> } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl + Samples + Samples> Backup for SpatiallyImplicitDispersalSampler @@ -55,6 +59,7 @@ impl + Samples + Samples> Bac } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl + Samples + Samples> DispersalSampler, G> @@ -98,6 +103,7 @@ impl + Samples + Samples> } } +#[allow(clippy::trait_duplication_in_bounds)] #[contract_trait] impl + Samples + Samples> SeparableDispersalSampler, G> diff --git a/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs b/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs index 416aae8e5..aa31b655d 100644 --- a/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs +++ b/necsim/impls/no-std/src/cogs/distribution/poisson_inversion.rs @@ -7,6 +7,7 @@ use necsim_core_bond::NonNegativeF64; #[allow(clippy::module_name_repetitions)] pub struct PoissonInverseTransformOrNormalSampler; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, R: RngCore, diff --git a/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs b/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs index ff8ab645f..6b3596a8f 100644 --- a/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs +++ b/necsim/impls/no-std/src/cogs/distribution/std_normal2d_box_muller.rs @@ -7,6 +7,7 @@ use necsim_core::cogs::{ pub struct StandardNormal2DBoxMullerSampler; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, R: RngCore, diff --git a/necsim/impls/no-std/src/cogs/rng/simple.rs b/necsim/impls/no-std/src/cogs/rng/simple.rs index 972af8c6f..4bf49ee77 100644 --- a/necsim/impls/no-std/src/cogs/rng/simple.rs +++ b/necsim/impls/no-std/src/cogs/rng/simple.rs @@ -235,6 +235,7 @@ impl DistributionSampler } } +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, R: RngCore, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs index 115791b4f..e609816bd 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/fixup.rs @@ -43,6 +43,7 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs index 96055414b..d932f189d 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/genesis.rs @@ -26,6 +26,7 @@ use super::CudaLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs index 7bebde14e..bd624a7b0 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/mod.rs @@ -29,6 +29,7 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub trait CudaLineageStoreSampleInitialiser< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs index 936bd6d65..649e1687e 100644 --- a/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs +++ b/rustcoalescence/algorithms/cuda/src/initialiser/resume.rs @@ -32,6 +32,7 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs index 2fed583c6..0e361bd03 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/fixup.rs @@ -48,6 +48,7 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs index b464810b7..9f5ea65d1 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/genesis.rs @@ -25,6 +25,7 @@ use super::EventSkippingLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs index 61e2f386f..99e617f7a 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/mod.rs @@ -22,6 +22,7 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub trait EventSkippingLineageStoreSampleInitialiser< M: MathsCore, G: Rng + Samples + Samples + Samples, diff --git a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs index aa93e90d6..ee7099fc1 100644 --- a/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/event_skipping/initialiser/resume.rs @@ -32,6 +32,7 @@ pub struct ResumeInitialiser> { } #[allow(clippy::type_complexity)] +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs index 7d052e903..e0b90e2f4 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/fixup.rs @@ -46,6 +46,7 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs index 1528cf6ba..b6cd74ee8 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/genesis.rs @@ -20,6 +20,7 @@ use super::ClassicalLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, G: Rng + Samples + Samples + Samples, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs index 6ef6014ba..dd7c0e210 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/mod.rs @@ -22,6 +22,7 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub trait ClassicalLineageStoreSampleInitialiser< M: MathsCore, G: Rng + Samples + Samples, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs index d7ab6eceb..a715c7fc0 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/classical/initialiser/resume.rs @@ -26,6 +26,7 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs index aa6d3d57a..efffb65ff 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/fixup.rs @@ -44,6 +44,7 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs index 6f9ae9605..91e3b3dea 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/genesis.rs @@ -21,6 +21,7 @@ use super::GillespieLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs index cb8fd7bc2..7ed78ef26 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/mod.rs @@ -20,6 +20,7 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub trait GillespieLineageStoreSampleInitialiser< M: MathsCore, G: Rng + Samples + Samples, diff --git a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs index 281635014..5ed8fae85 100644 --- a/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs +++ b/rustcoalescence/algorithms/gillespie/src/gillespie/turnover/initialiser/resume.rs @@ -27,6 +27,7 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs index 76ecab2b0..d0f3e70d9 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/fixup.rs @@ -39,6 +39,7 @@ pub struct FixUpInitialiser> { pub fixup_strategy: RestartFixUpStrategy, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs index 730c5e3ad..ac01ccb5d 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/genesis.rs @@ -22,6 +22,7 @@ use super::IndependentLineageStoreSampleInitialiser; #[allow(clippy::module_name_repetitions)] pub struct GenesisInitialiser; +#[allow(clippy::trait_duplication_in_bounds)] impl< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs index e599e6501..d3ec398b8 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/mod.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/mod.rs @@ -25,6 +25,7 @@ pub mod genesis; pub mod resume; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub trait IndependentLineageStoreSampleInitialiser< M: MathsCore, G: Rng diff --git a/rustcoalescence/algorithms/independent/src/initialiser/resume.rs b/rustcoalescence/algorithms/independent/src/initialiser/resume.rs index bccdd8fab..8ca52ef60 100644 --- a/rustcoalescence/algorithms/independent/src/initialiser/resume.rs +++ b/rustcoalescence/algorithms/independent/src/initialiser/resume.rs @@ -28,6 +28,7 @@ pub struct ResumeInitialiser> { pub resume_after: Option, } +#[allow(clippy::trait_duplication_in_bounds)] impl< L: ExactSizeIterator, M: MathsCore, diff --git a/rustcoalescence/scenarios/src/spatially_implicit.rs b/rustcoalescence/scenarios/src/spatially_implicit.rs index 276fddea7..f46865daa 100644 --- a/rustcoalescence/scenarios/src/spatially_implicit.rs +++ b/rustcoalescence/scenarios/src/spatially_implicit.rs @@ -25,6 +25,7 @@ use necsim_impls_no_std::{ use crate::{Scenario, ScenarioParameters}; #[allow(clippy::module_name_repetitions)] +#[allow(clippy::trait_duplication_in_bounds)] pub struct SpatiallyImplicitScenario< M: MathsCore, G: Rng + Samples + Samples, @@ -47,6 +48,7 @@ pub struct SpatiallyImplicitArguments { pub migration_probability_per_generation: PositiveUnitF64, } +#[allow(clippy::trait_duplication_in_bounds)] impl + Samples + Samples> ScenarioParameters for SpatiallyImplicitScenario { @@ -54,6 +56,7 @@ impl + Samples + Samples> Sce type Error = !; } +#[allow(clippy::trait_duplication_in_bounds)] impl + Samples + Samples> Scenario for SpatiallyImplicitScenario { From 039333ea8d8d73d54e25d31e0038ca7214cf9cb2 Mon Sep 17 00:00:00 2001 From: Juniper Langenstein Date: Wed, 28 Dec 2022 13:33:06 +0000 Subject: [PATCH 21/21] Fixed new WrappingHabitat for improved Rng --- .../no-std/src/cogs/dispersal_sampler/wrapping_noise.rs | 4 ++-- .../impls/no-std/src/cogs/origin_sampler/wrapping_noise.rs | 6 +++--- rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs | 5 ++++- rustcoalescence/scenarios/src/wrapping_noise.rs | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs index 09e86bd3a..399b75443 100644 --- a/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/dispersal_sampler/wrapping_noise.rs @@ -1,8 +1,8 @@ use necsim_core::{ cogs::{ distribution::{Bernoulli, Normal2D}, - Backup, DispersalSampler, DistributionSampler, Habitat, MathsCore, Rng, - Distribution, SeparableDispersalSampler, + Backup, DispersalSampler, Distribution, DistributionSampler, Habitat, MathsCore, Rng, + SeparableDispersalSampler, }, landscape::Location, }; diff --git a/necsim/impls/no-std/src/cogs/origin_sampler/wrapping_noise.rs b/necsim/impls/no-std/src/cogs/origin_sampler/wrapping_noise.rs index d2412c3ac..fff2c7fb0 100644 --- a/necsim/impls/no-std/src/cogs/origin_sampler/wrapping_noise.rs +++ b/necsim/impls/no-std/src/cogs/origin_sampler/wrapping_noise.rs @@ -16,7 +16,7 @@ use crate::cogs::{ #[allow(clippy::module_name_repetitions)] pub struct WrappingNoiseOriginSampler<'h, M: MathsCore, I: Iterator> { - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, last_index: u64, location_iterator: Peekable, habitat: &'h WrappingNoiseHabitat, @@ -40,7 +40,7 @@ impl<'h, M: MathsCore, I: Iterator> fmt::Debug impl<'h, M: MathsCore, I: Iterator> WrappingNoiseOriginSampler<'h, M, I> { #[must_use] pub fn new( - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, habitat: &'h WrappingNoiseHabitat, sample: LandscapeExtent, ) -> Self { @@ -65,7 +65,7 @@ impl<'h, M: MathsCore, I: Iterator> UntrustedOriginSampler<'h, M> self.habitat } - fn into_pre_sampler(self) -> OriginPreSampler { + fn into_pre_sampler(self) -> OriginPreSampler { self.pre_sampler } diff --git a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs index 8a342b4a4..e869cff72 100644 --- a/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs +++ b/rustcoalescence/algorithms/cuda/cpu-kernel/src/link.rs @@ -317,7 +317,10 @@ link_kernel!( necsim_impls_cuda::cogs::maths::NvptxMathsCore, necsim_impls_cuda::cogs::rng::CudaRng< necsim_impls_cuda::cogs::maths::NvptxMathsCore, - necsim_impls_no_std::cogs::rng::wyhash::WyHash, + necsim_impls_no_std::cogs::rng::simple::SimpleRng< + necsim_impls_cuda::cogs::maths::NvptxMathsCore, + necsim_impls_no_std::cogs::rng::wyhash::WyHash, + >, >, >, necsim_impls_no_std::cogs::turnover_rate::uniform::UniformTurnoverRate, diff --git a/rustcoalescence/scenarios/src/wrapping_noise.rs b/rustcoalescence/scenarios/src/wrapping_noise.rs index a83b1277a..71835de9f 100644 --- a/rustcoalescence/scenarios/src/wrapping_noise.rs +++ b/rustcoalescence/scenarios/src/wrapping_noise.rs @@ -130,7 +130,7 @@ where fn sample_habitat<'h, I: Iterator>( habitat: &'h Self::Habitat, - pre_sampler: OriginPreSampler, + pre_sampler: OriginPreSampler, (sample,): Self::OriginSamplerAuxiliary, ) -> Self::OriginSampler<'_, I> where