use cellular_raza_concepts::CycleEvent;
pub use circ_buffer::*;
use serde::{Deserialize, Serialize};
pub use cellular_raza_concepts::Xapy;
pub trait UpdateMechanics<Pos, Vel, For, const N: usize> {
fn set_last_position(&mut self, pos: Pos);
fn previous_positions<'a>(&'a self) -> RingBufferIterRef<'a, Pos, N>;
fn set_last_velocity(&mut self, vel: Vel);
fn previous_velocities<'a>(&'a self) -> RingBufferIterRef<'a, Vel, N>;
fn n_previous_values(&self) -> usize;
fn add_force(&mut self, force: For);
fn get_current_force_and_reset(&mut self) -> For;
}
#[derive(Clone, Deserialize, Serialize)]
pub struct AuxStorageMechanics<Pos, Vel, For, const N: usize> {
positions: RingBuffer<Pos, N>,
velocities: RingBuffer<Vel, N>,
current_force: For,
zero_force: For,
}
impl<Pos, Vel, For, const N: usize> Default for AuxStorageMechanics<Pos, Vel, For, N>
where
For: num::Zero,
{
fn default() -> Self {
Self {
positions: RingBuffer::<Pos, N>::default(),
velocities: RingBuffer::<Vel, N>::default(),
current_force: num::Zero::zero(),
zero_force: num::Zero::zero(),
}
}
}
pub trait DefaultFrom<T> {
fn default_from(value: &T) -> Self;
}
impl<Pos, Vel, For, const N: usize> DefaultFrom<For> for AuxStorageMechanics<Pos, Vel, For, N>
where
For: Clone,
{
fn default_from(value: &For) -> Self {
let force: For = value.clone().into();
Self {
positions: RingBuffer::default(),
velocities: RingBuffer::default(),
current_force: force.clone(),
zero_force: force.clone(),
}
}
}
impl<Pos, Vel, For, const N: usize> UpdateMechanics<Pos, Vel, For, N>
for AuxStorageMechanics<Pos, Vel, For, N>
where
For: Clone + core::ops::AddAssign<For>,
{
#[inline]
fn previous_positions<'a>(&'a self) -> RingBufferIterRef<'a, Pos, N> {
self.positions.iter()
}
#[inline]
fn previous_velocities<'a>(&'a self) -> RingBufferIterRef<'a, Vel, N> {
self.velocities.iter()
}
#[inline]
fn n_previous_values(&self) -> usize {
self.positions.get_size()
}
#[inline]
fn set_last_position(&mut self, pos: Pos) {
self.positions.push(pos);
}
#[inline]
fn set_last_velocity(&mut self, vel: Vel) {
self.velocities.push(vel);
}
#[inline]
fn add_force(&mut self, force: For) {
self.current_force += force;
}
#[inline]
fn get_current_force_and_reset(&mut self) -> For {
let f = self.current_force.clone();
self.current_force = self.zero_force.clone();
f
}
}
pub trait UpdateCycle {
fn set_cycle_events(&mut self, events: Vec<CycleEvent>);
fn get_cycle_events(&self) -> &Vec<CycleEvent>;
fn drain_cycle_events<'a>(&'a mut self) -> std::vec::Drain<'a, CycleEvent>;
fn add_cycle_event(&mut self, event: CycleEvent);
}
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AuxStorageCycle {
cycle_events: Vec<CycleEvent>,
}
impl UpdateCycle for AuxStorageCycle {
#[inline]
fn set_cycle_events(&mut self, events: Vec<CycleEvent>) {
self.cycle_events = events;
}
#[inline]
fn get_cycle_events(&self) -> &Vec<CycleEvent> {
&self.cycle_events
}
#[inline]
fn drain_cycle_events<'a>(&'a mut self) -> std::vec::Drain<'a, CycleEvent> {
self.cycle_events.drain(..)
}
#[inline]
fn add_cycle_event(&mut self, event: CycleEvent) {
self.cycle_events.push(event);
}
}
pub trait UpdateReactions<Ri> {
fn set_conc(&mut self, conc: Ri);
fn get_conc(&self) -> Ri;
fn incr_conc(&mut self, incr: Ri);
}
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AuxStorageReactions<Ri> {
concentration: Ri,
}
impl<Ri> DefaultFrom<Ri> for AuxStorageReactions<Ri>
where
Ri: Clone,
{
fn default_from(value: &Ri) -> Self {
AuxStorageReactions {
concentration: value.clone(),
}
}
}
impl<R> UpdateReactions<R> for AuxStorageReactions<R>
where
R: Clone + core::ops::Add<R, Output = R>,
{
#[inline]
fn get_conc(&self) -> R {
self.concentration.clone()
}
#[inline]
fn incr_conc(&mut self, incr: R) {
self.concentration = self.concentration.clone() + incr;
}
#[inline]
fn set_conc(&mut self, conc: R) {
self.concentration = conc;
}
}
pub trait UpdateReactionsContact<Ri, const N: usize> {
fn set_current_increment(&mut self, new_increment: Ri);
fn incr_current_increment(&mut self, increment: Ri);
fn get_current_increment(&self) -> Ri;
fn previous_increments<'a>(&'a self) -> RingBufferIterRef<'a, Ri, N>;
fn set_last_increment(&mut self, increment: Ri);
fn n_previous_values(&self) -> usize;
}
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AuxStorageReactionsContact<Ri, const N: usize> {
current_increment: Ri,
increments: RingBuffer<Ri, N>,
}
impl<Ri, const N: usize> DefaultFrom<Ri> for AuxStorageReactionsContact<Ri, N>
where
Ri: Clone,
{
fn default_from(value: &Ri) -> Self {
AuxStorageReactionsContact {
current_increment: value.clone(),
increments: Default::default(),
}
}
}
impl<Ri, const N: usize> UpdateReactionsContact<Ri, N> for AuxStorageReactionsContact<Ri, N>
where
Ri: Clone + core::ops::Add<Ri, Output = Ri>,
{
#[inline]
fn get_current_increment(&self) -> Ri {
self.current_increment.clone()
}
#[inline]
fn incr_current_increment(&mut self, increment: Ri) {
self.current_increment = self.current_increment.clone() + increment;
}
#[inline]
fn set_current_increment(&mut self, new_increment: Ri) {
self.current_increment = new_increment;
}
#[inline]
fn previous_increments<'a>(&'a self) -> RingBufferIterRef<'a, Ri, N> {
self.increments.iter()
}
#[inline]
fn set_last_increment(&mut self, increment: Ri) {
self.increments.push(increment)
}
#[inline]
fn n_previous_values(&self) -> usize {
self.increments.get_size()
}
}
pub trait UpdateNeighborSensing<Acc> {
fn get_accumulator(&mut self) -> &mut Acc;
}
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct AuxStorageNeighborSensing<Acc> {
accumulator: Acc,
}
impl<Acc> UpdateNeighborSensing<Acc> for AuxStorageNeighborSensing<Acc> {
fn get_accumulator(&mut self) -> &mut Acc {
&mut self.accumulator
}
}
#[allow(unused)]
#[doc(hidden)]
mod test_derive_aux_storage_compile {
fn mechanics_default() {}
fn mechanics_visibility_1() {}
fn mechanics_visibility_2() {}
fn mechanics_visibility_3() {}
fn mechanics_more_struct_generics() {}
fn mechanics_more_struct_const_generics() {}
fn mechanics_where_clause() {}
fn mechanics_other_attributes() {}
fn cycle_default() {}
fn cycle_visibility_1() {}
fn cycle_visibility_2() {}
fn cycle_generic_param() {}
fn cycle_const_generic_param() {}
fn cycle_where_clause() {}
fn cycle_other_attributes() {}
fn reactions_default() {}
fn reactions_visibility_1() {}
fn reactions_visibility_2() {}
fn reactions_generic_param() {}
fn reactions_const_generic_param() {}
fn reactions_where_clause() {}
fn reactions_other_attributes() {}
fn neighbor_sensing_default() {}
fn neighbor_sensing_visibility_1() {}
fn neighbor_sensing_visibility_2() {}
fn neighbor_sensing_generic_param() {}
fn neighbor_sensing_const_generic_param() {}
fn neighbor_sensing_where_clause() {}
fn neighbor_sensing_other_attributes() {}
}
#[cfg(test)]
mod test_derive_aux_storage {
use super::*;
use cellular_raza_core_proc_macro::AuxStorage;
#[derive(AuxStorage)]
struct TestStructDouble<Pos, Vel, For, const N: usize> {
#[UpdateCycle]
aux_cycle: AuxStorageCycle,
#[UpdateMechanics(Pos, Vel, For, N)]
aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
}
#[derive(AuxStorage)]
struct TestStructCycle {
#[UpdateCycle]
aux_cycle: AuxStorageCycle,
}
#[derive(AuxStorage)]
struct TestStructMechanics<Pos, Vel, For, const N: usize> {
#[UpdateMechanics(Pos, Vel, For, N)]
aux_mechanics: AuxStorageMechanics<Pos, Vel, For, N>,
}
fn add_get_events<A>(aux_storage: &mut A)
where
A: UpdateCycle,
{
aux_storage.add_cycle_event(CycleEvent::Division);
let events = aux_storage.get_cycle_events();
assert_eq!(events, &vec![CycleEvent::Division]);
}
fn set_get_events<A>(aux_storage: &mut A)
where
A: UpdateCycle,
{
let initial_events = vec![
CycleEvent::Division,
CycleEvent::Division,
CycleEvent::PhasedDeath,
];
aux_storage.set_cycle_events(initial_events.clone());
let events = aux_storage.get_cycle_events();
assert_eq!(events.len(), 3);
assert_eq!(events, &initial_events);
}
#[test]
fn cycle_add_get_events() {
let mut aux_storage = TestStructCycle {
aux_cycle: AuxStorageCycle::default(),
};
add_get_events(&mut aux_storage);
}
#[test]
fn cycle_set_get_events() {
let mut aux_storage = TestStructCycle {
aux_cycle: AuxStorageCycle::default(),
};
set_get_events(&mut aux_storage);
}
#[test]
fn mechanics() {
let mut aux_storage = TestStructMechanics::<_, _, _, 4> {
aux_mechanics: AuxStorageMechanics::default(),
};
aux_storage.set_last_position(3_f64);
aux_storage.set_last_velocity(5_f32);
aux_storage.add_force(1_f32);
}
#[test]
fn cycle_mechanics_add_get_events() {
let mut aux_storage = TestStructDouble::<_, _, _, 4> {
aux_cycle: AuxStorageCycle::default(),
aux_mechanics: AuxStorageMechanics::default(),
};
aux_storage.set_last_position(3_f64);
aux_storage.set_last_velocity(5_f32);
aux_storage.add_force(-5_f32);
add_get_events(&mut aux_storage);
}
#[test]
fn cycle_mechanics_set_get_events() {
let mut aux_storage = TestStructDouble::<_, _, _, 4> {
aux_cycle: AuxStorageCycle::default(),
aux_mechanics: AuxStorageMechanics::default(),
};
aux_storage.set_last_position(3_f64);
aux_storage.set_last_velocity(5_f32);
aux_storage.add_force(111_i64);
set_get_events(&mut aux_storage);
}
}
#[allow(unused)]
#[doc(hidden)]
mod test_build_aux_storage {
use crate::backend::chili::proc_macro::aux_storage_constructor;
macro_rules! construct (
(name:$test_name:ident,
aspects:[$($asp:ident),*]) => {
#[doc = concat!("aspects: [", $(stringify!($asp,),)* "],")]
#[doc = concat!(
"let mut aux_storage = (",
stringify!(aux_storage_constructor!(
aux_storage_name: __cr_AuxStorage,
core_path: cellular_raza_core,
aspects: [$($asp),*],
)),
")(());",
)]
#[doc = concat!($(
concat!("test_aspect!(", stringify!($asp), ");")
,)*)]
fn $test_name() {}
}
);
cellular_raza_core_proc_macro::run_test_for_aspects!(
test: construct,
aspects: [Mechanics, Interaction, NeighborSensing, Cycle, Reactions, ReactionsContact]
);
}