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
use necsim_impls_std::event_log::recorder::EventLogConfig;
use necsim_partitioning_core::reporter::ReporterContext;
use tiny_keccak::{Hasher, Keccak};

use rustcoalescence_algorithms::{
    result::SimulationOutcome as AlgorithmOutcome, AlgorithmDispatch,
};

use necsim_core::{
    cogs::{MathsCore, RngCore, SeedableRng},
    reporter::Reporter,
};
use necsim_core_bond::NonNegativeF64;

use rustcoalescence_scenarios::{Scenario, ScenarioCogs};

use crate::{
    args::config::{
        partitioning::Partitioning,
        rng::{Base32RngState, Rng as RngArgs},
        sample::Sample,
    },
    cli::simulate::parse,
};

use super::{
    super::super::{BufferingSimulateArgsBuilder, SimulationOutcome},
    info,
};

#[allow(clippy::too_many_arguments)]
pub(super) fn dispatch<
    M: MathsCore,
    G: RngCore<M>,
    A: AlgorithmDispatch<M, G, O, R>,
    O: Scenario<M, G>,
    R: Reporter,
    P: ReporterContext<Reporter = R>,
>(
    partitioning: Partitioning,
    event_log: Option<EventLogConfig>,
    reporter_context: P,

    sample: Sample,
    algorithm_args: A::Arguments,
    scenario: ScenarioCogs<M, G, O>,
    pause_before: Option<NonNegativeF64>,

    ron_args: &str,
    normalised_args: &mut BufferingSimulateArgsBuilder,
) -> anyhow::Result<SimulationOutcome>
where
    Result<AlgorithmOutcome<M, G>, A::Error>: anyhow::Context<AlgorithmOutcome<M, G>, A::Error>,
{
    let rng: G = match parse::rng::parse_and_normalise(
        ron_args,
        normalised_args,
        partitioning.get_logical_partition_size::<M, G, O, R, A>(&algorithm_args),
    )? {
        RngArgs::Seed(seed) => SeedableRng::seed_from_u64(seed),
        RngArgs::Sponge(bytes) => {
            let mut seed = G::Seed::default();

            let mut sponge = Keccak::v256();
            sponge.update(&bytes);
            sponge.finalize(seed.as_mut());

            RngCore::from_seed(seed)
        },
        RngArgs::State(state) => state.into(),
    };

    let result = info::dispatch::<M, G, A, O, R, P>(
        partitioning,
        event_log,
        reporter_context,
        sample,
        rng,
        scenario,
        algorithm_args,
        pause_before,
        normalised_args,
    )?;

    match result {
        AlgorithmOutcome::Done { time, steps } => Ok(SimulationOutcome::Done { time, steps }),
        AlgorithmOutcome::Paused {
            time,
            steps,
            lineages,
            rng: paused_rng,
            ..
        } => {
            normalised_args.rng(&RngArgs::State(Base32RngState::from(paused_rng)));

            Ok(SimulationOutcome::Paused {
                time,
                steps,
                lineages,
            })
        },
    }
}