Skip to content

Commit af18f9b

Browse files
committed
(ml5717) Added HabitatToU64Injection
1 parent 7fe0ff5 commit af18f9b

File tree

5 files changed

+67
-25
lines changed

5 files changed

+67
-25
lines changed

necsim-core/src/cogs/habitat.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,17 @@ pub trait Habitat: core::fmt::Debug {
2727
#[debug_requires(self.get_extent().contains(location), "location is inside habitat extent")]
2828
fn get_habitat_at_location(&self, location: &Location) -> u32;
2929
}
30+
31+
#[allow(clippy::inline_always, clippy::inline_fn_without_body)]
32+
#[allow(clippy::module_name_repetitions)]
33+
#[contract_trait]
34+
pub trait HabitatToU64Injection: Habitat {
35+
#[must_use]
36+
#[debug_requires(self.get_extent().contains(location), "location is inside habitat extent")]
37+
#[debug_requires(index_at_location < self.get_habitat_at_location(location) as usize)]
38+
fn map_indexed_location_to_u64_injective(
39+
&self,
40+
location: &Location,
41+
index_at_location: usize,
42+
) -> u64;
43+
}

necsim-core/src/cogs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod habitat;
2-
pub use habitat::Habitat;
2+
pub use habitat::{Habitat, HabitatToU64Injection};
33

44
mod rng;
55
pub use rng::{PrimeableRng, RngCore, RngSampler};

necsim-impls-no-std/src/cogs/active_lineage_sampler/independent/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::marker::PhantomData;
22

33
use necsim_core::cogs::{
4-
DispersalSampler, Habitat, IncoherentLineageStore, LineageReference, PrimeableRng,
4+
DispersalSampler, HabitatToU64Injection, IncoherentLineageStore, LineageReference, PrimeableRng,
55
};
66

77
mod sampler;
@@ -15,7 +15,7 @@ mod sampler;
1515
#[cfg_attr(feature = "cuda", r2cBound(S: rust_cuda::common::RustToCuda))]
1616
#[derive(Debug)]
1717
pub struct IndependentActiveLineageSampler<
18-
H: Habitat,
18+
H: HabitatToU64Injection,
1919
G: PrimeableRng<Prime = [u8; 16]>,
2020
D: DispersalSampler<H, G>,
2121
R: LineageReference<H>,
@@ -27,7 +27,7 @@ pub struct IndependentActiveLineageSampler<
2727
}
2828

2929
impl<
30-
H: Habitat,
30+
H: HabitatToU64Injection,
3131
G: PrimeableRng<Prime = [u8; 16]>,
3232
D: DispersalSampler<H, G>,
3333
R: LineageReference<H>,
@@ -46,7 +46,7 @@ impl<
4646
}
4747

4848
impl<
49-
H: Habitat,
49+
H: HabitatToU64Injection,
5050
G: PrimeableRng<Prime = [u8; 16]>,
5151
D: DispersalSampler<H, G>,
5252
R: LineageReference<H>,

necsim-impls-no-std/src/cogs/active_lineage_sampler/independent/sampler.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use float_next_after::NextAfter;
22

33
use necsim_core::cogs::{
4-
ActiveLineageSampler, DispersalSampler, Habitat, IncoherentLineageStore, LineageReference,
5-
PrimeableRng,
4+
ActiveLineageSampler, DispersalSampler, HabitatToU64Injection, IncoherentLineageStore,
5+
LineageReference, PrimeableRng,
66
};
77
use necsim_core::intrinsics::{exp, floor};
88
use necsim_core::landscape::Location;
@@ -15,7 +15,7 @@ use super::IndependentActiveLineageSampler;
1515

1616
#[contract_trait]
1717
impl<
18-
H: Habitat,
18+
H: HabitatToU64Injection,
1919
G: PrimeableRng<Prime = [u8; 16]>,
2020
D: DispersalSampler<H, G>,
2121
R: LineageReference<H>,
@@ -88,23 +88,21 @@ impl<
8888
let mut time_step = floor(time / delta_t) as u64 + 1;
8989

