1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use core::marker::PhantomData;

use crate::cogs::{
    CoalescenceSampler, DispersalSampler, EmigrationExit, EventSampler, Habitat, LineageStore,
    MathsCore, RngCore, SpeciationProbability, TurnoverRate,
};

#[repr(C)]
pub struct PartialSimulation<
    M: MathsCore,
    H: Habitat<M>,
    G: RngCore<M>,
    S: LineageStore<M, H>,
    X: EmigrationExit<M, H, G, S>,
    D: DispersalSampler<M, H, G>,
    C: CoalescenceSampler<M, H, S>,
    T: TurnoverRate<M, H>,
    N: SpeciationProbability<M, H>,
    E: EventSampler<M, H, G, S, X, D, C, T, N>,
> {
    pub maths: PhantomData<M>,
    pub habitat: H,
    pub lineage_store: S,
    pub dispersal_sampler: D,
    pub coalescence_sampler: C,
    pub turnover_rate: T,
    pub speciation_probability: N,
    pub emigration_exit: X,
    pub event_sampler: E,
    // priv
    _rng: PhantomData<G>,
}

impl<
        M: MathsCore,
        H: Habitat<M>,
        G: RngCore<M>,
        S: LineageStore<M, H>,
        X: EmigrationExit<M, H, G, S>,
        D: DispersalSampler<M, H, G>,
        C: CoalescenceSampler<M, H, S>,
        T: TurnoverRate<M, H>,
        N: SpeciationProbability<M, H>,
        E: EventSampler<M, H, G, S, X, D, C, T, N>,
    > PartialSimulation<M, H, G, S, X, D, C, T, N, E>
{
    #[inline]
    pub fn with_split_event_sampler<
        Q,
        F: FnOnce(&E, &super::event_sampler::PartialSimulation<M, H, G, S, X, D, C, T, N>) -> Q,
    >(
        &self,
        func: F,
    ) -> Q {
        // Cast &self to a &PartialSimulation without the event sampler
        // This is only safe as PartialSimulation's type and layout is a prefix
        //  subsequence of Self's type and layout
        let partial_simulation = unsafe {
            &*core::ptr::from_ref(self).cast::<super::event_sampler::PartialSimulation<
                M,
                H,
                G,
                S,
                X,
                D,
                C,
                T,
                N,
            >>()
        };

        func(&self.event_sampler, partial_simulation)
    }

    #[inline]
    pub fn with_mut_split_event_sampler<
        Q,
        F: FnOnce(
            &mut E,
            &mut super::event_sampler::PartialSimulation<M, H, G, S, X, D, C, T, N>,
        ) -> Q,
    >(
        &mut self,
        func: F,
    ) -> Q {
        // Cast &mut self to a &mut PartialSimulation without the event sampler
        // This is only safe as PartialSimulation's type and layout is a prefix
        //  subsequence of Self's type and layout
        let partial_simulation = unsafe {
            &mut *core::ptr::from_mut(self).cast::<super::event_sampler::PartialSimulation<
                M,
                H,
                G,
                S,
                X,
                D,
                C,
                T,
                N,
            >>()
        };

        func(&mut self.event_sampler, partial_simulation)
    }
}