use rayon::prelude::*;
pub mod adapters;
pub mod generators;
pub trait VectorGenerator {
type Vector;
fn generate_scan_vectors(self) -> impl Iterator<Item = Self::Vector>;
fn size_hint(&self) -> usize;
}
pub trait ParallelVectorGenerator {
type Vector;
fn generate_scan_vectors(
self,
) -> impl Iterator<Item = impl Iterator<Item = Self::Vector> + Send> + Send;
fn num_chunks(&self) -> usize;
fn size_hint(&self) -> usize;
}
pub trait ParameterAdapter<State, Parameters> {
type Vector;
fn compute_initial_state_and_parameters(&self, vector: Self::Vector) -> (State, Parameters);
}
pub fn scan<Vector, State, Parameters, Result>(
vector_generator: impl VectorGenerator<Vector = Vector>,
parameter_adapter: impl ParameterAdapter<State, Parameters, Vector = Vector>,
simulate: impl Fn(State, &Parameters) -> Result,
) -> impl Iterator<Item = (State, Parameters, Result)>
where
State: Default + Clone,
{
let scan_points = vector_generator.generate_scan_vectors();
scan_points.map(move |scan_point| {
let (initial_state, parameters) =
parameter_adapter.compute_initial_state_and_parameters(scan_point);
let result = simulate(initial_state.clone(), ¶meters);
(initial_state, parameters, result)
})
}
pub fn scan_parallel<Vector, State, Parameters, Result>(
vector_generator: impl ParallelVectorGenerator<Vector = Vector> + 'static,
parameter_adapter: impl ParameterAdapter<State, Parameters, Vector = Vector>
+ Sync
+ Send
+ Copy
+ 'static,
simulate: impl Fn(State, &Parameters) -> Result + Sync + Send + Copy + 'static,
) -> impl ParallelIterator<Item = (State, Parameters, Result)>
where
Vector: Send,
State: Default + Clone + Send + Sync,
Parameters: Send + Sync,
Result: Send + Sync,
{
vector_generator
.generate_scan_vectors()
.par_bridge()
.map(move |scan_points| {
scan_points.map(move |scan_point| {
let (initial_state, parameters) =
parameter_adapter.compute_initial_state_and_parameters(scan_point);
let result = simulate(initial_state.clone(), ¶meters);
(initial_state, parameters, result)
})
})
.flatten_iter()
}