9090
loop {
91-
let location_bytes_x = lineage_location.x().to_le_bytes();
92-
let location_bytes_y = lineage_location.y().to_le_bytes();
93-
let location_bytes_i = lineage_index_at_location.to_le_bytes();
91+
let location_bytes = simulation
92+
.habitat
93+
.map_indexed_location_to_u64_injective(&lineage_location, lineage_index_at_location)
94+
.to_le_bytes();
9495
let time_step_bytes = time_step.to_le_bytes();
9596

96-
// TODO: This should be more automatic, similar to Hash -> it should also NOT use simple xor
97-
// TODO: It would be much better if we could get a location index here, i.e. bijection from
98-
// u64 to Location & index_at_location (this would require a cumulative habitat)
9997
rng.prime_with([
100-
location_bytes_x[0] ^ location_bytes_i[7],
101-
location_bytes_x[1] ^ location_bytes_i[6],
102-
location_bytes_x[2] ^ location_bytes_i[5],
103-
location_bytes_x[3] ^ location_bytes_i[4],
104-
location_bytes_y[0] ^ location_bytes_i[3],
105-
location_bytes_y[1] ^ location_bytes_i[2],
106-
location_bytes_y[2] ^ location_bytes_i[1],
107-
location_bytes_y[3] ^ location_bytes_i[0],
98+
location_bytes[0],
99+
location_bytes[1],
100+
location_bytes[2],
101+
location_bytes[3],
102+
location_bytes[4],
103+
location_bytes[5],
104+
location_bytes[6],
105+
location_bytes[7],
108106
time_step_bytes[0],
109107
time_step_bytes[1],
110108
time_step_bytes[2],

necsim-impls-no-std/src/cogs/habitat/in_memory.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use array2d::Array2D;
22

3-
use necsim_core::cogs::Habitat;
3+
use necsim_core::cogs::{Habitat, HabitatToU64Injection};
44
use necsim_core::landscape::{LandscapeExtent, Location};
55

66
#[allow(clippy::module_name_repetitions)]
@@ -9,6 +9,8 @@ use necsim_core::landscape::{LandscapeExtent, Location};
99
pub struct InMemoryHabitat {
1010
#[cfg_attr(feature = "cuda", r2cEmbed)]
1111
habitat: Array2D<u32>,
12+
#[cfg_attr(feature = "cuda", r2cEmbed)]
13+
u64_injection: Array2D<u64>,
1214
}
1315

1416
#[contract_trait]
@@ -38,6 +40,19 @@ impl Habitat for InMemoryHabitat {
3840
}
3941
}
4042

43+
#[contract_trait]
44+
impl HabitatToU64Injection for InMemoryHabitat {
45+
#[must_use]
46+
fn map_indexed_location_to_u64_injective(
47+
&self,
48+
location: &Location,
49+
index_at_location: usize,
50+
) -> u64 {
51+
self.u64_injection[(location.y() as usize, location.x() as usize)]
52+
+ index_at_location as u64
53+
}
54+
}
55+
4156
impl InMemoryHabitat {
4257
#[must_use]
4358
#[debug_ensures(
@@ -46,7 +61,22 @@ impl InMemoryHabitat {
4661
"habitat extent has the dimension of the habitat array"
4762
)]
4863
pub fn new(habitat: Array2D<u32>) -> Self {
49-
#[allow(clippy::cast_possible_truncation)]
50-
Self { habitat }
64+
let mut index_acc = 0_u64;
65+
66+
let u64_injection = Array2D::from_iter_row_major(
67+
habitat.elements_row_major_iter().map(|h| {
68+
let injection = index_acc;
69+
index_acc += u64::from(*h);
70+
injection
71+
}),
72+
habitat.num_rows(),
73+
habitat.num_columns(),
74+
)
75+
.unwrap();
76+
77+
Self {
78+
habitat,
79+
u64_injection,
80+
}
5181
}
5282
}

0 commit comments

Comments
 (0)